{"_id":"@activebook/atom-updater","_rev":"3-69cce145b192b973f9e7e4489bf76b9d","name":"@activebook/atom-updater","dist-tags":{"latest":"2.0.2"},"versions":{"2.0.0":{"name":"@activebook/atom-updater","version":"2.0.0","keywords":["updater","atomic","directory","replacement","electron","app","bundle","macos","windows","linux"],"author":{"name":"Charles Liu"},"license":"MIT","_id":"@activebook/atom-updater@2.0.0","maintainers":[{"name":"activebook","email":"himurokaoru@gmail.com"}],"homepage":"https://github.com/activebook/atom-updater","bugs":{"url":"https://github.com/activebook/atom-updater/issues"},"dist":{"shasum":"e861602726ff0cb2edee2b950f645477068e1ac4","tarball":"https://registry.npmjs.org/@activebook/atom-updater/-/atom-updater-2.0.0.tgz","fileCount":39,"integrity":"sha512-meV01JyhOuNPnyAM8/pABJWI/AbQWhHtRoBrA2wswURX6xOmWlhQ2Wwo+XGS7VVwapqy7V/hVgwRu+/XHa2gaA==","signatures":[{"sig":"MEYCIQCmtPydnSd1A4V9J2Z4+naAcxgq+g1cq7vkzUDAANokwAIhAMI4zUyvaxxV0STVlYD9axmu31gNa8yjYg+SSl7LJIKK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14628767},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=14.0.0"},"gitHead":"8ef64d06336eff070fe8c2f02f13fe76d6818bea","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","format":"prettier --write src/**/*.ts","prepare":"npm run build","publish":"npm publish --access public"},"_npmUser":{"name":"activebook","email":"himurokaoru@gmail.com"},"repository":{"url":"git+https://github.com/activebook/atom-updater.git","type":"git"},"_npmVersion":"11.6.0","description":"Node.js wrapper for atom-updater Go executable - provides atomic directory replacement with rollback capabilities","directories":{},"_nodeVersion":"22.19.0","dependencies":{"node-fetch":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","prettier":"^2.8.0","typescript":"^4.9.0","@types/jest":"^29.0.0","@types/node":"^18.0.0","@typescript-eslint/parser":"^5.0.0","@typescript-eslint/eslint-plugin":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/atom-updater_2.0.0_1759137002386_0.03354456546357709","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@activebook/atom-updater","version":"2.0.1","keywords":["updater","atomic","directory","replacement","electron","app","bundle","macos","windows","linux"],"author":{"name":"Charles Liu"},"license":"MIT","_id":"@activebook/atom-updater@2.0.1","maintainers":[{"name":"activebook","email":"himurokaoru@gmail.com"}],"homepage":"https://github.com/activebook/atom-updater","bugs":{"url":"https://github.com/activebook/atom-updater/issues"},"dist":{"shasum":"76207ce81a5cefcea55fedd29cfbeef00046e417","tarball":"https://registry.npmjs.org/@activebook/atom-updater/-/atom-updater-2.0.1.tgz","fileCount":39,"integrity":"sha512-KgvK+K/WILMjoTKH2tYVHLaWmkhUDJRVAYPsDgYY2S1iT754PeUfXKzN1V1SUk8AR7xfJMOvef6CYqD/yhg2hQ==","signatures":[{"sig":"MEYCIQDV2+o4d2Z67vT28/td5m8sdOiBFj+Zi6tkmIzZMwD40wIhAJ+KCyhoJcmdPDHLWFC6dq86kX9RlBcI745VlVUqplMM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14628734},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=14.0.0"},"gitHead":"829a32f6f5a2b7f5cc33ce935307996dcb7c1607","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"tsc","format":"prettier --write src/**/*.ts","prepare":"npm run build","publish":"npm publish --access public"},"_npmUser":{"name":"activebook","email":"himurokaoru@gmail.com"},"repository":{"url":"git+https://github.com/activebook/atom-updater.git","type":"git"},"_npmVersion":"11.6.0","description":"Node.js wrapper for atom-updater Go executable - provides atomic directory replacement with rollback capabilities","directories":{},"_nodeVersion":"22.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","ts-jest":"^29.0.0","prettier":"^2.8.0","typescript":"^4.9.0","@types/jest":"^29.0.0","@types/node":"^18.0.0","@typescript-eslint/parser":"^5.0.0","@typescript-eslint/eslint-plugin":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/atom-updater_2.0.1_1759137674864_0.026702514871759453","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@activebook/atom-updater","version":"2.0.2","description":"Node.js wrapper for atom-updater Go executable - provides atomic directory replacement with rollback capabilities","type":"module","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","prepare":"npm run build","test":"jest","lint":"eslint src --ext .ts","format":"prettier --write src/**/*.ts","publish":"npm publish --access public"},"keywords":["updater","atomic","directory","replacement","electron","app","bundle","macos","windows","linux"],"author":{"name":"Charles Liu"},"license":"MIT","engines":{"node":">=14.0.0"},"devDependencies":{"@types/jest":"^29.0.0","@types/node":"^18.0.0","@typescript-eslint/eslint-plugin":"^5.0.0","@typescript-eslint/parser":"^5.0.0","eslint":"^8.0.0","jest":"^29.0.0","prettier":"^2.8.0","ts-jest":"^29.0.0","typescript":"^4.9.0"},"repository":{"type":"git","url":"git+https://github.com/activebook/atom-updater.git"},"homepage":"https://github.com/activebook/atom-updater","bugs":{"url":"https://github.com/activebook/atom-updater/issues"},"_id":"@activebook/atom-updater@2.0.2","gitHead":"7201041aee8112802dad64617c1c2baf14c0f5aa","_nodeVersion":"22.19.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-UxMWpUe0fGCZlJTMUPofYmEuXN4jhXSCveh1EfJLffrgIy5r+tzNz68RT1jkqblIaJZTFbMl9EL0Ub5zAW9Z/g==","shasum":"b88618dcce00558e9dab3161322af7cd98e79458","tarball":"https://registry.npmjs.org/@activebook/atom-updater/-/atom-updater-2.0.2.tgz","fileCount":39,"unpackedSize":14628691,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCAM2hJDJlo1m+dZQ4ltdG0F2BRtR/6uIlUZHqrM7jPaQIgDTuLrtgBESv7UCCT2KIMW2iXlP11TVAGe8xSRudg6p0="}]},"_npmUser":{"name":"activebook","email":"himurokaoru@gmail.com"},"directories":{},"maintainers":[{"name":"activebook","email":"himurokaoru@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/atom-updater_2.0.2_1759187983805_0.4166112058249207"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-29T09:10:02.275Z","modified":"2025-09-29T23:19:44.304Z","2.0.0":"2025-09-29T09:10:02.676Z","2.0.1":"2025-09-29T09:21:15.169Z","2.0.2":"2025-09-29T23:19:44.116Z"},"bugs":{"url":"https://github.com/activebook/atom-updater/issues"},"author":{"name":"Charles Liu"},"license":"MIT","homepage":"https://github.com/activebook/atom-updater","keywords":["updater","atomic","directory","replacement","electron","app","bundle","macos","windows","linux"],"repository":{"type":"git","url":"git+https://github.com/activebook/atom-updater.git"},"description":"Node.js wrapper for atom-updater Go executable - provides atomic directory replacement with rollback capabilities","maintainers":[{"name":"activebook","email":"himurokaoru@gmail.com"}],"readme":"# npm @activebook/atom-updater\n\nA TypeScript Node.js wrapper for the [atom-updater](https://github.com/activebook/atom-updater) Go executable. This package provides atomic directory replacement with rollback capabilities for Node.js and Electron applications.\n\n## Features\n\n- **Atomic Directory Updates**: All-or-nothing directory replacement with automatic rollback\n- **macOS .app Bundle Support**: Specialized handling for directories containing .app bundles\n- **Comprehensive Logging**: Real-time console output + persistent log file\n- **Robust Error Handling**: Graceful failure handling with safe rollback\n- **Smart Application Launching**: Auto-detects and launches the correct application\n- **Cross-Platform**: Works on Windows, macOS, and Linux\n- **Easy Integration**: Simple TypeScript API for Node.js and Electron apps\n- **Self-Contained**: Bundled binaries eliminate external dependencies\n\n## How It Works\n\nThis package uses a **bundled binary approach** where platform-specific `atom-updater` executables are included directly in the npm package. When you install the package, you get:\n\n- The TypeScript wrapper code\n- Pre-compiled `atom-updater` binaries for your platform\n- Automatic binary detection and selection\n\nThe wrapper automatically finds and uses the correct binary for your platform and architecture, eliminating the need for separate downloads or installations.\n\n### Self-Updating Applications\n\nFor applications that need to update themselves, use the `binDir` parameter to copy the atom-updater binary to an external location first:\n\n1. **Copy Phase**: The bundled binary is copied to an external directory outside your app\n2. **Update Phase**: The external copy performs the atomic directory replacement\n3. **Launch Phase**: The new version of your application is launched\n\nThis approach prevents the updater from trying to replace itself during self-updates.\n\n## Installation\n\n```bash\nnpm install @activebook/atom-updater\n```\n\nThe package includes platform-specific `atom-updater` binaries, so no additional downloads are required. The wrapper automatically detects and uses the bundled binary for your platform and architecture.\n\n## Quick Start\n\n```typescript\nimport { AtomUpdater } from 'atom-updater';\n\nconst updater = new AtomUpdater();\n\n// Check version\nconst version = await updater.getVersion();\nconsole.log(`Atom updater version: ${version}`);\n\n// Perform update\nconst result = await updater.update({\n  pid: process.pid,\n  currentAppDir: '/path/to/current/app',\n  newAppDir: '/path/to/new/app/version'\n});\n\nif (result.success) {\n  console.log('Update initiated successfully!');\n  console.log(`Log file: ${result.logPath}`);\n\n  // Exit immediately - atom-updater will handle the rest\n  process.exit(0);\n} else {\n  console.error('Update failed to start:', result.error);\n}\n```\n\n## API Reference\n\n### AtomUpdater Class\n\n#### Constructor\n\n```typescript\nconstructor(options?: AtomUpdaterOptions)\n```\n\n**Options:**\n- `executablePath?: string` - Custom path to the atom-updater executable\n- `workingDirectory?: string` - Working directory for the update process\n- `verbose?: boolean` - Enable verbose logging\n- `logger?: (message: string) => void` - Custom logger function\n\n#### Methods\n\n##### `getVersion(): Promise<string>`\n\nGet the version of the atom-updater executable.\n\n```typescript\nconst version = await updater.getVersion();\n```\n\n##### `update(config: UpdateConfig): Promise<UpdateResult>`\n\nPerform an atomic update by starting the atom-updater process as a detached background process. **This method returns immediately** - the actual update happens asynchronously after the calling process exits.\n\nFor self-updating applications, use the `binDir` parameter to copy the atom-updater binary to an external location first. This prevents the updater from trying to replace itself.\n\n```typescript\nconst result = await updater.update({\n  pid: 12345,\n  currentDir: '/path/to/current',\n  newDir: '/path/to/new',\n  appName: 'optional-app-name', // Optional\n  binDir: '/tmp/atom-updater-external' // Optional: for self-updates\n});\n\n// The method returns immediately with success: true\n// The calling application should exit immediately after this call\n// atom-updater will wait for the exit, perform the update, and launch the new version\n```\n\n##### `isAvailable(): Promise<boolean>`\n\nCheck if the atom-updater executable is available.\n\n```typescript\nconst available = await updater.isAvailable();\n```\n\n##### `getExecutablePath(): string`\n\nGet the path to the executable being used.\n\n### Types\n\n#### UpdateConfig\n\n```typescript\ninterface UpdateConfig {\n  pid: number;           // Process ID to wait for exit\n  currentAppDir: string; // Path to current application directory\n  newAppDir: string;     // Path to new application directory\n  appName?: string;      // Optional specific executable to launch\n  timeout?: number;      // Optional timeout for the update process\n  binDir?: string;       // Optional external directory to copy atom-updater binary (for self-updates)\n}\n```\n\n#### UpdateResult\n\n```typescript\ninterface UpdateResult {\n  success: boolean;      // Whether the update process was started successfully\n  logPath?: string;      // Path to the log file (atom-updater.log)\n  launchedPid?: number;  // Process ID of the atom-updater process\n  // Note: version and error fields are not used in the bundled binary approach\n}\n```\n\n## Update Process Flow\n\nWith the bundled binary approach, the update process follows this sequence:\n\n1. **Your app calls** `updater.update(config)` with paths and PID\n2. **Wrapper starts** `atom-updater` as a detached background process\n3. **Method returns immediately** with `success: true`\n4. **Your app exits** (via `app.quit()` in Electron or `process.exit()` in Node.js)\n5. **atom-updater waits** for your app process to fully exit\n6. **atom-updater performs** the atomic directory replacement\n7. **atom-updater launches** the new version of your application\n8. **atom-updater exits**\n\nThis approach ensures safe, atomic updates without the chicken-and-egg problem of waiting for completion.\n\n## Integration Examples\n\n### Electron Application\n\n```typescript\nimport { AtomUpdater } from 'atom-updater';\nimport { app } from 'electron';\n\nclass AppUpdater {\n  private updater = new AtomUpdater({ verbose: true });\n\n  async checkForUpdates() {\n    try {\n      const available = await this.updater.isAvailable();\n      if (!available) {\n        console.error('atom-updater executable not found');\n        return;\n      }\n\n      const version = await this.updater.getVersion();\n      console.log(`Using atom-updater version: ${version}`);\n    } catch (error) {\n      console.error('Failed to check updater:', error);\n    }\n  }\n\n  async performUpdate(newVersionPath: string) {\n    try {\n      const result = await this.updater.update({\n        pid: process.pid,\n        currentAppDir: __dirname, // Electron app directory\n        newAppDir: newVersionPath\n      });\n\n      if (result.success) {\n        console.log('Update initiated successfully!');\n        console.log(`Log file: ${result.logPath}`);\n\n        // Exit immediately - atom-updater will handle the rest\n        // It will wait for this process to exit, perform the update,\n        // and launch the new version automatically\n        app.quit();\n      } else {\n        console.error('Update failed to start:', result.error);\n      }\n    } catch (error) {\n      console.error('Update error:', error);\n    }\n  }\n}\n```\n\n### Self-Updating Electron Application\n\n```typescript\nimport { AtomUpdater } from 'atom-updater';\nimport { app } from 'electron';\nimport path from 'path';\nimport os from 'os';\n\nclass AppUpdater {\n  private updater = new AtomUpdater({ verbose: true });\n\n  async performSelfUpdate(newVersionPath: string) {\n    try {\n      // For self-updates, copy the updater binary to an external directory\n      const tempDir = os.tmpdir();\n      const externalBinDir = path.join(tempDir, 'atom-updater-bin');\n\n      const result = await this.updater.update({\n        pid: process.pid,\n        currentAppDir: __dirname, // Electron app directory\n        newAppDir: newVersionPath,\n        binDir: externalBinDir // Copy binary to external directory for self-update\n      });\n\n      if (result.success) {\n        console.log('Self-update initiated successfully!');\n        console.log(`External updater: ${externalUpdaterPath}`);\n        console.log(`Log file: ${result.logPath}`);\n\n        // Exit immediately - external updater will handle the rest\n        app.quit();\n      } else {\n        console.error('Self-update failed to start:', result.error);\n      }\n    } catch (error) {\n      console.error('Self-update error:', error);\n    }\n  }\n}\n```\n\n### Node.js Application\n\n```typescript\nimport { update, getVersion } from 'atom-updater';\n\nasync function performUpdate() {\n  try {\n    // Check if updater is available\n    const version = await getVersion();\n    console.log(`Using atom-updater ${version}`);\n\n    // Perform update\n    const result = await update({\n      pid: process.pid,\n      currentAppDir: process.cwd(),\n      newAppDir: './updates/new-version'\n    });\n\n    if (result.success) {\n      console.log('Update initiated successfully!');\n      console.log(`Log file: ${result.logPath}`);\n\n      // Exit immediately - atom-updater will handle the rest\n      process.exit(0);\n    } else {\n      console.error('Update failed to start:', result.error);\n    }\n  } catch (error) {\n    console.error('Update process failed:', error);\n  }\n}\n```\n\n### Custom Executable Path\n\n```typescript\nimport { AtomUpdater } from 'atom-updater';\n\nconst updater = new AtomUpdater({\n  executablePath: '/custom/path/to/atom-updater',\n  verbose: true\n});\n```\n\n## Platform Support\n\n- **Windows**: `amd64`, `386` - bundled binaries included\n- **macOS**: `amd64`, `arm64` (Apple Silicon) - bundled binaries included, **optimized for .app bundles**\n- **Linux**: `amd64`, `arm64`, `386` - bundled binaries included\n\nThe package includes platform-specific binaries, so no additional downloads are required.\n\n## Requirements\n\n- Node.js 14.0.0 or later\n- No additional dependencies - the `atom-updater` binary is bundled with the package\n\n## Error Handling\n\nThe package provides specific error classes for different failure scenarios:\n\n```typescript\nimport {\n  AtomUpdaterError,\n  ExecutableNotFoundError,\n  UpdateFailedError\n} from 'atom-updater';\n\ntry {\n  await updater.update(config);\n} catch (error) {\n  if (error instanceof ExecutableNotFoundError) {\n    console.error('atom-updater executable not found');\n  } else if (error instanceof UpdateFailedError) {\n    console.error('Update failed:', error.message);\n  } else {\n    console.error('Unexpected error:', error);\n  }\n}\n```\n\n## Logging\n\nThe atom-updater executable provides comprehensive logging:\n\n- **Console Output**: Real-time progress during updates\n- **File Logging**: Persistent log at `./atom-updater.log` (auto-cleared on startup)\n- **Debug Information**: Timestamps and source file names for troubleshooting\n\nThe log file is created in the same directory as the `atom-updater` executable.\n","readmeFilename":"README.md"}