@gpc-cli/cli 0.9.33 → 0.9.35
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 +21 -16
- package/dist/anomalies-QZJGQXTZ.js +59 -0
- package/dist/anomalies-QZJGQXTZ.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-4UPTLW37.js} +2 -3
- package/dist/{audit-A4BP27DN.js.map → audit-4UPTLW37.js.map} +1 -1
- package/dist/{auth-QSDK7NUO.js → auth-KPVEGAWV.js} +101 -9
- package/dist/auth-KPVEGAWV.js.map +1 -0
- package/dist/bin.js +14 -3
- package/dist/bin.js.map +1 -1
- package/dist/{bundle-7IF5FIB4.js → bundle-7XYHNVNF.js} +27 -2
- package/dist/bundle-7XYHNVNF.js.map +1 -0
- package/dist/{cache-SHWAVON6.js → cache-K23N6GJR.js} +1 -1
- package/dist/cache-K23N6GJR.js.map +1 -0
- package/dist/{chunk-UH3TMIAL.js → chunk-43SH6XEJ.js} +5 -5
- package/dist/{chunk-UH3TMIAL.js.map → chunk-43SH6XEJ.js.map} +1 -1
- package/dist/chunk-7BXCQKJG.js +37 -0
- package/dist/chunk-7BXCQKJG.js.map +1 -0
- package/dist/{chunk-DMMFPBYF.js → chunk-DDTPDKTB.js} +116 -31
- package/dist/chunk-DDTPDKTB.js.map +1 -0
- package/dist/{config-2L7QUYWP.js → config-REB7NINL.js} +14 -4
- package/dist/config-REB7NINL.js.map +1 -0
- package/dist/{data-safety-GDPKV5PN.js → data-safety-GN5VBKAK.js} +1 -1
- package/dist/data-safety-GN5VBKAK.js.map +1 -0
- package/dist/{doctor-UZB2UB5X.js → doctor-QDIFTXNB.js} +54 -6
- package/dist/doctor-QDIFTXNB.js.map +1 -0
- package/dist/enterprise-IH5HXYRB.js +65 -0
- package/dist/enterprise-IH5HXYRB.js.map +1 -0
- package/dist/{feedback-W5MZMRF2.js → feedback-NVGHRU7A.js} +3 -3
- package/dist/feedback-NVGHRU7A.js.map +1 -0
- package/dist/games-X57AGM3E.js +80 -0
- package/dist/games-X57AGM3E.js.map +1 -0
- package/dist/grants-CXTTYKR3.js +123 -0
- package/dist/grants-CXTTYKR3.js.map +1 -0
- package/dist/{iap-BBHF7BLZ.js → iap-MBDD7VWP.js} +6 -38
- package/dist/iap-MBDD7VWP.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{listings-VSBHQY5H.js → listings-7TWCGGMS.js} +94 -9
- package/dist/listings-7TWCGGMS.js.map +1 -0
- package/dist/{migrate-XQV7P4R7.js → migrate-OHN2FDY6.js} +13 -3
- package/dist/migrate-OHN2FDY6.js.map +1 -0
- package/dist/{publish-I6WJGR4S.js → publish-XM43UA5R.js} +2 -1
- package/dist/publish-XM43UA5R.js.map +1 -0
- package/dist/{purchases-YRO6B7M6.js → purchases-WIDU3FDQ.js} +28 -1
- package/dist/purchases-WIDU3FDQ.js.map +1 -0
- package/dist/quickstart-N7FXM5RQ.js +87 -0
- package/dist/quickstart-N7FXM5RQ.js.map +1 -0
- package/dist/quota-SNUI75NM.js +53 -0
- package/dist/quota-SNUI75NM.js.map +1 -0
- package/dist/{releases-ANC54YWF.js → releases-YRYM7JXC.js} +5 -1
- package/dist/releases-YRYM7JXC.js.map +1 -0
- package/dist/{reports-N5X66IUN.js → reports-YOT4DQGL.js} +1 -1
- package/dist/reports-YOT4DQGL.js.map +1 -0
- package/dist/{reviews-GJAQ5OVC.js → reviews-NN7YQITF.js} +59 -3
- package/dist/reviews-NN7YQITF.js.map +1 -0
- package/dist/{status-6Y2CHHVD.js → status-L5S2FGZ4.js} +45 -5
- package/dist/status-L5S2FGZ4.js.map +1 -0
- package/dist/{subscriptions-Z5ZPVUFM.js → subscriptions-OXAE7SNS.js} +32 -1
- package/dist/subscriptions-OXAE7SNS.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-6XSZRXSU.js} +3 -3
- package/dist/{update-NIVJLUNH.js.map → update-6XSZRXSU.js.map} +1 -1
- package/dist/{validate-MHLPENCM.js → validate-NC4MWKOB.js} +9 -4
- package/dist/validate-NC4MWKOB.js.map +1 -0
- package/dist/{version-7AI5IHVK.js → version-2X32UAAE.js} +3 -3
- package/dist/version-2X32UAAE.js.map +1 -0
- package/dist/{vitals-KSNAVN5F.js → vitals-LFL75LA6.js} +135 -4
- package/dist/vitals-LFL75LA6.js.map +1 -0
- package/package.json +8 -4
- 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-DMMFPBYF.js.map +0 -1
- package/dist/config-2L7QUYWP.js.map +0 -1
- package/dist/data-safety-GDPKV5PN.js.map +0 -1
- package/dist/doctor-UZB2UB5X.js.map +0 -1
- package/dist/feedback-W5MZMRF2.js.map +0 -1
- package/dist/iap-BBHF7BLZ.js.map +0 -1
- package/dist/listings-VSBHQY5H.js.map +0 -1
- package/dist/migrate-XQV7P4R7.js.map +0 -1
- package/dist/publish-I6WJGR4S.js.map +0 -1
- package/dist/purchases-YRO6B7M6.js.map +0 -1
- package/dist/releases-ANC54YWF.js.map +0 -1
- package/dist/reports-N5X66IUN.js.map +0 -1
- package/dist/reviews-GJAQ5OVC.js.map +0 -1
- package/dist/status-6Y2CHHVD.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/validate-MHLPENCM.js.map +0 -1
- package/dist/version-7AI5IHVK.js.map +0 -1
- package/dist/vitals-KSNAVN5F.js.map +0 -1
|
@@ -21,7 +21,7 @@ function registerConfigCommands(program) {
|
|
|
21
21
|
const initialConfig = {};
|
|
22
22
|
if (isInteractive(program)) {
|
|
23
23
|
console.log("\nGPC Setup Wizard\n");
|
|
24
|
-
|
|
24
|
+
const app = await promptInput("Default package name (e.g. com.example.app, blank to skip)");
|
|
25
25
|
if (app) {
|
|
26
26
|
if (!ANDROID_PACKAGE_RE.test(app)) {
|
|
27
27
|
console.error(
|
|
@@ -36,7 +36,7 @@ function registerConfigCommands(program) {
|
|
|
36
36
|
"service-account"
|
|
37
37
|
);
|
|
38
38
|
if (authMethod === "service-account") {
|
|
39
|
-
let saPath
|
|
39
|
+
let saPath;
|
|
40
40
|
while (true) {
|
|
41
41
|
saPath = await promptInput("Path to service account JSON key file");
|
|
42
42
|
if (!saPath) {
|
|
@@ -74,9 +74,19 @@ Configuration file created: ${path}`);
|
|
|
74
74
|
if (configured.length > 0) {
|
|
75
75
|
console.log(` ${configured.join(" \xB7 ")}`);
|
|
76
76
|
}
|
|
77
|
-
console.log("\nRun `gpc doctor` to verify your setup.");
|
|
78
77
|
writeAuditLog(createAuditEntry("config init", { path })).catch(() => {
|
|
79
78
|
});
|
|
79
|
+
console.log("\nVerifying setup...");
|
|
80
|
+
try {
|
|
81
|
+
const { registerDoctorCommand } = await import("./doctor-QDIFTXNB.js");
|
|
82
|
+
const { Command } = await import("commander");
|
|
83
|
+
const doctorProgram = new Command();
|
|
84
|
+
doctorProgram.option("-o, --output <format>", "Output format").option("-j, --json", "JSON mode");
|
|
85
|
+
registerDoctorCommand(doctorProgram);
|
|
86
|
+
await doctorProgram.parseAsync(["node", "gpc", "doctor"]);
|
|
87
|
+
} catch {
|
|
88
|
+
console.log("Run `gpc doctor` to verify your setup.");
|
|
89
|
+
}
|
|
80
90
|
});
|
|
81
91
|
config.command("show").description("Display resolved configuration").action(async () => {
|
|
82
92
|
const resolved = await loadConfig();
|
|
@@ -94,4 +104,4 @@ Configuration file created: ${path}`);
|
|
|
94
104
|
export {
|
|
95
105
|
registerConfigCommands
|
|
96
106
|
};
|
|
97
|
-
//# sourceMappingURL=config-
|
|
107
|
+
//# sourceMappingURL=config-REB7NINL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/config.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig, setConfigValue, getUserConfigPath, initConfig } from \"@gpc-cli/config\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { formatOutput, writeAuditLog, createAuditEntry } from \"@gpc-cli/core\";\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isInteractive, promptInput, promptSelect, promptConfirm } from \"../prompt.js\";\n\nconst ANDROID_PACKAGE_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$/;\n\nexport function registerConfigCommands(program: Command): void {\n const config = program.command(\"config\").description(\"Manage configuration\");\n\n config\n .command(\"init\")\n .description(\"Create a configuration file\")\n .option(\"--global\", \"Create in user config directory (~/.config/gpc/)\")\n .action(async (_options: { global?: boolean }) => {\n const initialConfig: Record<string, unknown> = {};\n\n if (isInteractive(program)) {\n console.log(\"\\nGPC Setup Wizard\\n\");\n\n // Package name\n const app = await promptInput(\"Default package name (e.g. com.example.app, blank to skip)\");\n if (app) {\n if (!ANDROID_PACKAGE_RE.test(app)) {\n console.error(\n ` Warning: \"${app}\" doesn't look like a valid Android package name — continuing anyway`,\n );\n }\n initialConfig[\"app\"] = app;\n }\n\n // Auth method\n const authMethod = await promptSelect(\n \"Authentication method:\",\n [\"service-account\", \"adc\", \"skip\"],\n \"service-account\",\n );\n\n if (authMethod === \"service-account\") {\n let saPath: string;\n while (true) {\n saPath = await promptInput(\"Path to service account JSON key file\");\n if (!saPath) {\n console.log(\" Skipping service account setup.\");\n break;\n }\n const resolved = resolve(saPath);\n if (existsSync(resolved)) {\n initialConfig[\"auth\"] = { serviceAccount: saPath };\n break;\n }\n console.error(` File not found: ${resolved}`);\n const retry = await promptConfirm(\"Try a different path?\");\n if (!retry) break;\n }\n } else if (authMethod === \"adc\") {\n console.log(\n \" Using Application Default Credentials — run `gcloud auth application-default login` if not already set up.\",\n );\n }\n\n // Output format\n const output = await promptSelect(\n \"Default output format:\",\n [\"table\", \"json\", \"yaml\", \"markdown\"],\n \"table\",\n );\n if (output !== \"table\") initialConfig[\"output\"] = output;\n }\n\n const path = await initConfig(initialConfig as GpcConfig);\n\n // Summary\n const configured: string[] = [];\n if (initialConfig[\"app\"]) configured.push(`app: ${initialConfig[\"app\"]}`);\n if (initialConfig[\"auth\"]) configured.push(\"auth: service account\");\n if (initialConfig[\"output\"]) configured.push(`output: ${initialConfig[\"output\"]}`);\n\n console.log(`\\nConfiguration file created: ${path}`);\n if (configured.length > 0) {\n console.log(` ${configured.join(\" · \")}`);\n }\n\n writeAuditLog(createAuditEntry(\"config init\", { path })).catch(() => {});\n\n // Run doctor inline to verify setup\n console.log(\"\\nVerifying setup...\");\n try {\n const { registerDoctorCommand } = await import(\"./doctor.js\");\n const { Command } = await import(\"commander\");\n const doctorProgram = new Command();\n doctorProgram\n .option(\"-o, --output <format>\", \"Output format\")\n .option(\"-j, --json\", \"JSON mode\");\n registerDoctorCommand(doctorProgram);\n await doctorProgram.parseAsync([\"node\", \"gpc\", \"doctor\"]);\n } catch {\n // Doctor failures should not prevent config init from succeeding\n console.log(\"Run `gpc doctor` to verify your setup.\");\n }\n });\n\n config\n .command(\"show\")\n .description(\"Display resolved configuration\")\n .action(async () => {\n const resolved = await loadConfig();\n const format = getOutputFormat(program, resolved);\n console.log(formatOutput(resolved, format));\n });\n\n config\n .command(\"set <key> <value>\")\n .description(\"Set a configuration value\")\n .action(async (key: string, value: string) => {\n await setConfigValue(key, value);\n console.log(`Set ${key} = ${value}`);\n });\n\n config\n .command(\"path\")\n .description(\"Show configuration file path\")\n .action(() => {\n console.log(getUserConfigPath());\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/data-safety.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n importDataSafety,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth });\n}\n\nexport function registerDataSafetyCommands(program: Command): void {\n const dataSafety = program\n .command(\"data-safety\")\n .description(\"Manage data safety declarations\");\n\n // Get — not supported by Google Play API (no GET endpoint for data safety)\n dataSafety\n .command(\"get\")\n .description(\"Get the current data safety declaration\")\n .action(async () => {\n console.error(\"Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.\");\n console.error(\"\");\n console.error(\"Data safety labels can only be updated (not read) via the API.\");\n console.error(\"To view your current data safety declaration, use the Google Play Console:\");\n console.error(\" https://play.google.com/console → App content → Data safety\");\n console.error(\"\");\n console.error(\"To update data safety via the API, use: gpc data-safety update --file <csv-file>\");\n process.exit(2);\n });\n\n // Update\n dataSafety\n .command(\"update\")\n .description(\"Update data safety declaration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to data safety JSON file\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"data-safety update\",\n action: \"update data safety from\",\n target: options.file,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await importDataSafety(client, packageName, options.file);\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Export — not supported (no GET endpoint)\n dataSafety\n .command(\"export\")\n .description(\"Export data safety declaration to a JSON file\")\n .option(\"--output <path>\", \"Output file path\", \"data-safety.json\")\n .action(async () => {\n console.error(\"Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.\");\n console.error(\"Data safety labels cannot be exported via the API.\");\n console.error(\"\");\n console.error(\"To export your data safety declaration, use the Google Play Console:\");\n console.error(\" App content → Data safety → Export to CSV\");\n process.exit(2);\n });\n}\n"],"mappings":";;;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAIP,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,gBAAgB,EAAE,KAAK,CAAC;AACjC;AAEO,SAAS,2BAA2B,SAAwB;AACjE,QAAM,aAAa,QAChB,QAAQ,aAAa,EACrB,YAAY,iCAAiC;AAGhD,aACG,QAAQ,KAAK,EACb,YAAY,yCAAyC,EACrD,OAAO,YAAY;AAClB,YAAQ,MAAM,oGAAoG;AAClH,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,gEAAgE;AAC9E,YAAQ,MAAM,4EAA4E;AAC1F,YAAQ,MAAM,yEAA+D;AAC7E,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,kFAAkF;AAChG,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGH,aACG,QAAQ,QAAQ,EAChB,YAAY,iDAAiD,EAC7D,eAAe,iBAAiB,+BAA+B,EAC/D,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,QAAQ;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,QAAQ,aAAa,QAAQ,IAAI;AACvE,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,aACG,QAAQ,QAAQ,EAChB,YAAY,+CAA+C,EAC3D,OAAO,mBAAmB,oBAAoB,kBAAkB,EAChE,OAAO,YAAY;AAClB,YAAQ,MAAM,oGAAoG;AAClH,YAAQ,MAAM,oDAAoD;AAClE,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,sEAAsE;AACpF,YAAQ,MAAM,uDAA6C;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;","names":[]}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
green,
|
|
4
|
+
red,
|
|
5
|
+
yellow
|
|
6
|
+
} from "./chunk-7BXCQKJG.js";
|
|
2
7
|
|
|
3
8
|
// src/commands/doctor.ts
|
|
4
9
|
import { loadConfig, getCacheDir, getConfigDir } from "@gpc-cli/config";
|
|
@@ -13,11 +18,11 @@ var INFO = "-";
|
|
|
13
18
|
function icon(status) {
|
|
14
19
|
switch (status) {
|
|
15
20
|
case "pass":
|
|
16
|
-
return PASS;
|
|
21
|
+
return green(PASS);
|
|
17
22
|
case "fail":
|
|
18
|
-
return FAIL;
|
|
23
|
+
return red(FAIL);
|
|
19
24
|
case "warn":
|
|
20
|
-
return WARN;
|
|
25
|
+
return yellow(WARN);
|
|
21
26
|
case "info":
|
|
22
27
|
return INFO;
|
|
23
28
|
}
|
|
@@ -55,8 +60,34 @@ function checkProxy(url) {
|
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
62
|
}
|
|
63
|
+
async function applyFix(check) {
|
|
64
|
+
switch (check.name) {
|
|
65
|
+
case "config-dir":
|
|
66
|
+
case "cache-dir": {
|
|
67
|
+
const dirMatch = check.message.match(/: (.+)$/);
|
|
68
|
+
if (!dirMatch?.[1]) return null;
|
|
69
|
+
const { mkdir } = await import("fs/promises");
|
|
70
|
+
await mkdir(dirMatch[1], { recursive: true, mode: check.name === "cache-dir" ? 448 : 493 });
|
|
71
|
+
return `Created ${dirMatch[1]}`;
|
|
72
|
+
}
|
|
73
|
+
case "service-account-permissions": {
|
|
74
|
+
const saPath = check.suggestion?.match(/chmod 600 (.+)$/)?.[1];
|
|
75
|
+
if (!saPath) return null;
|
|
76
|
+
const { chmod } = await import("fs/promises");
|
|
77
|
+
await chmod(saPath, 384);
|
|
78
|
+
return `Fixed permissions on ${saPath}`;
|
|
79
|
+
}
|
|
80
|
+
case "config": {
|
|
81
|
+
const { initConfig } = await import("@gpc-cli/config");
|
|
82
|
+
await initConfig({});
|
|
83
|
+
return "Initialized config file";
|
|
84
|
+
}
|
|
85
|
+
default:
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
58
89
|
function registerDoctorCommand(program) {
|
|
59
|
-
program.command("doctor").description("Verify setup and connectivity").action(async (
|
|
90
|
+
program.command("doctor").description("Verify setup and connectivity").option("--fix", "Attempt to auto-fix failing checks").action(async (opts, cmd) => {
|
|
60
91
|
const results = [];
|
|
61
92
|
const parentOpts = cmd.parent?.opts() ?? {};
|
|
62
93
|
const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
|
|
@@ -282,6 +313,22 @@ function registerDoctorCommand(program) {
|
|
|
282
313
|
});
|
|
283
314
|
}
|
|
284
315
|
}
|
|
316
|
+
if (opts["fix"]) {
|
|
317
|
+
for (const r of results) {
|
|
318
|
+
if (r.status === "fail" || r.status === "warn") {
|
|
319
|
+
try {
|
|
320
|
+
const fixMsg = await applyFix(r);
|
|
321
|
+
if (fixMsg) {
|
|
322
|
+
console.log(` ${green("\u2192")} Fixed: ${fixMsg}`);
|
|
323
|
+
r.status = "pass";
|
|
324
|
+
r.message += " (fixed)";
|
|
325
|
+
}
|
|
326
|
+
} catch (err) {
|
|
327
|
+
console.error(` ${red("\u2717")} Could not fix "${r.name}": ${err instanceof Error ? err.message : String(err)}`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
285
332
|
const errors = results.filter((r) => r.status === "fail").length;
|
|
286
333
|
const warnings = results.filter((r) => r.status === "warn").length;
|
|
287
334
|
const passed = results.filter((r) => r.status === "pass").length;
|
|
@@ -309,7 +356,8 @@ function registerDoctorCommand(program) {
|
|
|
309
356
|
} else if (warnings > 0) {
|
|
310
357
|
console.log("\nAll checks passed with warnings.");
|
|
311
358
|
} else {
|
|
312
|
-
console.log(
|
|
359
|
+
console.log(`
|
|
360
|
+
${green("\u2713")} Ready. Try: gpc status`);
|
|
313
361
|
}
|
|
314
362
|
});
|
|
315
363
|
}
|
|
@@ -319,4 +367,4 @@ export {
|
|
|
319
367
|
checkProxy,
|
|
320
368
|
registerDoctorCommand
|
|
321
369
|
};
|
|
322
|
-
//# sourceMappingURL=doctor-
|
|
370
|
+
//# sourceMappingURL=doctor-QDIFTXNB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig, getCacheDir, getConfigDir } from \"@gpc-cli/config\";\nimport { green, red, yellow } from \"../colors.js\";\nimport { resolveAuth, AuthError } from \"@gpc-cli/auth\";\nimport { existsSync, accessSync, statSync, constants } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { lookup } from \"node:dns/promises\";\n\nexport interface CheckResult {\n name: string;\n status: \"pass\" | \"fail\" | \"warn\" | \"info\";\n message: string;\n suggestion?: string;\n}\n\nconst PASS = \"\\u2713\";\nconst FAIL = \"\\u2717\";\nconst WARN = \"\\u26A0\";\nconst INFO = \"-\";\n\nfunction icon(status: CheckResult[\"status\"]): string {\n switch (status) {\n case \"pass\":\n return green(PASS);\n case \"fail\":\n return red(FAIL);\n case \"warn\":\n return yellow(WARN);\n case \"info\":\n return INFO;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pure, testable check helpers\n// ---------------------------------------------------------------------------\n\nconst ANDROID_PACKAGE_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$/;\n\nexport function checkNodeVersion(nodeVersion: string): CheckResult {\n const major = parseInt(nodeVersion.split(\".\")[0] ?? \"0\", 10);\n return major >= 20\n ? { name: \"node\", status: \"pass\", message: `Node.js ${nodeVersion}` }\n : {\n name: \"node\",\n status: \"fail\",\n message: `Node.js ${nodeVersion} (requires >=20)`,\n suggestion: \"Upgrade Node.js to v20 or later: https://nodejs.org\",\n };\n}\n\nexport function checkPackageName(app: string | undefined): CheckResult | null {\n if (!app) return null;\n return ANDROID_PACKAGE_RE.test(app)\n ? { name: \"package-name\", status: \"pass\", message: `Package name format OK: ${app}` }\n : {\n name: \"package-name\",\n status: \"warn\",\n message: `Package name may be invalid: ${app}`,\n suggestion:\n \"Android package names must have 2+ dot-separated segments, each starting with a letter (e.g. com.example.app)\",\n };\n}\n\nexport function checkProxy(url: string | undefined): CheckResult | null {\n if (!url) return null;\n try {\n new URL(url);\n return { name: \"proxy\", status: \"pass\", message: `Proxy configured: ${url}` };\n } catch {\n return {\n name: \"proxy\",\n status: \"warn\",\n message: `Invalid proxy URL: ${url}`,\n suggestion: \"Set HTTPS_PROXY to a valid URL (e.g. http://proxy.example.com:8080)\",\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nasync function applyFix(check: CheckResult): Promise<string | null> {\n switch (check.name) {\n case \"config-dir\":\n case \"cache-dir\": {\n const dirMatch = check.message.match(/: (.+)$/);\n if (!dirMatch?.[1]) return null;\n const { mkdir } = await import(\"node:fs/promises\");\n await mkdir(dirMatch[1], { recursive: true, mode: check.name === \"cache-dir\" ? 0o700 : 0o755 });\n return `Created ${dirMatch[1]}`;\n }\n case \"service-account-permissions\": {\n const saPath = check.suggestion?.match(/chmod 600 (.+)$/)?.[1];\n if (!saPath) return null;\n const { chmod } = await import(\"node:fs/promises\");\n await chmod(saPath, 0o600);\n return `Fixed permissions on ${saPath}`;\n }\n case \"config\": {\n const { initConfig } = await import(\"@gpc-cli/config\");\n await initConfig({});\n return \"Initialized config file\";\n }\n default:\n return null;\n }\n}\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Verify setup and connectivity\")\n .option(\"--fix\", \"Attempt to auto-fix failing checks\")\n .action(async (opts, cmd) => {\n const results: CheckResult[] = [];\n const parentOpts = cmd.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n // 1. Node.js version\n results.push(checkNodeVersion(process.versions.node));\n\n // 2. Config file\n let config;\n try {\n config = await loadConfig();\n results.push({ name: \"config\", status: \"pass\", message: \"Configuration loaded\" });\n if (config.app) {\n results.push({\n name: \"default-app\",\n status: \"pass\",\n message: `Default app: ${config.app}`,\n });\n // 2b. Package name format\n const pkgCheck = checkPackageName(config.app);\n if (pkgCheck) results.push(pkgCheck);\n } else {\n results.push({\n name: \"default-app\",\n status: \"info\",\n message: \"No default app configured\",\n suggestion: \"Use --app flag or run: gpc config set app <package>\",\n });\n }\n } catch {\n results.push({\n name: \"config\",\n status: \"fail\",\n message: \"Configuration could not be loaded\",\n suggestion: \"Run gpc config init to create a config file, or check .gpcrc.json for syntax errors\",\n });\n }\n\n // 3. Config directory permissions\n const configDir = getConfigDir();\n try {\n if (existsSync(configDir)) {\n accessSync(configDir, constants.R_OK | constants.W_OK);\n results.push({\n name: \"config-dir\",\n status: \"pass\",\n message: `Config directory: ${configDir}`,\n });\n } else {\n results.push({\n name: \"config-dir\",\n status: \"info\",\n message: `Config directory does not exist yet: ${configDir}`,\n });\n }\n } catch {\n results.push({\n name: \"config-dir\",\n status: \"warn\",\n message: `Config directory not writable: ${configDir}`,\n suggestion: `Fix permissions: chmod 755 ${configDir}`,\n });\n }\n\n // 4. Cache directory permissions\n const cacheDir = getCacheDir();\n try {\n if (existsSync(cacheDir)) {\n accessSync(cacheDir, constants.R_OK | constants.W_OK);\n results.push({\n name: \"cache-dir\",\n status: \"pass\",\n message: `Cache directory: ${cacheDir}`,\n });\n } else {\n results.push({\n name: \"cache-dir\",\n status: \"info\",\n message: `Cache directory does not exist yet: ${cacheDir}`,\n });\n }\n } catch {\n results.push({\n name: \"cache-dir\",\n status: \"warn\",\n message: `Cache directory not writable: ${cacheDir}`,\n suggestion: `Fix permissions: chmod 700 ${cacheDir}`,\n });\n }\n\n // 5. Service account file existence + permissions\n if (config?.auth?.serviceAccount) {\n const saValue = config.auth.serviceAccount;\n const looksLikePath = !saValue.trim().startsWith(\"{\");\n if (looksLikePath) {\n const saPath = resolve(saValue);\n if (existsSync(saPath)) {\n try {\n accessSync(saPath, constants.R_OK);\n results.push({\n name: \"service-account-file\",\n status: \"pass\",\n message: `Service account file: ${saPath}`,\n });\n } catch {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not readable: ${saPath}`,\n suggestion: `Fix permissions: chmod 600 ${saPath}`,\n });\n }\n\n // 5b. SA key file permissions (Unix only)\n if (process.platform !== \"win32\") {\n try {\n const mode = statSync(saPath).mode;\n const groupRead = (mode & 0o040) !== 0;\n const worldRead = (mode & 0o004) !== 0;\n if (groupRead || worldRead) {\n results.push({\n name: \"service-account-permissions\",\n status: \"warn\",\n message: `Service account file is group/world-readable (mode: ${(mode & 0o777).toString(8)})`,\n suggestion: `Restrict permissions: chmod 600 ${saPath}`,\n });\n } else {\n results.push({\n name: \"service-account-permissions\",\n status: \"pass\",\n message: `Service account file permissions OK (mode: ${(mode & 0o777).toString(8)})`,\n });\n }\n } catch {\n // stat failed — skip permission check\n }\n }\n } else {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not found: ${saPath}`,\n suggestion: \"Check the path in your config or GPC_SERVICE_ACCOUNT env var\",\n });\n }\n }\n }\n\n // 6. Profile validation\n const gpcProfile = process.env[\"GPC_PROFILE\"];\n if (gpcProfile && config) {\n if (config.profiles && gpcProfile in config.profiles) {\n results.push({\n name: \"profile\",\n status: \"pass\",\n message: `Profile \"${gpcProfile}\" found`,\n });\n } else {\n const available = config.profiles ? Object.keys(config.profiles).join(\", \") : \"\";\n results.push({\n name: \"profile\",\n status: \"fail\",\n message: `Profile \"${gpcProfile}\" not found`,\n suggestion: available\n ? `Available profiles: ${available}. Create with: gpc auth login --profile ${gpcProfile}`\n : `No profiles defined. Create one with: gpc auth login --profile ${gpcProfile}`,\n });\n }\n }\n\n // 7. Proxy configuration\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n const proxyCheck = checkProxy(proxyUrl);\n if (proxyCheck) results.push(proxyCheck);\n\n // 8. CA certificate\n const caCert = process.env[\"GPC_CA_CERT\"] || process.env[\"NODE_EXTRA_CA_CERTS\"];\n if (caCert) {\n if (existsSync(caCert)) {\n results.push({\n name: \"ca-cert\",\n status: \"pass\",\n message: `CA certificate: ${caCert}`,\n });\n } else {\n results.push({\n name: \"ca-cert\",\n status: \"warn\",\n message: `CA certificate file not found: ${caCert}`,\n suggestion: \"Check that GPC_CA_CERT points to an existing PEM file\",\n });\n }\n }\n\n // 9. DNS resolution — both API endpoints\n const dnsHosts = [\n \"androidpublisher.googleapis.com\",\n \"playdeveloperreporting.googleapis.com\",\n ];\n for (const host of dnsHosts) {\n try {\n await lookup(host);\n results.push({\n name: \"dns\",\n status: \"pass\",\n message: `DNS: ${host}`,\n });\n } catch {\n results.push({\n name: \"dns\",\n status: \"fail\",\n message: `Cannot resolve ${host}`,\n suggestion: \"Check your DNS settings and network connection\",\n });\n }\n }\n\n // 10. Authentication + API connectivity\n try {\n const authConfig = config ?? (await loadConfig());\n const client = await resolveAuth({\n serviceAccountPath: authConfig.auth?.serviceAccount,\n });\n results.push({\n name: \"auth\",\n status: \"pass\",\n message: `Authenticated as ${client.getClientEmail()}`,\n });\n\n await client.getAccessToken();\n results.push({\n name: \"api-connectivity\",\n status: \"pass\",\n message: \"API connectivity verified\",\n });\n } catch (error) {\n if (error instanceof AuthError) {\n results.push({\n name: \"auth\",\n status: \"fail\",\n message: `Authentication: ${error.message}`,\n suggestion: error.suggestion,\n });\n } else {\n results.push({\n name: \"api-connectivity\",\n status: \"fail\",\n message: \"API connectivity failed\",\n suggestion: \"Check your network connection and credentials\",\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Output\n // ---------------------------------------------------------------------------\n\n // Auto-fix failing checks if --fix was passed\n if (opts[\"fix\"]) {\n for (const r of results) {\n if (r.status === \"fail\" || r.status === \"warn\") {\n try {\n const fixMsg = await applyFix(r);\n if (fixMsg) {\n console.log(` ${green(\"→\")} Fixed: ${fixMsg}`);\n r.status = \"pass\";\n r.message += \" (fixed)\";\n }\n } catch (err) {\n console.error(` ${red(\"✗\")} Could not fix \"${r.name}\": ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n }\n }\n\n const errors = results.filter((r) => r.status === \"fail\").length;\n const warnings = results.filter((r) => r.status === \"warn\").length;\n const passed = results.filter((r) => r.status === \"pass\").length;\n\n if (jsonMode) {\n console.log(\n JSON.stringify({ success: errors === 0, errors, warnings, checks: results }, null, 2),\n );\n if (errors > 0) process.exit(1);\n return;\n }\n\n console.log(\"GPC Doctor\\n\");\n for (const r of results) {\n console.log(` ${icon(r.status)} ${r.message}`);\n if (r.suggestion && r.status !== \"pass\") {\n console.log(` ${r.suggestion}`);\n }\n }\n\n console.log(\n `\\n ${PASS} ${passed} passed ${WARN} ${warnings} warning${warnings !== 1 ? \"s\" : \"\"} ${FAIL} ${errors} failed`,\n );\n\n if (errors > 0) {\n console.log(\"\\nSome checks failed. Fix the issues above and run again.\");\n process.exit(1);\n } else if (warnings > 0) {\n console.log(\"\\nAll checks passed with warnings.\");\n } else {\n console.log(`\\n${green(\"✓\")} Ready. Try: gpc status`);\n }\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isDryRun,
|
|
4
|
+
printDryRun
|
|
5
|
+
} from "./chunk-Y3QZDAKS.js";
|
|
6
|
+
import {
|
|
7
|
+
getOutputFormat
|
|
8
|
+
} from "./chunk-ELXAK7GI.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/enterprise.ts
|
|
11
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
12
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
13
|
+
import { createEnterpriseClient } from "@gpc-cli/api";
|
|
14
|
+
import { listEnterpriseApps, createEnterpriseApp, formatOutput } from "@gpc-cli/core";
|
|
15
|
+
async function getClient() {
|
|
16
|
+
const config = await loadConfig();
|
|
17
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
18
|
+
return { client: createEnterpriseClient({ auth }), config };
|
|
19
|
+
}
|
|
20
|
+
function registerEnterpriseCommands(program) {
|
|
21
|
+
const enterprise = program.command("enterprise").description("Manage private enterprise apps via Managed Google Play").requiredOption("--org <id>", "Google Play organization ID");
|
|
22
|
+
enterprise.command("list").description("List private enterprise apps").action(async () => {
|
|
23
|
+
const { client, config } = await getClient();
|
|
24
|
+
const orgId = enterprise.opts()["org"];
|
|
25
|
+
const format = getOutputFormat(program, config);
|
|
26
|
+
try {
|
|
27
|
+
const result = await listEnterpriseApps(client, orgId);
|
|
28
|
+
if (result.length === 0 && format !== "json") {
|
|
29
|
+
console.log("No enterprise apps found.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(formatOutput(result, format));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
35
|
+
process.exit(4);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
enterprise.command("create").description("Create a new private enterprise app").requiredOption("--title <title>", "App title").option("--lang <code>", "Language code (default: en_US)", "en_US").action(async (options) => {
|
|
39
|
+
const { client, config } = await getClient();
|
|
40
|
+
const orgId = enterprise.opts()["org"];
|
|
41
|
+
const format = getOutputFormat(program, config);
|
|
42
|
+
if (isDryRun(program)) {
|
|
43
|
+
printDryRun(
|
|
44
|
+
{ command: "enterprise create", action: "create enterprise app", target: options.title },
|
|
45
|
+
format,
|
|
46
|
+
formatOutput
|
|
47
|
+
);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const result = await createEnterpriseApp(client, orgId, {
|
|
52
|
+
title: options.title,
|
|
53
|
+
languageCode: options.lang
|
|
54
|
+
});
|
|
55
|
+
console.log(formatOutput(result, format));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
|
+
process.exit(4);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
registerEnterpriseCommands
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=enterprise-IH5HXYRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/enterprise.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createEnterpriseClient } from \"@gpc-cli/api\";\nimport { listEnterpriseApps, createEnterpriseApp, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\n\nasync function getClient() {\n const config = await loadConfig();\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return { client: createEnterpriseClient({ auth }), config };\n}\n\nexport function registerEnterpriseCommands(program: Command): void {\n const enterprise = program\n .command(\"enterprise\")\n .description(\"Manage private enterprise apps via Managed Google Play\")\n .requiredOption(\"--org <id>\", \"Google Play organization ID\");\n\n enterprise\n .command(\"list\")\n .description(\"List private enterprise apps\")\n .action(async () => {\n const { client, config } = await getClient();\n const orgId = enterprise.opts()[\"org\"] as string;\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listEnterpriseApps(client, orgId);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No enterprise apps found.\");\n return;\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n enterprise\n .command(\"create\")\n .description(\"Create a new private enterprise app\")\n .requiredOption(\"--title <title>\", \"App title\")\n .option(\"--lang <code>\", \"Language code (default: en_US)\", \"en_US\")\n .action(async (options) => {\n const { client, config } = await getClient();\n const orgId = enterprise.opts()[\"org\"] as string;\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"enterprise create\", action: \"create enterprise app\", target: options.title as string },\n format,\n formatOutput,\n );\n return;\n }\n\n try {\n const result = await createEnterpriseApp(client, orgId, {\n title: options.title as string,\n languageCode: options.lang as string,\n });\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;;;;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,8BAA8B;AACvC,SAAS,oBAAoB,qBAAqB,oBAAoB;AAItE,eAAe,YAAY;AACzB,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,EAAE,QAAQ,uBAAuB,EAAE,KAAK,CAAC,GAAG,OAAO;AAC5D;AAEO,SAAS,2BAA2B,SAAwB;AACjE,QAAM,aAAa,QAChB,QAAQ,YAAY,EACpB,YAAY,wDAAwD,EACpE,eAAe,cAAc,6BAA6B;AAE7D,aACG,QAAQ,MAAM,EACd,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU;AAC3C,UAAM,QAAQ,WAAW,KAAK,EAAE,KAAK;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,QAAQ,KAAK;AACrD,UAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,gBAAQ,IAAI,2BAA2B;AACvC;AAAA,MACF;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,aACG,QAAQ,QAAQ,EAChB,YAAY,qCAAqC,EACjD,eAAe,mBAAmB,WAAW,EAC7C,OAAO,iBAAiB,kCAAkC,OAAO,EACjE,OAAO,OAAO,YAAY;AACzB,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU;AAC3C,UAAM,QAAQ,WAAW,KAAK,EAAE,KAAK;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE,EAAE,SAAS,qBAAqB,QAAQ,yBAAyB,QAAQ,QAAQ,MAAgB;AAAA,QACjG;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,QAAQ,OAAO;AAAA,QACtD,OAAO,QAAQ;AAAA,QACf,cAAc,QAAQ;AAAA,MACxB,CAAC;AACD,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
detectInstallMethod
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-43SH6XEJ.js";
|
|
5
5
|
import "./chunk-4O4D5SGL.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/feedback.ts
|
|
8
8
|
import { execFile } from "child_process";
|
|
9
9
|
function registerFeedbackCommand(program) {
|
|
10
10
|
program.command("feedback").description("Open a pre-filled GitHub issue with system diagnostics").option("--title <title>", "Issue title").action(async (opts) => {
|
|
11
|
-
const version =
|
|
11
|
+
const version = "0.9.35";
|
|
12
12
|
const body = [
|
|
13
13
|
"**GPC version:** " + version,
|
|
14
14
|
"**Node:** " + process.version,
|
|
@@ -43,4 +43,4 @@ ${url}`);
|
|
|
43
43
|
export {
|
|
44
44
|
registerFeedbackCommand
|
|
45
45
|
};
|
|
46
|
-
//# sourceMappingURL=feedback-
|
|
46
|
+
//# sourceMappingURL=feedback-NVGHRU7A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/feedback.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { execFile } from \"node:child_process\";\nimport { detectInstallMethod } from \"../updater.js\";\n\nexport function registerFeedbackCommand(program: Command): void {\n program\n .command(\"feedback\")\n .description(\"Open a pre-filled GitHub issue with system diagnostics\")\n .option(\"--title <title>\", \"Issue title\")\n .action(async (opts) => {\n const version = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n const body = [\n \"**GPC version:** \" + version,\n \"**Node:** \" + process.version,\n \"**Platform:** \" + process.platform + \"/\" + process.arch,\n \"**Install method:** \" + detectInstallMethod(),\n \"\",\n \"**Describe the issue:**\",\n \"<!-- Replace this with your bug description -->\",\n ].join(\"\\n\");\n const params = new URLSearchParams({\n title: opts.title ?? \"Bug report\",\n body,\n labels: \"bug\",\n });\n const url = `https://github.com/yasserstudio/gpc/issues/new?${params}`;\n if (process.platform === \"win32\") {\n execFile(\"cmd\", [\"/c\", \"start\", \"\", url], (err) => {\n if (err) console.log(`Open in your browser:\\n${url}`);\n else console.log(\"Opened GitHub issue form in your browser.\");\n });\n } else {\n const cmd = process.platform === \"darwin\" ? \"open\" : \"xdg-open\";\n execFile(cmd, [url], (err) => {\n if (err) console.log(`Open in your browser:\\n${url}`);\n else console.log(\"Opened GitHub issue form in your browser.\");\n });\n }\n });\n}\n"],"mappings":";;;;;;;AACA,SAAS,gBAAgB;AAGlB,SAAS,wBAAwB,SAAwB;AAC9D,UACG,QAAQ,UAAU,EAClB,YAAY,wDAAwD,EACpE,OAAO,mBAAmB,aAAa,EACvC,OAAO,OAAO,SAAS;AACtB,UAAM,UAAU;AAChB,UAAM,OAAO;AAAA,MACX,sBAAsB;AAAA,MACtB,eAAe,QAAQ;AAAA,MACvB,mBAAmB,QAAQ,WAAW,MAAM,QAAQ;AAAA,MACpD,yBAAyB,oBAAoB;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AACX,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC,OAAO,KAAK,SAAS;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AACD,UAAM,MAAM,kDAAkD,MAAM;AACpE,QAAI,QAAQ,aAAa,SAAS;AAChC,eAAS,OAAO,CAAC,MAAM,SAAS,IAAI,GAAG,GAAG,CAAC,QAAQ;AACjD,YAAI,IAAK,SAAQ,IAAI;AAAA,EAA0B,GAAG,EAAE;AAAA,YAC/C,SAAQ,IAAI,2CAA2C;AAAA,MAC9D,CAAC;AAAA,IACH,OAAO;AACL,YAAM,MAAM,QAAQ,aAAa,WAAW,SAAS;AACrD,eAAS,KAAK,CAAC,GAAG,GAAG,CAAC,QAAQ;AAC5B,YAAI,IAAK,SAAQ,IAAI;AAAA,EAA0B,GAAG,EAAE;AAAA,YAC/C,SAAQ,IAAI,2CAA2C;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getOutputFormat
|
|
4
|
+
} from "./chunk-ELXAK7GI.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/games.ts
|
|
7
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
8
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
9
|
+
import { createGamesClient } from "@gpc-cli/api";
|
|
10
|
+
import { listLeaderboards, listAchievements, listEvents, formatOutput } from "@gpc-cli/core";
|
|
11
|
+
function resolvePackageName(packageArg, config) {
|
|
12
|
+
const name = packageArg || config.app;
|
|
13
|
+
if (!name) {
|
|
14
|
+
console.error("Error: No package name. Use --app <package> or gpc config set app <package>");
|
|
15
|
+
process.exit(2);
|
|
16
|
+
}
|
|
17
|
+
return name;
|
|
18
|
+
}
|
|
19
|
+
async function getClient(config) {
|
|
20
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
21
|
+
return createGamesClient({ auth });
|
|
22
|
+
}
|
|
23
|
+
function registerGamesCommands(program) {
|
|
24
|
+
const games = program.command("games").description("Manage Play Games Services \u2014 leaderboards, achievements, events");
|
|
25
|
+
games.command("leaderboards").description("List leaderboards for the app").action(async () => {
|
|
26
|
+
const config = await loadConfig();
|
|
27
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
28
|
+
const client = await getClient(config);
|
|
29
|
+
const format = getOutputFormat(program, config);
|
|
30
|
+
try {
|
|
31
|
+
const result = await listLeaderboards(client, packageName);
|
|
32
|
+
if (result.length === 0 && format !== "json") {
|
|
33
|
+
console.log("No leaderboards found.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
console.log(formatOutput(result, format));
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
39
|
+
process.exit(4);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
games.command("achievements").description("List achievements for the app").action(async () => {
|
|
43
|
+
const config = await loadConfig();
|
|
44
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
45
|
+
const client = await getClient(config);
|
|
46
|
+
const format = getOutputFormat(program, config);
|
|
47
|
+
try {
|
|
48
|
+
const result = await listAchievements(client, packageName);
|
|
49
|
+
if (result.length === 0 && format !== "json") {
|
|
50
|
+
console.log("No achievements found.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
console.log(formatOutput(result, format));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
|
+
process.exit(4);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
games.command("events").description("List events for the app").action(async () => {
|
|
60
|
+
const config = await loadConfig();
|
|
61
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
62
|
+
const client = await getClient(config);
|
|
63
|
+
const format = getOutputFormat(program, config);
|
|
64
|
+
try {
|
|
65
|
+
const result = await listEvents(client, packageName);
|
|
66
|
+
if (result.length === 0 && format !== "json") {
|
|
67
|
+
console.log("No events found.");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log(formatOutput(result, format));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
73
|
+
process.exit(4);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
registerGamesCommands
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=games-X57AGM3E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/games.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createGamesClient } from \"@gpc-cli/api\";\nimport { listLeaderboards, listAchievements, listEvents, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createGamesClient({ auth });\n}\n\nexport function registerGamesCommands(program: Command): void {\n const games = program\n .command(\"games\")\n .description(\"Manage Play Games Services — leaderboards, achievements, events\");\n\n games\n .command(\"leaderboards\")\n .description(\"List leaderboards for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listLeaderboards(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No leaderboards found.\");\n return;\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n games\n .command(\"achievements\")\n .description(\"List achievements for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listAchievements(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No achievements found.\");\n return;\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n games\n .command(\"events\")\n .description(\"List events for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listEvents(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No events found.\");\n return;\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kBAAkB,kBAAkB,YAAY,oBAAoB;AAG7E,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,kBAAkB,EAAE,KAAK,CAAC;AACnC;AAEO,SAAS,sBAAsB,SAAwB;AAC5D,QAAM,QAAQ,QACX,QAAQ,OAAO,EACf,YAAY,sEAAiE;AAEhF,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,UAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,gBAAQ,IAAI,wBAAwB;AACpC;AAAA,MACF;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,UAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,gBAAQ,IAAI,wBAAwB;AACpC;AAAA,MACF;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,QAAQ,WAAW;AACnD,UAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,gBAAQ,IAAI,kBAAkB;AAC9B;AAAA,MACF;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isDryRun,
|
|
4
|
+
printDryRun
|
|
5
|
+
} from "./chunk-Y3QZDAKS.js";
|
|
6
|
+
import {
|
|
7
|
+
getOutputFormat
|
|
8
|
+
} from "./chunk-ELXAK7GI.js";
|
|
9
|
+
import {
|
|
10
|
+
requireConfirm
|
|
11
|
+
} from "./chunk-NV75I5VP.js";
|
|
12
|
+
|
|
13
|
+
// src/commands/grants.ts
|
|
14
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
15
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
16
|
+
import { createUsersClient } from "@gpc-cli/api";
|
|
17
|
+
import { listGrants, createGrant, updateGrant, deleteGrant, formatOutput } from "@gpc-cli/core";
|
|
18
|
+
function resolveDeveloperId(devIdArg, config) {
|
|
19
|
+
const id = devIdArg || config.developerId;
|
|
20
|
+
if (!id) {
|
|
21
|
+
console.error("Error: No developer ID. Use --developer-id <id> or gpc config set developerId <id>");
|
|
22
|
+
process.exit(2);
|
|
23
|
+
}
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
async function getClient(config) {
|
|
27
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
28
|
+
return createUsersClient({ auth });
|
|
29
|
+
}
|
|
30
|
+
function registerGrantsCommands(program) {
|
|
31
|
+
const grants = program.command("grants").description("Manage per-app permission grants for developer account users").option("--developer-id <id>", "Developer account ID");
|
|
32
|
+
grants.command("list <email>").description("List all per-app grants for a user").action(async (email) => {
|
|
33
|
+
const config = await loadConfig();
|
|
34
|
+
const developerId = resolveDeveloperId(grants.opts()["developerId"], config);
|
|
35
|
+
const client = await getClient(config);
|
|
36
|
+
const format = getOutputFormat(program, config);
|
|
37
|
+
try {
|
|
38
|
+
const result = await listGrants(client, developerId, email);
|
|
39
|
+
if (result.length === 0) {
|
|
40
|
+
if (format === "json") {
|
|
41
|
+
console.log(formatOutput([], format));
|
|
42
|
+
} else {
|
|
43
|
+
console.log(`No grants found for ${email}.`);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log(formatOutput(result, format));
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
|
+
process.exit(4);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
grants.command("create <email>").description("Grant app-level permissions to a user").requiredOption("--package <packageName>", "App package name").requiredOption("--permissions <list>", "Comma-separated permissions (e.g. CAN_MANAGE_RELEASES,VIEW_APP_INFORMATION)").action(async (email, options) => {
|
|
54
|
+
const config = await loadConfig();
|
|
55
|
+
const developerId = resolveDeveloperId(grants.opts()["developerId"], config);
|
|
56
|
+
const format = getOutputFormat(program, config);
|
|
57
|
+
const perms = options.permissions.split(",").map((p) => p.trim());
|
|
58
|
+
if (isDryRun(program)) {
|
|
59
|
+
printDryRun(
|
|
60
|
+
{ command: "grants create", action: "grant permissions", target: `${email}/${options.package}`, details: { permissions: perms } },
|
|
61
|
+
format,
|
|
62
|
+
formatOutput
|
|
63
|
+
);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const client = await getClient(config);
|
|
67
|
+
try {
|
|
68
|
+
const result = await createGrant(client, developerId, email, options.package, perms);
|
|
69
|
+
console.log(formatOutput(result, format));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
process.exit(4);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
grants.command("update <email>").description("Update app-level permissions for a user").requiredOption("--package <packageName>", "App package name").requiredOption("--permissions <list>", "New comma-separated permissions").action(async (email, options) => {
|
|
76
|
+
const config = await loadConfig();
|
|
77
|
+
const developerId = resolveDeveloperId(grants.opts()["developerId"], config);
|
|
78
|
+
const format = getOutputFormat(program, config);
|
|
79
|
+
const perms = options.permissions.split(",").map((p) => p.trim());
|
|
80
|
+
if (isDryRun(program)) {
|
|
81
|
+
printDryRun(
|
|
82
|
+
{ command: "grants update", action: "update permissions", target: `${email}/${options.package}`, details: { permissions: perms } },
|
|
83
|
+
format,
|
|
84
|
+
formatOutput
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const client = await getClient(config);
|
|
89
|
+
try {
|
|
90
|
+
const result = await updateGrant(client, developerId, email, options.package, perms);
|
|
91
|
+
console.log(formatOutput(result, format));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
94
|
+
process.exit(4);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
grants.command("delete <email>").description("Remove a per-app grant from a user").requiredOption("--package <packageName>", "App package name").action(async (email, options) => {
|
|
98
|
+
const config = await loadConfig();
|
|
99
|
+
const developerId = resolveDeveloperId(grants.opts()["developerId"], config);
|
|
100
|
+
const format = getOutputFormat(program, config);
|
|
101
|
+
await requireConfirm(`Remove grant for "${email}" on ${options.package}?`, program);
|
|
102
|
+
if (isDryRun(program)) {
|
|
103
|
+
printDryRun(
|
|
104
|
+
{ command: "grants delete", action: "remove grant", target: `${email}/${options.package}` },
|
|
105
|
+
format,
|
|
106
|
+
formatOutput
|
|
107
|
+
);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const client = await getClient(config);
|
|
111
|
+
try {
|
|
112
|
+
await deleteGrant(client, developerId, email, options.package);
|
|
113
|
+
console.log(`Grant removed for ${email} on ${options.package}.`);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
116
|
+
process.exit(4);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
registerGrantsCommands
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=grants-CXTTYKR3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/grants.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createUsersClient } from \"@gpc-cli/api\";\nimport { listGrants, createGrant, updateGrant, deleteGrant, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nfunction resolveDeveloperId(devIdArg: string | undefined, config: GpcConfig): string {\n const id = devIdArg || config.developerId;\n if (!id) {\n console.error(\"Error: No developer ID. Use --developer-id <id> or gpc config set developerId <id>\");\n process.exit(2);\n }\n return id;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createUsersClient({ auth });\n}\n\nexport function registerGrantsCommands(program: Command): void {\n const grants = program\n .command(\"grants\")\n .description(\"Manage per-app permission grants for developer account users\")\n .option(\"--developer-id <id>\", \"Developer account ID\");\n\n grants\n .command(\"list <email>\")\n .description(\"List all per-app grants for a user\")\n .action(async (email: string) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listGrants(client, developerId, email);\n if (result.length === 0) {\n if (format === \"json\") {\n console.log(formatOutput([], format));\n } else {\n console.log(`No grants found for ${email}.`);\n }\n return;\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n grants\n .command(\"create <email>\")\n .description(\"Grant app-level permissions to a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\"--permissions <list>\", \"Comma-separated permissions (e.g. CAN_MANAGE_RELEASES,VIEW_APP_INFORMATION)\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"grants create\", action: \"grant permissions\", target: `${email}/${options.package}`, details: { permissions: perms } },\n format, formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await createGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n grants\n .command(\"update <email>\")\n .description(\"Update app-level permissions for a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\"--permissions <list>\", \"New comma-separated permissions\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"grants update\", action: \"update permissions\", target: `${email}/${options.package}`, details: { permissions: perms } },\n format, formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await updateGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n grants\n .command(\"delete <email>\")\n .description(\"Remove a per-app grant from a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n\n await requireConfirm(`Remove grant for \"${email}\" on ${options.package}?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"grants delete\", action: \"remove grant\", target: `${email}/${options.package}` },\n format, formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteGrant(client, developerId, email, options.package);\n console.log(`Grant removed for ${email} on ${options.package}.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":"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","names":[]}
|