@gpc-cli/cli 0.9.61 → 0.9.63
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/README.md +1 -1
- package/dist/bin.js +2 -2
- package/dist/changelog-MPBEELTH.js +307 -0
- package/dist/changelog-MPBEELTH.js.map +1 -0
- package/dist/{chunk-CWJJ2BNH.js → chunk-QXXXY5CO.js} +8 -8
- package/dist/{config-FNZAEO4G.js → config-JMLIMKYJ.js} +2 -2
- package/dist/{doctor-2DWDH7FC.js → doctor-2R7WLRD4.js} +2 -2
- package/dist/{feedback-O4HR6XLM.js → feedback-MLQTM5EB.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{update-HIJOMQGO.js → update-MHWSESO4.js} +2 -2
- package/dist/{version-55ADSAN4.js → version-ZHOZKZ2I.js} +2 -2
- package/package.json +3 -3
- package/dist/changelog-PPTJ7BHJ.js +0 -100
- package/dist/changelog-PPTJ7BHJ.js.map +0 -1
- /package/dist/{chunk-CWJJ2BNH.js.map → chunk-QXXXY5CO.js.map} +0 -0
- /package/dist/{config-FNZAEO4G.js.map → config-JMLIMKYJ.js.map} +0 -0
- /package/dist/{doctor-2DWDH7FC.js.map → doctor-2R7WLRD4.js.map} +0 -0
- /package/dist/{feedback-O4HR6XLM.js.map → feedback-MLQTM5EB.js.map} +0 -0
- /package/dist/{update-HIJOMQGO.js.map → update-MHWSESO4.js.map} +0 -0
- /package/dist/{version-55ADSAN4.js.map → version-ZHOZKZ2I.js.map} +0 -0
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ curl -fsSL https://raw.githubusercontent.com/yasserstudio/gpc/main/scripts/insta
|
|
|
87
87
|
- [Commands reference](https://yasserstudio.github.io/gpc/commands/)
|
|
88
88
|
- [CI/CD recipes](https://yasserstudio.github.io/gpc/ci-cd/)
|
|
89
89
|
|
|
90
|
-
Free to use. 1,
|
|
90
|
+
Free to use. 1,999 tests. 90%+ coverage. Every write operation supports `--dry-run`.
|
|
91
91
|
|
|
92
92
|
## Licensing
|
|
93
93
|
|
package/dist/bin.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createProgram,
|
|
4
4
|
handleCliError,
|
|
5
5
|
loadPlugins
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QXXXY5CO.js";
|
|
7
7
|
import {
|
|
8
8
|
checkForUpdate,
|
|
9
9
|
formatUpdateNotification
|
|
@@ -57,7 +57,7 @@ if (!_isJsonMode && !_isQuiet && !_isSetupCommand && !existsSync(getUserConfigPa
|
|
|
57
57
|
}
|
|
58
58
|
await setupNetworking();
|
|
59
59
|
initAudit(getConfigDir());
|
|
60
|
-
var currentVersion = "0.9.
|
|
60
|
+
var currentVersion = "0.9.63";
|
|
61
61
|
var isUpdateCommand = process.argv[2] === "update";
|
|
62
62
|
var isCompletionProvider = process.argv[2] === "__complete";
|
|
63
63
|
var updateCheckPromise = isUpdateCommand || isCompletionProvider ? Promise.resolve(null) : checkForUpdate(currentVersion);
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getClient,
|
|
4
|
+
resolvePackageName
|
|
5
|
+
} from "./chunk-JDRY7HK5.js";
|
|
6
|
+
import {
|
|
7
|
+
dim,
|
|
8
|
+
yellow
|
|
9
|
+
} from "./chunk-FAN4ZITI.js";
|
|
10
|
+
import {
|
|
11
|
+
getOutputFormat
|
|
12
|
+
} from "./chunk-ELXAK7GI.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/changelog.ts
|
|
15
|
+
import {
|
|
16
|
+
fetchChangelog,
|
|
17
|
+
formatChangelogEntry,
|
|
18
|
+
formatOutput,
|
|
19
|
+
generateChangelog,
|
|
20
|
+
RENDERERS,
|
|
21
|
+
renderPlayStore,
|
|
22
|
+
renderPlayStoreMd,
|
|
23
|
+
renderPlayStorePrompt,
|
|
24
|
+
buildLocaleBundle,
|
|
25
|
+
translateBundle,
|
|
26
|
+
resolveAiConfig,
|
|
27
|
+
createTranslator,
|
|
28
|
+
fetchAggregateCost,
|
|
29
|
+
formatPathLabel,
|
|
30
|
+
PROVIDER_WHITELIST,
|
|
31
|
+
resolveLocales,
|
|
32
|
+
GpcError
|
|
33
|
+
} from "@gpc-cli/core";
|
|
34
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
35
|
+
var VALID_OUTPUT_MODES = ["md", "json", "prompt"];
|
|
36
|
+
var VALID_TARGETS = ["github", "play-store"];
|
|
37
|
+
var REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
38
|
+
function registerChangelogCommand(program) {
|
|
39
|
+
const changelog = program.command("changelog").description("Show release history").option("-n, --limit <count>", "Number of releases to show", parseInt, 5).option("--tag <tag>", "Show a specific release (e.g., v0.9.43)").option("--all", "Show all releases").action(async (opts) => {
|
|
40
|
+
const config = await loadConfig();
|
|
41
|
+
const format = getOutputFormat(program, config);
|
|
42
|
+
const entries = await fetchChangelog({
|
|
43
|
+
limit: opts.all ? 100 : opts.limit,
|
|
44
|
+
version: opts.tag
|
|
45
|
+
});
|
|
46
|
+
if (entries.length === 0) {
|
|
47
|
+
console.log("No releases found.");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (format === "json") {
|
|
51
|
+
console.log(formatOutput(entries, "json"));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (opts.tag || entries.length === 1) {
|
|
55
|
+
console.log(formatChangelogEntry(entries[0]));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const header = "VERSION DATE TITLE";
|
|
59
|
+
const separator = "\u2500".repeat(header.length);
|
|
60
|
+
console.log(header);
|
|
61
|
+
console.log(separator);
|
|
62
|
+
for (const entry of entries) {
|
|
63
|
+
const version = entry.version.padEnd(12);
|
|
64
|
+
const date = entry.date.padEnd(12);
|
|
65
|
+
console.log(`${version} ${date} ${entry.title}`);
|
|
66
|
+
}
|
|
67
|
+
console.log("");
|
|
68
|
+
console.log(
|
|
69
|
+
`Showing ${entries.length} releases. Use --tag <tag> for details, or --all for full history.`
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
changelog.command("generate").description("Generate release notes from local git commits").option("--from <ref>", "Starting ref (default: latest v* tag)").option("--to <ref>", "Ending ref (default: HEAD)").option("--format <mode>", "Renderer: md, json, or prompt", "md").option("--repo <owner/name>", "Override auto-detected repo (e.g., yasserstudio/gpc)").option("--target <mode>", "Output target: github or play-store", "github").option("--locales <csv|auto>", "Comma-separated BCP 47 locales, or 'auto' (play-store target only)").option("--ai", "Translate non-source locales via LLM (play-store target only, BYO key)").option(
|
|
73
|
+
"--provider <name>",
|
|
74
|
+
`AI provider (${PROVIDER_WHITELIST.join("|")}). Defaults to first env key detected`
|
|
75
|
+
).option("--model <id>", "Override default model for the chosen provider").option("--strict", "Exit non-zero if warnings, overflows, or translation failures occur").action(
|
|
76
|
+
async (opts) => {
|
|
77
|
+
const dryRun = !!program.opts()["dryRun"];
|
|
78
|
+
const mode = opts.format;
|
|
79
|
+
if (!VALID_OUTPUT_MODES.includes(mode)) {
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
`Invalid --format "${opts.format}". Valid: ${VALID_OUTPUT_MODES.join(", ")}
|
|
82
|
+
`
|
|
83
|
+
);
|
|
84
|
+
process.exitCode = 2;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!VALID_TARGETS.includes(opts.target)) {
|
|
88
|
+
process.stderr.write(
|
|
89
|
+
`Invalid --target "${opts.target}". Valid: ${VALID_TARGETS.join(", ")}
|
|
90
|
+
`
|
|
91
|
+
);
|
|
92
|
+
process.exitCode = 2;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const target = opts.target;
|
|
96
|
+
if (opts.repo && !REPO_RE.test(opts.repo)) {
|
|
97
|
+
process.stderr.write(
|
|
98
|
+
`Invalid --repo "${opts.repo}". Expected "owner/name" (e.g., yasserstudio/gpc).
|
|
99
|
+
`
|
|
100
|
+
);
|
|
101
|
+
process.exitCode = 2;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (target === "github" && opts.locales) {
|
|
105
|
+
process.stderr.write(
|
|
106
|
+
`--locales only applies to --target play-store (current target: github)
|
|
107
|
+
`
|
|
108
|
+
);
|
|
109
|
+
process.exitCode = 2;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (target === "github" && (opts.ai || opts.provider || opts.model)) {
|
|
113
|
+
process.stderr.write(
|
|
114
|
+
"--ai / --provider / --model only apply to --target play-store\n"
|
|
115
|
+
);
|
|
116
|
+
process.exitCode = 2;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (opts.ai && opts.format === "prompt" && !dryRun) {
|
|
120
|
+
process.stderr.write(
|
|
121
|
+
"--ai with --format prompt only makes sense with --dry-run\n (otherwise it would re-wrap translated text in a translation prompt).\n Hint: use --format md or --format json for live translation, or add --dry-run to inspect the prompt.\n"
|
|
122
|
+
);
|
|
123
|
+
process.exitCode = 2;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (target === "play-store" && !opts.locales) {
|
|
127
|
+
process.stderr.write(
|
|
128
|
+
"--target play-store requires --locales <csv|auto>\n Example: --locales en-US,fr-FR,de-DE\n Example: --locales auto (reads current Play Store listing \u2014 requires --app)\n"
|
|
129
|
+
);
|
|
130
|
+
process.exitCode = 2;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const generated = await generateChangelog({
|
|
134
|
+
from: opts.from,
|
|
135
|
+
to: opts.to,
|
|
136
|
+
repo: opts.repo
|
|
137
|
+
});
|
|
138
|
+
for (const w of generated.warnings) {
|
|
139
|
+
process.stderr.write(`${yellow("warn:")} ${w}
|
|
140
|
+
`);
|
|
141
|
+
}
|
|
142
|
+
if (generated.warnings.length > 0) {
|
|
143
|
+
process.stderr.write(
|
|
144
|
+
`${dim(`(${generated.warnings.length} warning${generated.warnings.length === 1 ? "" : "s"} \u2014 review before publishing)`)}
|
|
145
|
+
`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (target === "github") {
|
|
149
|
+
const output = RENDERERS[mode](generated);
|
|
150
|
+
console.log(output);
|
|
151
|
+
if (opts.strict && generated.warnings.length > 0) {
|
|
152
|
+
process.exitCode = 1;
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
let locales;
|
|
157
|
+
try {
|
|
158
|
+
if (opts.locales === "auto") {
|
|
159
|
+
const config = await loadConfig();
|
|
160
|
+
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
161
|
+
const client = await getClient(config);
|
|
162
|
+
locales = await resolveLocales("auto", { client, packageName });
|
|
163
|
+
} else {
|
|
164
|
+
locales = await resolveLocales(opts.locales);
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error instanceof GpcError) {
|
|
168
|
+
process.stderr.write(`${error.message}
|
|
169
|
+
`);
|
|
170
|
+
if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}
|
|
171
|
+
`);
|
|
172
|
+
process.exitCode = error.exitCode;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
const playStoreFormat = mode;
|
|
178
|
+
if (!opts.ai) {
|
|
179
|
+
const { output, bundle } = renderPlayStore(generated, {
|
|
180
|
+
locales,
|
|
181
|
+
format: playStoreFormat
|
|
182
|
+
});
|
|
183
|
+
console.log(output);
|
|
184
|
+
for (const lang of bundle.overflows) {
|
|
185
|
+
process.stderr.write(
|
|
186
|
+
`${yellow("warn:")} ${lang} exceeds ${bundle.limit} chars (truncated)
|
|
187
|
+
`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const hasOverflow2 = bundle.overflows.length > 0;
|
|
191
|
+
const hasWarnings2 = generated.warnings.length > 0;
|
|
192
|
+
if (opts.strict && (hasWarnings2 || hasOverflow2)) {
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let aiConfig;
|
|
198
|
+
try {
|
|
199
|
+
aiConfig = resolveAiConfig({ provider: opts.provider, model: opts.model });
|
|
200
|
+
} catch (error) {
|
|
201
|
+
if (error instanceof GpcError) {
|
|
202
|
+
process.stderr.write(`${error.message}
|
|
203
|
+
`);
|
|
204
|
+
if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}
|
|
205
|
+
`);
|
|
206
|
+
process.exitCode = error.exitCode;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
process.stderr.write(`${dim(`\u2192 ${formatPathLabel(aiConfig)}`)}
|
|
212
|
+
`);
|
|
213
|
+
const baseBundle = buildLocaleBundle(generated, {
|
|
214
|
+
locales,
|
|
215
|
+
format: playStoreFormat
|
|
216
|
+
});
|
|
217
|
+
if (dryRun) {
|
|
218
|
+
const preview = renderPlayStorePrompt(baseBundle, generated);
|
|
219
|
+
console.log(preview);
|
|
220
|
+
process.stderr.write(
|
|
221
|
+
`${dim("(--dry-run: no API call was made; the prompt above is what would be sent per locale)")}
|
|
222
|
+
`
|
|
223
|
+
);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const translator = await createTranslator(aiConfig);
|
|
227
|
+
let translated;
|
|
228
|
+
try {
|
|
229
|
+
translated = await translateBundle(baseBundle, {
|
|
230
|
+
translator,
|
|
231
|
+
strict: opts.strict,
|
|
232
|
+
onError: ({ language, reason }) => {
|
|
233
|
+
process.stderr.write(
|
|
234
|
+
`${yellow("warn:")} ${language} translation failed: ${reason}
|
|
235
|
+
`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
} catch (error) {
|
|
240
|
+
if (error instanceof GpcError) {
|
|
241
|
+
process.stderr.write(`${error.message}
|
|
242
|
+
`);
|
|
243
|
+
if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}
|
|
244
|
+
`);
|
|
245
|
+
process.exitCode = error.exitCode;
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
const costUsd = aiConfig.path === "gateway" ? await fetchAggregateCost(aiConfig.runId) : void 0;
|
|
251
|
+
const aiBlock = {
|
|
252
|
+
path: aiConfig.path,
|
|
253
|
+
provider: aiConfig.provider,
|
|
254
|
+
model: aiConfig.model,
|
|
255
|
+
tokensIn: translated.tokensIn,
|
|
256
|
+
tokensOut: translated.tokensOut
|
|
257
|
+
};
|
|
258
|
+
if (aiConfig.path === "gateway") {
|
|
259
|
+
aiBlock["runId"] = aiConfig.runId;
|
|
260
|
+
if (typeof costUsd === "number") aiBlock["costUsd"] = costUsd;
|
|
261
|
+
}
|
|
262
|
+
if (playStoreFormat === "json") {
|
|
263
|
+
const payload = {
|
|
264
|
+
from: translated.from,
|
|
265
|
+
to: translated.to,
|
|
266
|
+
limit: translated.limit,
|
|
267
|
+
sourceLanguage: translated.sourceLanguage,
|
|
268
|
+
ai: aiBlock,
|
|
269
|
+
locales: translated.locales,
|
|
270
|
+
overflows: translated.overflows,
|
|
271
|
+
failures: translated.failures
|
|
272
|
+
};
|
|
273
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
274
|
+
} else if (playStoreFormat === "prompt") {
|
|
275
|
+
console.log(renderPlayStorePrompt(translated, generated));
|
|
276
|
+
} else {
|
|
277
|
+
console.log(renderPlayStoreMd(translated));
|
|
278
|
+
}
|
|
279
|
+
for (const lang of translated.overflows) {
|
|
280
|
+
process.stderr.write(
|
|
281
|
+
`${yellow("warn:")} ${lang} exceeds ${translated.limit} chars (truncated)
|
|
282
|
+
`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
if (translated.failures.length > 0) {
|
|
286
|
+
process.stderr.write(
|
|
287
|
+
`${dim(`(${translated.failures.length} locale${translated.failures.length === 1 ? "" : "s"} failed \u2014 see placeholders in output)`)}
|
|
288
|
+
`
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
if (typeof costUsd === "number") {
|
|
292
|
+
process.stderr.write(`${dim(`(run cost: $${costUsd.toFixed(4)})`)}
|
|
293
|
+
`);
|
|
294
|
+
}
|
|
295
|
+
const hasOverflow = translated.overflows.length > 0;
|
|
296
|
+
const hasWarnings = generated.warnings.length > 0;
|
|
297
|
+
const hasFailures = translated.failures.length > 0;
|
|
298
|
+
if (opts.strict && (hasWarnings || hasOverflow || hasFailures)) {
|
|
299
|
+
process.exitCode = 1;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
export {
|
|
305
|
+
registerChangelogCommand
|
|
306
|
+
};
|
|
307
|
+
//# sourceMappingURL=changelog-MPBEELTH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/changelog.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n fetchChangelog,\n formatChangelogEntry,\n formatOutput,\n generateChangelog,\n RENDERERS,\n renderPlayStore,\n renderPlayStoreMd,\n renderPlayStorePrompt,\n buildLocaleBundle,\n translateBundle,\n resolveAiConfig,\n createTranslator,\n fetchAggregateCost,\n formatPathLabel,\n PROVIDER_WHITELIST,\n resolveLocales,\n GpcError,\n type OutputMode,\n type PlayStoreFormat,\n} from \"@gpc-cli/core\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { getOutputFormat } from \"../format.js\";\nimport { yellow, dim } from \"../colors.js\";\nimport { resolvePackageName, getClient } from \"../resolve.js\";\n\nconst VALID_OUTPUT_MODES: OutputMode[] = [\"md\", \"json\", \"prompt\"];\nconst VALID_TARGETS = [\"github\", \"play-store\"] as const;\ntype ChangelogTarget = (typeof VALID_TARGETS)[number];\nconst REPO_RE = /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/;\n\nexport function registerChangelogCommand(program: Command): void {\n const changelog = program\n .command(\"changelog\")\n .description(\"Show release history\")\n .option(\"-n, --limit <count>\", \"Number of releases to show\", parseInt, 5)\n .option(\"--tag <tag>\", \"Show a specific release (e.g., v0.9.43)\")\n .option(\"--all\", \"Show all releases\")\n .action(async (opts: { limit: number; tag?: string; all?: boolean }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n const entries = await fetchChangelog({\n limit: opts.all ? 100 : opts.limit,\n version: opts.tag,\n });\n\n if (entries.length === 0) {\n console.log(\"No releases found.\");\n return;\n }\n\n if (format === \"json\") {\n console.log(formatOutput(entries, \"json\"));\n return;\n }\n\n if (opts.tag || entries.length === 1) {\n console.log(formatChangelogEntry(entries[0]!));\n return;\n }\n\n const header = \"VERSION DATE TITLE\";\n const separator = \"─\".repeat(header.length);\n console.log(header);\n console.log(separator);\n for (const entry of entries) {\n const version = entry.version.padEnd(12);\n const date = entry.date.padEnd(12);\n console.log(`${version} ${date} ${entry.title}`);\n }\n console.log(\"\");\n console.log(\n `Showing ${entries.length} releases. Use --tag <tag> for details, or --all for full history.`,\n );\n });\n\n changelog\n .command(\"generate\")\n .description(\"Generate release notes from local git commits\")\n .option(\"--from <ref>\", \"Starting ref (default: latest v* tag)\")\n .option(\"--to <ref>\", \"Ending ref (default: HEAD)\")\n .option(\"--format <mode>\", \"Renderer: md, json, or prompt\", \"md\")\n .option(\"--repo <owner/name>\", \"Override auto-detected repo (e.g., yasserstudio/gpc)\")\n .option(\"--target <mode>\", \"Output target: github or play-store\", \"github\")\n .option(\"--locales <csv|auto>\", \"Comma-separated BCP 47 locales, or 'auto' (play-store target only)\")\n .option(\"--ai\", \"Translate non-source locales via LLM (play-store target only, BYO key)\")\n .option(\n \"--provider <name>\",\n `AI provider (${PROVIDER_WHITELIST.join(\"|\")}). Defaults to first env key detected`,\n )\n .option(\"--model <id>\", \"Override default model for the chosen provider\")\n .option(\"--strict\", \"Exit non-zero if warnings, overflows, or translation failures occur\")\n .action(\n async (opts: {\n from?: string;\n to?: string;\n format: string;\n repo?: string;\n target: string;\n locales?: string;\n strict?: boolean;\n ai?: boolean;\n provider?: string;\n model?: string;\n }) => {\n const dryRun = !!program.opts()[\"dryRun\"];\n const mode = opts.format as OutputMode;\n if (!VALID_OUTPUT_MODES.includes(mode)) {\n process.stderr.write(\n `Invalid --format \"${opts.format}\". Valid: ${VALID_OUTPUT_MODES.join(\", \")}\\n`,\n );\n process.exitCode = 2;\n return;\n }\n if (!VALID_TARGETS.includes(opts.target as ChangelogTarget)) {\n process.stderr.write(\n `Invalid --target \"${opts.target}\". Valid: ${VALID_TARGETS.join(\", \")}\\n`,\n );\n process.exitCode = 2;\n return;\n }\n const target = opts.target as ChangelogTarget;\n if (opts.repo && !REPO_RE.test(opts.repo)) {\n process.stderr.write(\n `Invalid --repo \"${opts.repo}\". Expected \"owner/name\" (e.g., yasserstudio/gpc).\\n`,\n );\n process.exitCode = 2;\n return;\n }\n if (target === \"github\" && opts.locales) {\n process.stderr.write(\n `--locales only applies to --target play-store (current target: github)\\n`,\n );\n process.exitCode = 2;\n return;\n }\n // Only block when the AI-adjacent flags are explicitly set. The root\n // program has its own `--dry-run` flag that may already be set\n // globally by the user for unrelated reasons; we silently ignore it\n // on non-AI code paths.\n if (target === \"github\" && (opts.ai || opts.provider || opts.model)) {\n process.stderr.write(\n \"--ai / --provider / --model only apply to --target play-store\\n\",\n );\n process.exitCode = 2;\n return;\n }\n // --format prompt + --ai is nonsensical outside --dry-run: it would\n // render a \"please translate this\" prompt from already-translated\n // text. Either inspect the prompt via --dry-run, or pick md/json.\n if (opts.ai && opts.format === \"prompt\" && !dryRun) {\n process.stderr.write(\n \"--ai with --format prompt only makes sense with --dry-run\\n\" +\n \" (otherwise it would re-wrap translated text in a translation prompt).\\n\" +\n \" Hint: use --format md or --format json for live translation, or add --dry-run to inspect the prompt.\\n\",\n );\n process.exitCode = 2;\n return;\n }\n if (target === \"play-store\" && !opts.locales) {\n process.stderr.write(\n \"--target play-store requires --locales <csv|auto>\\n\" +\n \" Example: --locales en-US,fr-FR,de-DE\\n\" +\n \" Example: --locales auto (reads current Play Store listing — requires --app)\\n\",\n );\n process.exitCode = 2;\n return;\n }\n\n const generated = await generateChangelog({\n from: opts.from,\n to: opts.to,\n repo: opts.repo,\n });\n\n for (const w of generated.warnings) {\n process.stderr.write(`${yellow(\"warn:\")} ${w}\\n`);\n }\n if (generated.warnings.length > 0) {\n process.stderr.write(\n `${dim(`(${generated.warnings.length} warning${generated.warnings.length === 1 ? \"\" : \"s\"} — review before publishing)`)}\\n`,\n );\n }\n\n if (target === \"github\") {\n const output = RENDERERS[mode](generated);\n console.log(output);\n if (opts.strict && generated.warnings.length > 0) {\n process.exitCode = 1;\n }\n return;\n }\n\n // target === \"play-store\"\n let locales: string[];\n try {\n if (opts.locales === \"auto\") {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n locales = await resolveLocales(\"auto\", { client, packageName });\n } else {\n locales = await resolveLocales(opts.locales!);\n }\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n const playStoreFormat = mode as PlayStoreFormat;\n\n // Non-AI path: existing v0.9.62 behavior\n if (!opts.ai) {\n const { output, bundle } = renderPlayStore(generated, {\n locales,\n format: playStoreFormat,\n });\n console.log(output);\n\n for (const lang of bundle.overflows) {\n process.stderr.write(\n `${yellow(\"warn:\")} ${lang} exceeds ${bundle.limit} chars (truncated)\\n`,\n );\n }\n\n const hasOverflow = bundle.overflows.length > 0;\n const hasWarnings = generated.warnings.length > 0;\n if (opts.strict && (hasWarnings || hasOverflow)) {\n process.exitCode = 1;\n }\n return;\n }\n\n // --ai path: resolve config, translate, render with ai block\n let aiConfig;\n try {\n aiConfig = resolveAiConfig({ provider: opts.provider, model: opts.model });\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n process.stderr.write(`${dim(`→ ${formatPathLabel(aiConfig)}`)}\\n`);\n\n const baseBundle = buildLocaleBundle(generated, {\n locales,\n format: playStoreFormat,\n });\n\n if (dryRun) {\n const preview = renderPlayStorePrompt(baseBundle, generated);\n console.log(preview);\n process.stderr.write(\n `${dim(\"(--dry-run: no API call was made; the prompt above is what would be sent per locale)\")}\\n`,\n );\n return;\n }\n\n const translator = await createTranslator(aiConfig);\n let translated;\n try {\n translated = await translateBundle(baseBundle, {\n translator,\n strict: opts.strict,\n onError: ({ language, reason }) => {\n process.stderr.write(\n `${yellow(\"warn:\")} ${language} translation failed: ${reason}\\n`,\n );\n },\n });\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n const costUsd =\n aiConfig.path === \"gateway\" ? await fetchAggregateCost(aiConfig.runId) : undefined;\n\n const aiBlock: Record<string, unknown> = {\n path: aiConfig.path,\n provider: aiConfig.provider,\n model: aiConfig.model,\n tokensIn: translated.tokensIn,\n tokensOut: translated.tokensOut,\n };\n if (aiConfig.path === \"gateway\") {\n aiBlock[\"runId\"] = aiConfig.runId;\n if (typeof costUsd === \"number\") aiBlock[\"costUsd\"] = costUsd;\n }\n\n if (playStoreFormat === \"json\") {\n const payload = {\n from: translated.from,\n to: translated.to,\n limit: translated.limit,\n sourceLanguage: translated.sourceLanguage,\n ai: aiBlock,\n locales: translated.locales,\n overflows: translated.overflows,\n failures: translated.failures,\n };\n console.log(JSON.stringify(payload, null, 2));\n } else if (playStoreFormat === \"prompt\") {\n console.log(renderPlayStorePrompt(translated, generated));\n } else {\n console.log(renderPlayStoreMd(translated));\n }\n\n for (const lang of translated.overflows) {\n process.stderr.write(\n `${yellow(\"warn:\")} ${lang} exceeds ${translated.limit} chars (truncated)\\n`,\n );\n }\n\n if (translated.failures.length > 0) {\n process.stderr.write(\n `${dim(`(${translated.failures.length} locale${translated.failures.length === 1 ? \"\" : \"s\"} failed — see placeholders in output)`)}\\n`,\n );\n }\n\n if (typeof costUsd === \"number\") {\n process.stderr.write(`${dim(`(run cost: $${costUsd.toFixed(4)})`)}\\n`);\n }\n\n const hasOverflow = translated.overflows.length > 0;\n const hasWarnings = generated.warnings.length > 0;\n const hasFailures = translated.failures.length > 0;\n if (opts.strict && (hasWarnings || hasOverflow || hasFailures)) {\n process.exitCode = 1;\n }\n },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,kBAAkB;AAK3B,IAAM,qBAAmC,CAAC,MAAM,QAAQ,QAAQ;AAChE,IAAM,gBAAgB,CAAC,UAAU,YAAY;AAE7C,IAAM,UAAU;AAET,SAAS,yBAAyB,SAAwB;AAC/D,QAAM,YAAY,QACf,QAAQ,WAAW,EACnB,YAAY,sBAAsB,EAClC,OAAO,uBAAuB,8BAA8B,UAAU,CAAC,EACvE,OAAO,eAAe,yCAAyC,EAC/D,OAAO,SAAS,mBAAmB,EACnC,OAAO,OAAO,SAAyD;AACtE,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,UAAU,MAAM,eAAe;AAAA,MACnC,OAAO,KAAK,MAAM,MAAM,KAAK;AAAA,MAC7B,SAAS,KAAK;AAAA,IAChB,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAI,oBAAoB;AAChC;AAAA,IACF;AAEA,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,aAAa,SAAS,MAAM,CAAC;AACzC;AAAA,IACF;AAEA,QAAI,KAAK,OAAO,QAAQ,WAAW,GAAG;AACpC,cAAQ,IAAI,qBAAqB,QAAQ,CAAC,CAAE,CAAC;AAC7C;AAAA,IACF;AAEA,UAAM,SAAS;AACf,UAAM,YAAY,SAAI,OAAO,OAAO,MAAM;AAC1C,YAAQ,IAAI,MAAM;AAClB,YAAQ,IAAI,SAAS;AACrB,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,YAAM,OAAO,MAAM,KAAK,OAAO,EAAE;AACjC,cAAQ,IAAI,GAAG,OAAO,IAAI,IAAI,IAAI,MAAM,KAAK,EAAE;AAAA,IACjD;AACA,YAAQ,IAAI,EAAE;AACd,YAAQ;AAAA,MACN,WAAW,QAAQ,MAAM;AAAA,IAC3B;AAAA,EACF,CAAC;AAEH,YACG,QAAQ,UAAU,EAClB,YAAY,+CAA+C,EAC3D,OAAO,gBAAgB,uCAAuC,EAC9D,OAAO,cAAc,4BAA4B,EACjD,OAAO,mBAAmB,iCAAiC,IAAI,EAC/D,OAAO,uBAAuB,sDAAsD,EACpF,OAAO,mBAAmB,uCAAuC,QAAQ,EACzE,OAAO,wBAAwB,oEAAoE,EACnG,OAAO,QAAQ,wEAAwE,EACvF;AAAA,IACC;AAAA,IACA,gBAAgB,mBAAmB,KAAK,GAAG,CAAC;AAAA,EAC9C,EACC,OAAO,gBAAgB,gDAAgD,EACvE,OAAO,YAAY,qEAAqE,EACxF;AAAA,IACC,OAAO,SAWD;AACJ,YAAM,SAAS,CAAC,CAAC,QAAQ,KAAK,EAAE,QAAQ;AACxC,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,mBAAmB,SAAS,IAAI,GAAG;AACtC,gBAAQ,OAAO;AAAA,UACb,qBAAqB,KAAK,MAAM,aAAa,mBAAmB,KAAK,IAAI,CAAC;AAAA;AAAA,QAC5E;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,UAAI,CAAC,cAAc,SAAS,KAAK,MAAyB,GAAG;AAC3D,gBAAQ,OAAO;AAAA,UACb,qBAAqB,KAAK,MAAM,aAAa,cAAc,KAAK,IAAI,CAAC;AAAA;AAAA,QACvE;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,YAAM,SAAS,KAAK;AACpB,UAAI,KAAK,QAAQ,CAAC,QAAQ,KAAK,KAAK,IAAI,GAAG;AACzC,gBAAQ,OAAO;AAAA,UACb,mBAAmB,KAAK,IAAI;AAAA;AAAA,QAC9B;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,UAAI,WAAW,YAAY,KAAK,SAAS;AACvC,gBAAQ,OAAO;AAAA,UACb;AAAA;AAAA,QACF;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AAKA,UAAI,WAAW,aAAa,KAAK,MAAM,KAAK,YAAY,KAAK,QAAQ;AACnE,gBAAQ,OAAO;AAAA,UACb;AAAA,QACF;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AAIA,UAAI,KAAK,MAAM,KAAK,WAAW,YAAY,CAAC,QAAQ;AAClD,gBAAQ,OAAO;AAAA,UACb;AAAA,QAGF;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,UAAI,WAAW,gBAAgB,CAAC,KAAK,SAAS;AAC5C,gBAAQ,OAAO;AAAA,UACb;AAAA,QAGF;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AAEA,YAAM,YAAY,MAAM,kBAAkB;AAAA,QACxC,MAAM,KAAK;AAAA,QACX,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,MACb,CAAC;AAED,iBAAW,KAAK,UAAU,UAAU;AAClC,gBAAQ,OAAO,MAAM,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC;AAAA,CAAI;AAAA,MAClD;AACA,UAAI,UAAU,SAAS,SAAS,GAAG;AACjC,gBAAQ,OAAO;AAAA,UACb,GAAG,IAAI,IAAI,UAAU,SAAS,MAAM,WAAW,UAAU,SAAS,WAAW,IAAI,KAAK,GAAG,mCAA8B,CAAC;AAAA;AAAA,QAC1H;AAAA,MACF;AAEA,UAAI,WAAW,UAAU;AACvB,cAAM,SAAS,UAAU,IAAI,EAAE,SAAS;AACxC,gBAAQ,IAAI,MAAM;AAClB,YAAI,KAAK,UAAU,UAAU,SAAS,SAAS,GAAG;AAChD,kBAAQ,WAAW;AAAA,QACrB;AACA;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,YAAI,KAAK,YAAY,QAAQ;AAC3B,gBAAM,SAAS,MAAM,WAAW;AAChC,gBAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,gBAAM,SAAS,MAAM,UAAU,MAAM;AACrC,oBAAU,MAAM,eAAe,QAAQ,EAAE,QAAQ,YAAY,CAAC;AAAA,QAChE,OAAO;AACL,oBAAU,MAAM,eAAe,KAAK,OAAQ;AAAA,QAC9C;AAAA,MACF,SAAS,OAAO;AACd,YAAI,iBAAiB,UAAU;AAC7B,kBAAQ,OAAO,MAAM,GAAG,MAAM,OAAO;AAAA,CAAI;AACzC,cAAI,MAAM,WAAY,SAAQ,OAAO,MAAM,GAAG,IAAI,MAAM,UAAU,CAAC;AAAA,CAAI;AACvE,kBAAQ,WAAW,MAAM;AACzB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAEA,YAAM,kBAAkB;AAGxB,UAAI,CAAC,KAAK,IAAI;AACZ,cAAM,EAAE,QAAQ,OAAO,IAAI,gBAAgB,WAAW;AAAA,UACpD;AAAA,UACA,QAAQ;AAAA,QACV,CAAC;AACD,gBAAQ,IAAI,MAAM;AAElB,mBAAW,QAAQ,OAAO,WAAW;AACnC,kBAAQ,OAAO;AAAA,YACb,GAAG,OAAO,OAAO,CAAC,IAAI,IAAI,YAAY,OAAO,KAAK;AAAA;AAAA,UACpD;AAAA,QACF;AAEA,cAAMA,eAAc,OAAO,UAAU,SAAS;AAC9C,cAAMC,eAAc,UAAU,SAAS,SAAS;AAChD,YAAI,KAAK,WAAWA,gBAAeD,eAAc;AAC/C,kBAAQ,WAAW;AAAA,QACrB;AACA;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,mBAAW,gBAAgB,EAAE,UAAU,KAAK,UAAU,OAAO,KAAK,MAAM,CAAC;AAAA,MAC3E,SAAS,OAAO;AACd,YAAI,iBAAiB,UAAU;AAC7B,kBAAQ,OAAO,MAAM,GAAG,MAAM,OAAO;AAAA,CAAI;AACzC,cAAI,MAAM,WAAY,SAAQ,OAAO,MAAM,GAAG,IAAI,MAAM,UAAU,CAAC;AAAA,CAAI;AACvE,kBAAQ,WAAW,MAAM;AACzB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAEA,cAAQ,OAAO,MAAM,GAAG,IAAI,UAAK,gBAAgB,QAAQ,CAAC,EAAE,CAAC;AAAA,CAAI;AAEjE,YAAM,aAAa,kBAAkB,WAAW;AAAA,QAC9C;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,QAAQ;AACV,cAAM,UAAU,sBAAsB,YAAY,SAAS;AAC3D,gBAAQ,IAAI,OAAO;AACnB,gBAAQ,OAAO;AAAA,UACb,GAAG,IAAI,sFAAsF,CAAC;AAAA;AAAA,QAChG;AACA;AAAA,MACF;AAEA,YAAM,aAAa,MAAM,iBAAiB,QAAQ;AAClD,UAAI;AACJ,UAAI;AACF,qBAAa,MAAM,gBAAgB,YAAY;AAAA,UAC7C;AAAA,UACA,QAAQ,KAAK;AAAA,UACb,SAAS,CAAC,EAAE,UAAU,OAAO,MAAM;AACjC,oBAAQ,OAAO;AAAA,cACb,GAAG,OAAO,OAAO,CAAC,IAAI,QAAQ,wBAAwB,MAAM;AAAA;AAAA,YAC9D;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YAAI,iBAAiB,UAAU;AAC7B,kBAAQ,OAAO,MAAM,GAAG,MAAM,OAAO;AAAA,CAAI;AACzC,cAAI,MAAM,WAAY,SAAQ,OAAO,MAAM,GAAG,IAAI,MAAM,UAAU,CAAC;AAAA,CAAI;AACvE,kBAAQ,WAAW,MAAM;AACzB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAEA,YAAM,UACJ,SAAS,SAAS,YAAY,MAAM,mBAAmB,SAAS,KAAK,IAAI;AAE3E,YAAM,UAAmC;AAAA,QACvC,MAAM,SAAS;AAAA,QACf,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,UAAU,WAAW;AAAA,QACrB,WAAW,WAAW;AAAA,MACxB;AACA,UAAI,SAAS,SAAS,WAAW;AAC/B,gBAAQ,OAAO,IAAI,SAAS;AAC5B,YAAI,OAAO,YAAY,SAAU,SAAQ,SAAS,IAAI;AAAA,MACxD;AAEA,UAAI,oBAAoB,QAAQ;AAC9B,cAAM,UAAU;AAAA,UACd,MAAM,WAAW;AAAA,UACjB,IAAI,WAAW;AAAA,UACf,OAAO,WAAW;AAAA,UAClB,gBAAgB,WAAW;AAAA,UAC3B,IAAI;AAAA,UACJ,SAAS,WAAW;AAAA,UACpB,WAAW,WAAW;AAAA,UACtB,UAAU,WAAW;AAAA,QACvB;AACA,gBAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,MAC9C,WAAW,oBAAoB,UAAU;AACvC,gBAAQ,IAAI,sBAAsB,YAAY,SAAS,CAAC;AAAA,MAC1D,OAAO;AACL,gBAAQ,IAAI,kBAAkB,UAAU,CAAC;AAAA,MAC3C;AAEA,iBAAW,QAAQ,WAAW,WAAW;AACvC,gBAAQ,OAAO;AAAA,UACb,GAAG,OAAO,OAAO,CAAC,IAAI,IAAI,YAAY,WAAW,KAAK;AAAA;AAAA,QACxD;AAAA,MACF;AAEA,UAAI,WAAW,SAAS,SAAS,GAAG;AAClC,gBAAQ,OAAO;AAAA,UACb,GAAG,IAAI,IAAI,WAAW,SAAS,MAAM,UAAU,WAAW,SAAS,WAAW,IAAI,KAAK,GAAG,4CAAuC,CAAC;AAAA;AAAA,QACpI;AAAA,MACF;AAEA,UAAI,OAAO,YAAY,UAAU;AAC/B,gBAAQ,OAAO,MAAM,GAAG,IAAI,eAAe,QAAQ,QAAQ,CAAC,CAAC,GAAG,CAAC;AAAA,CAAI;AAAA,MACvE;AAEA,YAAM,cAAc,WAAW,UAAU,SAAS;AAClD,YAAM,cAAc,UAAU,SAAS,SAAS;AAChD,YAAM,cAAc,WAAW,SAAS,SAAS;AACjD,UAAI,KAAK,WAAW,eAAe,eAAe,cAAc;AAC9D,gBAAQ,WAAW;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACJ;","names":["hasOverflow","hasWarnings"]}
|
|
@@ -67,25 +67,25 @@ function registerPluginCommands(program, manager) {
|
|
|
67
67
|
import { Command } from "commander";
|
|
68
68
|
async function createProgram(pluginManager) {
|
|
69
69
|
const program = new Command();
|
|
70
|
-
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.
|
|
70
|
+
program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.63", "-V, --version").option("-o, --output <format>", "Output format: table, json, yaml, markdown, junit").option("-v, --verbose", "Enable debug logging").option("-q, --quiet", "Suppress non-essential output").option("-a, --app <package>", "App package name").option("-p, --profile <name>", "Auth profile name").option("--no-color", "Disable colored output").option("--no-interactive", "Disable interactive prompts").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Preview changes without executing").option("--notify [target]", "Send webhook notification on completion (slack, discord, custom)").option("--ci", "Force CI mode (JSON output, no prompts, strict exit codes)").option("-j, --json", "Shorthand for --output json").option("--apps <csv>", "Comma-separated package names for multi-app operations").showSuggestionAfterError(false);
|
|
71
71
|
const commandLoaders = {
|
|
72
72
|
auth: async () => {
|
|
73
73
|
(await import("./auth-4DRT7ZH2.js")).registerAuthCommands(program);
|
|
74
74
|
},
|
|
75
75
|
config: async () => {
|
|
76
|
-
(await import("./config-
|
|
76
|
+
(await import("./config-JMLIMKYJ.js")).registerConfigCommands(program);
|
|
77
77
|
},
|
|
78
78
|
doctor: async () => {
|
|
79
|
-
(await import("./doctor-
|
|
79
|
+
(await import("./doctor-2R7WLRD4.js")).registerDoctorCommand(program);
|
|
80
80
|
},
|
|
81
81
|
update: async () => {
|
|
82
|
-
(await import("./update-
|
|
82
|
+
(await import("./update-MHWSESO4.js")).registerUpdateCommand(program);
|
|
83
83
|
},
|
|
84
84
|
docs: async () => {
|
|
85
85
|
(await import("./docs-GP6AEX4N.js")).registerDocsCommand(program);
|
|
86
86
|
},
|
|
87
87
|
changelog: async () => {
|
|
88
|
-
(await import("./changelog-
|
|
88
|
+
(await import("./changelog-MPBEELTH.js")).registerChangelogCommand(program);
|
|
89
89
|
},
|
|
90
90
|
completion: async () => {
|
|
91
91
|
(await import("./completion-4I3IJK3M.js")).registerCompletionCommand(program, async () => {
|
|
@@ -193,13 +193,13 @@ async function createProgram(pluginManager) {
|
|
|
193
193
|
(await import("./verify-H4ZUVHMZ.js")).registerVerifyCommand(program);
|
|
194
194
|
},
|
|
195
195
|
version: async () => {
|
|
196
|
-
(await import("./version-
|
|
196
|
+
(await import("./version-ZHOZKZ2I.js")).registerVersionCommand(program);
|
|
197
197
|
},
|
|
198
198
|
cache: async () => {
|
|
199
199
|
(await import("./cache-FGNP7Y37.js")).registerCacheCommand(program);
|
|
200
200
|
},
|
|
201
201
|
feedback: async () => {
|
|
202
|
-
(await import("./feedback-
|
|
202
|
+
(await import("./feedback-MLQTM5EB.js")).registerFeedbackCommand(program);
|
|
203
203
|
},
|
|
204
204
|
quickstart: async () => {
|
|
205
205
|
(await import("./quickstart-FOWM3OKT.js")).registerQuickstartCommand(program);
|
|
@@ -467,4 +467,4 @@ export {
|
|
|
467
467
|
createProgram,
|
|
468
468
|
handleCliError
|
|
469
469
|
};
|
|
470
|
-
//# sourceMappingURL=chunk-
|
|
470
|
+
//# sourceMappingURL=chunk-QXXXY5CO.js.map
|
|
@@ -78,7 +78,7 @@ Configuration file created: ${path}`);
|
|
|
78
78
|
});
|
|
79
79
|
console.log("\nVerifying setup...");
|
|
80
80
|
try {
|
|
81
|
-
const { registerDoctorCommand } = await import("./doctor-
|
|
81
|
+
const { registerDoctorCommand } = await import("./doctor-2R7WLRD4.js");
|
|
82
82
|
const { Command } = await import("commander");
|
|
83
83
|
const doctorProgram = new Command();
|
|
84
84
|
doctorProgram.option("-o, --output <format>", "Output format").option("-j, --json", "JSON mode");
|
|
@@ -107,4 +107,4 @@ Configuration file created: ${path}`);
|
|
|
107
107
|
export {
|
|
108
108
|
registerConfigCommands
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=config-
|
|
110
|
+
//# sourceMappingURL=config-JMLIMKYJ.js.map
|
|
@@ -141,7 +141,7 @@ function checkCiEnvironment() {
|
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
143
|
async function checkGpcVersion() {
|
|
144
|
-
const currentVersion = "0.9.
|
|
144
|
+
const currentVersion = "0.9.63";
|
|
145
145
|
if (currentVersion === "0.0.0") {
|
|
146
146
|
return { name: "version", status: "info", message: "GPC development build" };
|
|
147
147
|
}
|
|
@@ -800,4 +800,4 @@ export {
|
|
|
800
800
|
checkVerificationDeadline,
|
|
801
801
|
registerDoctorCommand
|
|
802
802
|
};
|
|
803
|
-
//# sourceMappingURL=doctor-
|
|
803
|
+
//# sourceMappingURL=doctor-2R7WLRD4.js.map
|
|
@@ -9,7 +9,7 @@ import { execFile } from "child_process";
|
|
|
9
9
|
import { listAuditEvents } from "@gpc-cli/core";
|
|
10
10
|
function registerFeedbackCommand(program) {
|
|
11
11
|
program.command("feedback").description("Open a pre-filled GitHub issue with system diagnostics").option("--title <title>", "Issue title").option("--print", "Print the report to stdout instead of opening a browser").action(async (opts) => {
|
|
12
|
-
const version = "0.9.
|
|
12
|
+
const version = "0.9.63";
|
|
13
13
|
let lastCommand = "";
|
|
14
14
|
try {
|
|
15
15
|
const events = await listAuditEvents({ limit: 3 });
|
|
@@ -67,4 +67,4 @@ ${url}`);
|
|
|
67
67
|
export {
|
|
68
68
|
registerFeedbackCommand
|
|
69
69
|
};
|
|
70
|
-
//# sourceMappingURL=feedback-
|
|
70
|
+
//# sourceMappingURL=feedback-MLQTM5EB.js.map
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
|
|
|
17
17
|
program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
|
|
18
18
|
const parentOpts = cmd.parent?.opts() ?? {};
|
|
19
19
|
const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
|
|
20
|
-
const currentVersion = "0.9.
|
|
20
|
+
const currentVersion = "0.9.63";
|
|
21
21
|
if (currentVersion === "0.0.0") {
|
|
22
22
|
if (jsonMode) {
|
|
23
23
|
console.log(
|
|
@@ -172,4 +172,4 @@ Run: gpc update`);
|
|
|
172
172
|
export {
|
|
173
173
|
registerUpdateCommand
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=update-
|
|
175
|
+
//# sourceMappingURL=update-MHWSESO4.js.map
|
|
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
|
|
|
7
7
|
// src/commands/version.ts
|
|
8
8
|
function registerVersionCommand(program) {
|
|
9
9
|
program.command("version").description("Show version information").action(() => {
|
|
10
|
-
const version = "0.9.
|
|
10
|
+
const version = "0.9.63";
|
|
11
11
|
if (program.opts()["output"] === "json") {
|
|
12
12
|
console.log(
|
|
13
13
|
JSON.stringify({
|
|
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
|
|
|
25
25
|
export {
|
|
26
26
|
registerVersionCommand
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=version-
|
|
28
|
+
//# sourceMappingURL=version-ZHOZKZ2I.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpc-cli/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.63",
|
|
4
4
|
"description": "GPC — Google Play Console CLI. 217 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
22
|
"@gpc-cli/api": "1.0.36",
|
|
23
|
-
"@gpc-cli/auth": "0.9.14",
|
|
24
23
|
"@gpc-cli/config": "0.9.14",
|
|
25
|
-
"@gpc-cli/
|
|
24
|
+
"@gpc-cli/auth": "0.9.14",
|
|
25
|
+
"@gpc-cli/core": "0.9.53",
|
|
26
26
|
"@gpc-cli/plugin-sdk": "0.9.10"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
dim,
|
|
4
|
-
yellow
|
|
5
|
-
} from "./chunk-FAN4ZITI.js";
|
|
6
|
-
import {
|
|
7
|
-
getOutputFormat
|
|
8
|
-
} from "./chunk-ELXAK7GI.js";
|
|
9
|
-
|
|
10
|
-
// src/commands/changelog.ts
|
|
11
|
-
import {
|
|
12
|
-
fetchChangelog,
|
|
13
|
-
formatChangelogEntry,
|
|
14
|
-
formatOutput,
|
|
15
|
-
generateChangelog,
|
|
16
|
-
RENDERERS
|
|
17
|
-
} from "@gpc-cli/core";
|
|
18
|
-
import { loadConfig } from "@gpc-cli/config";
|
|
19
|
-
var VALID_OUTPUT_MODES = ["md", "json", "prompt"];
|
|
20
|
-
var REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
21
|
-
function registerChangelogCommand(program) {
|
|
22
|
-
const changelog = program.command("changelog").description("Show release history").option("-n, --limit <count>", "Number of releases to show", parseInt, 5).option("--tag <tag>", "Show a specific release (e.g., v0.9.43)").option("--all", "Show all releases").action(async (opts) => {
|
|
23
|
-
const config = await loadConfig();
|
|
24
|
-
const format = getOutputFormat(program, config);
|
|
25
|
-
const entries = await fetchChangelog({
|
|
26
|
-
limit: opts.all ? 100 : opts.limit,
|
|
27
|
-
version: opts.tag
|
|
28
|
-
});
|
|
29
|
-
if (entries.length === 0) {
|
|
30
|
-
console.log("No releases found.");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (format === "json") {
|
|
34
|
-
console.log(formatOutput(entries, "json"));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
if (opts.tag || entries.length === 1) {
|
|
38
|
-
console.log(formatChangelogEntry(entries[0]));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const header = "VERSION DATE TITLE";
|
|
42
|
-
const separator = "\u2500".repeat(header.length);
|
|
43
|
-
console.log(header);
|
|
44
|
-
console.log(separator);
|
|
45
|
-
for (const entry of entries) {
|
|
46
|
-
const version = entry.version.padEnd(12);
|
|
47
|
-
const date = entry.date.padEnd(12);
|
|
48
|
-
console.log(`${version} ${date} ${entry.title}`);
|
|
49
|
-
}
|
|
50
|
-
console.log("");
|
|
51
|
-
console.log(
|
|
52
|
-
`Showing ${entries.length} releases. Use --tag <tag> for details, or --all for full history.`
|
|
53
|
-
);
|
|
54
|
-
});
|
|
55
|
-
changelog.command("generate").description("Generate release notes from local git commits").option("--from <ref>", "Starting ref (default: latest v* tag)").option("--to <ref>", "Ending ref (default: HEAD)").option("--format <mode>", "Renderer: md, json, or prompt", "md").option("--repo <owner/name>", "Override auto-detected repo (e.g., yasserstudio/gpc)").option("--strict", "Exit non-zero if linter warnings are emitted").action(
|
|
56
|
-
async (opts) => {
|
|
57
|
-
const mode = opts.format;
|
|
58
|
-
if (!VALID_OUTPUT_MODES.includes(mode)) {
|
|
59
|
-
process.stderr.write(
|
|
60
|
-
`Invalid --format "${opts.format}". Valid: ${VALID_OUTPUT_MODES.join(", ")}
|
|
61
|
-
`
|
|
62
|
-
);
|
|
63
|
-
process.exitCode = 2;
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (opts.repo && !REPO_RE.test(opts.repo)) {
|
|
67
|
-
process.stderr.write(
|
|
68
|
-
`Invalid --repo "${opts.repo}". Expected "owner/name" (e.g., yasserstudio/gpc).
|
|
69
|
-
`
|
|
70
|
-
);
|
|
71
|
-
process.exitCode = 2;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const generated = await generateChangelog({
|
|
75
|
-
from: opts.from,
|
|
76
|
-
to: opts.to,
|
|
77
|
-
repo: opts.repo
|
|
78
|
-
});
|
|
79
|
-
for (const w of generated.warnings) {
|
|
80
|
-
process.stderr.write(`${yellow("warn:")} ${w}
|
|
81
|
-
`);
|
|
82
|
-
}
|
|
83
|
-
if (generated.warnings.length > 0) {
|
|
84
|
-
process.stderr.write(
|
|
85
|
-
`${dim(`(${generated.warnings.length} warning${generated.warnings.length === 1 ? "" : "s"} \u2014 review before publishing)`)}
|
|
86
|
-
`
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
const output = RENDERERS[mode](generated);
|
|
90
|
-
console.log(output);
|
|
91
|
-
if (opts.strict && generated.warnings.length > 0) {
|
|
92
|
-
process.exitCode = 1;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
export {
|
|
98
|
-
registerChangelogCommand
|
|
99
|
-
};
|
|
100
|
-
//# sourceMappingURL=changelog-PPTJ7BHJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/changelog.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n fetchChangelog,\n formatChangelogEntry,\n formatOutput,\n generateChangelog,\n RENDERERS,\n type OutputMode,\n} from \"@gpc-cli/core\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { getOutputFormat } from \"../format.js\";\nimport { yellow, dim } from \"../colors.js\";\n\nconst VALID_OUTPUT_MODES: OutputMode[] = [\"md\", \"json\", \"prompt\"];\nconst REPO_RE = /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/;\n\nexport function registerChangelogCommand(program: Command): void {\n const changelog = program\n .command(\"changelog\")\n .description(\"Show release history\")\n .option(\"-n, --limit <count>\", \"Number of releases to show\", parseInt, 5)\n .option(\"--tag <tag>\", \"Show a specific release (e.g., v0.9.43)\")\n .option(\"--all\", \"Show all releases\")\n .action(async (opts: { limit: number; tag?: string; all?: boolean }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n const entries = await fetchChangelog({\n limit: opts.all ? 100 : opts.limit,\n version: opts.tag,\n });\n\n if (entries.length === 0) {\n console.log(\"No releases found.\");\n return;\n }\n\n if (format === \"json\") {\n console.log(formatOutput(entries, \"json\"));\n return;\n }\n\n if (opts.tag || entries.length === 1) {\n console.log(formatChangelogEntry(entries[0]!));\n return;\n }\n\n const header = \"VERSION DATE TITLE\";\n const separator = \"─\".repeat(header.length);\n console.log(header);\n console.log(separator);\n for (const entry of entries) {\n const version = entry.version.padEnd(12);\n const date = entry.date.padEnd(12);\n console.log(`${version} ${date} ${entry.title}`);\n }\n console.log(\"\");\n console.log(\n `Showing ${entries.length} releases. Use --tag <tag> for details, or --all for full history.`,\n );\n });\n\n changelog\n .command(\"generate\")\n .description(\"Generate release notes from local git commits\")\n .option(\"--from <ref>\", \"Starting ref (default: latest v* tag)\")\n .option(\"--to <ref>\", \"Ending ref (default: HEAD)\")\n .option(\"--format <mode>\", \"Renderer: md, json, or prompt\", \"md\")\n .option(\"--repo <owner/name>\", \"Override auto-detected repo (e.g., yasserstudio/gpc)\")\n .option(\"--strict\", \"Exit non-zero if linter warnings are emitted\")\n .action(\n async (opts: {\n from?: string;\n to?: string;\n format: string;\n repo?: string;\n strict?: boolean;\n }) => {\n const mode = opts.format as OutputMode;\n if (!VALID_OUTPUT_MODES.includes(mode)) {\n process.stderr.write(\n `Invalid --format \"${opts.format}\". Valid: ${VALID_OUTPUT_MODES.join(\", \")}\\n`,\n );\n process.exitCode = 2;\n return;\n }\n if (opts.repo && !REPO_RE.test(opts.repo)) {\n process.stderr.write(\n `Invalid --repo \"${opts.repo}\". Expected \"owner/name\" (e.g., yasserstudio/gpc).\\n`,\n );\n process.exitCode = 2;\n return;\n }\n\n const generated = await generateChangelog({\n from: opts.from,\n to: opts.to,\n repo: opts.repo,\n });\n\n for (const w of generated.warnings) {\n process.stderr.write(`${yellow(\"warn:\")} ${w}\\n`);\n }\n if (generated.warnings.length > 0) {\n process.stderr.write(\n `${dim(`(${generated.warnings.length} warning${generated.warnings.length === 1 ? \"\" : \"s\"} — review before publishing)`)}\\n`,\n );\n }\n\n const output = RENDERERS[mode](generated);\n console.log(output);\n\n if (opts.strict && generated.warnings.length > 0) {\n process.exitCode = 1;\n }\n },\n );\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|