@gpc-cli/cli 0.1.3 → 0.9.4

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 (73) hide show
  1. package/README.md +21 -21
  2. package/dist/{apps-BBYNHB2H.js → apps-TZG5GEDW.js} +9 -7
  3. package/dist/apps-TZG5GEDW.js.map +1 -0
  4. package/dist/{auth-T7IDSMVX.js → auth-CIITFC3C.js} +4 -2
  5. package/dist/auth-CIITFC3C.js.map +1 -0
  6. package/dist/bin.js +1 -1
  7. package/dist/bin.js.map +1 -1
  8. package/dist/{chunk-IVVT73IP.js → chunk-22DW4R5W.js} +31 -26
  9. package/dist/chunk-22DW4R5W.js.map +1 -0
  10. package/dist/{chunk-4QV4WD3F.js → chunk-Q7KVGI46.js} +9 -7
  11. package/dist/chunk-Q7KVGI46.js.map +1 -0
  12. package/dist/{chunk-QMKZYXDJ.js → chunk-Y3QZDAKS.js} +2 -2
  13. package/dist/chunk-Y3QZDAKS.js.map +1 -0
  14. package/dist/{completion-U44CGHRH.js → completion-IHVLP7OK.js} +1 -1
  15. package/dist/completion-IHVLP7OK.js.map +1 -0
  16. package/dist/{config-K7UJKIXT.js → config-7QKUVNZZ.js} +8 -4
  17. package/dist/config-7QKUVNZZ.js.map +1 -0
  18. package/dist/{doctor-VDDUPTIM.js → doctor-KVP7PGZU.js} +5 -3
  19. package/dist/doctor-KVP7PGZU.js.map +1 -0
  20. package/dist/{iap-QIV4CXKZ.js → iap-Z365AMDD.js} +37 -25
  21. package/dist/iap-Z365AMDD.js.map +1 -0
  22. package/dist/index.js +1 -1
  23. package/dist/{listings-PF5FDXKQ.js → listings-U3T6NFVH.js} +128 -68
  24. package/dist/listings-U3T6NFVH.js.map +1 -0
  25. package/dist/{pricing-S4SB5FXJ.js → pricing-LXIRB4R7.js} +21 -15
  26. package/dist/pricing-LXIRB4R7.js.map +1 -0
  27. package/dist/{prompt-VP5LURRP.js → prompt-ASDQX6LZ.js} +2 -2
  28. package/dist/{publish-3BAIN4NQ.js → publish-HKOJVZ23.js} +27 -16
  29. package/dist/publish-HKOJVZ23.js.map +1 -0
  30. package/dist/{purchases-E6A2T5WQ.js → purchases-ZQ7FXEZQ.js} +84 -49
  31. package/dist/purchases-ZQ7FXEZQ.js.map +1 -0
  32. package/dist/{releases-464IMEEF.js → releases-IZJJYTNZ.js} +103 -51
  33. package/dist/releases-IZJJYTNZ.js.map +1 -0
  34. package/dist/{reports-3YAD4U4F.js → reports-43OVCCU3.js} +83 -29
  35. package/dist/reports-43OVCCU3.js.map +1 -0
  36. package/dist/{reviews-2CLM53E3.js → reviews-T3SRAZLW.js} +25 -16
  37. package/dist/reviews-T3SRAZLW.js.map +1 -0
  38. package/dist/{status-M7U3YNMU.js → status-TBPVS7YR.js} +5 -3
  39. package/dist/status-TBPVS7YR.js.map +1 -0
  40. package/dist/{subscriptions-PUHH4FBB.js → subscriptions-UJUX3ELS.js} +201 -130
  41. package/dist/subscriptions-UJUX3ELS.js.map +1 -0
  42. package/dist/{testers-WWZMLB7J.js → testers-YNOGFHUR.js} +81 -44
  43. package/dist/testers-YNOGFHUR.js.map +1 -0
  44. package/dist/{tracks-427E34S3.js → tracks-HMJ3F55N.js} +5 -3
  45. package/dist/tracks-HMJ3F55N.js.map +1 -0
  46. package/dist/{users-E5Y5HI6K.js → users-GRQTY6HY.js} +48 -28
  47. package/dist/users-GRQTY6HY.js.map +1 -0
  48. package/dist/{vitals-YMZMUPNA.js → vitals-VP2GKG3G.js} +23 -9
  49. package/dist/vitals-VP2GKG3G.js.map +1 -0
  50. package/package.json +6 -6
  51. package/dist/apps-BBYNHB2H.js.map +0 -1
  52. package/dist/auth-T7IDSMVX.js.map +0 -1
  53. package/dist/chunk-4QV4WD3F.js.map +0 -1
  54. package/dist/chunk-IVVT73IP.js.map +0 -1
  55. package/dist/chunk-QMKZYXDJ.js.map +0 -1
  56. package/dist/completion-U44CGHRH.js.map +0 -1
  57. package/dist/config-K7UJKIXT.js.map +0 -1
  58. package/dist/doctor-VDDUPTIM.js.map +0 -1
  59. package/dist/iap-QIV4CXKZ.js.map +0 -1
  60. package/dist/listings-PF5FDXKQ.js.map +0 -1
  61. package/dist/pricing-S4SB5FXJ.js.map +0 -1
  62. package/dist/publish-3BAIN4NQ.js.map +0 -1
  63. package/dist/purchases-E6A2T5WQ.js.map +0 -1
  64. package/dist/releases-464IMEEF.js.map +0 -1
  65. package/dist/reports-3YAD4U4F.js.map +0 -1
  66. package/dist/reviews-2CLM53E3.js.map +0 -1
  67. package/dist/status-M7U3YNMU.js.map +0 -1
  68. package/dist/subscriptions-PUHH4FBB.js.map +0 -1
  69. package/dist/testers-WWZMLB7J.js.map +0 -1
  70. package/dist/tracks-427E34S3.js.map +0 -1
  71. package/dist/users-E5Y5HI6K.js.map +0 -1
  72. package/dist/vitals-YMZMUPNA.js.map +0 -1
  73. /package/dist/{prompt-VP5LURRP.js.map → prompt-ASDQX6LZ.js.map} +0 -0
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  isDryRun,
4
4
  printDryRun
5
- } from "./chunk-QMKZYXDJ.js";
5
+ } from "./chunk-Y3QZDAKS.js";
6
6
  import {
7
7
  isInteractive,
8
8
  promptInput,
9
9
  promptSelect
10
- } from "./chunk-4QV4WD3F.js";
10
+ } from "./chunk-Q7KVGI46.js";
11
11
 
12
12
  // src/commands/publish.ts
13
13
  import { appendFile } from "fs/promises";
@@ -31,7 +31,7 @@ function registerPublishCommand(program) {
31
31
  process.exit(2);
32
32
  }
33
33
  const config = await loadConfig();
34
- const packageName = resolvePackageName(program.opts().app, config);
34
+ const packageName = resolvePackageName(program.opts()["app"], config);
35
35
  const format = detectOutputFormat();
36
36
  if (isInteractive(program)) {
37
37
  if (!options.track || options.track === "internal") {
@@ -39,7 +39,10 @@ function registerPublishCommand(program) {
39
39
  options.track = await promptSelect("Select track:", tracks, "internal");
40
40
  }
41
41
  if (!options.rollout && options.track === "production") {
42
- const rolloutStr = await promptInput("Staged rollout percentage (1-100, blank for full)", "100");
42
+ const rolloutStr = await promptInput(
43
+ "Staged rollout percentage (1-100, blank for full)",
44
+ "100"
45
+ );
43
46
  if (rolloutStr && rolloutStr !== "100") {
44
47
  options.rollout = rolloutStr;
45
48
  }
@@ -50,19 +53,27 @@ function registerPublishCommand(program) {
50
53
  }
51
54
  }
52
55
  if (isDryRun(program)) {
53
- printDryRun({
54
- command: "publish",
55
- action: "publish",
56
- target: file,
57
- details: { track: options.track, rollout: options.rollout }
58
- }, format, formatOutput);
56
+ printDryRun(
57
+ {
58
+ command: "publish",
59
+ action: "publish",
60
+ target: file,
61
+ details: { track: options.track, rollout: options.rollout }
62
+ },
63
+ format,
64
+ formatOutput
65
+ );
59
66
  return;
60
67
  }
61
- const auditEntry = createAuditEntry("publish", {
62
- file,
63
- track: options.track,
64
- rollout: options.rollout
65
- }, packageName);
68
+ const auditEntry = createAuditEntry(
69
+ "publish",
70
+ {
71
+ file,
72
+ track: options.track,
73
+ rollout: options.rollout
74
+ },
75
+ packageName
76
+ );
66
77
  let onRetry;
67
78
  if (options.retryLog) {
68
79
  onRetry = (entry) => {
@@ -111,4 +122,4 @@ function registerPublishCommand(program) {
111
122
  export {
112
123
  registerPublishCommand
113
124
  };
114
- //# sourceMappingURL=publish-3BAIN4NQ.js.map
125
+ //# sourceMappingURL=publish-HKOJVZ23.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/publish.ts"],"sourcesContent":["import { appendFile } from \"node:fs/promises\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport type { Command } from \"commander\";\nimport { loadConfig, getCacheDir } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport type { RetryLogEntry } from \"@gpc-cli/api\";\nimport { publish, writeAuditLog, createAuditEntry } from \"@gpc-cli/core\";\nimport { detectOutputFormat, formatOutput } from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, promptSelect, promptInput } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nexport function registerPublishCommand(program: Command): void {\n program\n .command(\"publish <file>\")\n .description(\"Validate, upload, and release in one step\")\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(\"--notes-dir <dir>\", \"Read release notes from directory (<dir>/<lang>.txt)\")\n .option(\"--name <name>\", \"Release name\")\n .option(\"--mapping <file>\", \"ProGuard/R8 mapping file for deobfuscation\")\n .option(\"--retry-log <path>\", \"Write retry log entries to file (JSONL)\")\n .action(async (file: string, options) => {\n if (options.notes && options.notesDir) {\n console.error(\"Error: Cannot use both --notes and --notes-dir\");\n process.exit(2);\n }\n\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\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 (isDryRun(program)) {\n printDryRun(\n {\n command: \"publish\",\n action: \"publish\",\n target: file,\n details: { track: options.track, rollout: options.rollout },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const auditEntry = createAuditEntry(\n \"publish\",\n {\n file,\n track: options.track,\n rollout: options.rollout,\n },\n packageName,\n );\n\n let onRetry: ((entry: RetryLogEntry) => void) | undefined;\n if (options.retryLog) {\n onRetry = (entry: RetryLogEntry) => {\n appendFile(options.retryLog, JSON.stringify(entry) + \"\\n\").catch(() => {});\n };\n }\n\n const auth = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n const client = createApiClient({ auth, onRetry });\n\n try {\n const result = await publish(client, packageName, file, {\n track: options.track,\n rolloutPercent: options.rollout ? Number(options.rollout) : undefined,\n notes: options.notes,\n notesDir: options.notesDir,\n releaseName: options.name,\n mappingFile: options.mapping,\n });\n\n if (!result.upload) {\n console.error(\"Validation failed:\");\n for (const check of result.validation.checks) {\n const icon = check.passed ? \"✓\" : \"✗\";\n console.error(` ${icon} ${check.name}: ${check.message}`);\n }\n auditEntry.success = false;\n auditEntry.error = \"Validation failed\";\n process.exit(1);\n }\n\n console.log(formatOutput(result, format));\n auditEntry.success = true;\n } catch (error) {\n auditEntry.success = false;\n auditEntry.error = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n } finally {\n auditEntry.durationMs = Date.now() - new Date(auditEntry.timestamp).getTime();\n writeAuditLog(auditEntry).catch(() => {});\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  isDryRun,
4
4
  printDryRun
5
- } from "./chunk-QMKZYXDJ.js";
5
+ } from "./chunk-Y3QZDAKS.js";
6
6
  import {
7
7
  isInteractive,
8
8
  requireConfirm,
9
9
  requireOption
10
- } from "./chunk-4QV4WD3F.js";
10
+ } from "./chunk-Q7KVGI46.js";
11
11
 
12
12
  // src/commands/purchases.ts
13
13
  import { loadConfig } from "@gpc-cli/config";
@@ -42,7 +42,7 @@ function registerPurchasesCommands(program) {
42
42
  const purchases = program.command("purchases").description("Manage purchases and orders");
43
43
  purchases.command("get <product-id> <token>").description("Get a product purchase").action(async (productId, token) => {
44
44
  const config = await loadConfig();
45
- const packageName = resolvePackageName(program.opts().app, config);
45
+ const packageName = resolvePackageName(program.opts()["app"], config);
46
46
  const client = await getClient(config);
47
47
  const format = detectOutputFormat();
48
48
  try {
@@ -55,15 +55,19 @@ function registerPurchasesCommands(program) {
55
55
  });
56
56
  purchases.command("acknowledge <product-id> <token>").description("Acknowledge a product purchase").option("--payload <text>", "Developer payload").action(async (productId, token, options) => {
57
57
  const config = await loadConfig();
58
- const packageName = resolvePackageName(program.opts().app, config);
58
+ const packageName = resolvePackageName(program.opts()["app"], config);
59
59
  if (isDryRun(program)) {
60
60
  const format = detectOutputFormat();
61
- printDryRun({
62
- command: "purchases acknowledge",
63
- action: "acknowledge",
64
- target: `${productId}/${token}`,
65
- details: { payload: options.payload }
66
- }, format, formatOutput);
61
+ printDryRun(
62
+ {
63
+ command: "purchases acknowledge",
64
+ action: "acknowledge",
65
+ target: `${productId}/${token}`,
66
+ details: { payload: options.payload }
67
+ },
68
+ format,
69
+ formatOutput
70
+ );
67
71
  return;
68
72
  }
69
73
  const client = await getClient(config);
@@ -77,14 +81,18 @@ function registerPurchasesCommands(program) {
77
81
  });
78
82
  purchases.command("consume <product-id> <token>").description("Consume a product purchase").action(async (productId, token) => {
79
83
  const config = await loadConfig();
80
- const packageName = resolvePackageName(program.opts().app, config);
84
+ const packageName = resolvePackageName(program.opts()["app"], config);
81
85
  if (isDryRun(program)) {
82
86
  const format = detectOutputFormat();
83
- printDryRun({
84
- command: "purchases consume",
85
- action: "consume",
86
- target: `${productId}/${token}`
87
- }, format, formatOutput);
87
+ printDryRun(
88
+ {
89
+ command: "purchases consume",
90
+ action: "consume",
91
+ target: `${productId}/${token}`
92
+ },
93
+ format,
94
+ formatOutput
95
+ );
88
96
  return;
89
97
  }
90
98
  const client = await getClient(config);
@@ -99,7 +107,7 @@ function registerPurchasesCommands(program) {
99
107
  const sub = purchases.command("subscription").description("Manage subscription purchases");
100
108
  sub.command("get <token>").description("Get a subscription purchase (v2)").action(async (token) => {
101
109
  const config = await loadConfig();
102
- const packageName = resolvePackageName(program.opts().app, config);
110
+ const packageName = resolvePackageName(program.opts()["app"], config);
103
111
  const client = await getClient(config);
104
112
  const format = detectOutputFormat();
105
113
  try {
@@ -112,14 +120,18 @@ function registerPurchasesCommands(program) {
112
120
  });
113
121
  sub.command("cancel <subscription-id> <token>").description("Cancel a subscription (v1)").action(async (subscriptionId, token) => {
114
122
  const config = await loadConfig();
115
- const packageName = resolvePackageName(program.opts().app, config);
123
+ const packageName = resolvePackageName(program.opts()["app"], config);
116
124
  if (isDryRun(program)) {
117
125
  const format = detectOutputFormat();
118
- printDryRun({
119
- command: "purchases subscription cancel",
120
- action: "cancel subscription",
121
- target: `${subscriptionId}/${token}`
122
- }, format, formatOutput);
126
+ printDryRun(
127
+ {
128
+ command: "purchases subscription cancel",
129
+ action: "cancel subscription",
130
+ target: `${subscriptionId}/${token}`
131
+ },
132
+ format,
133
+ formatOutput
134
+ );
123
135
  return;
124
136
  }
125
137
  const client = await getClient(config);
@@ -133,24 +145,39 @@ function registerPurchasesCommands(program) {
133
145
  });
134
146
  sub.command("defer <subscription-id> <token>").description("Defer a subscription expiry").option("--expiry <iso-date>", "Desired new expiry date (ISO 8601)").action(async (subscriptionId, token, options) => {
135
147
  const config = await loadConfig();
136
- const packageName = resolvePackageName(program.opts().app, config);
148
+ const packageName = resolvePackageName(program.opts()["app"], config);
137
149
  const format = detectOutputFormat();
138
150
  const interactive = isInteractive(program);
139
- options.expiry = await requireOption("expiry", options.expiry, {
140
- message: "New expiry date (ISO 8601, e.g. 2026-12-31T23:59:59Z):"
141
- }, interactive);
151
+ options.expiry = await requireOption(
152
+ "expiry",
153
+ options.expiry,
154
+ {
155
+ message: "New expiry date (ISO 8601, e.g. 2026-12-31T23:59:59Z):"
156
+ },
157
+ interactive
158
+ );
142
159
  if (isDryRun(program)) {
143
- printDryRun({
144
- command: "purchases subscription defer",
145
- action: "defer subscription",
146
- target: `${subscriptionId}/${token}`,
147
- details: { expiry: options.expiry }
148
- }, format, formatOutput);
160
+ printDryRun(
161
+ {
162
+ command: "purchases subscription defer",
163
+ action: "defer subscription",
164
+ target: `${subscriptionId}/${token}`,
165
+ details: { expiry: options.expiry }
166
+ },
167
+ format,
168
+ formatOutput
169
+ );
149
170
  return;
150
171
  }
151
172
  const client = await getClient(config);
152
173
  try {
153
- const result = await deferSubscriptionPurchase(client, packageName, subscriptionId, token, options.expiry);
174
+ const result = await deferSubscriptionPurchase(
175
+ client,
176
+ packageName,
177
+ subscriptionId,
178
+ token,
179
+ options.expiry
180
+ );
154
181
  console.log(formatOutput(result, format));
155
182
  } catch (error) {
156
183
  console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
@@ -159,14 +186,18 @@ function registerPurchasesCommands(program) {
159
186
  });
160
187
  sub.command("revoke <token>").description("Revoke a subscription (v2)").action(async (token) => {
161
188
  const config = await loadConfig();
162
- const packageName = resolvePackageName(program.opts().app, config);
189
+ const packageName = resolvePackageName(program.opts()["app"], config);
163
190
  if (isDryRun(program)) {
164
191
  const format = detectOutputFormat();
165
- printDryRun({
166
- command: "purchases subscription revoke",
167
- action: "revoke subscription",
168
- target: token
169
- }, format, formatOutput);
192
+ printDryRun(
193
+ {
194
+ command: "purchases subscription revoke",
195
+ action: "revoke subscription",
196
+ target: token
197
+ },
198
+ format,
199
+ formatOutput
200
+ );
170
201
  return;
171
202
  }
172
203
  const client = await getClient(config);
@@ -180,7 +211,7 @@ function registerPurchasesCommands(program) {
180
211
  });
181
212
  purchases.command("voided").description("List voided purchases").option("--start-time <time>", "Start time (milliseconds)").option("--end-time <time>", "End time (milliseconds)").option("--max-results <n>", "Maximum results per page", parseInt).option("--limit <n>", "Maximum total results", parseInt).option("--next-page <token>", "Resume from page token").action(async (options) => {
182
213
  const config = await loadConfig();
183
- const packageName = resolvePackageName(program.opts().app, config);
214
+ const packageName = resolvePackageName(program.opts()["app"], config);
184
215
  const client = await getClient(config);
185
216
  const format = detectOutputFormat();
186
217
  try {
@@ -200,16 +231,20 @@ function registerPurchasesCommands(program) {
200
231
  const orders = purchases.command("orders").description("Manage orders");
201
232
  orders.command("refund <order-id>").description("Refund an order").option("--full-refund", "Full refund").option("--prorated-refund", "Prorated refund").action(async (orderId, options) => {
202
233
  const config = await loadConfig();
203
- const packageName = resolvePackageName(program.opts().app, config);
234
+ const packageName = resolvePackageName(program.opts()["app"], config);
204
235
  await requireConfirm(`Refund order "${orderId}"?`, program);
205
236
  if (isDryRun(program)) {
206
237
  const format = detectOutputFormat();
207
- printDryRun({
208
- command: "purchases orders refund",
209
- action: "refund",
210
- target: orderId,
211
- details: { fullRefund: options.fullRefund, proratedRefund: options.proratedRefund }
212
- }, format, formatOutput);
238
+ printDryRun(
239
+ {
240
+ command: "purchases orders refund",
241
+ action: "refund",
242
+ target: orderId,
243
+ details: { fullRefund: options.fullRefund, proratedRefund: options.proratedRefund }
244
+ },
245
+ format,
246
+ formatOutput
247
+ );
213
248
  return;
214
249
  }
215
250
  const client = await getClient(config);
@@ -228,4 +263,4 @@ function registerPurchasesCommands(program) {
228
263
  export {
229
264
  registerPurchasesCommands
230
265
  };
231
- //# sourceMappingURL=purchases-E6A2T5WQ.js.map
266
+ //# sourceMappingURL=purchases-ZQ7FXEZQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/purchases.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n getProductPurchase,\n acknowledgeProductPurchase,\n consumeProductPurchase,\n getSubscriptionPurchase,\n cancelSubscriptionPurchase,\n deferSubscriptionPurchase,\n revokeSubscriptionPurchase,\n listVoidedPurchases,\n refundOrder,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth });\n}\n\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 = detectOutputFormat();\n\n try {\n const result = await getProductPurchase(client, packageName, productId, token);\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n 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 = detectOutputFormat();\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 try {\n await acknowledgeProductPurchase(client, packageName, productId, token, options.payload);\n console.log(`Purchase acknowledged.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\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 = detectOutputFormat();\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 try {\n await consumeProductPurchase(client, packageName, productId, token);\n console.log(`Purchase consumed.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\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 = detectOutputFormat();\n\n try {\n const result = await getSubscriptionPurchase(client, packageName, token);\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n 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 = detectOutputFormat();\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 const client = await getClient(config);\n\n try {\n await cancelSubscriptionPurchase(client, packageName, subscriptionId, token);\n console.log(`Subscription cancelled.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\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 = detectOutputFormat();\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 try {\n const result = await deferSubscriptionPurchase(\n client,\n packageName,\n subscriptionId,\n token,\n options.expiry,\n );\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n sub\n .command(\"revoke <token>\")\n .description(\"Revoke a subscription (v2)\")\n .action(async (token: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n if (isDryRun(program)) {\n const format = detectOutputFormat();\n printDryRun(\n {\n command: \"purchases subscription revoke\",\n action: \"revoke subscription\",\n target: token,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await revokeSubscriptionPurchase(client, packageName, token);\n console.log(`Subscription revoked.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\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(\"--max-results <n>\", \"Maximum results per page\", parseInt)\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 = detectOutputFormat();\n\n try {\n const result = await listVoidedPurchases(client, packageName, {\n startTime: options.startTime,\n endTime: options.endTime,\n maxResults: options.maxResults,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // --- 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(\"--full-refund\", \"Full refund\")\n .option(\"--prorated-refund\", \"Prorated refund\")\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 = detectOutputFormat();\n printDryRun(\n {\n command: \"purchases orders refund\",\n action: \"refund\",\n target: orderId,\n details: { fullRefund: options.fullRefund, proratedRefund: options.proratedRefund },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await refundOrder(client, packageName, orderId, {\n fullRefund: options.fullRefund,\n proratedRefund: options.proratedRefund,\n });\n console.log(`Order ${orderId} refunded.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -2,20 +2,28 @@
2
2
  import {
3
3
  isDryRun,
4
4
  printDryRun
5
- } from "./chunk-QMKZYXDJ.js";
5
+ } from "./chunk-Y3QZDAKS.js";
6
6
  import {
7
7
  isInteractive,
8
8
  promptInput,
9
9
  promptSelect,
10
10
  requireOption
11
- } from "./chunk-4QV4WD3F.js";
11
+ } from "./chunk-Q7KVGI46.js";
12
12
 
13
13
  // src/commands/releases.ts
14
14
  import { appendFile } from "fs/promises";
15
15
  import { loadConfig } from "@gpc-cli/config";
16
16
  import { resolveAuth } from "@gpc-cli/auth";
17
17
  import { createApiClient } from "@gpc-cli/api";
18
- import { uploadRelease, getReleasesStatus, promoteRelease, updateRollout, readReleaseNotesFromDir, writeAuditLog, createAuditEntry } from "@gpc-cli/core";
18
+ import {
19
+ uploadRelease,
20
+ getReleasesStatus,
21
+ promoteRelease,
22
+ updateRollout,
23
+ readReleaseNotesFromDir,
24
+ writeAuditLog,
25
+ createAuditEntry
26
+ } from "@gpc-cli/core";
19
27
  import { detectOutputFormat, formatOutput } from "@gpc-cli/core";
20
28
  function resolvePackageName(packageArg, config) {
21
29
  const name = packageArg || config.app;
@@ -45,7 +53,7 @@ function registerReleasesCommands(program) {
45
53
  process.exit(2);
46
54
  }
47
55
  const config = await loadConfig();
48
- const packageName = resolvePackageName(program.opts().app, config);
56
+ const packageName = resolvePackageName(program.opts()["app"], config);
49
57
  const format = detectOutputFormat();
50
58
  if (isInteractive(program)) {
51
59
  if (!options.track || options.track === "internal") {
@@ -53,7 +61,10 @@ function registerReleasesCommands(program) {
53
61
  options.track = await promptSelect("Select track:", tracks, "internal");
54
62
  }
55
63
  if (!options.rollout && options.track === "production") {
56
- const rolloutStr = await promptInput("Staged rollout percentage (1-100, blank for full)", "100");
64
+ const rolloutStr = await promptInput(
65
+ "Staged rollout percentage (1-100, blank for full)",
66
+ "100"
67
+ );
57
68
  if (rolloutStr && rolloutStr !== "100") {
58
69
  options.rollout = rolloutStr;
59
70
  }
@@ -64,19 +75,27 @@ function registerReleasesCommands(program) {
64
75
  }
65
76
  }
66
77
  if (isDryRun(program)) {
67
- printDryRun({
68
- command: "releases upload",
69
- action: "upload",
70
- target: file,
71
- details: { track: options.track, rollout: options.rollout }
72
- }, format, formatOutput);
78
+ printDryRun(
79
+ {
80
+ command: "releases upload",
81
+ action: "upload",
82
+ target: file,
83
+ details: { track: options.track, rollout: options.rollout }
84
+ },
85
+ format,
86
+ formatOutput
87
+ );
73
88
  return;
74
89
  }
75
- const auditEntry = createAuditEntry("releases upload", {
76
- file,
77
- track: options.track,
78
- rollout: options.rollout
79
- }, packageName);
90
+ const auditEntry = createAuditEntry(
91
+ "releases upload",
92
+ {
93
+ file,
94
+ track: options.track,
95
+ rollout: options.rollout
96
+ },
97
+ packageName
98
+ );
80
99
  const client = await getClient(config, options.retryLog);
81
100
  try {
82
101
  let releaseNotes;
@@ -107,7 +126,7 @@ function registerReleasesCommands(program) {
107
126
  });
108
127
  releases.command("status").description("Show current release status across tracks").option("--track <track>", "Filter by track").action(async (options) => {
109
128
  const config = await loadConfig();
110
- const packageName = resolvePackageName(program.opts().app, config);
129
+ const packageName = resolvePackageName(program.opts()["app"], config);
111
130
  const client = await getClient(config);
112
131
  const format = detectOutputFormat();
113
132
  try {
@@ -120,25 +139,39 @@ function registerReleasesCommands(program) {
120
139
  });
121
140
  releases.command("promote").description("Promote a release from one track to another").option("--from <track>", "Source track").option("--to <track>", "Target track").option("--rollout <percent>", "Staged rollout percentage").option("--notes <text>", "Release notes").action(async (options) => {
122
141
  const config = await loadConfig();
123
- const packageName = resolvePackageName(program.opts().app, config);
142
+ const packageName = resolvePackageName(program.opts()["app"], config);
124
143
  const format = detectOutputFormat();
125
144
  const interactive = isInteractive(program);
126
145
  const tracks = ["internal", "alpha", "beta", "production"];
127
- options.from = await requireOption("from", options.from, {
128
- message: "Source track:",
129
- choices: tracks
130
- }, interactive);
131
- options.to = await requireOption("to", options.to, {
132
- message: "Target track:",
133
- choices: tracks.filter((t) => t !== options.from)
134
- }, interactive);
146
+ options.from = await requireOption(
147
+ "from",
148
+ options.from,
149
+ {
150
+ message: "Source track:",
151
+ choices: tracks
152
+ },
153
+ interactive
154
+ );
155
+ options.to = await requireOption(
156
+ "to",
157
+ options.to,
158
+ {
159
+ message: "Target track:",
160
+ choices: tracks.filter((t) => t !== options.from)
161
+ },
162
+ interactive
163
+ );
135
164
  if (isDryRun(program)) {
136
- printDryRun({
137
- command: "releases promote",
138
- action: "promote",
139
- target: `${options.from} \u2192 ${options.to}`,
140
- details: { rollout: options.rollout }
141
- }, format, formatOutput);
165
+ printDryRun(
166
+ {
167
+ command: "releases promote",
168
+ action: "promote",
169
+ target: `${options.from} \u2192 ${options.to}`,
170
+ details: { rollout: options.rollout }
171
+ },
172
+ format,
173
+ formatOutput
174
+ );
142
175
  return;
143
176
  }
144
177
  const client = await getClient(config);
@@ -161,26 +194,40 @@ function registerReleasesCommands(program) {
161
194
  }
162
195
  cmd.action(async (options) => {
163
196
  const config = await loadConfig();
164
- const packageName = resolvePackageName(program.opts().app, config);
197
+ const packageName = resolvePackageName(program.opts()["app"], config);
165
198
  const format = detectOutputFormat();
166
199
  const interactive = isInteractive(program);
167
200
  const tracks = ["internal", "alpha", "beta", "production"];
168
- options.track = await requireOption("track", options.track, {
169
- message: "Track:",
170
- choices: tracks
171
- }, interactive);
201
+ options.track = await requireOption(
202
+ "track",
203
+ options.track,
204
+ {
205
+ message: "Track:",
206
+ choices: tracks
207
+ },
208
+ interactive
209
+ );
172
210
  if (action === "increase") {
173
- options.to = await requireOption("to", options.to, {
174
- message: "New rollout percentage (1-100):"
175
- }, interactive);
211
+ options.to = await requireOption(
212
+ "to",
213
+ options.to,
214
+ {
215
+ message: "New rollout percentage (1-100):"
216
+ },
217
+ interactive
218
+ );
176
219
  }
177
220
  if (isDryRun(program)) {
178
- printDryRun({
179
- command: `releases rollout ${action}`,
180
- action,
181
- target: options.track,
182
- details: { percentage: options.to }
183
- }, format, formatOutput);
221
+ printDryRun(
222
+ {
223
+ command: `releases rollout ${action}`,
224
+ action,
225
+ target: options.track,
226
+ details: { percentage: options.to }
227
+ },
228
+ format,
229
+ formatOutput
230
+ );
184
231
  return;
185
232
  }
186
233
  const client = await getClient(config);
@@ -206,10 +253,15 @@ function registerReleasesCommands(program) {
206
253
  }
207
254
  const interactive = isInteractive(program);
208
255
  const tracks = ["internal", "alpha", "beta", "production"];
209
- options.track = await requireOption("track", options.track, {
210
- message: "Track:",
211
- choices: tracks
212
- }, interactive);
256
+ options.track = await requireOption(
257
+ "track",
258
+ options.track,
259
+ {
260
+ message: "Track:",
261
+ choices: tracks
262
+ },
263
+ interactive
264
+ );
213
265
  let notesText = options.notes;
214
266
  if (options.file) {
215
267
  const { readFile } = await import("fs/promises");
@@ -228,4 +280,4 @@ function registerReleasesCommands(program) {
228
280
  export {
229
281
  registerReleasesCommands
230
282
  };
231
- //# sourceMappingURL=releases-464IMEEF.js.map
283
+ //# sourceMappingURL=releases-IZJJYTNZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/releases.ts"],"sourcesContent":["import { appendFile } from \"node:fs/promises\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport type { RetryLogEntry } from \"@gpc-cli/api\";\nimport {\n uploadRelease,\n getReleasesStatus,\n promoteRelease,\n updateRollout,\n readReleaseNotesFromDir,\n writeAuditLog,\n createAuditEntry,\n} from \"@gpc-cli/core\";\nimport { detectOutputFormat, formatOutput } from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, promptSelect, promptInput, requireOption } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\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) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth, onRetry: createRetryLogger(retryLogPath) });\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(\"--retry-log <path>\", \"Write retry log entries to file (JSONL)\")\n .action(async (file: string, options) => {\n if (options.notes && options.notesDir) {\n console.error(\"Error: Cannot use both --notes and --notes-dir\");\n process.exit(2);\n }\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\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 (isDryRun(program)) {\n printDryRun(\n {\n command: \"releases upload\",\n action: \"upload\",\n target: file,\n details: { track: options.track, rollout: options.rollout },\n },\n format,\n formatOutput,\n );\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 client = await getClient(config, options.retryLog);\n\n try {\n let releaseNotes: { language: string; text: string }[] | undefined;\n if (options.notesDir) {\n releaseNotes = await readReleaseNotesFromDir(options.notesDir);\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 userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes,\n releaseName: options.name,\n mappingFile: options.mapping,\n });\n console.log(formatOutput(result, format));\n auditEntry.success = true;\n } catch (error) {\n auditEntry.success = false;\n auditEntry.error = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\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 .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const statuses = await getReleasesStatus(client, packageName, options.track);\n console.log(formatOutput(statuses, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\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 .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\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 (isDryRun(program)) {\n printDryRun(\n {\n command: \"releases promote\",\n action: \"promote\",\n target: `${options.from} → ${options.to}`,\n details: { rollout: options.rollout },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await promoteRelease(client, packageName, options.from, options.to, {\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes: options.notes ? [{ language: \"en-US\", text: options.notes }] : undefined,\n });\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // 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 }\n\n cmd.action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = detectOutputFormat();\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 (isDryRun(program)) {\n printDryRun(\n {\n command: `releases rollout ${action}`,\n action: action,\n target: options.track,\n details: { percentage: options.to },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await updateRollout(\n client,\n packageName,\n options.track,\n action,\n options.to ? Number(options.to) / 100 : undefined,\n );\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n }\n\n // Release notes\n releases\n .command(\"notes\")\n .description(\"Set release notes\")\n .argument(\"<action>\", \"Action: 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 console.error(\"Usage: gpc releases notes set --track <track> --notes <text>\");\n process.exit(2);\n }\n\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 let notesText = options.notes;\n if (options.file) {\n const { readFile } = await import(\"node:fs/promises\");\n notesText = await readFile(options.file, \"utf-8\");\n }\n\n if (!notesText && interactive) {\n notesText = await promptInput(\"Release notes text:\");\n }\n\n if (!notesText) {\n console.error(\"Provide --notes <text> or --file <path>\");\n process.exit(2);\n }\n\n console.log(`Release notes set for ${options.track} (${options.lang})`);\n });\n}\n"],"mappings":"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","names":[]}