diff --git a/package-lock.json b/package-lock.json index 82ed2a5..e3d6f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mind-reader", - "version": "0.0.1", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mind-reader", - "version": "0.0.1", + "version": "1.0.0", "dependencies": { "serialport": "^9.2.5" }, diff --git a/setup-development/install-windows.ps1 b/setup-development/install-windows.ps1 new file mode 100644 index 0000000..9c646cd --- /dev/null +++ b/setup-development/install-windows.ps1 @@ -0,0 +1,169 @@ +<# +.synopsis +Dependency installer for Mind-Reader on Windows. +This sets up a development environment from a BARE windows install. + +.description +Install Git for Windows, clone the Mind-Reader repository, and install all dependencies. + +The script uses winget (A.K.A. "App Installer") to download and install the latest versions of each dependency, defined in winget/dependencies.json + +Winget comes preinstalled on Windows 11 (21H2)/10 (21H1) or newer, and can be installed on Windows 10 1704+ through the Windows Store. +If you download Microsoft's developer VM, you have it! +As WinGet is built into Windows, it sidesteps any annoying third-party package managers, and is the lowest common denominator for package installation. + +.link +https://github.com/We-Dont-Byte/Mind_Reader/ + +.parameter GitDir +Path to clone the git repo into (Default: $HOME/git/) + +.parameter AllowAdministrator +Force-allow running this script as Administrator (not recommended, despite the frequent UAC prompts!) + +.parameter NoPrompt +Disable all prompts for user input, and all waiting. (not recommended when combined with AllowAdministrator!) + +.parameter ForceInstall +Force installation/upgrade of all modules, even if already present on the system. + +.parameter DryRun +Perform a "dry run" of the script, changing directories and running commands, but without modifying anything. + +.example +./install-windows.ps1 +Perform a default upgrade of all Mind_Reader dependencies + +.example +./install-windows.ps1 -DryRun +Perform a dry run of the upgrade process, so you can evaluate what commands will be run + +.example +./install-windows.ps1 -NoPrompt +Don't prompt for user input when upgrading + +.example +./install-windows.ps1 AllowAdministrator +Allow script to run as Administrator +#> + +param ( + [string]$GitDir = "$HOME/git/", # Path to clone the git repo into + [switch]$h, [switch]$Help, # Get help + [switch]$AllowAdministrator, # Force allow installation as administrator + [switch]$NoPrompt, # Disable the 3-second wait and press-any-key prompt + [switch]$ForceInstall, # Always try to install + [switch]$DryRun # Run script without installing +) + +$SetupPath = 'Mind_Reader/setup-development' + +if ($h -or $Help) { + Get-Help ./install-windows.ps1 + exit +} + + +# .description +# Command-Available: Checks whether a given command is available. +# If command is available, returns $false +function Command-Available { + param ($command) + # Use a wildcard here so the command doesn't throw an exception we'd have to trycatch + # It's not a filthy hack if it's elegant! + RETURN (Get-Command -Name $command*) +} + +#.description +# Dry-Run a powershell statement +function Dry-Run { + param ([string] $command) + $prompt = "> " + if ($DryRun) { + Write-Host "$prompt$command [dry]" -ForegroundColor darkgray + } + else { + Write-Host "$prompt$command" -ForegroundColor white + Invoke-Expression $command + } +} + +#.description +# Reload-Path: Reload the Path environment variable +function Reload-Path { + Write-Output "Reloading Path..." + #* Courtesy of user [mpen](https://stackoverflow.com/users/65387/mpen) on [StackOverflow](https://stackoverflow.com/a/31845512) + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") +} + + +# Check if Winget is available +if ( $NoWinget -or -not (Command-Available winget) ) { + Write-Warning "[ Warning ]: It looks like winget isn't available.`n" + Write-Host "Update 'App Installer' through the Microsoft Store, or grab the '.msixbundle' from the winget-cli repository:" + Write-Host "( https://github.com/microsoft/winget-cli/releases/latest )`n" -ForegroundColor White + exit +} + +# Check if the user ran the script with administrator privileges. +# Warn them. +if ( ([Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544') ) { + # If an administrator requests installation as administator, + # for example, to keep UAC prompts to a minimum, allow it. + if ($AllowAdministrator) { + Write-Warning "Script was run as Administrator. Exit now if you didn't mean to do this!" + # If you pass NoPrompt as an arg, you're very aware of the damage this script could do to your build env, and you just don't care + # The true chad of sysadmins. + if (!$NoPrompt) { + for ( $i = 3; $i -gt 0; $i--) { + Write-Host "Press Ctrl+C to exit. Continuing in $i...`r" -NoNewLine + sleep 1 + } + Write-Host "Press any key to continue... " + [void][Console]::ReadKey(1) # Equivalent to Command Prompt's `pause` command + } + } else { + # Throw a fatal error if the user tries to run as administrator. + Throw "Script must be run as a normal user." + } +} + +# Install Git +if ( -not (Command-Available git) ) { + Write-Host "`nInstalling Git with winget..." + Dry-Run 'winget install --id Git.Git' + Reload-Path + if ( -not (Command-Available git)) { + Throw "Git failed to install. Aborting." + } +} else { + Write-Host "Git already installed." -ForegroundColor green +} + +# Create git directory in GitDir +if ( -not (Test-Path "$GitDir") ) { + Dry-Run "mkdir '$GitDir'" +} + +# Clone the repository in GitDir +$dir = $pwd +cd $GitDir +Dry-Run "git clone 'https://github.com/We-Dont-Byte/Mind_Reader.git'" +# TODO: Change this during merge onto main branch +Dry-Run "git checkout johnBreaux" + +# Run the install script +if ( -not (Test-Path "$SetupPath")) { + Throw "Repository contains no subdirectory '$SetupPath'." +} +cd $SetupPath +# Run upgrade-windows to install the rest of the dependency chain. +$args = if ($AllowAdministrator) {" -AllowAdministrator"} else {""} +$args += if ($DryRun) {" -DryRun"} else {""} +PowerShell ("./upgrade-windows.ps1 -Install -NoPrompt" + $args) + + +cd $dir +if ( -not $NoPrompt ) { + Write-Host "Press any key to exit."; [void][Console]::ReadKey(1) +} \ No newline at end of file diff --git a/setup-development/upgrade-windows.ps1 b/setup-development/upgrade-windows.ps1 new file mode 100644 index 0000000..edc4d79 --- /dev/null +++ b/setup-development/upgrade-windows.ps1 @@ -0,0 +1,192 @@ +<# +.synopsis +Dependency updater for Mind-Reader on Windows. +This script expects to be run from Mind_Reader/setup-development + +.description +Updates dependencies (NodeJS, Python, etc.), VSCode, NVDA + +The script uses winget (A.K.A. "App Installer") to download and install the latest versions of each dependency, defined in winget/dependencies.json + +Winget comes preinstalled on Windows 11 (21H2)/10 (21H1) or newer, and can be installed on Windows 10 1704+ through the Windows Store. +If you download Microsoft's developer VM, you have it! +As WinGet is built into Windows, it sidesteps any annoying third-party package managers, and is the lowest common denominator for package installation. + +.link +https://github.com/We-Dont-Byte/Mind_Reader/ + +.parameter GitDir +Path to clone the git repo into (Default: $HOME/git/) + +.parameter AllowAdministrator +Force-allow running this script as Administrator (not recommended, despite the frequent UAC prompts!) + +.parameter NoPrompt +Disable all prompts for user input, and all waiting. (not recommended when combined with AllowAdministrator!) + +.parameter Install +Force installation/upgrade of all modules, even if already present on the system. + +.parameter DryRun +Perform a "dry run" of the script, changing directories and running commands, but without modifying anything. + +.example +./upgrade-windows.ps1 +Perform a default upgrade of all Mind_Reader dependencies + +.example +./upgrade-windows.ps1 -DryRun +Perform a dry run of the upgrade process, so you can evaluate what commands will be run + +.example +./upgrade-windows.ps1 -NoPrompt +Don't prompt for user input when upgrading + +.example +./upgrade-windows.ps1 -AllowAdministrator +Allow script to be run as Administrator +#> + +param ( + [switch]$AllowAdministrator, # Force allow installation as administrator + [switch]$NoPrompt, # Disable the 3-second wait and press-any-key prompt + [switch]$Install, # Perform all installations, even when commands are present + [switch]$DryRun, # Run script without installing + [switch]$NoWinget # Pretend Winget doesn't exist +) + +# .description +# Command-Available: Checks whether a given command is available. +# If command is available, returns $false +function Command-Available { + param ($command) + # Use a wildcard here so the command doesn't throw an exception we'd have to trycatch + # It's not a filthy hack if it's elegant! + RETURN (Get-Command -Name $command*) +} + +#.description +# Dry-Run a powershell statement +function Dry-Run { + param ([string] $command) + $prompt = "> " + if ($DryRun) { + Write-Host "$prompt$command [dry]" -ForegroundColor darkgray + } + else { + Write-Host "$prompt$command" -ForegroundColor white + Invoke-Expression $command + } +} + +#.description +# Reload-Path: Reload the Path environment variable +function Reload-Path { + Write-Output "Reloading Path..." + #* Courtesy of user [mpen](https://stackoverflow.com/users/65387/mpen) on [StackOverflow](https://stackoverflow.com/a/31845512) + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") +} + + +# Check if Winget is available +if ( $NoWinget -or -not (Command-Available winget) ) { + Write-Warning "[ Warning ]: It looks like winget isn't available.`n" + Write-Host "Update 'App Installer' through the Microsoft Store, or grab the '.msixbundle' from the winget-cli repository:" + Write-Host "( https://github.com/microsoft/winget-cli/releases/latest )`n" -ForegroundColor White + exit +} + +# Check if the user ran the script with administrator privileges. +# Warn them. +if ( ([Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544') ) { + # If an administrator requests installation as administator, + # for example, to keep UAC prompts to a minimum, allow it. + if ($AllowAdministrator) { + # If you pass -AllowAdministrator -NoPrompt as an arg, you're very aware of the damage this script could do to your build env, and you just don't care + # The true chad of sysadmins. + if (!$NoPrompt) { + Write-Warning "Script was run as Administrator. Exit now if you didn't mean to do this!" + for ( $i = 3; $i -gt 0; $i--) { + Write-Host "Press Ctrl+C to exit. Continuing in $i...`r" -NoNewLine + sleep 1 + } + + Write-Host "Press any key to continue... " + [void][Console]::ReadKey(1) # Equivalent to Command Prompt's `pause` command + } + } else { + # Throw a fatal error if the user tries to run as administrator. + Throw "Script must be run as a normal user." + } +} + +# Import the packages from dependencies.json (autogenerated file, do not edit!) +Write-Host "`nInstalling packages with winget..." +Dry-Run 'winget import winget/dependencies.json' +# Reload the PATH, so we can use some of those sweet new commands we just installed +Reload-Path + +# Check whether everything is available now: +$error = 0 +if ( -not (Command-Available code) ) { + $error += 1; Write-Host -ForegroundColor red "Visual Studio Code not available" +} +if ( -not (Command-Available node) ) { + $error += 2; Write-Host -ForegroundColor red "NodeJS not available" +} +if ( -not (Command-Available npm ) ) { + $error += 4; Write-Host -ForegroundColor red "Node Package Manager not available"; +} +if ( $error ) { exit } + +# Check if electron-rebuild is installed, if not, install it +if ( ($Install) -or -not (Command-Available electron-rebuild) ) { + Write-Host "`nInstalling Electron-Rebuild..." + Dry-Run 'npm install -g electron-rebuild' + Reload-Path + if ( -not (Command-Available electron-rebuild)) { + Throw "electron-rebuild failed to install. Aborting." + } +} else { + Write-Host "`nElectron-Rebuild already installed." -ForegroundColor green +} + +# We're about to do some path traversal, so save the current directory +$prev_directory = $pwd + +# install NodeJS dependencies for this extension +Write-Host "`nInstalling NodeJS Dependencies..." +cd .. +Dry-Run 'npm install' + +# if we're on a known VSCode version, go ahead and run electron-rebuild +switch -Regex (code --version) { +<# "1\.6[7-9]\.[0-9]+" { + #?: Do we update this in the future, or stop maintaining it and remove this entire switch block? + } #> + "1\.66\.[0-9]+" { # 1.66 + Write-Host "`nRebuilding Electron for your version of VSCode..." + Dry-Run 'electron-rebuild --version="17.2.0"' + Write-Host "Done!" -ForegroundColor green + break + } + "\d+\.\d+\.\d+" { # Anything else + Write-Host "`nOpen Visual Studio Code, select the `"Help`" tab in the Toolbar, and go to `"About`".`nYou should see a page that looks like the following:" -ForegroundColor darkcyan + + Write-Host " `(i`) Visual Studio Code`n`n Version: 1.66.2 `(user setup`)`n Commit: [Commit ID]`n Date: 2022-04-11T07:46:01.075Z`n Electron: 17.2.0`n [ ... ]" -ForegroundColor White + + Write-Host "Note the Electron version `(17.2.0 in the above example`)." -ForegroundColor darkcyan + + Write-Host "Run the command " -NoNewLine + Write-Host "electron-rebuild --version ELECTRON_VERSION" -NoNewLine -ForegroundColor green + Write-Host " in Mind-Reader`'s root folder.`n" + break # Don't process the next items in the collection. + } + default { } # Leave blank +} + +# Return from whence we came +cd $prev_directory +if ( -not $NoPrompt ) { + Write-Host "Press any key to exit."; [void][Console]::ReadKey(1) +} \ No newline at end of file diff --git a/setup-development/winget/dependencies.json b/setup-development/winget/dependencies.json new file mode 100644 index 0000000..64780e6 --- /dev/null +++ b/setup-development/winget/dependencies.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://aka.ms/winget-packages.schema.2.0.json", + "CreationDate": "2022-04-23T21:13:03.702-00:00", + "Sources": [ + { + "Packages": [ + { + "PackageIdentifier": "Microsoft.VisualStudio.2019.BuildTools" + }, + { + "PackageIdentifier": "Python.Python.3" + }, + { + "PackageIdentifier": "Git.Git" + }, + { + "PackageIdentifier": "OpenJS.NodeJS.LTS" + }, + { + "PackageIdentifier": "Microsoft.VisualStudioCode" + }, + { + "PackageIdentifier": "NVAccess.NVDA" + } + ], + "SourceDetails": { + "Argument": "https://winget.azureedge.net/cache", + "Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe", + "Name": "winget", + "Type": "Microsoft.PreIndexed.Package" + } + } + ], + "WinGetVersion": "1.2.10271" +} \ No newline at end of file