@gpc-cli/cli 0.9.8 → 0.9.10
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/dist/bin.js +18 -1
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-JVGSSJLY.js → chunk-ENBQPSKO.js} +17 -11
- package/dist/chunk-ENBQPSKO.js.map +1 -0
- package/dist/{completion-3UYUJD6S.js → completion-C3PPWNS7.js} +68 -1
- package/dist/completion-C3PPWNS7.js.map +1 -0
- package/dist/doctor-7IO43Y4R.js +236 -0
- package/dist/doctor-7IO43Y4R.js.map +1 -0
- package/dist/{external-transactions-YRK5CI2D.js → external-transactions-5U3PMAAG.js} +2 -2
- package/dist/external-transactions-5U3PMAAG.js.map +1 -0
- package/dist/{generated-apks-SUPM3NS3.js → generated-apks-HF7VYA54.js} +2 -2
- package/dist/generated-apks-HF7VYA54.js.map +1 -0
- package/dist/{iap-ZZS5NVFN.js → iap-2CV6SJUF.js} +7 -2
- package/dist/iap-2CV6SJUF.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{internal-sharing-ZQUI3SDM.js → internal-sharing-FEZFTPWE.js} +8 -3
- package/dist/internal-sharing-FEZFTPWE.js.map +1 -0
- package/dist/{listings-LTVQHMX3.js → listings-4QCTOEWL.js} +34 -2
- package/dist/listings-4QCTOEWL.js.map +1 -0
- package/dist/migrate-5IA6WGMO.js +76 -0
- package/dist/migrate-5IA6WGMO.js.map +1 -0
- package/dist/purchase-options-2NUBLODI.js +145 -0
- package/dist/purchase-options-2NUBLODI.js.map +1 -0
- package/dist/{releases-GUMQZRFC.js → releases-HDCDARH5.js} +30 -3
- package/dist/releases-HDCDARH5.js.map +1 -0
- package/dist/tracks-D6FUNJ75.js +84 -0
- package/dist/tracks-D6FUNJ75.js.map +1 -0
- package/package.json +5 -5
- package/dist/chunk-JVGSSJLY.js.map +0 -1
- package/dist/completion-3UYUJD6S.js.map +0 -1
- package/dist/doctor-KVP7PGZU.js +0 -61
- package/dist/doctor-KVP7PGZU.js.map +0 -1
- package/dist/external-transactions-YRK5CI2D.js.map +0 -1
- package/dist/generated-apks-SUPM3NS3.js.map +0 -1
- package/dist/iap-ZZS5NVFN.js.map +0 -1
- package/dist/internal-sharing-ZQUI3SDM.js.map +0 -1
- package/dist/listings-LTVQHMX3.js.map +0 -1
- package/dist/releases-GUMQZRFC.js.map +0 -1
- package/dist/tracks-AJH5KP7J.js +0 -41
- package/dist/tracks-AJH5KP7J.js.map +0 -1
|
@@ -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 { resolveAuth, AuthError } from \"@gpc-cli/auth\";\nimport { existsSync, accessSync, constants } from \"node:fs\";\nimport { lookup } from \"node:dns/promises\";\n\ninterface 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 PASS;\n case \"fail\":\n return FAIL;\n case \"warn\":\n return WARN;\n case \"info\":\n return INFO;\n }\n}\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Verify setup and connectivity\")\n .option(\"--json\", \"Output results as JSON\")\n .action(async (opts: { json?: boolean }) => {\n const results: CheckResult[] = [];\n const jsonMode = opts.json ?? false;\n\n // 1. Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split(\".\")[0] ?? \"0\", 10);\n results.push(\n 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\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 } 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 error\",\n suggestion: \"Check your .gpcrc.json or config file 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. 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 if (proxyUrl) {\n try {\n new URL(proxyUrl);\n results.push({\n name: \"proxy\",\n status: \"pass\",\n message: `Proxy configured: ${proxyUrl}`,\n });\n } catch {\n results.push({\n name: \"proxy\",\n status: \"warn\",\n message: `Invalid proxy URL: ${proxyUrl}`,\n suggestion: \"Set HTTPS_PROXY to a valid URL (e.g., http://proxy.example.com:8080)\",\n });\n }\n }\n\n // 6. 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 // 7. DNS resolution\n try {\n await lookup(\"androidpublisher.googleapis.com\");\n results.push({\n name: \"dns\",\n status: \"pass\",\n message: \"DNS resolution: androidpublisher.googleapis.com\",\n });\n } catch {\n results.push({\n name: \"dns\",\n status: \"fail\",\n message: \"Cannot resolve androidpublisher.googleapis.com\",\n suggestion: \"Check your DNS settings and network connection\",\n });\n }\n\n // 8. 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 // Output\n if (jsonMode) {\n const errors = results.filter((r) => r.status === \"fail\").length;\n const warnings = results.filter((r) => r.status === \"warn\").length;\n console.log(\n JSON.stringify(\n {\n success: errors === 0,\n errors,\n warnings,\n checks: results,\n },\n null,\n 2,\n ),\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 const errors = results.filter((r) => r.status === \"fail\").length;\n const warnings = results.filter((r) => r.status === \"warn\").length;\n\n console.log(\"\");\n if (errors > 0) {\n console.log(\"Some checks failed. Fix the issues above and run again.\");\n process.exit(1);\n } else if (warnings > 0) {\n console.log(\"All checks passed with warnings.\");\n } else {\n console.log(\"All checks passed!\");\n }\n });\n}\n"],"mappings":"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","names":["errors","warnings"]}
|
|
@@ -83,7 +83,7 @@ function registerExternalTransactionsCommands(program) {
|
|
|
83
83
|
});
|
|
84
84
|
extTxn.command("refund <id>").description("Refund an external transaction").option("--full", "Full refund").option(
|
|
85
85
|
"--partial-amount <micros>",
|
|
86
|
-
"Partial refund pre-tax amount in micros (e.g
|
|
86
|
+
"Partial refund pre-tax amount in micros (e.g., 1990000)"
|
|
87
87
|
).option("--currency <code>", "Currency code for partial refund (e.g. USD)").action(async (id, options) => {
|
|
88
88
|
const config = await loadConfig();
|
|
89
89
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
@@ -128,4 +128,4 @@ function registerExternalTransactionsCommands(program) {
|
|
|
128
128
|
export {
|
|
129
129
|
registerExternalTransactionsCommands
|
|
130
130
|
};
|
|
131
|
-
//# sourceMappingURL=external-transactions-
|
|
131
|
+
//# sourceMappingURL=external-transactions-5U3PMAAG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/external-transactions.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 createExternalTransaction,\n getExternalTransaction,\n refundExternalTransaction,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readFileSync } from \"node:fs\";\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 registerExternalTransactionsCommands(program: Command): void {\n const extTxn = program\n .command(\"external-transactions\")\n .alias(\"ext-txn\")\n .description(\"Manage external transactions (alternative billing)\");\n\n extTxn\n .command(\"create\")\n .description(\"Create a new external transaction\")\n .requiredOption(\"--file <path>\", \"Path to JSON file with transaction data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(readFileSync(options.file, \"utf-8\"));\n } catch (err) {\n console.error(\n `Error: Could not read transaction data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"external-transactions create\",\n action: \"create external transaction\",\n target: packageName,\n details: data,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await createExternalTransaction(client, packageName, data);\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 extTxn\n .command(\"get <id>\")\n .description(\"Get an external transaction by ID\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getExternalTransaction(client, packageName, id);\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 extTxn\n .command(\"refund <id>\")\n .description(\"Refund an external transaction\")\n .option(\"--full\", \"Full refund\")\n .option(\n \"--partial-amount <micros>\",\n \"Partial refund pre-tax amount in micros (e.g., 1990000)\",\n )\n .option(\"--currency <code>\", \"Currency code for partial refund (e.g. USD)\")\n .action(async (id: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n const refundData: Record<string, unknown> = {};\n if (options.full) {\n refundData.fullRefund = {};\n } else if (options.partialAmount) {\n refundData.partialRefund = {\n refundPreTaxAmount: {\n priceMicros: options.partialAmount,\n currency: options.currency,\n },\n };\n } else {\n refundData.fullRefund = {};\n }\n\n await requireConfirm(`Refund external transaction \"${id}\"?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"external-transactions refund\",\n action: \"refund external transaction\",\n target: id,\n details: refundData,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await refundExternalTransaction(client, packageName, id, refundData);\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":"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","names":[]}
|
|
@@ -23,7 +23,7 @@ async function getClient(config) {
|
|
|
23
23
|
return createApiClient({ auth });
|
|
24
24
|
}
|
|
25
25
|
function registerGeneratedApksCommands(program) {
|
|
26
|
-
const cmd = program.command("generated-apks").description("Manage
|
|
26
|
+
const cmd = program.command("generated-apks").description("Manage device-specific APKs generated by Google Play");
|
|
27
27
|
cmd.command("list <version-code>").description("List generated APKs for a version code").action(async (versionCodeStr) => {
|
|
28
28
|
const config = await loadConfig();
|
|
29
29
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
@@ -70,4 +70,4 @@ function registerGeneratedApksCommands(program) {
|
|
|
70
70
|
export {
|
|
71
71
|
registerGeneratedApksCommands
|
|
72
72
|
};
|
|
73
|
-
//# sourceMappingURL=generated-apks-
|
|
73
|
+
//# sourceMappingURL=generated-apks-HF7VYA54.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/generated-apks.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 listGeneratedApks,\n downloadGeneratedApk,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\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 registerGeneratedApksCommands(program: Command): void {\n const cmd = program\n .command(\"generated-apks\")\n .description(\"Manage device-specific APKs generated by Google Play\");\n\n cmd\n .command(\"list <version-code>\")\n .description(\"List generated APKs for a version code\")\n .action(async (versionCodeStr: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n const versionCode = parseInt(versionCodeStr, 10);\n if (isNaN(versionCode)) {\n console.error(\"Error: version-code must be a number\");\n process.exit(2);\n }\n\n try {\n const result = await listGeneratedApks(client, packageName, versionCode);\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 cmd\n .command(\"download <version-code> <apk-id>\")\n .description(\"Download a generated APK\")\n .requiredOption(\"--output <path>\", \"Output file path\")\n .action(async (versionCodeStr: string, apkId: string, opts: { output: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n const versionCode = parseInt(versionCodeStr, 10);\n if (isNaN(versionCode)) {\n console.error(\"Error: version-code must be a number\");\n process.exit(2);\n }\n\n try {\n const result = await downloadGeneratedApk(\n client,\n packageName,\n versionCode,\n apkId,\n opts.output,\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,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,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,8BAA8B,SAAwB;AACpE,QAAM,MAAM,QACT,QAAQ,gBAAgB,EACxB,YAAY,sDAAsD;AAErE,MACG,QAAQ,qBAAqB,EAC7B,YAAY,wCAAwC,EACpD,OAAO,OAAO,mBAA2B;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,mBAAmB;AAElC,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,MAAM,sCAAsC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,kBAAkB,QAAQ,aAAa,WAAW;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;AAEH,MACG,QAAQ,kCAAkC,EAC1C,YAAY,0BAA0B,EACtC,eAAe,mBAAmB,kBAAkB,EACpD,OAAO,OAAO,gBAAwB,OAAe,SAA6B;AACjF,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,mBAAmB;AAElC,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,MAAM,sCAAsC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;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":[]}
|
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
syncInAppProducts,
|
|
22
22
|
detectOutputFormat,
|
|
23
23
|
formatOutput,
|
|
24
|
-
sortResults
|
|
24
|
+
sortResults,
|
|
25
|
+
createSpinner
|
|
25
26
|
} from "@gpc-cli/core";
|
|
26
27
|
function resolvePackageName(packageArg, config) {
|
|
27
28
|
const name = packageArg || config.app;
|
|
@@ -155,15 +156,19 @@ function registerIapCommands(program) {
|
|
|
155
156
|
const client = await getClient(config);
|
|
156
157
|
const format = detectOutputFormat();
|
|
157
158
|
const dryRun = isDryRun(program);
|
|
159
|
+
const spinner = createSpinner("Syncing in-app products...");
|
|
160
|
+
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
158
161
|
try {
|
|
159
162
|
const result = await syncInAppProducts(client, packageName, options.dir, {
|
|
160
163
|
dryRun
|
|
161
164
|
});
|
|
165
|
+
spinner.stop("Sync complete");
|
|
162
166
|
if (dryRun) {
|
|
163
167
|
console.log(`[dry-run] Would create: ${result.created}, update: ${result.updated}`);
|
|
164
168
|
}
|
|
165
169
|
console.log(formatOutput(result, format));
|
|
166
170
|
} catch (error) {
|
|
171
|
+
spinner.fail("Sync failed");
|
|
167
172
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
173
|
process.exit(4);
|
|
169
174
|
}
|
|
@@ -172,4 +177,4 @@ function registerIapCommands(program) {
|
|
|
172
177
|
export {
|
|
173
178
|
registerIapCommands
|
|
174
179
|
};
|
|
175
|
-
//# sourceMappingURL=iap-
|
|
180
|
+
//# sourceMappingURL=iap-2CV6SJUF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/iap.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n listInAppProducts,\n getInAppProduct,\n createInAppProduct,\n updateInAppProduct,\n deleteInAppProduct,\n syncInAppProducts,\n detectOutputFormat,\n formatOutput,\n sortResults,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.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 registerIapCommands(program: Command): void {\n const iap = program.command(\"iap\").description(\"Manage in-app products\");\n\n iap\n .command(\"list\")\n .description(\"List in-app products\")\n .option(\"--max <n>\", \"Maximum results per page\", parseInt)\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await listInAppProducts(client, packageName, {\n maxResults: options.max,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n if (options.sort) {\n result.inappproduct = sortResults(result.inappproduct, options.sort);\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 iap\n .command(\"get <sku>\")\n .description(\"Get an in-app product\")\n .action(async (sku: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getInAppProduct(client, packageName, sku);\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 iap\n .command(\"create\")\n .description(\"Create an in-app product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"iap create\",\n action: \"create\",\n target: `in-app product from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = JSON.parse(await readFile(options.file, \"utf-8\"));\n const result = await createInAppProduct(client, packageName, data);\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 iap\n .command(\"update <sku>\")\n .description(\"Update an in-app product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .action(async (sku: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"iap update\",\n action: \"update\",\n target: sku,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = JSON.parse(await readFile(options.file, \"utf-8\"));\n const result = await updateInAppProduct(client, packageName, sku, data);\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 iap\n .command(\"delete <sku>\")\n .description(\"Delete an in-app product\")\n .action(async (sku: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete in-app product \"${sku}\"?`, program);\n\n if (isDryRun(program)) {\n const format = detectOutputFormat();\n printDryRun(\n {\n command: \"iap delete\",\n action: \"delete\",\n target: sku,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteInAppProduct(client, packageName, sku);\n console.log(`In-app product ${sku} deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n iap\n .command(\"sync\")\n .description(\"Sync in-app products from a directory of JSON files\")\n .requiredOption(\"--dir <path>\", \"Directory containing product JSON files\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n const dryRun = isDryRun(program);\n\n const spinner = createSpinner(\"Syncing in-app products...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await syncInAppProducts(client, packageName, options.dir, {\n dryRun,\n });\n spinner.stop(\"Sync complete\");\n if (dryRun) {\n console.log(`[dry-run] Would create: ${result.created}, update: ${result.updated}`);\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Sync failed\");\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":[]}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,8 @@ import { createApiClient } from "@gpc-cli/api";
|
|
|
7
7
|
import {
|
|
8
8
|
uploadInternalSharing,
|
|
9
9
|
detectOutputFormat,
|
|
10
|
-
formatOutput
|
|
10
|
+
formatOutput,
|
|
11
|
+
createSpinner
|
|
11
12
|
} from "@gpc-cli/core";
|
|
12
13
|
function resolvePackageName(packageArg, config) {
|
|
13
14
|
const name = packageArg || config.app;
|
|
@@ -22,17 +23,21 @@ async function getClient(config) {
|
|
|
22
23
|
return createApiClient({ auth });
|
|
23
24
|
}
|
|
24
25
|
function registerInternalSharingCommands(program) {
|
|
25
|
-
const cmd = program.command("internal-sharing").description("
|
|
26
|
+
const cmd = program.command("internal-sharing").description("Upload bundles or APKs for instant internal sharing");
|
|
26
27
|
cmd.command("upload <file>").description("Upload a bundle or APK for internal app sharing").option("--type <type>", "File type: bundle or apk (auto-detected from extension)").action(async (file, opts) => {
|
|
27
28
|
const config = await loadConfig();
|
|
28
29
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
29
30
|
const client = await getClient(config);
|
|
30
31
|
const format = detectOutputFormat();
|
|
31
32
|
const fileType = opts.type;
|
|
33
|
+
const spinner = createSpinner("Uploading for internal sharing...");
|
|
34
|
+
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
32
35
|
try {
|
|
33
36
|
const result = await uploadInternalSharing(client, packageName, file, fileType);
|
|
37
|
+
spinner.stop("Upload complete");
|
|
34
38
|
console.log(formatOutput(result, format));
|
|
35
39
|
} catch (error) {
|
|
40
|
+
spinner.fail("Upload failed");
|
|
36
41
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
42
|
process.exit(4);
|
|
38
43
|
}
|
|
@@ -41,4 +46,4 @@ function registerInternalSharingCommands(program) {
|
|
|
41
46
|
export {
|
|
42
47
|
registerInternalSharingCommands
|
|
43
48
|
};
|
|
44
|
-
//# sourceMappingURL=internal-sharing-
|
|
49
|
+
//# sourceMappingURL=internal-sharing-FEZFTPWE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/internal-sharing.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 uploadInternalSharing,\n detectOutputFormat,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\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 registerInternalSharingCommands(program: Command): void {\n const cmd = program\n .command(\"internal-sharing\")\n .description(\"Upload bundles or APKs for instant internal sharing\");\n\n cmd\n .command(\"upload <file>\")\n .description(\"Upload a bundle or APK for internal app sharing\")\n .option(\"--type <type>\", \"File type: bundle or apk (auto-detected from extension)\")\n .action(async (file: string, opts: { type?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n const fileType = opts.type as \"bundle\" | \"apk\" | undefined;\n\n const spinner = createSpinner(\"Uploading for internal sharing...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await uploadInternalSharing(client, packageName, file, fileType);\n spinner.stop(\"Upload complete\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Upload failed\");\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,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,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,gCAAgC,SAAwB;AACtE,QAAM,MAAM,QACT,QAAQ,kBAAkB,EAC1B,YAAY,qDAAqD;AAEpE,MACG,QAAQ,eAAe,EACvB,YAAY,iDAAiD,EAC7D,OAAO,iBAAiB,yDAAyD,EACjF,OAAO,OAAO,MAAc,SAA4B;AACvD,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,mBAAmB;AAElC,UAAM,WAAW,KAAK;AAEtB,UAAM,UAAU,cAAc,mCAAmC;AACjE,QAAI,CAAC,QAAQ,KAAK,EAAE,OAAO,KAAK,QAAQ,OAAO,MAAO,SAAQ,MAAM;AAEpE,QAAI;AACF,YAAM,SAAS,MAAM,sBAAsB,QAAQ,aAAa,MAAM,QAAQ;AAC9E,cAAQ,KAAK,iBAAiB;AAC9B,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,KAAK,eAAe;AAC5B,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -23,9 +23,11 @@ import {
|
|
|
23
23
|
listImages,
|
|
24
24
|
uploadImage,
|
|
25
25
|
deleteImage,
|
|
26
|
+
exportImages,
|
|
26
27
|
getCountryAvailability,
|
|
27
28
|
detectOutputFormat,
|
|
28
|
-
formatOutput
|
|
29
|
+
formatOutput,
|
|
30
|
+
createSpinner
|
|
29
31
|
} from "@gpc-cli/core";
|
|
30
32
|
function resolvePackageName(packageArg, config) {
|
|
31
33
|
const name = packageArg || config.app;
|
|
@@ -185,12 +187,16 @@ function registerListingsCommands(program) {
|
|
|
185
187
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
186
188
|
const client = await getClient(config);
|
|
187
189
|
const format = detectOutputFormat();
|
|
190
|
+
const spinner = createSpinner("Pushing listings...");
|
|
191
|
+
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
188
192
|
try {
|
|
189
193
|
const result = await pushListings(client, packageName, options.dir, {
|
|
190
194
|
dryRun: isDryRun(program)
|
|
191
195
|
});
|
|
196
|
+
spinner.stop("Listings pushed");
|
|
192
197
|
console.log(formatOutput(result, format));
|
|
193
198
|
} catch (error) {
|
|
199
|
+
spinner.fail("Push failed");
|
|
194
200
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
195
201
|
process.exit(4);
|
|
196
202
|
}
|
|
@@ -283,10 +289,14 @@ function registerListingsCommands(program) {
|
|
|
283
289
|
const client = await getClient(config);
|
|
284
290
|
const format = detectOutputFormat();
|
|
285
291
|
const imageType = validateImageType(options.type);
|
|
292
|
+
const spinner = createSpinner("Uploading image...");
|
|
293
|
+
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
286
294
|
try {
|
|
287
295
|
const result = await uploadImage(client, packageName, options.lang, imageType, file);
|
|
296
|
+
spinner.stop("Image uploaded");
|
|
288
297
|
console.log(formatOutput(result, format));
|
|
289
298
|
} catch (error) {
|
|
299
|
+
spinner.fail("Image upload failed");
|
|
290
300
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
291
301
|
process.exit(4);
|
|
292
302
|
}
|
|
@@ -331,6 +341,28 @@ function registerListingsCommands(program) {
|
|
|
331
341
|
process.exit(4);
|
|
332
342
|
}
|
|
333
343
|
});
|
|
344
|
+
images.command("export").description("Export all images to a local directory").option("--dir <path>", "Output directory", "images").option("--lang <language>", "Language code (BCP 47) \u2014 export only this language").option("--type <type>", "Image type \u2014 export only this type").action(async (options) => {
|
|
345
|
+
const config = await loadConfig();
|
|
346
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
347
|
+
const client = await getClient(config);
|
|
348
|
+
const format = detectOutputFormat();
|
|
349
|
+
const exportOpts = {};
|
|
350
|
+
if (options.lang) exportOpts.lang = options.lang;
|
|
351
|
+
if (options.type) {
|
|
352
|
+
exportOpts.type = validateImageType(options.type);
|
|
353
|
+
}
|
|
354
|
+
const spinner = createSpinner("Exporting images...");
|
|
355
|
+
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
356
|
+
try {
|
|
357
|
+
const result = await exportImages(client, packageName, options.dir, exportOpts);
|
|
358
|
+
spinner.stop("Images exported");
|
|
359
|
+
console.log(formatOutput(result, format));
|
|
360
|
+
} catch (error) {
|
|
361
|
+
spinner.fail("Image export failed");
|
|
362
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
363
|
+
process.exit(4);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
334
366
|
listings.command("availability").description("Get country availability for a track").option("--track <track>", "Track name", "production").action(async (options) => {
|
|
335
367
|
const config = await loadConfig();
|
|
336
368
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
@@ -348,4 +380,4 @@ function registerListingsCommands(program) {
|
|
|
348
380
|
export {
|
|
349
381
|
registerListingsCommands
|
|
350
382
|
};
|
|
351
|
-
//# sourceMappingURL=listings-
|
|
383
|
+
//# sourceMappingURL=listings-4QCTOEWL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/listings.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 type { ImageType } from \"@gpc-cli/api\";\nimport {\n getListings,\n updateListing,\n deleteListing,\n pullListings,\n pushListings,\n diffListingsCommand,\n listImages,\n uploadImage,\n deleteImage,\n exportImages,\n getCountryAvailability,\n detectOutputFormat,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.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\nconst VALID_IMAGE_TYPES: ImageType[] = [\n \"phoneScreenshots\",\n \"sevenInchScreenshots\",\n \"tenInchScreenshots\",\n \"tvScreenshots\",\n \"wearScreenshots\",\n \"icon\",\n \"featureGraphic\",\n \"tvBanner\",\n];\n\nfunction validateImageType(type: string): ImageType {\n if (!VALID_IMAGE_TYPES.includes(type as ImageType)) {\n console.error(`Error: Invalid image type \"${type}\".`);\n console.error(`Valid types: ${VALID_IMAGE_TYPES.join(\", \")}`);\n process.exit(2);\n }\n return type as ImageType;\n}\n\nexport function registerListingsCommands(program: Command): void {\n const listings = program.command(\"listings\").description(\"Manage store listings and metadata\");\n\n // Get\n listings\n .command(\"get\")\n .description(\"Get store listing(s)\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getListings(client, packageName, options.lang);\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 // Update\n listings\n .command(\"update\")\n .description(\"Update a store listing\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--title <text>\", \"App title\")\n .option(\"--short <text>\", \"Short description\")\n .option(\"--full <text>\", \"Full description\")\n .option(\"--full-file <path>\", \"Read full description from file\")\n .option(\"--video <url>\", \"Video URL\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n const format = detectOutputFormat();\n\n try {\n const data: Record<string, string> = {};\n if (options[\"title\"]) data[\"title\"] = options[\"title\"];\n if (options[\"short\"]) data[\"shortDescription\"] = options[\"short\"];\n if (options[\"full\"]) data[\"fullDescription\"] = options[\"full\"];\n if (options[\"fullFile\"]) {\n const { readFile } = await import(\"node:fs/promises\");\n data[\"fullDescription\"] = (await readFile(options[\"fullFile\"], \"utf-8\")).trimEnd();\n }\n if (options[\"video\"]) data[\"video\"] = options[\"video\"];\n\n if (Object.keys(data).length === 0) {\n console.error(\n \"Error: Provide at least one field to update (--title, --short, --full, --full-file, --video).\",\n );\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"listings update\",\n action: \"update listing for\",\n target: options.lang,\n details: data,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n const result = await updateListing(client, packageName, options.lang, data);\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 // Delete\n listings\n .command(\"delete\")\n .description(\"Delete a store listing for a language\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n },\n interactive,\n );\n\n await requireConfirm(`Delete listing for \"${options.lang}\"?`, program);\n\n if (isDryRun(program)) {\n const format = detectOutputFormat();\n printDryRun(\n {\n command: \"listings delete\",\n action: \"delete listing for\",\n target: options.lang,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteListing(client, packageName, options.lang);\n console.log(`Listing for \"${options.lang}\" deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Pull\n listings\n .command(\"pull\")\n .description(\"Download listings to Fastlane-format directory\")\n .option(\"--dir <path>\", \"Output directory\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await pullListings(client, packageName, options.dir);\n console.log(\n formatOutput(\n {\n directory: options.dir,\n languages: result.listings.map((l) => l.language),\n count: result.listings.length,\n },\n format,\n ),\n );\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Push\n listings\n .command(\"push\")\n .description(\"Upload listings from Fastlane-format directory\")\n .option(\"--dir <path>\", \"Source directory\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n const spinner = createSpinner(\"Pushing listings...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await pushListings(client, packageName, options.dir, {\n dryRun: isDryRun(program),\n });\n spinner.stop(\"Listings pushed\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Push failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Diff\n listings\n .command(\"diff\")\n .description(\"Compare local Fastlane-format metadata against remote listings\")\n .option(\"--dir <path>\", \"Local metadata directory\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const diffs = await diffListingsCommand(client, packageName, options.dir);\n\n if (diffs.length === 0) {\n if (format === \"json\") {\n console.log(formatOutput([], format));\n } else {\n console.log(\"No differences found.\");\n }\n return;\n }\n\n if (format === \"json\") {\n console.log(formatOutput(diffs, format));\n } else {\n for (const diff of diffs) {\n console.log(`[${diff.language}] ${diff.field}:`);\n console.log(` local: ${diff.local || \"(empty)\"}`);\n console.log(` remote: ${diff.remote || \"(empty)\"}`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images subcommand\n const images = listings.command(\"images\").description(\"Manage listing images\");\n\n // Images list\n images\n .command(\"list\")\n .description(\"List images for a language and type\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = detectOutputFormat();\n const imageType = validateImageType(options.type);\n\n try {\n const result = await listImages(client, packageName, options.lang, imageType);\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 // Images upload\n images\n .command(\"upload <file>\")\n .description(\"Upload an image\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .action(async (file: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = detectOutputFormat();\n const imageType = validateImageType(options.type);\n\n const spinner = createSpinner(\"Uploading image...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await uploadImage(client, packageName, options.lang, imageType, file);\n spinner.stop(\"Image uploaded\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Image upload failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images delete\n images\n .command(\"delete\")\n .description(\"Delete an image\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .option(\"--id <imageId>\", \"Image ID to delete\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n options.id = await requireOption(\n \"id\",\n options.id,\n {\n message: \"Image ID to delete:\",\n },\n interactive,\n );\n\n await requireConfirm(`Delete image \"${options.id}\"?`, program);\n\n const client = await getClient(config);\n const imageType = validateImageType(options.type);\n\n try {\n await deleteImage(client, packageName, options.lang, imageType, options.id);\n console.log(`Image \"${options.id}\" deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images export\n images\n .command(\"export\")\n .description(\"Export all images to a local directory\")\n .option(\"--dir <path>\", \"Output directory\", \"images\")\n .option(\"--lang <language>\", \"Language code (BCP 47) — export only this language\")\n .option(\"--type <type>\", \"Image type — export only this type\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n const exportOpts: { lang?: string; type?: ImageType } = {};\n if (options.lang) exportOpts.lang = options.lang;\n if (options.type) {\n exportOpts.type = validateImageType(options.type);\n }\n\n const spinner = createSpinner(\"Exporting images...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await exportImages(client, packageName, options.dir, exportOpts);\n spinner.stop(\"Images exported\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Image export failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Availability\n listings\n .command(\"availability\")\n .description(\"Get country availability for a track\")\n .option(\"--track <track>\", \"Track name\", \"production\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getCountryAvailability(client, packageName, options.track);\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":"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","names":[]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/migrate.ts
|
|
4
|
+
import {
|
|
5
|
+
detectFastlane,
|
|
6
|
+
generateMigrationPlan,
|
|
7
|
+
writeMigrationOutput,
|
|
8
|
+
detectOutputFormat,
|
|
9
|
+
formatOutput
|
|
10
|
+
} from "@gpc-cli/core";
|
|
11
|
+
function registerMigrateCommands(program) {
|
|
12
|
+
const migrate = program.command("migrate").description("Migrate from other tools to GPC");
|
|
13
|
+
migrate.command("fastlane").description("Migrate from Fastlane to GPC").option("--dir <path>", "Directory containing Fastlane files", ".").option("--output <path>", "Output directory for migration files", ".").action(async (options) => {
|
|
14
|
+
const format = detectOutputFormat();
|
|
15
|
+
try {
|
|
16
|
+
const detection = await detectFastlane(options.dir);
|
|
17
|
+
if (format === "json") {
|
|
18
|
+
console.log(formatOutput(detection, format));
|
|
19
|
+
} else {
|
|
20
|
+
console.log("Fastlane Detection Results:");
|
|
21
|
+
console.log(` Fastfile: ${detection.hasFastfile ? "found" : "not found"}`);
|
|
22
|
+
console.log(` Appfile: ${detection.hasAppfile ? "found" : "not found"}`);
|
|
23
|
+
console.log(` Metadata: ${detection.hasMetadata ? "found" : "not found"}`);
|
|
24
|
+
console.log(` Gemfile: ${detection.hasGemfile ? "found" : "not found"}`);
|
|
25
|
+
if (detection.packageName) {
|
|
26
|
+
console.log(` Package: ${detection.packageName}`);
|
|
27
|
+
}
|
|
28
|
+
if (detection.lanes.length > 0) {
|
|
29
|
+
console.log(`
|
|
30
|
+
Lanes found: ${detection.lanes.length}`);
|
|
31
|
+
for (const lane of detection.lanes) {
|
|
32
|
+
const equiv = lane.gpcEquivalent ? ` -> ${lane.gpcEquivalent}` : " (no equivalent)";
|
|
33
|
+
console.log(` - ${lane.name}${equiv}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (detection.metadataLanguages.length > 0) {
|
|
37
|
+
console.log(`
|
|
38
|
+
Metadata languages: ${detection.metadataLanguages.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!detection.hasFastfile && !detection.hasAppfile && !detection.hasMetadata) {
|
|
42
|
+
if (format !== "json") {
|
|
43
|
+
console.log("\nNo Fastlane files detected. Nothing to migrate.");
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const plan = generateMigrationPlan(detection);
|
|
48
|
+
const files = await writeMigrationOutput(plan, options.output);
|
|
49
|
+
if (format === "json") {
|
|
50
|
+
console.log(formatOutput({ detection, plan, files }, format));
|
|
51
|
+
} else {
|
|
52
|
+
console.log("\nMigration files written:");
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
console.log(` ${file}`);
|
|
55
|
+
}
|
|
56
|
+
if (plan.warnings.length > 0) {
|
|
57
|
+
console.log("\nWarnings:");
|
|
58
|
+
for (const warning of plan.warnings) {
|
|
59
|
+
console.log(` - ${warning}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log("\nMigration Checklist:");
|
|
63
|
+
for (const item of plan.checklist) {
|
|
64
|
+
console.log(` [ ] ${item}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
registerMigrateCommands
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=migrate-5IA6WGMO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/migrate.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n detectFastlane,\n generateMigrationPlan,\n writeMigrationOutput,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\n\nexport function registerMigrateCommands(program: Command): void {\n const migrate = program.command(\"migrate\").description(\"Migrate from other tools to GPC\");\n\n migrate\n .command(\"fastlane\")\n .description(\"Migrate from Fastlane to GPC\")\n .option(\"--dir <path>\", \"Directory containing Fastlane files\", \".\")\n .option(\"--output <path>\", \"Output directory for migration files\", \".\")\n .action(async (options) => {\n const format = detectOutputFormat();\n\n try {\n const detection = await detectFastlane(options.dir);\n\n // Show detection results\n if (format === \"json\") {\n console.log(formatOutput(detection, format));\n } else {\n console.log(\"Fastlane Detection Results:\");\n console.log(` Fastfile: ${detection.hasFastfile ? \"found\" : \"not found\"}`);\n console.log(` Appfile: ${detection.hasAppfile ? \"found\" : \"not found\"}`);\n console.log(` Metadata: ${detection.hasMetadata ? \"found\" : \"not found\"}`);\n console.log(` Gemfile: ${detection.hasGemfile ? \"found\" : \"not found\"}`);\n\n if (detection.packageName) {\n console.log(` Package: ${detection.packageName}`);\n }\n\n if (detection.lanes.length > 0) {\n console.log(`\\n Lanes found: ${detection.lanes.length}`);\n for (const lane of detection.lanes) {\n const equiv = lane.gpcEquivalent ? ` -> ${lane.gpcEquivalent}` : \" (no equivalent)\";\n console.log(` - ${lane.name}${equiv}`);\n }\n }\n\n if (detection.metadataLanguages.length > 0) {\n console.log(`\\n Metadata languages: ${detection.metadataLanguages.join(\", \")}`);\n }\n }\n\n if (\n !detection.hasFastfile &&\n !detection.hasAppfile &&\n !detection.hasMetadata\n ) {\n if (format !== \"json\") {\n console.log(\"\\nNo Fastlane files detected. Nothing to migrate.\");\n }\n return;\n }\n\n // Generate migration plan\n const plan = generateMigrationPlan(detection);\n\n // Write output files\n const files = await writeMigrationOutput(plan, options.output);\n\n if (format === \"json\") {\n console.log(formatOutput({ detection, plan, files }, format));\n } else {\n console.log(\"\\nMigration files written:\");\n for (const file of files) {\n console.log(` ${file}`);\n }\n\n if (plan.warnings.length > 0) {\n console.log(\"\\nWarnings:\");\n for (const warning of plan.warnings) {\n console.log(` - ${warning}`);\n }\n }\n\n console.log(\"\\nMigration Checklist:\");\n for (const item of plan.checklist) {\n console.log(` [ ] ${item}`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":";;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,iCAAiC;AAExF,UACG,QAAQ,UAAU,EAClB,YAAY,8BAA8B,EAC1C,OAAO,gBAAgB,uCAAuC,GAAG,EACjE,OAAO,mBAAmB,wCAAwC,GAAG,EACrE,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,mBAAmB;AAElC,QAAI;AACF,YAAM,YAAY,MAAM,eAAe,QAAQ,GAAG;AAGlD,UAAI,WAAW,QAAQ;AACrB,gBAAQ,IAAI,aAAa,WAAW,MAAM,CAAC;AAAA,MAC7C,OAAO;AACL,gBAAQ,IAAI,6BAA6B;AACzC,gBAAQ,IAAI,gBAAgB,UAAU,cAAc,UAAU,WAAW,EAAE;AAC3E,gBAAQ,IAAI,gBAAgB,UAAU,aAAa,UAAU,WAAW,EAAE;AAC1E,gBAAQ,IAAI,gBAAgB,UAAU,cAAc,UAAU,WAAW,EAAE;AAC3E,gBAAQ,IAAI,gBAAgB,UAAU,aAAa,UAAU,WAAW,EAAE;AAE1E,YAAI,UAAU,aAAa;AACzB,kBAAQ,IAAI,gBAAgB,UAAU,WAAW,EAAE;AAAA,QACrD;AAEA,YAAI,UAAU,MAAM,SAAS,GAAG;AAC9B,kBAAQ,IAAI;AAAA,iBAAoB,UAAU,MAAM,MAAM,EAAE;AACxD,qBAAW,QAAQ,UAAU,OAAO;AAClC,kBAAM,QAAQ,KAAK,gBAAgB,OAAO,KAAK,aAAa,KAAK;AACjE,oBAAQ,IAAI,SAAS,KAAK,IAAI,GAAG,KAAK,EAAE;AAAA,UAC1C;AAAA,QACF;AAEA,YAAI,UAAU,kBAAkB,SAAS,GAAG;AAC1C,kBAAQ,IAAI;AAAA,wBAA2B,UAAU,kBAAkB,KAAK,IAAI,CAAC,EAAE;AAAA,QACjF;AAAA,MACF;AAEA,UACE,CAAC,UAAU,eACX,CAAC,UAAU,cACX,CAAC,UAAU,aACX;AACA,YAAI,WAAW,QAAQ;AACrB,kBAAQ,IAAI,mDAAmD;AAAA,QACjE;AACA;AAAA,MACF;AAGA,YAAM,OAAO,sBAAsB,SAAS;AAG5C,YAAM,QAAQ,MAAM,qBAAqB,MAAM,QAAQ,MAAM;AAE7D,UAAI,WAAW,QAAQ;AACrB,gBAAQ,IAAI,aAAa,EAAE,WAAW,MAAM,MAAM,GAAG,MAAM,CAAC;AAAA,MAC9D,OAAO;AACL,gBAAQ,IAAI,4BAA4B;AACxC,mBAAW,QAAQ,OAAO;AACxB,kBAAQ,IAAI,KAAK,IAAI,EAAE;AAAA,QACzB;AAEA,YAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,kBAAQ,IAAI,aAAa;AACzB,qBAAW,WAAW,KAAK,UAAU;AACnC,oBAAQ,IAAI,OAAO,OAAO,EAAE;AAAA,UAC9B;AAAA,QACF;AAEA,gBAAQ,IAAI,wBAAwB;AACpC,mBAAW,QAAQ,KAAK,WAAW;AACjC,kBAAQ,IAAI,SAAS,IAAI,EAAE;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,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,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isDryRun,
|
|
4
|
+
printDryRun
|
|
5
|
+
} from "./chunk-Y3QZDAKS.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/purchase-options.ts
|
|
8
|
+
import { readFile } from "fs/promises";
|
|
9
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
10
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
11
|
+
import { createApiClient } from "@gpc-cli/api";
|
|
12
|
+
import {
|
|
13
|
+
listPurchaseOptions,
|
|
14
|
+
getPurchaseOption,
|
|
15
|
+
createPurchaseOption,
|
|
16
|
+
activatePurchaseOption,
|
|
17
|
+
deactivatePurchaseOption,
|
|
18
|
+
detectOutputFormat,
|
|
19
|
+
formatOutput,
|
|
20
|
+
sortResults
|
|
21
|
+
} from "@gpc-cli/core";
|
|
22
|
+
function resolvePackageName(packageArg, config) {
|
|
23
|
+
const name = packageArg || config.app;
|
|
24
|
+
if (!name) {
|
|
25
|
+
console.error("Error: No package name. Use --app <package> or gpc config set app <package>");
|
|
26
|
+
process.exit(2);
|
|
27
|
+
}
|
|
28
|
+
return name;
|
|
29
|
+
}
|
|
30
|
+
async function getClient(config) {
|
|
31
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
32
|
+
return createApiClient({ auth });
|
|
33
|
+
}
|
|
34
|
+
function registerPurchaseOptionsCommands(program) {
|
|
35
|
+
const po = program.command("purchase-options").description("Manage purchase options");
|
|
36
|
+
po.command("list").description("List purchase options").option("--sort <field>", "Sort by field (prefix with - for descending)").action(async (options) => {
|
|
37
|
+
const config = await loadConfig();
|
|
38
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
39
|
+
const client = await getClient(config);
|
|
40
|
+
const format = detectOutputFormat();
|
|
41
|
+
try {
|
|
42
|
+
const result = await listPurchaseOptions(client, packageName);
|
|
43
|
+
if (options.sort) {
|
|
44
|
+
result.purchaseOptions = sortResults(result.purchaseOptions, options.sort);
|
|
45
|
+
}
|
|
46
|
+
console.log(formatOutput(result, format));
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
process.exit(4);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
po.command("get <id>").description("Get a purchase option").action(async (id) => {
|
|
53
|
+
const config = await loadConfig();
|
|
54
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
55
|
+
const client = await getClient(config);
|
|
56
|
+
const format = detectOutputFormat();
|
|
57
|
+
try {
|
|
58
|
+
const result = await getPurchaseOption(client, packageName, id);
|
|
59
|
+
console.log(formatOutput(result, format));
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
|
+
process.exit(4);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
po.command("create").description("Create a purchase option from JSON file").requiredOption("--file <path>", "JSON file with purchase option data").action(async (options) => {
|
|
66
|
+
const config = await loadConfig();
|
|
67
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
68
|
+
const format = detectOutputFormat();
|
|
69
|
+
if (isDryRun(program)) {
|
|
70
|
+
printDryRun(
|
|
71
|
+
{
|
|
72
|
+
command: "purchase-options create",
|
|
73
|
+
action: "create",
|
|
74
|
+
target: `purchase option from ${options.file}`
|
|
75
|
+
},
|
|
76
|
+
format,
|
|
77
|
+
formatOutput
|
|
78
|
+
);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const client = await getClient(config);
|
|
82
|
+
try {
|
|
83
|
+
const data = JSON.parse(await readFile(options.file, "utf-8"));
|
|
84
|
+
const result = await createPurchaseOption(client, packageName, data);
|
|
85
|
+
console.log(formatOutput(result, format));
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
process.exit(4);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
po.command("activate <id>").description("Activate a purchase option").action(async (id) => {
|
|
92
|
+
const config = await loadConfig();
|
|
93
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
94
|
+
const format = detectOutputFormat();
|
|
95
|
+
if (isDryRun(program)) {
|
|
96
|
+
printDryRun(
|
|
97
|
+
{
|
|
98
|
+
command: "purchase-options activate",
|
|
99
|
+
action: "activate",
|
|
100
|
+
target: id
|
|
101
|
+
},
|
|
102
|
+
format,
|
|
103
|
+
formatOutput
|
|
104
|
+
);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const client = await getClient(config);
|
|
108
|
+
try {
|
|
109
|
+
const result = await activatePurchaseOption(client, packageName, id);
|
|
110
|
+
console.log(formatOutput(result, format));
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
113
|
+
process.exit(4);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
po.command("deactivate <id>").description("Deactivate a purchase option").action(async (id) => {
|
|
117
|
+
const config = await loadConfig();
|
|
118
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
119
|
+
const format = detectOutputFormat();
|
|
120
|
+
if (isDryRun(program)) {
|
|
121
|
+
printDryRun(
|
|
122
|
+
{
|
|
123
|
+
command: "purchase-options deactivate",
|
|
124
|
+
action: "deactivate",
|
|
125
|
+
target: id
|
|
126
|
+
},
|
|
127
|
+
format,
|
|
128
|
+
formatOutput
|
|
129
|
+
);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const client = await getClient(config);
|
|
133
|
+
try {
|
|
134
|
+
const result = await deactivatePurchaseOption(client, packageName, id);
|
|
135
|
+
console.log(formatOutput(result, format));
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
138
|
+
process.exit(4);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
registerPurchaseOptionsCommands
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=purchase-options-2NUBLODI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/purchase-options.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n listPurchaseOptions,\n getPurchaseOption,\n createPurchaseOption,\n activatePurchaseOption,\n deactivatePurchaseOption,\n detectOutputFormat,\n formatOutput,\n sortResults,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.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 registerPurchaseOptionsCommands(program: Command): void {\n const po = program\n .command(\"purchase-options\")\n .description(\"Manage purchase options\");\n\n po.command(\"list\")\n .description(\"List purchase options\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await listPurchaseOptions(client, packageName);\n if (options.sort) {\n result.purchaseOptions = sortResults(result.purchaseOptions, options.sort);\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 po.command(\"get <id>\")\n .description(\"Get a purchase option\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getPurchaseOption(client, packageName, id);\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 po.command(\"create\")\n .description(\"Create a purchase option from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with purchase option data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"purchase-options create\",\n action: \"create\",\n target: `purchase option from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = JSON.parse(await readFile(options.file, \"utf-8\"));\n const result = await createPurchaseOption(client, packageName, data);\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 po.command(\"activate <id>\")\n .description(\"Activate a purchase option\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"purchase-options activate\",\n action: \"activate\",\n target: id,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await activatePurchaseOption(client, packageName, id);\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 po.command(\"deactivate <id>\")\n .description(\"Deactivate a purchase option\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"purchase-options deactivate\",\n action: \"deactivate\",\n target: id,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await deactivatePurchaseOption(client, packageName, id);\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":"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","names":[]}
|