@gpc-cli/cli 0.1.1
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/LICENSE +21 -0
- package/dist/apps-BBYNHB2H.js +83 -0
- package/dist/apps-BBYNHB2H.js.map +1 -0
- package/dist/auth-T7IDSMVX.js +129 -0
- package/dist/auth-T7IDSMVX.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +36 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-4QV4WD3F.js +103 -0
- package/dist/chunk-4QV4WD3F.js.map +1 -0
- package/dist/chunk-IVVT73IP.js +245 -0
- package/dist/chunk-IVVT73IP.js.map +1 -0
- package/dist/chunk-QMKZYXDJ.js +24 -0
- package/dist/chunk-QMKZYXDJ.js.map +1 -0
- package/dist/completion-U44CGHRH.js +145 -0
- package/dist/completion-U44CGHRH.js.map +1 -0
- package/dist/config-K7UJKIXT.js +44 -0
- package/dist/config-K7UJKIXT.js.map +1 -0
- package/dist/docs-CVTWIVMS.js +20 -0
- package/dist/docs-CVTWIVMS.js.map +1 -0
- package/dist/doctor-VDDUPTIM.js +59 -0
- package/dist/doctor-VDDUPTIM.js.map +1 -0
- package/dist/iap-QIV4CXKZ.js +158 -0
- package/dist/iap-QIV4CXKZ.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/listings-PF5FDXKQ.js +261 -0
- package/dist/listings-PF5FDXKQ.js.map +1 -0
- package/dist/pricing-S4SB5FXJ.js +52 -0
- package/dist/pricing-S4SB5FXJ.js.map +1 -0
- package/dist/prompt-VP5LURRP.js +20 -0
- package/dist/prompt-VP5LURRP.js.map +1 -0
- package/dist/publish-3BAIN4NQ.js +114 -0
- package/dist/publish-3BAIN4NQ.js.map +1 -0
- package/dist/purchases-E6A2T5WQ.js +231 -0
- package/dist/purchases-E6A2T5WQ.js.map +1 -0
- package/dist/releases-464IMEEF.js +231 -0
- package/dist/releases-464IMEEF.js.map +1 -0
- package/dist/reports-3YAD4U4F.js +129 -0
- package/dist/reports-3YAD4U4F.js.map +1 -0
- package/dist/reviews-2CLM53E3.js +125 -0
- package/dist/reviews-2CLM53E3.js.map +1 -0
- package/dist/status-M7U3YNMU.js +32 -0
- package/dist/status-M7U3YNMU.js.map +1 -0
- package/dist/subscriptions-PUHH4FBB.js +376 -0
- package/dist/subscriptions-PUHH4FBB.js.map +1 -0
- package/dist/testers-WWZMLB7J.js +145 -0
- package/dist/testers-WWZMLB7J.js.map +1 -0
- package/dist/tracks-427E34S3.js +39 -0
- package/dist/tracks-427E34S3.js.map +1 -0
- package/dist/users-E5Y5HI6K.js +145 -0
- package/dist/users-E5Y5HI6K.js.map +1 -0
- package/dist/validate-TPKVSIMR.js +37 -0
- package/dist/validate-TPKVSIMR.js.map +1 -0
- package/dist/vitals-YMZMUPNA.js +166 -0
- package/dist/vitals-YMZMUPNA.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/releases.ts"],"sourcesContent":["import { appendFile } from \"node:fs/promises\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport type { RetryLogEntry } from \"@gpc-cli/api\";\nimport { uploadRelease, getReleasesStatus, promoteRelease, updateRollout, readReleaseNotesFromDir, writeAuditLog, createAuditEntry } from \"@gpc-cli/core\";\nimport { detectOutputFormat, formatOutput } from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, promptSelect, promptInput, promptConfirm, requireOption, requireConfirm } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: any): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nfunction createRetryLogger(retryLogPath?: string): ((entry: RetryLogEntry) => void) | undefined {\n if (!retryLogPath) return undefined;\n return (entry: RetryLogEntry) => {\n const line = JSON.stringify(entry) + \"\\n\";\n appendFile(retryLogPath, line).catch(() => {});\n };\n}\n\nasync function getClient(config: any, retryLogPath?: string) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth, onRetry: createRetryLogger(retryLogPath) });\n}\n\nexport function registerReleasesCommands(program: Command): void {\n const releases = program\n .command(\"releases\")\n .description(\"Manage releases and rollouts\");\n\n // Upload\n releases\n .command(\"upload <file>\")\n .description(\"Upload AAB/APK and assign to a track\")\n .option(\"--track <track>\", \"Target track\", \"internal\")\n .option(\"--rollout <percent>\", \"Staged rollout percentage (1-100)\")\n .option(\"--notes <text>\", \"Release notes (en-US)\")\n .option(\"--name <name>\", \"Release name\")\n .option(\"--mapping <file>\", \"ProGuard/R8 mapping file for deobfuscation\")\n .option(\"--notes-dir <dir>\", \"Read release notes from directory (<dir>/<lang>.txt)\")\n .option(\"--retry-log <path>\", \"Write retry log entries to file (JSONL)\")\n .action(async (file: string, options) => {\n if (options.notes && options.notesDir) {\n console.error(\"Error: Cannot use both --notes and --notes-dir\");\n process.exit(2);\n }\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const format = detectOutputFormat();\n\n // Interactive mode: prompt for missing options\n if (isInteractive(program)) {\n if (!options.track || options.track === \"internal\") {\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n options.track = await promptSelect(\"Select track:\", tracks, \"internal\");\n }\n\n if (!options.rollout && options.track === \"production\") {\n const rolloutStr = await promptInput(\"Staged rollout percentage (1-100, blank for full)\", \"100\");\n if (rolloutStr && rolloutStr !== \"100\") {\n options.rollout = rolloutStr;\n }\n }\n\n if (!options.notes && !options.notesDir) {\n const notes = await promptInput(\"Release notes (en-US, blank to skip)\");\n if (notes) options.notes = notes;\n }\n }\n\n if (isDryRun(program)) {\n printDryRun({\n command: \"releases upload\",\n action: \"upload\",\n target: file,\n details: { track: options.track, rollout: options.rollout },\n }, format, formatOutput);\n return;\n }\n\n const auditEntry = createAuditEntry(\"releases upload\", {\n file,\n track: options.track,\n rollout: options.rollout,\n }, packageName);\n\n const client = await getClient(config, options.retryLog);\n\n try {\n let releaseNotes: { language: string; text: string }[] | undefined;\n if (options.notesDir) {\n releaseNotes = await readReleaseNotesFromDir(options.notesDir);\n } else if (options.notes) {\n releaseNotes = [{ language: \"en-US\", text: options.notes }];\n }\n\n const result = await uploadRelease(client, packageName, file, {\n track: options.track,\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes,\n releaseName: options.name,\n mappingFile: options.mapping,\n });\n console.log(formatOutput(result, format));\n auditEntry.success = true;\n } catch (error) {\n auditEntry.success = false;\n auditEntry.error = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n } finally {\n auditEntry.durationMs = Date.now() - new Date(auditEntry.timestamp).getTime();\n writeAuditLog(auditEntry).catch(() => {});\n }\n });\n\n // Status\n releases\n .command(\"status\")\n .description(\"Show current release status across tracks\")\n .option(\"--track <track>\", \"Filter by track\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const statuses = await getReleasesStatus(client, packageName, options.track);\n console.log(formatOutput(statuses, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Promote\n releases\n .command(\"promote\")\n .description(\"Promote a release from one track to another\")\n .option(\"--from <track>\", \"Source track\")\n .option(\"--to <track>\", \"Target track\")\n .option(\"--rollout <percent>\", \"Staged rollout percentage\")\n .option(\"--notes <text>\", \"Release notes\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const format = detectOutputFormat();\n const interactive = isInteractive(program);\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n\n options.from = await requireOption(\"from\", options.from, {\n message: \"Source track:\",\n choices: tracks,\n }, interactive);\n\n options.to = await requireOption(\"to\", options.to, {\n message: \"Target track:\",\n choices: tracks.filter((t: string) => t !== options.from),\n }, interactive);\n\n if (isDryRun(program)) {\n printDryRun({\n command: \"releases promote\",\n action: \"promote\",\n target: `${options.from} → ${options.to}`,\n details: { rollout: options.rollout },\n }, format, formatOutput);\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await promoteRelease(client, packageName, options.from, options.to, {\n userFraction: options.rollout ? Number(options.rollout) / 100 : undefined,\n releaseNotes: options.notes ? [{ language: \"en-US\", text: options.notes }] : undefined,\n });\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n // Rollout subcommands\n const rollout = releases\n .command(\"rollout\")\n .description(\"Manage staged rollouts\");\n\n for (const action of [\"increase\", \"halt\", \"resume\", \"complete\"] as const) {\n const cmd = rollout\n .command(action)\n .description(`${action.charAt(0).toUpperCase() + action.slice(1)} a staged rollout`)\n .option(\"--track <track>\", \"Track name\");\n\n if (action === \"increase\") {\n cmd.option(\"--to <percent>\", \"New rollout percentage\");\n }\n\n cmd.action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const format = detectOutputFormat();\n const interactive = isInteractive(program);\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n\n options.track = await requireOption(\"track\", options.track, {\n message: \"Track:\",\n choices: tracks,\n }, interactive);\n\n if (action === \"increase\") {\n options.to = await requireOption(\"to\", options.to, {\n message: \"New rollout percentage (1-100):\",\n }, interactive);\n }\n\n if (isDryRun(program)) {\n printDryRun({\n command: `releases rollout ${action}`,\n action: action,\n target: options.track,\n details: { percentage: options.to },\n }, format, formatOutput);\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await updateRollout(\n client,\n packageName,\n options.track,\n action,\n options.to ? Number(options.to) / 100 : undefined,\n );\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n }\n\n // Release notes\n releases\n .command(\"notes\")\n .description(\"Set release notes\")\n .argument(\"<action>\", \"Action: set\")\n .option(\"--track <track>\", \"Track name\")\n .option(\"--lang <language>\", \"Language code\", \"en-US\")\n .option(\"--notes <text>\", \"Release notes text\")\n .option(\"--file <path>\", \"Read notes from file\")\n .action(async (action: string, options) => {\n if (action !== \"set\") {\n console.error(\"Usage: gpc releases notes set --track <track> --notes <text>\");\n process.exit(2);\n }\n\n const interactive = isInteractive(program);\n const tracks = [\"internal\", \"alpha\", \"beta\", \"production\"];\n\n options.track = await requireOption(\"track\", options.track, {\n message: \"Track:\",\n choices: tracks,\n }, interactive);\n\n let notesText = options.notes;\n if (options.file) {\n const { readFile } = await import(\"node:fs/promises\");\n notesText = await readFile(options.file, \"utf-8\");\n }\n\n if (!notesText && interactive) {\n notesText = await promptInput(\"Release notes text:\");\n }\n\n if (!notesText) {\n console.error(\"Provide --notes <text> or --file <path>\");\n process.exit(2);\n }\n\n console.log(`Release notes set for ${options.track} (${options.lang})`);\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isInteractive,
|
|
4
|
+
requireOption
|
|
5
|
+
} from "./chunk-4QV4WD3F.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/reports.ts
|
|
8
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
9
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
10
|
+
import { createApiClient } from "@gpc-cli/api";
|
|
11
|
+
import {
|
|
12
|
+
listReports,
|
|
13
|
+
downloadReport,
|
|
14
|
+
parseMonth,
|
|
15
|
+
isValidReportType,
|
|
16
|
+
isFinancialReportType,
|
|
17
|
+
isStatsReportType,
|
|
18
|
+
detectOutputFormat,
|
|
19
|
+
formatOutput
|
|
20
|
+
} from "@gpc-cli/core";
|
|
21
|
+
import { writeFile } from "fs/promises";
|
|
22
|
+
function resolvePackageName(packageArg, config) {
|
|
23
|
+
const name = packageArg || config.app;
|
|
24
|
+
if (!name) {
|
|
25
|
+
console.error("Error: No package name. Use --app <package> or gpc config set app <package>");
|
|
26
|
+
process.exit(2);
|
|
27
|
+
}
|
|
28
|
+
return name;
|
|
29
|
+
}
|
|
30
|
+
async function getClient(config) {
|
|
31
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
32
|
+
return createApiClient({ auth });
|
|
33
|
+
}
|
|
34
|
+
function registerReportsCommands(program) {
|
|
35
|
+
const reports = program.command("reports").description("Download financial and stats reports");
|
|
36
|
+
reports.command("list <report-type>").description("List available report buckets").option("--month <YYYY-MM>", "Report month (e.g., 2026-03)").action(async (reportType, options) => {
|
|
37
|
+
const interactive = isInteractive(program);
|
|
38
|
+
const now = /* @__PURE__ */ new Date();
|
|
39
|
+
const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
40
|
+
options.month = await requireOption("month", options.month, {
|
|
41
|
+
message: "Report month (YYYY-MM):",
|
|
42
|
+
default: defaultMonth
|
|
43
|
+
}, interactive);
|
|
44
|
+
if (!isValidReportType(reportType)) {
|
|
45
|
+
console.error(`Error: Invalid report type "${reportType}". Valid types: earnings, sales, estimated_sales, installs, crashes, ratings, reviews, store_performance, subscriptions, play_balance`);
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
const config = await loadConfig();
|
|
49
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
50
|
+
const client = await getClient(config);
|
|
51
|
+
const format = detectOutputFormat();
|
|
52
|
+
try {
|
|
53
|
+
const { year, month } = parseMonth(options.month);
|
|
54
|
+
const result = await listReports(client, packageName, reportType, year, month);
|
|
55
|
+
console.log(formatOutput(result, format));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
|
+
process.exit(4);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const download = reports.command("download").description("Download a report");
|
|
62
|
+
download.command("financial").description("Download a financial report").option("--month <YYYY-MM>", "Report month (e.g., 2026-03)").option("--type <report-type>", "Report type", "earnings").option("--output-file <path>", "Save to file instead of stdout").action(async (options) => {
|
|
63
|
+
const interactive = isInteractive(program);
|
|
64
|
+
const now = /* @__PURE__ */ new Date();
|
|
65
|
+
const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
66
|
+
options.month = await requireOption("month", options.month, {
|
|
67
|
+
message: "Report month (YYYY-MM):",
|
|
68
|
+
default: defaultMonth
|
|
69
|
+
}, interactive);
|
|
70
|
+
if (!isFinancialReportType(options.type)) {
|
|
71
|
+
console.error(`Error: Invalid financial report type "${options.type}". Valid types: earnings, sales, estimated_sales, play_balance`);
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
const config = await loadConfig();
|
|
75
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
76
|
+
const client = await getClient(config);
|
|
77
|
+
try {
|
|
78
|
+
const { year, month } = parseMonth(options.month);
|
|
79
|
+
const csv = await downloadReport(client, packageName, options.type, year, month);
|
|
80
|
+
if (options.outputFile) {
|
|
81
|
+
await writeFile(options.outputFile, csv, "utf-8");
|
|
82
|
+
console.log(`Report saved to ${options.outputFile}`);
|
|
83
|
+
} else {
|
|
84
|
+
console.log(csv);
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
process.exit(4);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
download.command("stats").description("Download a stats report").option("--month <YYYY-MM>", "Report month (e.g., 2026-03)").option("--type <report-type>", "Report type (installs, crashes, ratings, reviews, store_performance, subscriptions)").option("--output-file <path>", "Save to file instead of stdout").action(async (options) => {
|
|
92
|
+
const interactive = isInteractive(program);
|
|
93
|
+
const now = /* @__PURE__ */ new Date();
|
|
94
|
+
const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
95
|
+
const statsTypes = ["installs", "crashes", "ratings", "reviews", "store_performance", "subscriptions"];
|
|
96
|
+
options.month = await requireOption("month", options.month, {
|
|
97
|
+
message: "Report month (YYYY-MM):",
|
|
98
|
+
default: defaultMonth
|
|
99
|
+
}, interactive);
|
|
100
|
+
options.type = await requireOption("type", options.type, {
|
|
101
|
+
message: "Stats report type:",
|
|
102
|
+
choices: statsTypes
|
|
103
|
+
}, interactive);
|
|
104
|
+
if (!isStatsReportType(options.type)) {
|
|
105
|
+
console.error(`Error: Invalid stats report type "${options.type}". Valid types: installs, crashes, ratings, reviews, store_performance, subscriptions`);
|
|
106
|
+
process.exit(2);
|
|
107
|
+
}
|
|
108
|
+
const config = await loadConfig();
|
|
109
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
110
|
+
const client = await getClient(config);
|
|
111
|
+
try {
|
|
112
|
+
const { year, month } = parseMonth(options.month);
|
|
113
|
+
const csv = await downloadReport(client, packageName, options.type, year, month);
|
|
114
|
+
if (options.outputFile) {
|
|
115
|
+
await writeFile(options.outputFile, csv, "utf-8");
|
|
116
|
+
console.log(`Report saved to ${options.outputFile}`);
|
|
117
|
+
} else {
|
|
118
|
+
console.log(csv);
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
122
|
+
process.exit(4);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
export {
|
|
127
|
+
registerReportsCommands
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=reports-3YAD4U4F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/reports.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n listReports,\n downloadReport,\n parseMonth,\n isValidReportType,\n isFinancialReportType,\n isStatsReportType,\n isValidStatsDimension,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport type { ReportType, StatsDimension } from \"@gpc-cli/api\";\nimport { writeFile } from \"node:fs/promises\";\nimport { isInteractive, requireOption } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: any): 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: any) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth });\n}\n\nexport function registerReportsCommands(program: Command): void {\n const reports = program\n .command(\"reports\")\n .description(\"Download financial and stats reports\");\n\n reports\n .command(\"list <report-type>\")\n .description(\"List available report buckets\")\n .option(\"--month <YYYY-MM>\", \"Report month (e.g., 2026-03)\")\n .action(async (reportType: string, options) => {\n const interactive = isInteractive(program);\n const now = new Date();\n const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}`;\n\n options.month = await requireOption(\"month\", options.month, {\n message: \"Report month (YYYY-MM):\",\n default: defaultMonth,\n }, interactive);\n\n if (!isValidReportType(reportType)) {\n console.error(`Error: Invalid report type \"${reportType}\". Valid types: earnings, sales, estimated_sales, installs, crashes, ratings, reviews, store_performance, subscriptions, play_balance`);\n process.exit(2);\n }\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const { year, month } = parseMonth(options.month);\n const result = await listReports(client, packageName, reportType as ReportType, year, month);\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 const download = reports\n .command(\"download\")\n .description(\"Download a report\");\n\n download\n .command(\"financial\")\n .description(\"Download a financial report\")\n .option(\"--month <YYYY-MM>\", \"Report month (e.g., 2026-03)\")\n .option(\"--type <report-type>\", \"Report type\", \"earnings\")\n .option(\"--output-file <path>\", \"Save to file instead of stdout\")\n .action(async (options) => {\n const interactive = isInteractive(program);\n const now = new Date();\n const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}`;\n\n options.month = await requireOption(\"month\", options.month, {\n message: \"Report month (YYYY-MM):\",\n default: defaultMonth,\n }, interactive);\n\n if (!isFinancialReportType(options.type)) {\n console.error(`Error: Invalid financial report type \"${options.type}\". Valid types: earnings, sales, estimated_sales, play_balance`);\n process.exit(2);\n }\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n\n try {\n const { year, month } = parseMonth(options.month);\n const csv = await downloadReport(client, packageName, options.type as ReportType, year, month);\n if (options.outputFile) {\n await writeFile(options.outputFile, csv, \"utf-8\");\n console.log(`Report saved to ${options.outputFile}`);\n } else {\n console.log(csv);\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n download\n .command(\"stats\")\n .description(\"Download a stats report\")\n .option(\"--month <YYYY-MM>\", \"Report month (e.g., 2026-03)\")\n .option(\"--type <report-type>\", \"Report type (installs, crashes, ratings, reviews, store_performance, subscriptions)\")\n .option(\"--output-file <path>\", \"Save to file instead of stdout\")\n .action(async (options) => {\n const interactive = isInteractive(program);\n const now = new Date();\n const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}`;\n const statsTypes = [\"installs\", \"crashes\", \"ratings\", \"reviews\", \"store_performance\", \"subscriptions\"];\n\n options.month = await requireOption(\"month\", options.month, {\n message: \"Report month (YYYY-MM):\",\n default: defaultMonth,\n }, interactive);\n\n options.type = await requireOption(\"type\", options.type, {\n message: \"Stats report type:\",\n choices: statsTypes,\n }, interactive);\n\n if (!isStatsReportType(options.type)) {\n console.error(`Error: Invalid stats report type \"${options.type}\". Valid types: installs, crashes, ratings, reviews, store_performance, subscriptions`);\n process.exit(2);\n }\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n\n try {\n const { year, month } = parseMonth(options.month);\n const csv = await downloadReport(client, packageName, options.type as ReportType, year, month);\n if (options.outputFile) {\n await writeFile(options.outputFile, csv, \"utf-8\");\n console.log(`Report saved to ${options.outputFile}`);\n } else {\n console.log(csv);\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":[]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isDryRun,
|
|
4
|
+
printDryRun
|
|
5
|
+
} from "./chunk-QMKZYXDJ.js";
|
|
6
|
+
import {
|
|
7
|
+
isInteractive,
|
|
8
|
+
requireOption
|
|
9
|
+
} from "./chunk-4QV4WD3F.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/reviews.ts
|
|
12
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
13
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
14
|
+
import { createApiClient } from "@gpc-cli/api";
|
|
15
|
+
import {
|
|
16
|
+
listReviews,
|
|
17
|
+
getReview,
|
|
18
|
+
replyToReview,
|
|
19
|
+
exportReviews,
|
|
20
|
+
detectOutputFormat,
|
|
21
|
+
formatOutput
|
|
22
|
+
} from "@gpc-cli/core";
|
|
23
|
+
function resolvePackageName(packageArg, config) {
|
|
24
|
+
const name = packageArg || config.app;
|
|
25
|
+
if (!name) {
|
|
26
|
+
console.error("Error: No package name. Use --app <package> or gpc config set app <package>");
|
|
27
|
+
process.exit(2);
|
|
28
|
+
}
|
|
29
|
+
return name;
|
|
30
|
+
}
|
|
31
|
+
async function getClient(config) {
|
|
32
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
33
|
+
return createApiClient({ auth });
|
|
34
|
+
}
|
|
35
|
+
function registerReviewsCommands(program) {
|
|
36
|
+
const reviews = program.command("reviews").description("Manage user reviews and ratings");
|
|
37
|
+
reviews.command("list").description("List user reviews").option("--stars <n>", "Filter by star rating (1-5)", parseInt).option("--lang <code>", "Filter by reviewer language").option("--since <date>", "Filter reviews after date (ISO 8601)").option("--translate-to <lang>", "Translate reviews to language").option("--max <n>", "Maximum number of reviews per page", parseInt).option("--limit <n>", "Maximum total results", parseInt).option("--next-page <token>", "Resume from page token").action(async (options) => {
|
|
38
|
+
const config = await loadConfig();
|
|
39
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
40
|
+
const client = await getClient(config);
|
|
41
|
+
const format = detectOutputFormat();
|
|
42
|
+
try {
|
|
43
|
+
const result = await listReviews(client, packageName, {
|
|
44
|
+
stars: options.stars,
|
|
45
|
+
language: options.lang,
|
|
46
|
+
since: options.since,
|
|
47
|
+
translationLanguage: options.translateTo,
|
|
48
|
+
maxResults: options.max,
|
|
49
|
+
limit: options.limit,
|
|
50
|
+
nextPage: options.nextPage
|
|
51
|
+
});
|
|
52
|
+
console.log(formatOutput(result, format));
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
55
|
+
process.exit(4);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
reviews.command("get <review-id>").description("Get a single review").option("--translate-to <lang>", "Translate review to language").action(async (reviewId, options) => {
|
|
59
|
+
const config = await loadConfig();
|
|
60
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
61
|
+
const client = await getClient(config);
|
|
62
|
+
const format = detectOutputFormat();
|
|
63
|
+
try {
|
|
64
|
+
const result = await getReview(client, packageName, reviewId, options.translateTo);
|
|
65
|
+
console.log(formatOutput(result, format));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
process.exit(4);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
reviews.command("reply <review-id>").description("Reply to a review").option("--text <text>", "Reply text (max 350 chars)").action(async (reviewId, options) => {
|
|
72
|
+
const config = await loadConfig();
|
|
73
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
74
|
+
const format = detectOutputFormat();
|
|
75
|
+
const interactive = isInteractive(program);
|
|
76
|
+
options.text = await requireOption("text", options.text, {
|
|
77
|
+
message: "Reply text (max 350 chars):"
|
|
78
|
+
}, interactive);
|
|
79
|
+
if (isDryRun(program)) {
|
|
80
|
+
printDryRun({
|
|
81
|
+
command: "reviews reply",
|
|
82
|
+
action: "reply to",
|
|
83
|
+
target: reviewId,
|
|
84
|
+
details: { text: options.text }
|
|
85
|
+
}, format, formatOutput);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const client = await getClient(config);
|
|
89
|
+
try {
|
|
90
|
+
const result = await replyToReview(client, packageName, reviewId, options.text);
|
|
91
|
+
console.log(formatOutput(result, format));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
94
|
+
process.exit(4);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
reviews.command("export").description("Export reviews to JSON or CSV").option("--format <type>", "Output format: json or csv", "json").option("--stars <n>", "Filter by star rating (1-5)", parseInt).option("--lang <code>", "Filter by reviewer language").option("--since <date>", "Filter reviews after date (ISO 8601)").option("--translate-to <lang>", "Translate reviews to language").option("--output <file>", "Write output to file instead of stdout").action(async (options) => {
|
|
98
|
+
const config = await loadConfig();
|
|
99
|
+
const packageName = resolvePackageName(program.opts().app, config);
|
|
100
|
+
const client = await getClient(config);
|
|
101
|
+
try {
|
|
102
|
+
const result = await exportReviews(client, packageName, {
|
|
103
|
+
format: options.format,
|
|
104
|
+
stars: options.stars,
|
|
105
|
+
language: options.lang,
|
|
106
|
+
since: options.since,
|
|
107
|
+
translationLanguage: options.translateTo
|
|
108
|
+
});
|
|
109
|
+
if (options.output) {
|
|
110
|
+
const { writeFile } = await import("fs/promises");
|
|
111
|
+
await writeFile(options.output, result, "utf-8");
|
|
112
|
+
console.log(`Reviews exported to ${options.output}`);
|
|
113
|
+
} else {
|
|
114
|
+
console.log(result);
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
118
|
+
process.exit(4);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
registerReviewsCommands
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=reviews-2CLM53E3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/reviews.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport {\n listReviews,\n getReview,\n replyToReview,\n exportReviews,\n detectOutputFormat,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption } from \"../prompt.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: any): 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: any) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createApiClient({ auth });\n}\n\nexport function registerReviewsCommands(program: Command): void {\n const reviews = program\n .command(\"reviews\")\n .description(\"Manage user reviews and ratings\");\n\n reviews\n .command(\"list\")\n .description(\"List user reviews\")\n .option(\"--stars <n>\", \"Filter by star rating (1-5)\", parseInt)\n .option(\"--lang <code>\", \"Filter by reviewer language\")\n .option(\"--since <date>\", \"Filter reviews after date (ISO 8601)\")\n .option(\"--translate-to <lang>\", \"Translate reviews to language\")\n .option(\"--max <n>\", \"Maximum number of reviews per page\", parseInt)\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await listReviews(client, packageName, {\n stars: options.stars,\n language: options.lang,\n since: options.since,\n translationLanguage: options.translateTo,\n maxResults: options.max,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n console.log(formatOutput(result, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n\n reviews\n .command(\"get <review-id>\")\n .description(\"Get a single review\")\n .option(\"--translate-to <lang>\", \"Translate review to language\")\n .action(async (reviewId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n const format = detectOutputFormat();\n\n try {\n const result = await getReview(client, packageName, reviewId, options.translateTo);\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 reviews\n .command(\"reply <review-id>\")\n .description(\"Reply to a review\")\n .option(\"--text <text>\", \"Reply text (max 350 chars)\")\n .action(async (reviewId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const format = detectOutputFormat();\n const interactive = isInteractive(program);\n\n options.text = await requireOption(\"text\", options.text, {\n message: \"Reply text (max 350 chars):\",\n }, interactive);\n\n if (isDryRun(program)) {\n printDryRun({\n command: \"reviews reply\",\n action: \"reply to\",\n target: reviewId,\n details: { text: options.text },\n }, format, formatOutput);\n return;\n }\n\n const client = await getClient(config);\n\n try {\n const result = await replyToReview(client, packageName, reviewId, options.text);\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 reviews\n .command(\"export\")\n .description(\"Export reviews to JSON or CSV\")\n .option(\"--format <type>\", \"Output format: json or csv\", \"json\")\n .option(\"--stars <n>\", \"Filter by star rating (1-5)\", parseInt)\n .option(\"--lang <code>\", \"Filter by reviewer language\")\n .option(\"--since <date>\", \"Filter reviews after date (ISO 8601)\")\n .option(\"--translate-to <lang>\", \"Translate reviews to language\")\n .option(\"--output <file>\", \"Write output to file instead of stdout\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts().app, config);\n const client = await getClient(config);\n\n try {\n const result = await exportReviews(client, packageName, {\n format: options.format as \"json\" | \"csv\",\n stars: options.stars,\n language: options.lang,\n since: options.since,\n translationLanguage: options.translateTo,\n });\n\n if (options.output) {\n const { writeFile } = await import(\"node:fs/promises\");\n await writeFile(options.output, result, \"utf-8\");\n console.log(`Reviews exported to ${options.output}`);\n } else {\n console.log(result);\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":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/status.ts
|
|
4
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
5
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
6
|
+
import { createApiClient } from "@gpc-cli/api";
|
|
7
|
+
import { getReleasesStatus } from "@gpc-cli/core";
|
|
8
|
+
import { detectOutputFormat, formatOutput } from "@gpc-cli/core";
|
|
9
|
+
function registerStatusCommand(program) {
|
|
10
|
+
program.command("status").description("Cross-track release overview").action(async () => {
|
|
11
|
+
const config = await loadConfig();
|
|
12
|
+
const packageName = program.opts().app || config.app;
|
|
13
|
+
if (!packageName) {
|
|
14
|
+
console.error("Error: No package name. Use --app <package> or gpc config set app <package>");
|
|
15
|
+
process.exit(2);
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
19
|
+
const client = createApiClient({ auth });
|
|
20
|
+
const statuses = await getReleasesStatus(client, packageName);
|
|
21
|
+
const format = detectOutputFormat();
|
|
22
|
+
console.log(formatOutput(statuses, format));
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
process.exit(4);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
registerStatusCommand
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=status-M7U3YNMU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport { getReleasesStatus } from \"@gpc-cli/core\";\nimport { detectOutputFormat, formatOutput } from \"@gpc-cli/core\";\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Cross-track release overview\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = program.opts().app || config.app;\n if (!packageName) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n\n try {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const statuses = await getReleasesStatus(client, packageName);\n const format = detectOutputFormat();\n console.log(formatOutput(statuses, format));\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;AACA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,oBAAoB,oBAAoB;AAE1C,SAAS,sBAAsB,SAAwB;AAC5D,UACG,QAAQ,QAAQ,EAChB,YAAY,8BAA8B,EAC1C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,QAAQ,KAAK,EAAE,OAAO,OAAO;AACjD,QAAI,CAAC,aAAa;AAChB,cAAQ,MAAM,6EAA6E;AAC3F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,YAAM,SAAS,gBAAgB,EAAE,KAAK,CAAC;AACvC,YAAM,WAAW,MAAM,kBAAkB,QAAQ,WAAW;AAC5D,YAAM,SAAS,mBAAmB;AAClC,cAAQ,IAAI,aAAa,UAAU,MAAM,CAAC;AAAA,IAC5C,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":[]}
|