@gpc-cli/cli 0.9.45 → 0.9.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{anomalies-NU2IN2GJ.js → anomalies-UDE4NGHJ.js} +19 -24
- package/dist/anomalies-UDE4NGHJ.js.map +1 -0
- package/dist/{apps-J2446UDA.js → apps-FKD3ZG5X.js} +31 -35
- package/dist/apps-FKD3ZG5X.js.map +1 -0
- package/dist/{audit-N2CRHWUN.js → audit-JASSHRWN.js} +47 -62
- package/dist/audit-JASSHRWN.js.map +1 -0
- package/dist/{auth-XGSTT5G5.js → auth-OTA3SV3J.js} +145 -103
- package/dist/auth-OTA3SV3J.js.map +1 -0
- package/dist/bin.js +5 -3
- package/dist/bin.js.map +1 -1
- package/dist/bundle-F7MUVC5J.js +204 -0
- package/dist/bundle-F7MUVC5J.js.map +1 -0
- package/dist/{cache-SLNFRTI2.js → cache-XKPLZYEB.js} +4 -5
- package/dist/cache-XKPLZYEB.js.map +1 -0
- package/dist/changelog-7COFZO7Q.js +48 -0
- package/dist/changelog-7COFZO7Q.js.map +1 -0
- package/dist/{chunk-4O4D5SGL.js → chunk-3SJ6OXCZ.js} +4 -5
- package/dist/chunk-3SJ6OXCZ.js.map +1 -0
- package/dist/{chunk-SEVX56VN.js → chunk-6OWN6S6X.js} +52 -48
- package/dist/{chunk-SEVX56VN.js.map → chunk-6OWN6S6X.js.map} +1 -1
- package/dist/{chunk-U6ZTQ34I.js → chunk-BCBXQC7J.js} +45 -11
- package/dist/chunk-BCBXQC7J.js.map +1 -0
- package/dist/{chunk-AA577WVQ.js → chunk-NQH4G7BI.js} +9 -3
- package/dist/chunk-NQH4G7BI.js.map +1 -0
- package/dist/chunk-SLNJEAMK.js +23 -0
- package/dist/chunk-SLNJEAMK.js.map +1 -0
- package/dist/{chunk-NV75I5VP.js → chunk-YFUBD2XB.js} +10 -8
- package/dist/chunk-YFUBD2XB.js.map +1 -0
- package/dist/{config-BUXPDN7N.js → config-2FTCYEGD.js} +8 -5
- package/dist/config-2FTCYEGD.js.map +1 -0
- package/dist/{data-safety-Q7FTCEWU.js → data-safety-AFMD6MYI.js} +12 -27
- package/dist/data-safety-AFMD6MYI.js.map +1 -0
- package/dist/{device-tiers-MIOQEXYY.js → device-tiers-AQAMUQXI.js} +23 -38
- package/dist/device-tiers-AQAMUQXI.js.map +1 -0
- package/dist/diff-6EO4ID6W.js +91 -0
- package/dist/diff-6EO4ID6W.js.map +1 -0
- package/dist/{docs-7DUXIKA3.js → docs-4D2SJ4LY.js} +4 -3
- package/dist/docs-4D2SJ4LY.js.map +1 -0
- package/dist/doctor-H4X7Q57B.js +691 -0
- package/dist/doctor-H4X7Q57B.js.map +1 -0
- package/dist/{enterprise-7THXNBTC.js → enterprise-7PWXMSUN.js} +11 -21
- package/dist/enterprise-7PWXMSUN.js.map +1 -0
- package/dist/{external-transactions-2GWIMUVM.js → external-transactions-LCZALS3V.js} +12 -28
- package/dist/external-transactions-LCZALS3V.js.map +1 -0
- package/dist/{feedback-DPTO6DUT.js → feedback-XP765TOO.js} +3 -3
- package/dist/{games-BT777WUO.js → games-ZSNGEI7A.js} +17 -32
- package/dist/games-ZSNGEI7A.js.map +1 -0
- package/dist/{generated-apks-RJWTIX7L.js → generated-apks-RX2IUWSF.js} +30 -38
- package/dist/generated-apks-RX2IUWSF.js.map +1 -0
- package/dist/{grants-TKQJ3IER.js → grants-EBPECI26.js} +22 -40
- package/dist/grants-EBPECI26.js.map +1 -0
- package/dist/{iap-ICAEQLK5.js → iap-OUI5YYN4.js} +30 -51
- package/dist/iap-OUI5YYN4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{init-JZ2THPMS.js → init-WSTQTJOD.js} +5 -4
- package/dist/init-WSTQTJOD.js.map +1 -0
- package/dist/{install-skills-OV4HVANW.js → install-skills-6QDUXI5F.js} +5 -6
- package/dist/{install-skills-OV4HVANW.js.map → install-skills-6QDUXI5F.js.map} +1 -1
- package/dist/{internal-sharing-3U2XFHA4.js → internal-sharing-ONNIWIAT.js} +3 -4
- package/dist/{internal-sharing-3U2XFHA4.js.map → internal-sharing-ONNIWIAT.js.map} +1 -1
- package/dist/{listings-77HZW4S5.js → listings-7SGQ4SRX.js} +118 -157
- package/dist/listings-7SGQ4SRX.js.map +1 -0
- package/dist/migrate-ZQCJGQQS.js +138 -0
- package/dist/migrate-ZQCJGQQS.js.map +1 -0
- package/dist/{one-time-products-LHZAXQES.js → one-time-products-MGZTU7OM.js} +65 -120
- package/dist/one-time-products-MGZTU7OM.js.map +1 -0
- package/dist/{preflight-H3HEBYQW.js → preflight-N7ZRG2JI.js} +58 -55
- package/dist/preflight-N7ZRG2JI.js.map +1 -0
- package/dist/{pricing-XQSDTTK5.js → pricing-JJZFICFL.js} +8 -8
- package/dist/{pricing-XQSDTTK5.js.map → pricing-JJZFICFL.js.map} +1 -1
- package/dist/{prompt-BSV22CQZ.js → prompt-GXC2JSLA.js} +2 -2
- package/dist/{publish-Q5ZKEKZ5.js → publish-JPTI4EBT.js} +34 -30
- package/dist/publish-JPTI4EBT.js.map +1 -0
- package/dist/{purchase-options-CKRN4VIW.js → purchase-options-KFWW4JW2.js} +16 -11
- package/dist/purchase-options-KFWW4JW2.js.map +1 -0
- package/dist/{purchases-43AKV6HG.js → purchases-DAWTMXP6.js} +118 -193
- package/dist/purchases-DAWTMXP6.js.map +1 -0
- package/dist/{quickstart-4HB62YEL.js → quickstart-Z5Y3FYJU.js} +5 -3
- package/dist/quickstart-Z5Y3FYJU.js.map +1 -0
- package/dist/{quota-UHIQQYOY.js → quota-MZRWYJGR.js} +5 -15
- package/dist/quota-MZRWYJGR.js.map +1 -0
- package/dist/{recovery-5EV2R476.js → recovery-YE3Z7NIN.js} +32 -61
- package/dist/recovery-YE3Z7NIN.js.map +1 -0
- package/dist/{releases-C2WC2K4E.js → releases-2I3WBULC.js} +184 -185
- package/dist/releases-2I3WBULC.js.map +1 -0
- package/dist/{reports-2YX3RDOS.js → reports-CIB2T3XT.js} +19 -21
- package/dist/reports-CIB2T3XT.js.map +1 -0
- package/dist/reviews-BCCXIQ6C.js +188 -0
- package/dist/reviews-BCCXIQ6C.js.map +1 -0
- package/dist/{status-WHGLODGV.js → status-6LH5W4FU.js} +105 -83
- package/dist/status-6LH5W4FU.js.map +1 -0
- package/dist/{subscriptions-CI3JH3VQ.js → subscriptions-DZP3Y7O7.js} +142 -232
- package/dist/subscriptions-DZP3Y7O7.js.map +1 -0
- package/dist/{testers-NZOFA3EF.js → testers-LSMBXCA2.js} +24 -44
- package/dist/testers-LSMBXCA2.js.map +1 -0
- package/dist/tracks-YHMO2A6B.js +98 -0
- package/dist/tracks-YHMO2A6B.js.map +1 -0
- package/dist/{train-CJJVLY4B.js → train-MDD2EBHS.js} +35 -55
- package/dist/train-MDD2EBHS.js.map +1 -0
- package/dist/{update-NAK6CMUX.js → update-OMALGIBR.js} +29 -14
- package/dist/update-OMALGIBR.js.map +1 -0
- package/dist/{users-2YTC4Q36.js → users-UKG7VIQH.js} +45 -67
- package/dist/users-UKG7VIQH.js.map +1 -0
- package/dist/{validate-UOVTM6L3.js → validate-QIYSA3N7.js} +8 -10
- package/dist/validate-QIYSA3N7.js.map +1 -0
- package/dist/{version-N64UBW7A.js → version-NCSNXNVN.js} +3 -3
- package/dist/{vitals-A4CS4MSS.js → vitals-C23L2Y2E.js} +153 -172
- package/dist/vitals-C23L2Y2E.js.map +1 -0
- package/package.json +6 -6
- package/dist/anomalies-NU2IN2GJ.js.map +0 -1
- package/dist/apps-J2446UDA.js.map +0 -1
- package/dist/audit-N2CRHWUN.js.map +0 -1
- package/dist/auth-XGSTT5G5.js.map +0 -1
- package/dist/bundle-F43TD2BQ.js +0 -218
- package/dist/bundle-F43TD2BQ.js.map +0 -1
- package/dist/cache-SLNFRTI2.js.map +0 -1
- package/dist/changelog-ZYD6W5IV.js +0 -53
- package/dist/changelog-ZYD6W5IV.js.map +0 -1
- package/dist/chunk-4O4D5SGL.js.map +0 -1
- package/dist/chunk-AA577WVQ.js.map +0 -1
- package/dist/chunk-FWKYRLKY.js +0 -19
- package/dist/chunk-FWKYRLKY.js.map +0 -1
- package/dist/chunk-NV75I5VP.js.map +0 -1
- package/dist/chunk-U6ZTQ34I.js.map +0 -1
- package/dist/config-BUXPDN7N.js.map +0 -1
- package/dist/data-safety-Q7FTCEWU.js.map +0 -1
- package/dist/device-tiers-MIOQEXYY.js.map +0 -1
- package/dist/diff-V77SMKAQ.js +0 -96
- package/dist/diff-V77SMKAQ.js.map +0 -1
- package/dist/docs-7DUXIKA3.js.map +0 -1
- package/dist/doctor-3Z4ARPM2.js +0 -372
- package/dist/doctor-3Z4ARPM2.js.map +0 -1
- package/dist/enterprise-7THXNBTC.js.map +0 -1
- package/dist/external-transactions-2GWIMUVM.js.map +0 -1
- package/dist/games-BT777WUO.js.map +0 -1
- package/dist/generated-apks-RJWTIX7L.js.map +0 -1
- package/dist/grants-TKQJ3IER.js.map +0 -1
- package/dist/iap-ICAEQLK5.js.map +0 -1
- package/dist/init-JZ2THPMS.js.map +0 -1
- package/dist/listings-77HZW4S5.js.map +0 -1
- package/dist/migrate-SQT6RD6T.js +0 -143
- package/dist/migrate-SQT6RD6T.js.map +0 -1
- package/dist/one-time-products-LHZAXQES.js.map +0 -1
- package/dist/preflight-H3HEBYQW.js.map +0 -1
- package/dist/publish-Q5ZKEKZ5.js.map +0 -1
- package/dist/purchase-options-CKRN4VIW.js.map +0 -1
- package/dist/purchases-43AKV6HG.js.map +0 -1
- package/dist/quickstart-4HB62YEL.js.map +0 -1
- package/dist/quota-UHIQQYOY.js.map +0 -1
- package/dist/recovery-5EV2R476.js.map +0 -1
- package/dist/releases-C2WC2K4E.js.map +0 -1
- package/dist/reports-2YX3RDOS.js.map +0 -1
- package/dist/reviews-2CWOI5CV.js +0 -213
- package/dist/reviews-2CWOI5CV.js.map +0 -1
- package/dist/status-WHGLODGV.js.map +0 -1
- package/dist/subscriptions-CI3JH3VQ.js.map +0 -1
- package/dist/testers-NZOFA3EF.js.map +0 -1
- package/dist/tracks-NERFFEDT.js +0 -107
- package/dist/tracks-NERFFEDT.js.map +0 -1
- package/dist/train-CJJVLY4B.js.map +0 -1
- package/dist/update-NAK6CMUX.js.map +0 -1
- package/dist/users-2YTC4Q36.js.map +0 -1
- package/dist/validate-UOVTM6L3.js.map +0 -1
- package/dist/vitals-A4CS4MSS.js.map +0 -1
- /package/dist/{feedback-DPTO6DUT.js.map → feedback-XP765TOO.js.map} +0 -0
- /package/dist/{prompt-BSV22CQZ.js.map → prompt-GXC2JSLA.js.map} +0 -0
- /package/dist/{version-N64UBW7A.js.map → version-NCSNXNVN.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolvePackageName
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NQH4G7BI.js";
|
|
5
5
|
import {
|
|
6
6
|
isDryRun
|
|
7
7
|
} from "./chunk-Y3QZDAKS.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
isInteractive,
|
|
13
13
|
promptInput,
|
|
14
14
|
promptSelect
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YFUBD2XB.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/publish.ts
|
|
18
18
|
import { appendFile, stat } from "fs/promises";
|
|
@@ -24,7 +24,8 @@ import {
|
|
|
24
24
|
generateNotesFromGit,
|
|
25
25
|
writeAuditLog,
|
|
26
26
|
createAuditEntry,
|
|
27
|
-
formatOutput
|
|
27
|
+
formatOutput,
|
|
28
|
+
GpcError
|
|
28
29
|
} from "@gpc-cli/core";
|
|
29
30
|
var PASS = "\u2713";
|
|
30
31
|
var FAIL = "\u2717";
|
|
@@ -83,15 +84,21 @@ function registerPublishCommand(program) {
|
|
|
83
84
|
try {
|
|
84
85
|
await stat(file);
|
|
85
86
|
} catch {
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
throw new GpcError(
|
|
88
|
+
`File not found: ${file}`,
|
|
89
|
+
"PUBLISH_USAGE_ERROR",
|
|
90
|
+
2,
|
|
91
|
+
"Check the file path and try again."
|
|
92
|
+
);
|
|
88
93
|
}
|
|
89
94
|
const noteSources = [options.notes, options.notesDir, options.notesFromGit].filter(Boolean);
|
|
90
95
|
if (noteSources.length > 1) {
|
|
91
|
-
|
|
92
|
-
"
|
|
96
|
+
throw new GpcError(
|
|
97
|
+
"Cannot combine --notes, --notes-dir, and --notes-from-git. Use only one.",
|
|
98
|
+
"PUBLISH_USAGE_ERROR",
|
|
99
|
+
2,
|
|
100
|
+
"Pick one release notes source."
|
|
93
101
|
);
|
|
94
|
-
process.exit(2);
|
|
95
102
|
}
|
|
96
103
|
const config = await loadConfig();
|
|
97
104
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
@@ -118,10 +125,12 @@ function registerPublishCommand(program) {
|
|
|
118
125
|
if (options.rollout !== void 0) {
|
|
119
126
|
const rollout = Number(options.rollout);
|
|
120
127
|
if (!Number.isFinite(rollout) || rollout < 1 || rollout > 100) {
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
throw new GpcError(
|
|
129
|
+
`--rollout must be a number between 1 and 100 (got: ${options.rollout})`,
|
|
130
|
+
"PUBLISH_USAGE_ERROR",
|
|
131
|
+
2,
|
|
132
|
+
"Use a percentage between 1 and 100."
|
|
123
133
|
);
|
|
124
|
-
process.exit(2);
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
if (options.notesFromGit) {
|
|
@@ -146,21 +155,16 @@ function registerPublishCommand(program) {
|
|
|
146
155
|
});
|
|
147
156
|
const client = createApiClient({ auth, onRetry });
|
|
148
157
|
if (isDryRun(program)) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
console.log(formatDryRunOutput(result, format));
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
162
|
-
process.exit(4);
|
|
163
|
-
}
|
|
158
|
+
const result = await publish(client, packageName, file, {
|
|
159
|
+
track: options.track,
|
|
160
|
+
rolloutPercent: options.rollout ? Number(options.rollout) : void 0,
|
|
161
|
+
notes: options.notes,
|
|
162
|
+
notesDir: options.notesDir,
|
|
163
|
+
releaseName: options.name,
|
|
164
|
+
mappingFile: options.mapping,
|
|
165
|
+
dryRun: true
|
|
166
|
+
});
|
|
167
|
+
console.log(formatDryRunOutput(result, format));
|
|
164
168
|
return;
|
|
165
169
|
}
|
|
166
170
|
const auditEntry = createAuditEntry(
|
|
@@ -181,15 +185,15 @@ function registerPublishCommand(program) {
|
|
|
181
185
|
console.log(formatValidationOutput(result, format));
|
|
182
186
|
auditEntry.success = false;
|
|
183
187
|
auditEntry.error = "Validation failed";
|
|
184
|
-
process.
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
return;
|
|
185
190
|
}
|
|
186
191
|
console.log(formatPublishOutput(result, format));
|
|
187
192
|
auditEntry.success = true;
|
|
188
193
|
} catch (error) {
|
|
189
194
|
auditEntry.success = false;
|
|
190
195
|
auditEntry.error = error instanceof Error ? error.message : String(error);
|
|
191
|
-
|
|
192
|
-
process.exit(4);
|
|
196
|
+
throw error;
|
|
193
197
|
} finally {
|
|
194
198
|
auditEntry.durationMs = Date.now() - new Date(auditEntry.timestamp).getTime();
|
|
195
199
|
writeAuditLog(auditEntry).catch(() => {
|
|
@@ -200,4 +204,4 @@ function registerPublishCommand(program) {
|
|
|
200
204
|
export {
|
|
201
205
|
registerPublishCommand
|
|
202
206
|
};
|
|
203
|
-
//# sourceMappingURL=publish-
|
|
207
|
+
//# sourceMappingURL=publish-JPTI4EBT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/publish.ts"],"sourcesContent":["import { resolvePackageName } from \"../resolve.js\";\nimport { appendFile, stat } from \"node:fs/promises\";\nimport type { OutputFormat } 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 {\n publish,\n generateNotesFromGit,\n writeAuditLog,\n createAuditEntry,\n formatOutput,\n GpcError,\n} from \"@gpc-cli/core\";\nimport type { PublishResult, DryRunPublishResult } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun } from \"../dry-run.js\";\nimport { isInteractive, promptSelect, promptInput } from \"../prompt.js\";\n\nconst PASS = \"\\u2713\";\nconst FAIL = \"\\u2717\";\nconst WARN = \"\\u26A0\";\n\n\n// ---------------------------------------------------------------------------\n// Output formatters\n// ---------------------------------------------------------------------------\n\nfunction formatChecks(checks: { name: string; passed: boolean; message: string }[]): string[] {\n return checks.map((c) => ` ${c.passed ? PASS : FAIL} ${c.message}`);\n}\n\nfunction formatValidationOutput(result: PublishResult, format: OutputFormat): string {\n if (format !== \"table\") {\n return formatOutput({ success: false, validation: result.validation }, format);\n }\n const lines = [\"Validation failed:\\n\", ...formatChecks(result.validation.checks)];\n for (const w of result.validation.warnings) {\n lines.push(` ${WARN} ${w}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatPublishOutput(result: PublishResult, format: OutputFormat): string {\n if (format !== \"table\") return formatOutput(result, format);\n\n const upload = result.upload;\n if (!upload) return formatOutput(result, format);\n const rollout =\n upload.status === \"inProgress\" && \"userFraction\" in upload\n ? ` (${Math.round(Number((upload as Record<string, unknown>)[\"userFraction\"]) * 100)}% rollout)`\n : \"\";\n\n const lines = [\"Published successfully\\n\", ...formatChecks(result.validation.checks)];\n for (const w of result.validation.warnings) {\n lines.push(` ${WARN} ${w}`);\n }\n lines.push(\"\");\n lines.push(` versionCode ${upload.versionCode}`);\n lines.push(` track ${upload.track}`);\n lines.push(` status ${upload.status}${rollout}`);\n return lines.join(\"\\n\");\n}\n\nfunction formatDryRunOutput(result: DryRunPublishResult, format: OutputFormat): string {\n if (format !== \"table\") return formatOutput(result, format);\n\n const lines = [\"Dry run — no changes made\\n\", ...formatChecks(result.validation.checks)];\n for (const w of result.validation.warnings) {\n lines.push(` ${WARN} ${w}`);\n }\n\n const u = result.upload;\n lines.push(\"\");\n lines.push(` Track ${u.track}`);\n\n if (u.currentReleases.length === 0) {\n lines.push(` Current (no releases on this track)`);\n } else {\n for (const r of u.currentReleases) {\n const fraction =\n r.userFraction !== undefined ? ` (${Math.round(r.userFraction * 100)}%)` : \"\";\n lines.push(` Current ${r.versionCodes.join(\", \")} · ${r.status}${fraction}`);\n }\n }\n const plannedFraction =\n u.plannedRelease.userFraction !== undefined\n ? ` (${Math.round(u.plannedRelease.userFraction * 100)}%)`\n : \"\";\n lines.push(` Would be (new bundle) · ${u.plannedRelease.status}${plannedFraction}`);\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Command\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(\"--notes-from-git\", \"Generate release notes from git commit history\")\n .option(\"--since <ref>\", \"Git ref to start from (tag, SHA) — used with --notes-from-git\")\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 try {\n await stat(file);\n } catch {\n throw new GpcError(\n `File not found: ${file}`,\n \"PUBLISH_USAGE_ERROR\",\n 2,\n \"Check the file path and try again.\",\n );\n }\n\n const noteSources = [options.notes, options.notesDir, options.notesFromGit].filter(Boolean);\n if (noteSources.length > 1) {\n throw new GpcError(\n \"Cannot combine --notes, --notes-dir, and --notes-from-git. Use only one.\",\n \"PUBLISH_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\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 && !options.notesFromGit) {\n const notes = await promptInput(\"Release notes (en-US, blank to skip)\");\n if (notes) options.notes = notes;\n }\n }\n\n // Rollout range guard\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 \"PUBLISH_USAGE_ERROR\",\n 2,\n \"Use a percentage between 1 and 100.\",\n );\n }\n }\n\n // Resolve git-based release notes before calling publish\n if (options.notesFromGit) {\n const gitNotes = await generateNotesFromGit({ since: options.since });\n options.notes = gitNotes.text;\n if (gitNotes.truncated) {\n console.error(\n `${WARN} Release notes truncated to 500 characters (${gitNotes.commitCount} commits from ${gitNotes.since}).`,\n );\n }\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 if (isDryRun(program)) {\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 dryRun: true,\n });\n console.log(formatDryRunOutput(result as DryRunPublishResult, format));\n return;\n }\n\n const auditEntry = createAuditEntry(\n \"publish\",\n { file, track: options.track, rollout: options.rollout },\n packageName,\n );\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.log(formatValidationOutput(result as PublishResult, format));\n auditEntry.success = false;\n auditEntry.error = \"Validation failed\";\n process.exitCode = 1;\n return;\n }\n\n console.log(formatPublishOutput(result as PublishResult, format));\n auditEntry.success = true;\n } catch (error) {\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"],"mappings":"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","names":[]}
|
|
@@ -14,27 +14,32 @@ See: gpc otp offers --help`;
|
|
|
14
14
|
function registerPurchaseOptionsCommands(program) {
|
|
15
15
|
const po = program.command("purchase-options").description("Manage purchase options (use 'otp offers' commands)");
|
|
16
16
|
po.command("list").description("List purchase options").option("--sort <field>", "Sort by field").action(async () => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const err = new Error(REDIRECT_MESSAGE);
|
|
18
|
+
Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
|
|
19
|
+
throw err;
|
|
19
20
|
});
|
|
20
21
|
po.command("get <id>").description("Get a purchase option").action(async () => {
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const err = new Error(REDIRECT_MESSAGE);
|
|
23
|
+
Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
|
|
24
|
+
throw err;
|
|
23
25
|
});
|
|
24
26
|
po.command("create").description("Create a purchase option").option("--file <path>", "JSON file with purchase option data").action(async () => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const err = new Error(REDIRECT_MESSAGE);
|
|
28
|
+
Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
|
|
29
|
+
throw err;
|
|
27
30
|
});
|
|
28
31
|
po.command("activate <id>").description("Activate a purchase option").action(async () => {
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
const err = new Error(REDIRECT_MESSAGE);
|
|
33
|
+
Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
|
|
34
|
+
throw err;
|
|
31
35
|
});
|
|
32
36
|
po.command("deactivate <id>").description("Deactivate a purchase option").action(async () => {
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
const err = new Error(REDIRECT_MESSAGE);
|
|
38
|
+
Object.assign(err, { code: "USAGE_ERROR", exitCode: 2 });
|
|
39
|
+
throw err;
|
|
35
40
|
});
|
|
36
41
|
}
|
|
37
42
|
export {
|
|
38
43
|
registerPurchaseOptionsCommands
|
|
39
44
|
};
|
|
40
|
-
//# sourceMappingURL=purchase-options-
|
|
45
|
+
//# sourceMappingURL=purchase-options-KFWW4JW2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/purchase-options.ts"],"sourcesContent":["import type { Command } from \"commander\";\n\nconst REDIRECT_MESSAGE = `Purchase options are managed through one-time product offers.\n\nUse the following commands instead:\n gpc otp offers list <product-id> List purchase options for a product\n gpc otp offers get <product-id> <id> Get a specific purchase option\n gpc otp offers create <product-id> Create a purchase option\n gpc otp offers activate <product-id> <id>\n gpc otp offers deactivate <product-id> <id>\n\nSee: gpc otp offers --help`;\n\nexport function registerPurchaseOptionsCommands(program: Command): void {\n const po = program\n .command(\"purchase-options\")\n .description(\"Manage purchase options (use 'otp offers' commands)\");\n\n po.command(\"list\")\n .description(\"List purchase options\")\n .option(\"--sort <field>\", \"Sort by field\")\n .action(async () => {\n const err = new Error(REDIRECT_MESSAGE);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n });\n\n po.command(\"get <id>\")\n .description(\"Get a purchase option\")\n .action(async () => {\n const err = new Error(REDIRECT_MESSAGE);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n });\n\n po.command(\"create\")\n .description(\"Create a purchase option\")\n .option(\"--file <path>\", \"JSON file with purchase option data\")\n .action(async () => {\n const err = new Error(REDIRECT_MESSAGE);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n });\n\n po.command(\"activate <id>\")\n .description(\"Activate a purchase option\")\n .action(async () => {\n const err = new Error(REDIRECT_MESSAGE);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n });\n\n po.command(\"deactivate <id>\")\n .description(\"Deactivate a purchase option\")\n .action(async () => {\n const err = new Error(REDIRECT_MESSAGE);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n });\n}\n"],"mappings":";;;AAEA,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWlB,SAAS,gCAAgC,SAAwB;AACtE,QAAM,KAAK,QACR,QAAQ,kBAAkB,EAC1B,YAAY,qDAAqD;AAEpE,KAAG,QAAQ,MAAM,EACd,YAAY,uBAAuB,EACnC,OAAO,kBAAkB,eAAe,EACxC,OAAO,YAAY;AAClB,UAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,UAAM;AAAA,EACR,CAAC;AAEH,KAAG,QAAQ,UAAU,EAClB,YAAY,uBAAuB,EACnC,OAAO,YAAY;AAClB,UAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,UAAM;AAAA,EACR,CAAC;AAEH,KAAG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,YAAY;AAClB,UAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,UAAM;AAAA,EACR,CAAC;AAEH,KAAG,QAAQ,eAAe,EACvB,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAClB,UAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,UAAM;AAAA,EACR,CAAC;AAEH,KAAG,QAAQ,iBAAiB,EACzB,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAM,MAAM,IAAI,MAAM,gBAAgB;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,eAAe,UAAU,EAAE,CAAC;AACvD,UAAM;AAAA,EACR,CAAC;AACL;","names":[]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getClient,
|
|
4
4
|
resolvePackageName
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NQH4G7BI.js";
|
|
6
6
|
import {
|
|
7
7
|
isDryRun,
|
|
8
8
|
printDryRun
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
isInteractive,
|
|
15
15
|
requireConfirm,
|
|
16
16
|
requireOption
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-YFUBD2XB.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/purchases.ts
|
|
20
20
|
import { Option } from "commander";
|
|
@@ -44,24 +44,19 @@ function registerPurchasesCommands(program) {
|
|
|
44
44
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
45
45
|
const client = await getClient(config);
|
|
46
46
|
const format = getOutputFormat(program, config);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
console.log(formatOutput(result, format));
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
64
|
-
process.exit(4);
|
|
47
|
+
const result = await getProductPurchase(client, packageName, productId, token);
|
|
48
|
+
if (format !== "json") {
|
|
49
|
+
const r = result;
|
|
50
|
+
const row = {
|
|
51
|
+
orderId: r["orderId"] || "-",
|
|
52
|
+
purchaseState: r["purchaseState"] ?? "-",
|
|
53
|
+
consumptionState: r["consumptionState"] ?? "-",
|
|
54
|
+
purchaseTime: r["purchaseTimeMillis"] ? new Date(Number(r["purchaseTimeMillis"])).toISOString() : "-",
|
|
55
|
+
acknowledged: r["acknowledgementState"] ?? "-"
|
|
56
|
+
};
|
|
57
|
+
console.log(formatOutput(row, format));
|
|
58
|
+
} else {
|
|
59
|
+
console.log(formatOutput(result, format));
|
|
65
60
|
}
|
|
66
61
|
});
|
|
67
62
|
purchases.command("acknowledge <product-id> <token>").description("Acknowledge a product purchase").option("--payload <text>", "Developer payload").action(async (productId, token, options) => {
|
|
@@ -82,13 +77,8 @@ function registerPurchasesCommands(program) {
|
|
|
82
77
|
return;
|
|
83
78
|
}
|
|
84
79
|
const client = await getClient(config);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
console.log(`Purchase acknowledged.`);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
90
|
-
process.exit(4);
|
|
91
|
-
}
|
|
80
|
+
await acknowledgeProductPurchase(client, packageName, productId, token, options.payload);
|
|
81
|
+
console.log(`Purchase acknowledged.`);
|
|
92
82
|
});
|
|
93
83
|
purchases.command("consume <product-id> <token>").description("Consume a product purchase").action(async (productId, token) => {
|
|
94
84
|
const config = await loadConfig();
|
|
@@ -107,13 +97,8 @@ function registerPurchasesCommands(program) {
|
|
|
107
97
|
return;
|
|
108
98
|
}
|
|
109
99
|
const client = await getClient(config);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
console.log(`Purchase consumed.`);
|
|
113
|
-
} catch (error) {
|
|
114
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
115
|
-
process.exit(4);
|
|
116
|
-
}
|
|
100
|
+
await consumeProductPurchase(client, packageName, productId, token);
|
|
101
|
+
console.log(`Purchase consumed.`);
|
|
117
102
|
});
|
|
118
103
|
const sub = purchases.command("subscription").description("Manage subscription purchases");
|
|
119
104
|
sub.command("get <token>").description("Get a subscription purchase (v2)").action(async (token) => {
|
|
@@ -121,26 +106,21 @@ function registerPurchasesCommands(program) {
|
|
|
121
106
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
122
107
|
const client = await getClient(config);
|
|
123
108
|
const format = getOutputFormat(program, config);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
console.log(formatOutput(result, format));
|
|
140
|
-
}
|
|
141
|
-
} catch (error) {
|
|
142
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
143
|
-
process.exit(4);
|
|
109
|
+
const result = await getSubscriptionPurchase(client, packageName, token);
|
|
110
|
+
if (format !== "json") {
|
|
111
|
+
const r = result;
|
|
112
|
+
const lineItems = r["lineItems"];
|
|
113
|
+
const row = {
|
|
114
|
+
subscriptionState: r["subscriptionState"] || "-",
|
|
115
|
+
startTime: r["startTime"] || "-",
|
|
116
|
+
expiryTime: r["expiryTime"] || "-",
|
|
117
|
+
linkedPurchaseToken: r["linkedPurchaseToken"] ? "yes" : "no",
|
|
118
|
+
lineItems: lineItems?.length || 0,
|
|
119
|
+
acknowledgement: r["acknowledgementState"] || "-"
|
|
120
|
+
};
|
|
121
|
+
console.log(formatOutput(row, format));
|
|
122
|
+
} else {
|
|
123
|
+
console.log(formatOutput(result, format));
|
|
144
124
|
}
|
|
145
125
|
});
|
|
146
126
|
sub.command("cancel <subscription-id> <token>").description("Cancel a subscription (v1)").action(async (subscriptionId, token) => {
|
|
@@ -160,13 +140,8 @@ function registerPurchasesCommands(program) {
|
|
|
160
140
|
return;
|
|
161
141
|
}
|
|
162
142
|
const client = await getClient(config);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
console.log(`Subscription cancelled.`);
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
|
-
process.exit(4);
|
|
169
|
-
}
|
|
143
|
+
await cancelSubscriptionPurchase(client, packageName, subscriptionId, token);
|
|
144
|
+
console.log(`Subscription cancelled.`);
|
|
170
145
|
});
|
|
171
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) => {
|
|
172
147
|
const config = await loadConfig();
|
|
@@ -195,19 +170,14 @@ function registerPurchasesCommands(program) {
|
|
|
195
170
|
return;
|
|
196
171
|
}
|
|
197
172
|
const client = await getClient(config);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
console.log(formatOutput(result, format));
|
|
207
|
-
} catch (error) {
|
|
208
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
209
|
-
process.exit(4);
|
|
210
|
-
}
|
|
173
|
+
const result = await deferSubscriptionPurchase(
|
|
174
|
+
client,
|
|
175
|
+
packageName,
|
|
176
|
+
subscriptionId,
|
|
177
|
+
token,
|
|
178
|
+
options.expiry
|
|
179
|
+
);
|
|
180
|
+
console.log(formatOutput(result, format));
|
|
211
181
|
});
|
|
212
182
|
sub.command("refund <token>").description("Refund a subscription purchase (v2)").action(async (token) => {
|
|
213
183
|
const config = await loadConfig();
|
|
@@ -227,13 +197,8 @@ function registerPurchasesCommands(program) {
|
|
|
227
197
|
return;
|
|
228
198
|
}
|
|
229
199
|
const client = await getClient(config);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
console.log(`Subscription refunded.`);
|
|
233
|
-
} catch (error) {
|
|
234
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
235
|
-
process.exit(4);
|
|
236
|
-
}
|
|
200
|
+
await refundSubscriptionV2(client, packageName, token);
|
|
201
|
+
console.log(`Subscription refunded.`);
|
|
237
202
|
});
|
|
238
203
|
sub.command("revoke <token>").description("Revoke a subscription (v2)").action(async (token) => {
|
|
239
204
|
const config = await loadConfig();
|
|
@@ -252,13 +217,8 @@ function registerPurchasesCommands(program) {
|
|
|
252
217
|
return;
|
|
253
218
|
}
|
|
254
219
|
const client = await getClient(config);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
console.log(`Subscription revoked.`);
|
|
258
|
-
} catch (error) {
|
|
259
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
260
|
-
process.exit(4);
|
|
261
|
-
}
|
|
220
|
+
await revokeSubscriptionPurchase(client, packageName, token);
|
|
221
|
+
console.log(`Subscription revoked.`);
|
|
262
222
|
});
|
|
263
223
|
purchases.command("voided").description("List voided purchases").option("--start-time <time>", "Start time (milliseconds)").option("--end-time <time>", "End time (milliseconds)").addOption(
|
|
264
224
|
new Option("--max-results <n>", "Maximum results per page").argParser(parseInt).hideHelp()
|
|
@@ -267,34 +227,29 @@ function registerPurchasesCommands(program) {
|
|
|
267
227
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
268
228
|
const client = await getClient(config);
|
|
269
229
|
const format = getOutputFormat(program, config);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
console.log(formatOutput(rows, format));
|
|
289
|
-
} else {
|
|
290
|
-
console.log("No voided purchases found.");
|
|
291
|
-
}
|
|
230
|
+
const result = await listVoidedPurchases(client, packageName, {
|
|
231
|
+
startTime: options.startTime,
|
|
232
|
+
endTime: options.endTime,
|
|
233
|
+
maxResults: options.maxResults,
|
|
234
|
+
limit: options.limit,
|
|
235
|
+
nextPage: options.nextPage
|
|
236
|
+
});
|
|
237
|
+
if (format !== "json") {
|
|
238
|
+
const purchases2 = result["voidedPurchases"];
|
|
239
|
+
if (purchases2 && purchases2.length > 0) {
|
|
240
|
+
const rows = purchases2.map((p) => ({
|
|
241
|
+
orderId: p["orderId"] || "-",
|
|
242
|
+
purchaseToken: String(p["purchaseToken"] || "-").slice(0, 16) + "...",
|
|
243
|
+
voidedTime: p["voidedTimeMillis"] ? new Date(Number(p["voidedTimeMillis"])).toISOString() : "-",
|
|
244
|
+
voidedSource: p["voidedSource"] ?? "-",
|
|
245
|
+
voidedReason: p["voidedReason"] ?? "-"
|
|
246
|
+
}));
|
|
247
|
+
console.log(formatOutput(rows, format));
|
|
292
248
|
} else {
|
|
293
|
-
console.log(
|
|
249
|
+
console.log("No voided purchases found.");
|
|
294
250
|
}
|
|
295
|
-
}
|
|
296
|
-
console.
|
|
297
|
-
process.exit(4);
|
|
251
|
+
} else {
|
|
252
|
+
console.log(formatOutput(result, format));
|
|
298
253
|
}
|
|
299
254
|
});
|
|
300
255
|
const orders = purchases.command("orders").description("Manage orders");
|
|
@@ -317,40 +272,30 @@ function registerPurchasesCommands(program) {
|
|
|
317
272
|
return;
|
|
318
273
|
}
|
|
319
274
|
const client = await getClient(config);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
console.log(`Order ${orderId} refunded.`);
|
|
326
|
-
} catch (error) {
|
|
327
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
328
|
-
process.exit(4);
|
|
329
|
-
}
|
|
275
|
+
await refundOrder(client, packageName, orderId, {
|
|
276
|
+
fullRefund: options.fullRefund,
|
|
277
|
+
proratedRefund: options.proratedRefund
|
|
278
|
+
});
|
|
279
|
+
console.log(`Order ${orderId} refunded.`);
|
|
330
280
|
});
|
|
331
281
|
orders.command("get <order-id>").description("Get order details").action(async (orderId) => {
|
|
332
282
|
const config = await loadConfig();
|
|
333
283
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
334
284
|
const client = await getClient(config);
|
|
335
285
|
const format = getOutputFormat(program, config);
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
console.log(formatOutput(result, format));
|
|
350
|
-
}
|
|
351
|
-
} catch (error) {
|
|
352
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
353
|
-
process.exit(4);
|
|
286
|
+
const result = await getOrderDetails(client, packageName, orderId);
|
|
287
|
+
if (format !== "json") {
|
|
288
|
+
const row = {
|
|
289
|
+
orderId: result.orderId,
|
|
290
|
+
state: result.state,
|
|
291
|
+
purchaseToken: result.purchaseToken ? result.purchaseToken.slice(0, 16) + "..." : "-",
|
|
292
|
+
createTime: result.createTime || "-",
|
|
293
|
+
total: result.total ? `${result.total.units || "0"}.${String(result.total.nanos || 0).padStart(9, "0").slice(0, 2)} ${result.total.currencyCode}` : "-",
|
|
294
|
+
lineItems: result.lineItems?.length || 0
|
|
295
|
+
};
|
|
296
|
+
console.log(formatOutput(row, format));
|
|
297
|
+
} else {
|
|
298
|
+
console.log(formatOutput(result, format));
|
|
354
299
|
}
|
|
355
300
|
});
|
|
356
301
|
orders.command("batch-get").description("Get multiple orders at once").requiredOption("--ids <order-ids>", "Comma-separated order IDs (max 1000)").action(async (options) => {
|
|
@@ -359,26 +304,21 @@ function registerPurchasesCommands(program) {
|
|
|
359
304
|
const client = await getClient(config);
|
|
360
305
|
const format = getOutputFormat(program, config);
|
|
361
306
|
const orderIds = options.ids.split(",").map((id) => id.trim()).filter(Boolean);
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
console.log("No orders found.");
|
|
367
|
-
} else {
|
|
368
|
-
const rows = result.map((o) => ({
|
|
369
|
-
orderId: o.orderId,
|
|
370
|
-
state: o.state,
|
|
371
|
-
createTime: o.createTime || "-",
|
|
372
|
-
lineItems: o.lineItems?.length || 0
|
|
373
|
-
}));
|
|
374
|
-
console.log(formatOutput(rows, format));
|
|
375
|
-
}
|
|
307
|
+
const result = await batchGetOrders(client, packageName, orderIds);
|
|
308
|
+
if (format !== "json") {
|
|
309
|
+
if (result.length === 0) {
|
|
310
|
+
console.log("No orders found.");
|
|
376
311
|
} else {
|
|
377
|
-
|
|
312
|
+
const rows = result.map((o) => ({
|
|
313
|
+
orderId: o.orderId,
|
|
314
|
+
state: o.state,
|
|
315
|
+
createTime: o.createTime || "-",
|
|
316
|
+
lineItems: o.lineItems?.length || 0
|
|
317
|
+
}));
|
|
318
|
+
console.log(formatOutput(rows, format));
|
|
378
319
|
}
|
|
379
|
-
}
|
|
380
|
-
console.
|
|
381
|
-
process.exit(4);
|
|
320
|
+
} else {
|
|
321
|
+
console.log(formatOutput(result, format));
|
|
382
322
|
}
|
|
383
323
|
});
|
|
384
324
|
const product = purchases.command("product").description("Product purchase operations");
|
|
@@ -387,24 +327,19 @@ function registerPurchasesCommands(program) {
|
|
|
387
327
|
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
388
328
|
const client = await getClient(config);
|
|
389
329
|
const format = getOutputFormat(program, config);
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
console.log(formatOutput(result, format));
|
|
404
|
-
}
|
|
405
|
-
} catch (error) {
|
|
406
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
407
|
-
process.exit(4);
|
|
330
|
+
const result = await getProductPurchaseV2(client, packageName, token);
|
|
331
|
+
if (format !== "json") {
|
|
332
|
+
const row = {
|
|
333
|
+
orderId: result.orderId || "-",
|
|
334
|
+
state: result.purchaseStateContext?.state || "-",
|
|
335
|
+
regionCode: result.regionCode || "-",
|
|
336
|
+
completionTime: result.purchaseCompletionTime || "-",
|
|
337
|
+
acknowledgement: result.acknowledgementState || "-",
|
|
338
|
+
lineItems: result.productLineItem?.length || 0
|
|
339
|
+
};
|
|
340
|
+
console.log(formatOutput(row, format));
|
|
341
|
+
} else {
|
|
342
|
+
console.log(formatOutput(result, format));
|
|
408
343
|
}
|
|
409
344
|
});
|
|
410
345
|
sub.command("cancel-v2 <token>").description("Cancel a subscription (v2 \u2014 supports cancellation types)").option("--type <cancellationType>", "Cancellation type (e.g., USER_CANCELED, SYSTEM_CANCELED, DEVELOPER_CANCELED, REPLACED)").action(async (token, options) => {
|
|
@@ -421,13 +356,8 @@ function registerPurchasesCommands(program) {
|
|
|
421
356
|
return;
|
|
422
357
|
}
|
|
423
358
|
const client = await getClient(config);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
console.log("Subscription cancelled.");
|
|
427
|
-
} catch (error) {
|
|
428
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
429
|
-
process.exit(4);
|
|
430
|
-
}
|
|
359
|
+
await cancelSubscriptionV2(client, packageName, token, options.type);
|
|
360
|
+
console.log("Subscription cancelled.");
|
|
431
361
|
});
|
|
432
362
|
sub.command("defer-v2 <token>").description("Defer a subscription renewal (v2 \u2014 supports add-on subscriptions)").requiredOption("--until <date>", "Desired expiry time (ISO 8601 date)").action(async (token, options) => {
|
|
433
363
|
const config = await loadConfig();
|
|
@@ -443,16 +373,11 @@ function registerPurchasesCommands(program) {
|
|
|
443
373
|
return;
|
|
444
374
|
}
|
|
445
375
|
const client = await getClient(config);
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
console.log(`Subscription deferred. New expiry: ${result.newExpiryTime}`);
|
|
449
|
-
} catch (error) {
|
|
450
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
451
|
-
process.exit(4);
|
|
452
|
-
}
|
|
376
|
+
const result = await deferSubscriptionV2(client, packageName, token, options.until);
|
|
377
|
+
console.log(`Subscription deferred. New expiry: ${result.newExpiryTime}`);
|
|
453
378
|
});
|
|
454
379
|
}
|
|
455
380
|
export {
|
|
456
381
|
registerPurchasesCommands
|
|
457
382
|
};
|
|
458
|
-
//# sourceMappingURL=purchases-
|
|
383
|
+
//# sourceMappingURL=purchases-DAWTMXP6.js.map
|