@gpc-cli/cli 0.9.45 → 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 (167) 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 +5 -3
  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-SEVX56VN.js → chunk-6OWN6S6X.js} +52 -48
  20. package/dist/{chunk-SEVX56VN.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-BUXPDN7N.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-DPTO6DUT.js → feedback-XP765TOO.js} +3 -3
  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-43AKV6HG.js → purchases-DAWTMXP6.js} +118 -193
  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-CJJVLY4B.js → train-MDD2EBHS.js} +35 -55
  99. package/dist/train-MDD2EBHS.js.map +1 -0
  100. package/dist/{update-NAK6CMUX.js → update-OMALGIBR.js} +29 -14
  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-N64UBW7A.js → version-NCSNXNVN.js} +3 -3
  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-ZYD6W5IV.js +0 -53
  118. package/dist/changelog-ZYD6W5IV.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-BUXPDN7N.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-43AKV6HG.js.map +0 -1
  148. package/dist/quickstart-4HB62YEL.js.map +0 -1
  149. package/dist/quota-UHIQQYOY.js.map +0 -1
  150. package/dist/recovery-5EV2R476.js.map +0 -1
  151. package/dist/releases-C2WC2K4E.js.map +0 -1
  152. package/dist/reports-2YX3RDOS.js.map +0 -1
  153. package/dist/reviews-2CWOI5CV.js +0 -213
  154. package/dist/reviews-2CWOI5CV.js.map +0 -1
  155. package/dist/status-WHGLODGV.js.map +0 -1
  156. package/dist/subscriptions-CI3JH3VQ.js.map +0 -1
  157. package/dist/testers-NZOFA3EF.js.map +0 -1
  158. package/dist/tracks-NERFFEDT.js +0 -107
  159. package/dist/tracks-NERFFEDT.js.map +0 -1
  160. package/dist/train-CJJVLY4B.js.map +0 -1
  161. package/dist/update-NAK6CMUX.js.map +0 -1
  162. package/dist/users-2YTC4Q36.js.map +0 -1
  163. package/dist/validate-UOVTM6L3.js.map +0 -1
  164. package/dist/vitals-A4CS4MSS.js.map +0 -1
  165. /package/dist/{feedback-DPTO6DUT.js.map → feedback-XP765TOO.js.map} +0 -0
  166. /package/dist/{prompt-BSV22CQZ.js.map → prompt-GXC2JSLA.js.map} +0 -0
  167. /package/dist/{version-N64UBW7A.js.map → version-NCSNXNVN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport type { ResolvedConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient, createReportingClient } from \"@gpc-cli/api\";\nimport {\n getAppStatus,\n formatStatusTable,\n formatStatusSummary,\n formatStatusDiff,\n computeStatusDiff,\n loadStatusCache,\n saveStatusCache,\n statusHasBreach,\n runWatchLoop,\n trackBreachState,\n sendNotification,\n relativeTime,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport type { AppStatus } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { green, red, dim, gray } from \"../colors.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst VALID_SECTIONS = new Set([\"releases\", \"vitals\", \"reviews\"]);\nconst VALID_FORMATS = new Set([\"table\", \"summary\"]);\nconst MAX_ALL_APPS = 5;\n\nconst THRESHOLD_KEYS: Record<string, string> = {\n crashes: \"crashRate\",\n crash: \"crashRate\",\n anr: \"anrRate\",\n \"slow-starts\": \"slowStartRate\",\n \"slow-start\": \"slowStartRate\",\n \"slow-render\": \"slowRenderingRate\",\n \"slow-rendering\": \"slowRenderingRate\",\n};\n\n// ---------------------------------------------------------------------------\n// Validation error helper\n// ---------------------------------------------------------------------------\n\nfunction usageError(message: string, suggestion?: string): never {\n throw Object.assign(new Error(message), {\n code: \"STATUS_USAGE_ERROR\",\n exitCode: 2,\n suggestion,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Pure, testable helpers\n// ---------------------------------------------------------------------------\n\nexport function parseSections(raw: string): string[] {\n const sections = raw.split(\",\").map((s) => s.trim().toLowerCase());\n for (const s of sections) {\n if (!VALID_SECTIONS.has(s)) {\n usageError(\n `Unknown section \"${s}\"`,\n \"Valid sections: releases, vitals, reviews\",\n );\n }\n }\n return sections;\n}\n\nexport function parseThresholdOverrides(raw: string): Record<string, number> {\n const result: Record<string, number> = {};\n for (const pair of raw.split(\",\")) {\n const [key, val] = pair.split(\"=\").map((s) => s.trim());\n if (!key || !val) continue;\n const mapped = THRESHOLD_KEYS[key.toLowerCase()];\n if (!mapped) {\n usageError(\n `Unknown threshold \"${key}\"`,\n \"Valid: crashes, anr, slow-starts, slow-render\",\n );\n }\n const n = parseFloat(val);\n if (isNaN(n) || n < 0) {\n usageError(\n `Invalid threshold value \"${val}\" for ${key}`,\n \"Must be a positive number (percent)\",\n );\n }\n result[mapped] = n / 100; // Convert percent to decimal\n }\n return result;\n}\n\nexport function resolveWatchInterval(watch: string | boolean | undefined): number | null {\n if (watch === undefined) return null;\n if (watch === true || watch === \"\") return 30;\n const n = parseInt(String(watch), 10);\n return isNaN(n) ? 30 : n;\n}\n\nfunction resolveVitalThresholds(config: ResolvedConfig) {\n const raw = config as unknown as Record<string, unknown>;\n const vitals = raw[\"vitals\"] as Record<string, unknown> | undefined;\n if (!vitals || typeof vitals !== \"object\") return undefined;\n const t = vitals[\"thresholds\"] as Record<string, unknown> | undefined;\n if (!t || typeof t !== \"object\") return undefined;\n const toN = (v: unknown): number | undefined => {\n if (v === undefined || v === null) return undefined;\n const n = Number(v);\n return isNaN(n) ? undefined : n;\n };\n return {\n crashRate: toN(t[\"crashRate\"]),\n anrRate: toN(t[\"anrRate\"]),\n slowStartRate: toN(t[\"slowStartRate\"]),\n slowRenderingRate: toN(t[\"slowRenderingRate\"]),\n };\n}\n\nfunction resolvePackages(\n program: Command,\n config: ResolvedConfig,\n allApps?: boolean,\n): string[] {\n const rootApp = (program.opts()[\"app\"] || config.app) as string | undefined;\n if (!allApps) return rootApp ? [rootApp] : [];\n\n const seen = new Set<string>();\n const result: string[] = [];\n if (rootApp) {\n seen.add(rootApp);\n result.push(rootApp);\n }\n for (const profile of Object.values(config.profiles ?? {})) {\n if (profile.app && !seen.has(profile.app)) {\n seen.add(profile.app);\n result.push(profile.app);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\n\nfunction colorizeTrackStatus(s: string): string {\n switch (s) {\n case \"inProgress\":\n case \"completed\":\n return green(s);\n case \"halted\":\n return red(s);\n case \"draft\":\n return dim(s);\n default:\n return gray(s);\n }\n}\n\nfunction applyStatusColors(status: AppStatus): AppStatus {\n if (!status.releases || status.releases.length === 0) return status;\n return {\n ...status,\n releases: status.releases.map((r) => ({\n ...r,\n status: colorizeTrackStatus(r.status),\n })),\n };\n}\n\nfunction makeRenderer(\n format: string,\n displayFormat: string,\n includeDiff?: { prevStatus: AppStatus | null; sinceLast?: boolean },\n): (status: AppStatus) => string {\n return (status: AppStatus): string => {\n if (format === \"json\") {\n const sectionSet = new Set(status.sections);\n const filtered: Record<string, unknown> = {\n packageName: status.packageName,\n fetchedAt: status.fetchedAt,\n cached: status.cached,\n sections: status.sections,\n };\n if (sectionSet.has(\"releases\")) filtered[\"releases\"] = status.releases;\n if (sectionSet.has(\"vitals\")) filtered[\"vitals\"] = status.vitals;\n if (sectionSet.has(\"reviews\")) filtered[\"reviews\"] = status.reviews;\n\n // Embed diff in JSON output when --since-last is used\n if (includeDiff?.sinceLast && includeDiff.prevStatus) {\n filtered[\"diff\"] = computeStatusDiff(includeDiff.prevStatus, status);\n filtered[\"diffSince\"] = includeDiff.prevStatus.fetchedAt;\n }\n\n return formatOutput(filtered, \"json\");\n }\n const colorized = applyStatusColors(status);\n if (displayFormat === \"summary\") return formatStatusSummary(colorized);\n return formatStatusTable(colorized);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Unified app health snapshot: releases, vitals, and reviews\")\n .option(\"--days <n>\", \"Vitals window in days\", (v) => parseInt(v, 10), 7)\n .option(\"--review-days <n>\", \"Reviews window in days\", (v) => parseInt(v, 10), 30)\n .option(\"--cached\", \"Use last fetched data, skip API calls\")\n .option(\"--refresh\", \"Force live fetch, ignore cache TTL\")\n .option(\"--ttl <seconds>\", \"Cache TTL in seconds\", (v) => parseInt(v, 10), 3600)\n .option(\"--format <fmt>\", \"Display style: table (default) or summary\", \"table\")\n .option(\n \"--sections <list>\",\n \"Comma-separated sections: releases,vitals,reviews\",\n \"releases,vitals,reviews\",\n )\n .option(\"--watch [seconds]\", \"Poll every N seconds (min 10, default 30)\")\n .option(\"--since-last\", \"Show diff from last cached status\")\n .option(\"--all-apps\", `Run status for all configured app profiles (max ${MAX_ALL_APPS})`)\n .option(\"--notify\", \"Send desktop notification on threshold breach or clear\")\n .option(\"--threshold <overrides>\", \"Override vitals thresholds: crashes=1.5,anr=0.5 (percent)\")\n .action(\n async (opts: {\n days: number;\n reviewDays: number;\n cached?: boolean;\n refresh?: boolean;\n ttl: number;\n format: string;\n sections: string;\n watch?: string | boolean;\n sinceLast?: boolean;\n allApps?: boolean;\n threshold?: string;\n notify?: boolean;\n }) => {\n if (!VALID_FORMATS.has(opts.format)) {\n usageError(\n `Unknown format \"${opts.format}\"`,\n \"Valid: table, summary\",\n );\n }\n\n const sections = parseSections(opts.sections);\n\n if (!Number.isFinite(opts.days) || opts.days < 1) {\n usageError(`--days must be a positive integer (got: ${opts.days})`);\n }\n\n if (!Number.isFinite(opts.reviewDays) || opts.reviewDays < 1) {\n usageError(`--review-days must be a positive integer (got: ${opts.reviewDays})`);\n }\n\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n let vitalThresholds: RunCtx[\"vitalThresholds\"] = resolveVitalThresholds(config);\n if (opts.threshold) {\n const overrides = parseThresholdOverrides(opts.threshold);\n vitalThresholds = { ...vitalThresholds, ...overrides } as RunCtx[\"vitalThresholds\"];\n }\n const watchInterval = resolveWatchInterval(opts.watch);\n const packages = resolvePackages(program, config, opts.allApps);\n\n if (packages.length === 0) {\n usageError(\n \"No package name\",\n \"Use --app <package> or gpc config set app <package>\",\n );\n }\n if (opts.allApps && packages.length > MAX_ALL_APPS) {\n usageError(\n `--all-apps found ${packages.length} apps (max ${MAX_ALL_APPS})`,\n \"Use --app to target a specific app\",\n );\n }\n\n const authConfig = config.auth;\n\n const makeClients = async () => {\n const auth = await resolveAuth({\n serviceAccountPath: authConfig?.serviceAccount,\n });\n return {\n client: createApiClient({ auth }),\n reporting: createReportingClient({ auth }),\n };\n };\n\n let anyBreach = false;\n\n for (const packageName of packages) {\n if (packages.length > 1) {\n const label = statusHasBreach\n ? `\\n=== ${packageName} ===`\n : `\\n=== ${packageName} ===`;\n console.log(label);\n }\n\n try {\n const breach = await runStatusForPackage({\n packageName,\n opts,\n sections,\n format,\n vitalThresholds,\n watchInterval,\n makeClients,\n });\n if (breach) anyBreach = true;\n } catch (error) {\n if (packages.length === 1) throw error;\n // For --all-apps, print error and continue to next app\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n if (anyBreach) process.exitCode = 6;\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// Per-package status runner\n// ---------------------------------------------------------------------------\n\ninterface RunCtx {\n packageName: string;\n opts: {\n days: number;\n reviewDays: number;\n cached?: boolean;\n refresh?: boolean;\n ttl: number;\n format: string;\n sinceLast?: boolean;\n notify?: boolean;\n };\n sections: string[];\n format: string;\n vitalThresholds:\n | {\n crashRate?: number;\n anrRate?: number;\n slowStartRate?: number;\n slowRenderingRate?: number;\n }\n | undefined;\n watchInterval: number | null;\n makeClients: () => Promise<{\n client: ReturnType<typeof createApiClient>;\n reporting: ReturnType<typeof createReportingClient>;\n }>;\n}\n\n/** Override sections on a cached AppStatus with the user-requested sections for display. */\nfunction applyDisplaySections(status: AppStatus, requestedSections: string[]): AppStatus {\n const requested = new Set(requestedSections);\n const filtered = status.sections.filter((s) => requested.has(s));\n if (filtered.length === status.sections.length) return status;\n return { ...status, sections: filtered };\n}\n\n/** Returns true if a breach was detected. */\nasync function runStatusForPackage(ctx: RunCtx): Promise<boolean> {\n const { packageName, opts, sections, vitalThresholds, watchInterval } = ctx;\n\n const fetchLive = async (): Promise<AppStatus> => {\n const { client, reporting } = await ctx.makeClients();\n return getAppStatus(client, reporting, packageName, {\n days: opts.days,\n reviewDays: opts.reviewDays,\n sections,\n vitalThresholds: vitalThresholds ?? undefined,\n });\n };\n\n const save = (status: AppStatus) => saveStatusCache(packageName, status, opts.ttl);\n\n // Capture prev status early (for --since-last)\n const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;\n\n // Build the renderer — for JSON mode with --since-last, diff is embedded\n const render = makeRenderer(ctx.format, opts.format, {\n prevStatus,\n sinceLast: opts.sinceLast,\n });\n\n if (watchInterval !== null && opts.sinceLast) {\n process.stderr.write(\n \"Warning: --since-last is not supported with --watch and will be ignored.\\n\",\n );\n }\n\n // --watch: hand off entirely to runWatchLoop\n if (watchInterval !== null) {\n await runWatchLoop({ intervalSeconds: watchInterval, render, fetch: fetchLive, save });\n return false;\n }\n\n // --cached: serve from cache only\n if (opts.cached) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (!cached) {\n throw Object.assign(\n new Error(\"No cached status found\"),\n {\n code: \"STATUS_NO_CACHE\",\n exitCode: 2,\n suggestion: \"Run without --cached to fetch live data\",\n },\n );\n }\n const display = applyDisplaySections(cached, sections);\n printWithDiff(display, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n\n // Try cache (unless --refresh)\n if (!opts.refresh) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (cached) {\n const display = applyDisplaySections(cached, sections);\n if (ctx.format !== \"json\" && display.sections.length < cached.sections.length) {\n process.stderr.write(\n `Tip: cache contains all sections. Add --refresh to fetch only the requested sections and reduce API calls.\\n`,\n );\n }\n printWithDiff(display, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n }\n\n // Live fetch (with spinner in TTY mode)\n const spinner = createSpinner(\"Fetching app status...\");\n if (ctx.format !== \"json\") spinner.start();\n let status: AppStatus;\n try {\n status = await fetchLive();\n } catch (err) {\n spinner.fail(\"Failed to fetch app status\");\n throw err;\n }\n spinner.stop(\"Done\");\n await save(status);\n\n printWithDiff(status, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, status, opts.notify);\n return statusHasBreach(status);\n}\n\n// ---------------------------------------------------------------------------\n// Output helpers\n// ---------------------------------------------------------------------------\n\nfunction printWithDiff(\n status: AppStatus,\n prevStatus: AppStatus | null,\n sinceLast: boolean | undefined,\n render: (s: AppStatus) => string,\n format: string,\n): void {\n console.log(render(status));\n\n // In JSON mode, diff is embedded by makeRenderer — no extra text output\n if (format === \"json\") return;\n\n if (sinceLast && prevStatus) {\n const since = relativeTime(prevStatus.fetchedAt);\n console.log(\"\");\n console.log(formatStatusDiff(computeStatusDiff(prevStatus, status), since));\n } else if (sinceLast && !prevStatus) {\n console.log(\"\\n(No prior cached status to diff against)\");\n }\n}\n\nasync function handleNotify(\n packageName: string,\n status: AppStatus,\n notify: boolean | undefined,\n): Promise<void> {\n if (!notify) return;\n const breaching = statusHasBreach(status);\n const changed = await trackBreachState(packageName, breaching);\n if (changed) {\n const title = breaching ? \"GPC Alert\" : \"GPC Status\";\n const body = breaching\n ? `${packageName}: vitals threshold breached`\n : `${packageName}: vitals back to normal`;\n sendNotification(title, body);\n }\n}\n"],"mappings":";;;;;;;;;;;;AACA,SAAS,kBAAkB;AAE3B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB,6BAA6B;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASP,IAAM,iBAAiB,oBAAI,IAAI,CAAC,YAAY,UAAU,SAAS,CAAC;AAChE,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,SAAS,CAAC;AAClD,IAAM,eAAe;AAErB,IAAM,iBAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,OAAO;AAAA,EACP,KAAK;AAAA,EACL,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,kBAAkB;AACpB;AAMA,SAAS,WAAW,SAAiB,YAA4B;AAC/D,QAAM,OAAO,OAAO,IAAI,MAAM,OAAO,GAAG;AAAA,IACtC,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AACH;AAMO,SAAS,cAAc,KAAuB;AACnD,QAAM,WAAW,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC;AACjE,aAAW,KAAK,UAAU;AACxB,QAAI,CAAC,eAAe,IAAI,CAAC,GAAG;AAC1B;AAAA,QACE,oBAAoB,CAAC;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,wBAAwB,KAAqC;AAC3E,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,IAAI,MAAM,GAAG,GAAG;AACjC,UAAM,CAAC,KAAK,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACtD,QAAI,CAAC,OAAO,CAAC,IAAK;AAClB,UAAM,SAAS,eAAe,IAAI,YAAY,CAAC;AAC/C,QAAI,CAAC,QAAQ;AACX;AAAA,QACE,sBAAsB,GAAG;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,WAAW,GAAG;AACxB,QAAI,MAAM,CAAC,KAAK,IAAI,GAAG;AACrB;AAAA,QACE,4BAA4B,GAAG,SAAS,GAAG;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AACA,WAAO,MAAM,IAAI,IAAI;AAAA,EACvB;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB,OAAoD;AACvF,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,UAAU,QAAQ,UAAU,GAAI,QAAO;AAC3C,QAAM,IAAI,SAAS,OAAO,KAAK,GAAG,EAAE;AACpC,SAAO,MAAM,CAAC,IAAI,KAAK;AACzB;AAEA,SAAS,uBAAuB,QAAwB;AACtD,QAAM,MAAM;AACZ,QAAM,SAAS,IAAI,QAAQ;AAC3B,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,IAAI,OAAO,YAAY;AAC7B,MAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,QAAM,MAAM,CAAC,MAAmC;AAC9C,QAAI,MAAM,UAAa,MAAM,KAAM,QAAO;AAC1C,UAAM,IAAI,OAAO,CAAC;AAClB,WAAO,MAAM,CAAC,IAAI,SAAY;AAAA,EAChC;AACA,SAAO;AAAA,IACL,WAAW,IAAI,EAAE,WAAW,CAAC;AAAA,IAC7B,SAAS,IAAI,EAAE,SAAS,CAAC;AAAA,IACzB,eAAe,IAAI,EAAE,eAAe,CAAC;AAAA,IACrC,mBAAmB,IAAI,EAAE,mBAAmB,CAAC;AAAA,EAC/C;AACF;AAEA,SAAS,gBACP,SACA,QACA,SACU;AACV,QAAM,UAAW,QAAQ,KAAK,EAAE,KAAK,KAAK,OAAO;AACjD,MAAI,CAAC,QAAS,QAAO,UAAU,CAAC,OAAO,IAAI,CAAC;AAE5C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAmB,CAAC;AAC1B,MAAI,SAAS;AACX,SAAK,IAAI,OAAO;AAChB,WAAO,KAAK,OAAO;AAAA,EACrB;AACA,aAAW,WAAW,OAAO,OAAO,OAAO,YAAY,CAAC,CAAC,GAAG;AAC1D,QAAI,QAAQ,OAAO,CAAC,KAAK,IAAI,QAAQ,GAAG,GAAG;AACzC,WAAK,IAAI,QAAQ,GAAG;AACpB,aAAO,KAAK,QAAQ,GAAG;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,oBAAoB,GAAmB;AAC9C,UAAQ,GAAG;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO,MAAM,CAAC;AAAA,IAChB,KAAK;AACH,aAAO,IAAI,CAAC;AAAA,IACd,KAAK;AACH,aAAO,IAAI,CAAC;AAAA,IACd;AACE,aAAO,KAAK,CAAC;AAAA,EACjB;AACF;AAEA,SAAS,kBAAkB,QAA8B;AACvD,MAAI,CAAC,OAAO,YAAY,OAAO,SAAS,WAAW,EAAG,QAAO;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,OAAO,SAAS,IAAI,CAAC,OAAO;AAAA,MACpC,GAAG;AAAA,MACH,QAAQ,oBAAoB,EAAE,MAAM;AAAA,IACtC,EAAE;AAAA,EACJ;AACF;AAEA,SAAS,aACP,QACA,eACA,aAC+B;AAC/B,SAAO,CAAC,WAA8B;AACpC,QAAI,WAAW,QAAQ;AACrB,YAAM,aAAa,IAAI,IAAI,OAAO,QAAQ;AAC1C,YAAM,WAAoC;AAAA,QACxC,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,QAClB,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,MACnB;AACA,UAAI,WAAW,IAAI,UAAU,EAAG,UAAS,UAAU,IAAI,OAAO;AAC9D,UAAI,WAAW,IAAI,QAAQ,EAAG,UAAS,QAAQ,IAAI,OAAO;AAC1D,UAAI,WAAW,IAAI,SAAS,EAAG,UAAS,SAAS,IAAI,OAAO;AAG5D,UAAI,aAAa,aAAa,YAAY,YAAY;AACpD,iBAAS,MAAM,IAAI,kBAAkB,YAAY,YAAY,MAAM;AACnE,iBAAS,WAAW,IAAI,YAAY,WAAW;AAAA,MACjD;AAEA,aAAO,aAAa,UAAU,MAAM;AAAA,IACtC;AACA,UAAM,YAAY,kBAAkB,MAAM;AAC1C,QAAI,kBAAkB,UAAW,QAAO,oBAAoB,SAAS;AACrE,WAAO,kBAAkB,SAAS;AAAA,EACpC;AACF;AAMO,SAAS,sBAAsB,SAAwB;AAC5D,UACG,QAAQ,QAAQ,EAChB,YAAY,4DAA4D,EACxE,OAAO,cAAc,yBAAyB,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EACvE,OAAO,qBAAqB,0BAA0B,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,EAChF,OAAO,YAAY,uCAAuC,EAC1D,OAAO,aAAa,oCAAoC,EACxD,OAAO,mBAAmB,wBAAwB,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,EAC9E,OAAO,kBAAkB,6CAA6C,OAAO,EAC7E;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACC,OAAO,qBAAqB,2CAA2C,EACvE,OAAO,gBAAgB,mCAAmC,EAC1D,OAAO,cAAc,mDAAmD,YAAY,GAAG,EACvF,OAAO,YAAY,wDAAwD,EAC3E,OAAO,2BAA2B,2DAA2D,EAC7F;AAAA,IACC,OAAO,SAaD;AACJ,UAAI,CAAC,cAAc,IAAI,KAAK,MAAM,GAAG;AACnC;AAAA,UACE,mBAAmB,KAAK,MAAM;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAEA,YAAM,WAAW,cAAc,KAAK,QAAQ;AAE5C,UAAI,CAAC,OAAO,SAAS,KAAK,IAAI,KAAK,KAAK,OAAO,GAAG;AAChD,mBAAW,2CAA2C,KAAK,IAAI,GAAG;AAAA,MACpE;AAEA,UAAI,CAAC,OAAO,SAAS,KAAK,UAAU,KAAK,KAAK,aAAa,GAAG;AAC5D,mBAAW,kDAAkD,KAAK,UAAU,GAAG;AAAA,MACjF;AAEA,YAAM,SAAS,MAAM,WAAW;AAChC,YAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAI,kBAA6C,uBAAuB,MAAM;AAC9E,UAAI,KAAK,WAAW;AAClB,cAAM,YAAY,wBAAwB,KAAK,SAAS;AACxD,0BAAkB,EAAE,GAAG,iBAAiB,GAAG,UAAU;AAAA,MACvD;AACA,YAAM,gBAAgB,qBAAqB,KAAK,KAAK;AACrD,YAAM,WAAW,gBAAgB,SAAS,QAAQ,KAAK,OAAO;AAE9D,UAAI,SAAS,WAAW,GAAG;AACzB;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,UAAI,KAAK,WAAW,SAAS,SAAS,cAAc;AAClD;AAAA,UACE,oBAAoB,SAAS,MAAM,cAAc,YAAY;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAAa,OAAO;AAE1B,YAAM,cAAc,YAAY;AAC9B,cAAM,OAAO,MAAM,YAAY;AAAA,UAC7B,oBAAoB,YAAY;AAAA,QAClC,CAAC;AACD,eAAO;AAAA,UACL,QAAQ,gBAAgB,EAAE,KAAK,CAAC;AAAA,UAChC,WAAW,sBAAsB,EAAE,KAAK,CAAC;AAAA,QAC3C;AAAA,MACF;AAEA,UAAI,YAAY;AAEhB,iBAAW,eAAe,UAAU;AAClC,YAAI,SAAS,SAAS,GAAG;AACvB,gBAAM,QAAQ,kBACV;AAAA,MAAS,WAAW,SACpB;AAAA,MAAS,WAAW;AACxB,kBAAQ,IAAI,KAAK;AAAA,QACnB;AAEA,YAAI;AACF,gBAAM,SAAS,MAAM,oBAAoB;AAAA,YACvC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AACD,cAAI,OAAQ,aAAY;AAAA,QAC1B,SAAS,OAAO;AACd,cAAI,SAAS,WAAW,EAAG,OAAM;AAEjC,kBAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,QAClF;AAAA,MACF;AAEA,UAAI,UAAW,SAAQ,WAAW;AAAA,IACpC;AAAA,EACF;AACJ;AAoCA,SAAS,qBAAqB,QAAmB,mBAAwC;AACvF,QAAM,YAAY,IAAI,IAAI,iBAAiB;AAC3C,QAAM,WAAW,OAAO,SAAS,OAAO,CAAC,MAAM,UAAU,IAAI,CAAC,CAAC;AAC/D,MAAI,SAAS,WAAW,OAAO,SAAS,OAAQ,QAAO;AACvD,SAAO,EAAE,GAAG,QAAQ,UAAU,SAAS;AACzC;AAGA,eAAe,oBAAoB,KAA+B;AAChE,QAAM,EAAE,aAAa,MAAM,UAAU,iBAAiB,cAAc,IAAI;AAExE,QAAM,YAAY,YAAgC;AAChD,UAAM,EAAE,QAAQ,UAAU,IAAI,MAAM,IAAI,YAAY;AACpD,WAAO,aAAa,QAAQ,WAAW,aAAa;AAAA,MAClD,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,iBAAiB,mBAAmB;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CAACA,YAAsB,gBAAgB,aAAaA,SAAQ,KAAK,GAAG;AAGjF,QAAM,aAAa,KAAK,YAAY,MAAM,gBAAgB,aAAa,QAAQ,IAAI;AAGnF,QAAM,SAAS,aAAa,IAAI,QAAQ,KAAK,QAAQ;AAAA,IACnD;AAAA,IACA,WAAW,KAAK;AAAA,EAClB,CAAC;AAED,MAAI,kBAAkB,QAAQ,KAAK,WAAW;AAC5C,YAAQ,OAAO;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAGA,MAAI,kBAAkB,MAAM;AAC1B,UAAM,aAAa,EAAE,iBAAiB,eAAe,QAAQ,OAAO,WAAW,KAAK,CAAC;AACrF,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,QAAQ;AACf,UAAM,SAAS,MAAM,gBAAgB,aAAa,KAAK,GAAG;AAC1D,QAAI,CAAC,QAAQ;AACX,YAAM,OAAO;AAAA,QACX,IAAI,MAAM,wBAAwB;AAAA,QAClC;AAAA,UACE,MAAM;AAAA,UACN,UAAU;AAAA,UACV,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAU,qBAAqB,QAAQ,QAAQ;AACrD,kBAAc,SAAS,YAAY,KAAK,WAAW,QAAQ,IAAI,MAAM;AACrE,UAAM,aAAa,aAAa,QAAQ,KAAK,MAAM;AACnD,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAGA,MAAI,CAAC,KAAK,SAAS;AACjB,UAAM,SAAS,MAAM,gBAAgB,aAAa,KAAK,GAAG;AAC1D,QAAI,QAAQ;AACV,YAAM,UAAU,qBAAqB,QAAQ,QAAQ;AACrD,UAAI,IAAI,WAAW,UAAU,QAAQ,SAAS,SAAS,OAAO,SAAS,QAAQ;AAC7E,gBAAQ,OAAO;AAAA,UACb;AAAA;AAAA,QACF;AAAA,MACF;AACA,oBAAc,SAAS,YAAY,KAAK,WAAW,QAAQ,IAAI,MAAM;AACrE,YAAM,aAAa,aAAa,QAAQ,KAAK,MAAM;AACnD,aAAO,gBAAgB,MAAM;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,UAAU,cAAc,wBAAwB;AACtD,MAAI,IAAI,WAAW,OAAQ,SAAQ,MAAM;AACzC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,UAAU;AAAA,EAC3B,SAAS,KAAK;AACZ,YAAQ,KAAK,4BAA4B;AACzC,UAAM;AAAA,EACR;AACA,UAAQ,KAAK,MAAM;AACnB,QAAM,KAAK,MAAM;AAEjB,gBAAc,QAAQ,YAAY,KAAK,WAAW,QAAQ,IAAI,MAAM;AACpE,QAAM,aAAa,aAAa,QAAQ,KAAK,MAAM;AACnD,SAAO,gBAAgB,MAAM;AAC/B;AAMA,SAAS,cACP,QACA,YACA,WACA,QACA,QACM;AACN,UAAQ,IAAI,OAAO,MAAM,CAAC;AAG1B,MAAI,WAAW,OAAQ;AAEvB,MAAI,aAAa,YAAY;AAC3B,UAAM,QAAQ,aAAa,WAAW,SAAS;AAC/C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,iBAAiB,kBAAkB,YAAY,MAAM,GAAG,KAAK,CAAC;AAAA,EAC5E,WAAW,aAAa,CAAC,YAAY;AACnC,YAAQ,IAAI,4CAA4C;AAAA,EAC1D;AACF;AAEA,eAAe,aACb,aACA,QACA,QACe;AACf,MAAI,CAAC,OAAQ;AACb,QAAM,YAAY,gBAAgB,MAAM;AACxC,QAAM,UAAU,MAAM,iBAAiB,aAAa,SAAS;AAC7D,MAAI,SAAS;AACX,UAAM,QAAQ,YAAY,cAAc;AACxC,UAAM,OAAO,YACT,GAAG,WAAW,gCACd,GAAG,WAAW;AAClB,qBAAiB,OAAO,IAAI;AAAA,EAC9B;AACF;","names":["status"]}
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readJsonFile
4
- } from "./chunk-FWKYRLKY.js";
4
+ } from "./chunk-SLNJEAMK.js";
5
5
  import {
6
6
  getClient,
7
7
  resolvePackageName
8
- } from "./chunk-AA577WVQ.js";
8
+ } from "./chunk-NQH4G7BI.js";
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-ELXAK7GI.js";
16
16
  import {
17
17
  requireConfirm
18
- } from "./chunk-NV75I5VP.js";
18
+ } from "./chunk-YFUBD2XB.js";
19
19
 
20
20
  // src/commands/subscriptions.ts
21
21
  import { Option } from "commander";
@@ -49,35 +49,30 @@ function registerSubscriptionsCommands(program) {
49
49
  const packageName = resolvePackageName(program.opts()["app"], config);
50
50
  const client = await getClient(config);
51
51
  const format = getOutputFormat(program, config);
52
- try {
53
- const result = await listSubscriptions(client, packageName, {
54
- pageSize: options.pageSize,
55
- pageToken: options.pageToken,
56
- limit: options.limit,
57
- nextPage: options.nextPage
58
- });
59
- if (options.sort) {
60
- result.subscriptions = sortResults(result.subscriptions, options.sort);
61
- }
62
- const subs2 = result.subscriptions || [];
63
- if (format !== "json") {
64
- if (subs2.length === 0) {
65
- console.log("No subscriptions found.");
66
- return;
67
- }
68
- const summary = subs2.map((s) => ({
69
- productId: s.productId,
70
- basePlans: s.basePlans?.length || 0,
71
- listings: s.listings ? Object.keys(s.listings).length : 0,
72
- firstBasePlanState: s.basePlans?.[0]?.state || "-"
73
- }));
74
- console.log(formatOutput(summary, format));
75
- } else {
76
- console.log(formatOutput(subs2.length === 0 ? { subscriptions: [] } : result, format));
52
+ const result = await listSubscriptions(client, packageName, {
53
+ pageSize: options.pageSize,
54
+ pageToken: options.pageToken,
55
+ limit: options.limit,
56
+ nextPage: options.nextPage
57
+ });
58
+ if (options.sort) {
59
+ result.subscriptions = sortResults(result.subscriptions, options.sort);
60
+ }
61
+ const subs2 = result.subscriptions || [];
62
+ if (format !== "json") {
63
+ if (subs2.length === 0) {
64
+ console.log("No subscriptions found.");
65
+ return;
77
66
  }
78
- } catch (error) {
79
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
80
- process.exit(4);
67
+ const summary = subs2.map((s) => ({
68
+ productId: s.productId,
69
+ basePlans: s.basePlans?.length || 0,
70
+ listings: s.listings ? Object.keys(s.listings).length : 0,
71
+ firstBasePlanState: s.basePlans?.[0]?.state || "-"
72
+ }));
73
+ console.log(formatOutput(summary, format));
74
+ } else {
75
+ console.log(formatOutput(subs2.length === 0 ? { subscriptions: [] } : result, format));
81
76
  }
82
77
  });
83
78
  subs.command("get <product-id>").description("Get a subscription").action(async (productId) => {
@@ -85,29 +80,24 @@ function registerSubscriptionsCommands(program) {
85
80
  const packageName = resolvePackageName(program.opts()["app"], config);
86
81
  const client = await getClient(config);
87
82
  const format = getOutputFormat(program, config);
88
- try {
89
- const result = await getSubscription(client, packageName, productId);
90
- if (format !== "json") {
91
- const s = result;
92
- const basePlans2 = s["basePlans"];
93
- const listings = s["listings"];
94
- const listingLanguages = listings ? Array.isArray(listings) ? listings.map((l) => l["languageCode"] || l["language"] || "?").join(", ") : Object.keys(listings).join(", ") : "-";
95
- const listingCount = listings ? Array.isArray(listings) ? listings.length : Object.keys(listings).length : 0;
96
- const summary = {
97
- productId: s["productId"],
98
- basePlans: basePlans2?.length || 0,
99
- basePlanIds: basePlans2?.map((bp) => bp["basePlanId"]).join(", ") || "-",
100
- listings: listingCount,
101
- listingLanguages,
102
- taxCategory: s["taxAndComplianceSettings"]?.["taxRateInfoByRegionCode"] ? "configured" : "-"
103
- };
104
- console.log(formatOutput(summary, format));
105
- } else {
106
- console.log(formatOutput(result, format));
107
- }
108
- } catch (error) {
109
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
110
- process.exit(4);
83
+ const result = await getSubscription(client, packageName, productId);
84
+ if (format !== "json") {
85
+ const s = result;
86
+ const basePlans2 = s["basePlans"];
87
+ const listings = s["listings"];
88
+ const listingLanguages = listings ? Array.isArray(listings) ? listings.map((l) => l["languageCode"] || l["language"] || "?").join(", ") : Object.keys(listings).join(", ") : "-";
89
+ const listingCount = listings ? Array.isArray(listings) ? listings.length : Object.keys(listings).length : 0;
90
+ const summary = {
91
+ productId: s["productId"],
92
+ basePlans: basePlans2?.length || 0,
93
+ basePlanIds: basePlans2?.map((bp) => bp["basePlanId"]).join(", ") || "-",
94
+ listings: listingCount,
95
+ listingLanguages,
96
+ taxCategory: s["taxAndComplianceSettings"]?.["taxRateInfoByRegionCode"] ? "configured" : "-"
97
+ };
98
+ console.log(formatOutput(summary, format));
99
+ } else {
100
+ console.log(formatOutput(result, format));
111
101
  }
112
102
  });
113
103
  subs.command("create").description("Create a subscription from JSON file").requiredOption("--file <path>", "JSON file with subscription data").option("--activate", "Activate all base plans after creation").action(async (options) => {
@@ -128,24 +118,19 @@ function registerSubscriptionsCommands(program) {
128
118
  return;
129
119
  }
130
120
  const client = await getClient(config);
131
- try {
132
- const data = await readJsonFile(options.file);
133
- const result = await createSubscription(client, packageName, data);
134
- if (options.activate && result.basePlans) {
135
- for (const bp of result.basePlans) {
136
- if (bp.state === "DRAFT") {
137
- await activateBasePlan(client, packageName, result.productId, bp.basePlanId);
138
- console.error(`Activated base plan: ${bp.basePlanId}`);
139
- }
121
+ const data = await readJsonFile(options.file);
122
+ const result = await createSubscription(client, packageName, data);
123
+ if (options.activate && result.basePlans) {
124
+ for (const bp of result.basePlans) {
125
+ if (bp.state === "DRAFT") {
126
+ await activateBasePlan(client, packageName, result.productId, bp.basePlanId);
127
+ console.error(`Activated base plan: ${bp.basePlanId}`);
140
128
  }
141
- const updated = await getSubscription(client, packageName, result.productId);
142
- console.log(formatOutput(updated, format));
143
- } else {
144
- console.log(formatOutput(result, format));
145
129
  }
146
- } catch (error) {
147
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
148
- process.exit(4);
130
+ const updated = await getSubscription(client, packageName, result.productId);
131
+ console.log(formatOutput(updated, format));
132
+ } else {
133
+ console.log(formatOutput(result, format));
149
134
  }
150
135
  });
151
136
  subs.command("update <product-id>").description("Update a subscription from JSON file").requiredOption("--file <path>", "JSON file with subscription data").option("--update-mask <fields>", "Comma-separated field mask").action(async (productId, options) => {
@@ -166,20 +151,15 @@ function registerSubscriptionsCommands(program) {
166
151
  return;
167
152
  }
168
153
  const client = await getClient(config);
169
- try {
170
- const data = await readJsonFile(options.file);
171
- const result = await updateSubscription(
172
- client,
173
- packageName,
174
- productId,
175
- data,
176
- options.updateMask
177
- );
178
- console.log(formatOutput(result, format));
179
- } catch (error) {
180
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
181
- process.exit(4);
182
- }
154
+ const data = await readJsonFile(options.file);
155
+ const result = await updateSubscription(
156
+ client,
157
+ packageName,
158
+ productId,
159
+ data,
160
+ options.updateMask
161
+ );
162
+ console.log(formatOutput(result, format));
183
163
  });
184
164
  subs.command("delete <product-id>").description("Delete a subscription").action(async (productId) => {
185
165
  const config = await loadConfig();
@@ -199,13 +179,8 @@ function registerSubscriptionsCommands(program) {
199
179
  return;
200
180
  }
201
181
  const client = await getClient(config);
202
- try {
203
- await deleteSubscription(client, packageName, productId);
204
- console.log(`Subscription ${productId} deleted.`);
205
- } catch (error) {
206
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
207
- process.exit(4);
208
- }
182
+ await deleteSubscription(client, packageName, productId);
183
+ console.log(`Subscription ${productId} deleted.`);
209
184
  });
210
185
  const basePlans = subs.command("base-plans").description("Manage base plans");
211
186
  basePlans.command("activate <product-id> <base-plan-id>").description("Activate a base plan").action(async (productId, basePlanId) => {
@@ -225,13 +200,8 @@ function registerSubscriptionsCommands(program) {
225
200
  return;
226
201
  }
227
202
  const client = await getClient(config);
228
- try {
229
- const result = await activateBasePlan(client, packageName, productId, basePlanId);
230
- console.log(formatOutput(result, format));
231
- } catch (error) {
232
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
233
- process.exit(4);
234
- }
203
+ const result = await activateBasePlan(client, packageName, productId, basePlanId);
204
+ console.log(formatOutput(result, format));
235
205
  });
236
206
  basePlans.command("deactivate <product-id> <base-plan-id>").description("Deactivate a base plan").action(async (productId, basePlanId) => {
237
207
  const config = await loadConfig();
@@ -250,13 +220,8 @@ function registerSubscriptionsCommands(program) {
250
220
  return;
251
221
  }
252
222
  const client = await getClient(config);
253
- try {
254
- const result = await deactivateBasePlan(client, packageName, productId, basePlanId);
255
- console.log(formatOutput(result, format));
256
- } catch (error) {
257
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
258
- process.exit(4);
259
- }
223
+ const result = await deactivateBasePlan(client, packageName, productId, basePlanId);
224
+ console.log(formatOutput(result, format));
260
225
  });
261
226
  basePlans.command("delete <product-id> <base-plan-id>").description("Delete a base plan").action(async (productId, basePlanId) => {
262
227
  const config = await loadConfig();
@@ -279,13 +244,8 @@ function registerSubscriptionsCommands(program) {
279
244
  return;
280
245
  }
281
246
  const client = await getClient(config);
282
- try {
283
- await deleteBasePlan(client, packageName, productId, basePlanId);
284
- console.log(`Base plan ${basePlanId} deleted.`);
285
- } catch (error) {
286
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
287
- process.exit(4);
288
- }
247
+ await deleteBasePlan(client, packageName, productId, basePlanId);
248
+ console.log(`Base plan ${basePlanId} deleted.`);
289
249
  });
290
250
  basePlans.command("migrate-prices <product-id> <base-plan-id>").description("Migrate base plan prices").requiredOption("--file <path>", "JSON file with migration data").action(
291
251
  async (productId, basePlanId, options) => {
@@ -306,20 +266,15 @@ function registerSubscriptionsCommands(program) {
306
266
  return;
307
267
  }
308
268
  const client = await getClient(config);
309
- try {
310
- const data = await readJsonFile(options.file);
311
- const result = await migratePrices(
312
- client,
313
- packageName,
314
- productId,
315
- basePlanId,
316
- data
317
- );
318
- console.log(formatOutput(result, format));
319
- } catch (error) {
320
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
321
- process.exit(4);
322
- }
269
+ const data = await readJsonFile(options.file);
270
+ const result = await migratePrices(
271
+ client,
272
+ packageName,
273
+ productId,
274
+ basePlanId,
275
+ data
276
+ );
277
+ console.log(formatOutput(result, format));
323
278
  }
324
279
  );
325
280
  const offers = subs.command("offers").description("Manage subscription offers");
@@ -328,28 +283,23 @@ function registerSubscriptionsCommands(program) {
328
283
  const packageName = resolvePackageName(program.opts()["app"], config);
329
284
  const client = await getClient(config);
330
285
  const format = getOutputFormat(program, config);
331
- try {
332
- const result = await listOffers(client, packageName, productId, basePlanId);
333
- const offers_list = result["subscriptionOffers"];
334
- if (format !== "json") {
335
- if (!offers_list || offers_list.length === 0) {
336
- console.log("No offers found.");
337
- return;
338
- }
339
- const summary = offers_list.map((o) => ({
340
- offerId: o["offerId"],
341
- basePlanId: o["basePlanId"],
342
- state: o["state"] || "-",
343
- phases: o["phases"]?.length || 0,
344
- regionalConfigs: o["regionalConfigs"]?.length || 0
345
- }));
346
- console.log(formatOutput(summary, format));
347
- } else {
348
- console.log(formatOutput(result, format));
286
+ const result = await listOffers(client, packageName, productId, basePlanId);
287
+ const offers_list = result["subscriptionOffers"];
288
+ if (format !== "json") {
289
+ if (!offers_list || offers_list.length === 0) {
290
+ console.log("No offers found.");
291
+ return;
349
292
  }
350
- } catch (error) {
351
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
352
- process.exit(4);
293
+ const summary = offers_list.map((o) => ({
294
+ offerId: o["offerId"],
295
+ basePlanId: o["basePlanId"],
296
+ state: o["state"] || "-",
297
+ phases: o["phases"]?.length || 0,
298
+ regionalConfigs: o["regionalConfigs"]?.length || 0
299
+ }));
300
+ console.log(formatOutput(summary, format));
301
+ } else {
302
+ console.log(formatOutput(result, format));
353
303
  }
354
304
  });
355
305
  offers.command("get <product-id> <base-plan-id> <offer-id>").description("Get an offer").action(async (productId, basePlanId, offerId) => {
@@ -357,13 +307,8 @@ function registerSubscriptionsCommands(program) {
357
307
  const packageName = resolvePackageName(program.opts()["app"], config);
358
308
  const client = await getClient(config);
359
309
  const format = getOutputFormat(program, config);
360
- try {
361
- const result = await getOffer(client, packageName, productId, basePlanId, offerId);
362
- console.log(formatOutput(result, format));
363
- } catch (error) {
364
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
365
- process.exit(4);
366
- }
310
+ const result = await getOffer(client, packageName, productId, basePlanId, offerId);
311
+ console.log(formatOutput(result, format));
367
312
  });
368
313
  offers.command("create <product-id> <base-plan-id>").description("Create an offer from JSON file").requiredOption("--file <path>", "JSON file with offer data").action(
369
314
  async (productId, basePlanId, options) => {
@@ -384,14 +329,9 @@ function registerSubscriptionsCommands(program) {
384
329
  return;
385
330
  }
386
331
  const client = await getClient(config);
387
- try {
388
- const data = await readJsonFile(options.file);
389
- const result = await createOffer(client, packageName, productId, basePlanId, data);
390
- console.log(formatOutput(result, format));
391
- } catch (error) {
392
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
393
- process.exit(4);
394
- }
332
+ const data = await readJsonFile(options.file);
333
+ const result = await createOffer(client, packageName, productId, basePlanId, data);
334
+ console.log(formatOutput(result, format));
395
335
  }
396
336
  );
397
337
  offers.command("update <product-id> <base-plan-id> <offer-id>").description("Update an offer from JSON file").requiredOption("--file <path>", "JSON file with offer data").option("--update-mask <fields>", "Comma-separated field mask").action(
@@ -413,22 +353,17 @@ function registerSubscriptionsCommands(program) {
413
353
  return;
414
354
  }
415
355
  const client = await getClient(config);
416
- try {
417
- const data = await readJsonFile(options.file);
418
- const result = await updateOffer(
419
- client,
420
- packageName,
421
- productId,
422
- basePlanId,
423
- offerId,
424
- data,
425
- options.updateMask
426
- );
427
- console.log(formatOutput(result, format));
428
- } catch (error) {
429
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
430
- process.exit(4);
431
- }
356
+ const data = await readJsonFile(options.file);
357
+ const result = await updateOffer(
358
+ client,
359
+ packageName,
360
+ productId,
361
+ basePlanId,
362
+ offerId,
363
+ data,
364
+ options.updateMask
365
+ );
366
+ console.log(formatOutput(result, format));
432
367
  }
433
368
  );
434
369
  offers.command("delete <product-id> <base-plan-id> <offer-id>").description("Delete an offer").action(async (productId, basePlanId, offerId) => {
@@ -449,13 +384,8 @@ function registerSubscriptionsCommands(program) {
449
384
  return;
450
385
  }
451
386
  const client = await getClient(config);
452
- try {
453
- await deleteOffer(client, packageName, productId, basePlanId, offerId);
454
- console.log(`Offer ${offerId} deleted.`);
455
- } catch (error) {
456
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
457
- process.exit(4);
458
- }
387
+ await deleteOffer(client, packageName, productId, basePlanId, offerId);
388
+ console.log(`Offer ${offerId} deleted.`);
459
389
  });
460
390
  offers.command("activate <product-id> <base-plan-id> <offer-id>").description("Activate an offer").action(async (productId, basePlanId, offerId) => {
461
391
  const config = await loadConfig();
@@ -474,13 +404,8 @@ function registerSubscriptionsCommands(program) {
474
404
  return;
475
405
  }
476
406
  const client = await getClient(config);
477
- try {
478
- const result = await activateOffer(client, packageName, productId, basePlanId, offerId);
479
- console.log(formatOutput(result, format));
480
- } catch (error) {
481
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
482
- process.exit(4);
483
- }
407
+ const result = await activateOffer(client, packageName, productId, basePlanId, offerId);
408
+ console.log(formatOutput(result, format));
484
409
  });
485
410
  offers.command("deactivate <product-id> <base-plan-id> <offer-id>").description("Deactivate an offer").action(async (productId, basePlanId, offerId) => {
486
411
  const config = await loadConfig();
@@ -499,30 +424,20 @@ function registerSubscriptionsCommands(program) {
499
424
  return;
500
425
  }
501
426
  const client = await getClient(config);
502
- try {
503
- const result = await deactivateOffer(client, packageName, productId, basePlanId, offerId);
504
- console.log(formatOutput(result, format));
505
- } catch (error) {
506
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
507
- process.exit(4);
508
- }
427
+ const result = await deactivateOffer(client, packageName, productId, basePlanId, offerId);
428
+ console.log(formatOutput(result, format));
509
429
  });
510
430
  subs.command("diff <product-id>").description("Compare local JSON file against remote subscription").requiredOption("--file <path>", "Local JSON file to compare against remote").action(async (productId, options) => {
511
431
  const config = await loadConfig();
512
432
  const packageName = resolvePackageName(program.opts()["app"], config);
513
433
  const client = await getClient(config);
514
434
  const format = getOutputFormat(program, config);
515
- try {
516
- const localData = await readJsonFile(options.file);
517
- const diffs = await diffSubscription(client, packageName, productId, localData);
518
- if (diffs.length === 0) {
519
- console.log("No differences found.");
520
- } else {
521
- console.log(formatOutput(diffs, format));
522
- }
523
- } catch (error) {
524
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
525
- process.exit(4);
435
+ const localData = await readJsonFile(options.file);
436
+ const diffs = await diffSubscription(client, packageName, productId, localData);
437
+ if (diffs.length === 0) {
438
+ console.log("No differences found.");
439
+ } else {
440
+ console.log(formatOutput(diffs, format));
526
441
  }
527
442
  });
528
443
  subs.command("analytics").description("Subscription catalog analytics: active plans, offer counts, state breakdown").action(async () => {
@@ -530,33 +445,28 @@ function registerSubscriptionsCommands(program) {
530
445
  const packageName = resolvePackageName(program.opts()["app"], config);
531
446
  const client = await getClient(config);
532
447
  const format = getOutputFormat(program, config);
533
- try {
534
- const result = await getSubscriptionAnalytics(client, packageName);
535
- if (format === "json") {
536
- console.log(formatOutput(result, format));
537
- return;
538
- }
539
- console.log(`
448
+ const result = await getSubscriptionAnalytics(client, packageName);
449
+ if (format === "json") {
450
+ console.log(formatOutput(result, format));
451
+ return;
452
+ }
453
+ console.log(`
540
454
  Subscription Analytics \u2014 ${packageName}`);
541
- console.log(`${"\u2500".repeat(50)}`);
542
- console.log(`Total subscriptions: ${result.totalSubscriptions}`);
543
- console.log(`Active subscriptions: ${result.activeCount}`);
544
- console.log(`Active base plans: ${result.activeBasePlans}`);
545
- console.log(`Draft base plans: ${result.trialBasePlans}`);
546
- console.log(`Inactive base plans: ${result.pausedBasePlans}`);
547
- console.log(`Total offers: ${result.offerCount}`);
548
- if (result.byProductId.length > 0) {
549
- console.log(`
455
+ console.log(`${"\u2500".repeat(50)}`);
456
+ console.log(`Total subscriptions: ${result.totalSubscriptions}`);
457
+ console.log(`Active subscriptions: ${result.activeCount}`);
458
+ console.log(`Active base plans: ${result.activeBasePlans}`);
459
+ console.log(`Draft base plans: ${result.trialBasePlans}`);
460
+ console.log(`Inactive base plans: ${result.pausedBasePlans}`);
461
+ console.log(`Total offers: ${result.offerCount}`);
462
+ if (result.byProductId.length > 0) {
463
+ console.log(`
550
464
  By product:`);
551
- console.log(formatOutput(result.byProductId, format));
552
- }
553
- } catch (error) {
554
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
555
- process.exit(4);
465
+ console.log(formatOutput(result.byProductId, format));
556
466
  }
557
467
  });
558
468
  }
559
469
  export {
560
470
  registerSubscriptionsCommands
561
471
  };
562
- //# sourceMappingURL=subscriptions-CI3JH3VQ.js.map
472
+ //# sourceMappingURL=subscriptions-DZP3Y7O7.js.map