nw-autoupdater
v1.1.11
Published
Library provides low-level API to control NW.js app auto-updates
Downloads
58
Maintainers
Readme
NW-Autoupdater v1.1
Library provides low-level API to control NW.js app auto-updates. This project can be seen as a reincarnation of node-webkit-updater, which is not maintained anymore.
Features
- Node >= 7 compliant
- clean async/await syntax
- supports both Zip/Tar.Gz archives
- fires download/install progress events
Strategy ScriptSwap
:video_camera: Screencast: Running nw-autoupdater examples in the terminal on Ubuntu
What do we do to autoupdate (see demo A or demo B)
readRemoteManifest
reads manifest from the remote release servercheckNewVersion( rManifest )
checks if the version in the remote manifest greater than one of the local manifest- If the remote manifest doesn't have newer version, skips the update flow
- We subscribe for
download
events - We subscribe for
install
events
- We subscribe for
download( rManifest )
downloads the latest available release matching the host platform (according to thepackages
map of the remote manifest)unpack( updateFile )
unpacks the release archive (zip
ortar.gz
) in a temporary directory- Strategy AppSwap
restartToSwap( extraArgs )
closes the app and launches the downloaded releaseisSwapRequest()
- checks if we need to go the swap flow (while running in tmp and therefore having the initial app directory unlocked for writing)swap()
- backs up actual version and replaces it with the new onerestart( extraArgs )
- restarts the updated app from its original location
- Strategy ScriptSwap
restartToSwap()
closes the app and launches the swap script, which launches the application when it's done
Distribution
- Run release server (see example)
- Add to your client manifest (package.json) field
manifestUrl
pointing at release server - Package your app by using nwjs-builder (see example)
- Update the contents of
packages
field in release server manifest (e.g. by runningnode update.js
) - Update
version
field in release server manifest - Launch your app and observe it's auto-updating
Examples
API
Constructor
new AutoUpdate( manifest, options );
Params
manifest
- e.g.require( "./package.json" )
options.strategy
- (OPTIONAL) can beScriptSwap
orAppSwap
. By defaultAppSwap
options.executable
- (OPTIONAL) executable if it doesn't match project nameoptions.backupDir
- (OPTIONAL) directory to backup. By default it's <project_name>.bak next to app directoryoptions.execDir
- (OPTIONAL) app directory. By default it's extracted fromprocess.execPath
(nwjs-builder bundles the app into self-extractable andprocess.cwd()
is not a reliable source). Yet on a Macprocess.execPath
contains the full path to the executable within MacOS bundle. So you rather use this option to set the app path directly.options.updateDir
- (OPTIONAL) temporary directory where the downloaded package gets extracted. By default /tmp/nw-autoupdateroptions.logPath
- (OPTIONAL) the full path to the log file. By defaultnw.App.dataPath + "/nw-autoupdater.log"
: Windows: %LOCALAPPDATA%/<project_name>; Linux: ~/.config/<project_name>; OSX: ~/Library/Application Support/<project_name>options.verbose
- (OPTIONAL) whentrue
swap script reports verbose in the log file. By defaultfalse
options.swapScript
- (OPTIONAL) you custom swap script content (NOTE: available only for ScriptSwap strategy)options.accumulativeBackup
- (OPTIONAL) whentrue
for every backup creates a new folder. By defaultfalse
Writing custom swap script
You can define with options.swapScript
you own custom swap script:
const updater = new AutoUpdater( require( "./package.json" ), {
strategy: "ScriptSwap",
swapScript: `
BASH/BAT SCRIPT CONTENT
`
});
By default on Linux/MacIO the following script is used:
rsync -a\${VERBOSE} --delete \${APP_PATH}/. \${BAK_PATH}/
rsync -a\${VERBOSE} --delete \${UPDATE_PATH}/. \${APP_PATH}/
where the variables are populated from ARGV:
- VERBOSE - "v" or ""
- APP_PATH - application home directory
- BAK_PATH - backup directory
- UPDATE_PATH - update directory
For example, if you have for package not the entire NW.js application, but just HTML5 project, you set up the following script:
rsync -a\${VERBOSE} --delete \${APP_PATH}/. \${BAK_PATH}/
rsync -a\${VERBOSE} \${UPDATE_PATH}/. \${APP_PATH}/package
So it backups the project, but copies extracted packaged into package
subfolder in application home directory
readRemoteManifest
Reads package.json of the release server
const rManifest = await updater.readRemoteManifest();
Returns: Promise<manifest: Object>
checkNewVersion
Check if the release server has newer app version
const needsUpdate = await updater.checkNewVersion( rManifest );
Params
rManifest
- manifest of the release server
Returns: Promise<needsUpdate: boolean>
download
Download last available update to the temp directory
const updateFile = await updater.download( rManifest, { debounceTime: 100 });
Params
rManifest
- manifest of the release serveroptions.debounceTime
- (OPTIONAL) debounce time in milliseconds
Returns: Promise<filepath: string>
unpack
Unpack downloaded update
const extractDir = await updater.unpack( updateFile, { debounceTime: 100 } );
Params
updateFile
- path to downloaded updateoptions.debounceTime
- (OPTIONAL) debounce time in milliseconds
Returns: Promise<directory: string>
restartToSwap
Close this version of app and start the downloaded one with --swap param
await updater.restartToSwap();
Params
extraArgs
- (OPTIONAL) Extra arguments to be passed to the newly started app
Returns: Promise
Events
download
Subscribe on download progress event
updater.on( "download", ( downloadSize, totalSize ) => {
console.log( "download progress", Math.floor( downloadSize / totalSize * 100 ), "%" );
});
install
Subscribe on install progress event
updater.on( "install", ( installFiles, totalFiles ) => {
console.log( "install progress", Math.floor( installFiles / totalFiles * 100 ), "%" );
});
Extra Methods required for Strategy AppSwap
isSwapRequest
Checks if the app launched for swap
const needsSwap = updater.isSwapRequest();
Returns: boolean
swap
Backs up current version of the app and replaces it with the downloaded version
await updater.swap();
Returns: Promise
restart
Restarts the updated app
await updater.restart();
Params
extraArgs
- (OPTIONAL) Extra arguments to be passed to the newly started app
Returns: Promise
Contributing
nw-autoupdater
welcomes maintainers. There is plenty of work to do. No big commitment required,
if all you do is review a single Pull Request, you are a maintainer.
How to check changes
# Clone the git repo
git clone [email protected]:dsheiko/nw-autoupdater.git
# Navigate to the newly created directory
cd nw-autoupdater
# Switch the branch if needed
# Make changes in the code
# Bundle the package
npm pack
# You'will get a new file like `nw-autoupdater-1.1.11.tgz`
# Switch a client example
cd example/client-strategy-script/
# Install the updated package
npm i ../../nw-autoupdater-1.1.11.tgz
# Package demo app
npm run package
# Extract demo app package in a temp directory
unzip ../server/releases/nw-autoupdater-demo-r1.0.0-linux-x64.zip -d /tmp/Sandbox/
# Switch to release server example
cd ../server/
# Make sure dependencies up to date
npm i
# Update releases manifest
npm run update
# Start the server
npm start
# Now start the demo app from your temp /tmp/Sandbox/
/tmp/Sandbox/nw-autoupdater-demo
# It says:
# Application ver. 1.0.0
# App is up to date...
# Switch back to demo app and update its version
cd ../client-strategy-script/
npm version patch
npm run package
# Back to the server to update manifest
cd ../server/
npm run update
npm start
# When starting the built app it updates
/tmp/Sandbox/nw-autoupdater-demo