@gpc-cli/cli 0.9.19 → 0.9.21
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/bin.js +1 -1
- package/dist/{chunk-CLPVXK47.js → chunk-6DB65GRP.js} +14 -14
- package/dist/{data-safety-TNG3QMJX.js → data-safety-DBA26FHB.js} +16 -30
- package/dist/data-safety-DBA26FHB.js.map +1 -0
- package/dist/{device-tiers-WFBZWCTY.js → device-tiers-V2R6AEXL.js} +6 -1
- package/dist/device-tiers-V2R6AEXL.js.map +1 -0
- package/dist/{generated-apks-N4S5PIQH.js → generated-apks-VX7HYZDU.js} +17 -2
- package/dist/generated-apks-VX7HYZDU.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{listings-S4CJ7EDX.js → listings-VSBHQY5H.js} +9 -3
- package/dist/listings-VSBHQY5H.js.map +1 -0
- package/dist/{one-time-products-G3AYCVQQ.js → one-time-products-2PK4QKWE.js} +7 -2
- package/dist/one-time-products-2PK4QKWE.js.map +1 -0
- package/dist/{pricing-OB3MSWID.js → pricing-BYZSLN74.js} +21 -2
- package/dist/pricing-BYZSLN74.js.map +1 -0
- package/dist/purchase-options-CKRN4VIW.js +40 -0
- package/dist/purchase-options-CKRN4VIW.js.map +1 -0
- package/dist/{recovery-Q2I2HV6Q.js → recovery-S5UNJDBO.js} +14 -1
- package/dist/recovery-S5UNJDBO.js.map +1 -0
- package/dist/{releases-YRZ3SXAM.js → releases-JIBSHE4F.js} +5 -5
- package/dist/releases-JIBSHE4F.js.map +1 -0
- package/dist/reports-Q7GFQ5GG.js +80 -0
- package/dist/reports-Q7GFQ5GG.js.map +1 -0
- package/dist/{subscriptions-NY35T25K.js → subscriptions-Z5ZPVUFM.js} +36 -3
- package/dist/subscriptions-Z5ZPVUFM.js.map +1 -0
- package/dist/{testers-QSAXJM7W.js → testers-FXRW6KN3.js} +5 -1
- package/dist/testers-FXRW6KN3.js.map +1 -0
- package/dist/{vitals-EOHSUQJM.js → vitals-FE2V5OHW.js} +22 -9
- package/dist/vitals-FE2V5OHW.js.map +1 -0
- package/package.json +3 -3
- package/dist/data-safety-TNG3QMJX.js.map +0 -1
- package/dist/device-tiers-WFBZWCTY.js.map +0 -1
- package/dist/generated-apks-N4S5PIQH.js.map +0 -1
- package/dist/listings-S4CJ7EDX.js.map +0 -1
- package/dist/one-time-products-G3AYCVQQ.js.map +0 -1
- package/dist/pricing-OB3MSWID.js.map +0 -1
- package/dist/purchase-options-GXWKY6GF.js +0 -149
- package/dist/purchase-options-GXWKY6GF.js.map +0 -1
- package/dist/recovery-Q2I2HV6Q.js.map +0 -1
- package/dist/releases-YRZ3SXAM.js.map +0 -1
- package/dist/reports-ZFVKYI4C.js +0 -185
- package/dist/reports-ZFVKYI4C.js.map +0 -1
- package/dist/subscriptions-NY35T25K.js.map +0 -1
- package/dist/testers-QSAXJM7W.js.map +0 -1
- package/dist/vitals-EOHSUQJM.js.map +0 -1
- /package/dist/{chunk-CLPVXK47.js.map → chunk-6DB65GRP.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -88,7 +88,7 @@ async function createProgram(pluginManager) {
|
|
|
88
88
|
(await import("./apps-CVBURB5V.js")).registerAppsCommands(program);
|
|
89
89
|
},
|
|
90
90
|
releases: async () => {
|
|
91
|
-
(await import("./releases-
|
|
91
|
+
(await import("./releases-JIBSHE4F.js")).registerReleasesCommands(program);
|
|
92
92
|
},
|
|
93
93
|
tracks: async () => {
|
|
94
94
|
(await import("./tracks-TP6TDO56.js")).registerTracksCommands(program);
|
|
@@ -97,16 +97,16 @@ async function createProgram(pluginManager) {
|
|
|
97
97
|
(await import("./status-S3FAEXNH.js")).registerStatusCommand(program);
|
|
98
98
|
},
|
|
99
99
|
listings: async () => {
|
|
100
|
-
(await import("./listings-
|
|
100
|
+
(await import("./listings-VSBHQY5H.js")).registerListingsCommands(program);
|
|
101
101
|
},
|
|
102
102
|
reviews: async () => {
|
|
103
103
|
(await import("./reviews-PMUJVNVC.js")).registerReviewsCommands(program);
|
|
104
104
|
},
|
|
105
105
|
vitals: async () => {
|
|
106
|
-
(await import("./vitals-
|
|
106
|
+
(await import("./vitals-FE2V5OHW.js")).registerVitalsCommands(program);
|
|
107
107
|
},
|
|
108
108
|
subscriptions: async () => {
|
|
109
|
-
(await import("./subscriptions-
|
|
109
|
+
(await import("./subscriptions-Z5ZPVUFM.js")).registerSubscriptionsCommands(program);
|
|
110
110
|
},
|
|
111
111
|
iap: async () => {
|
|
112
112
|
(await import("./iap-VK5TU3Q2.js")).registerIapCommands(program);
|
|
@@ -115,16 +115,16 @@ async function createProgram(pluginManager) {
|
|
|
115
115
|
(await import("./purchases-NB5P4FL4.js")).registerPurchasesCommands(program);
|
|
116
116
|
},
|
|
117
117
|
pricing: async () => {
|
|
118
|
-
(await import("./pricing-
|
|
118
|
+
(await import("./pricing-BYZSLN74.js")).registerPricingCommands(program);
|
|
119
119
|
},
|
|
120
120
|
reports: async () => {
|
|
121
|
-
(await import("./reports-
|
|
121
|
+
(await import("./reports-Q7GFQ5GG.js")).registerReportsCommands(program);
|
|
122
122
|
},
|
|
123
123
|
users: async () => {
|
|
124
124
|
(await import("./users-KUVAYRJC.js")).registerUsersCommands(program);
|
|
125
125
|
},
|
|
126
126
|
testers: async () => {
|
|
127
|
-
(await import("./testers-
|
|
127
|
+
(await import("./testers-FXRW6KN3.js")).registerTestersCommands(program);
|
|
128
128
|
},
|
|
129
129
|
validate: async () => {
|
|
130
130
|
(await import("./validate-UYXICKBO.js")).registerValidateCommand(program);
|
|
@@ -133,10 +133,10 @@ async function createProgram(pluginManager) {
|
|
|
133
133
|
(await import("./publish-PZRWX3TH.js")).registerPublishCommand(program);
|
|
134
134
|
},
|
|
135
135
|
recovery: async () => {
|
|
136
|
-
(await import("./recovery-
|
|
136
|
+
(await import("./recovery-S5UNJDBO.js")).registerRecoveryCommands(program);
|
|
137
137
|
},
|
|
138
138
|
"data-safety": async () => {
|
|
139
|
-
(await import("./data-safety-
|
|
139
|
+
(await import("./data-safety-DBA26FHB.js")).registerDataSafetyCommands(program);
|
|
140
140
|
},
|
|
141
141
|
"external-transactions": async () => {
|
|
142
142
|
(await import("./external-transactions-HCL7ROMN.js")).registerExternalTransactionsCommands(
|
|
@@ -144,19 +144,19 @@ async function createProgram(pluginManager) {
|
|
|
144
144
|
);
|
|
145
145
|
},
|
|
146
146
|
"device-tiers": async () => {
|
|
147
|
-
(await import("./device-tiers-
|
|
147
|
+
(await import("./device-tiers-V2R6AEXL.js")).registerDeviceTiersCommands(program);
|
|
148
148
|
},
|
|
149
149
|
"one-time-products": async () => {
|
|
150
|
-
(await import("./one-time-products-
|
|
150
|
+
(await import("./one-time-products-2PK4QKWE.js")).registerOneTimeProductsCommands(program);
|
|
151
151
|
},
|
|
152
152
|
"internal-sharing": async () => {
|
|
153
153
|
(await import("./internal-sharing-OS3HVIY5.js")).registerInternalSharingCommands(program);
|
|
154
154
|
},
|
|
155
155
|
"generated-apks": async () => {
|
|
156
|
-
(await import("./generated-apks-
|
|
156
|
+
(await import("./generated-apks-VX7HYZDU.js")).registerGeneratedApksCommands(program);
|
|
157
157
|
},
|
|
158
158
|
"purchase-options": async () => {
|
|
159
|
-
(await import("./purchase-options-
|
|
159
|
+
(await import("./purchase-options-CKRN4VIW.js")).registerPurchaseOptionsCommands(program);
|
|
160
160
|
},
|
|
161
161
|
migrate: async () => {
|
|
162
162
|
(await import("./migrate-V6G5YUVH.js")).registerMigrateCommands(program);
|
|
@@ -302,4 +302,4 @@ export {
|
|
|
302
302
|
createProgram,
|
|
303
303
|
handleCliError
|
|
304
304
|
};
|
|
305
|
-
//# sourceMappingURL=chunk-
|
|
305
|
+
//# sourceMappingURL=chunk-6DB65GRP.js.map
|
|
@@ -12,8 +12,6 @@ import { loadConfig } from "@gpc-cli/config";
|
|
|
12
12
|
import { resolveAuth } from "@gpc-cli/auth";
|
|
13
13
|
import { createApiClient } from "@gpc-cli/api";
|
|
14
14
|
import {
|
|
15
|
-
getDataSafety,
|
|
16
|
-
exportDataSafety,
|
|
17
15
|
importDataSafety,
|
|
18
16
|
formatOutput
|
|
19
17
|
} from "@gpc-cli/core";
|
|
@@ -32,17 +30,14 @@ async function getClient(config) {
|
|
|
32
30
|
function registerDataSafetyCommands(program) {
|
|
33
31
|
const dataSafety = program.command("data-safety").description("Manage data safety declarations");
|
|
34
32
|
dataSafety.command("get").description("Get the current data safety declaration").action(async () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
-
process.exit(4);
|
|
45
|
-
}
|
|
33
|
+
console.error("Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.");
|
|
34
|
+
console.error("");
|
|
35
|
+
console.error("Data safety labels can only be updated (not read) via the API.");
|
|
36
|
+
console.error("To view your current data safety declaration, use the Google Play Console:");
|
|
37
|
+
console.error(" https://play.google.com/console \u2192 App content \u2192 Data safety");
|
|
38
|
+
console.error("");
|
|
39
|
+
console.error("To update data safety via the API, use: gpc data-safety update --file <csv-file>");
|
|
40
|
+
process.exit(1);
|
|
46
41
|
});
|
|
47
42
|
dataSafety.command("update").description("Update data safety declaration from a JSON file").requiredOption("--file <path>", "Path to data safety JSON file").action(async (options) => {
|
|
48
43
|
const config = await loadConfig();
|
|
@@ -69,25 +64,16 @@ function registerDataSafetyCommands(program) {
|
|
|
69
64
|
process.exit(4);
|
|
70
65
|
}
|
|
71
66
|
});
|
|
72
|
-
dataSafety.command("export").description("Export data safety declaration to a JSON file").option("--output <path>", "Output file path", "data-safety.json").action(async (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (format === "json") {
|
|
80
|
-
console.log(formatOutput({ file: options.output, dataSafety: result }, format));
|
|
81
|
-
} else {
|
|
82
|
-
console.log(`Data safety declaration exported to ${options.output}`);
|
|
83
|
-
}
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
86
|
-
process.exit(4);
|
|
87
|
-
}
|
|
67
|
+
dataSafety.command("export").description("Export data safety declaration to a JSON file").option("--output <path>", "Output file path", "data-safety.json").action(async () => {
|
|
68
|
+
console.error("Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.");
|
|
69
|
+
console.error("Data safety labels cannot be exported via the API.");
|
|
70
|
+
console.error("");
|
|
71
|
+
console.error("To export your data safety declaration, use the Google Play Console:");
|
|
72
|
+
console.error(" App content \u2192 Data safety \u2192 Export to CSV");
|
|
73
|
+
process.exit(1);
|
|
88
74
|
});
|
|
89
75
|
}
|
|
90
76
|
export {
|
|
91
77
|
registerDataSafetyCommands
|
|
92
78
|
};
|
|
93
|
-
//# sourceMappingURL=data-safety-
|
|
79
|
+
//# sourceMappingURL=data-safety-DBA26FHB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/data-safety.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 getDataSafety,\n updateDataSafety,\n exportDataSafety,\n importDataSafety,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.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 registerDataSafetyCommands(program: Command): void {\n const dataSafety = program\n .command(\"data-safety\")\n .description(\"Manage data safety declarations\");\n\n // Get — not supported by Google Play API (no GET endpoint for data safety)\n dataSafety\n .command(\"get\")\n .description(\"Get the current data safety declaration\")\n .action(async () => {\n console.error(\"Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.\");\n console.error(\"\");\n console.error(\"Data safety labels can only be updated (not read) via the API.\");\n console.error(\"To view your current data safety declaration, use the Google Play Console:\");\n console.error(\" https://play.google.com/console → App content → Data safety\");\n console.error(\"\");\n console.error(\"To update data safety via the API, use: gpc data-safety update --file <csv-file>\");\n process.exit(1);\n });\n\n // Update\n dataSafety\n .command(\"update\")\n .description(\"Update data safety declaration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to data safety JSON file\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"data-safety update\",\n action: \"update data safety from\",\n target: options.file,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await importDataSafety(client, packageName, options.file);\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 // Export — not supported (no GET endpoint)\n dataSafety\n .command(\"export\")\n .description(\"Export data safety declaration to a JSON file\")\n .option(\"--output <path>\", \"Output file path\", \"data-safety.json\")\n .action(async () => {\n console.error(\"Error: The Google Play Developer API does not provide a GET endpoint for data safety declarations.\");\n console.error(\"Data safety labels cannot be exported via the API.\");\n console.error(\"\");\n console.error(\"To export your data safety declaration, use the Google Play Console:\");\n console.error(\" App content → Data safety → Export to CSV\");\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC;AAAA,EAIE;AAAA,EACA;AAAA,OACK;AAIP,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,gBAAgB,EAAE,KAAK,CAAC;AACjC;AAEO,SAAS,2BAA2B,SAAwB;AACjE,QAAM,aAAa,QAChB,QAAQ,aAAa,EACrB,YAAY,iCAAiC;AAGhD,aACG,QAAQ,KAAK,EACb,YAAY,yCAAyC,EACrD,OAAO,YAAY;AAClB,YAAQ,MAAM,oGAAoG;AAClH,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,gEAAgE;AAC9E,YAAQ,MAAM,4EAA4E;AAC1F,YAAQ,MAAM,yEAA+D;AAC7E,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,kFAAkF;AAChG,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGH,aACG,QAAQ,QAAQ,EAChB,YAAY,iDAAiD,EAC7D,eAAe,iBAAiB,+BAA+B,EAC/D,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,QAAQ;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,QAAQ,aAAa,QAAQ,IAAI;AACvE,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,aACG,QAAQ,QAAQ,EAChB,YAAY,+CAA+C,EAC3D,OAAO,mBAAmB,oBAAoB,kBAAkB,EAChE,OAAO,YAAY;AAClB,YAAQ,MAAM,oGAAoG;AAClH,YAAQ,MAAM,oDAAoD;AAClE,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,sEAAsE;AACpF,YAAQ,MAAM,uDAA6C;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;","names":[]}
|
|
@@ -35,6 +35,11 @@ function registerDeviceTiersCommands(program) {
|
|
|
35
35
|
const format = getOutputFormat(program, config);
|
|
36
36
|
try {
|
|
37
37
|
const result = await listDeviceTiers(client, packageName);
|
|
38
|
+
const configs = result["deviceTierConfigs"];
|
|
39
|
+
if (format !== "json" && (!configs || configs.length === 0)) {
|
|
40
|
+
console.log("No device tier configs found.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
38
43
|
console.log(formatOutput(result, format));
|
|
39
44
|
} catch (error) {
|
|
40
45
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -73,4 +78,4 @@ function registerDeviceTiersCommands(program) {
|
|
|
73
78
|
export {
|
|
74
79
|
registerDeviceTiersCommands
|
|
75
80
|
};
|
|
76
|
-
//# sourceMappingURL=device-tiers-
|
|
81
|
+
//# sourceMappingURL=device-tiers-V2R6AEXL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/device-tiers.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 listDeviceTiers,\n getDeviceTier,\n createDeviceTier,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { readFile } from \"node:fs/promises\";\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 registerDeviceTiersCommands(program: Command): void {\n const dt = program.command(\"device-tiers\").description(\"Manage device tier configurations\");\n\n dt.command(\"list\")\n .description(\"List device tier configurations\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listDeviceTiers(client, packageName);\n const configs = (result as Record<string, unknown>)[\"deviceTierConfigs\"] as unknown[] | undefined;\n if (format !== \"json\" && (!configs || configs.length === 0)) {\n console.log(\"No device tier configs found.\");\n return;\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 dt.command(\"get <config-id>\")\n .description(\"Get a device tier configuration\")\n .action(async (configId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getDeviceTier(client, packageName, configId);\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 dt.command(\"create\")\n .description(\"Create a device tier configuration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to JSON config file\")\n .action(async (opts: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const raw = await readFile(opts.file, \"utf-8\");\n const tierConfig = JSON.parse(raw);\n const result = await createDeviceTier(client, packageName, tierConfig);\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"],"mappings":";;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,gBAAgB;AAEzB,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,gBAAgB,EAAE,KAAK,CAAC;AACjC;AAEO,SAAS,4BAA4B,SAAwB;AAClE,QAAM,KAAK,QAAQ,QAAQ,cAAc,EAAE,YAAY,mCAAmC;AAE1F,KAAG,QAAQ,MAAM,EACd,YAAY,iCAAiC,EAC7C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,gBAAgB,QAAQ,WAAW;AACxD,YAAM,UAAW,OAAmC,mBAAmB;AACvE,UAAI,WAAW,WAAW,CAAC,WAAW,QAAQ,WAAW,IAAI;AAC3D,gBAAQ,IAAI,+BAA+B;AAC3C;AAAA,MACF;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,KAAG,QAAQ,iBAAiB,EACzB,YAAY,iCAAiC,EAC7C,OAAO,OAAO,aAAqB;AAClC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,QAAQ,aAAa,QAAQ;AAChE,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,KAAG,QAAQ,QAAQ,EAChB,YAAY,qDAAqD,EACjE,eAAe,iBAAiB,0BAA0B,EAC1D,OAAO,OAAO,SAA2B;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,MAAM,MAAM,SAAS,KAAK,MAAM,OAAO;AAC7C,YAAM,aAAa,KAAK,MAAM,GAAG;AACjC,YAAM,SAAS,MAAM,iBAAiB,QAAQ,aAAa,UAAU;AACrE,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -38,7 +38,22 @@ function registerGeneratedApksCommands(program) {
|
|
|
38
38
|
}
|
|
39
39
|
try {
|
|
40
40
|
const result = await listGeneratedApks(client, packageName, versionCode);
|
|
41
|
-
|
|
41
|
+
if (format !== "json") {
|
|
42
|
+
const apks = result["generatedApks"];
|
|
43
|
+
if (apks && apks.length > 0) {
|
|
44
|
+
const rows = apks.map((apk) => ({
|
|
45
|
+
id: apk["generatedApkId"] || "-",
|
|
46
|
+
variantId: apk["variantId"] || "-",
|
|
47
|
+
moduleName: apk["moduleName"] || "-",
|
|
48
|
+
sha256: String(apk["certificateSha256Fingerprint"] || "-").slice(0, 16) + "..."
|
|
49
|
+
}));
|
|
50
|
+
console.log(formatOutput(rows, format));
|
|
51
|
+
} else {
|
|
52
|
+
console.log("No generated APKs found.");
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
console.log(formatOutput(result, format));
|
|
56
|
+
}
|
|
42
57
|
} catch (error) {
|
|
43
58
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
59
|
process.exit(4);
|
|
@@ -72,4 +87,4 @@ function registerGeneratedApksCommands(program) {
|
|
|
72
87
|
export {
|
|
73
88
|
registerGeneratedApksCommands
|
|
74
89
|
};
|
|
75
|
-
//# sourceMappingURL=generated-apks-
|
|
90
|
+
//# sourceMappingURL=generated-apks-VX7HYZDU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/generated-apks.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 listGeneratedApks,\n downloadGeneratedApk,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.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 registerGeneratedApksCommands(program: Command): void {\n const cmd = program\n .command(\"generated-apks\")\n .description(\"Manage device-specific APKs generated by Google Play\");\n\n cmd\n .command(\"list <version-code>\")\n .description(\"List generated APKs for a version code\")\n .action(async (versionCodeStr: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const versionCode = parseInt(versionCodeStr, 10);\n if (isNaN(versionCode)) {\n console.error(\"Error: version-code must be a number\");\n process.exit(2);\n }\n\n try {\n const result = await listGeneratedApks(client, packageName, versionCode);\n if (format !== \"json\") {\n const apks = (result as Record<string, unknown>)[\"generatedApks\"] as Array<Record<string, unknown>> | undefined;\n if (apks && apks.length > 0) {\n const rows = apks.map((apk) => ({\n id: apk[\"generatedApkId\"] || \"-\",\n variantId: apk[\"variantId\"] || \"-\",\n moduleName: apk[\"moduleName\"] || \"-\",\n sha256: String(apk[\"certificateSha256Fingerprint\"] || \"-\").slice(0, 16) + \"...\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(\"No generated APKs found.\");\n }\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n cmd\n .command(\"download <version-code> <apk-id>\")\n .description(\"Download a generated APK\")\n .requiredOption(\"--output <path>\", \"Output file path\")\n .action(async (versionCodeStr: string, apkId: string, opts: { output: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const versionCode = parseInt(versionCodeStr, 10);\n if (isNaN(versionCode)) {\n console.error(\"Error: version-code must be a number\");\n process.exit(2);\n }\n\n try {\n const result = await downloadGeneratedApk(\n client,\n packageName,\n versionCode,\n apkId,\n opts.output,\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"],"mappings":";;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,gBAAgB,EAAE,KAAK,CAAC;AACjC;AAEO,SAAS,8BAA8B,SAAwB;AACpE,QAAM,MAAM,QACT,QAAQ,gBAAgB,EACxB,YAAY,sDAAsD;AAErE,MACG,QAAQ,qBAAqB,EAC7B,YAAY,wCAAwC,EACpD,OAAO,OAAO,mBAA2B;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,MAAM,sCAAsC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,kBAAkB,QAAQ,aAAa,WAAW;AACvE,UAAI,WAAW,QAAQ;AACrB,cAAM,OAAQ,OAAmC,eAAe;AAChE,YAAI,QAAQ,KAAK,SAAS,GAAG;AAC3B,gBAAM,OAAO,KAAK,IAAI,CAAC,SAAS;AAAA,YAC9B,IAAI,IAAI,gBAAgB,KAAK;AAAA,YAC7B,WAAW,IAAI,WAAW,KAAK;AAAA,YAC/B,YAAY,IAAI,YAAY,KAAK;AAAA,YACjC,QAAQ,OAAO,IAAI,8BAA8B,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI;AAAA,UAC5E,EAAE;AACF,kBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,QACxC,OAAO;AACL,kBAAQ,IAAI,0BAA0B;AAAA,QACxC;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,MACG,QAAQ,kCAAkC,EAC1C,YAAY,0BAA0B,EACtC,eAAe,mBAAmB,kBAAkB,EACpD,OAAO,OAAO,gBAAwB,OAAe,SAA6B;AACjF,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,cAAc,SAAS,gBAAgB,EAAE;AAC/C,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,MAAM,sCAAsC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AACA,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -192,10 +192,11 @@ function registerListingsCommands(program) {
|
|
|
192
192
|
const spinner = createSpinner("Pushing listings...");
|
|
193
193
|
if (!program.opts()["quiet"] && process.stderr.isTTY) spinner.start();
|
|
194
194
|
try {
|
|
195
|
+
const dryRun = isDryRun(program);
|
|
195
196
|
const result = await pushListings(client, packageName, options.dir, {
|
|
196
|
-
dryRun
|
|
197
|
+
dryRun
|
|
197
198
|
});
|
|
198
|
-
spinner.stop("Listings pushed");
|
|
199
|
+
spinner.stop(dryRun ? "Dry-run complete (no changes made)" : "Listings pushed");
|
|
199
200
|
console.log(formatOutput(result, format));
|
|
200
201
|
} catch (error) {
|
|
201
202
|
spinner.fail("Push failed");
|
|
@@ -372,6 +373,11 @@ function registerListingsCommands(program) {
|
|
|
372
373
|
const format = getOutputFormat(program, config);
|
|
373
374
|
try {
|
|
374
375
|
const result = await getCountryAvailability(client, packageName, options.track);
|
|
376
|
+
const countries = result["countryTargeting"];
|
|
377
|
+
if (format !== "json" && (!countries || Array.isArray(countries) && countries.length === 0) && Object.keys(result).length === 0) {
|
|
378
|
+
console.log("No availability data.");
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
375
381
|
console.log(formatOutput(result, format));
|
|
376
382
|
} catch (error) {
|
|
377
383
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -382,4 +388,4 @@ function registerListingsCommands(program) {
|
|
|
382
388
|
export {
|
|
383
389
|
registerListingsCommands
|
|
384
390
|
};
|
|
385
|
-
//# sourceMappingURL=listings-
|
|
391
|
+
//# sourceMappingURL=listings-VSBHQY5H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/listings.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 type { ImageType } from \"@gpc-cli/api\";\nimport {\n getListings,\n updateListing,\n deleteListing,\n pullListings,\n pushListings,\n diffListingsCommand,\n listImages,\n uploadImage,\n deleteImage,\n exportImages,\n getCountryAvailability,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\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\nconst VALID_IMAGE_TYPES: ImageType[] = [\n \"phoneScreenshots\",\n \"sevenInchScreenshots\",\n \"tenInchScreenshots\",\n \"tvScreenshots\",\n \"wearScreenshots\",\n \"icon\",\n \"featureGraphic\",\n \"tvBanner\",\n];\n\nfunction validateImageType(type: string): ImageType {\n if (!VALID_IMAGE_TYPES.includes(type as ImageType)) {\n console.error(`Error: Invalid image type \"${type}\".`);\n console.error(`Valid types: ${VALID_IMAGE_TYPES.join(\", \")}`);\n process.exit(2);\n }\n return type as ImageType;\n}\n\nexport function registerListingsCommands(program: Command): void {\n const listings = program.command(\"listings\").description(\"Manage store listings and metadata\");\n\n // Get\n listings\n .command(\"get\")\n .description(\"Get store listing(s)\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getListings(client, packageName, options.lang);\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 // Update\n listings\n .command(\"update\")\n .description(\"Update a store listing\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--title <text>\", \"App title\")\n .option(\"--short <text>\", \"Short description\")\n .option(\"--full <text>\", \"Full description\")\n .option(\"--full-file <path>\", \"Read full description from file\")\n .option(\"--video <url>\", \"Video URL\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n const format = getOutputFormat(program, config);\n\n try {\n const data: Record<string, string> = {};\n if (options[\"title\"]) data[\"title\"] = options[\"title\"];\n if (options[\"short\"]) data[\"shortDescription\"] = options[\"short\"];\n if (options[\"full\"]) data[\"fullDescription\"] = options[\"full\"];\n if (options[\"fullFile\"]) {\n const { readFile } = await import(\"node:fs/promises\");\n data[\"fullDescription\"] = (await readFile(options[\"fullFile\"], \"utf-8\")).trimEnd();\n }\n if (options[\"video\"]) data[\"video\"] = options[\"video\"];\n\n if (Object.keys(data).length === 0) {\n console.error(\n \"Error: Provide at least one field to update (--title, --short, --full, --full-file, --video).\",\n );\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"listings update\",\n action: \"update listing for\",\n target: options.lang,\n details: data,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n const result = await updateListing(client, packageName, options.lang, data);\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 // Delete\n listings\n .command(\"delete\")\n .description(\"Delete a store listing for a language\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n },\n interactive,\n );\n\n await requireConfirm(`Delete listing for \"${options.lang}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"listings delete\",\n action: \"delete listing for\",\n target: options.lang,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteListing(client, packageName, options.lang);\n console.log(`Listing for \"${options.lang}\" deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Pull\n listings\n .command(\"pull\")\n .description(\"Download listings to Fastlane-format directory\")\n .option(\"--dir <path>\", \"Target directory (default: metadata)\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await pullListings(client, packageName, options.dir);\n console.log(\n formatOutput(\n {\n directory: options.dir,\n languages: result.listings.map((l) => l.language),\n count: result.listings.length,\n },\n format,\n ),\n );\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Push\n listings\n .command(\"push\")\n .description(\"Upload listings from Fastlane-format directory\")\n .option(\"--dir <path>\", \"Source directory (default: metadata)\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const spinner = createSpinner(\"Pushing listings...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const dryRun = isDryRun(program);\n const result = await pushListings(client, packageName, options.dir, {\n dryRun,\n });\n spinner.stop(dryRun ? \"Dry-run complete (no changes made)\" : \"Listings pushed\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Push failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Diff\n listings\n .command(\"diff\")\n .description(\"Compare local Fastlane-format metadata against remote listings\")\n .option(\"--dir <path>\", \"Local metadata directory\", \"metadata\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const diffs = await diffListingsCommand(client, packageName, options.dir);\n\n if (diffs.length === 0) {\n if (format === \"json\") {\n console.log(formatOutput([], format));\n } else {\n console.log(\"No differences found.\");\n }\n return;\n }\n\n if (format === \"json\") {\n console.log(formatOutput(diffs, format));\n } else {\n for (const diff of diffs) {\n console.log(`[${diff.language}] ${diff.field}:`);\n console.log(` local: ${diff.local || \"(empty)\"}`);\n console.log(` remote: ${diff.remote || \"(empty)\"}`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images subcommand\n const images = listings.command(\"images\").description(\"Manage listing images\");\n\n // Images list\n images\n .command(\"list\")\n .description(\"List images for a language and type\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const imageType = validateImageType(options.type);\n\n try {\n const result = await listImages(client, packageName, options.lang, imageType);\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 // Images upload\n images\n .command(\"upload <file>\")\n .description(\"Upload an image\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .action(async (file: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n default: \"en-US\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const imageType = validateImageType(options.type);\n\n const spinner = createSpinner(\"Uploading image...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await uploadImage(client, packageName, options.lang, imageType, file);\n spinner.stop(\"Image uploaded\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Image upload failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images delete\n images\n .command(\"delete\")\n .description(\"Delete an image\")\n .option(\"--lang <language>\", \"Language code (BCP 47)\")\n .option(\"--type <type>\", \"Image type\")\n .option(\"--id <imageId>\", \"Image ID to delete\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.lang = await requireOption(\n \"lang\",\n options.lang,\n {\n message: \"Language code (BCP 47):\",\n },\n interactive,\n );\n\n options.type = await requireOption(\n \"type\",\n options.type,\n {\n message: \"Image type:\",\n choices: VALID_IMAGE_TYPES as unknown as string[],\n },\n interactive,\n );\n\n options.id = await requireOption(\n \"id\",\n options.id,\n {\n message: \"Image ID to delete:\",\n },\n interactive,\n );\n\n await requireConfirm(`Delete image \"${options.id}\"?`, program);\n\n const client = await getClient(config);\n const imageType = validateImageType(options.type);\n\n try {\n await deleteImage(client, packageName, options.lang, imageType, options.id);\n console.log(`Image \"${options.id}\" deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Images export\n images\n .command(\"export\")\n .description(\"Export all images to a local directory\")\n .option(\"--dir <path>\", \"Output directory\", \"images\")\n .option(\"--lang <language>\", \"Language code (BCP 47) — export only this language\")\n .option(\"--type <type>\", \"Image type — export only this type\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const exportOpts: { lang?: string; type?: ImageType } = {};\n if (options.lang) exportOpts.lang = options.lang;\n if (options.type) {\n exportOpts.type = validateImageType(options.type);\n }\n\n const spinner = createSpinner(\"Exporting images...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await exportImages(client, packageName, options.dir, exportOpts);\n spinner.stop(\"Images exported\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Image export failed\");\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Availability\n listings\n .command(\"availability\")\n .description(\"Get country availability for a track\")\n .option(\"--track <track>\", \"Track name\", \"production\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getCountryAvailability(client, packageName, options.track);\n const countries = (result as Record<string, unknown>)[\"countryTargeting\"] as unknown[] | undefined;\n if (format !== \"json\" && (!countries || (Array.isArray(countries) && countries.length === 0)) && Object.keys(result as object).length === 0) {\n console.log(\"No availability data.\");\n return;\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"],"mappings":"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","names":[]}
|
|
@@ -56,8 +56,13 @@ function registerOneTimeProductsCommands(program) {
|
|
|
56
56
|
if (options.sort) {
|
|
57
57
|
result.oneTimeProducts = sortResults(result.oneTimeProducts, options.sort);
|
|
58
58
|
}
|
|
59
|
+
const products = result.oneTimeProducts || [];
|
|
59
60
|
if (format !== "json") {
|
|
60
|
-
|
|
61
|
+
if (products.length === 0) {
|
|
62
|
+
console.log("No one-time products found.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const summary = products.map((p) => ({
|
|
61
66
|
productId: p.productId,
|
|
62
67
|
purchaseType: p["purchaseType"] || "-",
|
|
63
68
|
listings: p.listings ? Object.keys(p.listings).length : 0,
|
|
@@ -296,4 +301,4 @@ function registerOneTimeProductsCommands(program) {
|
|
|
296
301
|
export {
|
|
297
302
|
registerOneTimeProductsCommands
|
|
298
303
|
};
|
|
299
|
-
//# sourceMappingURL=one-time-products-
|
|
304
|
+
//# sourceMappingURL=one-time-products-2PK4QKWE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/one-time-products.ts"],"sourcesContent":["import 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 { OneTimeProduct } from \"@gpc-cli/api\";\nimport {\n listOneTimeProducts,\n getOneTimeProduct,\n createOneTimeProduct,\n updateOneTimeProduct,\n deleteOneTimeProduct,\n listOneTimeOffers,\n getOneTimeOffer,\n createOneTimeOffer,\n updateOneTimeOffer,\n deleteOneTimeOffer,\n diffOneTimeProduct,\n formatOutput,\n sortResults,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.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 registerOneTimeProductsCommands(program: Command): void {\n const otp = program\n .command(\"one-time-products\")\n .alias(\"otp\")\n .description(\"Manage one-time products and offers (modern OTP API)\");\n\n otp\n .command(\"list\")\n .description(\"List one-time products\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listOneTimeProducts(client, packageName);\n if (options.sort) {\n result.oneTimeProducts = sortResults(result.oneTimeProducts, options.sort);\n }\n const products = result.oneTimeProducts || [];\n if (format !== \"json\") {\n if (products.length === 0) {\n console.log(\"No one-time products found.\");\n return;\n }\n const summary = products.map((p: OneTimeProduct) => ({\n productId: p.productId,\n purchaseType: (p as Record<string, unknown>)[\"purchaseType\"] || \"-\",\n listings: p.listings ? Object.keys(p.listings).length : 0,\n firstTitle: p.listings ? Object.values(p.listings)[0]?.title || \"-\" : \"-\",\n }));\n console.log(formatOutput(summary, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n otp\n .command(\"get <product-id>\")\n .description(\"Get a one-time product\")\n .action(async (productId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getOneTimeProduct(client, packageName, productId);\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 otp\n .command(\"create\")\n .description(\"Create a one-time product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"one-time-products create\",\n action: \"create\",\n target: `one-time product from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = await readJsonFile(options.file);\n const result = await createOneTimeProduct(client, packageName, data as any);\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 otp\n .command(\"update <product-id>\")\n .description(\"Update a one-time product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(async (productId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"one-time-products update\",\n action: \"update\",\n target: productId,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = await readJsonFile(options.file);\n const result = await updateOneTimeProduct(client, packageName, productId, data as any, options.updateMask);\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 otp\n .command(\"delete <product-id>\")\n .description(\"Delete a one-time product\")\n .action(async (productId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete one-time product \"${productId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"one-time-products delete\",\n action: \"delete\",\n target: productId,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteOneTimeProduct(client, packageName, productId);\n console.log(`One-time product ${productId} deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // --- Offers ---\n const offers = otp.command(\"offers\").description(\"Manage one-time product offers\");\n\n offers\n .command(\"list <product-id>\")\n .description(\"List offers for a one-time product\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (productId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await listOneTimeOffers(client, packageName, productId);\n if (options.sort) {\n result.oneTimeOffers = sortResults(result.oneTimeOffers, options.sort);\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 offers\n .command(\"get <product-id> <offer-id>\")\n .description(\"Get an offer for a one-time product\")\n .action(async (productId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getOneTimeOffer(client, packageName, productId, offerId);\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 offers\n .command(\"create <product-id>\")\n .description(\"Create an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .action(async (productId: string, options: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"one-time-products offers create\",\n action: \"create offer for\",\n target: productId,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = await readJsonFile(options.file);\n const result = await createOneTimeOffer(client, packageName, productId, data as any);\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 offers\n .command(\"update <product-id> <offer-id>\")\n .description(\"Update an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(async (productId: string, offerId: string, options: { file: string; updateMask?: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"one-time-products offers update\",\n action: \"update offer\",\n target: `${productId}/${offerId}`,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const data = await readJsonFile(options.file);\n const result = await updateOneTimeOffer(client, packageName, productId, offerId, data as any, options.updateMask);\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 offers\n .command(\"delete <product-id> <offer-id>\")\n .description(\"Delete an offer\")\n .action(async (productId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete offer \"${offerId}\" for product \"${productId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"one-time-products offers delete\",\n action: \"delete offer\",\n target: `${productId}/${offerId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n await deleteOneTimeOffer(client, packageName, productId, offerId);\n console.log(`Offer ${offerId} deleted.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // --- Diff ---\n otp\n .command(\"diff <product-id>\")\n .description(\"Compare local JSON file against remote one-time product\")\n .requiredOption(\"--file <path>\", \"Local JSON file to compare against remote\")\n .action(async (productId: string, options: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const localData = await readJsonFile(options.file) as OneTimeProduct;\n const diffs = await diffOneTimeProduct(client, packageName, productId, localData);\n if (diffs.length === 0) {\n console.log(\"No differences found.\");\n } else {\n console.log(formatOutput(diffs, format));\n }\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":[]}
|
|
@@ -48,7 +48,26 @@ function registerPricingCommands(program) {
|
|
|
48
48
|
const format = getOutputFormat(program, config);
|
|
49
49
|
try {
|
|
50
50
|
const result = await convertRegionPrices(client, packageName, options.from, options.amount);
|
|
51
|
-
|
|
51
|
+
if (format !== "json") {
|
|
52
|
+
const prices = result["convertedRegionPrices"];
|
|
53
|
+
if (prices) {
|
|
54
|
+
const rows = Object.entries(prices).map(([region, data]) => {
|
|
55
|
+
const money = data["price"];
|
|
56
|
+
const units = money?.["units"] || "0";
|
|
57
|
+
const nanos = String(money?.["nanos"] || 0).padStart(9, "0").slice(0, 2);
|
|
58
|
+
return {
|
|
59
|
+
region,
|
|
60
|
+
price: money ? `${units}.${nanos}` : data["priceMicros"] ? String(Number(data["priceMicros"]) / 1e6) : "-",
|
|
61
|
+
currencyCode: money?.["currencyCode"] || data["currencyCode"] || "-"
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
console.log(formatOutput(rows, format));
|
|
65
|
+
} else {
|
|
66
|
+
console.log(formatOutput(result, format));
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
console.log(formatOutput(result, format));
|
|
70
|
+
}
|
|
52
71
|
} catch (error) {
|
|
53
72
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
54
73
|
process.exit(4);
|
|
@@ -58,4 +77,4 @@ function registerPricingCommands(program) {
|
|
|
58
77
|
export {
|
|
59
78
|
registerPricingCommands
|
|
60
79
|
};
|
|
61
|
-
//# sourceMappingURL=pricing-
|
|
80
|
+
//# sourceMappingURL=pricing-BYZSLN74.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/pricing.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 { convertRegionPrices, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.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 registerPricingCommands(program: Command): void {\n const pricing = program.command(\"pricing\").description(\"Pricing and regional price conversion\");\n\n pricing\n .command(\"convert\")\n .description(\"Convert a price to all regional prices\")\n .option(\"--from <currency>\", \"Source currency code (e.g. USD)\")\n .option(\"--amount <number>\", \"Price amount (e.g. 4.99)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const { isInteractive, requireOption } = await import(\"../prompt.js\");\n const interactive = isInteractive(program);\n\n options.from = await requireOption(\n \"from\",\n options.from,\n {\n message: \"Source currency code (e.g. USD):\",\n default: \"USD\",\n },\n interactive,\n );\n\n options.amount = await requireOption(\n \"amount\",\n options.amount,\n {\n message: \"Price amount (e.g. 4.99):\",\n },\n interactive,\n );\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await convertRegionPrices(client, packageName, options.from, options.amount);\n if (format !== \"json\") {\n const prices = (result as Record<string, unknown>)[\"convertedRegionPrices\"] as Record<string, Record<string, unknown>> | undefined;\n if (prices) {\n const rows = Object.entries(prices).map(([region, data]) => {\n const money = data[\"price\"] as Record<string, unknown> | undefined;\n const units = money?.[\"units\"] || \"0\";\n const nanos = String(money?.[\"nanos\"] || 0).padStart(9, \"0\").slice(0, 2);\n return {\n region,\n price: money ? `${units}.${nanos}` : (data[\"priceMicros\"] ? String(Number(data[\"priceMicros\"]) / 1_000_000) : \"-\"),\n currencyCode: (money?.[\"currencyCode\"] || data[\"currencyCode\"] || \"-\") as string,\n };\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC,SAAS,qBAAqB,oBAAoB;AAGlD,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,gBAAgB,EAAE,KAAK,CAAC;AACjC;AAEO,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,uCAAuC;AAE9F,UACG,QAAQ,SAAS,EACjB,YAAY,wCAAwC,EACpD,OAAO,qBAAqB,iCAAiC,EAC7D,OAAO,qBAAqB,0BAA0B,EACtD,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,EAAE,eAAe,cAAc,IAAI,MAAM,OAAO,sBAAc;AACpE,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,OAAO,MAAM;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,SAAS,MAAM;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,QAAQ,aAAa,QAAQ,MAAM,QAAQ,MAAM;AAC1F,UAAI,WAAW,QAAQ;AACrB,cAAM,SAAU,OAAmC,uBAAuB;AAC1E,YAAI,QAAQ;AACV,gBAAM,OAAO,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM;AAC1D,kBAAM,QAAQ,KAAK,OAAO;AAC1B,kBAAM,QAAQ,QAAQ,OAAO,KAAK;AAClC,kBAAM,QAAQ,OAAO,QAAQ,OAAO,KAAK,CAAC,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,GAAG,CAAC;AACvE,mBAAO;AAAA,cACL;AAAA,cACA,OAAO,QAAQ,GAAG,KAAK,IAAI,KAAK,KAAM,KAAK,aAAa,IAAI,OAAO,OAAO,KAAK,aAAa,CAAC,IAAI,GAAS,IAAI;AAAA,cAC9G,cAAe,QAAQ,cAAc,KAAK,KAAK,cAAc,KAAK;AAAA,YACpE;AAAA,UACF,CAAC;AACD,kBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,QACxC,OAAO;AACL,kBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,QAC1C;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/purchase-options.ts
|
|
4
|
+
var REDIRECT_MESSAGE = `Purchase options are managed through one-time product offers.
|
|
5
|
+
|
|
6
|
+
Use the following commands instead:
|
|
7
|
+
gpc otp offers list <product-id> List purchase options for a product
|
|
8
|
+
gpc otp offers get <product-id> <id> Get a specific purchase option
|
|
9
|
+
gpc otp offers create <product-id> Create a purchase option
|
|
10
|
+
gpc otp offers activate <product-id> <id>
|
|
11
|
+
gpc otp offers deactivate <product-id> <id>
|
|
12
|
+
|
|
13
|
+
See: gpc otp offers --help`;
|
|
14
|
+
function registerPurchaseOptionsCommands(program) {
|
|
15
|
+
const po = program.command("purchase-options").description("Manage purchase options (use 'otp offers' commands)");
|
|
16
|
+
po.command("list").description("List purchase options").option("--sort <field>", "Sort by field").action(async () => {
|
|
17
|
+
console.log(REDIRECT_MESSAGE);
|
|
18
|
+
process.exit(2);
|
|
19
|
+
});
|
|
20
|
+
po.command("get <id>").description("Get a purchase option").action(async () => {
|
|
21
|
+
console.log(REDIRECT_MESSAGE);
|
|
22
|
+
process.exit(2);
|
|
23
|
+
});
|
|
24
|
+
po.command("create").description("Create a purchase option").option("--file <path>", "JSON file with purchase option data").action(async () => {
|
|
25
|
+
console.log(REDIRECT_MESSAGE);
|
|
26
|
+
process.exit(2);
|
|
27
|
+
});
|
|
28
|
+
po.command("activate <id>").description("Activate a purchase option").action(async () => {
|
|
29
|
+
console.log(REDIRECT_MESSAGE);
|
|
30
|
+
process.exit(2);
|
|
31
|
+
});
|
|
32
|
+
po.command("deactivate <id>").description("Deactivate a purchase option").action(async () => {
|
|
33
|
+
console.log(REDIRECT_MESSAGE);
|
|
34
|
+
process.exit(2);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
registerPurchaseOptionsCommands
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=purchase-options-CKRN4VIW.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 console.log(REDIRECT_MESSAGE);\n process.exit(2);\n });\n\n po.command(\"get <id>\")\n .description(\"Get a purchase option\")\n .action(async () => {\n console.log(REDIRECT_MESSAGE);\n process.exit(2);\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 console.log(REDIRECT_MESSAGE);\n process.exit(2);\n });\n\n po.command(\"activate <id>\")\n .description(\"Activate a purchase option\")\n .action(async () => {\n console.log(REDIRECT_MESSAGE);\n process.exit(2);\n });\n\n po.command(\"deactivate <id>\")\n .description(\"Deactivate a purchase option\")\n .action(async () => {\n console.log(REDIRECT_MESSAGE);\n process.exit(2);\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,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAEH,KAAG,QAAQ,UAAU,EAClB,YAAY,uBAAuB,EACnC,OAAO,YAAY;AAClB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAEH,KAAG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,YAAY;AAClB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAEH,KAAG,QAAQ,eAAe,EACvB,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAClB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAEH,KAAG,QAAQ,iBAAiB,EACzB,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;","names":[]}
|
|
@@ -43,7 +43,20 @@ function registerRecoveryCommands(program) {
|
|
|
43
43
|
const client = await getClient(config);
|
|
44
44
|
const format = getOutputFormat(program, config);
|
|
45
45
|
try {
|
|
46
|
+
if (options.versionCode === void 0) {
|
|
47
|
+
console.error("Error: --version-code is required. The API requires a version code to filter recovery actions.");
|
|
48
|
+
console.error("Usage: gpc recovery list --version-code <code>");
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
46
51
|
const result = await listRecoveryActions(client, packageName, options.versionCode);
|
|
52
|
+
if (Array.isArray(result) && result.length === 0) {
|
|
53
|
+
if (format === "json") {
|
|
54
|
+
console.log(formatOutput([], format));
|
|
55
|
+
} else {
|
|
56
|
+
console.log("No recovery actions found.");
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
47
60
|
console.log(formatOutput(result, format));
|
|
48
61
|
} catch (error) {
|
|
49
62
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -176,4 +189,4 @@ function registerRecoveryCommands(program) {
|
|
|
176
189
|
export {
|
|
177
190
|
registerRecoveryCommands
|
|
178
191
|
};
|
|
179
|
-
//# sourceMappingURL=recovery-
|
|
192
|
+
//# sourceMappingURL=recovery-S5UNJDBO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/recovery.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 listRecoveryActions,\n cancelRecoveryAction,\n deployRecoveryAction,\n createRecoveryAction,\n addRecoveryTargeting,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readFileSync } from \"node:fs\";\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 registerRecoveryCommands(program: Command): void {\n const recovery = program.command(\"recovery\").description(\"Manage app recovery actions\");\n\n recovery\n .command(\"list\")\n .description(\"List app recovery actions\")\n .option(\"--version-code <code>\", \"Filter by version code\", parseInt)\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n if (options.versionCode === undefined) {\n console.error(\"Error: --version-code is required. The API requires a version code to filter recovery actions.\");\n console.error(\"Usage: gpc recovery list --version-code <code>\");\n process.exit(2);\n }\n const result = await listRecoveryActions(client, packageName, options.versionCode);\n if (Array.isArray(result) && result.length === 0) {\n if (format === \"json\") {\n console.log(formatOutput([], format));\n } else {\n console.log(\"No recovery actions found.\");\n }\n return;\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 recovery\n .command(\"cancel <id>\")\n .description(\"Cancel a recovery action\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"recovery cancel\",\n action: \"cancel\",\n target: id,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(`Cancel recovery action ${id}?`, program);\n\n const client = await getClient(config);\n\n try {\n await cancelRecoveryAction(client, packageName, id);\n console.log(formatOutput({ success: true, appRecoveryId: id, action: \"cancelled\" }, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n recovery\n .command(\"deploy <id>\")\n .description(\"Deploy a recovery action\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"recovery deploy\",\n action: \"deploy\",\n target: id,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(`Deploy recovery action ${id}?`, program);\n\n const client = await getClient(config);\n\n try {\n await deployRecoveryAction(client, packageName, id);\n console.log(formatOutput({ success: true, appRecoveryId: id, action: \"deployed\" }, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n recovery\n .command(\"create\")\n .description(\"Create a new app recovery action\")\n .requiredOption(\"--file <path>\", \"Path to JSON file with recovery action data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(readFileSync(options.file, \"utf-8\"));\n } catch (err) {\n console.error(\n `Error: Could not read recovery action data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"recovery create\",\n action: \"create recovery action\",\n target: packageName,\n details: data,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await createRecoveryAction(client, packageName, data);\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 recovery\n .command(\"add-targeting <action-id>\")\n .description(\"Add targeting rules to an existing recovery action\")\n .requiredOption(\"--file <path>\", \"Path to JSON file with targeting data\")\n .action(async (actionId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n let targeting: Record<string, unknown>;\n try {\n targeting = JSON.parse(readFileSync(options.file, \"utf-8\"));\n } catch (err) {\n console.error(\n `Error: Could not read targeting data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(2);\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"recovery add-targeting\",\n action: \"add targeting to recovery action\",\n target: actionId,\n details: targeting,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await addRecoveryTargeting(client, packageName, actionId, targeting);\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"],"mappings":"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","names":[]}
|