@gpc-cli/cli 0.9.34 → 0.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -15
- package/dist/{anomalies-QZJGQXTZ.js → anomalies-KRRA75MJ.js} +1 -1
- package/dist/anomalies-KRRA75MJ.js.map +1 -0
- package/dist/{apps-CVBURB5V.js → apps-J2446UDA.js} +2 -2
- package/dist/{apps-CVBURB5V.js.map → apps-J2446UDA.js.map} +1 -1
- package/dist/{audit-A4BP27DN.js → audit-N2CRHWUN.js} +21 -6
- package/dist/audit-N2CRHWUN.js.map +1 -0
- package/dist/{auth-QSDK7NUO.js → auth-XGSTT5G5.js} +107 -9
- package/dist/auth-XGSTT5G5.js.map +1 -0
- package/dist/bin.js +2 -2
- package/dist/bin.js.map +1 -1
- package/dist/{bundle-7IF5FIB4.js → bundle-F43TD2BQ.js} +48 -14
- package/dist/bundle-F43TD2BQ.js.map +1 -0
- package/dist/{cache-SHWAVON6.js → cache-SLNFRTI2.js} +7 -3
- package/dist/cache-SLNFRTI2.js.map +1 -0
- package/dist/{chunk-7BXCQKJG.js → chunk-P5GF73XK.js} +1 -1
- package/dist/chunk-P5GF73XK.js.map +1 -0
- package/dist/{chunk-UH3TMIAL.js → chunk-U6ZTQ34I.js} +15 -17
- package/dist/chunk-U6ZTQ34I.js.map +1 -0
- package/dist/{chunk-5CSWPQO6.js → chunk-XHI7VKWZ.js} +113 -43
- package/dist/chunk-XHI7VKWZ.js.map +1 -0
- package/dist/{completion-C3PPWNS7.js → completion-BCHRJSAT.js} +23 -10
- package/dist/completion-BCHRJSAT.js.map +1 -0
- package/dist/{config-7EOY5HGL.js → config-F2U3KUHX.js} +4 -4
- package/dist/config-F2U3KUHX.js.map +1 -0
- package/dist/{data-safety-GDPKV5PN.js → data-safety-JR6PZ2BD.js} +11 -8
- package/dist/data-safety-JR6PZ2BD.js.map +1 -0
- package/dist/{device-tiers-GHIYJPMB.js → device-tiers-5SGJPSYG.js} +7 -8
- package/dist/device-tiers-5SGJPSYG.js.map +1 -0
- package/dist/{docs-HIGQU4UL.js → docs-7DUXIKA3.js} +3 -3
- package/dist/docs-7DUXIKA3.js.map +1 -0
- package/dist/{doctor-UKKOK55S.js → doctor-4BUPAVFT.js} +51 -7
- package/dist/doctor-4BUPAVFT.js.map +1 -0
- package/dist/enterprise-7THXNBTC.js +69 -0
- package/dist/enterprise-7THXNBTC.js.map +1 -0
- package/dist/{external-transactions-HCL7ROMN.js → external-transactions-O5P4QBIT.js} +5 -8
- package/dist/external-transactions-O5P4QBIT.js.map +1 -0
- package/dist/{feedback-W5MZMRF2.js → feedback-BZWHEADD.js} +3 -3
- package/dist/feedback-BZWHEADD.js.map +1 -0
- package/dist/games-X57AGM3E.js +80 -0
- package/dist/games-X57AGM3E.js.map +1 -0
- package/dist/{generated-apks-VX7HYZDU.js → generated-apks-KB2PLWDI.js} +2 -6
- package/dist/generated-apks-KB2PLWDI.js.map +1 -0
- package/dist/grants-TKQJ3IER.js +142 -0
- package/dist/grants-TKQJ3IER.js.map +1 -0
- package/dist/{iap-6XHJV5HX.js → iap-BNIAHBDN.js} +7 -3
- package/dist/iap-BNIAHBDN.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{internal-sharing-E7SJYDW3.js → internal-sharing-M74VNIQ2.js} +7 -7
- package/dist/internal-sharing-M74VNIQ2.js.map +1 -0
- package/dist/{listings-TOYS6XBU.js → listings-IVHZJNES.js} +91 -10
- package/dist/listings-IVHZJNES.js.map +1 -0
- package/dist/{migrate-OHN2FDY6.js → migrate-SQT6RD6T.js} +2 -4
- package/dist/migrate-SQT6RD6T.js.map +1 -0
- package/dist/{one-time-products-2PK4QKWE.js → one-time-products-3WNXDKE3.js} +43 -28
- package/dist/one-time-products-3WNXDKE3.js.map +1 -0
- package/dist/{pricing-BYZSLN74.js → pricing-HMHZD44S.js} +1 -1
- package/dist/pricing-HMHZD44S.js.map +1 -0
- package/dist/{publish-I6WJGR4S.js → publish-EPZXLGKZ.js} +4 -9
- package/dist/publish-EPZXLGKZ.js.map +1 -0
- package/dist/{purchases-YRO6B7M6.js → purchases-7ZPVCN6D.js} +31 -2
- package/dist/purchases-7ZPVCN6D.js.map +1 -0
- package/dist/quickstart-EYNNOTVD.js +87 -0
- package/dist/quickstart-EYNNOTVD.js.map +1 -0
- package/dist/quota-UHIQQYOY.js +58 -0
- package/dist/quota-UHIQQYOY.js.map +1 -0
- package/dist/{recovery-S5UNJDBO.js → recovery-YGPOVUFD.js} +7 -3
- package/dist/recovery-YGPOVUFD.js.map +1 -0
- package/dist/{releases-ANC54YWF.js → releases-I7QQVKPJ.js} +62 -22
- package/dist/releases-I7QQVKPJ.js.map +1 -0
- package/dist/{reports-N5X66IUN.js → reports-2YX3RDOS.js} +1 -1
- package/dist/reports-2YX3RDOS.js.map +1 -0
- package/dist/{reviews-UHK4FGK6.js → reviews-MOVGATUI.js} +68 -7
- package/dist/reviews-MOVGATUI.js.map +1 -0
- package/dist/{status-DQYZ7A6Y.js → status-G3AMJ34G.js} +17 -5
- package/dist/status-G3AMJ34G.js.map +1 -0
- package/dist/{subscriptions-Z5ZPVUFM.js → subscriptions-LSOJID6H.js} +39 -2
- package/dist/subscriptions-LSOJID6H.js.map +1 -0
- package/dist/{testers-UWSUGGVT.js → testers-SDLVWQ2Z.js} +1 -1
- package/dist/testers-SDLVWQ2Z.js.map +1 -0
- package/dist/{tracks-XFUN7JJX.js → tracks-NERFFEDT.js} +2 -2
- package/dist/tracks-NERFFEDT.js.map +1 -0
- package/dist/train-PX5Z26PQ.js +150 -0
- package/dist/train-PX5Z26PQ.js.map +1 -0
- package/dist/{update-NIVJLUNH.js → update-ARIQO53C.js} +6 -12
- package/dist/update-ARIQO53C.js.map +1 -0
- package/dist/{users-JASXONRY.js → users-2YTC4Q36.js} +1 -1
- package/dist/users-2YTC4Q36.js.map +1 -0
- package/dist/{validate-MHLPENCM.js → validate-VNIS6OEB.js} +9 -4
- package/dist/validate-VNIS6OEB.js.map +1 -0
- package/dist/{version-7AI5IHVK.js → version-MXIJ4BUH.js} +11 -9
- package/dist/version-MXIJ4BUH.js.map +1 -0
- package/dist/{vitals-QGWOFH7E.js → vitals-H7DCI6JJ.js} +125 -7
- package/dist/vitals-H7DCI6JJ.js.map +1 -0
- package/package.json +7 -3
- package/dist/anomalies-QZJGQXTZ.js.map +0 -1
- package/dist/audit-A4BP27DN.js.map +0 -1
- package/dist/auth-QSDK7NUO.js.map +0 -1
- package/dist/bundle-7IF5FIB4.js.map +0 -1
- package/dist/cache-SHWAVON6.js.map +0 -1
- package/dist/chunk-5CSWPQO6.js.map +0 -1
- package/dist/chunk-7BXCQKJG.js.map +0 -1
- package/dist/chunk-UH3TMIAL.js.map +0 -1
- package/dist/completion-C3PPWNS7.js.map +0 -1
- package/dist/config-7EOY5HGL.js.map +0 -1
- package/dist/data-safety-GDPKV5PN.js.map +0 -1
- package/dist/device-tiers-GHIYJPMB.js.map +0 -1
- package/dist/docs-HIGQU4UL.js.map +0 -1
- package/dist/doctor-UKKOK55S.js.map +0 -1
- package/dist/external-transactions-HCL7ROMN.js.map +0 -1
- package/dist/feedback-W5MZMRF2.js.map +0 -1
- package/dist/generated-apks-VX7HYZDU.js.map +0 -1
- package/dist/iap-6XHJV5HX.js.map +0 -1
- package/dist/internal-sharing-E7SJYDW3.js.map +0 -1
- package/dist/listings-TOYS6XBU.js.map +0 -1
- package/dist/migrate-OHN2FDY6.js.map +0 -1
- package/dist/one-time-products-2PK4QKWE.js.map +0 -1
- package/dist/pricing-BYZSLN74.js.map +0 -1
- package/dist/publish-I6WJGR4S.js.map +0 -1
- package/dist/purchases-YRO6B7M6.js.map +0 -1
- package/dist/recovery-S5UNJDBO.js.map +0 -1
- package/dist/releases-ANC54YWF.js.map +0 -1
- package/dist/reports-N5X66IUN.js.map +0 -1
- package/dist/reviews-UHK4FGK6.js.map +0 -1
- package/dist/status-DQYZ7A6Y.js.map +0 -1
- package/dist/subscriptions-Z5ZPVUFM.js.map +0 -1
- package/dist/testers-UWSUGGVT.js.map +0 -1
- package/dist/tracks-XFUN7JJX.js.map +0 -1
- package/dist/update-NIVJLUNH.js.map +0 -1
- package/dist/users-JASXONRY.js.map +0 -1
- package/dist/validate-MHLPENCM.js.map +0 -1
- package/dist/version-7AI5IHVK.js.map +0 -1
- package/dist/vitals-QGWOFH7E.js.map +0 -1
|
@@ -74,7 +74,9 @@ function registerCacheCommand(program) {
|
|
|
74
74
|
if (opts.type) {
|
|
75
75
|
const matcher = FILE_TYPES[opts.type];
|
|
76
76
|
if (!matcher) {
|
|
77
|
-
console.error(
|
|
77
|
+
console.error(
|
|
78
|
+
`Error: Unknown cache type "${opts.type}". Valid types: ${Object.keys(FILE_TYPES).join(", ")}`
|
|
79
|
+
);
|
|
78
80
|
process.exit(2);
|
|
79
81
|
}
|
|
80
82
|
toDelete = allFiles.filter((f) => matcher(f.name));
|
|
@@ -90,7 +92,9 @@ function registerCacheCommand(program) {
|
|
|
90
92
|
}
|
|
91
93
|
const { createInterface } = await import("readline");
|
|
92
94
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
93
|
-
const answer = await new Promise(
|
|
95
|
+
const answer = await new Promise(
|
|
96
|
+
(resolve) => rl.question("Proceed? [y/N] ", resolve)
|
|
97
|
+
);
|
|
94
98
|
rl.close();
|
|
95
99
|
if (answer.toLowerCase() !== "y") {
|
|
96
100
|
console.log("Aborted.");
|
|
@@ -111,4 +115,4 @@ function registerCacheCommand(program) {
|
|
|
111
115
|
export {
|
|
112
116
|
registerCacheCommand
|
|
113
117
|
};
|
|
114
|
-
//# sourceMappingURL=cache-
|
|
118
|
+
//# sourceMappingURL=cache-SLNFRTI2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/cache.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { readdir, stat, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { getCacheDir } from \"@gpc-cli/config\";\n\nconst FILE_TYPES: Record<string, (name: string) => boolean> = {\n status: (name) => name.startsWith(\"status-\") && name.endsWith(\".json\"),\n token: (name) => name === \"token-cache.json\",\n update: (name) => name === \"update-check.json\",\n};\n\nasync function getCacheFiles(\n cacheDir: string,\n): Promise<{ name: string; path: string; size: number; mtime: Date }[]> {\n let entries: string[];\n try {\n entries = await readdir(cacheDir);\n } catch {\n return [];\n }\n\n const files: { name: string; path: string; size: number; mtime: Date }[] = [];\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) continue;\n const filePath = join(cacheDir, entry);\n try {\n const info = await stat(filePath);\n if (info.isFile()) {\n files.push({ name: entry, path: filePath, size: info.size, mtime: info.mtime });\n }\n } catch {\n /* ignore */\n }\n }\n return files;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction fileType(name: string): string {\n for (const [type, matcher] of Object.entries(FILE_TYPES)) {\n if (matcher(name)) return type;\n }\n return \"other\";\n}\n\nexport function registerCacheCommand(program: Command): void {\n const cache = program.command(\"cache\").description(\"Manage local cache files\");\n\n cache\n .command(\"info\")\n .description(\"Show cache directory and total size\")\n .action(async () => {\n const cacheDir = getCacheDir();\n const files = await getCacheFiles(cacheDir);\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n console.log(`Cache directory: ${cacheDir}`);\n console.log(`Files: ${files.length}`);\n console.log(`Total size: ${formatBytes(totalSize)}`);\n });\n\n cache\n .command(\"list\")\n .description(\"List all cache files with size and age\")\n .action(async () => {\n const cacheDir = getCacheDir();\n const files = await getCacheFiles(cacheDir);\n if (files.length === 0) {\n console.log(\"No cache files found.\");\n return;\n }\n const now = Date.now();\n for (const f of files) {\n const ageMs = now - f.mtime.getTime();\n const ageMins = Math.floor(ageMs / 60000);\n const ageStr =\n ageMins < 60\n ? `${ageMins}m ago`\n : ageMins < 1440\n ? `${Math.floor(ageMins / 60)}h ago`\n : `${Math.floor(ageMins / 1440)}d ago`;\n const type = fileType(f.name);\n console.log(` ${f.name} [${type}] ${formatBytes(f.size)} ${ageStr}`);\n }\n });\n\n cache\n .command(\"clear\")\n .description(\"Remove cache files\")\n .option(\"--force\", \"Skip confirmation prompt\")\n .option(\"--type <type>\", \"Remove only files of this type (status|token|update)\")\n .action(async (opts) => {\n const cacheDir = getCacheDir();\n const allFiles = await getCacheFiles(cacheDir);\n\n let toDelete = allFiles;\n if (opts.type) {\n const matcher = FILE_TYPES[opts.type];\n if (!matcher) {\n console.error(\n `Error: Unknown cache type \"${opts.type}\". Valid types: ${Object.keys(FILE_TYPES).join(\", \")}`,\n );\n process.exit(2);\n }\n toDelete = allFiles.filter((f) => matcher(f.name));\n }\n\n if (toDelete.length === 0) {\n console.log(\"No cache files to remove.\");\n return;\n }\n\n if (!opts.force) {\n console.log(`About to remove ${toDelete.length} file(s) from ${cacheDir}:`);\n for (const f of toDelete) {\n console.log(` ${f.name} (${formatBytes(f.size)})`);\n }\n const { createInterface } = await import(\"node:readline\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) =>\n rl.question(\"Proceed? [y/N] \", resolve),\n );\n rl.close();\n if (answer.toLowerCase() !== \"y\") {\n console.log(\"Aborted.\");\n return;\n }\n }\n\n let removed = 0;\n for (const f of toDelete) {\n try {\n await unlink(f.path);\n removed++;\n } catch {\n /* ignore */\n }\n }\n console.log(`Removed ${removed} file(s).`);\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/colors.ts"],"sourcesContent":["// Named exports only. No default export.\n\nfunction isColorEnabled(): boolean {\n if (process.env[\"NO_COLOR\"] !== undefined && process.env[\"NO_COLOR\"] !== \"\") return false;\n if (\n process.env[\"FORCE_COLOR\"] === \"1\" ||\n process.env[\"FORCE_COLOR\"] === \"2\" ||\n process.env[\"FORCE_COLOR\"] === \"3\"\n )\n return true;\n return process.stdout.isTTY ?? false;\n}\n\nfunction wrap(code: number, s: string): string {\n if (!isColorEnabled()) return s;\n return `\\x1b[${code}m${s}\\x1b[0m`;\n}\n\nexport function green(s: string): string {\n return wrap(32, s);\n}\nexport function red(s: string): string {\n return wrap(31, s);\n}\nexport function yellow(s: string): string {\n return wrap(33, s);\n}\nexport function dim(s: string): string {\n return wrap(2, s);\n}\nexport function gray(s: string): string {\n return wrap(90, s);\n}\nexport function bold(s: string): string {\n return wrap(1, s);\n}\n"],"mappings":";;;AAEA,SAAS,iBAA0B;AACjC,MAAI,QAAQ,IAAI,UAAU,MAAM,UAAa,QAAQ,IAAI,UAAU,MAAM,GAAI,QAAO;AACpF,MACE,QAAQ,IAAI,aAAa,MAAM,OAC/B,QAAQ,IAAI,aAAa,MAAM,OAC/B,QAAQ,IAAI,aAAa,MAAM;AAE/B,WAAO;AACT,SAAO,QAAQ,OAAO,SAAS;AACjC;AAEA,SAAS,KAAK,MAAc,GAAmB;AAC7C,MAAI,CAAC,eAAe,EAAG,QAAO;AAC9B,SAAO,QAAQ,IAAI,IAAI,CAAC;AAC1B;AAEO,SAAS,MAAM,GAAmB;AACvC,SAAO,KAAK,IAAI,CAAC;AACnB;AACO,SAAS,IAAI,GAAmB;AACrC,SAAO,KAAK,IAAI,CAAC;AACnB;AACO,SAAS,OAAO,GAAmB;AACxC,SAAO,KAAK,IAAI,CAAC;AACnB;AACO,SAAS,IAAI,GAAmB;AACrC,SAAO,KAAK,GAAG,CAAC;AAClB;AACO,SAAS,KAAK,GAAmB;AACtC,SAAO,KAAK,IAAI,CAAC;AACnB;","names":[]}
|
|
@@ -77,9 +77,7 @@ async function fetchLatestRelease() {
|
|
|
77
77
|
}
|
|
78
78
|
if (response.status === 429) {
|
|
79
79
|
throw Object.assign(
|
|
80
|
-
new Error(
|
|
81
|
-
"GitHub API rate limit exceeded. Set GPC_GITHUB_TOKEN to increase the limit."
|
|
82
|
-
),
|
|
80
|
+
new Error("GitHub API rate limit exceeded. Set GPC_GITHUB_TOKEN to increase the limit."),
|
|
83
81
|
{ code: "UPDATE_RATE_LIMITED", exitCode: 4 }
|
|
84
82
|
);
|
|
85
83
|
}
|
|
@@ -197,10 +195,10 @@ async function sha256File(filePath) {
|
|
|
197
195
|
if (size === 0) return hash.digest("hex");
|
|
198
196
|
const { createReadStream } = await import("fs");
|
|
199
197
|
const stream = createReadStream(filePath);
|
|
200
|
-
await
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
await new Promise((resolve, reject) => {
|
|
199
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
200
|
+
stream.on("end", resolve);
|
|
201
|
+
stream.on("error", reject);
|
|
204
202
|
});
|
|
205
203
|
return hash.digest("hex");
|
|
206
204
|
}
|
|
@@ -252,7 +250,10 @@ async function updateBinaryInPlace(assetUrl, expectedSha256, currentBinaryPath,
|
|
|
252
250
|
dest
|
|
253
251
|
);
|
|
254
252
|
} else {
|
|
255
|
-
await pipeline(
|
|
253
|
+
await pipeline(
|
|
254
|
+
Readable.fromWeb(response.body),
|
|
255
|
+
dest
|
|
256
|
+
);
|
|
256
257
|
}
|
|
257
258
|
if (expectedSha256) {
|
|
258
259
|
const actual = await sha256File(tmpPath);
|
|
@@ -288,14 +289,11 @@ async function updateBinaryInPlace(assetUrl, expectedSha256, currentBinaryPath,
|
|
|
288
289
|
await unlink(tmpPath).catch(() => {
|
|
289
290
|
});
|
|
290
291
|
if (isPermissionError(err)) {
|
|
291
|
-
throw Object.assign(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
suggestion: `Run with elevated permissions: sudo gpc update`
|
|
297
|
-
}
|
|
298
|
-
);
|
|
292
|
+
throw Object.assign(new Error(`Permission denied replacing ${currentBinaryPath}`), {
|
|
293
|
+
code: "UPDATE_PERMISSION_DENIED",
|
|
294
|
+
exitCode: 1,
|
|
295
|
+
suggestion: `Run with elevated permissions: sudo gpc update`
|
|
296
|
+
});
|
|
299
297
|
}
|
|
300
298
|
throw err;
|
|
301
299
|
}
|
|
@@ -311,4 +309,4 @@ export {
|
|
|
311
309
|
updateViaBrew,
|
|
312
310
|
updateBinaryInPlace
|
|
313
311
|
};
|
|
314
|
-
//# sourceMappingURL=chunk-
|
|
312
|
+
//# sourceMappingURL=chunk-U6ZTQ34I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/updater.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 — but Homebrew also distributes as compiled binary, check execPath\n if (process.env[\"__GPC_BINARY\"] === \"1\") {\n try {\n const resolved = realpathSync(process.execPath).toLowerCase();\n if (resolved.includes(\"cellar\") || resolved.includes(\"homebrew\")) return \"homebrew\";\n } catch {\n /* ignore */\n }\n return \"binary\";\n }\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(\"GitHub API rate limit exceeded. Set GPC_GITHUB_TOKEN to increase the limit.\"),\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 err instanceof Error && \"code\" in err && (err.code === \"EACCES\" || err.code === \"EPERM\");\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 new Promise<void>((resolve, reject) => {\n stream.on(\"data\", (chunk: Buffer) => hash.update(chunk));\n stream.on(\"end\", resolve);\n stream.on(\"error\", reject);\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(\n Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]),\n dest,\n );\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(new Error(`Permission denied replacing ${currentBinaryPath}`), {\n code: \"UPDATE_PERMISSION_DENIED\",\n exitCode: 1,\n suggestion: `Run with elevated permissions: sudo gpc update`,\n });\n }\n throw err;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -67,123 +67,141 @@ function registerPluginCommands(program, manager) {
|
|
|
67
67
|
import { Command } from "commander";
|
|
68
68
|
async function createProgram(pluginManager) {
|
|
69
69
|
const program = new Command();
|
|
70
|
-
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version(
|
|
70
|
+
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.36", "-V, --version").option("-o, --output <format>", "Output format: table, json, yaml, markdown, junit").option("-v, --verbose", "Enable debug logging").option("-q, --quiet", "Suppress non-essential output").option("-a, --app <package>", "App package name").option("-p, --profile <name>", "Auth profile name").option("--no-color", "Disable colored output").option("--no-interactive", "Disable interactive prompts").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Preview changes without executing").option("--notify [target]", "Send webhook notification on completion (slack, discord, custom)").option("--ci", "Force CI mode (JSON output, no prompts, strict exit codes)").option("-j, --json", "Shorthand for --output json").option("--apps <csv>", "Comma-separated package names for multi-app operations").showSuggestionAfterError(false);
|
|
71
71
|
const commandLoaders = {
|
|
72
72
|
auth: async () => {
|
|
73
|
-
(await import("./auth-
|
|
73
|
+
(await import("./auth-XGSTT5G5.js")).registerAuthCommands(program);
|
|
74
74
|
},
|
|
75
75
|
config: async () => {
|
|
76
|
-
(await import("./config-
|
|
76
|
+
(await import("./config-F2U3KUHX.js")).registerConfigCommands(program);
|
|
77
77
|
},
|
|
78
78
|
doctor: async () => {
|
|
79
|
-
(await import("./doctor-
|
|
79
|
+
(await import("./doctor-4BUPAVFT.js")).registerDoctorCommand(program);
|
|
80
80
|
},
|
|
81
81
|
update: async () => {
|
|
82
|
-
(await import("./update-
|
|
82
|
+
(await import("./update-ARIQO53C.js")).registerUpdateCommand(program);
|
|
83
83
|
},
|
|
84
84
|
docs: async () => {
|
|
85
|
-
(await import("./docs-
|
|
85
|
+
(await import("./docs-7DUXIKA3.js")).registerDocsCommand(program);
|
|
86
86
|
},
|
|
87
87
|
completion: async () => {
|
|
88
|
-
(await import("./completion-
|
|
88
|
+
(await import("./completion-BCHRJSAT.js")).registerCompletionCommand(program);
|
|
89
89
|
},
|
|
90
90
|
apps: async () => {
|
|
91
|
-
(await import("./apps-
|
|
91
|
+
(await import("./apps-J2446UDA.js")).registerAppsCommands(program);
|
|
92
92
|
},
|
|
93
93
|
releases: async () => {
|
|
94
|
-
(await import("./releases-
|
|
94
|
+
(await import("./releases-I7QQVKPJ.js")).registerReleasesCommands(program);
|
|
95
95
|
},
|
|
96
96
|
tracks: async () => {
|
|
97
|
-
(await import("./tracks-
|
|
97
|
+
(await import("./tracks-NERFFEDT.js")).registerTracksCommands(program);
|
|
98
98
|
},
|
|
99
99
|
status: async () => {
|
|
100
|
-
(await import("./status-
|
|
100
|
+
(await import("./status-G3AMJ34G.js")).registerStatusCommand(program);
|
|
101
101
|
},
|
|
102
102
|
listings: async () => {
|
|
103
|
-
(await import("./listings-
|
|
103
|
+
(await import("./listings-IVHZJNES.js")).registerListingsCommands(program);
|
|
104
104
|
},
|
|
105
105
|
reviews: async () => {
|
|
106
|
-
(await import("./reviews-
|
|
106
|
+
(await import("./reviews-MOVGATUI.js")).registerReviewsCommands(program);
|
|
107
107
|
},
|
|
108
108
|
vitals: async () => {
|
|
109
|
-
(await import("./vitals-
|
|
109
|
+
(await import("./vitals-H7DCI6JJ.js")).registerVitalsCommands(program);
|
|
110
110
|
},
|
|
111
111
|
subscriptions: async () => {
|
|
112
|
-
(await import("./subscriptions-
|
|
112
|
+
(await import("./subscriptions-LSOJID6H.js")).registerSubscriptionsCommands(program);
|
|
113
113
|
},
|
|
114
114
|
iap: async () => {
|
|
115
|
-
(await import("./iap-
|
|
115
|
+
(await import("./iap-BNIAHBDN.js")).registerIapCommands(program);
|
|
116
116
|
},
|
|
117
117
|
purchases: async () => {
|
|
118
|
-
(await import("./purchases-
|
|
118
|
+
(await import("./purchases-7ZPVCN6D.js")).registerPurchasesCommands(program);
|
|
119
119
|
},
|
|
120
120
|
pricing: async () => {
|
|
121
|
-
(await import("./pricing-
|
|
121
|
+
(await import("./pricing-HMHZD44S.js")).registerPricingCommands(program);
|
|
122
122
|
},
|
|
123
123
|
reports: async () => {
|
|
124
|
-
(await import("./reports-
|
|
124
|
+
(await import("./reports-2YX3RDOS.js")).registerReportsCommands(program);
|
|
125
125
|
},
|
|
126
126
|
users: async () => {
|
|
127
|
-
(await import("./users-
|
|
127
|
+
(await import("./users-2YTC4Q36.js")).registerUsersCommands(program);
|
|
128
128
|
},
|
|
129
129
|
testers: async () => {
|
|
130
|
-
(await import("./testers-
|
|
130
|
+
(await import("./testers-SDLVWQ2Z.js")).registerTestersCommands(program);
|
|
131
131
|
},
|
|
132
132
|
validate: async () => {
|
|
133
|
-
(await import("./validate-
|
|
133
|
+
(await import("./validate-VNIS6OEB.js")).registerValidateCommand(program);
|
|
134
134
|
},
|
|
135
135
|
publish: async () => {
|
|
136
|
-
(await import("./publish-
|
|
136
|
+
(await import("./publish-EPZXLGKZ.js")).registerPublishCommand(program);
|
|
137
137
|
},
|
|
138
138
|
recovery: async () => {
|
|
139
|
-
(await import("./recovery-
|
|
139
|
+
(await import("./recovery-YGPOVUFD.js")).registerRecoveryCommands(program);
|
|
140
140
|
},
|
|
141
141
|
"data-safety": async () => {
|
|
142
|
-
(await import("./data-safety-
|
|
142
|
+
(await import("./data-safety-JR6PZ2BD.js")).registerDataSafetyCommands(program);
|
|
143
143
|
},
|
|
144
144
|
"external-transactions": async () => {
|
|
145
|
-
(await import("./external-transactions-
|
|
145
|
+
(await import("./external-transactions-O5P4QBIT.js")).registerExternalTransactionsCommands(
|
|
146
146
|
program
|
|
147
147
|
);
|
|
148
148
|
},
|
|
149
149
|
"device-tiers": async () => {
|
|
150
|
-
(await import("./device-tiers-
|
|
150
|
+
(await import("./device-tiers-5SGJPSYG.js")).registerDeviceTiersCommands(program);
|
|
151
151
|
},
|
|
152
152
|
"one-time-products": async () => {
|
|
153
|
-
(await import("./one-time-products-
|
|
153
|
+
(await import("./one-time-products-3WNXDKE3.js")).registerOneTimeProductsCommands(program);
|
|
154
154
|
},
|
|
155
155
|
"internal-sharing": async () => {
|
|
156
|
-
(await import("./internal-sharing-
|
|
156
|
+
(await import("./internal-sharing-M74VNIQ2.js")).registerInternalSharingCommands(program);
|
|
157
157
|
},
|
|
158
158
|
"generated-apks": async () => {
|
|
159
|
-
(await import("./generated-apks-
|
|
159
|
+
(await import("./generated-apks-KB2PLWDI.js")).registerGeneratedApksCommands(program);
|
|
160
160
|
},
|
|
161
161
|
"purchase-options": async () => {
|
|
162
162
|
(await import("./purchase-options-CKRN4VIW.js")).registerPurchaseOptionsCommands(program);
|
|
163
163
|
},
|
|
164
164
|
bundle: async () => {
|
|
165
|
-
(await import("./bundle-
|
|
165
|
+
(await import("./bundle-F43TD2BQ.js")).registerBundleCommands(program);
|
|
166
166
|
},
|
|
167
167
|
audit: async () => {
|
|
168
|
-
(await import("./audit-
|
|
168
|
+
(await import("./audit-N2CRHWUN.js")).registerAuditCommands(program);
|
|
169
169
|
},
|
|
170
170
|
migrate: async () => {
|
|
171
|
-
(await import("./migrate-
|
|
171
|
+
(await import("./migrate-SQT6RD6T.js")).registerMigrateCommands(program);
|
|
172
172
|
},
|
|
173
173
|
anomalies: async () => {
|
|
174
|
-
(await import("./anomalies-
|
|
174
|
+
(await import("./anomalies-KRRA75MJ.js")).registerAnomaliesCommands(program);
|
|
175
175
|
},
|
|
176
176
|
"install-skills": async () => {
|
|
177
177
|
(await import("./install-skills-OV4HVANW.js")).registerInstallSkillsCommand(program);
|
|
178
178
|
},
|
|
179
179
|
version: async () => {
|
|
180
|
-
(await import("./version-
|
|
180
|
+
(await import("./version-MXIJ4BUH.js")).registerVersionCommand(program);
|
|
181
181
|
},
|
|
182
182
|
cache: async () => {
|
|
183
|
-
(await import("./cache-
|
|
183
|
+
(await import("./cache-SLNFRTI2.js")).registerCacheCommand(program);
|
|
184
184
|
},
|
|
185
185
|
feedback: async () => {
|
|
186
|
-
(await import("./feedback-
|
|
186
|
+
(await import("./feedback-BZWHEADD.js")).registerFeedbackCommand(program);
|
|
187
|
+
},
|
|
188
|
+
quickstart: async () => {
|
|
189
|
+
(await import("./quickstart-EYNNOTVD.js")).registerQuickstartCommand(program);
|
|
190
|
+
},
|
|
191
|
+
grants: async () => {
|
|
192
|
+
(await import("./grants-TKQJ3IER.js")).registerGrantsCommands(program);
|
|
193
|
+
},
|
|
194
|
+
train: async () => {
|
|
195
|
+
(await import("./train-PX5Z26PQ.js")).registerTrainCommands(program);
|
|
196
|
+
},
|
|
197
|
+
quota: async () => {
|
|
198
|
+
(await import("./quota-UHIQQYOY.js")).registerQuotaCommand(program);
|
|
199
|
+
},
|
|
200
|
+
games: async () => {
|
|
201
|
+
(await import("./games-X57AGM3E.js")).registerGamesCommands(program);
|
|
202
|
+
},
|
|
203
|
+
enterprise: async () => {
|
|
204
|
+
(await import("./enterprise-7THXNBTC.js")).registerEnterpriseCommands(program);
|
|
187
205
|
},
|
|
188
206
|
plugins: async () => {
|
|
189
207
|
registerPluginsCommand(program, pluginManager);
|
|
@@ -195,14 +213,13 @@ async function createProgram(pluginManager) {
|
|
|
195
213
|
{ length: m + 1 },
|
|
196
214
|
(_, i) => Array.from({ length: n + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
|
|
197
215
|
);
|
|
216
|
+
const cell = (r, c) => dp[r]?.[c] ?? 0;
|
|
198
217
|
for (let i = 1; i <= m; i++) {
|
|
199
218
|
for (let j = 1; j <= n; j++) {
|
|
200
|
-
|
|
201
|
-
const prevRow = dp[i - 1];
|
|
202
|
-
row[j] = a[i - 1] === b[j - 1] ? prevRow[j - 1] : 1 + Math.min(prevRow[j], row[j - 1], prevRow[j - 1]);
|
|
219
|
+
dp[i][j] = a[i - 1] === b[j - 1] ? cell(i - 1, j - 1) : 1 + Math.min(cell(i - 1, j), cell(i, j - 1), cell(i - 1, j - 1));
|
|
203
220
|
}
|
|
204
221
|
}
|
|
205
|
-
return
|
|
222
|
+
return cell(m, n);
|
|
206
223
|
}
|
|
207
224
|
program.on("command:*", (operands) => {
|
|
208
225
|
const cmd = operands[0] ?? "";
|
|
@@ -292,6 +309,59 @@ Next steps:`);
|
|
|
292
309
|
console.log(`Plugin "${name}" was not in the approved list.`);
|
|
293
310
|
}
|
|
294
311
|
});
|
|
312
|
+
const REGISTRY_URL = "https://raw.githubusercontent.com/yasserstudio/gpc-plugins/main/registry.json";
|
|
313
|
+
cmd.command("search [query]").description("Search the GPC plugin registry").action(async (query) => {
|
|
314
|
+
try {
|
|
315
|
+
const res = await fetch(REGISTRY_URL);
|
|
316
|
+
if (!res.ok) throw new Error(`Registry fetch failed: ${res.status}`);
|
|
317
|
+
const plugins = await res.json();
|
|
318
|
+
const filtered = query ? plugins.filter(
|
|
319
|
+
(p) => p.name.includes(query) || p.description?.toLowerCase().includes(query.toLowerCase())
|
|
320
|
+
) : plugins;
|
|
321
|
+
if (filtered.length === 0) {
|
|
322
|
+
console.log(`No plugins found${query ? ` matching "${query}"` : ""}.`);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
for (const p of filtered) {
|
|
326
|
+
console.log(` ${p.name}@${p.version}`);
|
|
327
|
+
if (p.description) console.log(` ${p.description}`);
|
|
328
|
+
}
|
|
329
|
+
console.log(`
|
|
330
|
+
Install: gpc plugins install <name>`);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
333
|
+
process.exit(4);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
cmd.command("install <name>").description("Install a plugin from npm").action(async (name) => {
|
|
337
|
+
const { execSync } = await import("child_process");
|
|
338
|
+
console.log(`Installing plugin "${name}"...`);
|
|
339
|
+
try {
|
|
340
|
+
execSync(`npm install -g ${name}`, { stdio: "inherit" });
|
|
341
|
+
const { approvePlugin } = await import("@gpc-cli/config");
|
|
342
|
+
await approvePlugin(name);
|
|
343
|
+
console.log(`
|
|
344
|
+
Plugin "${name}" installed and approved. It will be loaded on next run.`);
|
|
345
|
+
console.log(`Configure it in .gpcrc.json: { "plugins": ["${name}"] }`);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
348
|
+
process.exit(4);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
cmd.command("uninstall <name>").description("Uninstall a plugin and revoke its approval").action(async (name) => {
|
|
352
|
+
const { execSync } = await import("child_process");
|
|
353
|
+
console.log(`Uninstalling plugin "${name}"...`);
|
|
354
|
+
try {
|
|
355
|
+
execSync(`npm uninstall -g ${name}`, { stdio: "inherit" });
|
|
356
|
+
const { revokePluginApproval } = await import("@gpc-cli/config");
|
|
357
|
+
await revokePluginApproval(name);
|
|
358
|
+
console.log(`
|
|
359
|
+
Plugin "${name}" uninstalled and approval revoked.`);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
362
|
+
process.exit(4);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
295
365
|
}
|
|
296
366
|
function wrapCommandHooks(program, manager) {
|
|
297
367
|
program.hook("preAction", async (thisCommand) => {
|
|
@@ -333,7 +403,7 @@ var AUTH_KEYWORDS = ["AUTH", "UNAUTHENTICATED", "PERMISSION_DENIED", "401", "403
|
|
|
333
403
|
function isAuthRelatedError(error) {
|
|
334
404
|
if (isTypedError(error)) {
|
|
335
405
|
if (error.exitCode === 3) return true;
|
|
336
|
-
if (error.code && AUTH_KEYWORDS.some((k) => error.code
|
|
406
|
+
if (error.code && AUTH_KEYWORDS.some((k) => error.code?.includes(k))) return true;
|
|
337
407
|
}
|
|
338
408
|
const msg = error instanceof Error ? error.message : String(error);
|
|
339
409
|
return AUTH_KEYWORDS.some((k) => msg.includes(k));
|
|
@@ -359,4 +429,4 @@ export {
|
|
|
359
429
|
createProgram,
|
|
360
430
|
handleCliError
|
|
361
431
|
};
|
|
362
|
-
//# sourceMappingURL=chunk-
|
|
432
|
+
//# sourceMappingURL=chunk-XHI7VKWZ.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(\"GPC — Google Play Console 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 .option(\"--apps <csv>\", \"Comma-separated package names for multi-app operations\")\n .showSuggestionAfterError(false);\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 anomalies: async () => {\n (await import(\"./commands/anomalies.js\")).registerAnomaliesCommands(program);\n },\n \"install-skills\": async () => {\n (await import(\"./commands/install-skills.js\")).registerInstallSkillsCommand(program);\n },\n version: async () => {\n (await import(\"./commands/version.js\")).registerVersionCommand(program);\n },\n cache: async () => {\n (await import(\"./commands/cache.js\")).registerCacheCommand(program);\n },\n feedback: async () => {\n (await import(\"./commands/feedback.js\")).registerFeedbackCommand(program);\n },\n quickstart: async () => {\n (await import(\"./commands/quickstart.js\")).registerQuickstartCommand(program);\n },\n grants: async () => {\n (await import(\"./commands/grants.js\")).registerGrantsCommands(program);\n },\n train: async () => {\n (await import(\"./commands/train.js\")).registerTrainCommands(program);\n },\n quota: async () => {\n (await import(\"./commands/quota.js\")).registerQuotaCommand(program);\n },\n games: async () => {\n (await import(\"./commands/games.js\")).registerGamesCommands(program);\n },\n enterprise: async () => {\n (await import(\"./commands/enterprise.js\")).registerEnterpriseCommands(program);\n },\n plugins: async () => {\n registerPluginsCommand(program, pluginManager);\n },\n };\n\n // \"Did you mean?\" suggestions for unknown commands\n function levenshtein(a: string, b: string): number {\n const m = a.length,\n n = b.length;\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n );\n const cell = (r: number, c: number): number => dp[r]?.[c] ?? 0;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n (dp[i] as number[])[j] =\n a[i - 1] === b[j - 1]\n ? cell(i - 1, j - 1)\n : 1 + Math.min(cell(i - 1, j), cell(i, j - 1), cell(i - 1, j - 1));\n }\n }\n return cell(m, n);\n }\n\n program.on(\"command:*\", (operands: string[]) => {\n const cmd = operands[0] ?? \"\";\n const names = Object.keys(commandLoaders);\n const best = names\n .map((name) => ({ name, d: levenshtein(cmd, name) }))\n .sort((a, b) => a.d - b.d)[0];\n console.error(`Error: Unknown command \"${cmd}\".`);\n if (best && best.d <= 3) console.error(`Did you mean: gpc ${best.name}?`);\n console.error(`Run \"gpc --help\" to see all commands.`);\n process.exit(2);\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 const REGISTRY_URL =\n \"https://raw.githubusercontent.com/yasserstudio/gpc-plugins/main/registry.json\";\n\n interface RegistryPlugin {\n name: string;\n description: string;\n version: string;\n author?: string;\n tags?: string[];\n }\n\n cmd\n .command(\"search [query]\")\n .description(\"Search the GPC plugin registry\")\n .action(async (query?: string) => {\n try {\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) throw new Error(`Registry fetch failed: ${res.status}`);\n const plugins = (await res.json()) as RegistryPlugin[];\n const filtered = query\n ? plugins.filter(\n (p) =>\n p.name.includes(query) ||\n p.description?.toLowerCase().includes(query.toLowerCase()),\n )\n : plugins;\n\n if (filtered.length === 0) {\n console.log(`No plugins found${query ? ` matching \"${query}\"` : \"\"}.`);\n return;\n }\n\n for (const p of filtered) {\n console.log(` ${p.name}@${p.version}`);\n if (p.description) console.log(` ${p.description}`);\n }\n console.log(`\\nInstall: gpc plugins install <name>`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n cmd\n .command(\"install <name>\")\n .description(\"Install a plugin from npm\")\n .action(async (name: string) => {\n const { execSync } = await import(\"node:child_process\");\n console.log(`Installing plugin \"${name}\"...`);\n try {\n execSync(`npm install -g ${name}`, { stdio: \"inherit\" });\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`\\nPlugin \"${name}\" installed and approved. It will be loaded on next run.`);\n console.log(`Configure it in .gpcrc.json: { \"plugins\": [\"${name}\"] }`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n cmd\n .command(\"uninstall <name>\")\n .description(\"Uninstall a plugin and revoke its approval\")\n .action(async (name: string) => {\n const { execSync } = await import(\"node:child_process\");\n console.log(`Uninstalling plugin \"${name}\"...`);\n try {\n execSync(`npm uninstall -g ${name}`, { stdio: \"inherit\" });\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n await revokePluginApproval(name);\n console.log(`\\nPlugin \"${name}\" uninstalled and approval revoked.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\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 (\n error instanceof Error && \"code\" in error && typeof (error as TypedError).code === \"string\"\n );\n}\n\nconst AUTH_KEYWORDS = [\"AUTH\", \"UNAUTHENTICATED\", \"PERMISSION_DENIED\", \"401\", \"403\"];\n\nfunction isAuthRelatedError(error: unknown): boolean {\n if (isTypedError(error)) {\n if (error.exitCode === 3) return true;\n if (error.code && AUTH_KEYWORDS.some((k) => error.code?.includes(k))) return true;\n }\n const msg = error instanceof Error ? error.message : String(error);\n return AUTH_KEYWORDS.some((k) => msg.includes(k));\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 const authHint = isAuthRelatedError(error)\n ? \"\\n→ Run gpc doctor to diagnose your credentials.\"\n : \"\";\n\n if (isTypedError(error)) {\n console.error(`Error [${error.code}]: ${error.message}`);\n if (error.suggestion) {\n console.error(`Suggestion: ${error.suggestion}`);\n }\n if (authHint) console.error(authHint);\n return error.exitCode ?? 1;\n }\n\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n if (authHint) console.error(authHint);\n return 1;\n}\n"],"mappings":"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","names":["_","loader"]}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/commands/completion.ts
|
|
4
|
-
var SUPPORTED_SHELLS = [
|
|
4
|
+
var SUPPORTED_SHELLS = [
|
|
5
|
+
"bash",
|
|
6
|
+
"zsh",
|
|
7
|
+
"fish",
|
|
8
|
+
"powershell"
|
|
9
|
+
];
|
|
5
10
|
function getCommandTree() {
|
|
6
11
|
return {
|
|
7
12
|
auth: {
|
|
@@ -320,17 +325,21 @@ function generateBashCompletions() {
|
|
|
320
325
|
for (const [cmd, def] of Object.entries(tree)) {
|
|
321
326
|
if (def.subcommands) {
|
|
322
327
|
const subNames = Object.keys(def.subcommands).join(" ");
|
|
323
|
-
caseEntries.push(
|
|
328
|
+
caseEntries.push(
|
|
329
|
+
` ${cmd})
|
|
324
330
|
COMPREPLY=( $(compgen -W "${subNames}" -- "\${cur}") )
|
|
325
331
|
return 0
|
|
326
|
-
;;`
|
|
332
|
+
;;`
|
|
333
|
+
);
|
|
327
334
|
for (const [sub, subDef] of Object.entries(def.subcommands)) {
|
|
328
335
|
if (subDef.subcommands) {
|
|
329
336
|
const subSubNames = Object.keys(subDef.subcommands).join(" ");
|
|
330
|
-
caseEntries.push(
|
|
337
|
+
caseEntries.push(
|
|
338
|
+
` ${sub})
|
|
331
339
|
COMPREPLY=( $(compgen -W "${subSubNames}" -- "\${cur}") )
|
|
332
340
|
return 0
|
|
333
|
-
;;`
|
|
341
|
+
;;`
|
|
342
|
+
);
|
|
334
343
|
}
|
|
335
344
|
}
|
|
336
345
|
}
|
|
@@ -374,9 +383,11 @@ ${topEntries}
|
|
|
374
383
|
arrayDefs.push(` ${varName}=(
|
|
375
384
|
${entries}
|
|
376
385
|
)`);
|
|
377
|
-
caseBranches.push(
|
|
386
|
+
caseBranches.push(
|
|
387
|
+
` ${cmd})
|
|
378
388
|
_describe -t ${varName} '${cmd} commands' ${varName}
|
|
379
|
-
;;`
|
|
389
|
+
;;`
|
|
390
|
+
);
|
|
380
391
|
for (const [sub, subDef] of Object.entries(def.subcommands)) {
|
|
381
392
|
if (subDef.subcommands) {
|
|
382
393
|
const subVarName = `${cmd.replace(/-/g, "_")}_${sub.replace(/-/g, "_")}_commands`;
|
|
@@ -394,9 +405,11 @@ ${subEntries}
|
|
|
394
405
|
for (const [sub, subDef] of Object.entries(def.subcommands)) {
|
|
395
406
|
if (subDef.subcommands) {
|
|
396
407
|
const subVarName = `${cmd.replace(/-/g, "_")}_${sub.replace(/-/g, "_")}_commands`;
|
|
397
|
-
level3Cases.push(
|
|
408
|
+
level3Cases.push(
|
|
409
|
+
` ${sub})
|
|
398
410
|
_describe -t ${subVarName} '${sub} commands' ${subVarName}
|
|
399
|
-
;;`
|
|
411
|
+
;;`
|
|
412
|
+
);
|
|
400
413
|
}
|
|
401
414
|
}
|
|
402
415
|
}
|
|
@@ -559,4 +572,4 @@ export {
|
|
|
559
572
|
getCommandTree,
|
|
560
573
|
registerCompletionCommand
|
|
561
574
|
};
|
|
562
|
-
//# sourceMappingURL=completion-
|
|
575
|
+
//# sourceMappingURL=completion-BCHRJSAT.js.map
|