@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
File without changes
@@ -19,6 +19,22 @@ import {
19
19
  clearAuditLog,
20
20
  formatOutput
21
21
  } from "@gpc-cli/core";
22
+ function formatAuditTimestamp(iso) {
23
+ const date = new Date(iso);
24
+ const now = /* @__PURE__ */ new Date();
25
+ const diffMs = now.getTime() - date.getTime();
26
+ const diffMin = Math.floor(diffMs / 6e4);
27
+ if (diffMin < 60) return diffMin < 1 ? "just now" : `${diffMin} min ago`;
28
+ const diffHr = Math.floor(diffMin / 60);
29
+ if (diffHr < 24) return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}`;
30
+ const diffDays = Math.floor(diffHr / 24);
31
+ if (diffDays < 7) {
32
+ const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
33
+ return `${days[date.getDay()]} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
34
+ }
35
+ const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
36
+ return `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
37
+ }
22
38
  function registerAuditCommands(program) {
23
39
  const audit = program.command("audit").description("Query and manage audit logs");
24
40
  audit.command("list").description("List recent audit events").option("--limit <n>", "Maximum events to show", parseInt, 50).option("--since <date>", "Show events since date (ISO 8601)").option("--command <name>", "Filter by command name").action(async (options) => {
@@ -37,7 +53,7 @@ function registerAuditCommands(program) {
37
53
  }
38
54
  if (format !== "json") {
39
55
  const rows = events.map((e) => ({
40
- timestamp: e.timestamp,
56
+ timestamp: formatAuditTimestamp(e.timestamp),
41
57
  command: e.command,
42
58
  app: e.app || "-",
43
59
  success: e.success !== void 0 ? String(e.success) : "-",
@@ -64,7 +80,7 @@ function registerAuditCommands(program) {
64
80
  }
65
81
  if (format !== "json") {
66
82
  const rows = events.map((e) => ({
67
- timestamp: e.timestamp,
83
+ timestamp: formatAuditTimestamp(e.timestamp),
68
84
  command: e.command,
69
85
  app: e.app || "-",
70
86
  success: e.success !== void 0 ? String(e.success) : "-"
@@ -105,4 +121,4 @@ function registerAuditCommands(program) {
105
121
  export {
106
122
  registerAuditCommands
107
123
  };
108
- //# sourceMappingURL=audit-QP75CEGB.js.map
124
+ //# sourceMappingURL=audit-A4BP27DN.js.map
@@ -0,0 +1 @@
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\nfunction formatAuditTimestamp(iso: string): string {\n const date = new Date(iso);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 60) return diffMin < 1 ? \"just now\" : `${diffMin} min ago`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}:${String(date.getSeconds()).padStart(2, \"0\")}`;\n const diffDays = Math.floor(diffHr / 24);\n if (diffDays < 7) {\n const days = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n return `${days[date.getDay()]} ${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}`;\n }\n const months = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n return `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;\n}\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: formatAuditTimestamp(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: formatAuditTimestamp(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":[]}
File without changes
package/dist/bin.js CHANGED
@@ -3,7 +3,11 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-PREKF2AM.js";
6
+ } from "./chunk-5VVYPCDE.js";
7
+ import {
8
+ checkForUpdate,
9
+ formatUpdateNotification
10
+ } from "./chunk-4O4D5SGL.js";
7
11
 
8
12
  // src/networking.ts
9
13
  async function setupNetworking() {
@@ -26,90 +30,11 @@ async function setupNetworking() {
26
30
  // src/bin.ts
27
31
  import { initAudit, sendWebhook } from "@gpc-cli/core";
28
32
  import { getConfigDir, loadConfig } from "@gpc-cli/config";
29
-
30
- // src/update-check.ts
31
- import { join } from "path";
32
- import { readFile, writeFile, mkdir } from "fs/promises";
33
- import { getCacheDir } from "@gpc-cli/config";
34
- var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
35
- var FETCH_TIMEOUT_MS = 3e3;
36
- var REGISTRY_URL = "https://registry.npmjs.org/@gpc-cli/cli/latest";
37
- function getCacheFilePath() {
38
- return join(getCacheDir(), "update-check.json");
39
- }
40
- function isNewerVersion(current, latest) {
41
- const a = current.split(".").map(Number);
42
- const b = latest.split(".").map(Number);
43
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
44
- const av = a[i] ?? 0;
45
- const bv = b[i] ?? 0;
46
- if (bv > av) return true;
47
- if (bv < av) return false;
48
- }
49
- return false;
50
- }
51
- async function readCache() {
52
- try {
53
- const raw = await readFile(getCacheFilePath(), "utf-8");
54
- const data = JSON.parse(raw);
55
- if (typeof data.latest === "string" && typeof data.checkedAt === "number") {
56
- return data;
57
- }
58
- return null;
59
- } catch {
60
- return null;
61
- }
62
- }
63
- function writeCache(data) {
64
- const filePath = getCacheFilePath();
65
- const dir = join(filePath, "..");
66
- mkdir(dir, { recursive: true }).then(() => writeFile(filePath, JSON.stringify(data), "utf-8")).catch(() => {
67
- });
68
- }
69
- async function fetchLatestVersion() {
70
- try {
71
- const controller = new AbortController();
72
- const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
73
- const response = await fetch(REGISTRY_URL, { signal: controller.signal });
74
- clearTimeout(timeout);
75
- if (!response.ok) return null;
76
- const body = await response.json();
77
- if (typeof body.version !== "string") return null;
78
- return body.version;
79
- } catch {
80
- return null;
81
- }
82
- }
83
- async function checkForUpdate(currentVersion2) {
84
- if (process.env["GPC_NO_UPDATE_CHECK"] === "1") return null;
85
- if (process.env["CI"]) return null;
86
- if (!process.stdout.isTTY) return null;
87
- const cache = await readCache();
88
- if (cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
89
- return {
90
- current: currentVersion2,
91
- latest: cache.latest,
92
- updateAvailable: isNewerVersion(currentVersion2, cache.latest)
93
- };
94
- }
95
- const latest = await fetchLatestVersion();
96
- if (!latest) return null;
97
- writeCache({ latest, checkedAt: Date.now() });
98
- return {
99
- current: currentVersion2,
100
- latest,
101
- updateAvailable: isNewerVersion(currentVersion2, latest)
102
- };
103
- }
104
- function formatUpdateNotification(result) {
105
- return `Update available: ${result.current} \u2192 ${result.latest} \u2014 npm install -g @gpc-cli/cli`;
106
- }
107
-
108
- // src/bin.ts
109
33
  await setupNetworking();
110
34
  initAudit(getConfigDir());
111
35
  var currentVersion = process.env["__GPC_VERSION"] || "0.0.0";
112
- var updateCheckPromise = checkForUpdate(currentVersion);
36
+ var isUpdateCommand = process.argv[2] === "update";
37
+ var updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);
113
38
  if (process.argv.includes("--ci")) {
114
39
  process.env["CI"] = "1";
115
40
  if (!process.argv.some((a) => a.startsWith("--output") || a.startsWith("-o"))) {
@@ -163,7 +88,7 @@ try {
163
88
  updateCheckPromise,
164
89
  new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
165
90
  ]);
166
- if (result && result.updateAvailable && process.stdout.isTTY && !process.argv.includes("--json") && program.opts()["output"] !== "json") {
91
+ if (result && result.updateAvailable && !isUpdateCommand && process.stdout.isTTY && !process.argv.includes("--json") && program.opts()["output"] !== "json") {
167
92
  process.stderr.write(`
168
93
  ${formatUpdateNotification(result)}
169
94
  `);
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/networking.ts","../src/bin.ts","../src/update-check.ts"],"sourcesContent":["/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n","import { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv.slice(2).filter((a) => !a.startsWith(\"--notify\")).join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n","import { join } from \"node:path\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { getCacheDir } from \"@gpc-cli/config\";\n\nexport interface UpdateCheckResult {\n current: string;\n latest: string;\n updateAvailable: boolean;\n}\n\ninterface CacheData {\n latest: string;\n checkedAt: number;\n}\n\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours\nconst FETCH_TIMEOUT_MS = 3000;\nconst REGISTRY_URL = \"https://registry.npmjs.org/@gpc-cli/cli/latest\";\n\nfunction getCacheFilePath(): string {\n return join(getCacheDir(), \"update-check.json\");\n}\n\n/**\n * Compare two semver strings numerically.\n * Returns true if `b` is newer than `a`.\n */\nexport function isNewerVersion(current: string, latest: string): boolean {\n const a = current.split(\".\").map(Number);\n const b = latest.split(\".\").map(Number);\n for (let i = 0; i < Math.max(a.length, b.length); i++) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n if (bv > av) return true;\n if (bv < av) return false;\n }\n return false;\n}\n\nasync function readCache(): Promise<CacheData | null> {\n try {\n const raw = await readFile(getCacheFilePath(), \"utf-8\");\n const data = JSON.parse(raw) as CacheData;\n if (typeof data.latest === \"string\" && typeof data.checkedAt === \"number\") {\n return data;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(data: CacheData): void {\n const filePath = getCacheFilePath();\n const dir = join(filePath, \"..\");\n // Fire-and-forget: ignore write errors\n mkdir(dir, { recursive: true })\n .then(() => writeFile(filePath, JSON.stringify(data), \"utf-8\"))\n .catch(() => {});\n}\n\nasync function fetchLatestVersion(): Promise<string | null> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n const response = await fetch(REGISTRY_URL, { signal: controller.signal });\n clearTimeout(timeout);\n\n if (!response.ok) return null;\n\n const body = (await response.json()) as { version?: string };\n if (typeof body.version !== \"string\") return null;\n\n return body.version;\n } catch {\n return null;\n }\n}\n\n/**\n * Check for a newer version of @gpc-cli/cli on npm.\n * Returns null if the check is skipped or fails.\n */\nexport async function checkForUpdate(currentVersion: string): Promise<UpdateCheckResult | null> {\n // Skip in non-interactive or CI environments\n if (process.env[\"GPC_NO_UPDATE_CHECK\"] === \"1\") return null;\n if (process.env[\"CI\"]) return null;\n if (!process.stdout.isTTY) return null;\n\n // Check cache first\n const cache = await readCache();\n if (cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {\n return {\n current: currentVersion,\n latest: cache.latest,\n updateAvailable: isNewerVersion(currentVersion, cache.latest),\n };\n }\n\n // Fetch from registry\n const latest = await fetchLatestVersion();\n if (!latest) return null;\n\n // Write cache (fire-and-forget)\n writeCache({ latest, checkedAt: Date.now() });\n\n return {\n current: currentVersion,\n latest,\n updateAvailable: isNewerVersion(currentVersion, latest),\n };\n}\n\n/**\n * Format a user-facing update notification string.\n */\nexport function formatUpdateNotification(result: UpdateCheckResult): string {\n return `Update available: ${result.current} \\u2192 ${result.latest} \\u2014 npm install -g @gpc-cli/cli`;\n}\n"],"mappings":";;;;;;;;AAIA,eAAsB,kBAAiC;AAErD,QAAM,SAAS,QAAQ,IAAI,aAAa;AACxC,MAAI,UAAU,CAAC,QAAQ,IAAI,qBAAqB,GAAG;AACjD,YAAQ,IAAI,qBAAqB,IAAI;AAAA,EACvC;AAGA,MAAI,QAAQ,IAAI,cAAc,MAAM,IAAK;AAEzC,QAAM,WACJ,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,YAAY,KACxB,QAAQ,IAAI,YAAY;AAC1B,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,EAAE,YAAY,oBAAoB,IAAI,MAAM,OAAO,QAAQ;AACjE,0BAAoB,IAAI,WAAW,QAAQ,CAAC;AAAA,IAC9C,QAAQ;AACN,cAAQ,MAAM,2EAA2E;AAAA,IAC3F;AAAA,EACF;AACF;;;ACxBA,SAAS,WAAW,mBAAmB;AAEvC,SAAS,cAAc,kBAAkB;;;ACNzC,SAAS,YAAY;AACrB,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,mBAAmB;AAa5B,IAAM,eAAe,KAAK,KAAK,KAAK;AACpC,IAAM,mBAAmB;AACzB,IAAM,eAAe;AAErB,SAAS,mBAA2B;AAClC,SAAO,KAAK,YAAY,GAAG,mBAAmB;AAChD;AAMO,SAAS,eAAe,SAAiB,QAAyB;AACvE,QAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AACvC,QAAM,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI,MAAM;AACtC,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK;AACrD,UAAM,KAAK,EAAE,CAAC,KAAK;AACnB,UAAM,KAAK,EAAE,CAAC,KAAK;AACnB,QAAI,KAAK,GAAI,QAAO;AACpB,QAAI,KAAK,GAAI,QAAO;AAAA,EACtB;AACA,SAAO;AACT;AAEA,eAAe,YAAuC;AACpD,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,iBAAiB,GAAG,OAAO;AACtD,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAI,OAAO,KAAK,WAAW,YAAY,OAAO,KAAK,cAAc,UAAU;AACzE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,MAAuB;AACzC,QAAM,WAAW,iBAAiB;AAClC,QAAM,MAAM,KAAK,UAAU,IAAI;AAE/B,QAAM,KAAK,EAAE,WAAW,KAAK,CAAC,EAC3B,KAAK,MAAM,UAAU,UAAU,KAAK,UAAU,IAAI,GAAG,OAAO,CAAC,EAC7D,MAAM,MAAM;AAAA,EAAC,CAAC;AACnB;AAEA,eAAe,qBAA6C;AAC1D,MAAI;AACF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,gBAAgB;AAErE,UAAM,WAAW,MAAM,MAAM,cAAc,EAAE,QAAQ,WAAW,OAAO,CAAC;AACxE,iBAAa,OAAO;AAEpB,QAAI,CAAC,SAAS,GAAI,QAAO;AAEzB,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,OAAO,KAAK,YAAY,SAAU,QAAO;AAE7C,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,eAAeA,iBAA2D;AAE9F,MAAI,QAAQ,IAAI,qBAAqB,MAAM,IAAK,QAAO;AACvD,MAAI,QAAQ,IAAI,IAAI,EAAG,QAAO;AAC9B,MAAI,CAAC,QAAQ,OAAO,MAAO,QAAO;AAGlC,QAAM,QAAQ,MAAM,UAAU;AAC9B,MAAI,SAAS,KAAK,IAAI,IAAI,MAAM,YAAY,cAAc;AACxD,WAAO;AAAA,MACL,SAASA;AAAA,MACT,QAAQ,MAAM;AAAA,MACd,iBAAiB,eAAeA,iBAAgB,MAAM,MAAM;AAAA,IAC9D;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,mBAAmB;AACxC,MAAI,CAAC,OAAQ,QAAO;AAGpB,aAAW,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE,CAAC;AAE5C,SAAO;AAAA,IACL,SAASA;AAAA,IACT;AAAA,IACA,iBAAiB,eAAeA,iBAAgB,MAAM;AAAA,EACxD;AACF;AAKO,SAAS,yBAAyB,QAAmC;AAC1E,SAAO,qBAAqB,OAAO,OAAO,WAAW,OAAO,MAAM;AACpE;;;AD9GA,MAAM,gBAAgB;AACtB,UAAU,aAAa,CAAC;AAExB,IAAM,iBAAiB,QAAQ,IAAI,eAAe,KAAK;AAGvD,IAAM,qBAAqB,eAAe,cAAc;AAGxD,IAAI,QAAQ,KAAK,SAAS,MAAM,GAAG;AACjC,UAAQ,IAAI,IAAI,IAAI;AAEpB,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,kBAAkB,GAAG;AAC9C,YAAQ,KAAK,KAAK,kBAAkB;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,YAAY,GAAG;AACxC,YAAQ,KAAK,KAAK,YAAY;AAAA,EAChC;AACF;AACA,IAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,KAAK,SAAS,IAAI,GAAG;AAClE,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACF;AAEA,IAAM,gBAAgB,MAAM,YAAY;AACxC,IAAM,UAAU,MAAM,cAAc,aAAa;AAEjD,IAAM,YAAY,KAAK,IAAI;AAC3B,IAAI,iBAAiB;AACrB,IAAI;AAEJ,MAAM,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,UAAmB;AAC/D,mBAAiB;AACjB,iBAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,QAAM,WAAW,eAAe,KAAK;AACrC,UAAQ,KAAK,QAAQ;AACvB,CAAC;AAGD,IAAM,YAAY,QAAQ,KAAK,EAAE,QAAQ;AACzC,IAAI,cAAc,UAAa,cAAc,OAAO;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,WAAW;AAChC,QAAI,OAAO,UAAU;AACnB,YAAM,cAAc,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,UAAU,CAAC,EAAE,KAAK,GAAG;AAC3F,YAAM,UAA0B;AAAA,QAC9B,SAAS,eAAe;AAAA,QACxB,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,KAAK,QAAQ,KAAK,EAAE,KAAK;AAAA,QACzB,OAAO;AAAA,MACT;AAEA,YAAM,SAAS,OAAO,cAAc,WAAW,YAAY;AAE3D,kBAAY,OAAO,UAAU,SAAS,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC9D;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAGA,IAAI;AACF,QAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,IAChC;AAAA,IACA,IAAI,QAAc,CAAC,YAAY,WAAW,MAAM,QAAQ,IAAI,GAAG,GAAI,CAAC;AAAA,EACtE,CAAC;AAED,MACE,UACA,OAAO,mBACP,QAAQ,OAAO,SACf,CAAC,QAAQ,KAAK,SAAS,QAAQ,KAC/B,QAAQ,KAAK,EAAE,QAAQ,MAAM,QAC7B;AACA,YAAQ,OAAO,MAAM;AAAA,EAAK,yBAAyB,MAAM,CAAC;AAAA,CAAI;AAAA,EAChE;AACF,QAAQ;AAER;","names":["currentVersion"]}
1
+ {"version":3,"sources":["../src/networking.ts","../src/bin.ts"],"sourcesContent":["/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n","import { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Skip passive update check when the user is explicitly running `gpc update` —\n// that command does its own check against the GitHub Releases API.\nconst isUpdateCommand = process.argv[2] === \"update\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv.slice(2).filter((a) => !a.startsWith(\"--notify\")).join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\n// isUpdateCommand is declared above — update check was skipped for this command\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n !isUpdateCommand &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n"],"mappings":"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","names":[]}
File without changes
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/update-check.ts
4
+ import { join } from "path";
5
+ import { readFile, writeFile, mkdir } from "fs/promises";
6
+ import { getCacheDir } from "@gpc-cli/config";
7
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
8
+ var FETCH_TIMEOUT_MS = 3e3;
9
+ var REGISTRY_URL = "https://registry.npmjs.org/@gpc-cli/cli/latest";
10
+ function getCacheFilePath() {
11
+ return join(getCacheDir(), "update-check.json");
12
+ }
13
+ function isNewerVersion(current, latest) {
14
+ const a = current.split(".").map(Number);
15
+ const b = latest.split(".").map(Number);
16
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
17
+ const av = a[i] ?? 0;
18
+ const bv = b[i] ?? 0;
19
+ if (bv > av) return true;
20
+ if (bv < av) return false;
21
+ }
22
+ return false;
23
+ }
24
+ async function readCache() {
25
+ try {
26
+ const raw = await readFile(getCacheFilePath(), "utf-8");
27
+ const data = JSON.parse(raw);
28
+ if (typeof data.latest === "string" && typeof data.checkedAt === "number") {
29
+ return data;
30
+ }
31
+ return null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ function writeCache(data) {
37
+ const filePath = getCacheFilePath();
38
+ const dir = join(filePath, "..");
39
+ mkdir(dir, { recursive: true }).then(() => writeFile(filePath, JSON.stringify(data), "utf-8")).catch(() => {
40
+ });
41
+ }
42
+ async function fetchLatestVersion() {
43
+ try {
44
+ const controller = new AbortController();
45
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
46
+ const response = await fetch(REGISTRY_URL, { signal: controller.signal });
47
+ clearTimeout(timeout);
48
+ if (!response.ok) return null;
49
+ const body = await response.json();
50
+ if (typeof body.version !== "string") return null;
51
+ return body.version;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+ async function checkForUpdate(currentVersion) {
57
+ if (process.env["GPC_NO_UPDATE_CHECK"] === "1") return null;
58
+ if (process.env["CI"]) return null;
59
+ if (!process.stdout.isTTY) return null;
60
+ const cache = await readCache();
61
+ if (cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
62
+ return {
63
+ current: currentVersion,
64
+ latest: cache.latest,
65
+ updateAvailable: isNewerVersion(currentVersion, cache.latest)
66
+ };
67
+ }
68
+ const latest = await fetchLatestVersion();
69
+ if (!latest) return null;
70
+ writeCache({ latest, checkedAt: Date.now() });
71
+ return {
72
+ current: currentVersion,
73
+ latest,
74
+ updateAvailable: isNewerVersion(currentVersion, latest)
75
+ };
76
+ }
77
+ function formatUpdateNotification(result) {
78
+ return `Update available: ${result.current} \u2192 ${result.latest} \u2014 Run: gpc update`;
79
+ }
80
+
81
+ export {
82
+ isNewerVersion,
83
+ checkForUpdate,
84
+ formatUpdateNotification
85
+ };
86
+ //# sourceMappingURL=chunk-4O4D5SGL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/update-check.ts"],"sourcesContent":["import { join } from \"node:path\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { getCacheDir } from \"@gpc-cli/config\";\n\nexport interface UpdateCheckResult {\n current: string;\n latest: string;\n updateAvailable: boolean;\n}\n\ninterface CacheData {\n latest: string;\n checkedAt: number;\n}\n\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours\nconst FETCH_TIMEOUT_MS = 3000;\nconst REGISTRY_URL = \"https://registry.npmjs.org/@gpc-cli/cli/latest\";\n\nfunction getCacheFilePath(): string {\n return join(getCacheDir(), \"update-check.json\");\n}\n\n/**\n * Compare two semver strings numerically.\n * Returns true if `b` is newer than `a`.\n */\nexport function isNewerVersion(current: string, latest: string): boolean {\n const a = current.split(\".\").map(Number);\n const b = latest.split(\".\").map(Number);\n for (let i = 0; i < Math.max(a.length, b.length); i++) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n if (bv > av) return true;\n if (bv < av) return false;\n }\n return false;\n}\n\nasync function readCache(): Promise<CacheData | null> {\n try {\n const raw = await readFile(getCacheFilePath(), \"utf-8\");\n const data = JSON.parse(raw) as CacheData;\n if (typeof data.latest === \"string\" && typeof data.checkedAt === \"number\") {\n return data;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(data: CacheData): void {\n const filePath = getCacheFilePath();\n const dir = join(filePath, \"..\");\n // Fire-and-forget: ignore write errors\n mkdir(dir, { recursive: true })\n .then(() => writeFile(filePath, JSON.stringify(data), \"utf-8\"))\n .catch(() => {});\n}\n\nasync function fetchLatestVersion(): Promise<string | null> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n const response = await fetch(REGISTRY_URL, { signal: controller.signal });\n clearTimeout(timeout);\n\n if (!response.ok) return null;\n\n const body = (await response.json()) as { version?: string };\n if (typeof body.version !== \"string\") return null;\n\n return body.version;\n } catch {\n return null;\n }\n}\n\n/**\n * Check for a newer version of @gpc-cli/cli on npm.\n * Returns null if the check is skipped or fails.\n */\nexport async function checkForUpdate(currentVersion: string): Promise<UpdateCheckResult | null> {\n // Skip in non-interactive or CI environments\n if (process.env[\"GPC_NO_UPDATE_CHECK\"] === \"1\") return null;\n if (process.env[\"CI\"]) return null;\n if (!process.stdout.isTTY) return null;\n\n // Check cache first\n const cache = await readCache();\n if (cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {\n return {\n current: currentVersion,\n latest: cache.latest,\n updateAvailable: isNewerVersion(currentVersion, cache.latest),\n };\n }\n\n // Fetch from registry\n const latest = await fetchLatestVersion();\n if (!latest) return null;\n\n // Write cache (fire-and-forget)\n writeCache({ latest, checkedAt: Date.now() });\n\n return {\n current: currentVersion,\n latest,\n updateAvailable: isNewerVersion(currentVersion, latest),\n };\n}\n\n/**\n * Format a user-facing update notification string.\n */\nexport function formatUpdateNotification(result: UpdateCheckResult): string {\n return `Update available: ${result.current} \\u2192 ${result.latest} \\u2014 Run: gpc update`;\n}\n"],"mappings":";;;AAAA,SAAS,YAAY;AACrB,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,mBAAmB;AAa5B,IAAM,eAAe,KAAK,KAAK,KAAK;AACpC,IAAM,mBAAmB;AACzB,IAAM,eAAe;AAErB,SAAS,mBAA2B;AAClC,SAAO,KAAK,YAAY,GAAG,mBAAmB;AAChD;AAMO,SAAS,eAAe,SAAiB,QAAyB;AACvE,QAAM,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AACvC,QAAM,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI,MAAM;AACtC,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK;AACrD,UAAM,KAAK,EAAE,CAAC,KAAK;AACnB,UAAM,KAAK,EAAE,CAAC,KAAK;AACnB,QAAI,KAAK,GAAI,QAAO;AACpB,QAAI,KAAK,GAAI,QAAO;AAAA,EACtB;AACA,SAAO;AACT;AAEA,eAAe,YAAuC;AACpD,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,iBAAiB,GAAG,OAAO;AACtD,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAI,OAAO,KAAK,WAAW,YAAY,OAAO,KAAK,cAAc,UAAU;AACzE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,MAAuB;AACzC,QAAM,WAAW,iBAAiB;AAClC,QAAM,MAAM,KAAK,UAAU,IAAI;AAE/B,QAAM,KAAK,EAAE,WAAW,KAAK,CAAC,EAC3B,KAAK,MAAM,UAAU,UAAU,KAAK,UAAU,IAAI,GAAG,OAAO,CAAC,EAC7D,MAAM,MAAM;AAAA,EAAC,CAAC;AACnB;AAEA,eAAe,qBAA6C;AAC1D,MAAI;AACF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,gBAAgB;AAErE,UAAM,WAAW,MAAM,MAAM,cAAc,EAAE,QAAQ,WAAW,OAAO,CAAC;AACxE,iBAAa,OAAO;AAEpB,QAAI,CAAC,SAAS,GAAI,QAAO;AAEzB,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,OAAO,KAAK,YAAY,SAAU,QAAO;AAE7C,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,eAAe,gBAA2D;AAE9F,MAAI,QAAQ,IAAI,qBAAqB,MAAM,IAAK,QAAO;AACvD,MAAI,QAAQ,IAAI,IAAI,EAAG,QAAO;AAC9B,MAAI,CAAC,QAAQ,OAAO,MAAO,QAAO;AAGlC,QAAM,QAAQ,MAAM,UAAU;AAC9B,MAAI,SAAS,KAAK,IAAI,IAAI,MAAM,YAAY,cAAc;AACxD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,MAAM;AAAA,MACd,iBAAiB,eAAe,gBAAgB,MAAM,MAAM;AAAA,IAC9D;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,mBAAmB;AACxC,MAAI,CAAC,OAAQ,QAAO;AAGpB,aAAW,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE,CAAC;AAE5C,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,iBAAiB,eAAe,gBAAgB,MAAM;AAAA,EACxD;AACF;AAKO,SAAS,yBAAyB,QAAmC;AAC1E,SAAO,qBAAqB,OAAO,OAAO,WAAW,OAAO,MAAM;AACpE;","names":[]}
@@ -78,8 +78,11 @@ async function createProgram(pluginManager) {
78
78
  doctor: async () => {
79
79
  (await import("./doctor-UZB2UB5X.js")).registerDoctorCommand(program);
80
80
  },
81
+ update: async () => {
82
+ (await import("./update-GC2A2WVP.js")).registerUpdateCommand(program);
83
+ },
81
84
  docs: async () => {
82
- (await import("./docs-CVTWIVMS.js")).registerDocsCommand(program);
85
+ (await import("./docs-HIGQU4UL.js")).registerDocsCommand(program);
83
86
  },
84
87
  completion: async () => {
85
88
  (await import("./completion-C3PPWNS7.js")).registerCompletionCommand(program);
@@ -88,13 +91,13 @@ async function createProgram(pluginManager) {
88
91
  (await import("./apps-CVBURB5V.js")).registerAppsCommands(program);
89
92
  },
90
93
  releases: async () => {
91
- (await import("./releases-ZKPSAPB2.js")).registerReleasesCommands(program);
94
+ (await import("./releases-JMRKXEZU.js")).registerReleasesCommands(program);
92
95
  },
93
96
  tracks: async () => {
94
97
  (await import("./tracks-XFUN7JJX.js")).registerTracksCommands(program);
95
98
  },
96
99
  status: async () => {
97
- (await import("./status-NE3A2UHN.js")).registerStatusCommand(program);
100
+ (await import("./status-6Y2CHHVD.js")).registerStatusCommand(program);
98
101
  },
99
102
  listings: async () => {
100
103
  (await import("./listings-VSBHQY5H.js")).registerListingsCommands(program);
@@ -130,7 +133,7 @@ async function createProgram(pluginManager) {
130
133
  (await import("./validate-MHLPENCM.js")).registerValidateCommand(program);
131
134
  },
132
135
  publish: async () => {
133
- (await import("./publish-26ZPS7XX.js")).registerPublishCommand(program);
136
+ (await import("./publish-I6WJGR4S.js")).registerPublishCommand(program);
134
137
  },
135
138
  recovery: async () => {
136
139
  (await import("./recovery-S5UNJDBO.js")).registerRecoveryCommands(program);
@@ -162,7 +165,7 @@ async function createProgram(pluginManager) {
162
165
  (await import("./bundle-7IF5FIB4.js")).registerBundleCommands(program);
163
166
  },
164
167
  audit: async () => {
165
- (await import("./audit-QP75CEGB.js")).registerAuditCommands(program);
168
+ (await import("./audit-A4BP27DN.js")).registerAuditCommands(program);
166
169
  },
167
170
  migrate: async () => {
168
171
  (await import("./migrate-XQV7P4R7.js")).registerMigrateCommands(program);
@@ -308,4 +311,4 @@ export {
308
311
  createProgram,
309
312
  handleCliError
310
313
  };
311
- //# sourceMappingURL=chunk-PREKF2AM.js.map
314
+ //# sourceMappingURL=chunk-5VVYPCDE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins.ts","../src/program.ts","../src/error-handler.ts"],"sourcesContent":["import { PluginManager, discoverPlugins } from \"@gpc-cli/core\";\nimport type { Command } from \"commander\";\n\n/**\n * Load and initialize all plugins.\n * First-party plugins (@gpc-cli/*) are auto-trusted.\n * Third-party plugins require prior approval stored in config.\n * Plugin loading is disabled in standalone binary mode.\n */\nexport async function loadPlugins(): Promise<PluginManager> {\n const manager = new PluginManager();\n\n // Standalone binary cannot resolve external npm packages at runtime\n if (process.env[\"__GPC_BINARY\"] === \"1\") {\n return manager;\n }\n\n try {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const plugins = await discoverPlugins({ configPlugins: config.plugins });\n const approved = new Set(config.approvedPlugins ?? []);\n\n for (const plugin of plugins) {\n const isTrusted = plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && !approved.has(plugin.name)) {\n // Skip unapproved third-party plugins silently in non-interactive mode\n // In interactive mode, the user would run `gpc plugins approve <name>` first\n const isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n if (!isQuiet) {\n console.error(\n `Plugin \"${plugin.name}\" is not approved. Run: gpc plugins approve ${plugin.name}`,\n );\n }\n continue;\n }\n\n try {\n await manager.load(plugin);\n } catch {\n // Skip plugins that fail to load — don't block the CLI\n }\n }\n } catch {\n // Config loading failure shouldn't block plugin-free commands\n }\n\n return manager;\n}\n\n/**\n * Register plugin-defined commands with the Commander program.\n */\nexport function registerPluginCommands(program: Command, manager: PluginManager): void {\n for (const def of manager.getRegisteredCommands()) {\n const cmd = program.command(def.name).description(def.description);\n\n if (def.arguments) {\n for (const arg of def.arguments) {\n const syntax = arg.required ? `<${arg.name}>` : `[${arg.name}]`;\n cmd.argument(syntax, arg.description);\n }\n }\n\n if (def.options) {\n for (const opt of def.options) {\n cmd.option(\n opt.flags,\n opt.description,\n opt.defaultValue as string | boolean | string[] | undefined,\n );\n }\n }\n\n cmd.action(async (...rawArgs: unknown[]) => {\n const opts = rawArgs[rawArgs.length - 2] as Record<string, unknown>;\n const args: Record<string, unknown> = {};\n\n if (def.arguments) {\n def.arguments.forEach((argDef, i) => {\n args[argDef.name] = rawArgs[i];\n });\n }\n\n await def.action(args, opts);\n });\n }\n}\n","import { Command } from \"commander\";\nimport type { PluginManager } from \"@gpc-cli/core\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\nimport { registerPluginCommands } from \"./plugins.js\";\n\nexport async function createProgram(pluginManager?: PluginManager): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"gpc\")\n .description(\"The complete Google Play CLI\")\n .version(process.env[\"__GPC_VERSION\"] || \"0.0.0\", \"-V, --version\")\n .option(\"-o, --output <format>\", \"Output format: table, json, yaml, markdown, junit\")\n .option(\"-v, --verbose\", \"Enable debug logging\")\n .option(\"-q, --quiet\", \"Suppress non-essential output\")\n .option(\"-a, --app <package>\", \"App package name\")\n .option(\"-p, --profile <name>\", \"Auth profile name\")\n .option(\"--no-color\", \"Disable colored output\")\n .option(\"--no-interactive\", \"Disable interactive prompts\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without executing\")\n .option(\"--notify [target]\", \"Send webhook notification on completion (slack, discord, custom)\")\n .option(\"--ci\", \"Force CI mode (JSON output, no prompts, strict exit codes)\")\n .option(\"-j, --json\", \"Shorthand for --output json\")\n .showSuggestionAfterError(true);\n\n const commandLoaders: Record<string, () => Promise<void>> = {\n auth: async () => {\n (await import(\"./commands/auth.js\")).registerAuthCommands(program);\n },\n config: async () => {\n (await import(\"./commands/config.js\")).registerConfigCommands(program);\n },\n doctor: async () => {\n (await import(\"./commands/doctor.js\")).registerDoctorCommand(program);\n },\n update: async () => {\n (await import(\"./commands/update.js\")).registerUpdateCommand(program);\n },\n docs: async () => {\n (await import(\"./commands/docs.js\")).registerDocsCommand(program);\n },\n completion: async () => {\n (await import(\"./commands/completion.js\")).registerCompletionCommand(program);\n },\n apps: async () => {\n (await import(\"./commands/apps.js\")).registerAppsCommands(program);\n },\n releases: async () => {\n (await import(\"./commands/releases.js\")).registerReleasesCommands(program);\n },\n tracks: async () => {\n (await import(\"./commands/tracks.js\")).registerTracksCommands(program);\n },\n status: async () => {\n (await import(\"./commands/status.js\")).registerStatusCommand(program);\n },\n listings: async () => {\n (await import(\"./commands/listings.js\")).registerListingsCommands(program);\n },\n reviews: async () => {\n (await import(\"./commands/reviews.js\")).registerReviewsCommands(program);\n },\n vitals: async () => {\n (await import(\"./commands/vitals.js\")).registerVitalsCommands(program);\n },\n subscriptions: async () => {\n (await import(\"./commands/subscriptions.js\")).registerSubscriptionsCommands(program);\n },\n iap: async () => {\n (await import(\"./commands/iap.js\")).registerIapCommands(program);\n },\n purchases: async () => {\n (await import(\"./commands/purchases.js\")).registerPurchasesCommands(program);\n },\n pricing: async () => {\n (await import(\"./commands/pricing.js\")).registerPricingCommands(program);\n },\n reports: async () => {\n (await import(\"./commands/reports.js\")).registerReportsCommands(program);\n },\n users: async () => {\n (await import(\"./commands/users.js\")).registerUsersCommands(program);\n },\n testers: async () => {\n (await import(\"./commands/testers.js\")).registerTestersCommands(program);\n },\n validate: async () => {\n (await import(\"./commands/validate.js\")).registerValidateCommand(program);\n },\n publish: async () => {\n (await import(\"./commands/publish.js\")).registerPublishCommand(program);\n },\n recovery: async () => {\n (await import(\"./commands/recovery.js\")).registerRecoveryCommands(program);\n },\n \"data-safety\": async () => {\n (await import(\"./commands/data-safety.js\")).registerDataSafetyCommands(program);\n },\n \"external-transactions\": async () => {\n (await import(\"./commands/external-transactions.js\")).registerExternalTransactionsCommands(\n program,\n );\n },\n \"device-tiers\": async () => {\n (await import(\"./commands/device-tiers.js\")).registerDeviceTiersCommands(program);\n },\n \"one-time-products\": async () => {\n (await import(\"./commands/one-time-products.js\")).registerOneTimeProductsCommands(program);\n },\n \"internal-sharing\": async () => {\n (await import(\"./commands/internal-sharing.js\")).registerInternalSharingCommands(program);\n },\n \"generated-apks\": async () => {\n (await import(\"./commands/generated-apks.js\")).registerGeneratedApksCommands(program);\n },\n \"purchase-options\": async () => {\n (await import(\"./commands/purchase-options.js\")).registerPurchaseOptionsCommands(program);\n },\n bundle: async () => {\n (await import(\"./commands/bundle.js\")).registerBundleCommands(program);\n },\n audit: async () => {\n (await import(\"./commands/audit.js\")).registerAuditCommands(program);\n },\n migrate: async () => {\n (await import(\"./commands/migrate.js\")).registerMigrateCommands(program);\n },\n \"install-skills\": async () => {\n (await import(\"./commands/install-skills.js\")).registerInstallSkillsCommand(program);\n },\n plugins: async () => {\n registerPluginsCommand(program, pluginManager);\n },\n };\n\n // Resolve command aliases for lazy loading\n const commandAliases: Record<string, string> = {\n \"ext-txn\": \"external-transactions\",\n otp: \"one-time-products\",\n };\n\n const rawTarget = process.argv[2];\n const target = rawTarget ? (commandAliases[rawTarget] ?? rawTarget) : undefined;\n\n const loader = target ? commandLoaders[target] : undefined;\n if (loader) {\n await loader();\n } else {\n await Promise.all(Object.values(commandLoaders).map((loader) => loader()));\n }\n\n // Register plugin-defined commands\n if (pluginManager) {\n registerPluginCommands(program, pluginManager);\n }\n\n // Wire plugin lifecycle hooks around command execution\n if (pluginManager) {\n wrapCommandHooks(program, pluginManager);\n }\n\n return program;\n}\n\n/**\n * `gpc plugins` — manage plugins.\n */\nfunction registerPluginsCommand(program: Command, manager?: PluginManager): void {\n const cmd = program.command(\"plugins\").description(\"Manage plugins\");\n\n cmd\n .command(\"list\")\n .description(\"List loaded plugins\")\n .action(() => {\n const plugins = manager?.getLoadedPlugins() ?? [];\n const opts = program.opts();\n\n if (opts[\"output\"] === \"json\") {\n console.log(JSON.stringify(plugins, null, 2));\n return;\n }\n\n if (plugins.length === 0) {\n console.log(\"No plugins loaded.\");\n console.log('\\nConfigure plugins in .gpcrc.json: { \"plugins\": [\"@gpc-cli/plugin-ci\"] }');\n return;\n }\n\n console.log(\"Loaded plugins:\\n\");\n for (const p of plugins) {\n const trust = p.trusted ? \"trusted\" : \"third-party\";\n console.log(` ${p.name}@${p.version} (${trust})`);\n }\n\n const commands = manager?.getRegisteredCommands() ?? [];\n if (commands.length > 0) {\n console.log(\"\\nPlugin commands:\\n\");\n for (const c of commands) {\n console.log(` gpc ${c.name} — ${c.description}`);\n }\n }\n });\n\n cmd\n .command(\"init <name>\")\n .description(\"Scaffold a new plugin project\")\n .option(\"-d, --dir <path>\", \"Output directory (defaults to ./gpc-plugin-<name>)\")\n .option(\"--description <text>\", \"Plugin description\")\n .action(async (name: string, opts: { dir?: string; description?: string }) => {\n const { scaffoldPlugin } = await import(\"@gpc-cli/core\");\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const dir = opts.dir ?? `./${pluginName}`;\n\n const result = await scaffoldPlugin({ name, dir, description: opts.description });\n\n console.log(`Plugin scaffolded at ${result.dir}/\\n`);\n console.log(\"Files created:\");\n for (const f of result.files) {\n console.log(` ${f}`);\n }\n console.log(`\\nNext steps:`);\n console.log(` cd ${pluginName}`);\n console.log(` npm install`);\n console.log(` npm run build`);\n console.log(` npm test`);\n });\n\n cmd\n .command(\"approve <name>\")\n .description(\"Approve a third-party plugin for loading\")\n .action(async (name: string) => {\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`Plugin \"${name}\" approved. It will be loaded on next run.`);\n });\n\n cmd\n .command(\"revoke <name>\")\n .description(\"Revoke approval for a third-party plugin\")\n .action(async (name: string) => {\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n const removed = await revokePluginApproval(name);\n if (removed) {\n console.log(`Plugin \"${name}\" approval revoked.`);\n } else {\n console.log(`Plugin \"${name}\" was not in the approved list.`);\n }\n });\n}\n\n/**\n * Wrap all registered commands so plugin hooks fire before/after each command.\n */\nfunction wrapCommandHooks(program: Command, manager: PluginManager): void {\n program.hook(\"preAction\", async (thisCommand) => {\n const event: CommandEvent = {\n command: getFullCommandName(thisCommand),\n args: thisCommand.opts(),\n app: program.opts()[\"app\"] as string | undefined,\n startedAt: new Date(),\n };\n\n // Store on the command for afterCommand/onError\n (thisCommand as unknown as Record<string, unknown>)[\"__pluginEvent\"] = event;\n\n await manager.runBeforeCommand(event);\n });\n\n program.hook(\"postAction\", async (thisCommand) => {\n const event: CommandEvent = (thisCommand as unknown as Record<string, unknown>)[\n \"__pluginEvent\"\n ] as CommandEvent;\n if (!event) return;\n\n const result: CommandResult = {\n success: true,\n durationMs: Date.now() - event.startedAt.getTime(),\n exitCode: 0,\n };\n\n await manager.runAfterCommand(event, result);\n });\n}\n\nfunction getFullCommandName(cmd: Command): string {\n const parts: string[] = [];\n let current: Command | null = cmd;\n while (current && current.name() !== \"gpc\") {\n parts.unshift(current.name());\n current = current.parent;\n }\n return parts.join(\" \");\n}\n","/**\n * Shared error formatting for CLI output.\n * Extracts error code, message, and suggestion from typed errors (GpcError, AuthError, ApiError, ConfigError).\n */\n\ninterface TypedError {\n message: string;\n code?: string;\n suggestion?: string;\n exitCode?: number;\n}\n\nfunction isTypedError(error: unknown): error is Error & TypedError {\n return error instanceof Error && \"code\" in error && typeof (error as TypedError).code === \"string\";\n}\n\n/**\n * Format an error for CLI output. Prints:\n * Error [CODE]: message\n * Suggestion: suggestion (if available)\n *\n * Returns the appropriate exit code.\n */\nexport function handleCliError(error: unknown): number {\n if (isTypedError(error)) {\n console.error(`Error [${error.code}]: ${error.message}`);\n if (error.suggestion) {\n console.error(`Suggestion: ${error.suggestion}`);\n }\n return error.exitCode ?? 1;\n }\n\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n return 1;\n}\n"],"mappings":"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","names":["loader"]}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/docs.ts
4
+ import { execFile } from "child_process";
5
+ var PAGE_MAP = {
6
+ releases: "commands/releases",
7
+ status: "commands/status",
8
+ vitals: "commands/vitals",
9
+ reviews: "commands/reviews",
10
+ listings: "commands/listings",
11
+ subscriptions: "commands/subscriptions",
12
+ bundle: "commands/bundle",
13
+ users: "commands/users",
14
+ audit: "commands/audit",
15
+ config: "commands/config",
16
+ doctor: "commands/doctor",
17
+ publish: "commands/publish"
18
+ };
19
+ var BASE = "https://yasserstudio.github.io/gpc/";
20
+ function registerDocsCommand(program) {
21
+ program.command("docs [topic]").description("Open documentation in browser").option("--list", "List available documentation topics").action((topic, opts) => {
22
+ if (opts?.list) {
23
+ console.log("Available topics:");
24
+ for (const key of Object.keys(PAGE_MAP)) console.log(` gpc docs ${key}`);
25
+ return;
26
+ }
27
+ const path = topic ? PAGE_MAP[topic] : void 0;
28
+ if (topic && !path) {
29
+ console.error(`Unknown topic "${topic}". Run: gpc docs --list`);
30
+ process.exit(2);
31
+ }
32
+ const url = path ? `${BASE}${path}` : BASE;
33
+ const platform = process.platform;
34
+ const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
35
+ execFile(cmd, [url], (error) => {
36
+ if (error) {
37
+ console.log(`Open in your browser: ${url}`);
38
+ }
39
+ });
40
+ });
41
+ }
42
+ export {
43
+ registerDocsCommand
44
+ };
45
+ //# sourceMappingURL=docs-HIGQU4UL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/docs.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { execFile } from \"node:child_process\";\n\nconst PAGE_MAP: Record<string, string> = {\n releases: \"commands/releases\",\n status: \"commands/status\",\n vitals: \"commands/vitals\",\n reviews: \"commands/reviews\",\n listings: \"commands/listings\",\n subscriptions: \"commands/subscriptions\",\n bundle: \"commands/bundle\",\n users: \"commands/users\",\n audit: \"commands/audit\",\n config: \"commands/config\",\n doctor: \"commands/doctor\",\n publish: \"commands/publish\",\n};\n\nconst BASE = \"https://yasserstudio.github.io/gpc/\";\n\nexport function registerDocsCommand(program: Command): void {\n program\n .command(\"docs [topic]\")\n .description(\"Open documentation in browser\")\n .option(\"--list\", \"List available documentation topics\")\n .action((topic?: string, opts?: { list?: boolean }) => {\n if (opts?.list) {\n console.log(\"Available topics:\");\n for (const key of Object.keys(PAGE_MAP)) console.log(` gpc docs ${key}`);\n return;\n }\n const path = topic ? PAGE_MAP[topic] : undefined;\n if (topic && !path) {\n console.error(`Unknown topic \"${topic}\". Run: gpc docs --list`);\n process.exit(2);\n }\n const url = path ? `${BASE}${path}` : BASE;\n const platform = process.platform;\n const cmd = platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"start\" : \"xdg-open\";\n execFile(cmd, [url], (error) => {\n if (error) {\n console.log(`Open in your browser: ${url}`);\n }\n });\n });\n}\n"],"mappings":";;;AACA,SAAS,gBAAgB;AAEzB,IAAM,WAAmC;AAAA,EACvC,UAAe;AAAA,EACf,QAAe;AAAA,EACf,QAAe;AAAA,EACf,SAAe;AAAA,EACf,UAAe;AAAA,EACf,eAAe;AAAA,EACf,QAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA,EACf,QAAe;AAAA,EACf,QAAe;AAAA,EACf,SAAe;AACjB;AAEA,IAAM,OAAO;AAEN,SAAS,oBAAoB,SAAwB;AAC1D,UACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,UAAU,qCAAqC,EACtD,OAAO,CAAC,OAAgB,SAA8B;AACrD,QAAI,MAAM,MAAM;AACd,cAAQ,IAAI,mBAAmB;AAC/B,iBAAW,OAAO,OAAO,KAAK,QAAQ,EAAG,SAAQ,IAAI,cAAc,GAAG,EAAE;AACxE;AAAA,IACF;AACA,UAAM,OAAO,QAAQ,SAAS,KAAK,IAAI;AACvC,QAAI,SAAS,CAAC,MAAM;AAClB,cAAQ,MAAM,kBAAkB,KAAK,yBAAyB;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,KAAK;AACtC,UAAM,WAAW,QAAQ;AACzB,UAAM,MAAM,aAAa,WAAW,SAAS,aAAa,UAAU,UAAU;AAC9E,aAAS,KAAK,CAAC,GAAG,GAAG,CAAC,UAAU;AAC9B,UAAI,OAAO;AACT,gBAAQ,IAAI,yBAAyB,GAAG,EAAE;AAAA,MAC5C;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACL;","names":[]}
File without changes
File without changes
File without changes
File without changes
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  createProgram,
4
4
  handleCliError
5
- } from "./chunk-PREKF2AM.js";
5
+ } from "./chunk-5VVYPCDE.js";
6
6
  export {
7
7
  createProgram,
8
8
  handleCliError
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-NV75I5VP.js";
13
13
 
14
14
  // src/commands/publish.ts
15
- import { appendFile } from "fs/promises";
15
+ import { appendFile, stat } from "fs/promises";
16
16
  import { loadConfig, getCacheDir } from "@gpc-cli/config";
17
17
  import { resolveAuth } from "@gpc-cli/auth";
18
18
  import { createApiClient } from "@gpc-cli/api";
@@ -90,6 +90,12 @@ function formatDryRunOutput(result, format) {
90
90
  }
91
91
  function registerPublishCommand(program) {
92
92
  program.command("publish <file>").description("Validate, upload, and release in one step").option("--track <track>", "Target track", "internal").option("--rollout <percent>", "Staged rollout percentage (1-100)").option("--notes <text>", "Release notes (en-US)").option("--notes-dir <dir>", "Read release notes from directory (<dir>/<lang>.txt)").option("--notes-from-git", "Generate release notes from git commit history").option("--since <ref>", "Git ref to start from (tag, SHA) \u2014 used with --notes-from-git").option("--name <name>", "Release name").option("--mapping <file>", "ProGuard/R8 mapping file for deobfuscation").option("--retry-log <path>", "Write retry log entries to file (JSONL)").action(async (file, options) => {
93
+ try {
94
+ await stat(file);
95
+ } catch {
96
+ console.error(`Error: File not found: ${file}`);
97
+ process.exit(2);
98
+ }
93
99
  const noteSources = [options.notes, options.notesDir, options.notesFromGit].filter(Boolean);
94
100
  if (noteSources.length > 1) {
95
101
  console.error(
@@ -204,4 +210,4 @@ function registerPublishCommand(program) {
204
210
  export {
205
211
  registerPublishCommand
206
212
  };
207
- //# sourceMappingURL=publish-26ZPS7XX.js.map
213
+ //# sourceMappingURL=publish-I6WJGR4S.js.map