creative-upload-extension-updater 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@ macOS Native Messaging updater for the unpacked Creative Upload Chrome extension
5
5
  ## First installation
6
6
 
7
7
  ```bash
8
- npm install -g creative-upload-extension-updater
8
+ npm install -g @ttam/creative-upload-extension-updater
9
9
  creative-upload-extension-updater install
10
10
  ```
11
11
 
@@ -20,13 +20,14 @@ The extension ID is fixed to `amfhocfbdlbooohhoinhhhgobfdmaljc`. Do not change t
20
20
  creative-upload-extension-updater diagnose
21
21
  creative-upload-extension-updater update
22
22
  creative-upload-extension-updater rollback
23
+ creative-upload-updater uninstall
24
+ creative-upload-updater uninstall --purge
23
25
  ```
24
26
 
25
- `creative-upload-updater` is kept as a shorter command alias. Both commands
26
- run the same updater and are supported for backward compatibility.
27
-
28
27
  `update` immediately checks the Registry and applies a newer verified release when available. On macOS it then opens a controlled extension URL so the running extension calls `chrome.runtime.reload()` automatically; pass `--no-reload` to only replace files. `rollback` restores the previous verified extension directory. Chrome must then reload the extension once.
29
28
 
29
+ `uninstall` removes the Native Messaging registration and updater configuration but retains the downloaded extension. `uninstall --purge` additionally deletes the extension and rollback files. Both modes require manually removing the loaded extension in `chrome://extensions`; uninstall the CLI itself with `npm uninstall -g creative-upload-extension-updater`.
30
+
30
31
  ## Security
31
32
 
32
33
  The updater accepts only the configured Registry URL, checks the release SHA256, verifies the detached Ed25519 signature, and verifies the manifest version and fixed Extension ID before replacing files. HTTP is a temporary internal-network transport exception; the signing private key is never stored in this package or in the Registry.
@@ -1,7 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  const fs = require('node:fs');
3
3
  const path = require('node:path');
4
- const { diagnose, install, requestChromeReload, rollback, update, TRANSITION_HTTP_REGISTRY_ORIGIN } = require('../lib/updater');
4
+ const { diagnose, install, requestChromeReload, rollback, uninstall, update, TRANSITION_HTTP_REGISTRY_ORIGIN } = require('../lib/updater');
5
+
6
+ const packageVersion = require('../package.json').version;
7
+ const usage = `用法:creative-upload-updater <命令> [选项]
8
+
9
+ 命令:
10
+ install [--registry <url>] [--allow-insecure] 安装更新器与首次插件版本
11
+ update [--no-reload] 下载并应用最新插件版本
12
+ diagnose 输出本机安装诊断
13
+ rollback 回滚到上一插件版本
14
+ uninstall [--purge] 移除更新器注册;--purge 同时删除插件文件
15
+
16
+ 选项:
17
+ --help, -h 显示帮助
18
+ --version, -v 显示版本`;
5
19
 
6
20
  const parseArguments = (values) =>
7
21
  values.reduce((result, value, index) => {
@@ -15,6 +29,14 @@ const parseArguments = (values) =>
15
29
  const main = async () => {
16
30
  const [command] = process.argv.slice(2);
17
31
  const args = parseArguments(process.argv.slice(3));
32
+ if (!command || command === '--help' || command === '-h' || args.help === true) {
33
+ process.stdout.write(`${usage}\n`);
34
+ return;
35
+ }
36
+ if (command === '--version' || command === '-v' || args.version === true) {
37
+ process.stdout.write(`${packageVersion}\n`);
38
+ return;
39
+ }
18
40
  if (command === 'install') {
19
41
  const publicKey =
20
42
  typeof args['public-key'] === 'string'
@@ -40,9 +62,8 @@ const main = async () => {
40
62
  return process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
41
63
  }
42
64
  if (command === 'rollback') return process.stdout.write(`${JSON.stringify(rollback(), null, 2)}\n`);
43
- throw new Error(
44
- '用法:creative-upload-extension-updater install [--registry <url>] [--allow-insecure] | update [--no-reload] | diagnose | rollback。默认使用当前 Devbox 过渡地址。',
45
- );
65
+ if (command === 'uninstall') return process.stdout.write(`${JSON.stringify(uninstall({ purge: args.purge === true }), null, 2)}\n`);
66
+ throw new Error(`未知命令:${command}\n\n${usage}`);
46
67
  };
47
68
 
48
69
  main().catch((error) => {
package/lib/updater.js CHANGED
@@ -16,6 +16,15 @@ const configPath = path.join(baseDirectory, 'updater.json');
16
16
  const extensionDirectory = path.join(baseDirectory, 'extension');
17
17
  const previousDirectory = path.join(baseDirectory, 'previous');
18
18
  const nativeHostLauncherPath = path.join(baseDirectory, 'native-host');
19
+ const nativeHostManifestPath = path.join(
20
+ os.homedir(),
21
+ 'Library',
22
+ 'Application Support',
23
+ 'Google',
24
+ 'Chrome',
25
+ 'NativeMessagingHosts',
26
+ `${HOST_NAME}.json`,
27
+ );
19
28
 
20
29
  const readConfig = () => {
21
30
  if (!fs.existsSync(configPath)) throw new Error('更新器尚未安装。请运行 creative-upload-extension-updater install。');
@@ -148,12 +157,26 @@ const install = async ({ registryUrl = TRANSITION_HTTP_REGISTRY_ORIGIN, extensio
148
157
  const config = { registryUrl: registryUrl.replace(/\/$/, ''), extensionId, signingPublicKey: publicKey, allowInsecure };
149
158
  writeConfig(config);
150
159
  const update = await checkAndUpdate({ extensionId, currentVersion: '0.0.0' });
151
- const manifestDirectory = path.join(os.homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts');
160
+ const manifestDirectory = path.dirname(nativeHostManifestPath);
152
161
  fs.mkdirSync(manifestDirectory, { recursive: true, mode: 0o700 });
153
162
  const launcherPath = installNativeHostLauncher(hostPath);
154
- fs.writeFileSync(path.join(manifestDirectory, `${HOST_NAME}.json`), `${JSON.stringify({ name: HOST_NAME, description: 'Creative Upload Extension Updater', path: launcherPath, type: 'stdio', allowed_origins: [`chrome-extension://${extensionId}/`] }, null, 2)}\n`, { mode: 0o600 });
163
+ fs.writeFileSync(nativeHostManifestPath, `${JSON.stringify({ name: HOST_NAME, description: 'Creative Upload Extension Updater', path: launcherPath, type: 'stdio', allowed_origins: [`chrome-extension://${extensionId}/`] }, null, 2)}\n`, { mode: 0o600 });
155
164
  return { ...update, extensionDirectory, extensionId };
156
165
  };
166
+ const uninstall = ({ purge = false } = {}) => {
167
+ const nativeHostRegistered = fs.existsSync(nativeHostManifestPath);
168
+ fs.rmSync(nativeHostManifestPath, { force: true });
169
+ fs.rmSync(configPath, { force: true });
170
+ fs.rmSync(nativeHostLauncherPath, { force: true });
171
+ if (purge) fs.rmSync(baseDirectory, { recursive: true, force: true });
172
+ return {
173
+ nativeHostRemoved: nativeHostRegistered,
174
+ extensionDirectory,
175
+ extensionRetained: !purge && fs.existsSync(extensionDirectory),
176
+ purged: purge,
177
+ chromeAction: '请在 chrome://extensions 手动移除已加载的扩展。',
178
+ };
179
+ };
157
180
  const rollback = () => {
158
181
  if (!fs.existsSync(previousDirectory)) throw new Error('没有可回滚的上一版本。');
159
182
  const currentDirectory = `${extensionDirectory}.rollback-${Date.now()}`;
@@ -164,8 +187,7 @@ const rollback = () => {
164
187
  };
165
188
  const diagnose = () => {
166
189
  const config = readConfig();
167
- const manifestPath = path.join(os.homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts', `${HOST_NAME}.json`);
168
- return { extensionDirectory, extensionLoaded: fs.existsSync(path.join(extensionDirectory, 'manifest.json')), nativeHostRegistered: fs.existsSync(manifestPath), registryUrl: config.registryUrl, extensionId: config.extensionId };
190
+ return { extensionDirectory, extensionLoaded: fs.existsSync(path.join(extensionDirectory, 'manifest.json')), nativeHostRegistered: fs.existsSync(nativeHostManifestPath), registryUrl: config.registryUrl, extensionId: config.extensionId };
169
191
  };
170
192
 
171
- module.exports = { DEFAULT_EXTENSION_ID, HOST_NAME, TRANSITION_HTTP_REGISTRY_ORIGIN, checkAndUpdate, diagnose, install, requestChromeReload, rollback, update };
193
+ module.exports = { DEFAULT_EXTENSION_ID, HOST_NAME, TRANSITION_HTTP_REGISTRY_ORIGIN, checkAndUpdate, diagnose, install, requestChromeReload, rollback, uninstall, update };
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "creative-upload-extension-updater",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "description": "Native Messaging updater for the Creative Upload unpacked Chrome extension.",
6
6
  "bin": {
7
- "creative-upload-updater": "bin/creative-upload-extension-updater.js",
8
- "creative-upload-extension-updater": "bin/creative-upload-extension-updater.js"
7
+ "creative-upload-updater": "bin/creative-upload-extension-updater.js"
9
8
  },
10
9
  "engines": {
11
10
  "node": ">=18"