@gpc-cli/cli 0.9.44 → 0.9.46

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 (168) hide show
  1. package/dist/{anomalies-NU2IN2GJ.js → anomalies-UDE4NGHJ.js} +19 -24
  2. package/dist/anomalies-UDE4NGHJ.js.map +1 -0
  3. package/dist/{apps-J2446UDA.js → apps-FKD3ZG5X.js} +31 -35
  4. package/dist/apps-FKD3ZG5X.js.map +1 -0
  5. package/dist/{audit-N2CRHWUN.js → audit-JASSHRWN.js} +47 -62
  6. package/dist/audit-JASSHRWN.js.map +1 -0
  7. package/dist/{auth-XGSTT5G5.js → auth-OTA3SV3J.js} +145 -103
  8. package/dist/auth-OTA3SV3J.js.map +1 -0
  9. package/dist/bin.js +6 -4
  10. package/dist/bin.js.map +1 -1
  11. package/dist/bundle-F7MUVC5J.js +204 -0
  12. package/dist/bundle-F7MUVC5J.js.map +1 -0
  13. package/dist/{cache-SLNFRTI2.js → cache-XKPLZYEB.js} +4 -5
  14. package/dist/cache-XKPLZYEB.js.map +1 -0
  15. package/dist/changelog-7COFZO7Q.js +48 -0
  16. package/dist/changelog-7COFZO7Q.js.map +1 -0
  17. package/dist/{chunk-4O4D5SGL.js → chunk-3SJ6OXCZ.js} +4 -5
  18. package/dist/chunk-3SJ6OXCZ.js.map +1 -0
  19. package/dist/{chunk-7LURVNQV.js → chunk-6OWN6S6X.js} +53 -49
  20. package/dist/{chunk-7LURVNQV.js.map → chunk-6OWN6S6X.js.map} +1 -1
  21. package/dist/{chunk-U6ZTQ34I.js → chunk-BCBXQC7J.js} +45 -11
  22. package/dist/chunk-BCBXQC7J.js.map +1 -0
  23. package/dist/{chunk-AA577WVQ.js → chunk-NQH4G7BI.js} +9 -3
  24. package/dist/chunk-NQH4G7BI.js.map +1 -0
  25. package/dist/chunk-SLNJEAMK.js +23 -0
  26. package/dist/chunk-SLNJEAMK.js.map +1 -0
  27. package/dist/{chunk-NV75I5VP.js → chunk-YFUBD2XB.js} +10 -8
  28. package/dist/chunk-YFUBD2XB.js.map +1 -0
  29. package/dist/{config-222P3MKK.js → config-2FTCYEGD.js} +8 -5
  30. package/dist/config-2FTCYEGD.js.map +1 -0
  31. package/dist/{data-safety-Q7FTCEWU.js → data-safety-AFMD6MYI.js} +12 -27
  32. package/dist/data-safety-AFMD6MYI.js.map +1 -0
  33. package/dist/{device-tiers-MIOQEXYY.js → device-tiers-AQAMUQXI.js} +23 -38
  34. package/dist/device-tiers-AQAMUQXI.js.map +1 -0
  35. package/dist/diff-6EO4ID6W.js +91 -0
  36. package/dist/diff-6EO4ID6W.js.map +1 -0
  37. package/dist/{docs-7DUXIKA3.js → docs-4D2SJ4LY.js} +4 -3
  38. package/dist/docs-4D2SJ4LY.js.map +1 -0
  39. package/dist/doctor-H4X7Q57B.js +691 -0
  40. package/dist/doctor-H4X7Q57B.js.map +1 -0
  41. package/dist/{enterprise-7THXNBTC.js → enterprise-7PWXMSUN.js} +11 -21
  42. package/dist/enterprise-7PWXMSUN.js.map +1 -0
  43. package/dist/{external-transactions-2GWIMUVM.js → external-transactions-LCZALS3V.js} +12 -28
  44. package/dist/external-transactions-LCZALS3V.js.map +1 -0
  45. package/dist/{feedback-2W2XJGZX.js → feedback-XP765TOO.js} +4 -4
  46. package/dist/{games-BT777WUO.js → games-ZSNGEI7A.js} +17 -32
  47. package/dist/games-ZSNGEI7A.js.map +1 -0
  48. package/dist/{generated-apks-RJWTIX7L.js → generated-apks-RX2IUWSF.js} +30 -38
  49. package/dist/generated-apks-RX2IUWSF.js.map +1 -0
  50. package/dist/{grants-TKQJ3IER.js → grants-EBPECI26.js} +22 -40
  51. package/dist/grants-EBPECI26.js.map +1 -0
  52. package/dist/{iap-ICAEQLK5.js → iap-OUI5YYN4.js} +30 -51
  53. package/dist/iap-OUI5YYN4.js.map +1 -0
  54. package/dist/index.js +1 -1
  55. package/dist/{init-JZ2THPMS.js → init-WSTQTJOD.js} +5 -4
  56. package/dist/init-WSTQTJOD.js.map +1 -0
  57. package/dist/{install-skills-OV4HVANW.js → install-skills-6QDUXI5F.js} +5 -6
  58. package/dist/{install-skills-OV4HVANW.js.map → install-skills-6QDUXI5F.js.map} +1 -1
  59. package/dist/{internal-sharing-3U2XFHA4.js → internal-sharing-ONNIWIAT.js} +3 -4
  60. package/dist/{internal-sharing-3U2XFHA4.js.map → internal-sharing-ONNIWIAT.js.map} +1 -1
  61. package/dist/{listings-77HZW4S5.js → listings-7SGQ4SRX.js} +118 -157
  62. package/dist/listings-7SGQ4SRX.js.map +1 -0
  63. package/dist/migrate-ZQCJGQQS.js +138 -0
  64. package/dist/migrate-ZQCJGQQS.js.map +1 -0
  65. package/dist/{one-time-products-LHZAXQES.js → one-time-products-MGZTU7OM.js} +65 -120
  66. package/dist/one-time-products-MGZTU7OM.js.map +1 -0
  67. package/dist/{preflight-H3HEBYQW.js → preflight-N7ZRG2JI.js} +58 -55
  68. package/dist/preflight-N7ZRG2JI.js.map +1 -0
  69. package/dist/{pricing-XQSDTTK5.js → pricing-JJZFICFL.js} +8 -8
  70. package/dist/{pricing-XQSDTTK5.js.map → pricing-JJZFICFL.js.map} +1 -1
  71. package/dist/{prompt-BSV22CQZ.js → prompt-GXC2JSLA.js} +2 -2
  72. package/dist/{publish-Q5ZKEKZ5.js → publish-JPTI4EBT.js} +34 -30
  73. package/dist/publish-JPTI4EBT.js.map +1 -0
  74. package/dist/{purchase-options-CKRN4VIW.js → purchase-options-KFWW4JW2.js} +16 -11
  75. package/dist/purchase-options-KFWW4JW2.js.map +1 -0
  76. package/dist/purchases-DAWTMXP6.js +383 -0
  77. package/dist/purchases-DAWTMXP6.js.map +1 -0
  78. package/dist/{quickstart-4HB62YEL.js → quickstart-Z5Y3FYJU.js} +5 -3
  79. package/dist/quickstart-Z5Y3FYJU.js.map +1 -0
  80. package/dist/{quota-UHIQQYOY.js → quota-MZRWYJGR.js} +5 -15
  81. package/dist/quota-MZRWYJGR.js.map +1 -0
  82. package/dist/{recovery-5EV2R476.js → recovery-YE3Z7NIN.js} +32 -61
  83. package/dist/recovery-YE3Z7NIN.js.map +1 -0
  84. package/dist/{releases-C2WC2K4E.js → releases-2I3WBULC.js} +184 -185
  85. package/dist/releases-2I3WBULC.js.map +1 -0
  86. package/dist/{reports-2YX3RDOS.js → reports-CIB2T3XT.js} +19 -21
  87. package/dist/reports-CIB2T3XT.js.map +1 -0
  88. package/dist/reviews-BCCXIQ6C.js +188 -0
  89. package/dist/reviews-BCCXIQ6C.js.map +1 -0
  90. package/dist/{status-WHGLODGV.js → status-6LH5W4FU.js} +105 -83
  91. package/dist/status-6LH5W4FU.js.map +1 -0
  92. package/dist/{subscriptions-CI3JH3VQ.js → subscriptions-DZP3Y7O7.js} +142 -232
  93. package/dist/subscriptions-DZP3Y7O7.js.map +1 -0
  94. package/dist/{testers-NZOFA3EF.js → testers-LSMBXCA2.js} +24 -44
  95. package/dist/testers-LSMBXCA2.js.map +1 -0
  96. package/dist/tracks-YHMO2A6B.js +98 -0
  97. package/dist/tracks-YHMO2A6B.js.map +1 -0
  98. package/dist/{train-XKE4JN3Y.js → train-MDD2EBHS.js} +35 -55
  99. package/dist/train-MDD2EBHS.js.map +1 -0
  100. package/dist/{update-QMPRL5Y6.js → update-OMALGIBR.js} +30 -15
  101. package/dist/update-OMALGIBR.js.map +1 -0
  102. package/dist/{users-2YTC4Q36.js → users-UKG7VIQH.js} +45 -67
  103. package/dist/users-UKG7VIQH.js.map +1 -0
  104. package/dist/{validate-UOVTM6L3.js → validate-QIYSA3N7.js} +8 -10
  105. package/dist/validate-QIYSA3N7.js.map +1 -0
  106. package/dist/{version-NK5SJLHJ.js → version-NCSNXNVN.js} +4 -4
  107. package/dist/{vitals-A4CS4MSS.js → vitals-C23L2Y2E.js} +153 -172
  108. package/dist/vitals-C23L2Y2E.js.map +1 -0
  109. package/package.json +6 -6
  110. package/dist/anomalies-NU2IN2GJ.js.map +0 -1
  111. package/dist/apps-J2446UDA.js.map +0 -1
  112. package/dist/audit-N2CRHWUN.js.map +0 -1
  113. package/dist/auth-XGSTT5G5.js.map +0 -1
  114. package/dist/bundle-F43TD2BQ.js +0 -218
  115. package/dist/bundle-F43TD2BQ.js.map +0 -1
  116. package/dist/cache-SLNFRTI2.js.map +0 -1
  117. package/dist/changelog-OYUZOCOL.js +0 -53
  118. package/dist/changelog-OYUZOCOL.js.map +0 -1
  119. package/dist/chunk-4O4D5SGL.js.map +0 -1
  120. package/dist/chunk-AA577WVQ.js.map +0 -1
  121. package/dist/chunk-FWKYRLKY.js +0 -19
  122. package/dist/chunk-FWKYRLKY.js.map +0 -1
  123. package/dist/chunk-NV75I5VP.js.map +0 -1
  124. package/dist/chunk-U6ZTQ34I.js.map +0 -1
  125. package/dist/config-222P3MKK.js.map +0 -1
  126. package/dist/data-safety-Q7FTCEWU.js.map +0 -1
  127. package/dist/device-tiers-MIOQEXYY.js.map +0 -1
  128. package/dist/diff-V77SMKAQ.js +0 -96
  129. package/dist/diff-V77SMKAQ.js.map +0 -1
  130. package/dist/docs-7DUXIKA3.js.map +0 -1
  131. package/dist/doctor-3Z4ARPM2.js +0 -372
  132. package/dist/doctor-3Z4ARPM2.js.map +0 -1
  133. package/dist/enterprise-7THXNBTC.js.map +0 -1
  134. package/dist/external-transactions-2GWIMUVM.js.map +0 -1
  135. package/dist/games-BT777WUO.js.map +0 -1
  136. package/dist/generated-apks-RJWTIX7L.js.map +0 -1
  137. package/dist/grants-TKQJ3IER.js.map +0 -1
  138. package/dist/iap-ICAEQLK5.js.map +0 -1
  139. package/dist/init-JZ2THPMS.js.map +0 -1
  140. package/dist/listings-77HZW4S5.js.map +0 -1
  141. package/dist/migrate-SQT6RD6T.js +0 -143
  142. package/dist/migrate-SQT6RD6T.js.map +0 -1
  143. package/dist/one-time-products-LHZAXQES.js.map +0 -1
  144. package/dist/preflight-H3HEBYQW.js.map +0 -1
  145. package/dist/publish-Q5ZKEKZ5.js.map +0 -1
  146. package/dist/purchase-options-CKRN4VIW.js.map +0 -1
  147. package/dist/purchases-HSMCOG4A.js +0 -330
  148. package/dist/purchases-HSMCOG4A.js.map +0 -1
  149. package/dist/quickstart-4HB62YEL.js.map +0 -1
  150. package/dist/quota-UHIQQYOY.js.map +0 -1
  151. package/dist/recovery-5EV2R476.js.map +0 -1
  152. package/dist/releases-C2WC2K4E.js.map +0 -1
  153. package/dist/reports-2YX3RDOS.js.map +0 -1
  154. package/dist/reviews-2CWOI5CV.js +0 -213
  155. package/dist/reviews-2CWOI5CV.js.map +0 -1
  156. package/dist/status-WHGLODGV.js.map +0 -1
  157. package/dist/subscriptions-CI3JH3VQ.js.map +0 -1
  158. package/dist/testers-NZOFA3EF.js.map +0 -1
  159. package/dist/tracks-NERFFEDT.js +0 -107
  160. package/dist/tracks-NERFFEDT.js.map +0 -1
  161. package/dist/train-XKE4JN3Y.js.map +0 -1
  162. package/dist/update-QMPRL5Y6.js.map +0 -1
  163. package/dist/users-2YTC4Q36.js.map +0 -1
  164. package/dist/validate-UOVTM6L3.js.map +0 -1
  165. package/dist/vitals-A4CS4MSS.js.map +0 -1
  166. /package/dist/{feedback-2W2XJGZX.js.map → feedback-XP765TOO.js.map} +0 -0
  167. /package/dist/{prompt-BSV22CQZ.js.map → prompt-GXC2JSLA.js.map} +0 -0
  168. /package/dist/{version-NK5SJLHJ.js.map → version-NCSNXNVN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig, getCacheDir, getConfigDir } from \"@gpc-cli/config\";\nimport { green, red, yellow, dim } from \"../colors.js\";\nimport { resolveAuth, AuthError } from \"@gpc-cli/auth\";\nimport { existsSync, accessSync, statSync, constants } from \"node:fs\";\nimport { readFile, stat, statfs } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport { lookup } from \"node:dns/promises\";\nimport { isNewerVersion } from \"../update-check.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CheckResult {\n name: string;\n status: \"pass\" | \"fail\" | \"warn\" | \"info\";\n message: string;\n suggestion?: string;\n /** Structured data for applyFix — avoids fragile regex on suggestion text. */\n fixData?: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst PASS = \"\\u2713\";\nconst FAIL = \"\\u2717\";\nconst WARN = \"\\u26A0\";\nconst INFO = \"-\";\n\nconst ANDROID_PACKAGE_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$/;\n\n/** All user-facing keys accepted in .gpcrc.json / config.json. */\nconst KNOWN_CONFIG_KEYS = new Set([\n \"app\",\n \"output\",\n \"profile\",\n \"auth\",\n \"developerId\",\n \"plugins\",\n \"profiles\",\n \"approvedPlugins\",\n \"webhooks\",\n \"debug\",\n \"train\",\n]);\n\nconst NPM_REGISTRY_URL = \"https://registry.npmjs.org/@gpc-cli/cli/latest\";\nconst API_HOST = \"androidpublisher.googleapis.com\";\nconst REPORTING_HOST = \"playdeveloperreporting.googleapis.com\";\nconst SA_KEY_ROTATION_DAYS = 90;\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\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\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\nexport function checkDeveloperId(id: string | undefined): CheckResult | null {\n if (!id) return null;\n if (/^\\d+$/.test(id)) {\n return { name: \"developer-id\", status: \"pass\", message: `Developer ID: ${id}` };\n }\n return {\n name: \"developer-id\",\n status: \"warn\",\n message: `Developer ID may be invalid: ${id}`,\n suggestion:\n \"Developer IDs are numeric. Find yours at: Play Console → Settings → Developer account → Developer ID\",\n };\n}\n\nexport function checkConflictingCredentials(configSaPath?: string): CheckResult | null {\n const sources: string[] = [];\n if (configSaPath) sources.push(\"config file (auth.serviceAccount)\");\n if (process.env[\"GPC_SERVICE_ACCOUNT\"]) sources.push(\"GPC_SERVICE_ACCOUNT env var\");\n if (process.env[\"GOOGLE_APPLICATION_CREDENTIALS\"])\n sources.push(\"GOOGLE_APPLICATION_CREDENTIALS env var\");\n\n if (sources.length <= 1) return null;\n return {\n name: \"credentials-conflict\",\n status: \"warn\",\n message: `Multiple credential sources: ${sources.join(\", \")}`,\n suggestion:\n \"GPC uses the first match: config file → GPC_SERVICE_ACCOUNT → GOOGLE_APPLICATION_CREDENTIALS → ADC. Remove unused sources to avoid confusion.\",\n };\n}\n\nexport function checkConfigKeys(config: Record<string, unknown>): CheckResult | null {\n const unknown = Object.keys(config).filter((k) => !KNOWN_CONFIG_KEYS.has(k));\n if (unknown.length === 0) return null;\n return {\n name: \"config-keys\",\n status: \"warn\",\n message: `Unknown config key${unknown.length > 1 ? \"s\" : \"\"}: ${unknown.join(\", \")}`,\n suggestion: `Valid keys: ${[...KNOWN_CONFIG_KEYS].sort().join(\", \")}`,\n };\n}\n\nexport function checkCiEnvironment(): CheckResult | null {\n if (!process.env[\"CI\"]) return null;\n\n let platform = \"Unknown CI\";\n if (process.env[\"GITHUB_ACTIONS\"]) platform = \"GitHub Actions\";\n else if (process.env[\"GITLAB_CI\"]) platform = \"GitLab CI\";\n else if (process.env[\"BITBUCKET_PIPELINE_UUID\"]) platform = \"Bitbucket Pipelines\";\n else if (process.env[\"CIRCLECI\"]) platform = \"CircleCI\";\n else if (process.env[\"JENKINS_URL\"]) platform = \"Jenkins\";\n else if (process.env[\"TRAVIS\"]) platform = \"Travis CI\";\n else if (process.env[\"CODEBUILD_BUILD_ID\"]) platform = \"AWS CodeBuild\";\n else if (process.env[\"BUILD_BUILDID\"]) platform = \"Azure Pipelines\";\n\n const tips: string[] = [];\n if (!process.env[\"GPC_NO_COLOR\"]) tips.push(\"Set GPC_NO_COLOR=1 for clean logs\");\n if (!process.env[\"GPC_NO_UPDATE_CHECK\"])\n tips.push(\"Set GPC_NO_UPDATE_CHECK=1 to skip update checks\");\n\n return {\n name: \"ci\",\n status: \"info\",\n message: `CI detected: ${platform}`,\n suggestion: tips.length > 0 ? tips.join(\". \") : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Async check helpers\n// ---------------------------------------------------------------------------\n\nasync function checkGpcVersion(): Promise<CheckResult> {\n const currentVersion = process.env[\"__GPC_VERSION\"] ?? \"0.0.0\";\n if (currentVersion === \"0.0.0\") {\n return { name: \"version\", status: \"info\", message: \"GPC development build\" };\n }\n try {\n const resp = await fetch(NPM_REGISTRY_URL, {\n signal: AbortSignal.timeout(3000),\n });\n if (!resp.ok) return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n const body = (await resp.json()) as { version?: string };\n if (!body.version)\n return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n\n if (isNewerVersion(currentVersion, body.version)) {\n return {\n name: \"version\",\n status: \"warn\",\n message: `GPC v${currentVersion} (v${body.version} available)`,\n suggestion: \"Run: gpc update\",\n };\n }\n return {\n name: \"version\",\n status: \"pass\",\n message: `GPC v${currentVersion} (up to date)`,\n };\n } catch {\n return { name: \"version\", status: \"pass\", message: `GPC v${currentVersion}` };\n }\n}\n\nasync function checkDiskSpace(dir: string): Promise<CheckResult> {\n try {\n const stats = await statfs(dir);\n const availableGB = (Number(stats.bavail) * Number(stats.bsize)) / 1024 ** 3;\n if (availableGB < 0.1) {\n return {\n name: \"disk-space\",\n status: \"warn\",\n message: `Low disk space: ${availableGB.toFixed(1)} GB available`,\n suggestion: \"Free up disk space — AAB uploads can be up to 2 GB\",\n };\n }\n return {\n name: \"disk-space\",\n status: \"pass\",\n message: `Disk space: ${availableGB.toFixed(1)} GB available`,\n };\n } catch {\n // statfs may fail on some filesystems (network mounts, etc.)\n return { name: \"disk-space\", status: \"info\", message: \"Could not check disk space\" };\n }\n}\n\nasync function checkSaKeyAge(saPath: string): Promise<CheckResult | null> {\n try {\n const stats = await stat(saPath);\n const ageDays = Math.floor((Date.now() - stats.mtimeMs) / (1000 * 60 * 60 * 24));\n if (ageDays > SA_KEY_ROTATION_DAYS) {\n return {\n name: \"service-account-age\",\n status: \"warn\",\n message: `Service account key is ${ageDays} days old`,\n suggestion: `Google recommends rotating service account keys every ${SA_KEY_ROTATION_DAYS} days`,\n };\n }\n return null; // Don't clutter output when key is fresh\n } catch {\n return null;\n }\n}\n\nasync function checkTokenCache(cacheDir: string): Promise<CheckResult | null> {\n const cachePath = join(cacheDir, \"token-cache.json\");\n try {\n if (!existsSync(cachePath)) return null;\n const content = await readFile(cachePath, \"utf-8\");\n JSON.parse(content);\n return { name: \"token-cache\", status: \"pass\", message: \"Token cache OK\" };\n } catch {\n return {\n name: \"token-cache\",\n status: \"warn\",\n message: \"Token cache is corrupt\",\n suggestion: \"Clear with: gpc cache clear\",\n fixData: { path: cachePath },\n };\n }\n}\n\nasync function probeHttps(\n host: string,\n timeoutMs = 5000,\n): Promise<{ ok: boolean; latencyMs: number; error?: string }> {\n const { connect } = await import(\"node:tls\");\n return new Promise((resolve) => {\n const start = performance.now();\n const socket = connect({ host, port: 443 }, () => {\n const latencyMs = Math.round(performance.now() - start);\n socket.end();\n resolve({ ok: true, latencyMs });\n });\n socket.setTimeout(timeoutMs);\n socket.on(\"error\", (err: Error) => {\n socket.destroy();\n resolve({ ok: false, latencyMs: 0, error: err.message });\n });\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve({ ok: false, latencyMs: 0, error: \"Connection timed out\" });\n });\n });\n}\n\nasync function checkAppAccess(packageName: string, accessToken: string): Promise<CheckResult> {\n try {\n const insertResp = await fetch(\n `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}/edits`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({}),\n signal: AbortSignal.timeout(10_000),\n },\n );\n\n if (!insertResp.ok) {\n const body = (await insertResp.json().catch(() => ({}))) as {\n error?: { message?: string; status?: string };\n };\n\n // API not enabled in GCP project\n if (\n body.error?.status === \"PERMISSION_DENIED\" &&\n body.error?.message?.includes(\"has not been used\")\n ) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: \"Google Play Android Developer API is not enabled\",\n suggestion:\n \"Enable it: https://console.cloud.google.com/apis/api/androidpublisher.googleapis.com\",\n };\n }\n\n if (insertResp.status === 403) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `No access to ${packageName}`,\n suggestion:\n \"Grant the service account access in Google Play Console → Users and permissions\",\n };\n }\n if (insertResp.status === 404) {\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `App not found: ${packageName}`,\n suggestion: \"Check the package name with: gpc config get app\",\n };\n }\n return {\n name: \"app-access\",\n status: \"fail\",\n message: `App access check failed: HTTP ${insertResp.status}`,\n suggestion: body.error?.message ?? \"Check your credentials and app configuration\",\n };\n }\n\n // Clean up the test edit\n const edit = (await insertResp.json()) as { id?: string };\n if (edit.id) {\n await fetch(\n `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}/edits/${edit.id}`,\n {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(5000),\n },\n ).catch(() => {});\n }\n\n return {\n name: \"app-access\",\n status: \"pass\",\n message: `App access verified: ${packageName}`,\n };\n } catch (err) {\n return {\n name: \"app-access\",\n status: \"warn\",\n message: `Could not verify app access: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auto-fix\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], {\n recursive: true,\n mode: check.name === \"cache-dir\" ? 0o700 : 0o755,\n });\n return `Created ${dirMatch[1]}`;\n }\n case \"service-account-permissions\": {\n const saPath = check.fixData?.path;\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 \"token-cache\": {\n const cachePath = check.fixData?.path;\n if (!cachePath) return null;\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(cachePath);\n return `Cleared corrupt token cache`;\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\n// ---------------------------------------------------------------------------\n// Command registration\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 // -----------------------------------------------------------------------\n // 1. Node.js version\n // -----------------------------------------------------------------------\n results.push(checkNodeVersion(process.versions.node));\n\n // -----------------------------------------------------------------------\n // 2. GPC version (non-blocking — catches internally)\n // -----------------------------------------------------------------------\n results.push(await checkGpcVersion());\n\n // -----------------------------------------------------------------------\n // 3. CI environment (info only)\n // -----------------------------------------------------------------------\n const ciResult = checkCiEnvironment();\n if (ciResult) results.push(ciResult);\n\n // -----------------------------------------------------------------------\n // 4. Config file + dependent checks\n // -----------------------------------------------------------------------\n let config;\n try {\n config = await loadConfig();\n results.push({ name: \"config\", status: \"pass\", message: \"Configuration loaded\" });\n\n // 4b. Unknown config keys\n const keysCheck = checkConfigKeys(config as unknown as Record<string, unknown>);\n if (keysCheck) results.push(keysCheck);\n\n // 4c. Default app\n if (config.app) {\n results.push({\n name: \"default-app\",\n status: \"pass\",\n message: `Default app: ${config.app}`,\n });\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\n // 4d. Developer ID\n const devIdCheck = checkDeveloperId(config.developerId);\n if (devIdCheck) results.push(devIdCheck);\n } catch {\n results.push({\n name: \"config\",\n status: \"fail\",\n message: \"Configuration could not be loaded\",\n suggestion:\n \"Run gpc config init to create a config file, or check .gpcrc.json for syntax errors\",\n });\n }\n\n // -----------------------------------------------------------------------\n // 5. Config directory permissions\n // -----------------------------------------------------------------------\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 // -----------------------------------------------------------------------\n // 6. Cache directory permissions\n // -----------------------------------------------------------------------\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 // -----------------------------------------------------------------------\n // 7. Disk space\n // -----------------------------------------------------------------------\n const spaceDir = existsSync(cacheDir) ? cacheDir : configDir;\n if (existsSync(spaceDir)) {\n results.push(await checkDiskSpace(spaceDir));\n }\n\n // -----------------------------------------------------------------------\n // 8. Service account file + permissions\n // -----------------------------------------------------------------------\n let saFilePath: string | undefined;\n if (config?.auth?.serviceAccount) {\n const saValue = config.auth.serviceAccount;\n const looksLikePath = !saValue.trim().startsWith(\"{\");\n if (looksLikePath) {\n saFilePath = resolve(saValue);\n if (existsSync(saFilePath)) {\n try {\n accessSync(saFilePath, constants.R_OK);\n results.push({\n name: \"service-account-file\",\n status: \"pass\",\n message: `Service account file: ${saFilePath}`,\n });\n } catch {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not readable: ${saFilePath}`,\n suggestion: `Fix permissions: chmod 600 ${saFilePath}`,\n });\n }\n\n // 8b. SA key file permissions (Unix only)\n if (process.platform !== \"win32\") {\n try {\n const mode = statSync(saFilePath).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 ${saFilePath}`,\n fixData: { path: saFilePath },\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\n // 8c. SA key age\n const ageResult = await checkSaKeyAge(saFilePath);\n if (ageResult) results.push(ageResult);\n } else {\n results.push({\n name: \"service-account-file\",\n status: \"fail\",\n message: `Service account file not found: ${saFilePath}`,\n suggestion: \"Check the path in your config or GPC_SERVICE_ACCOUNT env var\",\n });\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // 9. Conflicting credentials\n // -----------------------------------------------------------------------\n const conflictCheck = checkConflictingCredentials(saFilePath);\n if (conflictCheck) results.push(conflictCheck);\n\n // -----------------------------------------------------------------------\n // 10. Token cache health\n // -----------------------------------------------------------------------\n const cacheResult = await checkTokenCache(cacheDir);\n if (cacheResult) results.push(cacheResult);\n\n // -----------------------------------------------------------------------\n // 11. Profile validation\n // -----------------------------------------------------------------------\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 // -----------------------------------------------------------------------\n // 12. Proxy configuration\n // -----------------------------------------------------------------------\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n const proxyCheck = checkProxy(proxyUrl);\n if (proxyCheck) results.push(proxyCheck);\n\n // -----------------------------------------------------------------------\n // 13. CA certificate\n // -----------------------------------------------------------------------\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 // -----------------------------------------------------------------------\n // 14. DNS resolution — with latency\n // -----------------------------------------------------------------------\n const dnsHosts = [API_HOST, REPORTING_HOST];\n const dnsPassedHosts: string[] = [];\n\n for (const host of dnsHosts) {\n const label = host.split(\".\")[0]!;\n try {\n const start = performance.now();\n await lookup(host);\n const ms = Math.round(performance.now() - start);\n results.push({\n name: `dns-${label}`,\n status: \"pass\",\n message: `DNS: ${host} (${ms}ms)`,\n });\n dnsPassedHosts.push(host);\n } catch {\n results.push({\n name: `dns-${label}`,\n status: \"fail\",\n message: `Cannot resolve ${host}`,\n suggestion: \"Check your DNS settings and network connection\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 15. HTTPS connectivity probe — only for hosts that passed DNS\n // -----------------------------------------------------------------------\n for (const host of dnsPassedHosts) {\n const label = host.split(\".\")[0]!;\n const probe = await probeHttps(host);\n if (probe.ok) {\n results.push({\n name: `https-${label}`,\n status: \"pass\",\n message: `HTTPS: ${host} (${probe.latencyMs}ms)`,\n });\n } else {\n results.push({\n name: `https-${label}`,\n status: \"fail\",\n message: `HTTPS connection failed: ${host}`,\n suggestion: probe.error\n ? `Error: ${probe.error}. Check firewall rules and proxy settings.`\n : \"Check firewall rules and proxy settings\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 16. Authentication + API connectivity\n // -----------------------------------------------------------------------\n let accessToken: string | undefined;\n\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 accessToken = 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 const detail = error instanceof Error ? error.message : String(error);\n results.push({\n name: \"api-connectivity\",\n status: \"fail\",\n message: `API connectivity failed: ${detail}`,\n suggestion: \"Check your network connection and credentials\",\n });\n }\n }\n\n // -----------------------------------------------------------------------\n // 17. App access (only if auth succeeded and app is configured)\n // -----------------------------------------------------------------------\n if (accessToken && config?.app) {\n results.push(await checkAppAccess(config.app, accessToken));\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(\"\\u2192\")} Fixed: ${fixMsg}`);\n r.status = \"pass\";\n r.message += \" (fixed)\";\n }\n } catch (err) {\n console.error(\n ` ${red(\"\\u2717\")} Could not fix \"${r.name}\": ${err instanceof Error ? err.message : String(err)}`,\n );\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 // Strip fixData from JSON output\n const cleanResults = results.map(({ fixData: _, ...rest }) => rest);\n console.log(\n JSON.stringify(\n { success: errors === 0, errors, warnings, checks: cleanResults },\n null,\n 2,\n ),\n );\n process.exitCode = errors > 0 ? 1 : 0;\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 ${green(PASS)} ${passed} passed ${yellow(WARN)} ${warnings} warning${warnings !== 1 ? \"s\" : \"\"} ${red(FAIL)} ${errors} failed`,\n );\n\n if (errors > 0) {\n console.log(\"\\nSome checks failed. Fix the issues above and run again.\");\n process.exitCode = 1;\n } else if (warnings > 0) {\n console.log(\"\\nAll checks passed with warnings.\");\n } else {\n console.log(`\\n${green(\"\\u2713\")} Ready. Try: gpc status`);\n }\n });\n}\n"],"mappings":"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","names":["resolve"]}
@@ -23,17 +23,12 @@ function registerEnterpriseCommands(program) {
23
23
  const { client, config } = await getClient();
24
24
  const orgId = enterprise.opts()["org"];
25
25
  const format = getOutputFormat(program, config);
26
- try {
27
- const result = await listEnterpriseApps(client, orgId);
28
- if (result.length === 0 && format !== "json") {
29
- console.log("No enterprise apps found.");
30
- return;
31
- }
32
- console.log(formatOutput(result, format));
33
- } catch (error) {
34
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
35
- process.exit(4);
26
+ const result = await listEnterpriseApps(client, orgId);
27
+ if (result.length === 0 && format !== "json") {
28
+ console.log("No enterprise apps found.");
29
+ return;
36
30
  }
31
+ console.log(formatOutput(result, format));
37
32
  });
38
33
  enterprise.command("create").description("Create a new private enterprise app").requiredOption("--title <title>", "App title").option("--lang <code>", "Language code (default: en_US)", "en_US").action(async (options) => {
39
34
  const { client, config } = await getClient();
@@ -51,19 +46,14 @@ function registerEnterpriseCommands(program) {
51
46
  );
52
47
  return;
53
48
  }
54
- try {
55
- const result = await createEnterpriseApp(client, orgId, {
56
- title: options.title,
57
- languageCode: options.lang
58
- });
59
- console.log(formatOutput(result, format));
60
- } catch (error) {
61
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
62
- process.exit(4);
63
- }
49
+ const result = await createEnterpriseApp(client, orgId, {
50
+ title: options.title,
51
+ languageCode: options.lang
52
+ });
53
+ console.log(formatOutput(result, format));
64
54
  });
65
55
  }
66
56
  export {
67
57
  registerEnterpriseCommands
68
58
  };
69
- //# sourceMappingURL=enterprise-7THXNBTC.js.map
59
+ //# sourceMappingURL=enterprise-7PWXMSUN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/enterprise.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createEnterpriseClient } from \"@gpc-cli/api\";\nimport { listEnterpriseApps, createEnterpriseApp, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\n\nasync function getClient() {\n const config = await loadConfig();\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return { client: createEnterpriseClient({ auth }), config };\n}\n\nexport function registerEnterpriseCommands(program: Command): void {\n const enterprise = program\n .command(\"enterprise\")\n .description(\"Manage private enterprise apps via Managed Google Play\")\n .requiredOption(\"--org <id>\", \"Google Play organization ID\");\n\n enterprise\n .command(\"list\")\n .description(\"List private enterprise apps\")\n .action(async () => {\n const { client, config } = await getClient();\n const orgId = enterprise.opts()[\"org\"] as string;\n const format = getOutputFormat(program, config);\n\n const result = await listEnterpriseApps(client, orgId);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No enterprise apps found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n enterprise\n .command(\"create\")\n .description(\"Create a new private enterprise app\")\n .requiredOption(\"--title <title>\", \"App title\")\n .option(\"--lang <code>\", \"Language code (default: en_US)\", \"en_US\")\n .action(async (options) => {\n const { client, config } = await getClient();\n const orgId = enterprise.opts()[\"org\"] as string;\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"enterprise create\",\n action: \"create enterprise app\",\n target: options.title as string,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const result = await createEnterpriseApp(client, orgId, {\n title: options.title as string,\n languageCode: options.lang as string,\n });\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,8BAA8B;AACvC,SAAS,oBAAoB,qBAAqB,oBAAoB;AAItE,eAAe,YAAY;AACzB,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,EAAE,QAAQ,uBAAuB,EAAE,KAAK,CAAC,GAAG,OAAO;AAC5D;AAEO,SAAS,2BAA2B,SAAwB;AACjE,QAAM,aAAa,QAChB,QAAQ,YAAY,EACpB,YAAY,wDAAwD,EACpE,eAAe,cAAc,6BAA6B;AAE7D,aACG,QAAQ,MAAM,EACd,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU;AAC3C,UAAM,QAAQ,WAAW,KAAK,EAAE,KAAK;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,mBAAmB,QAAQ,KAAK;AACrD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,2BAA2B;AACvC;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,aACG,QAAQ,QAAQ,EAChB,YAAY,qCAAqC,EACjD,eAAe,mBAAmB,WAAW,EAC7C,OAAO,iBAAiB,kCAAkC,OAAO,EACjE,OAAO,OAAO,YAAY;AACzB,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU;AAC3C,UAAM,QAAQ,WAAW,KAAK,EAAE,KAAK;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;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,oBAAoB,QAAQ,OAAO;AAAA,MACtD,OAAO,QAAQ;AAAA,MACf,cAAc,QAAQ;AAAA,IACxB,CAAC;AACD,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getClient,
4
4
  resolvePackageName
5
- } from "./chunk-AA577WVQ.js";
5
+ } from "./chunk-NQH4G7BI.js";
6
6
  import {
7
7
  isDryRun,
8
8
  printDryRun
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-ELXAK7GI.js";
13
13
  import {
14
14
  requireConfirm
15
- } from "./chunk-NV75I5VP.js";
15
+ } from "./chunk-YFUBD2XB.js";
16
16
 
17
17
  // src/commands/external-transactions.ts
18
18
  import { loadConfig } from "@gpc-cli/config";
@@ -33,10 +33,9 @@ function registerExternalTransactionsCommands(program) {
33
33
  try {
34
34
  data = JSON.parse(readFileSync(options.file, "utf-8"));
35
35
  } catch (err) {
36
- console.error(
37
- `Error: Could not read transaction data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`
38
- );
39
- process.exit(2);
36
+ const error = new Error(`Could not read transaction data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`);
37
+ Object.assign(error, { code: "INVALID_INPUT", exitCode: 2, suggestion: "Check the file path and ensure it contains valid JSON." });
38
+ throw error;
40
39
  }
41
40
  if (isDryRun(program)) {
42
41
  printDryRun(
@@ -52,26 +51,16 @@ function registerExternalTransactionsCommands(program) {
52
51
  return;
53
52
  }
54
53
  const client = await getClient(config);
55
- try {
56
- const result = await createExternalTransaction(client, packageName, data);
57
- console.log(formatOutput(result, format));
58
- } catch (error) {
59
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
60
- process.exit(4);
61
- }
54
+ const result = await createExternalTransaction(client, packageName, data);
55
+ console.log(formatOutput(result, format));
62
56
  });
63
57
  extTxn.command("get <id>").description("Get an external transaction by ID").action(async (id) => {
64
58
  const config = await loadConfig();
65
59
  const packageName = resolvePackageName(program.opts()["app"], config);
66
60
  const client = await getClient(config);
67
61
  const format = getOutputFormat(program, config);
68
- try {
69
- const result = await getExternalTransaction(client, packageName, id);
70
- console.log(formatOutput(result, format));
71
- } catch (error) {
72
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
73
- process.exit(4);
74
- }
62
+ const result = await getExternalTransaction(client, packageName, id);
63
+ console.log(formatOutput(result, format));
75
64
  });
76
65
  extTxn.command("refund <id>").description("Refund an external transaction").option("--full", "Full refund").option("--partial-amount <micros>", "Partial refund pre-tax amount in micros (e.g., 1990000)").option("--currency <code>", "Currency code for partial refund (e.g. USD)").action(async (id, options) => {
77
66
  const config = await loadConfig();
@@ -105,16 +94,11 @@ function registerExternalTransactionsCommands(program) {
105
94
  return;
106
95
  }
107
96
  const client = await getClient(config);
108
- try {
109
- const result = await refundExternalTransaction(client, packageName, id, refundData);
110
- console.log(formatOutput(result, format));
111
- } catch (error) {
112
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
113
- process.exit(4);
114
- }
97
+ const result = await refundExternalTransaction(client, packageName, id, refundData);
98
+ console.log(formatOutput(result, format));
115
99
  });
116
100
  }
117
101
  export {
118
102
  registerExternalTransactionsCommands
119
103
  };
120
- //# sourceMappingURL=external-transactions-2GWIMUVM.js.map
104
+ //# sourceMappingURL=external-transactions-LCZALS3V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/external-transactions.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\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\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 const error = new Error(`Could not read transaction data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`);\n Object.assign(error, { code: \"INVALID_INPUT\", exitCode: 2, suggestion: \"Check the file path and ensure it contains valid JSON.\" });\n throw error;\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 const result = await createExternalTransaction(client, packageName, data);\n console.log(formatOutput(result, format));\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 const result = await getExternalTransaction(client, packageName, id);\n console.log(formatOutput(result, format));\n });\n\n extTxn\n .command(\"refund <id>\")\n .description(\"Refund an external transaction\")\n .option(\"--full\", \"Full refund\")\n .option(\"--partial-amount <micros>\", \"Partial refund pre-tax amount in micros (e.g., 1990000)\")\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 const result = await refundExternalTransaction(client, packageName, id, refundData);\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":"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","names":[]}
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  detectInstallMethod
4
- } from "./chunk-U6ZTQ34I.js";
5
- import "./chunk-4O4D5SGL.js";
4
+ } from "./chunk-BCBXQC7J.js";
5
+ import "./chunk-3SJ6OXCZ.js";
6
6
 
7
7
  // src/commands/feedback.ts
8
8
  import { execFile } from "child_process";
9
9
  import { listAuditEvents } from "@gpc-cli/core";
10
10
  function registerFeedbackCommand(program) {
11
11
  program.command("feedback").description("Open a pre-filled GitHub issue with system diagnostics").option("--title <title>", "Issue title").option("--print", "Print the report to stdout instead of opening a browser").action(async (opts) => {
12
- const version = "0.9.44";
12
+ const version = "0.9.45";
13
13
  let lastCommand = "";
14
14
  try {
15
15
  const events = await listAuditEvents({ limit: 3 });
@@ -67,4 +67,4 @@ ${url}`);
67
67
  export {
68
68
  registerFeedbackCommand
69
69
  };
70
- //# sourceMappingURL=feedback-2W2XJGZX.js.map
70
+ //# sourceMappingURL=feedback-XP765TOO.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolvePackageName
4
- } from "./chunk-AA577WVQ.js";
4
+ } from "./chunk-NQH4G7BI.js";
5
5
  import {
6
6
  getOutputFormat
7
7
  } from "./chunk-ELXAK7GI.js";
@@ -22,54 +22,39 @@ function registerGamesCommands(program) {
22
22
  const packageName = resolvePackageName(program.opts()["app"], config);
23
23
  const client = await getGamesClient(config);
24
24
  const format = getOutputFormat(program, config);
25
- try {
26
- const result = await listLeaderboards(client, packageName);
27
- if (result.length === 0 && format !== "json") {
28
- console.log("No leaderboards found.");
29
- return;
30
- }
31
- console.log(formatOutput(result, format));
32
- } catch (error) {
33
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
34
- process.exit(4);
25
+ const result = await listLeaderboards(client, packageName);
26
+ if (result.length === 0 && format !== "json") {
27
+ console.log("No leaderboards found.");
28
+ return;
35
29
  }
30
+ console.log(formatOutput(result, format));
36
31
  });
37
32
  games.command("achievements").description("List achievements for the app").action(async () => {
38
33
  const config = await loadConfig();
39
34
  const packageName = resolvePackageName(program.opts()["app"], config);
40
35
  const client = await getGamesClient(config);
41
36
  const format = getOutputFormat(program, config);
42
- try {
43
- const result = await listAchievements(client, packageName);
44
- if (result.length === 0 && format !== "json") {
45
- console.log("No achievements found.");
46
- return;
47
- }
48
- console.log(formatOutput(result, format));
49
- } catch (error) {
50
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
51
- process.exit(4);
37
+ const result = await listAchievements(client, packageName);
38
+ if (result.length === 0 && format !== "json") {
39
+ console.log("No achievements found.");
40
+ return;
52
41
  }
42
+ console.log(formatOutput(result, format));
53
43
  });
54
44
  games.command("events").description("List events for the app").action(async () => {
55
45
  const config = await loadConfig();
56
46
  const packageName = resolvePackageName(program.opts()["app"], config);
57
47
  const client = await getGamesClient(config);
58
48
  const format = getOutputFormat(program, config);
59
- try {
60
- const result = await listEvents(client, packageName);
61
- if (result.length === 0 && format !== "json") {
62
- console.log("No events found.");
63
- return;
64
- }
65
- console.log(formatOutput(result, format));
66
- } catch (error) {
67
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
68
- process.exit(4);
49
+ const result = await listEvents(client, packageName);
50
+ if (result.length === 0 && format !== "json") {
51
+ console.log("No events found.");
52
+ return;
69
53
  }
54
+ console.log(formatOutput(result, format));
70
55
  });
71
56
  }
72
57
  export {
73
58
  registerGamesCommands
74
59
  };
75
- //# sourceMappingURL=games-BT777WUO.js.map
60
+ //# sourceMappingURL=games-ZSNGEI7A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/games.ts"],"sourcesContent":["import { resolvePackageName } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createGamesClient } from \"@gpc-cli/api\";\nimport { listLeaderboards, listAchievements, listEvents, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nasync function getGamesClient(config: { auth?: { serviceAccount?: string } }) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createGamesClient({ auth });\n}\n\n\n\nexport function registerGamesCommands(program: Command): void {\n const games = program\n .command(\"games\")\n .description(\"Manage Play Games Services — leaderboards, achievements, events\");\n\n games\n .command(\"leaderboards\")\n .description(\"List leaderboards for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getGamesClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listLeaderboards(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No leaderboards found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n games\n .command(\"achievements\")\n .description(\"List achievements for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getGamesClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listAchievements(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No achievements found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n games\n .command(\"events\")\n .description(\"List events for the app\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getGamesClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listEvents(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No events found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kBAAkB,kBAAkB,YAAY,oBAAoB;AAG7E,eAAe,eAAe,QAAgD;AAC5E,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,kBAAkB,EAAE,KAAK,CAAC;AACnC;AAIO,SAAS,sBAAsB,SAAwB;AAC5D,QAAM,QAAQ,QACX,QAAQ,OAAO,EACf,YAAY,sEAAiE;AAEhF,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,wBAAwB;AACpC;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,wBAAwB;AACpC;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,WAAW,QAAQ,WAAW;AACnD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,kBAAkB;AAC9B;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getClient,
4
4
  resolvePackageName
5
- } from "./chunk-AA577WVQ.js";
5
+ } from "./chunk-NQH4G7BI.js";
6
6
  import {
7
7
  getOutputFormat
8
8
  } from "./chunk-ELXAK7GI.js";
@@ -19,30 +19,26 @@ function registerGeneratedApksCommands(program) {
19
19
  const format = getOutputFormat(program, config);
20
20
  const versionCode = parseInt(versionCodeStr, 10);
21
21
  if (isNaN(versionCode)) {
22
- console.error("Error: version-code must be a number");
23
- process.exit(2);
22
+ const err = new Error("version-code must be a number");
23
+ Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
24
+ throw err;
24
25
  }
25
- try {
26
- const result = await listGeneratedApks(client, packageName, versionCode);
27
- if (format !== "json") {
28
- const apks = result["generatedApks"];
29
- if (apks && apks.length > 0) {
30
- const rows = apks.map((apk) => ({
31
- id: apk["generatedApkId"] || "-",
32
- variantId: apk["variantId"] || "-",
33
- moduleName: apk["moduleName"] || "-",
34
- sha256: String(apk["certificateSha256Fingerprint"] || "-").slice(0, 16) + "..."
35
- }));
36
- console.log(formatOutput(rows, format));
37
- } else {
38
- console.log("No generated APKs found.");
39
- }
26
+ const result = await listGeneratedApks(client, packageName, versionCode);
27
+ if (format !== "json") {
28
+ const apks = result["generatedApks"];
29
+ if (apks && apks.length > 0) {
30
+ const rows = apks.map((apk) => ({
31
+ id: apk["generatedApkId"] || "-",
32
+ variantId: apk["variantId"] || "-",
33
+ moduleName: apk["moduleName"] || "-",
34
+ sha256: String(apk["certificateSha256Fingerprint"] || "-").slice(0, 16) + "..."
35
+ }));
36
+ console.log(formatOutput(rows, format));
40
37
  } else {
41
- console.log(formatOutput(result, format));
38
+ console.log("No generated APKs found.");
42
39
  }
43
- } catch (error) {
44
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
45
- process.exit(4);
40
+ } else {
41
+ console.log(formatOutput(result, format));
46
42
  }
47
43
  });
48
44
  cmd.command("download <version-code> <apk-id>").description("Download a generated APK").requiredOption("--output <path>", "Output file path").action(async (versionCodeStr, apkId, opts) => {
@@ -52,25 +48,21 @@ function registerGeneratedApksCommands(program) {
52
48
  const format = getOutputFormat(program, config);
53
49
  const versionCode = parseInt(versionCodeStr, 10);
54
50
  if (isNaN(versionCode)) {
55
- console.error("Error: version-code must be a number");
56
- process.exit(2);
57
- }
58
- try {
59
- const result = await downloadGeneratedApk(
60
- client,
61
- packageName,
62
- versionCode,
63
- apkId,
64
- opts.output
65
- );
66
- console.log(formatOutput(result, format));
67
- } catch (error) {
68
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
69
- process.exit(4);
51
+ const err = new Error("version-code must be a number");
52
+ Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
53
+ throw err;
70
54
  }
55
+ const result = await downloadGeneratedApk(
56
+ client,
57
+ packageName,
58
+ versionCode,
59
+ apkId,
60
+ opts.output
61
+ );
62
+ console.log(formatOutput(result, format));
71
63
  });
72
64
  }
73
65
  export {
74
66
  registerGeneratedApksCommands
75
67
  };
76
- //# sourceMappingURL=generated-apks-RJWTIX7L.js.map
68
+ //# sourceMappingURL=generated-apks-RX2IUWSF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/generated-apks.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport { listGeneratedApks, downloadGeneratedApk, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\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 const err = new Error(\"version-code must be a number\");\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n }\n\n const result = await listGeneratedApks(client, packageName, versionCode);\n if (format !== \"json\") {\n const apks = (result as unknown as Record<string, unknown>)[\"generatedApks\"] as\n | Array<Record<string, unknown>>\n | 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 });\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 const err = new Error(\"version-code must be a number\");\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n }\n\n const result = await downloadGeneratedApk(\n client,\n packageName,\n versionCode,\n apkId,\n opts.output,\n );\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;;AAEA,SAAS,kBAAkB;AAE3B,SAAS,mBAAmB,sBAAsB,oBAAoB;AAK/D,SAAS,8BAA8B,SAAwB;AACpE,QAAM,MAAM,QACT,QAAQ,gBAAgB,EACxB,YAAY,sDAAsD;AAErE,MACG,QAAQ,qBAAqB,EAC7B,YAAY,wCAAwC,EACpD,OAAO,OAAO,mBAA2B;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,MAAM,IAAI,MAAM,+BAA+B;AACrD,aAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,YAAM;AAAA,IACR;AAEA,UAAM,SAAS,MAAM,kBAAkB,QAAQ,aAAa,WAAW;AACvE,QAAI,WAAW,QAAQ;AACrB,YAAM,OAAQ,OAA8C,eAAe;AAG3E,UAAI,QAAQ,KAAK,SAAS,GAAG;AAC3B,cAAM,OAAO,KAAK,IAAI,CAAC,SAAS;AAAA,UAC9B,IAAI,IAAI,gBAAgB,KAAK;AAAA,UAC7B,WAAW,IAAI,WAAW,KAAK;AAAA,UAC/B,YAAY,IAAI,YAAY,KAAK;AAAA,UACjC,QAAQ,OAAO,IAAI,8BAA8B,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI;AAAA,QAC5E,EAAE;AACF,gBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,MACxC,OAAO;AACL,gBAAQ,IAAI,0BAA0B;AAAA,MACxC;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C;AAAA,EACF,CAAC;AAEH,MACG,QAAQ,kCAAkC,EAC1C,YAAY,0BAA0B,EACtC,eAAe,mBAAmB,kBAAkB,EACpD,OAAO,OAAO,gBAAwB,OAAe,SAA6B;AACjF,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,MAAM,IAAI,MAAM,+BAA+B;AACrD,aAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,YAAM;AAAA,IACR;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
@@ -8,20 +8,22 @@ import {
8
8
  } from "./chunk-ELXAK7GI.js";
9
9
  import {
10
10
  requireConfirm
11
- } from "./chunk-NV75I5VP.js";
11
+ } from "./chunk-YFUBD2XB.js";
12
12
 
13
13
  // src/commands/grants.ts
14
14
  import { loadConfig } from "@gpc-cli/config";
15
15
  import { resolveAuth } from "@gpc-cli/auth";
16
16
  import { createUsersClient } from "@gpc-cli/api";
17
- import { listGrants, createGrant, updateGrant, deleteGrant, formatOutput } from "@gpc-cli/core";
17
+ import { listGrants, createGrant, updateGrant, deleteGrant, formatOutput, GpcError } from "@gpc-cli/core";
18
18
  function resolveDeveloperId(devIdArg, config) {
19
19
  const id = devIdArg || config.developerId;
20
20
  if (!id) {
21
- console.error(
22
- "Error: No developer ID. Use --developer-id <id> or gpc config set developerId <id>"
21
+ throw new GpcError(
22
+ "No developer ID. Use --developer-id <id> or gpc config set developerId <id>",
23
+ "MISSING_DEVELOPER_ID",
24
+ 2,
25
+ "gpc config set developerId <id>"
23
26
  );
24
- process.exit(2);
25
27
  }
26
28
  return id;
27
29
  }
@@ -36,21 +38,16 @@ function registerGrantsCommands(program) {
36
38
  const developerId = resolveDeveloperId(grants.opts()["developerId"], config);
37
39
  const client = await getClient(config);
38
40
  const format = getOutputFormat(program, config);
39
- try {
40
- const result = await listGrants(client, developerId, email);
41
- if (result.length === 0) {
42
- if (format === "json") {
43
- console.log(formatOutput([], format));
44
- } else {
45
- console.log(`No grants found for ${email}.`);
46
- }
47
- return;
41
+ const result = await listGrants(client, developerId, email);
42
+ if (result.length === 0) {
43
+ if (format === "json") {
44
+ console.log(formatOutput([], format));
45
+ } else {
46
+ console.log(`No grants found for ${email}.`);
48
47
  }
49
- console.log(formatOutput(result, format));
50
- } catch (error) {
51
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
52
- process.exit(4);
48
+ return;
53
49
  }
50
+ console.log(formatOutput(result, format));
54
51
  });
55
52
  grants.command("create <email>").description("Grant app-level permissions to a user").requiredOption("--package <packageName>", "App package name").requiredOption(
56
53
  "--permissions <list>",
@@ -74,13 +71,8 @@ function registerGrantsCommands(program) {
74
71
  return;
75
72
  }
76
73
  const client = await getClient(config);
77
- try {
78
- const result = await createGrant(client, developerId, email, options.package, perms);
79
- console.log(formatOutput(result, format));
80
- } catch (error) {
81
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
82
- process.exit(4);
83
- }
74
+ const result = await createGrant(client, developerId, email, options.package, perms);
75
+ console.log(formatOutput(result, format));
84
76
  });
85
77
  grants.command("update <email>").description("Update app-level permissions for a user").requiredOption("--package <packageName>", "App package name").requiredOption("--permissions <list>", "New comma-separated permissions").action(async (email, options) => {
86
78
  const config = await loadConfig();
@@ -101,13 +93,8 @@ function registerGrantsCommands(program) {
101
93
  return;
102
94
  }
103
95
  const client = await getClient(config);
104
- try {
105
- const result = await updateGrant(client, developerId, email, options.package, perms);
106
- console.log(formatOutput(result, format));
107
- } catch (error) {
108
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
109
- process.exit(4);
110
- }
96
+ const result = await updateGrant(client, developerId, email, options.package, perms);
97
+ console.log(formatOutput(result, format));
111
98
  });
112
99
  grants.command("delete <email>").description("Remove a per-app grant from a user").requiredOption("--package <packageName>", "App package name").action(async (email, options) => {
113
100
  const config = await loadConfig();
@@ -127,16 +114,11 @@ function registerGrantsCommands(program) {
127
114
  return;
128
115
  }
129
116
  const client = await getClient(config);
130
- try {
131
- await deleteGrant(client, developerId, email, options.package);
132
- console.log(`Grant removed for ${email} on ${options.package}.`);
133
- } catch (error) {
134
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
135
- process.exit(4);
136
- }
117
+ await deleteGrant(client, developerId, email, options.package);
118
+ console.log(`Grant removed for ${email} on ${options.package}.`);
137
119
  });
138
120
  }
139
121
  export {
140
122
  registerGrantsCommands
141
123
  };
142
- //# sourceMappingURL=grants-TKQJ3IER.js.map
124
+ //# sourceMappingURL=grants-EBPECI26.js.map