@gpc-cli/cli 0.9.28 → 0.9.31

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.
Files changed (61) hide show
  1. package/dist/apps-CVBURB5V.js +0 -0
  2. package/dist/{audit-QP75CEGB.js → audit-A4BP27DN.js} +19 -3
  3. package/dist/audit-A4BP27DN.js.map +1 -0
  4. package/dist/auth-5XAQMZRV.js +0 -0
  5. package/dist/bin.js +8 -83
  6. package/dist/bin.js.map +1 -1
  7. package/dist/bundle-7IF5FIB4.js +0 -0
  8. package/dist/chunk-4O4D5SGL.js +86 -0
  9. package/dist/chunk-4O4D5SGL.js.map +1 -0
  10. package/dist/{chunk-PREKF2AM.js → chunk-5VVYPCDE.js} +9 -6
  11. package/dist/chunk-5VVYPCDE.js.map +1 -0
  12. package/dist/chunk-ELXAK7GI.js +0 -0
  13. package/dist/chunk-FWKYRLKY.js +0 -0
  14. package/dist/chunk-NV75I5VP.js +0 -0
  15. package/dist/chunk-Y3QZDAKS.js +0 -0
  16. package/dist/completion-C3PPWNS7.js +0 -0
  17. package/dist/config-2L7QUYWP.js +0 -0
  18. package/dist/data-safety-GDPKV5PN.js +0 -0
  19. package/dist/device-tiers-GHIYJPMB.js +0 -0
  20. package/dist/docs-HIGQU4UL.js +45 -0
  21. package/dist/docs-HIGQU4UL.js.map +1 -0
  22. package/dist/doctor-UZB2UB5X.js +0 -0
  23. package/dist/external-transactions-HCL7ROMN.js +0 -0
  24. package/dist/generated-apks-VX7HYZDU.js +0 -0
  25. package/dist/iap-BBHF7BLZ.js +0 -0
  26. package/dist/index.js +1 -1
  27. package/dist/install-skills-OV4HVANW.js +0 -0
  28. package/dist/internal-sharing-E7SJYDW3.js +0 -0
  29. package/dist/listings-VSBHQY5H.js +0 -0
  30. package/dist/migrate-XQV7P4R7.js +0 -0
  31. package/dist/one-time-products-2PK4QKWE.js +0 -0
  32. package/dist/pricing-BYZSLN74.js +0 -0
  33. package/dist/prompt-BSV22CQZ.js +0 -0
  34. package/dist/{publish-26ZPS7XX.js → publish-I6WJGR4S.js} +8 -2
  35. package/dist/publish-I6WJGR4S.js.map +1 -0
  36. package/dist/purchase-options-CKRN4VIW.js +0 -0
  37. package/dist/purchases-YRO6B7M6.js +0 -0
  38. package/dist/recovery-S5UNJDBO.js +0 -0
  39. package/dist/{releases-ZKPSAPB2.js → releases-JMRKXEZU.js} +49 -7
  40. package/dist/releases-JMRKXEZU.js.map +1 -0
  41. package/dist/reports-N5X66IUN.js +0 -0
  42. package/dist/reviews-GJAQ5OVC.js +0 -0
  43. package/dist/{status-NE3A2UHN.js → status-6Y2CHHVD.js} +34 -4
  44. package/dist/status-6Y2CHHVD.js.map +1 -0
  45. package/dist/subscriptions-Z5ZPVUFM.js +0 -0
  46. package/dist/testers-UWSUGGVT.js +0 -0
  47. package/dist/tracks-XFUN7JJX.js +0 -0
  48. package/dist/update-GC2A2WVP.js +451 -0
  49. package/dist/update-GC2A2WVP.js.map +1 -0
  50. package/dist/users-JASXONRY.js +0 -0
  51. package/dist/validate-MHLPENCM.js +0 -0
  52. package/dist/vitals-KSNAVN5F.js +0 -0
  53. package/package.json +17 -17
  54. package/LICENSE +0 -21
  55. package/dist/audit-QP75CEGB.js.map +0 -1
  56. package/dist/chunk-PREKF2AM.js.map +0 -1
  57. package/dist/docs-CVTWIVMS.js +0 -20
  58. package/dist/docs-CVTWIVMS.js.map +0 -1
  59. package/dist/publish-26ZPS7XX.js.map +0 -1
  60. package/dist/releases-ZKPSAPB2.js.map +0 -1
  61. package/dist/status-NE3A2UHN.js.map +0 -1
@@ -0,0 +1,451 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isNewerVersion
4
+ } from "./chunk-4O4D5SGL.js";
5
+
6
+ // src/updater.ts
7
+ import { createWriteStream } from "fs";
8
+ import { rename, chmod, unlink, stat } from "fs/promises";
9
+ import { realpathSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ import { createHash } from "crypto";
12
+ import { pipeline } from "stream/promises";
13
+ import { Readable, Transform } from "stream";
14
+ import { spawn } from "child_process";
15
+ var GITHUB_API_URL = "https://api.github.com/repos/yasserstudio/gpc/releases/latest";
16
+ var GITHUB_TIMEOUT_MS = 1e4;
17
+ var DOWNLOAD_TIMEOUT_MS = 12e4;
18
+ function detectInstallMethod() {
19
+ if (process.env["__GPC_BINARY"] === "1") return "binary";
20
+ if (process.env["npm_config_prefix"]) return "npm";
21
+ try {
22
+ const resolved = realpathSync(process.argv[1] ?? "").toLowerCase();
23
+ if (resolved.includes("cellar") || resolved.includes("homebrew")) return "homebrew";
24
+ if (resolved.includes("node_modules")) return "npm";
25
+ } catch {
26
+ }
27
+ return "unknown";
28
+ }
29
+ function getPlatformAsset() {
30
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
31
+ switch (process.platform) {
32
+ case "darwin":
33
+ return `gpc-darwin-${arch}`;
34
+ case "linux":
35
+ return `gpc-linux-${arch}`;
36
+ case "win32":
37
+ return "gpc-windows-x64.exe";
38
+ default:
39
+ return null;
40
+ }
41
+ }
42
+ function getCurrentBinaryPath() {
43
+ if (process.env["__GPC_BINARY"] === "1") return process.execPath;
44
+ return process.argv[1] ?? process.execPath;
45
+ }
46
+ function githubHeaders() {
47
+ const headers = {
48
+ "User-Agent": "gpc-cli",
49
+ Accept: "application/vnd.github+json",
50
+ "X-GitHub-Api-Version": "2022-11-28"
51
+ };
52
+ if (process.env["GPC_GITHUB_TOKEN"]) {
53
+ headers["Authorization"] = `Bearer ${process.env["GPC_GITHUB_TOKEN"]}`;
54
+ }
55
+ return headers;
56
+ }
57
+ async function fetchLatestRelease() {
58
+ let response;
59
+ try {
60
+ response = await fetch(GITHUB_API_URL, {
61
+ headers: githubHeaders(),
62
+ signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS)
63
+ });
64
+ } catch (err) {
65
+ const msg = err instanceof Error ? err.message : String(err);
66
+ throw Object.assign(new Error(`Network error checking for updates: ${msg}`), {
67
+ code: "NETWORK_ERROR",
68
+ exitCode: 5
69
+ });
70
+ }
71
+ if (response.status === 429) {
72
+ throw Object.assign(
73
+ new Error(
74
+ "GitHub API rate limit exceeded. Set GPC_GITHUB_TOKEN to increase the limit."
75
+ ),
76
+ { code: "UPDATE_RATE_LIMITED", exitCode: 4 }
77
+ );
78
+ }
79
+ if (!response.ok) {
80
+ throw Object.assign(new Error(`GitHub API returned HTTP ${response.status}`), {
81
+ code: "UPDATE_API_ERROR",
82
+ exitCode: 4
83
+ });
84
+ }
85
+ return await response.json();
86
+ }
87
+ async function fetchChecksums(release) {
88
+ const asset = release.assets.find((a) => a.name === "checksums.txt");
89
+ if (!asset) return /* @__PURE__ */ new Map();
90
+ try {
91
+ const response = await fetch(asset.browser_download_url, {
92
+ headers: githubHeaders(),
93
+ signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS)
94
+ });
95
+ if (!response.ok) return /* @__PURE__ */ new Map();
96
+ const map = /* @__PURE__ */ new Map();
97
+ for (const line of (await response.text()).split("\n")) {
98
+ const parts = line.trim().split(/\s+/);
99
+ const hash = parts[0];
100
+ const name = parts[1];
101
+ if (hash && name) map.set(name, hash.toLowerCase());
102
+ }
103
+ return map;
104
+ } catch {
105
+ return /* @__PURE__ */ new Map();
106
+ }
107
+ }
108
+ async function checkForUpdate(currentVersion) {
109
+ const release = await fetchLatestRelease();
110
+ const latest = release.tag_name.replace(/^v/, "");
111
+ return {
112
+ current: currentVersion,
113
+ latest,
114
+ latestTag: release.tag_name,
115
+ updateAvailable: isNewerVersion(currentVersion, latest),
116
+ installMethod: detectInstallMethod(),
117
+ release
118
+ };
119
+ }
120
+ async function updateViaNpm(options = {}) {
121
+ return new Promise((resolve, reject) => {
122
+ const proc = spawn("npm", ["install", "-g", "@gpc-cli/cli@latest"], {
123
+ // In silent (JSON) mode, redirect npm's stdout to stderr so it doesn't
124
+ // pollute the machine-readable JSON that gpc writes to stdout.
125
+ stdio: options.silent ? ["inherit", process.stderr, process.stderr] : "inherit",
126
+ shell: false
127
+ });
128
+ proc.on("close", (code) => {
129
+ if (code === 0) {
130
+ resolve();
131
+ } else {
132
+ reject(
133
+ Object.assign(new Error(`npm exited with code ${code}`), {
134
+ code: "UPDATE_NPM_FAILED",
135
+ exitCode: 1,
136
+ suggestion: "Run manually: npm install -g @gpc-cli/cli@latest"
137
+ })
138
+ );
139
+ }
140
+ });
141
+ proc.on("error", (err) => {
142
+ reject(
143
+ Object.assign(new Error(`Failed to run npm: ${err.message}`), {
144
+ code: "UPDATE_NPM_SPAWN_FAILED",
145
+ exitCode: 1,
146
+ suggestion: "Ensure npm is in your PATH"
147
+ })
148
+ );
149
+ });
150
+ });
151
+ }
152
+ async function updateViaBrew(options = {}) {
153
+ return new Promise((resolve, reject) => {
154
+ const proc = spawn("brew", ["upgrade", "yasserstudio/tap/gpc"], {
155
+ // In silent (JSON) mode, redirect brew's stdout to stderr so it doesn't
156
+ // pollute the machine-readable JSON that gpc writes to stdout.
157
+ stdio: options.silent ? ["inherit", process.stderr, process.stderr] : "inherit",
158
+ shell: false
159
+ });
160
+ proc.on("close", (code) => {
161
+ if (code === 0) {
162
+ resolve();
163
+ } else {
164
+ reject(
165
+ Object.assign(new Error(`brew exited with code ${code}`), {
166
+ code: "UPDATE_BREW_FAILED",
167
+ exitCode: 1,
168
+ suggestion: "Run manually: brew upgrade yasserstudio/tap/gpc"
169
+ })
170
+ );
171
+ }
172
+ });
173
+ proc.on("error", (err) => {
174
+ reject(
175
+ Object.assign(new Error(`Failed to run brew: ${err.message}`), {
176
+ code: "UPDATE_BREW_SPAWN_FAILED",
177
+ exitCode: 1,
178
+ suggestion: "Ensure Homebrew is installed: https://brew.sh"
179
+ })
180
+ );
181
+ });
182
+ });
183
+ }
184
+ function isPermissionError(err) {
185
+ return err instanceof Error && "code" in err && (err.code === "EACCES" || err.code === "EPERM");
186
+ }
187
+ async function sha256File(filePath) {
188
+ const hash = createHash("sha256");
189
+ const { size } = await stat(filePath);
190
+ if (size === 0) return hash.digest("hex");
191
+ const { createReadStream } = await import("fs");
192
+ const stream = createReadStream(filePath);
193
+ await pipeline(stream, async function* (source) {
194
+ for await (const chunk of source) {
195
+ hash.update(chunk);
196
+ }
197
+ });
198
+ return hash.digest("hex");
199
+ }
200
+ async function updateBinaryInPlace(assetUrl, expectedSha256, currentBinaryPath, options = {}) {
201
+ const dir = dirname(currentBinaryPath);
202
+ const tmpPath = join(dir, `.gpc-update-${process.pid}.tmp`);
203
+ const oldPath = join(dir, `.gpc-old-${process.pid}`);
204
+ try {
205
+ let response;
206
+ try {
207
+ response = await fetch(assetUrl, {
208
+ signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
209
+ });
210
+ } catch (err) {
211
+ const msg = err instanceof Error ? err.message : String(err);
212
+ throw Object.assign(new Error(`Download failed: ${msg}`), {
213
+ code: "UPDATE_DOWNLOAD_FAILED",
214
+ exitCode: 5
215
+ });
216
+ }
217
+ if (!response.ok) {
218
+ throw Object.assign(new Error(`Download failed: HTTP ${response.status}`), {
219
+ code: "UPDATE_DOWNLOAD_FAILED",
220
+ exitCode: 4
221
+ });
222
+ }
223
+ if (!response.body) {
224
+ throw Object.assign(new Error("Empty response body"), {
225
+ code: "UPDATE_DOWNLOAD_FAILED",
226
+ exitCode: 4
227
+ });
228
+ }
229
+ const contentLength = response.headers.get("content-length");
230
+ const total = contentLength ? parseInt(contentLength, 10) : 0;
231
+ let downloaded = 0;
232
+ const dest = createWriteStream(tmpPath);
233
+ const { onProgress } = options;
234
+ if (onProgress) {
235
+ const tracker = new Transform({
236
+ transform(chunk, _enc, cb) {
237
+ downloaded += chunk.length;
238
+ onProgress(downloaded, total);
239
+ cb(null, chunk);
240
+ }
241
+ });
242
+ await pipeline(
243
+ Readable.fromWeb(response.body),
244
+ tracker,
245
+ dest
246
+ );
247
+ } else {
248
+ await pipeline(Readable.fromWeb(response.body), dest);
249
+ }
250
+ if (expectedSha256) {
251
+ const actual = await sha256File(tmpPath);
252
+ if (actual !== expectedSha256.toLowerCase()) {
253
+ throw Object.assign(
254
+ new Error(`Checksum mismatch \u2014 expected ${expectedSha256}, got ${actual}`),
255
+ {
256
+ code: "UPDATE_CHECKSUM_MISMATCH",
257
+ exitCode: 1,
258
+ suggestion: "The download may be corrupt. Try again."
259
+ }
260
+ );
261
+ }
262
+ }
263
+ if (process.platform !== "win32") {
264
+ await chmod(tmpPath, 493);
265
+ }
266
+ if (process.platform === "win32") {
267
+ await rename(currentBinaryPath, oldPath);
268
+ try {
269
+ await rename(tmpPath, currentBinaryPath);
270
+ } catch (renameErr) {
271
+ await rename(oldPath, currentBinaryPath).catch(() => {
272
+ });
273
+ throw renameErr;
274
+ }
275
+ unlink(oldPath).catch(() => {
276
+ });
277
+ } else {
278
+ await rename(tmpPath, currentBinaryPath);
279
+ }
280
+ } catch (err) {
281
+ await unlink(tmpPath).catch(() => {
282
+ });
283
+ if (isPermissionError(err)) {
284
+ throw Object.assign(
285
+ new Error(`Permission denied replacing ${currentBinaryPath}`),
286
+ {
287
+ code: "UPDATE_PERMISSION_DENIED",
288
+ exitCode: 1,
289
+ suggestion: `Run with elevated permissions: sudo gpc update`
290
+ }
291
+ );
292
+ }
293
+ throw err;
294
+ }
295
+ }
296
+
297
+ // src/commands/update.ts
298
+ import { createSpinner } from "@gpc-cli/core";
299
+ function registerUpdateCommand(program) {
300
+ program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
301
+ const parentOpts = cmd.parent?.opts() ?? {};
302
+ const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
303
+ const currentVersion = process.env["__GPC_VERSION"] ?? "0.0.0";
304
+ if (currentVersion === "0.0.0") {
305
+ if (jsonMode) {
306
+ console.log(
307
+ JSON.stringify({
308
+ success: false,
309
+ reason: "Cannot update a development build",
310
+ current: currentVersion
311
+ })
312
+ );
313
+ } else {
314
+ console.log("Cannot update a development build (version: 0.0.0).");
315
+ }
316
+ return;
317
+ }
318
+ const spinner = createSpinner("Checking for updates...");
319
+ spinner.start();
320
+ let result;
321
+ try {
322
+ result = await checkForUpdate(currentVersion);
323
+ } catch (err) {
324
+ spinner.fail("Failed to check for updates");
325
+ throw err;
326
+ }
327
+ if (opts.check) {
328
+ spinner.stop();
329
+ if (jsonMode) {
330
+ console.log(
331
+ JSON.stringify({
332
+ current: result.current,
333
+ latest: result.latest,
334
+ updateAvailable: result.updateAvailable,
335
+ installMethod: result.installMethod,
336
+ releaseUrl: result.release.html_url
337
+ })
338
+ );
339
+ } else if (result.updateAvailable) {
340
+ console.log(`Update available: ${result.current} \u2192 ${result.latest}`);
341
+ console.log(`Install method: ${result.installMethod}`);
342
+ console.log(`Release: ${result.release.html_url}`);
343
+ console.log(`
344
+ Run: gpc update`);
345
+ } else {
346
+ console.log(`Already on latest version: v${result.current}`);
347
+ }
348
+ return;
349
+ }
350
+ if (!result.updateAvailable && !opts.force) {
351
+ spinner.stop(`Already on latest version: v${result.current}`);
352
+ if (jsonMode) {
353
+ console.log(
354
+ JSON.stringify({
355
+ success: true,
356
+ current: result.current,
357
+ latest: result.latest,
358
+ updated: false
359
+ })
360
+ );
361
+ }
362
+ return;
363
+ }
364
+ spinner.update(
365
+ `Updating v${result.current} \u2192 v${result.latest} (${result.installMethod})...`
366
+ );
367
+ switch (result.installMethod) {
368
+ case "npm":
369
+ spinner.stop();
370
+ await updateViaNpm({ silent: jsonMode });
371
+ break;
372
+ case "homebrew":
373
+ spinner.stop();
374
+ await updateViaBrew({ silent: jsonMode });
375
+ break;
376
+ case "binary": {
377
+ const assetName = getPlatformAsset();
378
+ if (!assetName) {
379
+ spinner.fail();
380
+ console.error(
381
+ `Error: Unsupported platform: ${process.platform}/${process.arch}`
382
+ );
383
+ console.error(
384
+ `Download manually: ${result.release.html_url}`
385
+ );
386
+ process.exit(1);
387
+ }
388
+ const assetObj = result.release.assets.find((a) => a.name === assetName);
389
+ if (!assetObj) {
390
+ spinner.fail();
391
+ console.error(
392
+ `Error: No binary found for ${assetName} in release ${result.latestTag}`
393
+ );
394
+ console.error(`Check: ${result.release.html_url}`);
395
+ process.exit(1);
396
+ }
397
+ const sizeMB = (assetObj.size / (1024 * 1024)).toFixed(1);
398
+ spinner.stop();
399
+ const checksums = await fetchChecksums(result.release);
400
+ const expectedHash = checksums.get(assetName) ?? "";
401
+ const binaryPath = getCurrentBinaryPath();
402
+ if (jsonMode) {
403
+ await updateBinaryInPlace(assetObj.browser_download_url, expectedHash, binaryPath);
404
+ } else {
405
+ const label = `Downloading ${assetName} (${sizeMB} MB)`;
406
+ process.stdout.write(`${label}...
407
+ `);
408
+ let lastPct = -1;
409
+ await updateBinaryInPlace(assetObj.browser_download_url, expectedHash, binaryPath, {
410
+ onProgress(downloaded, total) {
411
+ if (total <= 0) return;
412
+ const pct = Math.min(100, Math.round(downloaded / total * 100));
413
+ if (pct === lastPct) return;
414
+ lastPct = pct;
415
+ const dlMB = (downloaded / (1024 * 1024)).toFixed(1);
416
+ process.stdout.write(
417
+ `\r${label} ${dlMB} / ${sizeMB} MB (${String(pct).padStart(3)}%) `
418
+ );
419
+ }
420
+ });
421
+ process.stdout.write("\n");
422
+ }
423
+ break;
424
+ }
425
+ case "unknown":
426
+ spinner.fail();
427
+ console.error("Error: Could not detect install method. Update manually:");
428
+ console.error(` npm: npm install -g @gpc-cli/cli@latest`);
429
+ console.error(` Homebrew: brew upgrade yasserstudio/tap/gpc`);
430
+ console.error(` Binary: https://github.com/yasserstudio/gpc/releases/latest`);
431
+ process.exit(1);
432
+ }
433
+ if (jsonMode) {
434
+ console.log(
435
+ JSON.stringify({
436
+ success: true,
437
+ previous: result.current,
438
+ current: result.latest,
439
+ method: result.installMethod
440
+ })
441
+ );
442
+ } else {
443
+ console.log(`
444
+ \u2714 Updated to v${result.latest}`);
445
+ }
446
+ });
447
+ }
448
+ export {
449
+ registerUpdateCommand
450
+ };
451
+ //# sourceMappingURL=update-GC2A2WVP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/updater.ts","../src/commands/update.ts"],"sourcesContent":["/**\n * Self-update logic for `gpc update`.\n *\n * All functions here are pure / testable — no Commander.js dependency.\n * The command layer in commands/update.ts handles output and flags.\n */\n\nimport { createWriteStream } from \"node:fs\";\nimport { rename, chmod, unlink, stat } from \"node:fs/promises\";\nimport { realpathSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { pipeline } from \"node:stream/promises\";\nimport { Readable, Transform } from \"node:stream\";\nimport { spawn } from \"node:child_process\";\nimport { isNewerVersion } from \"./update-check.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type InstallMethod = \"npm\" | \"homebrew\" | \"binary\" | \"unknown\";\n\nexport interface GithubAsset {\n name: string;\n browser_download_url: string;\n size: number;\n}\n\nexport interface GithubRelease {\n tag_name: string;\n html_url: string;\n assets: GithubAsset[];\n}\n\nexport interface UpdateCheckResult {\n current: string;\n latest: string;\n latestTag: string;\n updateAvailable: boolean;\n installMethod: InstallMethod;\n release: GithubRelease;\n}\n\nconst GITHUB_API_URL = \"https://api.github.com/repos/yasserstudio/gpc/releases/latest\";\nconst GITHUB_TIMEOUT_MS = 10_000;\nconst DOWNLOAD_TIMEOUT_MS = 120_000;\n\n// ---------------------------------------------------------------------------\n// Install method detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect how gpc was installed.\n *\n * Priority:\n * 1. __GPC_BINARY env var (injected by esbuild at compile time) → \"binary\"\n * 2. npm_config_prefix env var → \"npm\"\n * 3. realpathSync(process.argv[1]) contains \"cellar\" or \"homebrew\" → \"homebrew\"\n * 4. realpathSync(process.argv[1]) contains \"node_modules\" → \"npm\"\n * 5. fallback → \"unknown\"\n *\n * Using realpathSync(process.argv[1]) instead of shelling to `which gpc`:\n * - No child process spawn\n * - Works on Windows without `where.exe`\n * - Resolves symlinks — critical for Intel Mac Homebrew where the bin path\n * is a symlink but the real path contains \"Cellar\"\n */\nexport function detectInstallMethod(): InstallMethod {\n // 1. Compiled binary — most reliable, baked in at esbuild build time\n if (process.env[\"__GPC_BINARY\"] === \"1\") return \"binary\";\n\n // 2. npm global install\n if (process.env[\"npm_config_prefix\"]) return \"npm\";\n\n // 3. Resolve symlinks and inspect path\n try {\n const resolved = realpathSync(process.argv[1] ?? \"\").toLowerCase();\n if (resolved.includes(\"cellar\") || resolved.includes(\"homebrew\")) return \"homebrew\";\n if (resolved.includes(\"node_modules\")) return \"npm\";\n } catch {\n // realpathSync can throw if the path doesn't exist — fall through to unknown\n }\n\n return \"unknown\";\n}\n\n// ---------------------------------------------------------------------------\n// Platform asset mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the GitHub release asset name for the current platform/arch,\n * matching the names produced by scripts/build-binary.ts TARGETS map.\n */\nexport function getPlatformAsset(): string | null {\n const arch = process.arch === \"arm64\" ? \"arm64\" : \"x64\";\n switch (process.platform) {\n case \"darwin\":\n return `gpc-darwin-${arch}`;\n case \"linux\":\n return `gpc-linux-${arch}`;\n case \"win32\":\n return \"gpc-windows-x64.exe\";\n default:\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Current binary path\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the path of the currently running gpc binary.\n * For compiled binaries, process.execPath IS the binary.\n * For npm/dev installs, process.argv[1] is the script entrypoint.\n */\nexport function getCurrentBinaryPath(): string {\n if (process.env[\"__GPC_BINARY\"] === \"1\") return process.execPath;\n return process.argv[1] ?? process.execPath;\n}\n\n// ---------------------------------------------------------------------------\n// GitHub Releases API\n// ---------------------------------------------------------------------------\n\nfunction githubHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n \"User-Agent\": \"gpc-cli\",\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n };\n // Support GPC_GITHUB_TOKEN for authenticated requests (avoids 60 req/hr limit\n // on shared CI runner IPs)\n if (process.env[\"GPC_GITHUB_TOKEN\"]) {\n headers[\"Authorization\"] = `Bearer ${process.env[\"GPC_GITHUB_TOKEN\"]}`;\n }\n return headers;\n}\n\nexport async function fetchLatestRelease(): Promise<GithubRelease> {\n let response: Response;\n try {\n response = await fetch(GITHUB_API_URL, {\n headers: githubHeaders(),\n signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(`Network error checking for updates: ${msg}`), {\n code: \"NETWORK_ERROR\",\n exitCode: 5,\n });\n }\n\n if (response.status === 429) {\n throw Object.assign(\n new Error(\n \"GitHub API rate limit exceeded. Set GPC_GITHUB_TOKEN to increase the limit.\",\n ),\n { code: \"UPDATE_RATE_LIMITED\", exitCode: 4 },\n );\n }\n\n if (!response.ok) {\n throw Object.assign(new Error(`GitHub API returned HTTP ${response.status}`), {\n code: \"UPDATE_API_ERROR\",\n exitCode: 4,\n });\n }\n\n return (await response.json()) as GithubRelease;\n}\n\n/**\n * Fetch and parse checksums.txt from the release assets.\n * Returns a Map of filename → lowercase sha256 hex.\n * Returns an empty Map if the asset is missing or the fetch fails.\n */\nexport async function fetchChecksums(release: GithubRelease): Promise<Map<string, string>> {\n const asset = release.assets.find((a) => a.name === \"checksums.txt\");\n if (!asset) return new Map();\n\n try {\n const response = await fetch(asset.browser_download_url, {\n headers: githubHeaders(),\n signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),\n });\n if (!response.ok) return new Map();\n\n const map = new Map<string, string>();\n for (const line of (await response.text()).split(\"\\n\")) {\n const parts = line.trim().split(/\\s+/);\n const hash = parts[0];\n const name = parts[1];\n if (hash && name) map.set(name, hash.toLowerCase());\n }\n return map;\n } catch {\n return new Map();\n }\n}\n\n// ---------------------------------------------------------------------------\n// High-level update check\n// ---------------------------------------------------------------------------\n\nexport async function checkForUpdate(currentVersion: string): Promise<UpdateCheckResult> {\n const release = await fetchLatestRelease();\n const latest = release.tag_name.replace(/^v/, \"\");\n return {\n current: currentVersion,\n latest,\n latestTag: release.tag_name,\n updateAvailable: isNewerVersion(currentVersion, latest),\n installMethod: detectInstallMethod(),\n release,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Update execution paths\n// ---------------------------------------------------------------------------\n\nexport async function updateViaNpm(options: { silent?: boolean } = {}): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(\"npm\", [\"install\", \"-g\", \"@gpc-cli/cli@latest\"], {\n // In silent (JSON) mode, redirect npm's stdout to stderr so it doesn't\n // pollute the machine-readable JSON that gpc writes to stdout.\n stdio: options.silent ? [\"inherit\", process.stderr, process.stderr] : \"inherit\",\n shell: false,\n });\n proc.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(\n Object.assign(new Error(`npm exited with code ${code}`), {\n code: \"UPDATE_NPM_FAILED\",\n exitCode: 1,\n suggestion: \"Run manually: npm install -g @gpc-cli/cli@latest\",\n }),\n );\n }\n });\n proc.on(\"error\", (err) => {\n reject(\n Object.assign(new Error(`Failed to run npm: ${err.message}`), {\n code: \"UPDATE_NPM_SPAWN_FAILED\",\n exitCode: 1,\n suggestion: \"Ensure npm is in your PATH\",\n }),\n );\n });\n });\n}\n\nexport async function updateViaBrew(options: { silent?: boolean } = {}): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(\"brew\", [\"upgrade\", \"yasserstudio/tap/gpc\"], {\n // In silent (JSON) mode, redirect brew's stdout to stderr so it doesn't\n // pollute the machine-readable JSON that gpc writes to stdout.\n stdio: options.silent ? [\"inherit\", process.stderr, process.stderr] : \"inherit\",\n shell: false,\n });\n proc.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(\n Object.assign(new Error(`brew exited with code ${code}`), {\n code: \"UPDATE_BREW_FAILED\",\n exitCode: 1,\n suggestion: \"Run manually: brew upgrade yasserstudio/tap/gpc\",\n }),\n );\n }\n });\n proc.on(\"error\", (err) => {\n reject(\n Object.assign(new Error(`Failed to run brew: ${err.message}`), {\n code: \"UPDATE_BREW_SPAWN_FAILED\",\n exitCode: 1,\n suggestion: \"Ensure Homebrew is installed: https://brew.sh\",\n }),\n );\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// Binary in-place replace\n// ---------------------------------------------------------------------------\n\nfunction isPermissionError(err: unknown): boolean {\n return (\n err instanceof Error &&\n \"code\" in err &&\n (err.code === \"EACCES\" || err.code === \"EPERM\")\n );\n}\n\nasync function sha256File(filePath: string): Promise<string> {\n const hash = createHash(\"sha256\");\n const { size } = await stat(filePath);\n if (size === 0) return hash.digest(\"hex\");\n\n // Read in 64 KB chunks\n const { createReadStream } = await import(\"node:fs\");\n const stream = createReadStream(filePath);\n await pipeline(stream, async function* (source) {\n for await (const chunk of source) {\n hash.update(chunk as Buffer);\n }\n });\n return hash.digest(\"hex\");\n}\n\n/**\n * Download a new binary and atomically replace the current one.\n *\n * macOS/Linux: rename(tmp, current) — safe because open files can be replaced\n * Windows: rename(current, .old) then rename(tmp, current) — avoids EBUSY\n * because Windows locks running executables\n */\nexport async function updateBinaryInPlace(\n assetUrl: string,\n expectedSha256: string,\n currentBinaryPath: string,\n options: { onProgress?: (downloaded: number, total: number) => void } = {},\n): Promise<void> {\n const dir = dirname(currentBinaryPath);\n const tmpPath = join(dir, `.gpc-update-${process.pid}.tmp`);\n const oldPath = join(dir, `.gpc-old-${process.pid}`);\n\n try {\n // 1. Download\n let response: Response;\n try {\n response = await fetch(assetUrl, {\n signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS),\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw Object.assign(new Error(`Download failed: ${msg}`), {\n code: \"UPDATE_DOWNLOAD_FAILED\",\n exitCode: 5,\n });\n }\n\n if (!response.ok) {\n throw Object.assign(new Error(`Download failed: HTTP ${response.status}`), {\n code: \"UPDATE_DOWNLOAD_FAILED\",\n exitCode: 4,\n });\n }\n if (!response.body) {\n throw Object.assign(new Error(\"Empty response body\"), {\n code: \"UPDATE_DOWNLOAD_FAILED\",\n exitCode: 4,\n });\n }\n\n const contentLength = response.headers.get(\"content-length\");\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n let downloaded = 0;\n\n const dest = createWriteStream(tmpPath);\n const { onProgress } = options;\n\n if (onProgress) {\n const tracker = new Transform({\n transform(chunk: Buffer, _enc, cb) {\n downloaded += chunk.length;\n onProgress(downloaded, total);\n cb(null, chunk);\n },\n });\n await pipeline(\n Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]),\n tracker,\n dest,\n );\n } else {\n await pipeline(Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]), dest);\n }\n\n // 2. Verify checksum (skip if no checksum available)\n if (expectedSha256) {\n const actual = await sha256File(tmpPath);\n if (actual !== expectedSha256.toLowerCase()) {\n throw Object.assign(\n new Error(`Checksum mismatch — expected ${expectedSha256}, got ${actual}`),\n {\n code: \"UPDATE_CHECKSUM_MISMATCH\",\n exitCode: 1,\n suggestion: \"The download may be corrupt. Try again.\",\n },\n );\n }\n }\n\n // 3. Set executable bit (no-op on Windows)\n if (process.platform !== \"win32\") {\n await chmod(tmpPath, 0o755);\n }\n\n // 4. Atomic replace\n if (process.platform === \"win32\") {\n // Windows locks running executables, so we rename the current binary\n // out of the way first, then move the new one into place\n await rename(currentBinaryPath, oldPath);\n try {\n await rename(tmpPath, currentBinaryPath);\n } catch (renameErr) {\n // Roll back — restore original binary\n await rename(oldPath, currentBinaryPath).catch(() => {});\n throw renameErr;\n }\n // Delete the old binary in the background (best-effort)\n unlink(oldPath).catch(() => {});\n } else {\n await rename(tmpPath, currentBinaryPath);\n }\n } catch (err) {\n // Clean up temp file on any error\n await unlink(tmpPath).catch(() => {});\n\n if (isPermissionError(err)) {\n throw Object.assign(\n new Error(`Permission denied replacing ${currentBinaryPath}`),\n {\n code: \"UPDATE_PERMISSION_DENIED\",\n exitCode: 1,\n suggestion: `Run with elevated permissions: sudo gpc update`,\n },\n );\n }\n throw err;\n }\n}\n","import type { Command } from \"commander\";\nimport {\n checkForUpdate,\n fetchChecksums,\n updateViaNpm,\n updateViaBrew,\n updateBinaryInPlace,\n getPlatformAsset,\n getCurrentBinaryPath,\n} from \"../updater.js\";\nimport { createSpinner } from \"@gpc-cli/core\";\n\nexport function registerUpdateCommand(program: Command): void {\n program\n .command(\"update\")\n .description(\"Update gpc to the latest version\")\n .option(\"--check\", \"Check for updates without installing (exits 0 always)\")\n .option(\"--force\", \"Update even if already on the latest version\")\n .action(async (opts: { check?: boolean; force?: boolean }, cmd) => {\n const parentOpts = (cmd.parent?.opts() ?? {}) as Record<string, unknown>;\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n const currentVersion = process.env[\"__GPC_VERSION\"] ?? \"0.0.0\";\n\n // Dev build guard\n if (currentVersion === \"0.0.0\") {\n if (jsonMode) {\n console.log(\n JSON.stringify({\n success: false,\n reason: \"Cannot update a development build\",\n current: currentVersion,\n }),\n );\n } else {\n console.log(\"Cannot update a development build (version: 0.0.0).\");\n }\n return;\n }\n\n const spinner = createSpinner(\"Checking for updates...\");\n spinner.start();\n\n let result;\n try {\n result = await checkForUpdate(currentVersion);\n } catch (err) {\n spinner.fail(\"Failed to check for updates\");\n throw err;\n }\n\n // --check mode: always exit 0, communicate via output\n if (opts.check) {\n spinner.stop();\n if (jsonMode) {\n console.log(\n JSON.stringify({\n current: result.current,\n latest: result.latest,\n updateAvailable: result.updateAvailable,\n installMethod: result.installMethod,\n releaseUrl: result.release.html_url,\n }),\n );\n } else if (result.updateAvailable) {\n console.log(`Update available: ${result.current} → ${result.latest}`);\n console.log(`Install method: ${result.installMethod}`);\n console.log(`Release: ${result.release.html_url}`);\n console.log(`\\nRun: gpc update`);\n } else {\n console.log(`Already on latest version: v${result.current}`);\n }\n return;\n }\n\n // Already up to date\n if (!result.updateAvailable && !opts.force) {\n spinner.stop(`Already on latest version: v${result.current}`);\n if (jsonMode) {\n console.log(\n JSON.stringify({\n success: true,\n current: result.current,\n latest: result.latest,\n updated: false,\n }),\n );\n }\n return;\n }\n\n spinner.update(\n `Updating v${result.current} → v${result.latest} (${result.installMethod})...`,\n );\n\n switch (result.installMethod) {\n case \"npm\":\n spinner.stop();\n await updateViaNpm({ silent: jsonMode });\n break;\n\n case \"homebrew\":\n spinner.stop();\n await updateViaBrew({ silent: jsonMode });\n break;\n\n case \"binary\": {\n const assetName = getPlatformAsset();\n if (!assetName) {\n spinner.fail();\n console.error(\n `Error: Unsupported platform: ${process.platform}/${process.arch}`,\n );\n console.error(\n `Download manually: ${result.release.html_url}`,\n );\n process.exit(1);\n }\n\n const assetObj = result.release.assets.find((a) => a.name === assetName);\n if (!assetObj) {\n spinner.fail();\n console.error(\n `Error: No binary found for ${assetName} in release ${result.latestTag}`,\n );\n console.error(`Check: ${result.release.html_url}`);\n process.exit(1);\n }\n\n const sizeMB = (assetObj.size / (1024 * 1024)).toFixed(1);\n spinner.stop();\n\n const checksums = await fetchChecksums(result.release);\n const expectedHash = checksums.get(assetName) ?? \"\";\n const binaryPath = getCurrentBinaryPath();\n\n if (jsonMode) {\n await updateBinaryInPlace(assetObj.browser_download_url, expectedHash, binaryPath);\n } else {\n // Show live download progress on a single overwriting line\n const label = `Downloading ${assetName} (${sizeMB} MB)`;\n process.stdout.write(`${label}...\\n`);\n let lastPct = -1;\n await updateBinaryInPlace(assetObj.browser_download_url, expectedHash, binaryPath, {\n onProgress(downloaded, total) {\n if (total <= 0) return;\n const pct = Math.min(100, Math.round((downloaded / total) * 100));\n if (pct === lastPct) return; // avoid redundant writes\n lastPct = pct;\n const dlMB = (downloaded / (1024 * 1024)).toFixed(1);\n process.stdout.write(\n `\\r${label} ${dlMB} / ${sizeMB} MB (${String(pct).padStart(3)}%) `,\n );\n },\n });\n process.stdout.write(\"\\n\");\n }\n break;\n }\n\n case \"unknown\":\n spinner.fail();\n console.error(\"Error: Could not detect install method. Update manually:\");\n console.error(` npm: npm install -g @gpc-cli/cli@latest`);\n console.error(` Homebrew: brew upgrade yasserstudio/tap/gpc`);\n console.error(` Binary: https://github.com/yasserstudio/gpc/releases/latest`);\n process.exit(1);\n }\n\n if (jsonMode) {\n console.log(\n JSON.stringify({\n success: true,\n previous: result.current,\n current: result.latest,\n method: result.installMethod,\n }),\n );\n } else {\n console.log(`\\n✔ Updated to v${result.latest}`);\n }\n });\n}\n"],"mappings":"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","names":[]}
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpc-cli/cli",
3
- "version": "0.9.28",
3
+ "version": "0.9.31",
4
4
  "description": "The complete Google Play CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,13 +17,22 @@
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "lint": "eslint src/",
26
+ "typecheck": "tsc --noEmit",
27
+ "clean": "rm -rf dist"
28
+ },
20
29
  "dependencies": {
21
- "commander": "^14.0.3",
22
- "@gpc-cli/api": "1.0.17",
23
- "@gpc-cli/auth": "^0.9.9",
24
- "@gpc-cli/core": "0.9.25",
25
- "@gpc-cli/plugin-sdk": "0.9.6",
26
- "@gpc-cli/config": "0.9.8"
30
+ "@gpc-cli/api": "workspace:*",
31
+ "@gpc-cli/auth": "workspace:^",
32
+ "@gpc-cli/config": "workspace:*",
33
+ "@gpc-cli/core": "workspace:*",
34
+ "@gpc-cli/plugin-sdk": "workspace:*",
35
+ "commander": "^14.0.3"
27
36
  },
28
37
  "keywords": [
29
38
  "google-play",
@@ -41,14 +50,5 @@
41
50
  },
42
51
  "devDependencies": {
43
52
  "@types/node": "^25.3.5"
44
- },
45
- "scripts": {
46
- "build": "tsup",
47
- "dev": "tsup --watch",
48
- "test": "vitest run",
49
- "test:watch": "vitest",
50
- "lint": "eslint src/",
51
- "typecheck": "tsc --noEmit",
52
- "clean": "rm -rf dist"
53
53
  }
54
- }
54
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 GPC Contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/audit.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { getConfigDir } from \"@gpc-cli/config\";\nimport {\n initAudit,\n listAuditEvents,\n searchAuditEvents,\n clearAuditLog,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nexport function registerAuditCommands(program: Command): void {\n const audit = program.command(\"audit\").description(\"Query and manage audit logs\");\n\n audit\n .command(\"list\")\n .description(\"List recent audit events\")\n .option(\"--limit <n>\", \"Maximum events to show\", parseInt, 50)\n .option(\"--since <date>\", \"Show events since date (ISO 8601)\")\n .option(\"--command <name>\", \"Filter by command name\")\n .action(async (options) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n initAudit(getConfigDir());\n\n try {\n const events = await listAuditEvents({\n limit: options.limit,\n since: options.since,\n command: options.command,\n });\n if (events.length === 0 && format !== \"json\") {\n console.log(\"No audit events found.\");\n return;\n }\n if (format !== \"json\") {\n const rows = events.map((e) => ({\n timestamp: e.timestamp,\n command: e.command,\n app: e.app || \"-\",\n success: e.success !== undefined ? String(e.success) : \"-\",\n durationMs: e.durationMs ?? \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(events, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n audit\n .command(\"search <query>\")\n .description(\"Search audit events by keyword\")\n .action(async (query: string) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n initAudit(getConfigDir());\n\n try {\n const events = await searchAuditEvents(query);\n if (events.length === 0 && format !== \"json\") {\n console.log(`No audit events matching \"${query}\".`);\n return;\n }\n if (format !== \"json\") {\n const rows = events.map((e) => ({\n timestamp: e.timestamp,\n command: e.command,\n app: e.app || \"-\",\n success: e.success !== undefined ? String(e.success) : \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(events, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n audit\n .command(\"clear\")\n .description(\"Clear audit log entries\")\n .option(\"--before <date>\", \"Clear entries before date (ISO 8601)\")\n .option(\"--dry-run\", \"Preview what would be cleared\")\n .action(async (options, cmd: Command) => {\n const dryRun = options.dryRun || isDryRun(cmd);\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n initAudit(getConfigDir());\n\n if (!dryRun && !options.before) {\n await requireConfirm(\"Clear all audit log entries?\", program);\n }\n\n try {\n const result = await clearAuditLog({\n before: options.before,\n dryRun,\n });\n if (dryRun) {\n console.log(`[dry-run] Would delete ${result.deleted} entries, ${result.remaining} would remain.`);\n } else {\n console.log(`Deleted ${result.deleted} entries. ${result.remaining} remaining.`);\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":[]}