npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

nw-ota

v1.0.0

Published

Update NW.js application bundle (app files) without replacing the entire application

Readme

nw-ota

English | Русский

Update NW.js application bundle (app files) without replacing the entire application.

This library allows you to update only the application bundle (e.g., app/ folder) of your NW.js application, while keeping the NW.js runtime and other files intact.

Installation

npm install nw-ota

Usage

Basic Example - Updating Bundle

import BundleUpdater from "nw-ota";

// Option 1: Auto-detect bundle path (recommended for NW.js apps)
// bundlePath will be automatically detected using getDefaultBundlePath()
const updater = new BundleUpdater({});

// Option 2: Manual path
// const updater = new BundleUpdater({
//   bundlePath: "./app", // Path to your app bundle directory
// });

// Update bundle from URL
try {
  await updater.update("https://example.com/updates/app-bundle.zip");
  console.log("Bundle updated successfully!");
} catch (error) {
  console.error("Update failed:", error);
}

Automatic Update Check (NW.js Context)

The library can automatically check for updates from S3 and install them. This works in NW.js context and automatically detects platform and application version:

import BundleUpdater from "nw-ota";

// Auto-detect bundle path based on platform (bundlePath is optional)
const updater = new BundleUpdater({});

// Check for updates and install automatically
await updater.checkForUpdate({
  endpoint: "https://bucket.s3.region.amazonaws.com",
  projectKey: "my-project",
  // currentVersion is optional - if not provided, will load from saved version file
  // After successful update, version is automatically saved

  // Callbacks
  progress: (received, total) => {
    console.log(`Download progress: ${received}/${total} bytes`);
  },

  updateFound: (update) => {
    console.log(`Update found: version ${update.version}`);
  },

  updateSuccess: () => {
    console.log("Update installed successfully!");
  },

  updateFail: (error) => {
    console.error("Update failed:", error);
  },

  noUpdate: () => {
    console.log("No updates available");
  },

  // Optional: notify that restart is needed
  onNeedRestart: () => {
    console.log("Update installed! Please restart the app to apply changes.");
  },

  // Optional: track status changes
  onStatus: (status) => {
    console.log("Update status:", status);
  },
});

The function automatically:

  • Detects platform (win/mac/linux32/linux64) from NW.js
  • Gets application version (e.g., "1.0.0") from nw.App.manifest.version - this is the version from your package.json/manifest
  • Loads current bundle version from local file (.nw-bundle-version.json) if currentVersion is not provided
  • Builds update.json URL: {endpoint}/ota/nwjs/{projectKey}/{platform}/{appVersion}/update.json
  • Finds the latest enabled update with version > currentVersion
  • Downloads and installs the update
  • Saves the new version automatically after successful installation

Note: The appVersion in the URL path refers to the application version from nw.App.manifest.version (like "1.0.0", "1.2.3"). This allows you to have separate update channels for different application versions.

Step-by-step Update

import BundleUpdater from "nw-ota";

const updater = new BundleUpdater({
  bundlePath: "./app",
  temporaryDirectory: "./temp",
  backup: true, // Create backup before replacing (default: true)
});

try {
  // 1. Download the zip file
  const zipPath = await updater.download(
    "https://example.com/updates/app-bundle.zip"
  );

  // 2. Unpack the zip file
  const unpackedPath = await updater.unpack(zipPath);

  // 3. Replace the bundle
  await updater.replace(unpackedPath);

  console.log("Bundle updated successfully!");
} catch (error) {
  console.error("Update failed:", error);
}

Publishing Updates (CLI)

The package includes a CLI tool for publishing updates to S3 storage.

Installation

npm install -g nw-ota

Or use with npx:

npx nw-ota

Usage

Run the publish command in your project directory:

npx nw-ota-publish

Or:

npx nw-ota

The CLI will guide you through the process:

  1. Build Path: Enter the path to your build directory (saved for future use)
  2. Project Key: Enter a unique project identifier (saved for future use)
  3. Platform: Select platform (win, mac, linux32, linux64)
  4. Version: Enter the application version (e.g., "1.0.0") - this should match the version from your package.json/manifest (saved per platform)
  5. S3 Configuration: Enter S3 credentials and settings (saved for future use)
  6. Upload: The tool will:
    • Create a zip archive from your build directory
    • Upload it to S3 at: /ota/nwjs/{projectKey}/{platform}/{version}/update-v{X}.zip
    • Update or create update.json with the new version

Note: The version should match the application version from your package.json/manifest (e.g., "1.0.0", "1.2.3"). This allows you to have separate update channels for different application versions.

Configuration

The CLI saves configuration in .nw-ota-config.json in your project directory. This file contains:

  • Build path
  • Project key
  • Platform-specific versions
  • S3 configuration

Note: The config file is automatically added to .gitignore to prevent committing sensitive S3 credentials.

S3 Structure

Updates are stored in S3 with the following structure:

ota/nwjs/{projectKey}/{platform}/{version}/
  ├── update.json
  ├── update-v1.zip
  ├── update-v2.zip
  └── ...

update.json Format

The update.json file contains an array of available updates:

[
  {
    "version": 1,
    "enable": true,
    "download": "https://bucket.s3.region.amazonaws.com/ota/nwjs/project/win/1.0.0/update-v1.zip"
  },
  {
    "version": 2,
    "enable": true,
    "download": "https://bucket.s3.region.amazonaws.com/ota/nwjs/project/win/1.0.0/update-v2.zip"
  }
]

API

new BundleUpdater(options)

Creates a new instance of BundleUpdater.

Options:

  • bundlePath (optional): Path to the bundle directory to replace. If not provided, will be automatically detected using BundleUpdater.getDefaultBundlePath().

    Important: In NW.js apps, bundle location is platform-specific according to NW.js documentation:

    • Windows/Linux: Same folder as nw.exe (or nw), OR package.nw folder in the same directory
    • Mac: nwjs.app/Contents/Resources/app.nw

    If bundlePath is not provided, the library will automatically detect it:

    // Auto-detect (recommended for NW.js apps)
    const updater = new BundleUpdater({});
    
    // Or provide manually
    const updater = new BundleUpdater({
      bundlePath: "./app",
    });

    Examples:

    • './app' - relative path
    • './package.nw' - package.nw folder (Windows/Linux)
    • '/path/to/app' - absolute path
  • temporaryDirectory (optional): Path to temporary directory for downloads. Defaults to os.tmpdir()

  • backup (optional): Whether to create a backup before replacing. Defaults to true

BundleUpdater.getDefaultBundlePath()

Static method that automatically detects the default bundle path based on NW.js platform-specific structure.

Returns: string | null - The detected bundle path, or null if NW.js is not available or path cannot be determined.

Example:

const defaultPath = BundleUpdater.getDefaultBundlePath();
if (defaultPath) {
  const updater = new BundleUpdater({
    bundlePath: defaultPath,
  });
} else {
  // Fallback to manual path
  const updater = new BundleUpdater({
    bundlePath: "./app",
  });
}

updater.update(url)

Downloads, unpacks and replaces the bundle in one call.

Parameters:

  • url (string): URL to download the zip file from

Returns: Promise<void>

updater.download(url)

Downloads a zip file from URL.

Parameters:

  • url (string): URL to download the zip file from

Returns: Promise<string> - Path to the downloaded file

updater.unpack(zipPath)

Unpacks a zip file to a temporary directory.

Parameters:

  • zipPath (string): Path to the zip file

Returns: Promise<string> - Path to the unpacked directory

updater.replace(newBundlePath)

Replaces the current bundle with the new one.

Parameters:

  • newBundlePath (string): Path to the new bundle directory

Returns: Promise<void>

updater.createBackup()

Creates a backup of the current bundle.

Returns: Promise<string | null> - Path to the backup directory, or null if bundle doesn't exist

updater.getCurrentVersion()

Gets the current bundle version from the saved version file.

Returns: number - Current bundle version (0 if no version file exists)

Note: The version is automatically saved after successful updates via checkForUpdate(). The version file is stored at .nw-bundle-version.json next to the bundle directory.

updater.getVersionInfo()

Gets version info string with platform, application version, and OTA bundle version.

Returns: string - Version info in format: "Platform Version OTAVersion"

Example:

const versionInfo = updater.getVersionInfo();
console.log(versionInfo); // "win 1.0.0 5" or "mac 1.2.3 3"

This is the same information that is used when checking for updates (platform, application version, and current OTA version).

updater.checkForUpdate(options)

Checks for updates from S3 storage and installs them automatically. Works in NW.js context - automatically detects platform and application version.

Parameters:

  • options (CheckUpdateOptions): Configuration object

    • endpoint (string, required): S3 endpoint/base URL where updates are stored
    • projectKey (string, required): Unique project identifier
    • currentVersion (number, optional): Current bundle version. If not provided, will be loaded from saved version file (.nw-bundle-version.json). Defaults to 0 if no saved version exists.
    • headers (Record<string, string>, optional): Optional headers for requests
    • progress (function, optional): Callback for download progress (received: number, total: number) => void
    • updateFound (function, optional): Callback when update is found (update: UpdateEntry) => void
    • updateSuccess (function, optional): Callback when update succeeds () => void
    • updateFail (function, optional): Callback when update fails (error?: string | Error) => void
    • noUpdate (function, optional): Callback when no update is available () => void
    • onNeedRestart (function, optional): Callback triggered after update is successfully installed. The app will not restart automatically - user must restart manually to apply the update () => void
    • onStatus (function, optional): Callback triggered on every status change during the update process. Provides unified status tracking (status: UpdateStatus) => void

UpdateStatus values:

  • 'checking' - Checking for available updates
  • 'update-found' - Update has been found and will be installed
  • 'downloading' - Downloading the update package
  • 'downloaded' - Download completed successfully
  • 'unpacking' - Unpacking the downloaded archive
  • 'unpacked' - Unpacking completed successfully
  • 'replacing' - Replacing the current bundle with the new one
  • 'replaced' - Bundle replacement completed successfully
  • 'saving' - Saving the new version information
  • 'cleaning' - Cleaning up temporary files
  • 'success' - Update installation completed successfully
  • 'error' - An error occurred during the update process
  • 'no-update' - No updates available
  • 'restart-needed' - Update installed, application restart is required

Returns: Promise<void>

Example:

await updater.checkForUpdate({
  endpoint: "https://bucket.s3.region.amazonaws.com",
  projectKey: "my-project",
  // currentVersion will be loaded automatically from saved file
  progress: (received, total) => {
    console.log(`Progress: ${((received / total) * 100).toFixed(2)}%`);
  },
  updateSuccess: () => {
    console.log("Update installed! Version saved automatically.");
  },
  onNeedRestart: () => {
    console.log("Please restart the app to apply the update.");
  },
});

// Get current version
const currentVersion = updater.getCurrentVersion();
console.log(`Current bundle version: ${currentVersion}`);

Building

To build the TypeScript source:

npm run build

This will compile the TypeScript files to JavaScript in the dist/ directory.

Differences from nw-updater

  • nw-updater: Replaces the entire NW.js application (executable, runtime, and all files)
  • nw-ota: Replaces only the application bundle (your app code), keeping the NW.js runtime intact

This is useful when:

  • You want to update your application code without redistributing the entire NW.js runtime
  • You want smaller update packages
  • You want faster updates (only app files, not the entire application)

Requirements

  • Node.js 14.0.0 or higher
  • TypeScript 5.0+ (for development)
  • For Windows: PowerShell 5.0+ (Windows 10+) or unzip utility
  • For macOS/Linux: unzip utility (usually pre-installed)
  • For publishing: AWS S3 or S3-compatible storage
  • For automatic updates: NW.js application context (for checkForUpdate method)

License

MIT