@gpc-cli/cli 0.9.35 → 0.9.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +9 -9
  2. package/dist/{anomalies-QZJGQXTZ.js → anomalies-KRRA75MJ.js} +1 -1
  3. package/dist/anomalies-KRRA75MJ.js.map +1 -0
  4. package/dist/{audit-4UPTLW37.js → audit-N2CRHWUN.js} +20 -4
  5. package/dist/audit-N2CRHWUN.js.map +1 -0
  6. package/dist/{auth-KPVEGAWV.js → auth-XGSTT5G5.js} +9 -3
  7. package/dist/auth-XGSTT5G5.js.map +1 -0
  8. package/dist/bin.js +2 -2
  9. package/dist/bin.js.map +1 -1
  10. package/dist/{bundle-7XYHNVNF.js → bundle-F43TD2BQ.js} +22 -13
  11. package/dist/{bundle-7XYHNVNF.js.map → bundle-F43TD2BQ.js.map} +1 -1
  12. package/dist/{cache-K23N6GJR.js → cache-SLNFRTI2.js} +7 -3
  13. package/dist/cache-SLNFRTI2.js.map +1 -0
  14. package/dist/{chunk-DDTPDKTB.js → chunk-EO7EJDT7.js} +49 -43
  15. package/dist/chunk-EO7EJDT7.js.map +1 -0
  16. package/dist/{chunk-7BXCQKJG.js → chunk-P5GF73XK.js} +1 -1
  17. package/dist/chunk-P5GF73XK.js.map +1 -0
  18. package/dist/{chunk-43SH6XEJ.js → chunk-U6ZTQ34I.js} +11 -13
  19. package/dist/chunk-U6ZTQ34I.js.map +1 -0
  20. package/dist/{completion-C3PPWNS7.js → completion-BCHRJSAT.js} +23 -10
  21. package/dist/completion-BCHRJSAT.js.map +1 -0
  22. package/dist/{config-REB7NINL.js → config-F2U3KUHX.js} +2 -2
  23. package/dist/{data-safety-GN5VBKAK.js → data-safety-JR6PZ2BD.js} +11 -8
  24. package/dist/data-safety-JR6PZ2BD.js.map +1 -0
  25. package/dist/{device-tiers-GHIYJPMB.js → device-tiers-5SGJPSYG.js} +7 -8
  26. package/dist/device-tiers-5SGJPSYG.js.map +1 -0
  27. package/dist/{docs-HIGQU4UL.js → docs-7DUXIKA3.js} +3 -3
  28. package/dist/docs-7DUXIKA3.js.map +1 -0
  29. package/dist/{doctor-QDIFTXNB.js → doctor-4BUPAVFT.js} +10 -8
  30. package/dist/doctor-4BUPAVFT.js.map +1 -0
  31. package/dist/{enterprise-IH5HXYRB.js → enterprise-7THXNBTC.js} +6 -2
  32. package/dist/{enterprise-IH5HXYRB.js.map → enterprise-7THXNBTC.js.map} +1 -1
  33. package/dist/{external-transactions-HCL7ROMN.js → external-transactions-O5P4QBIT.js} +5 -8
  34. package/dist/external-transactions-O5P4QBIT.js.map +1 -0
  35. package/dist/{feedback-NVGHRU7A.js → feedback-ERWH4SZF.js} +3 -3
  36. package/dist/{generated-apks-VX7HYZDU.js → generated-apks-KB2PLWDI.js} +2 -6
  37. package/dist/generated-apks-KB2PLWDI.js.map +1 -0
  38. package/dist/{grants-CXTTYKR3.js → grants-TKQJ3IER.js} +25 -6
  39. package/dist/grants-TKQJ3IER.js.map +1 -0
  40. package/dist/{iap-MBDD7VWP.js → iap-BNIAHBDN.js} +7 -3
  41. package/dist/iap-BNIAHBDN.js.map +1 -0
  42. package/dist/index.js +1 -1
  43. package/dist/{internal-sharing-E7SJYDW3.js → internal-sharing-M74VNIQ2.js} +7 -7
  44. package/dist/internal-sharing-M74VNIQ2.js.map +1 -0
  45. package/dist/{listings-7TWCGGMS.js → listings-IVHZJNES.js} +2 -2
  46. package/dist/listings-IVHZJNES.js.map +1 -0
  47. package/dist/{migrate-OHN2FDY6.js → migrate-SQT6RD6T.js} +2 -4
  48. package/dist/migrate-SQT6RD6T.js.map +1 -0
  49. package/dist/{one-time-products-2PK4QKWE.js → one-time-products-3WNXDKE3.js} +43 -28
  50. package/dist/one-time-products-3WNXDKE3.js.map +1 -0
  51. package/dist/{pricing-BYZSLN74.js → pricing-HMHZD44S.js} +1 -1
  52. package/dist/pricing-HMHZD44S.js.map +1 -0
  53. package/dist/{publish-XM43UA5R.js → publish-EPZXLGKZ.js} +3 -9
  54. package/dist/publish-EPZXLGKZ.js.map +1 -0
  55. package/dist/{purchases-WIDU3FDQ.js → purchases-7ZPVCN6D.js} +4 -2
  56. package/dist/purchases-7ZPVCN6D.js.map +1 -0
  57. package/dist/{quickstart-N7FXM5RQ.js → quickstart-EYNNOTVD.js} +2 -2
  58. package/dist/quickstart-EYNNOTVD.js.map +1 -0
  59. package/dist/quota-UHIQQYOY.js +58 -0
  60. package/dist/quota-UHIQQYOY.js.map +1 -0
  61. package/dist/{recovery-S5UNJDBO.js → recovery-YGPOVUFD.js} +7 -3
  62. package/dist/recovery-YGPOVUFD.js.map +1 -0
  63. package/dist/{releases-YRYM7JXC.js → releases-I7QQVKPJ.js} +59 -23
  64. package/dist/releases-I7QQVKPJ.js.map +1 -0
  65. package/dist/{reports-YOT4DQGL.js → reports-2YX3RDOS.js} +1 -1
  66. package/dist/reports-2YX3RDOS.js.map +1 -0
  67. package/dist/{reviews-NN7YQITF.js → reviews-MOVGATUI.js} +18 -9
  68. package/dist/reviews-MOVGATUI.js.map +1 -0
  69. package/dist/{status-L5S2FGZ4.js → status-G3AMJ34G.js} +5 -3
  70. package/dist/status-G3AMJ34G.js.map +1 -0
  71. package/dist/{subscriptions-OXAE7SNS.js → subscriptions-LSOJID6H.js} +8 -2
  72. package/dist/subscriptions-LSOJID6H.js.map +1 -0
  73. package/dist/{update-6XSZRXSU.js → update-O63L7KFJ.js} +6 -12
  74. package/dist/update-O63L7KFJ.js.map +1 -0
  75. package/dist/{users-JASXONRY.js → users-2YTC4Q36.js} +1 -1
  76. package/dist/users-2YTC4Q36.js.map +1 -0
  77. package/dist/{validate-NC4MWKOB.js → validate-VNIS6OEB.js} +2 -2
  78. package/dist/{version-2X32UAAE.js → version-JY5ITFST.js} +11 -9
  79. package/dist/version-JY5ITFST.js.map +1 -0
  80. package/dist/{vitals-LFL75LA6.js → vitals-H7DCI6JJ.js} +16 -9
  81. package/dist/vitals-H7DCI6JJ.js.map +1 -0
  82. package/package.json +5 -5
  83. package/dist/anomalies-QZJGQXTZ.js.map +0 -1
  84. package/dist/audit-4UPTLW37.js.map +0 -1
  85. package/dist/auth-KPVEGAWV.js.map +0 -1
  86. package/dist/cache-K23N6GJR.js.map +0 -1
  87. package/dist/chunk-43SH6XEJ.js.map +0 -1
  88. package/dist/chunk-7BXCQKJG.js.map +0 -1
  89. package/dist/chunk-DDTPDKTB.js.map +0 -1
  90. package/dist/completion-C3PPWNS7.js.map +0 -1
  91. package/dist/data-safety-GN5VBKAK.js.map +0 -1
  92. package/dist/device-tiers-GHIYJPMB.js.map +0 -1
  93. package/dist/docs-HIGQU4UL.js.map +0 -1
  94. package/dist/doctor-QDIFTXNB.js.map +0 -1
  95. package/dist/external-transactions-HCL7ROMN.js.map +0 -1
  96. package/dist/generated-apks-VX7HYZDU.js.map +0 -1
  97. package/dist/grants-CXTTYKR3.js.map +0 -1
  98. package/dist/iap-MBDD7VWP.js.map +0 -1
  99. package/dist/internal-sharing-E7SJYDW3.js.map +0 -1
  100. package/dist/listings-7TWCGGMS.js.map +0 -1
  101. package/dist/migrate-OHN2FDY6.js.map +0 -1
  102. package/dist/one-time-products-2PK4QKWE.js.map +0 -1
  103. package/dist/pricing-BYZSLN74.js.map +0 -1
  104. package/dist/publish-XM43UA5R.js.map +0 -1
  105. package/dist/purchases-WIDU3FDQ.js.map +0 -1
  106. package/dist/quickstart-N7FXM5RQ.js.map +0 -1
  107. package/dist/quota-SNUI75NM.js +0 -53
  108. package/dist/quota-SNUI75NM.js.map +0 -1
  109. package/dist/recovery-S5UNJDBO.js.map +0 -1
  110. package/dist/releases-YRYM7JXC.js.map +0 -1
  111. package/dist/reports-YOT4DQGL.js.map +0 -1
  112. package/dist/reviews-NN7YQITF.js.map +0 -1
  113. package/dist/status-L5S2FGZ4.js.map +0 -1
  114. package/dist/subscriptions-OXAE7SNS.js.map +0 -1
  115. package/dist/update-6XSZRXSU.js.map +0 -1
  116. package/dist/users-JASXONRY.js.map +0 -1
  117. package/dist/version-2X32UAAE.js.map +0 -1
  118. package/dist/vitals-LFL75LA6.js.map +0 -1
  119. /package/dist/{config-REB7NINL.js.map → config-F2U3KUHX.js.map} +0 -0
  120. /package/dist/{feedback-NVGHRU7A.js.map → feedback-ERWH4SZF.js.map} +0 -0
  121. /package/dist/{validate-NC4MWKOB.js.map → validate-VNIS6OEB.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/plugins.ts","../src/program.ts","../src/error-handler.ts"],"sourcesContent":["import { PluginManager, discoverPlugins } from \"@gpc-cli/core\";\nimport type { Command } from \"commander\";\n\n/**\n * Load and initialize all plugins.\n * First-party plugins (@gpc-cli/*) are auto-trusted.\n * Third-party plugins require prior approval stored in config.\n * Plugin loading is disabled in standalone binary mode.\n */\nexport async function loadPlugins(): Promise<PluginManager> {\n const manager = new PluginManager();\n\n // Standalone binary cannot resolve external npm packages at runtime\n if (process.env[\"__GPC_BINARY\"] === \"1\") {\n return manager;\n }\n\n try {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const plugins = await discoverPlugins({ configPlugins: config.plugins });\n const approved = new Set(config.approvedPlugins ?? []);\n\n for (const plugin of plugins) {\n const isTrusted = plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && !approved.has(plugin.name)) {\n // Skip unapproved third-party plugins silently in non-interactive mode\n // In interactive mode, the user would run `gpc plugins approve <name>` first\n const isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n if (!isQuiet) {\n console.error(\n `Plugin \"${plugin.name}\" is not approved. Run: gpc plugins approve ${plugin.name}`,\n );\n }\n continue;\n }\n\n try {\n await manager.load(plugin);\n } catch {\n // Skip plugins that fail to load — don't block the CLI\n }\n }\n } catch {\n // Config loading failure shouldn't block plugin-free commands\n }\n\n return manager;\n}\n\n/**\n * Register plugin-defined commands with the Commander program.\n */\nexport function registerPluginCommands(program: Command, manager: PluginManager): void {\n for (const def of manager.getRegisteredCommands()) {\n const cmd = program.command(def.name).description(def.description);\n\n if (def.arguments) {\n for (const arg of def.arguments) {\n const syntax = arg.required ? `<${arg.name}>` : `[${arg.name}]`;\n cmd.argument(syntax, arg.description);\n }\n }\n\n if (def.options) {\n for (const opt of def.options) {\n cmd.option(\n opt.flags,\n opt.description,\n opt.defaultValue as string | boolean | string[] | undefined,\n );\n }\n }\n\n cmd.action(async (...rawArgs: unknown[]) => {\n const opts = rawArgs[rawArgs.length - 2] as Record<string, unknown>;\n const args: Record<string, unknown> = {};\n\n if (def.arguments) {\n def.arguments.forEach((argDef, i) => {\n args[argDef.name] = rawArgs[i];\n });\n }\n\n await def.action(args, opts);\n });\n }\n}\n","import { Command } from \"commander\";\nimport type { PluginManager } from \"@gpc-cli/core\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\nimport { registerPluginCommands } from \"./plugins.js\";\n\nexport async function createProgram(pluginManager?: PluginManager): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"gpc\")\n .description(\"GPC — Google Play Console CLI\")\n .version(process.env[\"__GPC_VERSION\"] || \"0.0.0\", \"-V, --version\")\n .option(\"-o, --output <format>\", \"Output format: table, json, yaml, markdown, junit\")\n .option(\"-v, --verbose\", \"Enable debug logging\")\n .option(\"-q, --quiet\", \"Suppress non-essential output\")\n .option(\"-a, --app <package>\", \"App package name\")\n .option(\"-p, --profile <name>\", \"Auth profile name\")\n .option(\"--no-color\", \"Disable colored output\")\n .option(\"--no-interactive\", \"Disable interactive prompts\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without executing\")\n .option(\"--notify [target]\", \"Send webhook notification on completion (slack, discord, custom)\")\n .option(\"--ci\", \"Force CI mode (JSON output, no prompts, strict exit codes)\")\n .option(\"-j, --json\", \"Shorthand for --output json\")\n .option(\"--apps <csv>\", \"Comma-separated package names for multi-app operations\")\n .showSuggestionAfterError(false);\n\n const commandLoaders: Record<string, () => Promise<void>> = {\n auth: async () => {\n (await import(\"./commands/auth.js\")).registerAuthCommands(program);\n },\n config: async () => {\n (await import(\"./commands/config.js\")).registerConfigCommands(program);\n },\n doctor: async () => {\n (await import(\"./commands/doctor.js\")).registerDoctorCommand(program);\n },\n update: async () => {\n (await import(\"./commands/update.js\")).registerUpdateCommand(program);\n },\n docs: async () => {\n (await import(\"./commands/docs.js\")).registerDocsCommand(program);\n },\n completion: async () => {\n (await import(\"./commands/completion.js\")).registerCompletionCommand(program);\n },\n apps: async () => {\n (await import(\"./commands/apps.js\")).registerAppsCommands(program);\n },\n releases: async () => {\n (await import(\"./commands/releases.js\")).registerReleasesCommands(program);\n },\n tracks: async () => {\n (await import(\"./commands/tracks.js\")).registerTracksCommands(program);\n },\n status: async () => {\n (await import(\"./commands/status.js\")).registerStatusCommand(program);\n },\n listings: async () => {\n (await import(\"./commands/listings.js\")).registerListingsCommands(program);\n },\n reviews: async () => {\n (await import(\"./commands/reviews.js\")).registerReviewsCommands(program);\n },\n vitals: async () => {\n (await import(\"./commands/vitals.js\")).registerVitalsCommands(program);\n },\n subscriptions: async () => {\n (await import(\"./commands/subscriptions.js\")).registerSubscriptionsCommands(program);\n },\n iap: async () => {\n (await import(\"./commands/iap.js\")).registerIapCommands(program);\n },\n purchases: async () => {\n (await import(\"./commands/purchases.js\")).registerPurchasesCommands(program);\n },\n pricing: async () => {\n (await import(\"./commands/pricing.js\")).registerPricingCommands(program);\n },\n reports: async () => {\n (await import(\"./commands/reports.js\")).registerReportsCommands(program);\n },\n users: async () => {\n (await import(\"./commands/users.js\")).registerUsersCommands(program);\n },\n testers: async () => {\n (await import(\"./commands/testers.js\")).registerTestersCommands(program);\n },\n validate: async () => {\n (await import(\"./commands/validate.js\")).registerValidateCommand(program);\n },\n publish: async () => {\n (await import(\"./commands/publish.js\")).registerPublishCommand(program);\n },\n recovery: async () => {\n (await import(\"./commands/recovery.js\")).registerRecoveryCommands(program);\n },\n \"data-safety\": async () => {\n (await import(\"./commands/data-safety.js\")).registerDataSafetyCommands(program);\n },\n \"external-transactions\": async () => {\n (await import(\"./commands/external-transactions.js\")).registerExternalTransactionsCommands(\n program,\n );\n },\n \"device-tiers\": async () => {\n (await import(\"./commands/device-tiers.js\")).registerDeviceTiersCommands(program);\n },\n \"one-time-products\": async () => {\n (await import(\"./commands/one-time-products.js\")).registerOneTimeProductsCommands(program);\n },\n \"internal-sharing\": async () => {\n (await import(\"./commands/internal-sharing.js\")).registerInternalSharingCommands(program);\n },\n \"generated-apks\": async () => {\n (await import(\"./commands/generated-apks.js\")).registerGeneratedApksCommands(program);\n },\n \"purchase-options\": async () => {\n (await import(\"./commands/purchase-options.js\")).registerPurchaseOptionsCommands(program);\n },\n bundle: async () => {\n (await import(\"./commands/bundle.js\")).registerBundleCommands(program);\n },\n audit: async () => {\n (await import(\"./commands/audit.js\")).registerAuditCommands(program);\n },\n migrate: async () => {\n (await import(\"./commands/migrate.js\")).registerMigrateCommands(program);\n },\n anomalies: async () => {\n (await import(\"./commands/anomalies.js\")).registerAnomaliesCommands(program);\n },\n \"install-skills\": async () => {\n (await import(\"./commands/install-skills.js\")).registerInstallSkillsCommand(program);\n },\n version: async () => {\n (await import(\"./commands/version.js\")).registerVersionCommand(program);\n },\n cache: async () => {\n (await import(\"./commands/cache.js\")).registerCacheCommand(program);\n },\n feedback: async () => {\n (await import(\"./commands/feedback.js\")).registerFeedbackCommand(program);\n },\n quickstart: async () => {\n (await import(\"./commands/quickstart.js\")).registerQuickstartCommand(program);\n },\n grants: async () => {\n (await import(\"./commands/grants.js\")).registerGrantsCommands(program);\n },\n train: async () => {\n (await import(\"./commands/train.js\")).registerTrainCommands(program);\n },\n quota: async () => {\n (await import(\"./commands/quota.js\")).registerQuotaCommand(program);\n },\n games: async () => {\n (await import(\"./commands/games.js\")).registerGamesCommands(program);\n },\n enterprise: async () => {\n (await import(\"./commands/enterprise.js\")).registerEnterpriseCommands(program);\n },\n plugins: async () => {\n registerPluginsCommand(program, pluginManager);\n },\n };\n\n // \"Did you mean?\" suggestions for unknown commands\n function levenshtein(a: string, b: string): number {\n const m = a.length, n = b.length;\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\n );\n const cell = (r: number, c: number): number => dp[r]?.[c] ?? 0;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n (dp[i] as number[])[j] = a[i - 1] === b[j - 1]\n ? cell(i - 1, j - 1)\n : 1 + Math.min(cell(i - 1, j), cell(i, j - 1), cell(i - 1, j - 1));\n }\n }\n return cell(m, n);\n }\n\n program.on(\"command:*\", (operands: string[]) => {\n const cmd = operands[0] ?? \"\";\n const names = Object.keys(commandLoaders);\n const best = names.map(name => ({ name, d: levenshtein(cmd, name) })).sort((a, b) => a.d - b.d)[0];\n console.error(`Error: Unknown command \"${cmd}\".`);\n if (best && best.d <= 3) console.error(`Did you mean: gpc ${best.name}?`);\n console.error(`Run \"gpc --help\" to see all commands.`);\n process.exit(2);\n });\n\n // Resolve command aliases for lazy loading\n const commandAliases: Record<string, string> = {\n \"ext-txn\": \"external-transactions\",\n otp: \"one-time-products\",\n };\n\n const rawTarget = process.argv[2];\n const target = rawTarget ? (commandAliases[rawTarget] ?? rawTarget) : undefined;\n\n const loader = target ? commandLoaders[target] : undefined;\n if (loader) {\n await loader();\n } else {\n await Promise.all(Object.values(commandLoaders).map((loader) => loader()));\n }\n\n // Register plugin-defined commands\n if (pluginManager) {\n registerPluginCommands(program, pluginManager);\n }\n\n // Wire plugin lifecycle hooks around command execution\n if (pluginManager) {\n wrapCommandHooks(program, pluginManager);\n }\n\n return program;\n}\n\n/**\n * `gpc plugins` — manage plugins.\n */\nfunction registerPluginsCommand(program: Command, manager?: PluginManager): void {\n const cmd = program.command(\"plugins\").description(\"Manage plugins\");\n\n cmd\n .command(\"list\")\n .description(\"List loaded plugins\")\n .action(() => {\n const plugins = manager?.getLoadedPlugins() ?? [];\n const opts = program.opts();\n\n if (opts[\"output\"] === \"json\") {\n console.log(JSON.stringify(plugins, null, 2));\n return;\n }\n\n if (plugins.length === 0) {\n console.log(\"No plugins loaded.\");\n console.log('\\nConfigure plugins in .gpcrc.json: { \"plugins\": [\"@gpc-cli/plugin-ci\"] }');\n return;\n }\n\n console.log(\"Loaded plugins:\\n\");\n for (const p of plugins) {\n const trust = p.trusted ? \"trusted\" : \"third-party\";\n console.log(` ${p.name}@${p.version} (${trust})`);\n }\n\n const commands = manager?.getRegisteredCommands() ?? [];\n if (commands.length > 0) {\n console.log(\"\\nPlugin commands:\\n\");\n for (const c of commands) {\n console.log(` gpc ${c.name} — ${c.description}`);\n }\n }\n });\n\n cmd\n .command(\"init <name>\")\n .description(\"Scaffold a new plugin project\")\n .option(\"-d, --dir <path>\", \"Output directory (defaults to ./gpc-plugin-<name>)\")\n .option(\"--description <text>\", \"Plugin description\")\n .action(async (name: string, opts: { dir?: string; description?: string }) => {\n const { scaffoldPlugin } = await import(\"@gpc-cli/core\");\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const dir = opts.dir ?? `./${pluginName}`;\n\n const result = await scaffoldPlugin({ name, dir, description: opts.description });\n\n console.log(`Plugin scaffolded at ${result.dir}/\\n`);\n console.log(\"Files created:\");\n for (const f of result.files) {\n console.log(` ${f}`);\n }\n console.log(`\\nNext steps:`);\n console.log(` cd ${pluginName}`);\n console.log(` npm install`);\n console.log(` npm run build`);\n console.log(` npm test`);\n });\n\n cmd\n .command(\"approve <name>\")\n .description(\"Approve a third-party plugin for loading\")\n .action(async (name: string) => {\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`Plugin \"${name}\" approved. It will be loaded on next run.`);\n });\n\n cmd\n .command(\"revoke <name>\")\n .description(\"Revoke approval for a third-party plugin\")\n .action(async (name: string) => {\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n const removed = await revokePluginApproval(name);\n if (removed) {\n console.log(`Plugin \"${name}\" approval revoked.`);\n } else {\n console.log(`Plugin \"${name}\" was not in the approved list.`);\n }\n });\n\n const REGISTRY_URL =\n \"https://raw.githubusercontent.com/yasserstudio/gpc-plugins/main/registry.json\";\n\n interface RegistryPlugin {\n name: string;\n description: string;\n version: string;\n author?: string;\n tags?: string[];\n }\n\n cmd\n .command(\"search [query]\")\n .description(\"Search the GPC plugin registry\")\n .action(async (query?: string) => {\n try {\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) throw new Error(`Registry fetch failed: ${res.status}`);\n const plugins = (await res.json()) as RegistryPlugin[];\n const filtered = query\n ? plugins.filter(\n (p) =>\n p.name.includes(query) ||\n p.description?.toLowerCase().includes(query.toLowerCase()),\n )\n : plugins;\n\n if (filtered.length === 0) {\n console.log(`No plugins found${query ? ` matching \"${query}\"` : \"\"}.`);\n return;\n }\n\n for (const p of filtered) {\n console.log(` ${p.name}@${p.version}`);\n if (p.description) console.log(` ${p.description}`);\n }\n console.log(`\\nInstall: gpc plugins install <name>`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n cmd\n .command(\"install <name>\")\n .description(\"Install a plugin from npm\")\n .action(async (name: string) => {\n const { execSync } = await import(\"node:child_process\");\n console.log(`Installing plugin \"${name}\"...`);\n try {\n execSync(`npm install -g ${name}`, { stdio: \"inherit\" });\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`\\nPlugin \"${name}\" installed and approved. It will be loaded on next run.`);\n console.log(`Configure it in .gpcrc.json: { \"plugins\": [\"${name}\"] }`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n cmd\n .command(\"uninstall <name>\")\n .description(\"Uninstall a plugin and revoke its approval\")\n .action(async (name: string) => {\n const { execSync } = await import(\"node:child_process\");\n console.log(`Uninstalling plugin \"${name}\"...`);\n try {\n execSync(`npm uninstall -g ${name}`, { stdio: \"inherit\" });\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n await revokePluginApproval(name);\n console.log(`\\nPlugin \"${name}\" uninstalled and approval revoked.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n\n/**\n * Wrap all registered commands so plugin hooks fire before/after each command.\n */\nfunction wrapCommandHooks(program: Command, manager: PluginManager): void {\n program.hook(\"preAction\", async (thisCommand) => {\n const event: CommandEvent = {\n command: getFullCommandName(thisCommand),\n args: thisCommand.opts(),\n app: program.opts()[\"app\"] as string | undefined,\n startedAt: new Date(),\n };\n\n // Store on the command for afterCommand/onError\n (thisCommand as unknown as Record<string, unknown>)[\"__pluginEvent\"] = event;\n\n await manager.runBeforeCommand(event);\n });\n\n program.hook(\"postAction\", async (thisCommand) => {\n const event: CommandEvent = (thisCommand as unknown as Record<string, unknown>)[\n \"__pluginEvent\"\n ] as CommandEvent;\n if (!event) return;\n\n const result: CommandResult = {\n success: true,\n durationMs: Date.now() - event.startedAt.getTime(),\n exitCode: 0,\n };\n\n await manager.runAfterCommand(event, result);\n });\n}\n\nfunction getFullCommandName(cmd: Command): string {\n const parts: string[] = [];\n let current: Command | null = cmd;\n while (current && current.name() !== \"gpc\") {\n parts.unshift(current.name());\n current = current.parent;\n }\n return parts.join(\" \");\n}\n","/**\n * Shared error formatting for CLI output.\n * Extracts error code, message, and suggestion from typed errors (GpcError, AuthError, ApiError, ConfigError).\n */\n\ninterface TypedError {\n message: string;\n code?: string;\n suggestion?: string;\n exitCode?: number;\n}\n\nfunction isTypedError(error: unknown): error is Error & TypedError {\n return error instanceof Error && \"code\" in error && typeof (error as TypedError).code === \"string\";\n}\n\nconst AUTH_KEYWORDS = [\"AUTH\", \"UNAUTHENTICATED\", \"PERMISSION_DENIED\", \"401\", \"403\"];\n\nfunction isAuthRelatedError(error: unknown): boolean {\n if (isTypedError(error)) {\n if (error.exitCode === 3) return true;\n if (error.code && AUTH_KEYWORDS.some((k) => error.code?.includes(k))) return true;\n }\n const msg = error instanceof Error ? error.message : String(error);\n return AUTH_KEYWORDS.some((k) => msg.includes(k));\n}\n\n/**\n * Format an error for CLI output. Prints:\n * Error [CODE]: message\n * Suggestion: suggestion (if available)\n *\n * Returns the appropriate exit code.\n */\nexport function handleCliError(error: unknown): number {\n const authHint = isAuthRelatedError(error)\n ? \"\\n→ Run gpc doctor to diagnose your credentials.\"\n : \"\";\n\n if (isTypedError(error)) {\n console.error(`Error [${error.code}]: ${error.message}`);\n if (error.suggestion) {\n console.error(`Suggestion: ${error.suggestion}`);\n }\n if (authHint) console.error(authHint);\n return error.exitCode ?? 1;\n }\n\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n if (authHint) console.error(authHint);\n return 1;\n}\n"],"mappings":"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","names":["_","loader"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/completion.ts"],"sourcesContent":["import type { Command } from \"commander\";\n\nexport type ShellType = \"bash\" | \"zsh\" | \"fish\" | \"powershell\";\n\nexport const SUPPORTED_SHELLS: readonly ShellType[] = [\"bash\", \"zsh\", \"fish\", \"powershell\"] as const;\n\n/**\n * Full command tree for gpc CLI.\n * Each entry maps a command name to its description and optional subcommands.\n */\ninterface CommandDef {\n description: string;\n subcommands?: Record<string, CommandDef>;\n}\n\nexport function getCommandTree(): Record<string, CommandDef> {\n return {\n auth: {\n description: \"Manage authentication\",\n subcommands: {\n login: { description: \"Authenticate with Google Play Developer API\" },\n status: { description: \"Show current authentication status\" },\n logout: { description: \"Remove stored credentials\" },\n whoami: { description: \"Show the authenticated account\" },\n },\n },\n config: {\n description: \"Manage configuration\",\n subcommands: {\n init: { description: \"Create a configuration file\" },\n show: { description: \"Show current configuration\" },\n set: { description: \"Set a configuration value\" },\n path: { description: \"Show the configuration file path\" },\n },\n },\n apps: {\n description: \"Manage applications\",\n subcommands: {\n info: { description: \"Show app details\" },\n update: { description: \"Update app details\" },\n list: { description: \"List configured applications\" },\n },\n },\n releases: {\n description: \"Manage releases and rollouts\",\n subcommands: {\n upload: { description: \"Upload AAB/APK and assign to a track\" },\n status: { description: \"Show current release status across tracks\" },\n promote: { description: \"Promote a release from one track to another\" },\n rollout: {\n description: \"Manage staged rollouts\",\n subcommands: {\n increase: { description: \"Increase a staged rollout\" },\n halt: { description: \"Halt a staged rollout\" },\n resume: { description: \"Resume a staged rollout\" },\n complete: { description: \"Complete a staged rollout\" },\n },\n },\n notes: { description: \"Set release notes\" },\n },\n },\n tracks: {\n description: \"Manage tracks\",\n subcommands: {\n list: { description: \"List all tracks\" },\n },\n },\n status: { description: \"Cross-track release overview\" },\n listings: {\n description: \"Manage store listings and metadata\",\n subcommands: {\n get: { description: \"Get store listing(s)\" },\n update: { description: \"Update a store listing\" },\n delete: { description: \"Delete a store listing for a language\" },\n pull: { description: \"Download listings to Fastlane-format directory\" },\n push: { description: \"Upload listings from Fastlane-format directory\" },\n images: {\n description: \"Manage listing images\",\n subcommands: {\n list: { description: \"List images for a language and type\" },\n upload: { description: \"Upload an image\" },\n delete: { description: \"Delete an image\" },\n },\n },\n availability: { description: \"Get country availability for a track\" },\n },\n },\n reviews: {\n description: \"Manage user reviews and ratings\",\n subcommands: {\n list: { description: \"List user reviews\" },\n get: { description: \"Get a single review\" },\n reply: { description: \"Reply to a review\" },\n export: { description: \"Export reviews to JSON or CSV\" },\n },\n },\n vitals: {\n description: \"Monitor app vitals and performance metrics\",\n subcommands: {\n overview: { description: \"Dashboard summary of all vital metrics\" },\n crashes: { description: \"Query crash rate metrics\" },\n anr: { description: \"Query ANR rate metrics\" },\n startup: { description: \"Query slow startup metrics\" },\n rendering: { description: \"Query slow rendering metrics\" },\n battery: { description: \"Query excessive wakeup metrics\" },\n memory: { description: \"Query stuck wakelock metrics\" },\n anomalies: { description: \"Detect anomalies in app vitals\" },\n errors: {\n description: \"Search and view error issues\",\n subcommands: {\n search: { description: \"Search error issues\" },\n },\n },\n compare: { description: \"Compare metric trend between periods\" },\n },\n },\n subscriptions: {\n description: \"Manage subscriptions and base plans\",\n subcommands: {\n list: { description: \"List subscriptions\" },\n get: { description: \"Get a subscription\" },\n create: { description: \"Create a subscription from JSON file\" },\n update: { description: \"Update a subscription from JSON file\" },\n delete: { description: \"Delete a subscription\" },\n \"base-plans\": {\n description: \"Manage base plans\",\n subcommands: {\n activate: { description: \"Activate a base plan\" },\n deactivate: { description: \"Deactivate a base plan\" },\n delete: { description: \"Delete a base plan\" },\n \"migrate-prices\": { description: \"Migrate base plan prices\" },\n },\n },\n offers: {\n description: \"Manage subscription offers\",\n subcommands: {\n list: { description: \"List offers for a base plan\" },\n get: { description: \"Get an offer\" },\n create: { description: \"Create an offer from JSON file\" },\n update: { description: \"Update an offer from JSON file\" },\n delete: { description: \"Delete an offer\" },\n activate: { description: \"Activate an offer\" },\n deactivate: { description: \"Deactivate an offer\" },\n },\n },\n },\n },\n iap: {\n description: \"Manage in-app products\",\n subcommands: {\n list: { description: \"List in-app products\" },\n get: { description: \"Get an in-app product\" },\n create: { description: \"Create an in-app product from JSON file\" },\n update: { description: \"Update an in-app product from JSON file\" },\n delete: { description: \"Delete an in-app product\" },\n sync: { description: \"Sync in-app products from a directory\" },\n },\n },\n purchases: {\n description: \"Manage purchases and orders\",\n subcommands: {\n get: { description: \"Get a product purchase\" },\n acknowledge: { description: \"Acknowledge a product purchase\" },\n consume: { description: \"Consume a product purchase\" },\n subscription: {\n description: \"Manage subscription purchases\",\n subcommands: {\n get: { description: \"Get a subscription purchase\" },\n cancel: { description: \"Cancel a subscription\" },\n defer: { description: \"Defer a subscription expiry\" },\n revoke: { description: \"Revoke a subscription\" },\n },\n },\n voided: { description: \"List voided purchases\" },\n orders: {\n description: \"Manage orders\",\n subcommands: {\n refund: { description: \"Refund an order\" },\n },\n },\n },\n },\n pricing: {\n description: \"Pricing and regional price conversion\",\n subcommands: {\n convert: { description: \"Convert a price to all regional prices\" },\n },\n },\n reports: {\n description: \"Download financial and stats reports\",\n subcommands: {\n list: { description: \"List available report buckets\" },\n download: {\n description: \"Download a report\",\n subcommands: {\n financial: { description: \"Download a financial report\" },\n stats: { description: \"Download a stats report\" },\n },\n },\n },\n },\n users: {\n description: \"Manage developer account users and permissions\",\n subcommands: {\n list: { description: \"List all users in the developer account\" },\n get: { description: \"Get user details\" },\n invite: { description: \"Invite a user to the developer account\" },\n update: { description: \"Update user permissions\" },\n remove: { description: \"Remove a user from the developer account\" },\n },\n },\n testers: {\n description: \"Manage testers and tester groups\",\n subcommands: {\n list: { description: \"List testers for a track\" },\n add: { description: \"Add testers to a track\" },\n remove: { description: \"Remove testers from a track\" },\n import: { description: \"Import testers from a CSV file\" },\n },\n },\n recovery: {\n description: \"Manage app recovery actions\",\n subcommands: {\n list: { description: \"List app recovery actions\" },\n cancel: { description: \"Cancel a recovery action\" },\n deploy: { description: \"Deploy a recovery action\" },\n create: { description: \"Create a recovery action\" },\n \"add-targeting\": { description: \"Add targeting to a recovery action\" },\n },\n },\n \"data-safety\": {\n description: \"Manage data safety declarations\",\n subcommands: {\n get: { description: \"Get data safety declaration\" },\n update: { description: \"Update data safety declaration\" },\n export: { description: \"Export data safety declaration\" },\n },\n },\n \"external-transactions\": {\n description: \"Manage external transactions\",\n subcommands: {\n create: { description: \"Create an external transaction\" },\n get: { description: \"Get an external transaction\" },\n refund: { description: \"Refund an external transaction\" },\n },\n },\n \"device-tiers\": {\n description: \"Manage device tier configurations\",\n subcommands: {\n list: { description: \"List device tier configurations\" },\n get: { description: \"Get a device tier configuration\" },\n create: { description: \"Create a device tier configuration\" },\n },\n },\n \"one-time-products\": {\n description: \"Manage one-time products\",\n subcommands: {\n list: { description: \"List one-time products\" },\n get: { description: \"Get a one-time product\" },\n create: { description: \"Create a one-time product\" },\n update: { description: \"Update a one-time product\" },\n delete: { description: \"Delete a one-time product\" },\n offers: {\n description: \"Manage one-time product offers\",\n subcommands: {\n list: { description: \"List offers for a one-time product\" },\n get: { description: \"Get a one-time product offer\" },\n create: { description: \"Create a one-time product offer\" },\n update: { description: \"Update a one-time product offer\" },\n delete: { description: \"Delete a one-time product offer\" },\n },\n },\n },\n },\n \"internal-sharing\": {\n description: \"Manage internal app sharing\",\n subcommands: {\n upload: { description: \"Upload an artifact for internal sharing\" },\n },\n },\n \"generated-apks\": {\n description: \"Manage generated APKs from app bundles\",\n subcommands: {\n list: { description: \"List generated APKs for a version\" },\n download: { description: \"Download a generated APK\" },\n },\n },\n doctor: { description: \"Verify setup and connectivity\" },\n docs: { description: \"Open documentation in browser\" },\n validate: { description: \"Pre-submission validation checks\" },\n publish: { description: \"Validate, upload, and release in one step\" },\n completion: {\n description: \"Generate shell completions\",\n subcommands: {\n bash: { description: \"Generate bash completions\" },\n zsh: { description: \"Generate zsh completions\" },\n fish: { description: \"Generate fish completions\" },\n powershell: { description: \"Generate PowerShell completions\" },\n },\n },\n plugins: {\n description: \"Manage plugins\",\n subcommands: {\n list: { description: \"List loaded plugins\" },\n init: { description: \"Scaffold a new plugin project\" },\n approve: { description: \"Approve a third-party plugin for loading\" },\n revoke: { description: \"Revoke approval for a third-party plugin\" },\n },\n },\n };\n}\n\nexport function registerCompletionCommand(program: Command): void {\n const completion = program.command(\"completion\").description(\"Generate shell completions\");\n\n completion\n .command(\"bash\")\n .description(\"Generate bash completions\")\n .action(() => {\n console.log(generateBashCompletions());\n });\n\n completion\n .command(\"zsh\")\n .description(\"Generate zsh completions\")\n .action(() => {\n console.log(generateZshCompletions());\n });\n\n completion\n .command(\"fish\")\n .description(\"Generate fish completions\")\n .action(() => {\n console.log(generateFishCompletions());\n });\n\n completion\n .command(\"powershell\")\n .description(\"Generate PowerShell completions\")\n .action(() => {\n console.log(generatePowerShellCompletions());\n });\n}\n\nexport function generateBashCompletions(): string {\n const tree = getCommandTree();\n\n const topLevelNames = Object.keys(tree).join(\" \");\n\n // Build case entries for each command that has subcommands (up to 3 levels)\n const caseEntries: string[] = [];\n\n for (const [cmd, def] of Object.entries(tree)) {\n if (def.subcommands) {\n const subNames = Object.keys(def.subcommands).join(\" \");\n caseEntries.push(` ${cmd})\\n COMPREPLY=( $(compgen -W \"${subNames}\" -- \"\\${cur}\") )\\n return 0\\n ;;`);\n\n // Level 3: subcommands of subcommands\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (subDef.subcommands) {\n const subSubNames = Object.keys(subDef.subcommands).join(\" \");\n caseEntries.push(` ${sub})\\n COMPREPLY=( $(compgen -W \"${subSubNames}\" -- \"\\${cur}\") )\\n return 0\\n ;;`);\n }\n }\n }\n }\n\n return `# bash completion for gpc\n# Install: gpc completion bash >> ~/.bashrc\n_gpc() {\n local cur prev commands\n COMPREPLY=()\n cur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n prev=\"\\${COMP_WORDS[COMP_CWORD-1]}\"\n\n commands=\"${topLevelNames}\"\n\n case \"\\${prev}\" in\n gpc)\n COMPREPLY=( $(compgen -W \"\\${commands}\" -- \"\\${cur}\") )\n return 0\n ;;\n${caseEntries.join(\"\\n\")}\n esac\n\n COMPREPLY=( $(compgen -W \"\\${commands}\" -- \"\\${cur}\") )\n return 0\n}\n\ncomplete -F _gpc gpc`;\n}\n\nexport function generateZshCompletions(): string {\n const tree = getCommandTree();\n\n // Build zsh arrays\n const arrayDefs: string[] = [];\n const caseBranches: string[] = [];\n\n // Top-level\n const topEntries = Object.entries(tree)\n .map(([name, def]) => ` '${name}:${escapeZsh(def.description)}'`)\n .join(\"\\n\");\n arrayDefs.push(` commands=(\\n${topEntries}\\n )`);\n\n // Build subcommand arrays and case branches for level 2\n for (const [cmd, def] of Object.entries(tree)) {\n if (def.subcommands) {\n const varName = `${cmd.replace(/-/g, \"_\")}_commands`;\n const entries = Object.entries(def.subcommands)\n .map(([name, sub]) => ` '${name}:${escapeZsh(sub.description)}'`)\n .join(\"\\n\");\n arrayDefs.push(` ${varName}=(\\n${entries}\\n )`);\n caseBranches.push(` ${cmd})\\n _describe -t ${varName} '${cmd} commands' ${varName}\\n ;;`);\n\n // Level 3\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (subDef.subcommands) {\n const subVarName = `${cmd.replace(/-/g, \"_\")}_${sub.replace(/-/g, \"_\")}_commands`;\n const subEntries = Object.entries(subDef.subcommands)\n .map(([name, s]) => ` '${name}:${escapeZsh(s.description)}'`)\n .join(\"\\n\");\n arrayDefs.push(` ${subVarName}=(\\n${subEntries}\\n )`);\n }\n }\n }\n }\n\n // Build level 3 case for subsubcommand state\n const level3Cases: string[] = [];\n for (const [cmd, def] of Object.entries(tree)) {\n if (!def.subcommands) continue;\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (subDef.subcommands) {\n const subVarName = `${cmd.replace(/-/g, \"_\")}_${sub.replace(/-/g, \"_\")}_commands`;\n level3Cases.push(` ${sub})\\n _describe -t ${subVarName} '${sub} commands' ${subVarName}\\n ;;`);\n }\n }\n }\n\n // Collect all variable names for local declarations\n const varNames: string[] = [\"commands\"];\n for (const [cmd, def] of Object.entries(tree)) {\n if (def.subcommands) {\n varNames.push(`${cmd.replace(/-/g, \"_\")}_commands`);\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (subDef.subcommands) {\n varNames.push(`${cmd.replace(/-/g, \"_\")}_${sub.replace(/-/g, \"_\")}_commands`);\n }\n }\n }\n }\n\n const localDecls = varNames.map((v) => ` local -a ${v}`).join(\"\\n\");\n\n return `#compdef gpc\n# Install: gpc completion zsh > ~/.zsh/completions/_gpc\n\n_gpc() {\n${localDecls}\n\n${arrayDefs.join(\"\\n\\n\")}\n\n _arguments -C \\\\\n '1: :->command' \\\\\n '2: :->subcommand' \\\\\n '3: :->subsubcommand' \\\\\n '*::arg:->args'\n\n case \"$state\" in\n command)\n _describe -t commands 'gpc commands' commands\n ;;\n subcommand)\n case \"$words[2]\" in\n${caseBranches.join(\"\\n\")}\n esac\n ;;\n subsubcommand)\n case \"$words[3]\" in\n${level3Cases.join(\"\\n\")}\n esac\n ;;\n esac\n}\n\n_gpc \"$@\"`;\n}\n\nexport function generateFishCompletions(): string {\n const tree = getCommandTree();\n const lines: string[] = [\n \"# fish completions for gpc\",\n \"# Install: gpc completion fish > ~/.config/fish/completions/gpc.fish\",\n \"\",\n \"# Disable file completions by default\",\n \"complete -c gpc -f\",\n \"\",\n \"# Top-level commands\",\n ];\n\n for (const [cmd, def] of Object.entries(tree)) {\n lines.push(\n `complete -c gpc -n '__fish_use_subcommand' -a ${cmd} -d '${escapeFish(def.description)}'`,\n );\n }\n\n // Level 2 subcommands\n for (const [cmd, def] of Object.entries(tree)) {\n if (!def.subcommands) continue;\n lines.push(\"\");\n lines.push(`# ${cmd} subcommands`);\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n lines.push(\n `complete -c gpc -n '__fish_seen_subcommand_from ${cmd}; and not __fish_seen_subcommand_from ${Object.keys(def.subcommands).join(\" \")}' -a ${sub} -d '${escapeFish(subDef.description)}'`,\n );\n }\n\n // Level 3 subcommands\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (!subDef.subcommands) continue;\n lines.push(\"\");\n lines.push(`# ${cmd} ${sub} subcommands`);\n for (const [subsub, subsubDef] of Object.entries(subDef.subcommands)) {\n lines.push(\n `complete -c gpc -n '__fish_seen_subcommand_from ${sub}; and not __fish_seen_subcommand_from ${Object.keys(subDef.subcommands).join(\" \")}' -a ${subsub} -d '${escapeFish(subsubDef.description)}'`,\n );\n }\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function generatePowerShellCompletions(): string {\n const tree = getCommandTree();\n\n // Build the completion hashtable entries\n const completionEntries: string[] = [];\n\n // Top-level completions\n for (const [cmd, def] of Object.entries(tree)) {\n completionEntries.push(\n ` [CompletionResult]::new('${cmd}', '${cmd}', [CompletionResultType]::ParameterValue, '${escapePowerShell(def.description)}')`,\n );\n }\n\n // Subcommand completions (level 2)\n const subcommandCases: string[] = [];\n const level3Cases: string[] = [];\n\n for (const [cmd, def] of Object.entries(tree)) {\n if (!def.subcommands) continue;\n const subEntries = Object.entries(def.subcommands)\n .map(\n ([sub, subDef]) =>\n ` [CompletionResult]::new('${sub}', '${sub}', [CompletionResultType]::ParameterValue, '${escapePowerShell(subDef.description)}')`,\n )\n .join(\"\\n\");\n subcommandCases.push(` '${cmd}' {\\n${subEntries}\\n }`);\n\n // Level 3\n for (const [sub, subDef] of Object.entries(def.subcommands)) {\n if (!subDef.subcommands) continue;\n const subSubEntries = Object.entries(subDef.subcommands)\n .map(\n ([subsub, subsubDef]) =>\n ` [CompletionResult]::new('${subsub}', '${subsub}', [CompletionResultType]::ParameterValue, '${escapePowerShell(subsubDef.description)}')`,\n )\n .join(\"\\n\");\n level3Cases.push(` '${sub}' {\\n${subSubEntries}\\n }`);\n }\n }\n\n return `# PowerShell completions for gpc\n# Install: gpc completion powershell >> $PROFILE\n\nusing namespace System.Management.Automation\n\nRegister-ArgumentCompleter -CommandName gpc -Native -ScriptBlock {\n param($wordToComplete, $commandAst, $cursorPosition)\n\n $tokens = $commandAst.ToString().Substring(0, $cursorPosition).Trim() -split '\\\\s+'\n $tokenCount = $tokens.Count\n\n # Determine context\n if ($tokenCount -le 1 -or ($tokenCount -eq 2 -and $wordToComplete)) {\n # Top-level commands\n${completionEntries.join(\"\\n\")}\n } elseif ($tokenCount -eq 2 -or ($tokenCount -eq 3 -and $wordToComplete)) {\n # Subcommands\n $command = $tokens[1]\n switch ($command) {\n${subcommandCases.join(\"\\n\")}\n }\n } elseif ($tokenCount -eq 3 -or ($tokenCount -eq 4 -and $wordToComplete)) {\n # Sub-subcommands\n $subcommand = $tokens[2]\n switch ($subcommand) {\n${level3Cases.join(\"\\n\")}\n }\n }\n}`;\n}\n\nfunction escapeZsh(str: string): string {\n return str.replace(/'/g, \"'\\\\''\");\n}\n\nfunction escapeFish(str: string): string {\n return str.replace(/'/g, \"\\\\'\");\n}\n\nfunction escapePowerShell(str: string): string {\n return str.replace(/'/g, \"''\");\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
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 +0,0 @@
1
- {"version":3,"sources":["../src/commands/device-tiers.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 listDeviceTiers,\n getDeviceTier,\n createDeviceTier,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { readFile } from \"node:fs/promises\";\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 registerDeviceTiersCommands(program: Command): void {\n const dt = program.command(\"device-tiers\").description(\"Manage device tier configurations\");\n\n dt.command(\"list\")\n .description(\"List device tier configurations\")\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 listDeviceTiers(client, packageName);\n const configs = (result as Record<string, unknown>)[\"deviceTierConfigs\"] as Record<string, unknown>[] | undefined;\n if (format !== \"json\" && (!configs || configs.length === 0)) {\n console.log(\"No device tier configs found.\");\n return;\n }\n if (format !== \"json\" && configs) {\n const rows = configs.map((c) => ({\n deviceTierConfigId: c[\"deviceTierConfigId\"] || \"-\",\n deviceGroups: Array.isArray(c[\"deviceGroups\"]) ? (c[\"deviceGroups\"] as unknown[]).length : 0,\n deviceTierSet: c[\"deviceTierSet\"] ? \"yes\" : \"no\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n dt.command(\"get <config-id>\")\n .description(\"Get a device tier configuration\")\n .action(async (configId: string) => {\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 getDeviceTier(client, packageName, configId);\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 dt.command(\"create\")\n .description(\"Create a device tier configuration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to JSON config file\")\n .action(async (opts: { file: string }) => {\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 { command: \"device-tiers create\", action: \"create device tier config from\", target: opts.file },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const raw = await readFile(opts.file, \"utf-8\");\n const tierConfig = JSON.parse(raw);\n const result = await createDeviceTier(client, packageName, tierConfig);\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;AAGP,SAAS,gBAAgB;AAEzB,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,4BAA4B,SAAwB;AAClE,QAAM,KAAK,QAAQ,QAAQ,cAAc,EAAE,YAAY,mCAAmC;AAE1F,KAAG,QAAQ,MAAM,EACd,YAAY,iCAAiC,EAC7C,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,gBAAgB,QAAQ,WAAW;AACxD,YAAM,UAAW,OAAmC,mBAAmB;AACvE,UAAI,WAAW,WAAW,CAAC,WAAW,QAAQ,WAAW,IAAI;AAC3D,gBAAQ,IAAI,+BAA+B;AAC3C;AAAA,MACF;AACA,UAAI,WAAW,UAAU,SAAS;AAChC,cAAM,OAAO,QAAQ,IAAI,CAAC,OAAO;AAAA,UAC/B,oBAAoB,EAAE,oBAAoB,KAAK;AAAA,UAC/C,cAAc,MAAM,QAAQ,EAAE,cAAc,CAAC,IAAK,EAAE,cAAc,EAAgB,SAAS;AAAA,UAC3F,eAAe,EAAE,eAAe,IAAI,QAAQ;AAAA,QAC9C,EAAE;AACF,gBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,MACxC,OAAO;AACL,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C;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;AAEH,KAAG,QAAQ,iBAAiB,EACzB,YAAY,iCAAiC,EAC7C,OAAO,OAAO,aAAqB;AAClC,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,cAAc,QAAQ,aAAa,QAAQ;AAChE,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,KAAG,QAAQ,QAAQ,EAChB,YAAY,qDAAqD,EACjE,eAAe,iBAAiB,0BAA0B,EAC1D,OAAO,OAAO,SAA2B;AACxC,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,EAAE,SAAS,uBAAuB,QAAQ,kCAAkC,QAAQ,KAAK,KAAK;AAAA,QAC9F;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,QAAI;AACF,YAAM,MAAM,MAAM,SAAS,KAAK,MAAM,OAAO;AAC7C,YAAM,aAAa,KAAK,MAAM,GAAG;AACjC,YAAM,SAAS,MAAM,iBAAiB,QAAQ,aAAa,UAAU;AACrE,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 +0,0 @@
1
- {"version":3,"sources":["../src/commands/docs.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { execFile } from \"node:child_process\";\n\nconst PAGE_MAP: Record<string, string> = {\n releases: \"commands/releases\",\n status: \"commands/status\",\n vitals: \"commands/vitals\",\n reviews: \"commands/reviews\",\n listings: \"commands/listings\",\n subscriptions: \"commands/subscriptions\",\n bundle: \"commands/bundle\",\n users: \"commands/users\",\n audit: \"commands/audit\",\n config: \"commands/config\",\n doctor: \"commands/doctor\",\n publish: \"commands/publish\",\n};\n\nconst BASE = \"https://yasserstudio.github.io/gpc/\";\n\nexport function registerDocsCommand(program: Command): void {\n program\n .command(\"docs [topic]\")\n .description(\"Open documentation in browser\")\n .option(\"--list\", \"List available documentation topics\")\n .action((topic?: string, opts?: { list?: boolean }) => {\n if (opts?.list) {\n console.log(\"Available topics:\");\n for (const key of Object.keys(PAGE_MAP)) console.log(` gpc docs ${key}`);\n return;\n }\n const path = topic ? PAGE_MAP[topic] : undefined;\n if (topic && !path) {\n console.error(`Unknown topic \"${topic}\". Run: gpc docs --list`);\n process.exit(2);\n }\n const url = path ? `${BASE}${path}` : BASE;\n const platform = process.platform;\n const cmd = platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"start\" : \"xdg-open\";\n execFile(cmd, [url], (error) => {\n if (error) {\n console.log(`Open in your browser: ${url}`);\n }\n });\n });\n}\n"],"mappings":";;;AACA,SAAS,gBAAgB;AAEzB,IAAM,WAAmC;AAAA,EACvC,UAAe;AAAA,EACf,QAAe;AAAA,EACf,QAAe;AAAA,EACf,SAAe;AAAA,EACf,UAAe;AAAA,EACf,eAAe;AAAA,EACf,QAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA,EACf,QAAe;AAAA,EACf,QAAe;AAAA,EACf,SAAe;AACjB;AAEA,IAAM,OAAO;AAEN,SAAS,oBAAoB,SAAwB;AAC1D,UACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,UAAU,qCAAqC,EACtD,OAAO,CAAC,OAAgB,SAA8B;AACrD,QAAI,MAAM,MAAM;AACd,cAAQ,IAAI,mBAAmB;AAC/B,iBAAW,OAAO,OAAO,KAAK,QAAQ,EAAG,SAAQ,IAAI,cAAc,GAAG,EAAE;AACxE;AAAA,IACF;AACA,UAAM,OAAO,QAAQ,SAAS,KAAK,IAAI;AACvC,QAAI,SAAS,CAAC,MAAM;AAClB,cAAQ,MAAM,kBAAkB,KAAK,yBAAyB;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,KAAK;AACtC,UAAM,WAAW,QAAQ;AACzB,UAAM,MAAM,aAAa,WAAW,SAAS,aAAa,UAAU,UAAU;AAC9E,aAAS,KAAK,CAAC,GAAG,GAAG,CAAC,UAAU;AAC9B,UAAI,OAAO;AACT,gBAAQ,IAAI,yBAAyB,GAAG,EAAE;AAAA,MAC5C;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACL;","names":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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 formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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":[]}
@@ -1 +0,0 @@
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 formatOutput,\n} 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 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 = getOutputFormat(program, config);\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 if (format !== \"json\") {\n const apks = (result as Record<string, unknown>)[\"generatedApks\"] as Array<Record<string, unknown>> | undefined;\n if (apks && apks.length > 0) {\n const rows = apks.map((apk) => ({\n id: apk[\"generatedApkId\"] || \"-\",\n variantId: apk[\"variantId\"] || \"-\",\n moduleName: apk[\"moduleName\"] || \"-\",\n sha256: String(apk[\"certificateSha256Fingerprint\"] || \"-\").slice(0, 16) + \"...\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(\"No generated APKs found.\");\n }\n } else {\n console.log(formatOutput(result, format));\n }\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 = getOutputFormat(program, config);\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":"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","names":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/iap.ts"],"sourcesContent":["import 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 listOneTimeProducts,\n getOneTimeProduct,\n createInAppProduct,\n updateInAppProduct,\n deleteInAppProduct,\n syncInAppProducts,\n formatOutput,\n sortResults,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.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 (uses one-time products API)\");\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 = getOutputFormat(program, config);\n\n console.error(\"Note: Using oneTimeProducts API (inappproducts endpoint is deprecated, shutdown Aug 2027)\");\n\n try {\n const result = await listOneTimeProducts(client, packageName);\n let products = result.oneTimeProducts || [];\n if (options.sort) {\n products = sortResults(products, options.sort);\n }\n console.log(formatOutput(products, 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 = getOutputFormat(program, config);\n\n console.error(\"Note: Using oneTimeProducts API (inappproducts endpoint is deprecated, shutdown Aug 2027)\");\n\n try {\n const result = await getOneTimeProduct(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 = getOutputFormat(program, config);\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 = await readJsonFile(options.file);\n const result = await createInAppProduct(client, packageName, data as any);\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 = getOutputFormat(program, config);\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 = await readJsonFile(options.file);\n const result = await updateInAppProduct(client, packageName, sku, data as any);\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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 iap\n .command(\"batch-get\")\n .description(\"Batch get multiple in-app products\")\n .option(\"--skus <skus>\", \"Comma-separated list of SKUs\")\n .option(\"--file <path>\", \"JSON file with array of SKUs\")\n .action(async (_options) => {\n console.error(\n \"Note: The inappproducts batchGet endpoint is permanently blocked by Google Play (returns 403 PERMISSION_DENIED).\\n\" +\n \"Use `gpc iap get <sku>` for a single product, or `gpc iap list` for all products.\"\n );\n process.exit(1);\n });\n\n iap\n .command(\"batch-update\")\n .description(\"Batch update multiple in-app products from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with array of product objects\")\n .option(\"--dry-run\", \"Preview changes without executing\")\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 (options.dryRun || isDryRun(program)) {\n const data = await readJsonFile(options.file);\n const products = Array.isArray(data) ? data : [];\n console.log(`[dry-run] Would batch update ${products.length} product(s)`);\n if (format !== \"json\") {\n const rows = products.map((p: Record<string, unknown>) => ({\n sku: p[\"sku\"] || \"-\",\n action: \"update\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(products, format));\n }\n return;\n }\n\n const client = await getClient(config);\n console.error(\"Note: Using inappproducts batch API\");\n\n const spinner = createSpinner(\"Batch updating products...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const data = await readJsonFile(options.file);\n const products = Array.isArray(data) ? data : [];\n const request = {\n requests: products.map((p: Record<string, unknown>) => ({\n inappproduct: p,\n packageName,\n sku: p[\"sku\"] as string,\n })),\n };\n const result = await client.inappproducts.batchUpdate(packageName, request as any);\n spinner.stop(\"Batch update complete\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Batch update 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":[]}
@@ -1 +0,0 @@
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 formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\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 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 format = getOutputFormat(program, config);\n\n const fileType = opts.type as \"bundle\" | \"apk\" | undefined;\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"internal-sharing upload\", action: \"upload for internal sharing\", target: file },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\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,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,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,gBAAgB,SAAS,MAAM;AAE9C,UAAM,WAAW,KAAK;AAEtB,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE,EAAE,SAAS,2BAA2B,QAAQ,+BAA+B,QAAQ,KAAK;AAAA,QAC1F;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,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":[]}
@@ -1 +0,0 @@
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 diffListingsEnhanced,\n lintLocalListings,\n analyzeRemoteListings,\n listImages,\n uploadImage,\n deleteImage,\n exportImages,\n getCountryAvailability,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\nimport { green, red } from \"../colors.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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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>\", \"Target directory (default: metadata)\", \"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 = getOutputFormat(program, config);\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 (default: metadata)\", \"metadata\")\n .option(\"--force\", \"Push even if fields exceed character limits\")\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 = getOutputFormat(program, config);\n\n const spinner = createSpinner(\"Pushing listings...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const dryRun = isDryRun(program);\n const result = await pushListings(client, packageName, options.dir, {\n dryRun,\n force: options.force,\n });\n spinner.stop(dryRun ? \"Dry-run complete (no changes made)\" : \"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 (enhanced: --lang filter, word-level inline 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 .option(\"--lang <language>\", \"Filter diff to a specific language\")\n .option(\"--word-diff\", \"Show word-level inline diff for fullDescription\")\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 = getOutputFormat(program, config);\n\n try {\n const diffs = await diffListingsEnhanced(client, packageName, options.dir, {\n lang: options.lang,\n wordLevel: options.wordDiff,\n });\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 const charInfo = (diff as Record<string, unknown>)[\"chars\"]\n ? ` (${(diff as Record<string, unknown>)[\"chars\"]} chars)`\n : \"\";\n console.log(`[${diff.language}] ${diff.field}:${charInfo}`);\n if ((diff as Record<string, unknown>)[\"diffSummary\"]) {\n console.log(` ${(diff as Record<string, unknown>)[\"diffSummary\"]}`);\n } else {\n console.log(green(` + local: ${diff.local || \"(empty)\"}`));\n console.log(red(` - remote: ${diff.remote || \"(empty)\"}`));\n }\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Lint (local, no API)\n listings\n .command(\"lint\")\n .description(\"Lint local listing metadata for Play Store character limits (no API)\")\n .option(\"--dir <path>\", \"Metadata directory\", \"metadata\")\n .action(async (options) => {\n const format = getOutputFormat(program, await loadConfig());\n try {\n const results = await lintLocalListings(options.dir);\n if (format === \"json\") {\n console.log(formatOutput(results, format));\n return;\n }\n let exitCode = 0;\n for (const r of results) {\n console.log(`\\n[${r.language}] ${r.valid ? green(\"✓ valid\") : red(\"✗ over limit\")}`);\n const rows = r.fields.map((f) => ({\n field: f.field,\n chars: f.chars,\n limit: f.limit,\n pct: `${f.pct}%`,\n status: f.status === \"ok\" ? green(\"✓\") : f.status === \"warn\" ? \"⚠\" : red(\"✗\"),\n }));\n console.log(formatOutput(rows, \"table\"));\n if (!r.valid) exitCode = 1;\n }\n if (exitCode) process.exit(exitCode);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n // Analyze (live, fetches remote)\n listings\n .command(\"analyze\")\n .description(\"Analyze live Play Store listings for character limit compliance\")\n .option(\"--expected <locales>\", \"Comma-separated list of expected locale codes\")\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 = getOutputFormat(program, config);\n\n const spinner = createSpinner(\"Fetching remote listings...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const expectedLocales = options.expected\n ? (options.expected as string).split(\",\").map((s: string) => s.trim())\n : undefined;\n const { results, missingLocales } = await analyzeRemoteListings(client, packageName, {\n expectedLocales,\n });\n spinner.stop(\"Done\");\n\n if (format === \"json\") {\n console.log(formatOutput({ results, missingLocales }, format));\n return;\n }\n\n let exitCode = 0;\n for (const r of results) {\n console.log(`\\n[${r.language}] ${r.valid ? green(\"✓ valid\") : red(\"✗ over limit\")}`);\n const rows = r.fields.map((f) => ({\n field: f.field,\n chars: f.chars,\n limit: f.limit,\n pct: `${f.pct}%`,\n status: f.status === \"ok\" ? green(\"✓\") : f.status === \"warn\" ? \"⚠\" : red(\"✗\"),\n }));\n console.log(formatOutput(rows, \"table\"));\n if (!r.valid) exitCode = 1;\n }\n\n if (missingLocales && missingLocales.length > 0) {\n console.log(`\\nMissing locales: ${missingLocales.join(\", \")}`);\n }\n\n if (exitCode) process.exit(exitCode);\n } catch (error) {\n spinner.fail(\"Analysis failed\");\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\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 = getOutputFormat(program, config);\n\n try {\n const result = await getCountryAvailability(client, packageName, options.track);\n const countries = (result as Record<string, unknown>)[\"countryTargeting\"] as unknown[] | undefined;\n if (format !== \"json\" && (!countries || (Array.isArray(countries) && countries.length === 0)) && Object.keys(result as object).length === 0) {\n console.log(\"No availability data.\");\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":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/migrate.ts"],"sourcesContent":["import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport {\n detectFastlane,\n generateMigrationPlan,\n writeMigrationOutput,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nconst WARN = \"\\u26A0\";\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\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 .option(\"--dry-run\", \"Preview migration plan without writing any files\")\n .action(async (options: { dir: string; output: string; dryRun?: boolean }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const dryRun = options.dryRun ?? false;\n\n try {\n const detection = await detectFastlane(options.dir);\n\n if (format === \"json\") {\n if (\n !detection.hasFastfile &&\n !detection.hasAppfile &&\n !detection.hasMetadata\n ) {\n console.log(formatOutput({ detection, plan: null, files: [] }, format));\n return;\n }\n const plan = generateMigrationPlan(detection);\n if (!dryRun) {\n const files = await writeMigrationOutput(plan, options.output);\n console.log(formatOutput({ detection, plan, files }, format));\n } else {\n console.log(formatOutput({ detection, plan, files: [] }, format));\n }\n return;\n }\n\n // Human-readable output\n console.log(\"Fastlane Detection Results:\\n\");\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 (${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 if (detection.parseWarnings.length > 0) {\n console.log(\"\");\n for (const w of detection.parseWarnings) {\n console.log(` ${WARN} ${w}`);\n }\n }\n\n if (\n !detection.hasFastfile &&\n !detection.hasAppfile &&\n !detection.hasMetadata\n ) {\n console.log(\"\\nNo Fastlane files detected in this directory. Nothing to migrate.\");\n console.log(\" Try: gpc migrate fastlane --dir <path-to-your-android-project>\");\n return;\n }\n\n const plan = generateMigrationPlan(detection);\n\n if (dryRun) {\n console.log(\"\\nMigration Plan (dry run — nothing written):\\n\");\n\n if (plan.warnings.length > 0) {\n console.log(\"Warnings:\");\n for (const w of plan.warnings) {\n console.log(` ${WARN} ${w}`);\n }\n console.log(\"\");\n }\n\n console.log(\"Checklist:\");\n for (const item of plan.checklist) {\n console.log(` [ ] ${item}`);\n }\n\n if (Object.keys(plan.config).length > 0) {\n console.log(\"\\n.gpcrc.json (would be written):\");\n console.log(JSON.stringify(plan.config, null, 2).replace(/^/gm, \" \"));\n }\n\n console.log(\n \"\\nRun without --dry-run to write MIGRATION.md\" +\n (Object.keys(plan.config).length > 0 ? \" and .gpcrc.json\" : \"\") +\n \".\",\n );\n return;\n }\n\n // Conflict check — abort before clobbering existing .gpcrc.json unless --yes\n if (\n Object.keys(plan.config).length > 0 &&\n (await fileExists(join(options.output, \".gpcrc.json\")))\n ) {\n const hasYes =\n process.argv.includes(\"--yes\") || process.argv.includes(\"-y\");\n\n if (!hasYes) {\n console.log(\n `\\n${WARN} .gpcrc.json already exists and will be overwritten. Use --dry-run to preview first.`,\n );\n console.log(\n \"Aborting. Pass --yes to overwrite without confirmation.\",\n );\n return;\n }\n\n console.log(\n `\\n${WARN} .gpcrc.json already exists in ${options.output} — overwriting (--yes passed).`,\n );\n }\n\n const files = await writeMigrationOutput(plan, options.output);\n\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 w of plan.warnings) {\n console.log(` ${WARN} ${w}`);\n }\n }\n\n console.log(\"\\nMigration Checklist:\");\n for (const item of plan.checklist) {\n console.log(` [ ] ${item}`);\n }\n\n console.log(\n \"\\nNext step: open MIGRATION.md and work through the checklist. Run `gpc doctor` when done.\",\n );\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":["plan","files"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/one-time-products.ts"],"sourcesContent":["import 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 type { OneTimeProduct } from \"@gpc-cli/api\";\nimport {\n listOneTimeProducts,\n getOneTimeProduct,\n createOneTimeProduct,\n updateOneTimeProduct,\n deleteOneTimeProduct,\n listOneTimeOffers,\n getOneTimeOffer,\n createOneTimeOffer,\n updateOneTimeOffer,\n deleteOneTimeOffer,\n diffOneTimeProduct,\n formatOutput,\n sortResults,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.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 registerOneTimeProductsCommands(program: Command): void {\n const otp = program\n .command(\"one-time-products\")\n .alias(\"otp\")\n .description(\"Manage one-time products and offers (modern OTP API)\");\n\n otp\n .command(\"list\")\n .description(\"List one-time products\")\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 = getOutputFormat(program, config);\n\n try {\n const result = await listOneTimeProducts(client, packageName);\n if (options.sort) {\n result.oneTimeProducts = sortResults(result.oneTimeProducts, options.sort);\n }\n const products = result.oneTimeProducts || [];\n if (format !== \"json\") {\n if (products.length === 0) {\n console.log(\"No one-time products found.\");\n return;\n }\n const summary = products.map((p: OneTimeProduct) => ({\n productId: p.productId,\n purchaseType: (p as Record<string, unknown>)[\"purchaseType\"] || \"-\",\n listings: p.listings ? Object.keys(p.listings).length : 0,\n firstTitle: p.listings ? Object.values(p.listings)[0]?.title || \"-\" : \"-\",\n }));\n console.log(formatOutput(summary, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n otp\n .command(\"get <product-id>\")\n .description(\"Get a one-time product\")\n .action(async (productId: string) => {\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 getOneTimeProduct(client, packageName, productId);\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 otp\n .command(\"create\")\n .description(\"Create a one-time 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 = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"one-time-products create\",\n action: \"create\",\n target: `one-time 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 = await readJsonFile(options.file);\n const result = await createOneTimeProduct(client, packageName, data as any);\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 otp\n .command(\"update <product-id>\")\n .description(\"Update a one-time product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(async (productId: string, 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: \"one-time-products update\",\n action: \"update\",\n target: productId,\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 = await readJsonFile(options.file);\n const result = await updateOneTimeProduct(client, packageName, productId, data as any, options.updateMask);\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 otp\n .command(\"delete <product-id>\")\n .description(\"Delete a one-time product\")\n .action(async (productId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete one-time product \"${productId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"one-time-products delete\",\n action: \"delete\",\n target: productId,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteOneTimeProduct(client, packageName, productId);\n console.log(`One-time product ${productId} deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // --- Offers ---\n const offers = otp.command(\"offers\").description(\"Manage one-time product offers\");\n\n offers\n .command(\"list <product-id>\")\n .description(\"List offers for a one-time product\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (productId: string, options) => {\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 listOneTimeOffers(client, packageName, productId);\n if (options.sort) {\n result.oneTimeOffers = sortResults(result.oneTimeOffers, 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 offers\n .command(\"get <product-id> <offer-id>\")\n .description(\"Get an offer for a one-time product\")\n .action(async (productId: string, offerId: string) => {\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 getOneTimeOffer(client, packageName, productId, offerId);\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 offers\n .command(\"create <product-id>\")\n .description(\"Create an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .action(async (productId: string, options: { file: string }) => {\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: \"one-time-products offers create\",\n action: \"create offer for\",\n target: productId,\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 = await readJsonFile(options.file);\n const result = await createOneTimeOffer(client, packageName, productId, data as any);\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 offers\n .command(\"update <product-id> <offer-id>\")\n .description(\"Update an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(async (productId: string, offerId: string, options: { file: string; updateMask?: string }) => {\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: \"one-time-products offers update\",\n action: \"update offer\",\n target: `${productId}/${offerId}`,\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 = await readJsonFile(options.file);\n const result = await updateOneTimeOffer(client, packageName, productId, offerId, data as any, options.updateMask);\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 offers\n .command(\"delete <product-id> <offer-id>\")\n .description(\"Delete an offer\")\n .action(async (productId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete offer \"${offerId}\" for product \"${productId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"one-time-products offers delete\",\n action: \"delete offer\",\n target: `${productId}/${offerId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteOneTimeOffer(client, packageName, productId, offerId);\n console.log(`Offer ${offerId} deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // --- Diff ---\n otp\n .command(\"diff <product-id>\")\n .description(\"Compare local JSON file against remote one-time product\")\n .requiredOption(\"--file <path>\", \"Local JSON file to compare against remote\")\n .action(async (productId: string, options: { file: string }) => {\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 localData = await readJsonFile(options.file) as OneTimeProduct;\n const diffs = await diffOneTimeProduct(client, packageName, productId, localData);\n if (diffs.length === 0) {\n console.log(\"No differences found.\");\n } else {\n console.log(formatOutput(diffs, format));\n }\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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/pricing.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 { convertRegionPrices, 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 createApiClient({ auth });\n}\n\nexport function registerPricingCommands(program: Command): void {\n const pricing = program.command(\"pricing\").description(\"Pricing and regional price conversion\");\n\n pricing\n .command(\"convert\")\n .description(\"Convert a price to all regional prices\")\n .option(\"--from <currency>\", \"Source currency code (e.g. USD)\")\n .option(\"--amount <number>\", \"Price amount (e.g. 4.99)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const { isInteractive, requireOption } = await import(\"../prompt.js\");\n const interactive = isInteractive(program);\n\n options.from = await requireOption(\n \"from\",\n options.from,\n {\n message: \"Source currency code (e.g. USD):\",\n default: \"USD\",\n },\n interactive,\n );\n\n options.amount = await requireOption(\n \"amount\",\n options.amount,\n {\n message: \"Price amount (e.g. 4.99):\",\n },\n interactive,\n );\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await convertRegionPrices(client, packageName, options.from, options.amount);\n if (format !== \"json\") {\n const prices = (result as Record<string, unknown>)[\"convertedRegionPrices\"] as Record<string, Record<string, unknown>> | undefined;\n if (prices) {\n const rows = Object.entries(prices).map(([region, data]) => {\n const money = data[\"price\"] as Record<string, unknown> | undefined;\n const units = money?.[\"units\"] || \"0\";\n const nanos = String(money?.[\"nanos\"] || 0).padStart(9, \"0\").slice(0, 2);\n return {\n region,\n price: money ? `${units}.${nanos}` : (data[\"priceMicros\"] ? String(Number(data[\"priceMicros\"]) / 1_000_000) : \"-\"),\n currencyCode: (money?.[\"currencyCode\"] || data[\"currencyCode\"] || \"-\") as string,\n };\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } else {\n console.log(formatOutput(result, format));\n }\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,SAAS,qBAAqB,oBAAoB;AAGlD,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,wBAAwB,SAAwB;AAC9D,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,uCAAuC;AAE9F,UACG,QAAQ,SAAS,EACjB,YAAY,wCAAwC,EACpD,OAAO,qBAAqB,iCAAiC,EAC7D,OAAO,qBAAqB,0BAA0B,EACtD,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,EAAE,eAAe,cAAc,IAAI,MAAM,OAAO,sBAAc;AACpE,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,OAAO,MAAM;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,SAAS,MAAM;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,QAAQ,aAAa,QAAQ,MAAM,QAAQ,MAAM;AAC1F,UAAI,WAAW,QAAQ;AACrB,cAAM,SAAU,OAAmC,uBAAuB;AAC1E,YAAI,QAAQ;AACV,gBAAM,OAAO,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM;AAC1D,kBAAM,QAAQ,KAAK,OAAO;AAC1B,kBAAM,QAAQ,QAAQ,OAAO,KAAK;AAClC,kBAAM,QAAQ,OAAO,QAAQ,OAAO,KAAK,CAAC,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,GAAG,CAAC;AACvE,mBAAO;AAAA,cACL;AAAA,cACA,OAAO,QAAQ,GAAG,KAAK,IAAI,KAAK,KAAM,KAAK,aAAa,IAAI,OAAO,OAAO,KAAK,aAAa,CAAC,IAAI,GAAS,IAAI;AAAA,cAC9G,cAAe,QAAQ,cAAc,KAAK,KAAK,cAAc,KAAK;AAAA,YACpE;AAAA,UACF,CAAC;AACD,kBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,QACxC,OAAO;AACL,kBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,QAC1C;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C;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":[]}