@gpc-cli/cli 0.9.78 → 0.9.79

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 (65) hide show
  1. package/dist/{apps-WPUQOQLL.js → apps-WT4FKQFR.js} +2 -2
  2. package/dist/{audit-BDPS5ODN.js → audit-D54TYDFD.js} +2 -2
  3. package/dist/bin.js +2 -2
  4. package/dist/{chunk-Y3QZDAKS.js → chunk-QHBTG2NG.js} +1 -1
  5. package/dist/chunk-QHBTG2NG.js.map +1 -0
  6. package/dist/{chunk-UKVIYCC4.js → chunk-TPSF4BAR.js} +29 -29
  7. package/dist/{config-WF24TCVM.js → config-WSKL2CK6.js} +2 -2
  8. package/dist/{data-safety-UM74SYYE.js → data-safety-PDZTJ32M.js} +2 -2
  9. package/dist/{device-tiers-MNZYMG3Y.js → device-tiers-EKU2TUPW.js} +2 -2
  10. package/dist/{doctor-24TL3GUJ.js → doctor-JGJO52HH.js} +2 -2
  11. package/dist/{enterprise-L7DTIX2O.js → enterprise-NP3EVLCN.js} +2 -2
  12. package/dist/{external-transactions-4YBOHUXS.js → external-transactions-IIF2TSH6.js} +2 -2
  13. package/dist/{feedback-RXYFYMLH.js → feedback-56LWTSEP.js} +2 -2
  14. package/dist/generated/docs-bundle.json +1 -1
  15. package/dist/{grants-32DED5QL.js → grants-Q3FWJYGR.js} +2 -2
  16. package/dist/{iap-EPJ76IAC.js → iap-S5X4O7XF.js} +2 -2
  17. package/dist/index.js +1 -1
  18. package/dist/{internal-sharing-KW6YENDG.js → internal-sharing-BC76IRJG.js} +2 -2
  19. package/dist/{listings-7RTA4MCI.js → listings-ZC7T3IBA.js} +2 -2
  20. package/dist/{one-time-products-OIDBVCFE.js → one-time-products-YSX5VI6I.js} +2 -2
  21. package/dist/{publish-4LBADN6P.js → publish-PGDTANYD.js} +2 -2
  22. package/dist/{purchases-XCBF2PZY.js → purchases-LHGBIZNF.js} +9 -3
  23. package/dist/purchases-LHGBIZNF.js.map +1 -0
  24. package/dist/{recovery-2VJJLAIQ.js → recovery-NSKTIJIN.js} +2 -2
  25. package/dist/{releases-S3ISG5SL.js → releases-IH2ZK3BB.js} +2 -2
  26. package/dist/releases-IH2ZK3BB.js.map +1 -0
  27. package/dist/{reviews-GZ2VOIRN.js → reviews-FF2N2SLT.js} +2 -2
  28. package/dist/{subscriptions-U75YUOR2.js → subscriptions-FR6GCMPC.js} +2 -2
  29. package/dist/{system-apks-KWTN5LHO.js → system-apks-ZKVZLJPY.js} +2 -2
  30. package/dist/{testers-7ILUCKYB.js → testers-YQZ2XHI6.js} +2 -2
  31. package/dist/{tracks-RH3RKVFB.js → tracks-N7KPBVPC.js} +2 -2
  32. package/dist/{train-G44NEK43.js → train-N4TPYUTB.js} +2 -2
  33. package/dist/{update-QGUJ7SIQ.js → update-4SKKZHXQ.js} +2 -2
  34. package/dist/{users-W66YCFDX.js → users-CJ23I3IS.js} +2 -2
  35. package/dist/{version-BZPNDZEJ.js → version-YJSTOXO5.js} +2 -2
  36. package/package.json +1 -1
  37. package/dist/chunk-Y3QZDAKS.js.map +0 -1
  38. package/dist/purchases-XCBF2PZY.js.map +0 -1
  39. package/dist/releases-S3ISG5SL.js.map +0 -1
  40. /package/dist/{apps-WPUQOQLL.js.map → apps-WT4FKQFR.js.map} +0 -0
  41. /package/dist/{audit-BDPS5ODN.js.map → audit-D54TYDFD.js.map} +0 -0
  42. /package/dist/{chunk-UKVIYCC4.js.map → chunk-TPSF4BAR.js.map} +0 -0
  43. /package/dist/{config-WF24TCVM.js.map → config-WSKL2CK6.js.map} +0 -0
  44. /package/dist/{data-safety-UM74SYYE.js.map → data-safety-PDZTJ32M.js.map} +0 -0
  45. /package/dist/{device-tiers-MNZYMG3Y.js.map → device-tiers-EKU2TUPW.js.map} +0 -0
  46. /package/dist/{doctor-24TL3GUJ.js.map → doctor-JGJO52HH.js.map} +0 -0
  47. /package/dist/{enterprise-L7DTIX2O.js.map → enterprise-NP3EVLCN.js.map} +0 -0
  48. /package/dist/{external-transactions-4YBOHUXS.js.map → external-transactions-IIF2TSH6.js.map} +0 -0
  49. /package/dist/{feedback-RXYFYMLH.js.map → feedback-56LWTSEP.js.map} +0 -0
  50. /package/dist/{grants-32DED5QL.js.map → grants-Q3FWJYGR.js.map} +0 -0
  51. /package/dist/{iap-EPJ76IAC.js.map → iap-S5X4O7XF.js.map} +0 -0
  52. /package/dist/{internal-sharing-KW6YENDG.js.map → internal-sharing-BC76IRJG.js.map} +0 -0
  53. /package/dist/{listings-7RTA4MCI.js.map → listings-ZC7T3IBA.js.map} +0 -0
  54. /package/dist/{one-time-products-OIDBVCFE.js.map → one-time-products-YSX5VI6I.js.map} +0 -0
  55. /package/dist/{publish-4LBADN6P.js.map → publish-PGDTANYD.js.map} +0 -0
  56. /package/dist/{recovery-2VJJLAIQ.js.map → recovery-NSKTIJIN.js.map} +0 -0
  57. /package/dist/{reviews-GZ2VOIRN.js.map → reviews-FF2N2SLT.js.map} +0 -0
  58. /package/dist/{subscriptions-U75YUOR2.js.map → subscriptions-FR6GCMPC.js.map} +0 -0
  59. /package/dist/{system-apks-KWTN5LHO.js.map → system-apks-ZKVZLJPY.js.map} +0 -0
  60. /package/dist/{testers-7ILUCKYB.js.map → testers-YQZ2XHI6.js.map} +0 -0
  61. /package/dist/{tracks-RH3RKVFB.js.map → tracks-N7KPBVPC.js.map} +0 -0
  62. /package/dist/{train-G44NEK43.js.map → train-N4TPYUTB.js.map} +0 -0
  63. /package/dist/{update-QGUJ7SIQ.js.map → update-4SKKZHXQ.js.map} +0 -0
  64. /package/dist/{users-W66YCFDX.js.map → users-CJ23I3IS.js.map} +0 -0
  65. /package/dist/{version-BZPNDZEJ.js.map → version-YJSTOXO5.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  isDryRun,
4
4
  printDryRun
5
- } from "./chunk-Y3QZDAKS.js";
5
+ } from "./chunk-QHBTG2NG.js";
6
6
  import {
7
7
  requireConfirm
8
8
  } from "./chunk-RZQSEDKI.js";
@@ -128,4 +128,4 @@ function registerGrantsCommands(program) {
128
128
  export {
129
129
  registerGrantsCommands
130
130
  };
131
- //# sourceMappingURL=grants-32DED5QL.js.map
131
+ //# sourceMappingURL=grants-Q3FWJYGR.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  requireConfirm
15
15
  } from "./chunk-RZQSEDKI.js";
@@ -201,4 +201,4 @@ function registerIapCommands(program) {
201
201
  export {
202
202
  registerIapCommands
203
203
  };
204
- //# sourceMappingURL=iap-EPJ76IAC.js.map
204
+ //# sourceMappingURL=iap-S5X4O7XF.js.map
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  createProgram,
4
4
  handleCliError
5
- } from "./chunk-UKVIYCC4.js";
5
+ } from "./chunk-TPSF4BAR.js";
6
6
  export {
7
7
  createProgram,
8
8
  handleCliError
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  isDryRun,
8
8
  printDryRun
9
- } from "./chunk-Y3QZDAKS.js";
9
+ } from "./chunk-QHBTG2NG.js";
10
10
  import {
11
11
  getOutputFormat
12
12
  } from "./chunk-ELXAK7GI.js";
@@ -49,4 +49,4 @@ function registerInternalSharingCommands(program) {
49
49
  export {
50
50
  registerInternalSharingCommands
51
51
  };
52
- //# sourceMappingURL=internal-sharing-KW6YENDG.js.map
52
+ //# sourceMappingURL=internal-sharing-BC76IRJG.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  isInteractive,
15
15
  requireConfirm,
@@ -515,4 +515,4 @@ Missing locales: ${missingLocales.join(", ")}`);
515
515
  export {
516
516
  registerListingsCommands
517
517
  };
518
- //# sourceMappingURL=listings-7RTA4MCI.js.map
518
+ //# sourceMappingURL=listings-ZC7T3IBA.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  requireConfirm
15
15
  } from "./chunk-RZQSEDKI.js";
@@ -469,4 +469,4 @@ function registerOneTimeProductsCommands(program) {
469
469
  export {
470
470
  registerOneTimeProductsCommands
471
471
  };
472
- //# sourceMappingURL=one-time-products-OIDBVCFE.js.map
472
+ //# sourceMappingURL=one-time-products-YSX5VI6I.js.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-WSLFHX5X.js";
8
8
  import {
9
9
  isDryRun
10
- } from "./chunk-Y3QZDAKS.js";
10
+ } from "./chunk-QHBTG2NG.js";
11
11
  import {
12
12
  isInteractive,
13
13
  promptInput,
@@ -248,4 +248,4 @@ function registerPublishCommand(program) {
248
248
  export {
249
249
  registerPublishCommand
250
250
  };
251
- //# sourceMappingURL=publish-4LBADN6P.js.map
251
+ //# sourceMappingURL=publish-PGDTANYD.js.map
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  isDryRun,
8
8
  printDryRun
9
- } from "./chunk-Y3QZDAKS.js";
9
+ } from "./chunk-QHBTG2NG.js";
10
10
  import {
11
11
  isInteractive,
12
12
  requireConfirm,
@@ -109,13 +109,19 @@ function registerPurchasesCommands(program) {
109
109
  if (format !== "json") {
110
110
  const r = result;
111
111
  const lineItems = r["lineItems"];
112
+ const onHold = r["onHoldStateContext"];
113
+ const inGrace = r["inGracePeriodStateContext"];
114
+ const onHoldPending = onHold?.["renewalDeclined"]?.["pendingOrderId"];
115
+ const inGracePending = inGrace?.["renewalDeclined"]?.["pendingOrderId"];
112
116
  const row = {
113
117
  subscriptionState: r["subscriptionState"] || "-",
114
118
  startTime: r["startTime"] || "-",
115
119
  expiryTime: r["expiryTime"] || "-",
116
120
  linkedPurchaseToken: r["linkedPurchaseToken"] ? "yes" : "no",
117
121
  lineItems: lineItems?.length || 0,
118
- acknowledgement: r["acknowledgementState"] || "-"
122
+ acknowledgement: r["acknowledgementState"] || "-",
123
+ ...onHoldPending && { onHoldPendingOrderId: onHoldPending },
124
+ ...inGracePending && { gracePeriodPendingOrderId: inGracePending }
119
125
  };
120
126
  console.log(formatOutput(row, format));
121
127
  } else {
@@ -418,4 +424,4 @@ Use one of these instead:
418
424
  export {
419
425
  registerPurchasesCommands
420
426
  };
421
- //# sourceMappingURL=purchases-XCBF2PZY.js.map
427
+ //# sourceMappingURL=purchases-LHGBIZNF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/purchases.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { Option } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport {\n getProductPurchase,\n getProductPurchaseV2,\n acknowledgeProductPurchase,\n consumeProductPurchase,\n getSubscriptionPurchase,\n cancelSubscriptionPurchase,\n cancelSubscriptionV2,\n deferSubscriptionPurchase,\n deferSubscriptionV2,\n revokeSubscriptionPurchase,\n listVoidedPurchases,\n refundOrder,\n getOrderDetails,\n batchGetOrders,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\n\nexport function registerPurchasesCommands(program: Command): void {\n const purchases = program.command(\"purchases\").description(\"Manage purchases and orders\");\n\n purchases\n .command(\"get <product-id> <token>\")\n .description(\"Get a product purchase\")\n .action(async (productId: string, token: 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 getProductPurchase(client, packageName, productId, token);\n if (format !== \"json\") {\n const r = result as unknown as Record<string, unknown>;\n const row = {\n orderId: r[\"orderId\"] || \"-\",\n purchaseState: r[\"purchaseState\"] ?? \"-\",\n consumptionState: r[\"consumptionState\"] ?? \"-\",\n purchaseTime: r[\"purchaseTimeMillis\"]\n ? new Date(Number(r[\"purchaseTimeMillis\"])).toISOString()\n : \"-\",\n acknowledged: r[\"acknowledgementState\"] ?? \"-\",\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n purchases\n .command(\"acknowledge <product-id> <token>\")\n .description(\"Acknowledge a product purchase\")\n .option(\"--payload <text>\", \"Developer payload\")\n .action(async (productId: string, token: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases acknowledge\",\n action: \"acknowledge\",\n target: `${productId}/${token}`,\n details: { payload: options.payload },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await acknowledgeProductPurchase(client, packageName, productId, token, options.payload);\n console.log(`Purchase acknowledged.`);\n });\n\n purchases\n .command(\"consume <product-id> <token>\")\n .description(\"Consume a product purchase\")\n .action(async (productId: string, token: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases consume\",\n action: \"consume\",\n target: `${productId}/${token}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await consumeProductPurchase(client, packageName, productId, token);\n console.log(`Purchase consumed.`);\n });\n\n // --- Subscription purchases ---\n const sub = purchases.command(\"subscription\").description(\"Manage subscription purchases\");\n\n sub\n .command(\"get <token>\")\n .description(\"Get a subscription purchase (v2)\")\n .action(async (token: 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 getSubscriptionPurchase(client, packageName, token);\n if (format !== \"json\") {\n const r = result as unknown as Record<string, unknown>;\n const lineItems = r[\"lineItems\"] as Record<string, unknown>[] | undefined;\n const onHold = r[\"onHoldStateContext\"] as Record<string, unknown> | undefined;\n const inGrace = r[\"inGracePeriodStateContext\"] as Record<string, unknown> | undefined;\n const onHoldPending = (\n onHold?.[\"renewalDeclined\"] as Record<string, unknown> | undefined\n )?.[\"pendingOrderId\"];\n const inGracePending = (\n inGrace?.[\"renewalDeclined\"] as Record<string, unknown> | undefined\n )?.[\"pendingOrderId\"];\n const row: Record<string, unknown> = {\n subscriptionState: r[\"subscriptionState\"] || \"-\",\n startTime: r[\"startTime\"] || \"-\",\n expiryTime: r[\"expiryTime\"] || \"-\",\n linkedPurchaseToken: r[\"linkedPurchaseToken\"] ? \"yes\" : \"no\",\n lineItems: lineItems?.length || 0,\n acknowledgement: r[\"acknowledgementState\"] || \"-\",\n ...(onHoldPending && { onHoldPendingOrderId: onHoldPending }),\n ...(inGracePending && { gracePeriodPendingOrderId: inGracePending }),\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n sub\n .command(\"cancel <subscription-id> <token>\")\n .description(\"Cancel a subscription (v1)\")\n .action(async (subscriptionId: string, token: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription cancel\",\n action: \"cancel subscription\",\n target: `${subscriptionId}/${token}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Cancel subscription ${subscriptionId}? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await cancelSubscriptionPurchase(client, packageName, subscriptionId, token);\n console.log(`Subscription cancelled.`);\n });\n\n sub\n .command(\"defer <subscription-id> <token>\")\n .description(\"Defer a subscription expiry\")\n .option(\"--expiry <iso-date>\", \"Desired new expiry date (ISO 8601)\")\n .action(async (subscriptionId: string, token: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.expiry = await requireOption(\n \"expiry\",\n options.expiry,\n {\n message: \"New expiry date (ISO 8601, e.g. 2026-12-31T23:59:59Z):\",\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"purchases subscription defer\",\n action: \"defer subscription\",\n target: `${subscriptionId}/${token}`,\n details: { expiry: options.expiry },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deferSubscriptionPurchase(\n client,\n packageName,\n subscriptionId,\n token,\n options.expiry,\n );\n console.log(formatOutput(result, format));\n });\n\n sub\n .command(\"refund <token>\")\n .description(\"Refund a subscription purchase (use 'orders refund' instead)\")\n .action(async () => {\n console.error(\n `The subscriptionsv2 refund endpoint does not exist in the Google Play API.\\n\\n` +\n `Use one of these instead:\\n` +\n ` gpc purchases orders refund <order-id> Refund via orders API\\n` +\n ` gpc purchases subscription revoke <token> Revoke + refund via v2 API\\n`,\n );\n process.exit(2);\n });\n\n sub\n .command(\"revoke <token>\")\n .description(\"Revoke a subscription (v2)\")\n .option(\"--refund-type <type>\", \"Refund type: full, prorated, or item (default: prorated)\")\n .option(\n \"--product-id <id>\",\n \"Product ID for item-based refund (required with --refund-type item)\",\n )\n .action(async (token: string, opts: { refundType?: string; productId?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const refundType = (opts.refundType ?? \"prorated\") as \"full\" | \"prorated\" | \"item\";\n\n if (![\"full\", \"prorated\", \"item\"].includes(refundType)) {\n console.error(`Invalid --refund-type \"${refundType}\". Use: full, prorated, or item`);\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription revoke\",\n action: \"revoke subscription\",\n target: token,\n details: {\n refundType,\n ...(opts.productId && { productId: opts.productId }),\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Revoke subscription (${refundType} refund)? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await revokeSubscriptionPurchase(client, packageName, token, refundType, opts.productId);\n console.log(`Subscription revoked (${refundType} refund).`);\n });\n\n // --- Voided purchases ---\n purchases\n .command(\"voided\")\n .description(\"List voided purchases\")\n .option(\"--start-time <time>\", \"Start time (milliseconds)\")\n .option(\"--end-time <time>\", \"End time (milliseconds)\")\n .option(\n \"--type <n>\",\n \"Purchase type: 0=in-app only (default), 1=in-app + subscriptions\",\n parseInt,\n )\n .option(\"--include-partial-refunds\", \"Include quantity-based partial refunds\")\n .addOption(\n new Option(\"--max-results <n>\", \"Maximum results per page\").argParser(parseInt).hideHelp(),\n )\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listVoidedPurchases(client, packageName, {\n startTime: options.startTime,\n endTime: options.endTime,\n type: options.type,\n includeQuantityBasedPartialRefund: options.includePartialRefunds,\n maxResults: options.maxResults,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n if (format !== \"json\") {\n const purchases = (result as Record<string, unknown>)[\"voidedPurchases\"] as\n | Record<string, unknown>[]\n | undefined;\n if (purchases && purchases.length > 0) {\n const rows = purchases.map((p) => ({\n orderId: p[\"orderId\"] || \"-\",\n purchaseToken: String(p[\"purchaseToken\"] || \"-\").slice(0, 16) + \"...\",\n voidedTime: p[\"voidedTimeMillis\"]\n ? new Date(Number(p[\"voidedTimeMillis\"])).toISOString()\n : \"-\",\n voidedSource: p[\"voidedSource\"] ?? \"-\",\n voidedReason: p[\"voidedReason\"] ?? \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(\"No voided purchases found.\");\n }\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Orders ---\n const orders = purchases.command(\"orders\").description(\"Manage orders\");\n\n orders\n .command(\"refund <order-id>\")\n .description(\"Refund an order\")\n .option(\"--revoke\", \"Revoke the order (remove entitlement)\")\n .action(async (orderId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Refund order \"${orderId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases orders refund\",\n action: \"refund\",\n target: orderId,\n details: { revoke: options.revoke },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await refundOrder(client, packageName, orderId, {\n revoke: options.revoke,\n });\n console.log(`Order ${orderId} refunded.`);\n });\n\n orders\n .command(\"get <order-id>\")\n .description(\"Get order details\")\n .action(async (orderId: 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 getOrderDetails(client, packageName, orderId);\n if (format !== \"json\") {\n const row = {\n orderId: result.orderId,\n state: result.state,\n purchaseToken: result.purchaseToken ? result.purchaseToken.slice(0, 16) + \"...\" : \"-\",\n createTime: result.createTime || \"-\",\n total: result.total\n ? `${result.total.units || \"0\"}.${String(result.total.nanos || 0)\n .padStart(9, \"0\")\n .slice(0, 2)} ${result.total.currencyCode}`\n : \"-\",\n lineItems: result.lineItems?.length || 0,\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n orders\n .command(\"batch-get\")\n .description(\"Get multiple orders at once\")\n .requiredOption(\"--ids <order-ids>\", \"Comma-separated order IDs (max 1000)\")\n .action(async (options: { ids: 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 orderIds = options.ids\n .split(\",\")\n .map((id) => id.trim())\n .filter(Boolean);\n\n const result = await batchGetOrders(client, packageName, orderIds);\n if (format !== \"json\") {\n if (result.length === 0) {\n console.log(\"No orders found.\");\n } else {\n const rows = result.map((o) => ({\n orderId: o.orderId,\n state: o.state,\n createTime: o.createTime || \"-\",\n lineItems: o.lineItems?.length || 0,\n }));\n console.log(formatOutput(rows, format));\n }\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Product purchases V2 (Jun 2025) ---\n const product = purchases.command(\"product\").description(\"Product purchase operations\");\n\n product\n .command(\"get-v2 <token>\")\n .description(\"Get product purchase details (v2 — supports multi-offer OTPs)\")\n .action(async (token: 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 getProductPurchaseV2(client, packageName, token);\n if (format !== \"json\") {\n const row = {\n orderId: result.orderId || \"-\",\n state: result.purchaseStateContext?.purchaseState || \"-\",\n regionCode: result.regionCode || \"-\",\n completionTime: result.purchaseCompletionTime || \"-\",\n acknowledgement: result.acknowledgementState || \"-\",\n lineItems: result.productLineItem?.length || 0,\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Subscription V2 cancel/defer (Sep 2025 / Jan 2026) ---\n // Added to existing `sub` group alongside v1 cancel/defer\n\n sub\n .command(\"cancel-v2 <token>\")\n .description(\"Cancel a subscription (v2 -- supports cancellation types)\")\n .option(\n \"--type <cancellationType>\",\n \"USER_REQUESTED_STOP_RENEWALS (default) or DEVELOPER_REQUESTED_STOP_PAYMENTS\",\n )\n .action(async (token: string, options: { type?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription cancel-v2\",\n action: \"cancel\",\n target: token.slice(0, 16) + \"...\",\n details: { cancellationType: options.type },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Cancel subscription (token: ${token.slice(0, 16)}...)? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await cancelSubscriptionV2(client, packageName, token, options.type);\n console.log(\"Subscription cancelled.\");\n });\n\n sub\n .command(\"defer-v2 <token>\")\n .description(\"Defer a subscription renewal (v2 -- supports add-on subscriptions)\")\n .requiredOption(\"--duration <seconds>\", \"Duration to defer by (e.g. '2592000s' for 30 days)\")\n .option(\"--etag <etag>\", \"Subscription etag (fetched automatically if omitted)\")\n .action(async (token: string, options: { duration: string; etag?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Defer subscription renewal by ${options.duration}?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription defer-v2\",\n action: \"defer\",\n target: token.slice(0, 16) + \"...\",\n details: { deferDuration: options.duration },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deferSubscriptionV2(\n client,\n packageName,\n token,\n options.duration,\n options.etag,\n );\n for (const item of result.itemExpiryTimeDetails) {\n console.log(`${item.productId}: new expiry ${item.expiryTime}`);\n }\n });\n}\n"],"mappings":"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","names":["purchases"]}
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  isDryRun,
8
8
  printDryRun
9
- } from "./chunk-Y3QZDAKS.js";
9
+ } from "./chunk-QHBTG2NG.js";
10
10
  import {
11
11
  requireConfirm
12
12
  } from "./chunk-RZQSEDKI.js";
@@ -170,4 +170,4 @@ function registerRecoveryCommands(program) {
170
170
  export {
171
171
  registerRecoveryCommands
172
172
  };
173
- //# sourceMappingURL=recovery-2VJJLAIQ.js.map
173
+ //# sourceMappingURL=recovery-NSKTIJIN.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  isDryRun,
7
7
  printDryRun
8
- } from "./chunk-Y3QZDAKS.js";
8
+ } from "./chunk-QHBTG2NG.js";
9
9
  import {
10
10
  isInteractive,
11
11
  promptInput,
@@ -773,4 +773,4 @@ function registerReleasesCommands(program) {
773
773
  export {
774
774
  registerReleasesCommands
775
775
  };
776
- //# sourceMappingURL=releases-S3ISG5SL.js.map
776
+ //# sourceMappingURL=releases-IH2ZK3BB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/releases.ts"],"sourcesContent":["import { appendFile, stat } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient, createReportingClient } from \"@gpc-cli/api\";\nimport type { RetryLogEntry, ExternallyHostedApk, UploadProgressEvent } from \"@gpc-cli/api\";\nimport {\n uploadRelease,\n getReleasesStatus,\n promoteRelease,\n assignRelease,\n updateRollout,\n readReleaseNotesFromDir,\n isVersionedNotesDir,\n generateNotesFromGit,\n writeAuditLog,\n createAuditEntry,\n uploadExternallyHosted,\n diffReleases,\n fetchReleaseNotes,\n getVitalsCrashes,\n checkThreshold,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { formatOutput, sortResults, createSpinner, maybePaginate } from \"@gpc-cli/core\";\nimport type { UploadResult } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport {\n isInteractive,\n promptSelect,\n promptInput,\n requireOption,\n requireConfirm,\n} from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Set a default app: gpc config set app <package>\",\n );\n }\n return name;\n}\n\nimport { buildCommitOptions } from \"../commit-options.js\";\n\nfunction createRetryLogger(retryLogPath?: string): ((entry: RetryLogEntry) => void) | undefined {\n if (!retryLogPath) return undefined;\n return (entry: RetryLogEntry) => {\n const line = JSON.stringify(entry) + \"\\n\";\n appendFile(retryLogPath, line).catch(() => {});\n };\n}\n\nasync function getClient(config: GpcConfig, retryLogPath?: string, uploadTimeout?: number) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth, onRetry: createRetryLogger(retryLogPath), uploadTimeout });\n}\n\nexport function registerReleasesCommands(program: Command): void {\n const releases = program.command(\"releases\").description(\"Manage releases and rollouts\");\n\n // Upload\n releases\n .command(\"upload <file>\")\n .description(\"Upload AAB/APK and assign to a track\")\n .option(\"--track <track>\", \"Target track\", \"internal\")\n .option(\"--rollout <percent>\", \"Staged rollout percentage (1-100)\")\n .option(\"--notes <text>\", \"Release notes (en-US)\")\n .option(\"--name <name>\", \"Release name\")\n .option(\"--mapping <file>\", \"ProGuard/R8 mapping file for deobfuscation\")\n .option(\"--notes-dir <dir>\", \"Read release notes from directory (<dir>/<lang>.txt)\")\n .option(\"--notes-from-git\", \"Generate release notes from git commit history\")\n .option(\"--copy-notes-from <track>\", \"Copy release notes from another track\")\n .option(\"--changelog-ai\", \"Generate AI-translated release notes from git history\")\n .option(\"--locales <csv|auto>\", \"Locales for --changelog-ai (comma-separated BCP 47 or 'auto')\")\n .option(\"--provider <name>\", \"AI provider for --changelog-ai (anthropic|openai|google)\")\n .option(\"--model <id>\", \"Override AI model for --changelog-ai\")\n .option(\n \"--since <ref>\",\n \"Git ref to start from (tag, SHA) — used with --notes-from-git or --changelog-ai\",\n )\n .option(\"--retry-log <path>\", \"Write retry log entries to file (JSONL)\")\n .option(\n \"--timeout <ms>\",\n \"Upload timeout in milliseconds (auto-scales with file size by default)\",\n parseInt,\n )\n .option(\n \"--status <status>\",\n \"Release status: completed, inProgress, draft, halted\",\n \"completed\",\n )\n .option(\"--mapping-type <type>\", \"Deobfuscation file type: proguard or nativeCode\", \"proguard\")\n .option(\"--device-tier-config <id>\", \"Device tier config ID (or LATEST)\")\n .option(\n \"--changes-not-sent-for-review\",\n \"Commit changes without sending for review (required for rejected apps)\",\n )\n .option(\n \"--error-if-in-review\",\n \"Fail if changes are already in review instead of cancelling them\",\n )\n .option(\n \"--validate-only\",\n \"Upload and validate without committing (changes are discarded after validation)\",\n )\n .option(\n \"--in-app-update-priority <priority>\",\n \"In-app update priority (0-5, where 5 is highest)\",\n (v: string) => {\n const n = parseInt(v, 10);\n if (isNaN(n) || n < 0 || n > 5) {\n throw new GpcError(\n `Invalid in-app update priority: ${v}`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a value from 0 (default, no priority) to 5 (highest priority).\",\n );\n }\n return n;\n },\n )\n .option(\n \"--retain-version-codes <codes>\",\n \"Retain previous version codes alongside the new upload (comma-separated)\",\n (v: string) =>\n v\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n )\n .action(async (file: string, options) => {\n try {\n await stat(file);\n } catch {\n throw new GpcError(\n `File not found: ${file}`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Check the file path and try again.\",\n );\n }\n\n const ext = extname(file).toLowerCase();\n if (ext !== \".aab\" && ext !== \".apk\") {\n throw new GpcError(\n `Expected .aab or .apk file, got \"${ext || \"(no extension)\"}\"`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Provide a .aab or .apk file.\",\n );\n }\n\n const noteSources = [\n options.notes,\n options.notesDir,\n options.notesFromGit,\n options.copyNotesFrom,\n options.changelogAi,\n ].filter(Boolean);\n if (noteSources.length > 1) {\n throw new GpcError(\n \"Cannot combine --notes, --notes-dir, --notes-from-git, --copy-notes-from, and --changelog-ai. Use only one.\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Pick one release notes source.\",\n );\n }\n if (options.changelogAi && !options.locales) {\n throw new GpcError(\n \"--changelog-ai requires --locales <csv|auto>\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Example: --changelog-ai --locales en-US,fr-FR or --changelog-ai --locales auto\",\n );\n }\n if (options.validateOnly && isDryRun(program)) {\n throw new GpcError(\n \"Cannot combine --dry-run and --validate-only.\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use --dry-run to preview without any API changes, or --validate-only to upload and validate without committing.\",\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n // Interactive mode: prompt for missing options\n if (isInteractive(program)) {\n if (!options.track || options.track === \"internal\") {\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n options.track = await promptSelect(\"Select track:\", tracks, \"internal\");\n }\n\n if (!options.rollout && options.track === \"production\") {\n const rolloutStr = await promptInput(\n \"Staged rollout percentage (1-100, blank for full)\",\n \"100\",\n );\n if (rolloutStr && rolloutStr !== \"100\") {\n options.rollout = rolloutStr;\n }\n }\n\n if (!options.notes && !options.notesDir) {\n const notes = await promptInput(\"Release notes (en-US, blank to skip)\");\n if (notes) options.notes = notes;\n }\n }\n\n if (options.rollout !== undefined) {\n const rollout = Number(options.rollout);\n if (!Number.isFinite(rollout) || rollout < 1 || rollout > 100) {\n throw new GpcError(\n `--rollout must be a number between 1 and 100 (got: ${options.rollout})`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a percentage between 1 and 100.\",\n );\n }\n }\n\n if (\n options.mappingType &&\n options.mappingType !== \"proguard\" &&\n options.mappingType !== \"nativeCode\"\n ) {\n throw new GpcError(\n `--mapping-type must be \"proguard\" or \"nativeCode\" (got: \"${options.mappingType}\")`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use --mapping-type proguard (default) for ProGuard/R8 maps, or --mapping-type nativeCode for native debug symbols.\",\n );\n }\n\n const { size: fileSize } = await stat(file);\n const jsonMode = format === \"json\";\n const client = await getClient(config, options.retryLog, options.timeout);\n\n const showProgress = !jsonMode && process.stderr.isTTY && !program.opts()[\"quiet\"];\n const sizeMB = (fileSize / (1024 * 1024)).toFixed(1);\n\n function formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n }\n\n const BAR_WIDTH = 20;\n const onUploadProgress = showProgress\n ? (event: UploadProgressEvent) => {\n const filled = Math.round((event.percent / 100) * BAR_WIDTH);\n const bar = \"█\".repeat(filled) + \"░\".repeat(BAR_WIDTH - filled);\n const uploaded = formatBytes(event.bytesUploaded);\n const total = formatBytes(event.totalBytes);\n const speed =\n event.bytesPerSecond > 0 ? `${formatBytes(event.bytesPerSecond)}/s` : \"...\";\n const eta = event.etaSeconds > 0 ? `ETA ${event.etaSeconds}s` : \"\";\n process.stderr.write(\n `\\r ${bar} ${event.percent}% ${uploaded}/${total} ${speed} ${eta}\\x1b[K`,\n );\n }\n : undefined;\n\n if (isDryRun(program)) {\n const result = await uploadRelease(client, packageName, file, {\n track: options.track,\n status: options.status,\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n mappingFileType: options.mappingType,\n deviceTierConfigId: options.deviceTierConfig,\n inAppUpdatePriority: options.inAppUpdatePriority,\n retainVersionCodes: options.retainVersionCodes,\n dryRun: true,\n });\n console.log(formatOutput(result, format));\n return;\n }\n\n const auditEntry = createAuditEntry(\n \"releases upload\",\n {\n file,\n track: options.track,\n rollout: options.rollout,\n },\n packageName,\n );\n\n const spinner = createSpinner(`Uploading ${basename(file)} (${sizeMB} MB)...`);\n if (!showProgress) spinner.start();\n\n try {\n let releaseNotes: { language: string; text: string }[] | undefined;\n let notesDirVersioned: string | undefined;\n if (options.copyNotesFrom) {\n releaseNotes = await fetchReleaseNotes(client, packageName, options.copyNotesFrom);\n } else if (options.notesFromGit) {\n const gitNotes = await generateNotesFromGit({ since: options.since });\n releaseNotes = [{ language: gitNotes.language, text: gitNotes.text }];\n } else if (options.notesDir) {\n if (await isVersionedNotesDir(options.notesDir)) {\n notesDirVersioned = options.notesDir;\n } else {\n releaseNotes = await readReleaseNotesFromDir(options.notesDir);\n }\n } else if (options.changelogAi) {\n const {\n generateChangelog,\n buildLocaleBundle,\n resolveAiConfig,\n createTranslator,\n translateBundle,\n bundleToReleaseNotes,\n resolveLocales,\n formatPathLabel,\n } = await import(\"@gpc-cli/core\");\n\n const generated = await generateChangelog({ from: options.since });\n\n let locales: string[];\n if (options.locales === \"auto\") {\n locales = await resolveLocales(\"auto\", { client, packageName });\n } else {\n locales = await resolveLocales(options.locales);\n }\n\n const baseBundle = buildLocaleBundle(generated, { locales, format: \"md\" });\n\n const aiConfig = resolveAiConfig({\n provider: options.provider,\n model: options.model,\n });\n if (!jsonMode) {\n process.stderr.write(` → AI: ${formatPathLabel(aiConfig)}\\n`);\n }\n\n const translator = await createTranslator(aiConfig);\n const translated = await translateBundle(baseBundle, {\n translator,\n strict: false,\n onError: ({ language, reason }: { language: string; reason: string }) => {\n if (!jsonMode) {\n process.stderr.write(` warn: ${language} translation failed: ${reason}\\n`);\n }\n },\n });\n\n releaseNotes = bundleToReleaseNotes(translated);\n if (!jsonMode && releaseNotes.length > 0) {\n process.stderr.write(\n ` → ${releaseNotes.length} locale${releaseNotes.length !== 1 ? \"s\" : \"\"} generated\\n`,\n );\n }\n } else if (options.notes) {\n releaseNotes = [{ language: \"en-US\", text: options.notes }];\n }\n\n const result = await uploadRelease(client, packageName, file, {\n track: options.track,\n status: options.status,\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes,\n releaseName: options.name,\n mappingFile: options.mapping,\n mappingFileType: options.mappingType,\n deviceTierConfigId: options.deviceTierConfig,\n validateOnly: options.validateOnly,\n inAppUpdatePriority: options.inAppUpdatePriority,\n retainVersionCodes: options.retainVersionCodes,\n notesDirVersioned,\n onUploadProgress,\n commitOptions: buildCommitOptions(options),\n });\n if (showProgress) {\n process.stderr.write(`\\r ✓ Uploaded ${basename(file)} ${sizeMB} MB\\x1b[K\\n`);\n }\n spinner.stop(\n (result as UploadResult).validateOnly\n ? \"Validation passed (not committed)\"\n : \"Upload complete\",\n );\n console.log(formatOutput(result, format));\n auditEntry.success = true;\n } catch (error) {\n if (showProgress) {\n process.stderr.write(\"\\n\");\n }\n spinner.fail(\"Upload failed\");\n auditEntry.success = false;\n auditEntry.error = error instanceof Error ? error.message : String(error);\n throw error;\n } finally {\n auditEntry.durationMs = Date.now() - new Date(auditEntry.timestamp).getTime();\n writeAuditLog(auditEntry).catch(() => {});\n }\n });\n\n // Status\n releases\n .command(\"status\")\n .description(\"Show current release status across tracks\")\n .option(\"--track <track>\", \"Filter by track\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const TRACK_ORDER = [\"production\", \"beta\", \"alpha\", \"internal\"];\n const rawStatuses = await getReleasesStatus(client, packageName, options.track);\n const statuses = options.track\n ? Array.isArray(rawStatuses)\n ? rawStatuses.filter((s: any) => s.track === options.track)\n : rawStatuses\n : rawStatuses;\n const sorted = Array.isArray(statuses)\n ? options.sort\n ? sortResults(statuses, options.sort)\n : [...statuses].sort((a, b) => {\n const ai = TRACK_ORDER.indexOf(\n String((a as unknown as Record<string, unknown>)[\"track\"] ?? \"\"),\n );\n const bi = TRACK_ORDER.indexOf(\n String((b as unknown as Record<string, unknown>)[\"track\"] ?? \"\"),\n );\n return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi);\n })\n : statuses;\n if (format !== \"json\" && Array.isArray(sorted)) {\n const rows = sorted.map((s: unknown) => {\n const sr = s as Record<string, unknown>;\n return {\n track: sr[\"track\"] || \"-\",\n status: sr[\"status\"] || \"-\",\n name: sr[\"name\"] || \"-\",\n versionCodes: Array.isArray(sr[\"versionCodes\"])\n ? (sr[\"versionCodes\"] as unknown[]).join(\", \")\n : \"-\",\n userFraction:\n sr[\"userFraction\"] !== undefined\n ? `${Math.round(Number(sr[\"userFraction\"]) * 100)}%`\n : \"—\",\n };\n });\n await maybePaginate(formatOutput(rows, format));\n } else {\n await maybePaginate(formatOutput(sorted, format));\n }\n });\n\n // Promote\n releases\n .command(\"promote\")\n .description(\"Promote a release from one track to another\")\n .option(\"--from <track>\", \"Source track\")\n .option(\"--to <track>\", \"Target track\")\n .option(\"--rollout <percent>\", \"Staged rollout percentage\")\n .option(\"--notes <text>\", \"Release notes\")\n .option(\"--copy-notes-from <track>\", \"Copy release notes from another track\")\n .option(\"--status <status>\", \"Release status: completed, inProgress, draft, halted\")\n .option(\n \"--changes-not-sent-for-review\",\n \"Commit changes without sending for review (required for rejected apps)\",\n )\n .option(\n \"--error-if-in-review\",\n \"Fail if changes are already in review instead of cancelling them\",\n )\n .action(async (options) => {\n if (options.notes && options.copyNotesFrom) {\n throw new GpcError(\n \"Cannot combine --notes and --copy-notes-from. Use only one.\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Pick one release notes source.\",\n );\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n\n options.from = await requireOption(\n \"from\",\n options.from,\n {\n message: \"Source track:\",\n choices: tracks,\n },\n interactive,\n );\n\n options.to = await requireOption(\n \"to\",\n options.to,\n {\n message: \"Target track:\",\n choices: tracks.filter((t: string) => t !== options.from),\n },\n interactive,\n );\n\n if (options.from === options.to) {\n throw new GpcError(\n `--from and --to must be different tracks (both are \"${options.from}\")`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Specify different source and target tracks.\",\n );\n }\n\n if (options.rollout !== undefined) {\n const rollout = Number(options.rollout);\n if (!Number.isFinite(rollout) || rollout < 1 || rollout > 100) {\n throw new GpcError(\n `--rollout must be a number between 1 and 100 (got: ${options.rollout})`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a percentage between 1 and 100.\",\n );\n }\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"releases promote\",\n action: \"promote\",\n target: `${options.from} → ${options.to}`,\n details: {\n rollout: options.rollout,\n ...(options.status && { status: options.status }),\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n let releaseNotes: { language: string; text: string }[] | undefined;\n if (options.copyNotesFrom) {\n releaseNotes = await fetchReleaseNotes(client, packageName, options.copyNotesFrom);\n } else if (options.notes) {\n releaseNotes = [{ language: \"en-US\", text: options.notes }];\n }\n\n const result = await promoteRelease(client, packageName, options.from, options.to, {\n status: options.status,\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes,\n commitOptions: buildCommitOptions(options),\n });\n console.log(formatOutput(result, format));\n });\n\n // Assign\n releases\n .command(\"assign <versionCode>\")\n .description(\"Assign an already-uploaded version code to a track without re-uploading\")\n .option(\"--track <track>\", \"Target track\", \"internal\")\n .option(\"--status <status>\", \"Release status: completed, inProgress, draft, halted\")\n .option(\"--rollout <percent>\", \"Staged rollout percentage (sets status to inProgress)\")\n .option(\"--notes <text>\", \"Release notes (en-US)\")\n .option(\"--name <name>\", \"Release name\")\n .option(\n \"--in-app-update-priority <priority>\",\n \"In-app update priority (0-5, where 5 is highest)\",\n (v: string) => {\n const n = parseInt(v, 10);\n if (isNaN(n) || n < 0 || n > 5) {\n throw new GpcError(\n `Invalid in-app update priority: ${v}`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a value from 0 (default, no priority) to 5 (highest priority).\",\n );\n }\n return n;\n },\n )\n .option(\n \"--retain-version-codes <codes>\",\n \"Retain previous version codes alongside the new one (comma-separated)\",\n (v: string) =>\n v\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n )\n .option(\n \"--changes-not-sent-for-review\",\n \"Commit changes without sending for review (required for rejected apps)\",\n )\n .option(\n \"--error-if-in-review\",\n \"Fail if changes are already in review instead of cancelling them\",\n )\n .action(async (versionCodeArg: string, options) => {\n const versionCode = Number(versionCodeArg);\n if (!Number.isFinite(versionCode) || versionCode <= 0) {\n throw new GpcError(\n `Invalid version code: ${versionCodeArg}`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Provide a positive integer version code (e.g., gpc releases assign 42 --track beta).\",\n );\n }\n\n if (options.rollout !== undefined) {\n const rolloutVal = Number(options.rollout);\n if (!Number.isFinite(rolloutVal) || rolloutVal < 1 || rolloutVal > 100) {\n throw new GpcError(\n `--rollout must be a number between 1 and 100 (got: ${options.rollout})`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a percentage between 1 and 100.\",\n );\n }\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"releases assign\",\n action: \"assign\",\n target: `versionCode ${versionCode} → ${options.track}`,\n details: {\n ...(options.rollout && { rollout: options.rollout }),\n ...(options.status && { status: options.status }),\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n const result = await assignRelease(client, packageName, versionCode, {\n track: options.track,\n status: options.status,\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes: options.notes ? [{ language: \"en-US\", text: options.notes }] : undefined,\n releaseName: options.name,\n inAppUpdatePriority: options.inAppUpdatePriority,\n retainVersionCodes: options.retainVersionCodes,\n commitOptions: buildCommitOptions(options),\n });\n console.log(formatOutput(result, format));\n });\n\n // Rollout subcommands\n const rollout = releases.command(\"rollout\").description(\"Manage staged rollouts\");\n\n for (const action of [\"increase\", \"halt\", \"resume\", \"complete\"] as const) {\n const cmd = rollout\n .command(action)\n .description(`${action.charAt(0).toUpperCase() + action.slice(1)} a staged rollout`)\n .option(\"--track <track>\", \"Track name\");\n\n if (action === \"increase\") {\n cmd.option(\"--to <percent>\", \"New rollout percentage\");\n cmd.option(\"--vitals-gate\", \"Halt rollout if crash rate exceeds configured threshold\");\n }\n\n cmd.option(\n \"--changes-not-sent-for-review\",\n \"Commit changes without sending for review (required for rejected apps)\",\n );\n cmd.option(\n \"--error-if-in-review\",\n \"Fail if changes are already in review instead of cancelling them\",\n );\n\n cmd.action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: tracks,\n },\n interactive,\n );\n\n if (action === \"increase\") {\n options.to = await requireOption(\n \"to\",\n options.to,\n {\n message: \"New rollout percentage (1-100):\",\n },\n interactive,\n );\n }\n\n if (action === \"increase\" && options.to !== undefined) {\n const to = Number(options.to);\n if (!Number.isFinite(to) || to < 1 || to > 100) {\n throw new GpcError(\n `--to must be a number between 1 and 100 (got: ${options.to})`,\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use a percentage between 1 and 100.\",\n );\n }\n }\n\n // Require confirmation for destructive rollout halt\n if (action === \"halt\") {\n await requireConfirm(\n `Halt rollout on track \"${options.track}\" for ${packageName}?`,\n program,\n );\n }\n\n if (isDryRun(program)) {\n if (action === \"increase\" && options.vitalsGate) {\n console.error(\n \"Warning: --vitals-gate is ignored in --dry-run mode. Gate will run on live execution.\",\n );\n }\n printDryRun(\n {\n command: `releases rollout ${action}`,\n action: action,\n target: options.track,\n details: { percentage: options.to !== undefined ? `${options.to}%` : undefined },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n // Vitals gate: check crash rate BEFORE rollout increase\n if (action === \"increase\" && options.vitalsGate) {\n const threshold = (config as any).vitals?.thresholds?.crashRate;\n if (!threshold) {\n console.error(\n \"Warning: --vitals-gate requires vitals.thresholds.crashRate in config. Skipping gate.\",\n );\n } else {\n try {\n const { auth: authConfig } = config;\n const vitalsAuth = await resolveAuth({\n serviceAccountPath: authConfig?.serviceAccount,\n });\n const reportingClient = createReportingClient({ auth: vitalsAuth });\n const vitalsResult = await getVitalsCrashes(reportingClient, packageName, {\n days: 1,\n });\n const latest = (vitalsResult as any).data?.[0]?.crashRate;\n const check = checkThreshold(latest, threshold);\n if (check.breached) {\n console.error(\n `Vitals gate: crash rate ${String(latest)}% > threshold ${String(threshold)}%. Rollout increase blocked.`,\n );\n process.exitCode = 6;\n return;\n }\n } catch (vitalsErr) {\n console.error(\n `Warning: Vitals gate check failed: ${vitalsErr instanceof Error ? vitalsErr.message : String(vitalsErr)}`,\n );\n }\n }\n }\n\n const result = await updateRollout(\n client,\n packageName,\n options.track,\n action,\n options.to ? Number(options.to) / 100 : undefined,\n buildCommitOptions(options),\n );\n\n console.log(formatOutput(result, format));\n });\n }\n\n // Release notes\n releases\n .command(\"notes\")\n .description(\"Get or set release notes\")\n .argument(\"<action>\", \"Action: get|set\")\n .option(\"--track <track>\", \"Track name\")\n .option(\"--lang <language>\", \"Language code\", \"en-US\")\n .option(\"--notes <text>\", \"Release notes text\")\n .option(\"--file <path>\", \"Read notes from file\")\n .action(async (action: string, options) => {\n if (action === \"set\") {\n throw new GpcError(\n \"gpc releases notes set is not implemented as a standalone command.\",\n \"RELEASES_USAGE_ERROR\",\n 1,\n \"Use --notes, --notes-dir, or --notes-from-git with: gpc releases upload or gpc publish\",\n );\n }\n\n if (action === \"get\") {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const track = options.track ?? \"internal\";\n\n // Try getReleasesStatus first (has all releases), then fallback to fetchReleaseNotes\n const statuses = await getReleasesStatus(client, packageName, track);\n let notes = Array.isArray(statuses)\n ? statuses.flatMap((s: any) => s.releaseNotes ?? [])\n : ((statuses as any).releaseNotes ?? []);\n\n // Fallback: fetchReleaseNotes reads the raw track data which may have notes\n // even when getReleasesStatus doesn't (e.g. completed releases)\n if (notes.length === 0) {\n try {\n notes = await fetchReleaseNotes(client, packageName, track);\n } catch {\n // No release found on track — fall through to empty message\n }\n }\n\n if (notes.length === 0) {\n console.log(`No release notes found on track \"${track}\".`);\n return;\n }\n console.log(formatOutput(notes, format));\n return;\n }\n\n throw new GpcError(\n \"Unknown action. Usage: gpc releases notes <get|set> --track <track>\",\n \"RELEASES_USAGE_ERROR\",\n 2,\n \"Use: gpc releases notes get --track <track>\",\n );\n });\n\n // Upload externally hosted APK\n releases\n .command(\"upload-external\")\n .description(\"Upload an externally hosted APK configuration\")\n .requiredOption(\"--url <url>\", \"External URL where the APK is hosted\")\n .requiredOption(\"--file <config>\", \"Path to JSON config file with APK metadata\")\n .action(async (options: { url: string; file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n const { readFile } = await import(\"node:fs/promises\");\n const raw = await readFile(options.file, \"utf-8\");\n const apkConfig = JSON.parse(raw) as Record<string, unknown>;\n\n // Override with CLI-provided URL\n apkConfig[\"externallyHostedUrl\"] = options.url;\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const result = await uploadExternallyHosted(\n client,\n packageName,\n apkConfig as unknown as ExternallyHostedApk,\n );\n console.log(formatOutput(result, format));\n });\n\n // Diff\n releases\n .command(\"diff\")\n .description(\"Compare releases between two tracks\")\n .option(\"--from <track>\", \"Source track\", \"internal\")\n .option(\"--to <track>\", \"Target track\", \"production\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await diffReleases(client, packageName, options.from, options.to);\n if (result.diffs.length === 0) {\n console.log(`No differences between ${result.fromTrack} and ${result.toTrack}.`);\n } else {\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n } else {\n console.log(`Differences: ${result.fromTrack} vs ${result.toTrack}\\n`);\n console.log(formatOutput(result.diffs, format));\n }\n }\n });\n\n // Count\n releases\n .command(\"count\")\n .description(\"Count releases per track\")\n .option(\"--track <track>\", \"Filter to a specific track\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const statuses = await getReleasesStatus(client, packageName, options.track);\n\n // Group by track\n const trackCounts = new Map<string, { total: number; statuses: Record<string, number> }>();\n for (const r of statuses) {\n const entry = trackCounts.get(r.track) ?? { total: 0, statuses: {} };\n entry.total++;\n entry.statuses[r.status] = (entry.statuses[r.status] ?? 0) + 1;\n trackCounts.set(r.track, entry);\n }\n\n if (format === \"json\") {\n const data = Object.fromEntries(\n [...trackCounts.entries()].map(([track, info]) => [track, info]),\n );\n console.log(formatOutput(data, format));\n } else {\n const rows = [...trackCounts.entries()].map(([track, info]) => ({\n track,\n releases: info.total,\n ...info.statuses,\n }));\n if (rows.length === 0) {\n console.log(\"No releases found.\");\n } else {\n console.log(formatOutput(rows, format));\n }\n }\n });\n}\n"],"mappings":"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","names":["rollout"]}
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  isDryRun,
8
8
  printDryRun
9
- } from "./chunk-Y3QZDAKS.js";
9
+ } from "./chunk-QHBTG2NG.js";
10
10
  import {
11
11
  isInteractive,
12
12
  requireOption
@@ -194,4 +194,4 @@ Rating distribution:`);
194
194
  export {
195
195
  registerReviewsCommands
196
196
  };
197
- //# sourceMappingURL=reviews-GZ2VOIRN.js.map
197
+ //# sourceMappingURL=reviews-FF2N2SLT.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  requireConfirm
15
15
  } from "./chunk-RZQSEDKI.js";
@@ -507,4 +507,4 @@ By product:`);
507
507
  export {
508
508
  registerSubscriptionsCommands
509
509
  };
510
- //# sourceMappingURL=subscriptions-U75YUOR2.js.map
510
+ //# sourceMappingURL=subscriptions-FR6GCMPC.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  requireConfirm
15
15
  } from "./chunk-RZQSEDKI.js";
@@ -108,4 +108,4 @@ function registerSystemApksCommands(program) {
108
108
  export {
109
109
  registerSystemApksCommands
110
110
  };
111
- //# sourceMappingURL=system-apks-KWTN5LHO.js.map
111
+ //# sourceMappingURL=system-apks-ZKVZLJPY.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  isDryRun,
11
11
  printDryRun
12
- } from "./chunk-Y3QZDAKS.js";
12
+ } from "./chunk-QHBTG2NG.js";
13
13
  import {
14
14
  isInteractive,
15
15
  requireConfirm,
@@ -188,4 +188,4 @@ function registerTestersCommands(program) {
188
188
  export {
189
189
  registerTestersCommands
190
190
  };
191
- //# sourceMappingURL=testers-7ILUCKYB.js.map
191
+ //# sourceMappingURL=testers-YQZ2XHI6.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  isDryRun,
7
7
  printDryRun
8
- } from "./chunk-Y3QZDAKS.js";
8
+ } from "./chunk-QHBTG2NG.js";
9
9
  import {
10
10
  getOutputFormat
11
11
  } from "./chunk-ELXAK7GI.js";
@@ -104,4 +104,4 @@ function registerTracksCommands(program) {
104
104
  export {
105
105
  registerTracksCommands
106
106
  };
107
- //# sourceMappingURL=tracks-RH3RKVFB.js.map
107
+ //# sourceMappingURL=tracks-N7KPBVPC.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  isDryRun,
7
7
  printDryRun
8
- } from "./chunk-Y3QZDAKS.js";
8
+ } from "./chunk-QHBTG2NG.js";
9
9
  import {
10
10
  requireConfirm
11
11
  } from "./chunk-RZQSEDKI.js";
@@ -122,4 +122,4 @@ function registerTrainCommands(program) {
122
122
  export {
123
123
  registerTrainCommands
124
124
  };
125
- //# sourceMappingURL=train-G44NEK43.js.map
125
+ //# sourceMappingURL=train-N4TPYUTB.js.map
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
17
17
  program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
18
18
  const parentOpts = cmd.parent?.opts() ?? {};
19
19
  const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
20
- const currentVersion = "0.9.78";
20
+ const currentVersion = "0.9.79";
21
21
  if (currentVersion === "0.0.0") {
22
22
  if (jsonMode) {
23
23
  console.log(
@@ -172,4 +172,4 @@ Run: gpc update`);
172
172
  export {
173
173
  registerUpdateCommand
174
174
  };
175
- //# sourceMappingURL=update-QGUJ7SIQ.js.map
175
+ //# sourceMappingURL=update-4SKKZHXQ.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  isDryRun,
4
4
  printDryRun
5
- } from "./chunk-Y3QZDAKS.js";
5
+ } from "./chunk-QHBTG2NG.js";
6
6
  import {
7
7
  requireConfirm
8
8
  } from "./chunk-RZQSEDKI.js";
@@ -162,4 +162,4 @@ function registerUsersCommands(program) {
162
162
  export {
163
163
  registerUsersCommands
164
164
  };
165
- //# sourceMappingURL=users-W66YCFDX.js.map
165
+ //# sourceMappingURL=users-CJ23I3IS.js.map
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
7
7
  // src/commands/version.ts
8
8
  function registerVersionCommand(program) {
9
9
  program.command("version").description("Show version information").action(() => {
10
- const version = "0.9.78";
10
+ const version = "0.9.79";
11
11
  if (program.opts()["output"] === "json") {
12
12
  console.log(
13
13
  JSON.stringify({
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
25
25
  export {
26
26
  registerVersionCommand
27
27
  };
28
- //# sourceMappingURL=version-BZPNDZEJ.js.map
28
+ //# sourceMappingURL=version-YJSTOXO5.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpc-cli/cli",
3
- "version": "0.9.78",
3
+ "version": "0.9.79",
4
4
  "description": "GPC — Google Play Console CLI. 217 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dry-run.ts"],"sourcesContent":["import type { OutputFormat } from \"@gpc-cli/config\";\n\nexport interface DryRunPreview {\n command: string;\n action: string;\n target: string;\n details?: Record<string, unknown>;\n}\n\nexport function isDryRun(program: { opts(): Record<string, unknown> }): boolean {\n let cmd: { parent?: unknown; opts(): Record<string, unknown> } = program;\n while (cmd.parent) {\n cmd = cmd.parent as typeof cmd;\n }\n return !!cmd.opts()[\"dryRun\"];\n}\n\nexport function printDryRun(\n preview: DryRunPreview,\n format: OutputFormat,\n formatOutput: (data: unknown, format: OutputFormat, redact?: boolean) => string,\n): void {\n const output = {\n dryRun: true,\n ...preview,\n message: `Would ${preview.action} ${preview.target}`,\n };\n console.log(formatOutput(output, format));\n}\n"],"mappings":";;;AASO,SAAS,SAAS,SAAuD;AAC9E,MAAI,MAA6D;AACjE,SAAO,IAAI,QAAQ;AACjB,UAAM,IAAI;AAAA,EACZ;AACA,SAAO,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ;AAC9B;AAEO,SAAS,YACd,SACA,QACA,cACM;AACN,QAAM,SAAS;AAAA,IACb,QAAQ;AAAA,IACR,GAAG;AAAA,IACH,SAAS,SAAS,QAAQ,MAAM,IAAI,QAAQ,MAAM;AAAA,EACpD;AACA,UAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAC1C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/purchases.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { Option } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport {\n getProductPurchase,\n getProductPurchaseV2,\n acknowledgeProductPurchase,\n consumeProductPurchase,\n getSubscriptionPurchase,\n cancelSubscriptionPurchase,\n cancelSubscriptionV2,\n deferSubscriptionPurchase,\n deferSubscriptionV2,\n revokeSubscriptionPurchase,\n listVoidedPurchases,\n refundOrder,\n getOrderDetails,\n batchGetOrders,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\n\nexport function registerPurchasesCommands(program: Command): void {\n const purchases = program.command(\"purchases\").description(\"Manage purchases and orders\");\n\n purchases\n .command(\"get <product-id> <token>\")\n .description(\"Get a product purchase\")\n .action(async (productId: string, token: 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 getProductPurchase(client, packageName, productId, token);\n if (format !== \"json\") {\n const r = result as unknown as Record<string, unknown>;\n const row = {\n orderId: r[\"orderId\"] || \"-\",\n purchaseState: r[\"purchaseState\"] ?? \"-\",\n consumptionState: r[\"consumptionState\"] ?? \"-\",\n purchaseTime: r[\"purchaseTimeMillis\"]\n ? new Date(Number(r[\"purchaseTimeMillis\"])).toISOString()\n : \"-\",\n acknowledged: r[\"acknowledgementState\"] ?? \"-\",\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n purchases\n .command(\"acknowledge <product-id> <token>\")\n .description(\"Acknowledge a product purchase\")\n .option(\"--payload <text>\", \"Developer payload\")\n .action(async (productId: string, token: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases acknowledge\",\n action: \"acknowledge\",\n target: `${productId}/${token}`,\n details: { payload: options.payload },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await acknowledgeProductPurchase(client, packageName, productId, token, options.payload);\n console.log(`Purchase acknowledged.`);\n });\n\n purchases\n .command(\"consume <product-id> <token>\")\n .description(\"Consume a product purchase\")\n .action(async (productId: string, token: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases consume\",\n action: \"consume\",\n target: `${productId}/${token}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await consumeProductPurchase(client, packageName, productId, token);\n console.log(`Purchase consumed.`);\n });\n\n // --- Subscription purchases ---\n const sub = purchases.command(\"subscription\").description(\"Manage subscription purchases\");\n\n sub\n .command(\"get <token>\")\n .description(\"Get a subscription purchase (v2)\")\n .action(async (token: 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 getSubscriptionPurchase(client, packageName, token);\n if (format !== \"json\") {\n const r = result as unknown as Record<string, unknown>;\n const lineItems = r[\"lineItems\"] as Record<string, unknown>[] | undefined;\n const row = {\n subscriptionState: r[\"subscriptionState\"] || \"-\",\n startTime: r[\"startTime\"] || \"-\",\n expiryTime: r[\"expiryTime\"] || \"-\",\n linkedPurchaseToken: r[\"linkedPurchaseToken\"] ? \"yes\" : \"no\",\n lineItems: lineItems?.length || 0,\n acknowledgement: r[\"acknowledgementState\"] || \"-\",\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n sub\n .command(\"cancel <subscription-id> <token>\")\n .description(\"Cancel a subscription (v1)\")\n .action(async (subscriptionId: string, token: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription cancel\",\n action: \"cancel subscription\",\n target: `${subscriptionId}/${token}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Cancel subscription ${subscriptionId}? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await cancelSubscriptionPurchase(client, packageName, subscriptionId, token);\n console.log(`Subscription cancelled.`);\n });\n\n sub\n .command(\"defer <subscription-id> <token>\")\n .description(\"Defer a subscription expiry\")\n .option(\"--expiry <iso-date>\", \"Desired new expiry date (ISO 8601)\")\n .action(async (subscriptionId: string, token: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.expiry = await requireOption(\n \"expiry\",\n options.expiry,\n {\n message: \"New expiry date (ISO 8601, e.g. 2026-12-31T23:59:59Z):\",\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"purchases subscription defer\",\n action: \"defer subscription\",\n target: `${subscriptionId}/${token}`,\n details: { expiry: options.expiry },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deferSubscriptionPurchase(\n client,\n packageName,\n subscriptionId,\n token,\n options.expiry,\n );\n console.log(formatOutput(result, format));\n });\n\n sub\n .command(\"refund <token>\")\n .description(\"Refund a subscription purchase (use 'orders refund' instead)\")\n .action(async () => {\n console.error(\n `The subscriptionsv2 refund endpoint does not exist in the Google Play API.\\n\\n` +\n `Use one of these instead:\\n` +\n ` gpc purchases orders refund <order-id> Refund via orders API\\n` +\n ` gpc purchases subscription revoke <token> Revoke + refund via v2 API\\n`,\n );\n process.exit(2);\n });\n\n sub\n .command(\"revoke <token>\")\n .description(\"Revoke a subscription (v2)\")\n .option(\"--refund-type <type>\", \"Refund type: full, prorated, or item (default: prorated)\")\n .option(\n \"--product-id <id>\",\n \"Product ID for item-based refund (required with --refund-type item)\",\n )\n .action(async (token: string, opts: { refundType?: string; productId?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const refundType = (opts.refundType ?? \"prorated\") as \"full\" | \"prorated\" | \"item\";\n\n if (![\"full\", \"prorated\", \"item\"].includes(refundType)) {\n console.error(`Invalid --refund-type \"${refundType}\". Use: full, prorated, or item`);\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription revoke\",\n action: \"revoke subscription\",\n target: token,\n details: {\n refundType,\n ...(opts.productId && { productId: opts.productId }),\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Revoke subscription (${refundType} refund)? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await revokeSubscriptionPurchase(client, packageName, token, refundType, opts.productId);\n console.log(`Subscription revoked (${refundType} refund).`);\n });\n\n // --- Voided purchases ---\n purchases\n .command(\"voided\")\n .description(\"List voided purchases\")\n .option(\"--start-time <time>\", \"Start time (milliseconds)\")\n .option(\"--end-time <time>\", \"End time (milliseconds)\")\n .option(\n \"--type <n>\",\n \"Purchase type: 0=in-app only (default), 1=in-app + subscriptions\",\n parseInt,\n )\n .option(\"--include-partial-refunds\", \"Include quantity-based partial refunds\")\n .addOption(\n new Option(\"--max-results <n>\", \"Maximum results per page\").argParser(parseInt).hideHelp(),\n )\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listVoidedPurchases(client, packageName, {\n startTime: options.startTime,\n endTime: options.endTime,\n type: options.type,\n includeQuantityBasedPartialRefund: options.includePartialRefunds,\n maxResults: options.maxResults,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n if (format !== \"json\") {\n const purchases = (result as Record<string, unknown>)[\"voidedPurchases\"] as\n | Record<string, unknown>[]\n | undefined;\n if (purchases && purchases.length > 0) {\n const rows = purchases.map((p) => ({\n orderId: p[\"orderId\"] || \"-\",\n purchaseToken: String(p[\"purchaseToken\"] || \"-\").slice(0, 16) + \"...\",\n voidedTime: p[\"voidedTimeMillis\"]\n ? new Date(Number(p[\"voidedTimeMillis\"])).toISOString()\n : \"-\",\n voidedSource: p[\"voidedSource\"] ?? \"-\",\n voidedReason: p[\"voidedReason\"] ?? \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(\"No voided purchases found.\");\n }\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Orders ---\n const orders = purchases.command(\"orders\").description(\"Manage orders\");\n\n orders\n .command(\"refund <order-id>\")\n .description(\"Refund an order\")\n .option(\"--revoke\", \"Revoke the order (remove entitlement)\")\n .action(async (orderId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Refund order \"${orderId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases orders refund\",\n action: \"refund\",\n target: orderId,\n details: { revoke: options.revoke },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await refundOrder(client, packageName, orderId, {\n revoke: options.revoke,\n });\n console.log(`Order ${orderId} refunded.`);\n });\n\n orders\n .command(\"get <order-id>\")\n .description(\"Get order details\")\n .action(async (orderId: 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 getOrderDetails(client, packageName, orderId);\n if (format !== \"json\") {\n const row = {\n orderId: result.orderId,\n state: result.state,\n purchaseToken: result.purchaseToken ? result.purchaseToken.slice(0, 16) + \"...\" : \"-\",\n createTime: result.createTime || \"-\",\n total: result.total\n ? `${result.total.units || \"0\"}.${String(result.total.nanos || 0)\n .padStart(9, \"0\")\n .slice(0, 2)} ${result.total.currencyCode}`\n : \"-\",\n lineItems: result.lineItems?.length || 0,\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n orders\n .command(\"batch-get\")\n .description(\"Get multiple orders at once\")\n .requiredOption(\"--ids <order-ids>\", \"Comma-separated order IDs (max 1000)\")\n .action(async (options: { ids: 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 orderIds = options.ids\n .split(\",\")\n .map((id) => id.trim())\n .filter(Boolean);\n\n const result = await batchGetOrders(client, packageName, orderIds);\n if (format !== \"json\") {\n if (result.length === 0) {\n console.log(\"No orders found.\");\n } else {\n const rows = result.map((o) => ({\n orderId: o.orderId,\n state: o.state,\n createTime: o.createTime || \"-\",\n lineItems: o.lineItems?.length || 0,\n }));\n console.log(formatOutput(rows, format));\n }\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Product purchases V2 (Jun 2025) ---\n const product = purchases.command(\"product\").description(\"Product purchase operations\");\n\n product\n .command(\"get-v2 <token>\")\n .description(\"Get product purchase details (v2 — supports multi-offer OTPs)\")\n .action(async (token: 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 getProductPurchaseV2(client, packageName, token);\n if (format !== \"json\") {\n const row = {\n orderId: result.orderId || \"-\",\n state: result.purchaseStateContext?.purchaseState || \"-\",\n regionCode: result.regionCode || \"-\",\n completionTime: result.purchaseCompletionTime || \"-\",\n acknowledgement: result.acknowledgementState || \"-\",\n lineItems: result.productLineItem?.length || 0,\n };\n console.log(formatOutput(row, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n // --- Subscription V2 cancel/defer (Sep 2025 / Jan 2026) ---\n // Added to existing `sub` group alongside v1 cancel/defer\n\n sub\n .command(\"cancel-v2 <token>\")\n .description(\"Cancel a subscription (v2 -- supports cancellation types)\")\n .option(\n \"--type <cancellationType>\",\n \"USER_REQUESTED_STOP_RENEWALS (default) or DEVELOPER_REQUESTED_STOP_PAYMENTS\",\n )\n .action(async (token: string, options: { type?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription cancel-v2\",\n action: \"cancel\",\n target: token.slice(0, 16) + \"...\",\n details: { cancellationType: options.type },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Cancel subscription (token: ${token.slice(0, 16)}...)? This cannot be undone.`,\n program,\n );\n\n const client = await getClient(config);\n\n await cancelSubscriptionV2(client, packageName, token, options.type);\n console.log(\"Subscription cancelled.\");\n });\n\n sub\n .command(\"defer-v2 <token>\")\n .description(\"Defer a subscription renewal (v2 -- supports add-on subscriptions)\")\n .requiredOption(\"--duration <seconds>\", \"Duration to defer by (e.g. '2592000s' for 30 days)\")\n .option(\"--etag <etag>\", \"Subscription etag (fetched automatically if omitted)\")\n .action(async (token: string, options: { duration: string; etag?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Defer subscription renewal by ${options.duration}?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"purchases subscription defer-v2\",\n action: \"defer\",\n target: token.slice(0, 16) + \"...\",\n details: { deferDuration: options.duration },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deferSubscriptionV2(\n client,\n packageName,\n token,\n options.duration,\n options.etag,\n );\n for (const item of result.itemExpiryTimeDetails) {\n console.log(`${item.productId}: new expiry ${item.expiryTime}`);\n }\n });\n}\n"],"mappings":"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","names":["purchases"]}