@gpc-cli/cli 0.9.22 → 0.9.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +32 -27
  2. package/dist/bin.js +1 -1
  3. package/dist/bundle-7IF5FIB4.js +184 -0
  4. package/dist/bundle-7IF5FIB4.js.map +1 -0
  5. package/dist/{chunk-RPOQGWF6.js → chunk-SZLO6HOO.js} +14 -11
  6. package/dist/{chunk-RPOQGWF6.js.map → chunk-SZLO6HOO.js.map} +1 -1
  7. package/dist/config-2L7QUYWP.js +97 -0
  8. package/dist/config-2L7QUYWP.js.map +1 -0
  9. package/dist/{data-safety-DBA26FHB.js → data-safety-GDPKV5PN.js} +3 -3
  10. package/dist/{data-safety-DBA26FHB.js.map → data-safety-GDPKV5PN.js.map} +1 -1
  11. package/dist/{device-tiers-2TFSUHXY.js → device-tiers-GHIYJPMB.js} +14 -2
  12. package/dist/device-tiers-GHIYJPMB.js.map +1 -0
  13. package/dist/{doctor-TEIKODLP.js → doctor-JMEHYOGJ.js} +76 -63
  14. package/dist/doctor-JMEHYOGJ.js.map +1 -0
  15. package/dist/index.js +1 -1
  16. package/dist/{internal-sharing-OS3HVIY5.js → internal-sharing-E7SJYDW3.js} +14 -2
  17. package/dist/internal-sharing-E7SJYDW3.js.map +1 -0
  18. package/dist/migrate-XQV7P4R7.js +135 -0
  19. package/dist/migrate-XQV7P4R7.js.map +1 -0
  20. package/dist/{publish-PZRWX3TH.js → publish-26ZPS7XX.js} +86 -16
  21. package/dist/publish-26ZPS7XX.js.map +1 -0
  22. package/dist/{reports-Q7GFQ5GG.js → reports-N5X66IUN.js} +4 -4
  23. package/dist/{reports-Q7GFQ5GG.js.map → reports-N5X66IUN.js.map} +1 -1
  24. package/dist/status-C222ZKHH.js +96 -0
  25. package/dist/status-C222ZKHH.js.map +1 -0
  26. package/dist/{tracks-TP6TDO56.js → tracks-XFUN7JJX.js} +23 -3
  27. package/dist/tracks-XFUN7JJX.js.map +1 -0
  28. package/package.json +5 -5
  29. package/dist/config-R5U7GV56.js +0 -51
  30. package/dist/config-R5U7GV56.js.map +0 -1
  31. package/dist/device-tiers-2TFSUHXY.js.map +0 -1
  32. package/dist/doctor-TEIKODLP.js.map +0 -1
  33. package/dist/internal-sharing-OS3HVIY5.js.map +0 -1
  34. package/dist/migrate-V6G5YUVH.js +0 -80
  35. package/dist/migrate-V6G5YUVH.js.map +0 -1
  36. package/dist/publish-PZRWX3TH.js.map +0 -1
  37. package/dist/status-S3FAEXNH.js +0 -37
  38. package/dist/status-S3FAEXNH.js.map +0 -1
  39. package/dist/tracks-TP6TDO56.js.map +0 -1
package/README.md CHANGED
@@ -1,17 +1,29 @@
1
1
  # @gpc-cli/cli
2
2
 
3
- Ship Android apps from your terminal. The complete CLI for Google Play Developer API v3.
3
+ <p align="center"><strong>Ship Android apps from your terminal.</strong></p>
4
+
5
+ <p align="center">
6
+ The complete CLI for Google Play — 187 API endpoints, one tool.<br>
7
+ Releases, rollouts, metadata, vitals, reviews, subscriptions, reports, and more.
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://www.npmjs.com/package/@gpc-cli/cli"><img src="https://img.shields.io/npm/v/@gpc-cli/cli?color=00D26A" alt="npm version"></a>
12
+ <a href="https://github.com/yasserstudio/gpc"><img src="https://img.shields.io/github/stars/yasserstudio/gpc" alt="GitHub Stars"></a>
13
+ <img src="https://img.shields.io/badge/Tests-1299_passing-00D26A" alt="Tests">
14
+ <img src="https://img.shields.io/badge/License-MIT-yellow" alt="License">
15
+ </p>
4
16
 
5
17
  ## Install
6
18
 
7
19
  ```bash
8
- # npm
20
+ # npm (includes plugin support)
9
21
  npm install -g @gpc-cli/cli
10
22
 
11
- # Homebrew
23
+ # Homebrew (macOS/Linux)
12
24
  brew install yasserstudio/tap/gpc
13
25
 
14
- # Standalone binary
26
+ # Standalone binary (no Node.js required)
15
27
  curl -fsSL https://raw.githubusercontent.com/yasserstudio/gpc/main/scripts/install.sh | sh
16
28
  ```
17
29
 
@@ -36,48 +48,37 @@ gpc reviews list --stars 1-3 --since 7d
36
48
 
37
49
  ## What You Get
38
50
 
39
- 187 API endpoints across 10 command groups:
51
+ 187 API endpoints across these command groups:
40
52
 
41
- | Command Group | Examples |
53
+ | Group | Examples |
42
54
  | ----------------- | -------------------------------------------------------------- |
43
55
  | **Releases** | `upload`, `promote`, `rollout increase/halt/resume`, `publish` |
44
56
  | **Listings** | `pull`, `push`, `images upload/delete`, Fastlane format |
45
57
  | **Reviews** | `list`, `reply`, `export --format csv` |
46
58
  | **Vitals** | `crashes`, `anr`, `startup`, `rendering`, `battery`, `memory` |
47
- | **Subscriptions** | `list`, `create`, `base-plans`, `offers` |
48
- | **IAP** | `list`, `create`, `sync --dir products/` |
49
- | **Purchases** | `get`, `acknowledge`, `cancel`, `refund` |
59
+ | **Bundle** | `analyze` (size breakdown), `compare` (size diff) |
60
+ | **Subscriptions** | `list`, `create`, `update`, `base-plans`, `offers` |
61
+ | **IAP** | `list`, `create`, `sync --dir products/`, `batch-get/update` |
62
+ | **Purchases** | `get`, `acknowledge`, `cancel`, `refund`, `voided list` |
50
63
  | **Reports** | `download financial`, `download stats` |
51
64
  | **Testers** | `add`, `remove`, `import --file testers.csv` |
52
65
  | **Users** | `invite`, `update`, `remove`, per-app grants |
53
66
 
54
- ## CI/CD
67
+ ## CI/CD Ready
55
68
 
56
- JSON output, semantic exit codes (0-6), env var config no wrapper scripts needed.
69
+ JSON output when piped. Formatted tables in your terminal. Semantic exit codes (0-6) your CI can react to.
57
70
 
58
71
  ```yaml
59
- - name: Install GPC
60
- run: npm install -g @gpc-cli/cli
61
-
62
72
  - name: Upload
63
73
  env:
64
74
  GPC_SERVICE_ACCOUNT: ${{ secrets.GPC_SERVICE_ACCOUNT }}
65
75
  GPC_APP: com.example.myapp
66
- run: gpc releases upload app.aab --track internal
76
+ run: |
77
+ npm install -g @gpc-cli/cli
78
+ gpc releases upload app.aab --track internal
67
79
  ```
68
80
 
69
- ## Output Formats
70
-
71
- GPC auto-detects your environment:
72
-
73
- - **Terminal:** formatted tables
74
- - **Piped/CI:** structured JSON
75
-
76
- Override with `--output json|yaml|markdown|table`.
77
-
78
- ## Documentation
79
-
80
- Full docs at **[yasserstudio.github.io/gpc](https://yasserstudio.github.io/gpc/)**
81
+ Every write operation supports `--dry-run`.
81
82
 
82
83
  ## Part of the GPC Monorepo
83
84
 
@@ -91,6 +92,10 @@ Full docs at **[yasserstudio.github.io/gpc](https://yasserstudio.github.io/gpc/)
91
92
  | [@gpc-cli/plugin-sdk](https://www.npmjs.com/package/@gpc-cli/plugin-sdk) | Plugin interface and lifecycle hooks |
92
93
  | [@gpc-cli/plugin-ci](https://www.npmjs.com/package/@gpc-cli/plugin-ci) | CI/CD helpers |
93
94
 
95
+ ## Documentation
96
+
97
+ Full docs at **[yasserstudio.github.io/gpc](https://yasserstudio.github.io/gpc/)**
98
+
94
99
  ## License
95
100
 
96
101
  MIT
package/dist/bin.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-RPOQGWF6.js";
6
+ } from "./chunk-SZLO6HOO.js";
7
7
 
8
8
  // src/networking.ts
9
9
  async function setupNetworking() {
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getOutputFormat
4
+ } from "./chunk-ELXAK7GI.js";
5
+
6
+ // src/commands/bundle.ts
7
+ import {
8
+ analyzeBundle,
9
+ compareBundles,
10
+ formatOutput
11
+ } from "@gpc-cli/core";
12
+ function formatSize(bytes) {
13
+ const abs = Math.abs(bytes);
14
+ const sign = bytes < 0 ? "-" : "";
15
+ if (abs < 1024) return `${sign}${abs} B`;
16
+ if (abs < 1024 * 1024) return `${sign}${(abs / 1024).toFixed(1)} KB`;
17
+ return `${sign}${(abs / (1024 * 1024)).toFixed(2)} MB`;
18
+ }
19
+ function formatDelta(delta) {
20
+ const prefix = delta > 0 ? "+" : "";
21
+ return `${prefix}${formatSize(delta)}`;
22
+ }
23
+ function registerBundleCommands(program) {
24
+ const bundle = program.command("bundle").description("Analyze app bundles and APKs");
25
+ bundle.command("analyze <file>").description("Analyze size breakdown of an AAB or APK").option("--threshold <mb>", "Fail if compressed size exceeds threshold (MB)", parseFloat).action(async (file, opts) => {
26
+ const format = getOutputFormat(program, await getConfig());
27
+ try {
28
+ const analysis = await analyzeBundle(file);
29
+ if (format === "json") {
30
+ console.log(formatOutput(analysis, format));
31
+ } else if (format === "markdown") {
32
+ const moduleRows = analysis.modules.map((m) => ({
33
+ module: m.name,
34
+ compressed: formatSize(m.compressedSize),
35
+ uncompressed: formatSize(m.uncompressedSize),
36
+ entries: m.entries
37
+ }));
38
+ const categoryRows = analysis.categories.map((c) => ({
39
+ category: c.name,
40
+ compressed: formatSize(c.compressedSize),
41
+ uncompressed: formatSize(c.uncompressedSize),
42
+ entries: c.entries
43
+ }));
44
+ console.log(`## Bundle Analysis: \`${analysis.filePath}\``);
45
+ console.log();
46
+ console.log(`| Property | Value |`);
47
+ console.log(`| --- | --- |`);
48
+ console.log(`| Type | ${analysis.fileType.toUpperCase()} |`);
49
+ console.log(`| Total compressed | ${formatSize(analysis.totalCompressed)} |`);
50
+ console.log(`| Total uncompressed | ${formatSize(analysis.totalUncompressed)} |`);
51
+ console.log(`| Entries | ${analysis.entryCount} |`);
52
+ console.log();
53
+ console.log(`### Modules`);
54
+ console.log();
55
+ console.log(formatOutput(moduleRows, "markdown"));
56
+ console.log();
57
+ console.log(`### Categories`);
58
+ console.log();
59
+ console.log(formatOutput(categoryRows, "markdown"));
60
+ } else {
61
+ console.log(`
62
+ File: ${analysis.filePath}`);
63
+ console.log(`Type: ${analysis.fileType.toUpperCase()}`);
64
+ console.log(`Total compressed: ${formatSize(analysis.totalCompressed)}`);
65
+ console.log(`Total uncompressed: ${formatSize(analysis.totalUncompressed)}`);
66
+ console.log(`Entries: ${analysis.entryCount}
67
+ `);
68
+ const moduleRows = analysis.modules.map((m) => ({
69
+ module: m.name,
70
+ compressed: formatSize(m.compressedSize),
71
+ uncompressed: formatSize(m.uncompressedSize),
72
+ entries: m.entries
73
+ }));
74
+ console.log("Modules:");
75
+ console.log(formatOutput(moduleRows, "table"));
76
+ const categoryRows = analysis.categories.map((c) => ({
77
+ category: c.name,
78
+ compressed: formatSize(c.compressedSize),
79
+ uncompressed: formatSize(c.uncompressedSize),
80
+ entries: c.entries
81
+ }));
82
+ console.log("\nCategories:");
83
+ console.log(formatOutput(categoryRows, "table"));
84
+ }
85
+ if (opts.threshold !== void 0) {
86
+ const thresholdBytes = opts.threshold * 1024 * 1024;
87
+ if (analysis.totalCompressed > thresholdBytes) {
88
+ console.error(
89
+ `
90
+ Threshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold} MB`
91
+ );
92
+ process.exit(6);
93
+ }
94
+ }
95
+ } catch (error) {
96
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ bundle.command("compare <file1> <file2>").description("Compare size differences between two bundles or APKs").action(async (file1, file2) => {
101
+ const format = getOutputFormat(program, await getConfig());
102
+ try {
103
+ const [before, after] = await Promise.all([
104
+ analyzeBundle(file1),
105
+ analyzeBundle(file2)
106
+ ]);
107
+ const comparison = compareBundles(before, after);
108
+ if (format === "json") {
109
+ console.log(formatOutput(comparison, format));
110
+ } else if (format === "markdown") {
111
+ const sign = comparison.sizeDelta >= 0 ? "+" : "";
112
+ const moduleRows = comparison.moduleDeltas.filter((m) => m.delta !== 0).map((m) => ({
113
+ module: m.module,
114
+ before: formatSize(m.before),
115
+ after: formatSize(m.after),
116
+ delta: formatDelta(m.delta)
117
+ }));
118
+ const categoryRows = comparison.categoryDeltas.filter((c) => c.delta !== 0).map((c) => ({
119
+ category: c.category,
120
+ before: formatSize(c.before),
121
+ after: formatSize(c.after),
122
+ delta: formatDelta(c.delta)
123
+ }));
124
+ console.log(`## Bundle Comparison`);
125
+ console.log();
126
+ console.log(`| | Path | Size |`);
127
+ console.log(`| --- | --- | --- |`);
128
+ console.log(`| Before | \`${comparison.before.path}\` | ${formatSize(comparison.before.totalCompressed)} |`);
129
+ console.log(`| After | \`${comparison.after.path}\` | ${formatSize(comparison.after.totalCompressed)} |`);
130
+ console.log(`| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`);
131
+ if (moduleRows.length > 0) {
132
+ console.log();
133
+ console.log(`### Module Changes`);
134
+ console.log();
135
+ console.log(formatOutput(moduleRows, "markdown"));
136
+ }
137
+ if (categoryRows.length > 0) {
138
+ console.log();
139
+ console.log(`### Category Changes`);
140
+ console.log();
141
+ console.log(formatOutput(categoryRows, "markdown"));
142
+ }
143
+ } else {
144
+ const sign = comparison.sizeDelta >= 0 ? "+" : "";
145
+ console.log(`
146
+ Before: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`);
147
+ console.log(`After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`);
148
+ console.log(`Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)
149
+ `);
150
+ const moduleRows = comparison.moduleDeltas.filter((m) => m.delta !== 0).map((m) => ({
151
+ module: m.module,
152
+ before: formatSize(m.before),
153
+ after: formatSize(m.after),
154
+ delta: formatDelta(m.delta)
155
+ }));
156
+ if (moduleRows.length > 0) {
157
+ console.log("Module changes:");
158
+ console.log(formatOutput(moduleRows, "table"));
159
+ }
160
+ const categoryRows = comparison.categoryDeltas.filter((c) => c.delta !== 0).map((c) => ({
161
+ category: c.category,
162
+ before: formatSize(c.before),
163
+ after: formatSize(c.after),
164
+ delta: formatDelta(c.delta)
165
+ }));
166
+ if (categoryRows.length > 0) {
167
+ console.log("\nCategory changes:");
168
+ console.log(formatOutput(categoryRows, "table"));
169
+ }
170
+ }
171
+ } catch (error) {
172
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
173
+ process.exit(1);
174
+ }
175
+ });
176
+ }
177
+ async function getConfig() {
178
+ const { loadConfig } = await import("@gpc-cli/config");
179
+ return loadConfig();
180
+ }
181
+ export {
182
+ registerBundleCommands
183
+ };
184
+ //# sourceMappingURL=bundle-7IF5FIB4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/bundle.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n analyzeBundle,\n compareBundles,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction formatSize(bytes: number): string {\n const abs = Math.abs(bytes);\n const sign = bytes < 0 ? \"-\" : \"\";\n if (abs < 1024) return `${sign}${abs} B`;\n if (abs < 1024 * 1024) return `${sign}${(abs / 1024).toFixed(1)} KB`;\n return `${sign}${(abs / (1024 * 1024)).toFixed(2)} MB`;\n}\n\nfunction formatDelta(delta: number): string {\n const prefix = delta > 0 ? \"+\" : \"\";\n return `${prefix}${formatSize(delta)}`;\n}\n\nexport function registerBundleCommands(program: Command): void {\n const bundle = program.command(\"bundle\").description(\"Analyze app bundles and APKs\");\n\n bundle\n .command(\"analyze <file>\")\n .description(\"Analyze size breakdown of an AAB or APK\")\n .option(\"--threshold <mb>\", \"Fail if compressed size exceeds threshold (MB)\", parseFloat)\n .action(async (file: string, opts: { threshold?: number }) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const analysis = await analyzeBundle(file);\n\n if (format === \"json\") {\n console.log(formatOutput(analysis, format));\n } else if (format === \"markdown\") {\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(`## Bundle Analysis: \\`${analysis.filePath}\\``);\n console.log();\n console.log(`| Property | Value |`);\n console.log(`| --- | --- |`);\n console.log(`| Type | ${analysis.fileType.toUpperCase()} |`);\n console.log(`| Total compressed | ${formatSize(analysis.totalCompressed)} |`);\n console.log(`| Total uncompressed | ${formatSize(analysis.totalUncompressed)} |`);\n console.log(`| Entries | ${analysis.entryCount} |`);\n console.log();\n console.log(`### Modules`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n console.log();\n console.log(`### Categories`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n } else {\n console.log(`\\nFile: ${analysis.filePath}`);\n console.log(`Type: ${analysis.fileType.toUpperCase()}`);\n console.log(`Total compressed: ${formatSize(analysis.totalCompressed)}`);\n console.log(`Total uncompressed: ${formatSize(analysis.totalUncompressed)}`);\n console.log(`Entries: ${analysis.entryCount}\\n`);\n\n // Modules table\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n console.log(\"Modules:\");\n console.log(formatOutput(moduleRows, \"table\"));\n\n // Categories table\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(\"\\nCategories:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n\n // Threshold check\n if (opts.threshold !== undefined) {\n const thresholdBytes = opts.threshold * 1024 * 1024;\n if (analysis.totalCompressed > thresholdBytes) {\n console.error(\n `\\nThreshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold} MB`,\n );\n process.exit(6);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n bundle\n .command(\"compare <file1> <file2>\")\n .description(\"Compare size differences between two bundles or APKs\")\n .action(async (file1: string, file2: string) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const [before, after] = await Promise.all([\n analyzeBundle(file1),\n analyzeBundle(file2),\n ]);\n const comparison = compareBundles(before, after);\n\n if (format === \"json\") {\n console.log(formatOutput(comparison, format));\n } else if (format === \"markdown\") {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n console.log(`## Bundle Comparison`);\n console.log();\n console.log(`| | Path | Size |`);\n console.log(`| --- | --- | --- |`);\n console.log(`| Before | \\`${comparison.before.path}\\` | ${formatSize(comparison.before.totalCompressed)} |`);\n console.log(`| After | \\`${comparison.after.path}\\` | ${formatSize(comparison.after.totalCompressed)} |`);\n console.log(`| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`);\n if (moduleRows.length > 0) {\n console.log();\n console.log(`### Module Changes`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n }\n if (categoryRows.length > 0) {\n console.log();\n console.log(`### Category Changes`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n }\n } else {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n console.log(`\\nBefore: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`);\n console.log(`After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`);\n console.log(`Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)\\n`);\n\n // Module deltas\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n if (moduleRows.length > 0) {\n console.log(\"Module changes:\");\n console.log(formatOutput(moduleRows, \"table\"));\n }\n\n // Category deltas\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n if (categoryRows.length > 0) {\n console.log(\"\\nCategory changes:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n\nasync function getConfig() {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n return loadConfig();\n}\n"],"mappings":"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","names":[]}
@@ -73,10 +73,10 @@ async function createProgram(pluginManager) {
73
73
  (await import("./auth-5XAQMZRV.js")).registerAuthCommands(program);
74
74
  },
75
75
  config: async () => {
76
- (await import("./config-R5U7GV56.js")).registerConfigCommands(program);
76
+ (await import("./config-2L7QUYWP.js")).registerConfigCommands(program);
77
77
  },
78
78
  doctor: async () => {
79
- (await import("./doctor-TEIKODLP.js")).registerDoctorCommand(program);
79
+ (await import("./doctor-JMEHYOGJ.js")).registerDoctorCommand(program);
80
80
  },
81
81
  docs: async () => {
82
82
  (await import("./docs-CVTWIVMS.js")).registerDocsCommand(program);
@@ -91,10 +91,10 @@ async function createProgram(pluginManager) {
91
91
  (await import("./releases-ZKPSAPB2.js")).registerReleasesCommands(program);
92
92
  },
93
93
  tracks: async () => {
94
- (await import("./tracks-TP6TDO56.js")).registerTracksCommands(program);
94
+ (await import("./tracks-XFUN7JJX.js")).registerTracksCommands(program);
95
95
  },
96
96
  status: async () => {
97
- (await import("./status-S3FAEXNH.js")).registerStatusCommand(program);
97
+ (await import("./status-C222ZKHH.js")).registerStatusCommand(program);
98
98
  },
99
99
  listings: async () => {
100
100
  (await import("./listings-VSBHQY5H.js")).registerListingsCommands(program);
@@ -118,7 +118,7 @@ async function createProgram(pluginManager) {
118
118
  (await import("./pricing-BYZSLN74.js")).registerPricingCommands(program);
119
119
  },
120
120
  reports: async () => {
121
- (await import("./reports-Q7GFQ5GG.js")).registerReportsCommands(program);
121
+ (await import("./reports-N5X66IUN.js")).registerReportsCommands(program);
122
122
  },
123
123
  users: async () => {
124
124
  (await import("./users-JASXONRY.js")).registerUsersCommands(program);
@@ -130,13 +130,13 @@ async function createProgram(pluginManager) {
130
130
  (await import("./validate-UYXICKBO.js")).registerValidateCommand(program);
131
131
  },
132
132
  publish: async () => {
133
- (await import("./publish-PZRWX3TH.js")).registerPublishCommand(program);
133
+ (await import("./publish-26ZPS7XX.js")).registerPublishCommand(program);
134
134
  },
135
135
  recovery: async () => {
136
136
  (await import("./recovery-S5UNJDBO.js")).registerRecoveryCommands(program);
137
137
  },
138
138
  "data-safety": async () => {
139
- (await import("./data-safety-DBA26FHB.js")).registerDataSafetyCommands(program);
139
+ (await import("./data-safety-GDPKV5PN.js")).registerDataSafetyCommands(program);
140
140
  },
141
141
  "external-transactions": async () => {
142
142
  (await import("./external-transactions-HCL7ROMN.js")).registerExternalTransactionsCommands(
@@ -144,13 +144,13 @@ async function createProgram(pluginManager) {
144
144
  );
145
145
  },
146
146
  "device-tiers": async () => {
147
- (await import("./device-tiers-2TFSUHXY.js")).registerDeviceTiersCommands(program);
147
+ (await import("./device-tiers-GHIYJPMB.js")).registerDeviceTiersCommands(program);
148
148
  },
149
149
  "one-time-products": async () => {
150
150
  (await import("./one-time-products-2PK4QKWE.js")).registerOneTimeProductsCommands(program);
151
151
  },
152
152
  "internal-sharing": async () => {
153
- (await import("./internal-sharing-OS3HVIY5.js")).registerInternalSharingCommands(program);
153
+ (await import("./internal-sharing-E7SJYDW3.js")).registerInternalSharingCommands(program);
154
154
  },
155
155
  "generated-apks": async () => {
156
156
  (await import("./generated-apks-VX7HYZDU.js")).registerGeneratedApksCommands(program);
@@ -158,11 +158,14 @@ async function createProgram(pluginManager) {
158
158
  "purchase-options": async () => {
159
159
  (await import("./purchase-options-CKRN4VIW.js")).registerPurchaseOptionsCommands(program);
160
160
  },
161
+ bundle: async () => {
162
+ (await import("./bundle-7IF5FIB4.js")).registerBundleCommands(program);
163
+ },
161
164
  audit: async () => {
162
165
  (await import("./audit-DSTCSU4V.js")).registerAuditCommands(program);
163
166
  },
164
167
  migrate: async () => {
165
- (await import("./migrate-V6G5YUVH.js")).registerMigrateCommands(program);
168
+ (await import("./migrate-XQV7P4R7.js")).registerMigrateCommands(program);
166
169
  },
167
170
  "install-skills": async () => {
168
171
  (await import("./install-skills-OV4HVANW.js")).registerInstallSkillsCommand(program);
@@ -305,4 +308,4 @@ export {
305
308
  createProgram,
306
309
  handleCliError
307
310
  };
308
- //# sourceMappingURL=chunk-RPOQGWF6.js.map
311
+ //# sourceMappingURL=chunk-SZLO6HOO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugins.ts","../src/program.ts","../src/error-handler.ts"],"sourcesContent":["import { PluginManager, discoverPlugins } from \"@gpc-cli/core\";\nimport type { Command } from \"commander\";\n\n/**\n * Load and initialize all plugins.\n * First-party plugins (@gpc-cli/*) are auto-trusted.\n * Third-party plugins require prior approval stored in config.\n * Plugin loading is disabled in standalone binary mode.\n */\nexport async function loadPlugins(): Promise<PluginManager> {\n const manager = new PluginManager();\n\n // Standalone binary cannot resolve external npm packages at runtime\n if (process.env[\"__GPC_BINARY\"] === \"1\") {\n return manager;\n }\n\n try {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const plugins = await discoverPlugins({ configPlugins: config.plugins });\n const approved = new Set(config.approvedPlugins ?? []);\n\n for (const plugin of plugins) {\n const isTrusted = plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && !approved.has(plugin.name)) {\n // Skip unapproved third-party plugins silently in non-interactive mode\n // In interactive mode, the user would run `gpc plugins approve <name>` first\n const isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n if (!isQuiet) {\n console.error(\n `Plugin \"${plugin.name}\" is not approved. Run: gpc plugins approve ${plugin.name}`,\n );\n }\n continue;\n }\n\n try {\n await manager.load(plugin);\n } catch {\n // Skip plugins that fail to load — don't block the CLI\n }\n }\n } catch {\n // Config loading failure shouldn't block plugin-free commands\n }\n\n return manager;\n}\n\n/**\n * Register plugin-defined commands with the Commander program.\n */\nexport function registerPluginCommands(program: Command, manager: PluginManager): void {\n for (const def of manager.getRegisteredCommands()) {\n const cmd = program.command(def.name).description(def.description);\n\n if (def.arguments) {\n for (const arg of def.arguments) {\n const syntax = arg.required ? `<${arg.name}>` : `[${arg.name}]`;\n cmd.argument(syntax, arg.description);\n }\n }\n\n if (def.options) {\n for (const opt of def.options) {\n cmd.option(\n opt.flags,\n opt.description,\n opt.defaultValue as string | boolean | string[] | undefined,\n );\n }\n }\n\n cmd.action(async (...rawArgs: unknown[]) => {\n const opts = rawArgs[rawArgs.length - 2] as Record<string, unknown>;\n const args: Record<string, unknown> = {};\n\n if (def.arguments) {\n def.arguments.forEach((argDef, i) => {\n args[argDef.name] = rawArgs[i];\n });\n }\n\n await def.action(args, opts);\n });\n }\n}\n","import { Command } from \"commander\";\nimport type { PluginManager } from \"@gpc-cli/core\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\nimport { registerPluginCommands } from \"./plugins.js\";\n\nexport async function createProgram(pluginManager?: PluginManager): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"gpc\")\n .description(\"The complete Google Play CLI\")\n .version(process.env[\"__GPC_VERSION\"] || \"0.0.0\", \"-V, --version\")\n .option(\"-o, --output <format>\", \"Output format: table, json, yaml, markdown, junit\")\n .option(\"-v, --verbose\", \"Enable debug logging\")\n .option(\"-q, --quiet\", \"Suppress non-essential output\")\n .option(\"-a, --app <package>\", \"App package name\")\n .option(\"-p, --profile <name>\", \"Auth profile name\")\n .option(\"--no-color\", \"Disable colored output\")\n .option(\"--no-interactive\", \"Disable interactive prompts\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without executing\")\n .option(\"--notify [target]\", \"Send webhook notification on completion (slack, discord, custom)\")\n .option(\"--ci\", \"Force CI mode (JSON output, no prompts, strict exit codes)\")\n .option(\"-j, --json\", \"Shorthand for --output json\")\n .showSuggestionAfterError(true);\n\n const commandLoaders: Record<string, () => Promise<void>> = {\n auth: async () => {\n (await import(\"./commands/auth.js\")).registerAuthCommands(program);\n },\n config: async () => {\n (await import(\"./commands/config.js\")).registerConfigCommands(program);\n },\n doctor: async () => {\n (await import(\"./commands/doctor.js\")).registerDoctorCommand(program);\n },\n docs: async () => {\n (await import(\"./commands/docs.js\")).registerDocsCommand(program);\n },\n completion: async () => {\n (await import(\"./commands/completion.js\")).registerCompletionCommand(program);\n },\n apps: async () => {\n (await import(\"./commands/apps.js\")).registerAppsCommands(program);\n },\n releases: async () => {\n (await import(\"./commands/releases.js\")).registerReleasesCommands(program);\n },\n tracks: async () => {\n (await import(\"./commands/tracks.js\")).registerTracksCommands(program);\n },\n status: async () => {\n (await import(\"./commands/status.js\")).registerStatusCommand(program);\n },\n listings: async () => {\n (await import(\"./commands/listings.js\")).registerListingsCommands(program);\n },\n reviews: async () => {\n (await import(\"./commands/reviews.js\")).registerReviewsCommands(program);\n },\n vitals: async () => {\n (await import(\"./commands/vitals.js\")).registerVitalsCommands(program);\n },\n subscriptions: async () => {\n (await import(\"./commands/subscriptions.js\")).registerSubscriptionsCommands(program);\n },\n iap: async () => {\n (await import(\"./commands/iap.js\")).registerIapCommands(program);\n },\n purchases: async () => {\n (await import(\"./commands/purchases.js\")).registerPurchasesCommands(program);\n },\n pricing: async () => {\n (await import(\"./commands/pricing.js\")).registerPricingCommands(program);\n },\n reports: async () => {\n (await import(\"./commands/reports.js\")).registerReportsCommands(program);\n },\n users: async () => {\n (await import(\"./commands/users.js\")).registerUsersCommands(program);\n },\n testers: async () => {\n (await import(\"./commands/testers.js\")).registerTestersCommands(program);\n },\n validate: async () => {\n (await import(\"./commands/validate.js\")).registerValidateCommand(program);\n },\n publish: async () => {\n (await import(\"./commands/publish.js\")).registerPublishCommand(program);\n },\n recovery: async () => {\n (await import(\"./commands/recovery.js\")).registerRecoveryCommands(program);\n },\n \"data-safety\": async () => {\n (await import(\"./commands/data-safety.js\")).registerDataSafetyCommands(program);\n },\n \"external-transactions\": async () => {\n (await import(\"./commands/external-transactions.js\")).registerExternalTransactionsCommands(\n program,\n );\n },\n \"device-tiers\": async () => {\n (await import(\"./commands/device-tiers.js\")).registerDeviceTiersCommands(program);\n },\n \"one-time-products\": async () => {\n (await import(\"./commands/one-time-products.js\")).registerOneTimeProductsCommands(program);\n },\n \"internal-sharing\": async () => {\n (await import(\"./commands/internal-sharing.js\")).registerInternalSharingCommands(program);\n },\n \"generated-apks\": async () => {\n (await import(\"./commands/generated-apks.js\")).registerGeneratedApksCommands(program);\n },\n \"purchase-options\": async () => {\n (await import(\"./commands/purchase-options.js\")).registerPurchaseOptionsCommands(program);\n },\n audit: async () => {\n (await import(\"./commands/audit.js\")).registerAuditCommands(program);\n },\n migrate: async () => {\n (await import(\"./commands/migrate.js\")).registerMigrateCommands(program);\n },\n \"install-skills\": async () => {\n (await import(\"./commands/install-skills.js\")).registerInstallSkillsCommand(program);\n },\n plugins: async () => {\n registerPluginsCommand(program, pluginManager);\n },\n };\n\n // Resolve command aliases for lazy loading\n const commandAliases: Record<string, string> = {\n \"ext-txn\": \"external-transactions\",\n otp: \"one-time-products\",\n };\n\n const rawTarget = process.argv[2];\n const target = rawTarget ? (commandAliases[rawTarget] ?? rawTarget) : undefined;\n\n const loader = target ? commandLoaders[target] : undefined;\n if (loader) {\n await loader();\n } else {\n await Promise.all(Object.values(commandLoaders).map((loader) => loader()));\n }\n\n // Register plugin-defined commands\n if (pluginManager) {\n registerPluginCommands(program, pluginManager);\n }\n\n // Wire plugin lifecycle hooks around command execution\n if (pluginManager) {\n wrapCommandHooks(program, pluginManager);\n }\n\n return program;\n}\n\n/**\n * `gpc plugins` — manage plugins.\n */\nfunction registerPluginsCommand(program: Command, manager?: PluginManager): void {\n const cmd = program.command(\"plugins\").description(\"Manage plugins\");\n\n cmd\n .command(\"list\")\n .description(\"List loaded plugins\")\n .action(() => {\n const plugins = manager?.getLoadedPlugins() ?? [];\n const opts = program.opts();\n\n if (opts[\"output\"] === \"json\") {\n console.log(JSON.stringify(plugins, null, 2));\n return;\n }\n\n if (plugins.length === 0) {\n console.log(\"No plugins loaded.\");\n console.log('\\nConfigure plugins in .gpcrc.json: { \"plugins\": [\"@gpc-cli/plugin-ci\"] }');\n return;\n }\n\n console.log(\"Loaded plugins:\\n\");\n for (const p of plugins) {\n const trust = p.trusted ? \"trusted\" : \"third-party\";\n console.log(` ${p.name}@${p.version} (${trust})`);\n }\n\n const commands = manager?.getRegisteredCommands() ?? [];\n if (commands.length > 0) {\n console.log(\"\\nPlugin commands:\\n\");\n for (const c of commands) {\n console.log(` gpc ${c.name} — ${c.description}`);\n }\n }\n });\n\n cmd\n .command(\"init <name>\")\n .description(\"Scaffold a new plugin project\")\n .option(\"-d, --dir <path>\", \"Output directory (defaults to ./gpc-plugin-<name>)\")\n .option(\"--description <text>\", \"Plugin description\")\n .action(async (name: string, opts: { dir?: string; description?: string }) => {\n const { scaffoldPlugin } = await import(\"@gpc-cli/core\");\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const dir = opts.dir ?? `./${pluginName}`;\n\n const result = await scaffoldPlugin({ name, dir, description: opts.description });\n\n console.log(`Plugin scaffolded at ${result.dir}/\\n`);\n console.log(\"Files created:\");\n for (const f of result.files) {\n console.log(` ${f}`);\n }\n console.log(`\\nNext steps:`);\n console.log(` cd ${pluginName}`);\n console.log(` npm install`);\n console.log(` npm run build`);\n console.log(` npm test`);\n });\n\n cmd\n .command(\"approve <name>\")\n .description(\"Approve a third-party plugin for loading\")\n .action(async (name: string) => {\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`Plugin \"${name}\" approved. It will be loaded on next run.`);\n });\n\n cmd\n .command(\"revoke <name>\")\n .description(\"Revoke approval for a third-party plugin\")\n .action(async (name: string) => {\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n const removed = await revokePluginApproval(name);\n if (removed) {\n console.log(`Plugin \"${name}\" approval revoked.`);\n } else {\n console.log(`Plugin \"${name}\" was not in the approved list.`);\n }\n });\n}\n\n/**\n * Wrap all registered commands so plugin hooks fire before/after each command.\n */\nfunction wrapCommandHooks(program: Command, manager: PluginManager): void {\n program.hook(\"preAction\", async (thisCommand) => {\n const event: CommandEvent = {\n command: getFullCommandName(thisCommand),\n args: thisCommand.opts(),\n app: program.opts()[\"app\"] as string | undefined,\n startedAt: new Date(),\n };\n\n // Store on the command for afterCommand/onError\n (thisCommand as unknown as Record<string, unknown>)[\"__pluginEvent\"] = event;\n\n await manager.runBeforeCommand(event);\n });\n\n program.hook(\"postAction\", async (thisCommand) => {\n const event: CommandEvent = (thisCommand as unknown as Record<string, unknown>)[\n \"__pluginEvent\"\n ] as CommandEvent;\n if (!event) return;\n\n const result: CommandResult = {\n success: true,\n durationMs: Date.now() - event.startedAt.getTime(),\n exitCode: 0,\n };\n\n await manager.runAfterCommand(event, result);\n });\n}\n\nfunction getFullCommandName(cmd: Command): string {\n const parts: string[] = [];\n let current: Command | null = cmd;\n while (current && current.name() !== \"gpc\") {\n parts.unshift(current.name());\n current = current.parent;\n }\n return parts.join(\" \");\n}\n","/**\n * Shared error formatting for CLI output.\n * Extracts error code, message, and suggestion from typed errors (GpcError, AuthError, ApiError, ConfigError).\n */\n\ninterface TypedError {\n message: string;\n code?: string;\n suggestion?: string;\n exitCode?: number;\n}\n\nfunction isTypedError(error: unknown): error is Error & TypedError {\n return error instanceof Error && \"code\" in error && typeof (error as TypedError).code === \"string\";\n}\n\n/**\n * Format an error for CLI output. Prints:\n * Error [CODE]: message\n * Suggestion: suggestion (if available)\n *\n * Returns the appropriate exit code.\n */\nexport function handleCliError(error: unknown): number {\n if (isTypedError(error)) {\n console.error(`Error [${error.code}]: ${error.message}`);\n if (error.suggestion) {\n console.error(`Suggestion: ${error.suggestion}`);\n }\n return error.exitCode ?? 1;\n }\n\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n return 1;\n}\n"],"mappings":"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","names":["loader"]}
1
+ {"version":3,"sources":["../src/plugins.ts","../src/program.ts","../src/error-handler.ts"],"sourcesContent":["import { PluginManager, discoverPlugins } from \"@gpc-cli/core\";\nimport type { Command } from \"commander\";\n\n/**\n * Load and initialize all plugins.\n * First-party plugins (@gpc-cli/*) are auto-trusted.\n * Third-party plugins require prior approval stored in config.\n * Plugin loading is disabled in standalone binary mode.\n */\nexport async function loadPlugins(): Promise<PluginManager> {\n const manager = new PluginManager();\n\n // Standalone binary cannot resolve external npm packages at runtime\n if (process.env[\"__GPC_BINARY\"] === \"1\") {\n return manager;\n }\n\n try {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const plugins = await discoverPlugins({ configPlugins: config.plugins });\n const approved = new Set(config.approvedPlugins ?? []);\n\n for (const plugin of plugins) {\n const isTrusted = plugin.name.startsWith(\"@gpc-cli/\");\n\n if (!isTrusted && !approved.has(plugin.name)) {\n // Skip unapproved third-party plugins silently in non-interactive mode\n // In interactive mode, the user would run `gpc plugins approve <name>` first\n const isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n if (!isQuiet) {\n console.error(\n `Plugin \"${plugin.name}\" is not approved. Run: gpc plugins approve ${plugin.name}`,\n );\n }\n continue;\n }\n\n try {\n await manager.load(plugin);\n } catch {\n // Skip plugins that fail to load — don't block the CLI\n }\n }\n } catch {\n // Config loading failure shouldn't block plugin-free commands\n }\n\n return manager;\n}\n\n/**\n * Register plugin-defined commands with the Commander program.\n */\nexport function registerPluginCommands(program: Command, manager: PluginManager): void {\n for (const def of manager.getRegisteredCommands()) {\n const cmd = program.command(def.name).description(def.description);\n\n if (def.arguments) {\n for (const arg of def.arguments) {\n const syntax = arg.required ? `<${arg.name}>` : `[${arg.name}]`;\n cmd.argument(syntax, arg.description);\n }\n }\n\n if (def.options) {\n for (const opt of def.options) {\n cmd.option(\n opt.flags,\n opt.description,\n opt.defaultValue as string | boolean | string[] | undefined,\n );\n }\n }\n\n cmd.action(async (...rawArgs: unknown[]) => {\n const opts = rawArgs[rawArgs.length - 2] as Record<string, unknown>;\n const args: Record<string, unknown> = {};\n\n if (def.arguments) {\n def.arguments.forEach((argDef, i) => {\n args[argDef.name] = rawArgs[i];\n });\n }\n\n await def.action(args, opts);\n });\n }\n}\n","import { Command } from \"commander\";\nimport type { PluginManager } from \"@gpc-cli/core\";\nimport type { CommandEvent, CommandResult } from \"@gpc-cli/plugin-sdk\";\nimport { registerPluginCommands } from \"./plugins.js\";\n\nexport async function createProgram(pluginManager?: PluginManager): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"gpc\")\n .description(\"The complete Google Play CLI\")\n .version(process.env[\"__GPC_VERSION\"] || \"0.0.0\", \"-V, --version\")\n .option(\"-o, --output <format>\", \"Output format: table, json, yaml, markdown, junit\")\n .option(\"-v, --verbose\", \"Enable debug logging\")\n .option(\"-q, --quiet\", \"Suppress non-essential output\")\n .option(\"-a, --app <package>\", \"App package name\")\n .option(\"-p, --profile <name>\", \"Auth profile name\")\n .option(\"--no-color\", \"Disable colored output\")\n .option(\"--no-interactive\", \"Disable interactive prompts\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without executing\")\n .option(\"--notify [target]\", \"Send webhook notification on completion (slack, discord, custom)\")\n .option(\"--ci\", \"Force CI mode (JSON output, no prompts, strict exit codes)\")\n .option(\"-j, --json\", \"Shorthand for --output json\")\n .showSuggestionAfterError(true);\n\n const commandLoaders: Record<string, () => Promise<void>> = {\n auth: async () => {\n (await import(\"./commands/auth.js\")).registerAuthCommands(program);\n },\n config: async () => {\n (await import(\"./commands/config.js\")).registerConfigCommands(program);\n },\n doctor: async () => {\n (await import(\"./commands/doctor.js\")).registerDoctorCommand(program);\n },\n docs: async () => {\n (await import(\"./commands/docs.js\")).registerDocsCommand(program);\n },\n completion: async () => {\n (await import(\"./commands/completion.js\")).registerCompletionCommand(program);\n },\n apps: async () => {\n (await import(\"./commands/apps.js\")).registerAppsCommands(program);\n },\n releases: async () => {\n (await import(\"./commands/releases.js\")).registerReleasesCommands(program);\n },\n tracks: async () => {\n (await import(\"./commands/tracks.js\")).registerTracksCommands(program);\n },\n status: async () => {\n (await import(\"./commands/status.js\")).registerStatusCommand(program);\n },\n listings: async () => {\n (await import(\"./commands/listings.js\")).registerListingsCommands(program);\n },\n reviews: async () => {\n (await import(\"./commands/reviews.js\")).registerReviewsCommands(program);\n },\n vitals: async () => {\n (await import(\"./commands/vitals.js\")).registerVitalsCommands(program);\n },\n subscriptions: async () => {\n (await import(\"./commands/subscriptions.js\")).registerSubscriptionsCommands(program);\n },\n iap: async () => {\n (await import(\"./commands/iap.js\")).registerIapCommands(program);\n },\n purchases: async () => {\n (await import(\"./commands/purchases.js\")).registerPurchasesCommands(program);\n },\n pricing: async () => {\n (await import(\"./commands/pricing.js\")).registerPricingCommands(program);\n },\n reports: async () => {\n (await import(\"./commands/reports.js\")).registerReportsCommands(program);\n },\n users: async () => {\n (await import(\"./commands/users.js\")).registerUsersCommands(program);\n },\n testers: async () => {\n (await import(\"./commands/testers.js\")).registerTestersCommands(program);\n },\n validate: async () => {\n (await import(\"./commands/validate.js\")).registerValidateCommand(program);\n },\n publish: async () => {\n (await import(\"./commands/publish.js\")).registerPublishCommand(program);\n },\n recovery: async () => {\n (await import(\"./commands/recovery.js\")).registerRecoveryCommands(program);\n },\n \"data-safety\": async () => {\n (await import(\"./commands/data-safety.js\")).registerDataSafetyCommands(program);\n },\n \"external-transactions\": async () => {\n (await import(\"./commands/external-transactions.js\")).registerExternalTransactionsCommands(\n program,\n );\n },\n \"device-tiers\": async () => {\n (await import(\"./commands/device-tiers.js\")).registerDeviceTiersCommands(program);\n },\n \"one-time-products\": async () => {\n (await import(\"./commands/one-time-products.js\")).registerOneTimeProductsCommands(program);\n },\n \"internal-sharing\": async () => {\n (await import(\"./commands/internal-sharing.js\")).registerInternalSharingCommands(program);\n },\n \"generated-apks\": async () => {\n (await import(\"./commands/generated-apks.js\")).registerGeneratedApksCommands(program);\n },\n \"purchase-options\": async () => {\n (await import(\"./commands/purchase-options.js\")).registerPurchaseOptionsCommands(program);\n },\n bundle: async () => {\n (await import(\"./commands/bundle.js\")).registerBundleCommands(program);\n },\n audit: async () => {\n (await import(\"./commands/audit.js\")).registerAuditCommands(program);\n },\n migrate: async () => {\n (await import(\"./commands/migrate.js\")).registerMigrateCommands(program);\n },\n \"install-skills\": async () => {\n (await import(\"./commands/install-skills.js\")).registerInstallSkillsCommand(program);\n },\n plugins: async () => {\n registerPluginsCommand(program, pluginManager);\n },\n };\n\n // Resolve command aliases for lazy loading\n const commandAliases: Record<string, string> = {\n \"ext-txn\": \"external-transactions\",\n otp: \"one-time-products\",\n };\n\n const rawTarget = process.argv[2];\n const target = rawTarget ? (commandAliases[rawTarget] ?? rawTarget) : undefined;\n\n const loader = target ? commandLoaders[target] : undefined;\n if (loader) {\n await loader();\n } else {\n await Promise.all(Object.values(commandLoaders).map((loader) => loader()));\n }\n\n // Register plugin-defined commands\n if (pluginManager) {\n registerPluginCommands(program, pluginManager);\n }\n\n // Wire plugin lifecycle hooks around command execution\n if (pluginManager) {\n wrapCommandHooks(program, pluginManager);\n }\n\n return program;\n}\n\n/**\n * `gpc plugins` — manage plugins.\n */\nfunction registerPluginsCommand(program: Command, manager?: PluginManager): void {\n const cmd = program.command(\"plugins\").description(\"Manage plugins\");\n\n cmd\n .command(\"list\")\n .description(\"List loaded plugins\")\n .action(() => {\n const plugins = manager?.getLoadedPlugins() ?? [];\n const opts = program.opts();\n\n if (opts[\"output\"] === \"json\") {\n console.log(JSON.stringify(plugins, null, 2));\n return;\n }\n\n if (plugins.length === 0) {\n console.log(\"No plugins loaded.\");\n console.log('\\nConfigure plugins in .gpcrc.json: { \"plugins\": [\"@gpc-cli/plugin-ci\"] }');\n return;\n }\n\n console.log(\"Loaded plugins:\\n\");\n for (const p of plugins) {\n const trust = p.trusted ? \"trusted\" : \"third-party\";\n console.log(` ${p.name}@${p.version} (${trust})`);\n }\n\n const commands = manager?.getRegisteredCommands() ?? [];\n if (commands.length > 0) {\n console.log(\"\\nPlugin commands:\\n\");\n for (const c of commands) {\n console.log(` gpc ${c.name} — ${c.description}`);\n }\n }\n });\n\n cmd\n .command(\"init <name>\")\n .description(\"Scaffold a new plugin project\")\n .option(\"-d, --dir <path>\", \"Output directory (defaults to ./gpc-plugin-<name>)\")\n .option(\"--description <text>\", \"Plugin description\")\n .action(async (name: string, opts: { dir?: string; description?: string }) => {\n const { scaffoldPlugin } = await import(\"@gpc-cli/core\");\n const pluginName = name.startsWith(\"gpc-plugin-\") ? name : `gpc-plugin-${name}`;\n const dir = opts.dir ?? `./${pluginName}`;\n\n const result = await scaffoldPlugin({ name, dir, description: opts.description });\n\n console.log(`Plugin scaffolded at ${result.dir}/\\n`);\n console.log(\"Files created:\");\n for (const f of result.files) {\n console.log(` ${f}`);\n }\n console.log(`\\nNext steps:`);\n console.log(` cd ${pluginName}`);\n console.log(` npm install`);\n console.log(` npm run build`);\n console.log(` npm test`);\n });\n\n cmd\n .command(\"approve <name>\")\n .description(\"Approve a third-party plugin for loading\")\n .action(async (name: string) => {\n const { approvePlugin } = await import(\"@gpc-cli/config\");\n await approvePlugin(name);\n console.log(`Plugin \"${name}\" approved. It will be loaded on next run.`);\n });\n\n cmd\n .command(\"revoke <name>\")\n .description(\"Revoke approval for a third-party plugin\")\n .action(async (name: string) => {\n const { revokePluginApproval } = await import(\"@gpc-cli/config\");\n const removed = await revokePluginApproval(name);\n if (removed) {\n console.log(`Plugin \"${name}\" approval revoked.`);\n } else {\n console.log(`Plugin \"${name}\" was not in the approved list.`);\n }\n });\n}\n\n/**\n * Wrap all registered commands so plugin hooks fire before/after each command.\n */\nfunction wrapCommandHooks(program: Command, manager: PluginManager): void {\n program.hook(\"preAction\", async (thisCommand) => {\n const event: CommandEvent = {\n command: getFullCommandName(thisCommand),\n args: thisCommand.opts(),\n app: program.opts()[\"app\"] as string | undefined,\n startedAt: new Date(),\n };\n\n // Store on the command for afterCommand/onError\n (thisCommand as unknown as Record<string, unknown>)[\"__pluginEvent\"] = event;\n\n await manager.runBeforeCommand(event);\n });\n\n program.hook(\"postAction\", async (thisCommand) => {\n const event: CommandEvent = (thisCommand as unknown as Record<string, unknown>)[\n \"__pluginEvent\"\n ] as CommandEvent;\n if (!event) return;\n\n const result: CommandResult = {\n success: true,\n durationMs: Date.now() - event.startedAt.getTime(),\n exitCode: 0,\n };\n\n await manager.runAfterCommand(event, result);\n });\n}\n\nfunction getFullCommandName(cmd: Command): string {\n const parts: string[] = [];\n let current: Command | null = cmd;\n while (current && current.name() !== \"gpc\") {\n parts.unshift(current.name());\n current = current.parent;\n }\n return parts.join(\" \");\n}\n","/**\n * Shared error formatting for CLI output.\n * Extracts error code, message, and suggestion from typed errors (GpcError, AuthError, ApiError, ConfigError).\n */\n\ninterface TypedError {\n message: string;\n code?: string;\n suggestion?: string;\n exitCode?: number;\n}\n\nfunction isTypedError(error: unknown): error is Error & TypedError {\n return error instanceof Error && \"code\" in error && typeof (error as TypedError).code === \"string\";\n}\n\n/**\n * Format an error for CLI output. Prints:\n * Error [CODE]: message\n * Suggestion: suggestion (if available)\n *\n * Returns the appropriate exit code.\n */\nexport function handleCliError(error: unknown): number {\n if (isTypedError(error)) {\n console.error(`Error [${error.code}]: ${error.message}`);\n if (error.suggestion) {\n console.error(`Suggestion: ${error.suggestion}`);\n }\n return error.exitCode ?? 1;\n }\n\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${message}`);\n return 1;\n}\n"],"mappings":"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","names":["loader"]}
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getOutputFormat
4
+ } from "./chunk-ELXAK7GI.js";
5
+ import {
6
+ isInteractive,
7
+ promptConfirm,
8
+ promptInput,
9
+ promptSelect
10
+ } from "./chunk-NV75I5VP.js";
11
+
12
+ // src/commands/config.ts
13
+ import { loadConfig, setConfigValue, getUserConfigPath, initConfig } from "@gpc-cli/config";
14
+ import { formatOutput, writeAuditLog, createAuditEntry } from "@gpc-cli/core";
15
+ import { existsSync } from "fs";
16
+ import { resolve } from "path";
17
+ var ANDROID_PACKAGE_RE = /^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$/;
18
+ function registerConfigCommands(program) {
19
+ const config = program.command("config").description("Manage configuration");
20
+ config.command("init").description("Create a configuration file").option("--global", "Create in user config directory (~/.config/gpc/)").action(async (_options) => {
21
+ const initialConfig = {};
22
+ if (isInteractive(program)) {
23
+ console.log("\nGPC Setup Wizard\n");
24
+ let app = await promptInput("Default package name (e.g. com.example.app, blank to skip)");
25
+ if (app) {
26
+ if (!ANDROID_PACKAGE_RE.test(app)) {
27
+ console.error(
28
+ ` Warning: "${app}" doesn't look like a valid Android package name \u2014 continuing anyway`
29
+ );
30
+ }
31
+ initialConfig["app"] = app;
32
+ }
33
+ const authMethod = await promptSelect(
34
+ "Authentication method:",
35
+ ["service-account", "adc", "skip"],
36
+ "service-account"
37
+ );
38
+ if (authMethod === "service-account") {
39
+ let saPath = "";
40
+ while (true) {
41
+ saPath = await promptInput("Path to service account JSON key file");
42
+ if (!saPath) {
43
+ console.log(" Skipping service account setup.");
44
+ break;
45
+ }
46
+ const resolved = resolve(saPath);
47
+ if (existsSync(resolved)) {
48
+ initialConfig["auth"] = { serviceAccount: saPath };
49
+ break;
50
+ }
51
+ console.error(` File not found: ${resolved}`);
52
+ const retry = await promptConfirm("Try a different path?");
53
+ if (!retry) break;
54
+ }
55
+ } else if (authMethod === "adc") {
56
+ console.log(
57
+ " Using Application Default Credentials \u2014 run `gcloud auth application-default login` if not already set up."
58
+ );
59
+ }
60
+ const output = await promptSelect(
61
+ "Default output format:",
62
+ ["table", "json", "yaml", "markdown"],
63
+ "table"
64
+ );
65
+ if (output !== "table") initialConfig["output"] = output;
66
+ }
67
+ const path = await initConfig(initialConfig);
68
+ const configured = [];
69
+ if (initialConfig["app"]) configured.push(`app: ${initialConfig["app"]}`);
70
+ if (initialConfig["auth"]) configured.push("auth: service account");
71
+ if (initialConfig["output"]) configured.push(`output: ${initialConfig["output"]}`);
72
+ console.log(`
73
+ Configuration file created: ${path}`);
74
+ if (configured.length > 0) {
75
+ console.log(` ${configured.join(" \xB7 ")}`);
76
+ }
77
+ console.log("\nRun `gpc doctor` to verify your setup.");
78
+ writeAuditLog(createAuditEntry("config init", { path })).catch(() => {
79
+ });
80
+ });
81
+ config.command("show").description("Display resolved configuration").action(async () => {
82
+ const resolved = await loadConfig();
83
+ const format = getOutputFormat(program, resolved);
84
+ console.log(formatOutput(resolved, format));
85
+ });
86
+ config.command("set <key> <value>").description("Set a configuration value").action(async (key, value) => {
87
+ await setConfigValue(key, value);
88
+ console.log(`Set ${key} = ${value}`);
89
+ });
90
+ config.command("path").description("Show configuration file path").action(() => {
91
+ console.log(getUserConfigPath());
92
+ });
93
+ }
94
+ export {
95
+ registerConfigCommands
96
+ };
97
+ //# sourceMappingURL=config-2L7QUYWP.js.map