@gpc-cli/cli 0.9.85 → 0.9.87

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 (30) hide show
  1. package/README.md +2 -2
  2. package/dist/bin.js +2 -2
  3. package/dist/{chunk-IAPAEPDL.js → chunk-E2NRW3TQ.js} +11 -11
  4. package/dist/{config-XOJX2NCA.js → config-7SLPBJI3.js} +2 -2
  5. package/dist/{doctor-PFLPGPM3.js → doctor-3MJZSIGX.js} +2 -2
  6. package/dist/{feedback-FF3CBERM.js → feedback-TXDXWK7N.js} +2 -2
  7. package/dist/games-7K5RKXCO.js +361 -0
  8. package/dist/games-7K5RKXCO.js.map +1 -0
  9. package/dist/generated/docs-bundle.json +1 -1
  10. package/dist/{grants-Q3FWJYGR.js → grants-ANDUST7O.js} +13 -9
  11. package/dist/grants-ANDUST7O.js.map +1 -0
  12. package/dist/index.js +1 -1
  13. package/dist/{testers-YQZ2XHI6.js → testers-OQNP43O6.js} +14 -4
  14. package/dist/testers-OQNP43O6.js.map +1 -0
  15. package/dist/{tracks-N7KPBVPC.js → tracks-E7RUNA3C.js} +16 -4
  16. package/dist/tracks-E7RUNA3C.js.map +1 -0
  17. package/dist/{update-JGLB2ELN.js → update-UMNA6KMP.js} +2 -2
  18. package/dist/{version-B4AE5NVE.js → version-PFYWZWJC.js} +2 -2
  19. package/package.json +5 -5
  20. package/dist/games-SVFN2YIS.js +0 -60
  21. package/dist/games-SVFN2YIS.js.map +0 -1
  22. package/dist/grants-Q3FWJYGR.js.map +0 -1
  23. package/dist/testers-YQZ2XHI6.js.map +0 -1
  24. package/dist/tracks-N7KPBVPC.js.map +0 -1
  25. /package/dist/{chunk-IAPAEPDL.js.map → chunk-E2NRW3TQ.js.map} +0 -0
  26. /package/dist/{config-XOJX2NCA.js.map → config-7SLPBJI3.js.map} +0 -0
  27. /package/dist/{doctor-PFLPGPM3.js.map → doctor-3MJZSIGX.js.map} +0 -0
  28. /package/dist/{feedback-FF3CBERM.js.map → feedback-TXDXWK7N.js.map} +0 -0
  29. /package/dist/{update-JGLB2ELN.js.map → update-UMNA6KMP.js.map} +0 -0
  30. /package/dist/{version-B4AE5NVE.js.map → version-PFYWZWJC.js.map} +0 -0
package/README.md CHANGED
@@ -33,7 +33,7 @@ gpc doctor # 22 setup checks
33
33
 
34
34
  | | **GPC** | Fastlane supply |
35
35
  | ------------------------------- | ------------------------------ | --------------- |
36
- | API coverage | **217 endpoints** | ~20 |
36
+ | API coverage | **227 endpoints** | ~20 |
37
37
  | Runtime | Node.js or binary | Ruby + Bundler |
38
38
  | Cold start | <500ms | 2-3s |
39
39
  | Reviews & Vitals | Yes | No |
@@ -97,7 +97,7 @@ curl -fsSL https://raw.githubusercontent.com/yasserstudio/gpc/main/scripts/insta
97
97
  - [Commands reference](https://yasserstudio.github.io/gpc/commands/)
98
98
  - [CI/CD recipes](https://yasserstudio.github.io/gpc/ci-cd/)
99
99
 
100
- Free to use. 2,380 tests. 90%+ coverage. Every write operation supports `--dry-run`.
100
+ Free to use. 2,413 tests. 90%+ coverage. Every write operation supports `--dry-run`.
101
101
 
102
102
  ## Licensing
103
103
 
package/dist/bin.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-IAPAEPDL.js";
6
+ } from "./chunk-E2NRW3TQ.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.85";
60
+ var currentVersion = "0.9.87";
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);
@@ -59,19 +59,19 @@ function registerPluginCommands(program, manager) {
59
59
  import { Command } from "commander";
60
60
  async function createProgram(pluginManager) {
61
61
  const program = new Command();
62
- program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.85", "-V, --version").option("-o, --output <format>", "Output format: table, json, yaml, markdown, csv, tsv, 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);
62
+ program.name("gpc").description("GPC \u2014 Google Play Console CLI").version("0.9.87", "-V, --version").option("-o, --output <format>", "Output format: table, json, yaml, markdown, csv, tsv, 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);
63
63
  const commandLoaders = {
64
64
  auth: async () => {
65
65
  (await import("./auth-C6K563I5.js")).registerAuthCommands(program);
66
66
  },
67
67
  config: async () => {
68
- (await import("./config-XOJX2NCA.js")).registerConfigCommands(program);
68
+ (await import("./config-7SLPBJI3.js")).registerConfigCommands(program);
69
69
  },
70
70
  doctor: async () => {
71
- (await import("./doctor-PFLPGPM3.js")).registerDoctorCommand(program);
71
+ (await import("./doctor-3MJZSIGX.js")).registerDoctorCommand(program);
72
72
  },
73
73
  update: async () => {
74
- (await import("./update-JGLB2ELN.js")).registerUpdateCommand(program);
74
+ (await import("./update-UMNA6KMP.js")).registerUpdateCommand(program);
75
75
  },
76
76
  docs: async () => {
77
77
  (await import("./docs-ADZRT76Y.js")).registerDocsCommand(program);
@@ -96,7 +96,7 @@ async function createProgram(pluginManager) {
96
96
  (await import("./releases-YJCNQHY7.js")).registerReleasesCommands(program);
97
97
  },
98
98
  tracks: async () => {
99
- (await import("./tracks-N7KPBVPC.js")).registerTracksCommands(program);
99
+ (await import("./tracks-E7RUNA3C.js")).registerTracksCommands(program);
100
100
  },
101
101
  status: async () => {
102
102
  (await import("./status-32AJ7A6O.js")).registerStatusCommand(program);
@@ -129,7 +129,7 @@ async function createProgram(pluginManager) {
129
129
  (await import("./users-EKXLDY2Y.js")).registerUsersCommands(program);
130
130
  },
131
131
  testers: async () => {
132
- (await import("./testers-YQZ2XHI6.js")).registerTestersCommands(program);
132
+ (await import("./testers-OQNP43O6.js")).registerTestersCommands(program);
133
133
  },
134
134
  validate: async () => {
135
135
  (await import("./validate-RHWEZYD2.js")).registerValidateCommand(program);
@@ -191,13 +191,13 @@ async function createProgram(pluginManager) {
191
191
  (await import("./verify-O2PSBTIC.js")).registerVerifyCommand(program);
192
192
  },
193
193
  version: async () => {
194
- (await import("./version-B4AE5NVE.js")).registerVersionCommand(program);
194
+ (await import("./version-PFYWZWJC.js")).registerVersionCommand(program);
195
195
  },
196
196
  cache: async () => {
197
197
  (await import("./cache-FGNP7Y37.js")).registerCacheCommand(program);
198
198
  },
199
199
  feedback: async () => {
200
- (await import("./feedback-FF3CBERM.js")).registerFeedbackCommand(program);
200
+ (await import("./feedback-TXDXWK7N.js")).registerFeedbackCommand(program);
201
201
  },
202
202
  setup: async () => {
203
203
  (await import("./setup-XC4X323X.js")).registerSetupCommand(program);
@@ -206,7 +206,7 @@ async function createProgram(pluginManager) {
206
206
  (await import("./quickstart-FOWM3OKT.js")).registerQuickstartCommand(program);
207
207
  },
208
208
  grants: async () => {
209
- (await import("./grants-Q3FWJYGR.js")).registerGrantsCommands(program);
209
+ (await import("./grants-ANDUST7O.js")).registerGrantsCommands(program);
210
210
  },
211
211
  train: async () => {
212
212
  (await import("./train-N4TPYUTB.js")).registerTrainCommands(program);
@@ -215,7 +215,7 @@ async function createProgram(pluginManager) {
215
215
  (await import("./quota-MZRWYJGR.js")).registerQuotaCommand(program);
216
216
  },
217
217
  games: async () => {
218
- (await import("./games-SVFN2YIS.js")).registerGamesCommands(program);
218
+ (await import("./games-7K5RKXCO.js")).registerGamesCommands(program);
219
219
  },
220
220
  enterprise: async () => {
221
221
  (await import("./enterprise-T5NWQS2R.js")).registerEnterpriseCommands(program);
@@ -471,4 +471,4 @@ export {
471
471
  createProgram,
472
472
  handleCliError
473
473
  };
474
- //# sourceMappingURL=chunk-IAPAEPDL.js.map
474
+ //# sourceMappingURL=chunk-E2NRW3TQ.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-PFLPGPM3.js");
81
+ const { registerDoctorCommand } = await import("./doctor-3MJZSIGX.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-XOJX2NCA.js.map
110
+ //# sourceMappingURL=config-7SLPBJI3.js.map
@@ -144,7 +144,7 @@ function checkCiEnvironment() {
144
144
  };
145
145
  }
146
146
  async function checkGpcVersion() {
147
- const currentVersion = "0.9.85";
147
+ const currentVersion = "0.9.87";
148
148
  if (currentVersion === "0.0.0") {
149
149
  return { name: "version", status: "info", message: "GPC development build" };
150
150
  }
@@ -1138,4 +1138,4 @@ export {
1138
1138
  checkVerificationDeadline,
1139
1139
  registerDoctorCommand
1140
1140
  };
1141
- //# sourceMappingURL=doctor-PFLPGPM3.js.map
1141
+ //# sourceMappingURL=doctor-3MJZSIGX.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.85";
12
+ const version = "0.9.87";
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-FF3CBERM.js.map
70
+ //# sourceMappingURL=feedback-TXDXWK7N.js.map
@@ -0,0 +1,361 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readJsonFile
4
+ } from "./chunk-22XCOLZX.js";
5
+ import {
6
+ resolvePackageName
7
+ } from "./chunk-JDRY7HK5.js";
8
+ import {
9
+ isDryRun,
10
+ printDryRun
11
+ } from "./chunk-QHBTG2NG.js";
12
+ import {
13
+ requireConfirm
14
+ } from "./chunk-RZQSEDKI.js";
15
+ import {
16
+ getOutputFormat
17
+ } from "./chunk-ELXAK7GI.js";
18
+
19
+ // src/commands/games.ts
20
+ import { loadConfig } from "@gpc-cli/config";
21
+ import { resolveAuth } from "@gpc-cli/auth";
22
+ import {
23
+ createGamesClient,
24
+ createGamesConfigClient
25
+ } from "@gpc-cli/api";
26
+ import {
27
+ listLeaderboards,
28
+ listAchievements,
29
+ listAchievementConfigs,
30
+ getAchievementConfig,
31
+ createAchievementConfig,
32
+ updateAchievementConfig,
33
+ deleteAchievementConfig,
34
+ diffAchievementConfig,
35
+ listLeaderboardConfigs,
36
+ getLeaderboardConfig,
37
+ createLeaderboardConfig,
38
+ updateLeaderboardConfig,
39
+ deleteLeaderboardConfig,
40
+ diffLeaderboardConfig,
41
+ formatOutput,
42
+ annotateListResult,
43
+ moreResultsFooter,
44
+ GpcError
45
+ } from "@gpc-cli/core";
46
+ function resolveGameId(flag, config) {
47
+ const gameId = flag ?? process.env["GPC_GAME_ID"] ?? config.games?.applicationId;
48
+ if (!gameId) {
49
+ throw new GpcError(
50
+ "Game application ID is required. Pass --game-id, set GPC_GAME_ID, or add games.applicationId to .gpcrc.json.",
51
+ "GAMES_NO_APPLICATION_ID",
52
+ 2,
53
+ "Find your numeric application ID in Play Console > Play Games Services > Setup."
54
+ );
55
+ }
56
+ return gameId;
57
+ }
58
+ async function getGamesClient(config) {
59
+ const auth = await resolveAuth({
60
+ serviceAccountPath: config.auth?.serviceAccount
61
+ });
62
+ return createGamesClient({ auth });
63
+ }
64
+ async function getGamesConfigClientFromConfig(config) {
65
+ const auth = await resolveAuth({
66
+ serviceAccountPath: config.auth?.serviceAccount
67
+ });
68
+ return createGamesConfigClient({ auth });
69
+ }
70
+ function registerGamesCommands(program) {
71
+ const games = program.command("games").description(
72
+ "Manage Play Games Services \u2014 achievements, leaderboards (configuration API)"
73
+ ).option("--game-id <id>", "Games application ID (numeric)");
74
+ const achievements = games.command("achievements").description("Manage achievement configurations");
75
+ achievements.command("list").description("List achievement configurations").option("--limit <n>", "Maximum results per page", parseInt).option("--next-page <token>", "Resume from page token").action(async (options) => {
76
+ const config = await loadConfig();
77
+ const gameId = resolveGameId(games.opts()["gameId"], config);
78
+ const client = await getGamesConfigClientFromConfig(config);
79
+ const format = getOutputFormat(program, config);
80
+ const result = await listAchievementConfigs(client, gameId, {
81
+ maxResults: options.limit,
82
+ pageToken: options.nextPage
83
+ });
84
+ const items = result.items ?? [];
85
+ if (format !== "json") {
86
+ if (items.length === 0) {
87
+ console.log("No achievement configurations found.");
88
+ } else {
89
+ console.log(formatOutput(items, format));
90
+ const footer = moreResultsFooter(result.nextPageToken);
91
+ if (footer) console.log(footer);
92
+ }
93
+ } else {
94
+ console.log(
95
+ formatOutput(
96
+ annotateListResult(
97
+ { achievements: items, nextPageToken: result.nextPageToken },
98
+ "achievements",
99
+ "No achievement configurations found"
100
+ ),
101
+ format
102
+ )
103
+ );
104
+ }
105
+ });
106
+ achievements.command("get <achievement-id>").description("Get an achievement configuration").action(async (achievementId) => {
107
+ const config = await loadConfig();
108
+ const client = await getGamesConfigClientFromConfig(config);
109
+ const format = getOutputFormat(program, config);
110
+ const result = await getAchievementConfig(client, achievementId);
111
+ console.log(formatOutput(result, format));
112
+ });
113
+ achievements.command("create").description("Create an achievement from a JSON file").requiredOption("--file <path>", "JSON file with achievement data").action(async (options) => {
114
+ const config = await loadConfig();
115
+ const gameId = resolveGameId(games.opts()["gameId"], config);
116
+ const format = getOutputFormat(program, config);
117
+ if (isDryRun(program)) {
118
+ printDryRun(
119
+ {
120
+ command: "games achievements create",
121
+ action: "create",
122
+ target: `achievement from ${options.file}`
123
+ },
124
+ format,
125
+ formatOutput
126
+ );
127
+ return;
128
+ }
129
+ const client = await getGamesConfigClientFromConfig(config);
130
+ const data = await readJsonFile(options.file);
131
+ const result = await createAchievementConfig(
132
+ client,
133
+ gameId,
134
+ data
135
+ );
136
+ console.log(formatOutput(result, format));
137
+ });
138
+ achievements.command("update <achievement-id>").description("Update an achievement from a JSON file").requiredOption("--file <path>", "JSON file with achievement data").action(async (achievementId, options) => {
139
+ const config = await loadConfig();
140
+ const format = getOutputFormat(program, config);
141
+ if (isDryRun(program)) {
142
+ printDryRun(
143
+ {
144
+ command: "games achievements update",
145
+ action: "update",
146
+ target: achievementId,
147
+ details: { file: options.file }
148
+ },
149
+ format,
150
+ formatOutput
151
+ );
152
+ return;
153
+ }
154
+ const client = await getGamesConfigClientFromConfig(config);
155
+ const data = await readJsonFile(options.file);
156
+ const result = await updateAchievementConfig(
157
+ client,
158
+ achievementId,
159
+ data
160
+ );
161
+ console.log(formatOutput(result, format));
162
+ });
163
+ achievements.command("delete <achievement-id>").description("Delete an achievement").action(async (achievementId) => {
164
+ const config = await loadConfig();
165
+ if (isDryRun(program)) {
166
+ const format = getOutputFormat(program, config);
167
+ printDryRun(
168
+ {
169
+ command: "games achievements delete",
170
+ action: "delete",
171
+ target: achievementId
172
+ },
173
+ format,
174
+ formatOutput
175
+ );
176
+ return;
177
+ }
178
+ await requireConfirm(
179
+ `Delete achievement "${achievementId}"? This cannot be undone.`,
180
+ program
181
+ );
182
+ const client = await getGamesConfigClientFromConfig(config);
183
+ await deleteAchievementConfig(client, achievementId);
184
+ console.log(`Achievement ${achievementId} deleted.`);
185
+ });
186
+ achievements.command("diff <achievement-id>").description("Compare local JSON against remote achievement configuration").requiredOption("--file <path>", "JSON file with local achievement data").action(async (achievementId, options) => {
187
+ const config = await loadConfig();
188
+ const client = await getGamesConfigClientFromConfig(config);
189
+ const format = getOutputFormat(program, config);
190
+ const localData = await readJsonFile(options.file);
191
+ const diffs = await diffAchievementConfig(
192
+ client,
193
+ achievementId,
194
+ localData
195
+ );
196
+ if (diffs.length === 0) {
197
+ console.log("No differences found.");
198
+ } else {
199
+ console.log(formatOutput(diffs, format));
200
+ }
201
+ });
202
+ const leaderboards = games.command("leaderboards").description("Manage leaderboard configurations");
203
+ leaderboards.command("list").description("List leaderboard configurations").option("--limit <n>", "Maximum results per page", parseInt).option("--next-page <token>", "Resume from page token").action(async (options) => {
204
+ const config = await loadConfig();
205
+ const gameId = resolveGameId(games.opts()["gameId"], config);
206
+ const client = await getGamesConfigClientFromConfig(config);
207
+ const format = getOutputFormat(program, config);
208
+ const result = await listLeaderboardConfigs(client, gameId, {
209
+ maxResults: options.limit,
210
+ pageToken: options.nextPage
211
+ });
212
+ const items = result.items ?? [];
213
+ if (format !== "json") {
214
+ if (items.length === 0) {
215
+ console.log("No leaderboard configurations found.");
216
+ } else {
217
+ console.log(formatOutput(items, format));
218
+ const footer = moreResultsFooter(result.nextPageToken);
219
+ if (footer) console.log(footer);
220
+ }
221
+ } else {
222
+ console.log(
223
+ formatOutput(
224
+ annotateListResult(
225
+ { leaderboards: items, nextPageToken: result.nextPageToken },
226
+ "leaderboards",
227
+ "No leaderboard configurations found"
228
+ ),
229
+ format
230
+ )
231
+ );
232
+ }
233
+ });
234
+ leaderboards.command("get <leaderboard-id>").description("Get a leaderboard configuration").action(async (leaderboardId) => {
235
+ const config = await loadConfig();
236
+ const client = await getGamesConfigClientFromConfig(config);
237
+ const format = getOutputFormat(program, config);
238
+ const result = await getLeaderboardConfig(client, leaderboardId);
239
+ console.log(formatOutput(result, format));
240
+ });
241
+ leaderboards.command("create").description("Create a leaderboard from a JSON file").requiredOption("--file <path>", "JSON file with leaderboard data").action(async (options) => {
242
+ const config = await loadConfig();
243
+ const gameId = resolveGameId(games.opts()["gameId"], config);
244
+ const format = getOutputFormat(program, config);
245
+ if (isDryRun(program)) {
246
+ printDryRun(
247
+ {
248
+ command: "games leaderboards create",
249
+ action: "create",
250
+ target: `leaderboard from ${options.file}`
251
+ },
252
+ format,
253
+ formatOutput
254
+ );
255
+ return;
256
+ }
257
+ const client = await getGamesConfigClientFromConfig(config);
258
+ const data = await readJsonFile(options.file);
259
+ const result = await createLeaderboardConfig(
260
+ client,
261
+ gameId,
262
+ data
263
+ );
264
+ console.log(formatOutput(result, format));
265
+ });
266
+ leaderboards.command("update <leaderboard-id>").description("Update a leaderboard from a JSON file").requiredOption("--file <path>", "JSON file with leaderboard data").action(async (leaderboardId, options) => {
267
+ const config = await loadConfig();
268
+ const format = getOutputFormat(program, config);
269
+ if (isDryRun(program)) {
270
+ printDryRun(
271
+ {
272
+ command: "games leaderboards update",
273
+ action: "update",
274
+ target: leaderboardId,
275
+ details: { file: options.file }
276
+ },
277
+ format,
278
+ formatOutput
279
+ );
280
+ return;
281
+ }
282
+ const client = await getGamesConfigClientFromConfig(config);
283
+ const data = await readJsonFile(options.file);
284
+ const result = await updateLeaderboardConfig(
285
+ client,
286
+ leaderboardId,
287
+ data
288
+ );
289
+ console.log(formatOutput(result, format));
290
+ });
291
+ leaderboards.command("delete <leaderboard-id>").description("Delete a leaderboard").action(async (leaderboardId) => {
292
+ const config = await loadConfig();
293
+ if (isDryRun(program)) {
294
+ const format = getOutputFormat(program, config);
295
+ printDryRun(
296
+ {
297
+ command: "games leaderboards delete",
298
+ action: "delete",
299
+ target: leaderboardId
300
+ },
301
+ format,
302
+ formatOutput
303
+ );
304
+ return;
305
+ }
306
+ await requireConfirm(
307
+ `Delete leaderboard "${leaderboardId}"? This cannot be undone.`,
308
+ program
309
+ );
310
+ const client = await getGamesConfigClientFromConfig(config);
311
+ await deleteLeaderboardConfig(client, leaderboardId);
312
+ console.log(`Leaderboard ${leaderboardId} deleted.`);
313
+ });
314
+ leaderboards.command("diff <leaderboard-id>").description(
315
+ "Compare local JSON against remote leaderboard configuration"
316
+ ).requiredOption("--file <path>", "JSON file with local leaderboard data").action(async (leaderboardId, options) => {
317
+ const config = await loadConfig();
318
+ const client = await getGamesConfigClientFromConfig(config);
319
+ const format = getOutputFormat(program, config);
320
+ const localData = await readJsonFile(options.file);
321
+ const diffs = await diffLeaderboardConfig(
322
+ client,
323
+ leaderboardId,
324
+ localData
325
+ );
326
+ if (diffs.length === 0) {
327
+ console.log("No differences found.");
328
+ } else {
329
+ console.log(formatOutput(diffs, format));
330
+ }
331
+ });
332
+ const runtime = games.command("runtime").description("Inspect runtime player data (Games v1 API, read-only)");
333
+ runtime.command("leaderboards").description("List runtime leaderboard data").action(async () => {
334
+ const config = await loadConfig();
335
+ const packageName = resolvePackageName(program.opts()["app"], config);
336
+ const client = await getGamesClient(config);
337
+ const format = getOutputFormat(program, config);
338
+ const result = await listLeaderboards(client, packageName);
339
+ if (result.length === 0 && format !== "json") {
340
+ console.log("No leaderboards found.");
341
+ return;
342
+ }
343
+ console.log(formatOutput(result, format));
344
+ });
345
+ runtime.command("achievements").description("List runtime achievement data").action(async () => {
346
+ const config = await loadConfig();
347
+ const packageName = resolvePackageName(program.opts()["app"], config);
348
+ const client = await getGamesClient(config);
349
+ const format = getOutputFormat(program, config);
350
+ const result = await listAchievements(client, packageName);
351
+ if (result.length === 0 && format !== "json") {
352
+ console.log("No achievements found.");
353
+ return;
354
+ }
355
+ console.log(formatOutput(result, format));
356
+ });
357
+ }
358
+ export {
359
+ registerGamesCommands
360
+ };
361
+ //# sourceMappingURL=games-7K5RKXCO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/games.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport type { ResolvedConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport {\n createGamesClient,\n createGamesConfigClient,\n type AchievementConfiguration,\n type LeaderboardConfiguration,\n} from \"@gpc-cli/api\";\nimport {\n listLeaderboards,\n listAchievements,\n listAchievementConfigs,\n getAchievementConfig,\n createAchievementConfig,\n updateAchievementConfig,\n deleteAchievementConfig,\n diffAchievementConfig,\n listLeaderboardConfigs,\n getLeaderboardConfig,\n createLeaderboardConfig,\n updateLeaderboardConfig,\n deleteLeaderboardConfig,\n diffLeaderboardConfig,\n formatOutput,\n annotateListResult,\n moreResultsFooter,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { resolvePackageName } from \"../resolve.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.js\";\n\nfunction resolveGameId(\n flag: string | undefined,\n config: ResolvedConfig,\n): string {\n const gameId =\n flag ?? process.env[\"GPC_GAME_ID\"] ?? config.games?.applicationId;\n if (!gameId) {\n throw new GpcError(\n \"Game application ID is required. Pass --game-id, set GPC_GAME_ID, or add games.applicationId to .gpcrc.json.\",\n \"GAMES_NO_APPLICATION_ID\",\n 2,\n \"Find your numeric application ID in Play Console > Play Games Services > Setup.\",\n );\n }\n return gameId;\n}\n\nasync function getGamesClient(config: { auth?: { serviceAccount?: string } }) {\n const auth = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n return createGamesClient({ auth });\n}\n\nasync function getGamesConfigClientFromConfig(config: {\n auth?: { serviceAccount?: string };\n}) {\n const auth = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n return createGamesConfigClient({ auth });\n}\n\nexport function registerGamesCommands(program: Command): void {\n const games = program\n .command(\"games\")\n .description(\n \"Manage Play Games Services — achievements, leaderboards (configuration API)\",\n )\n .option(\"--game-id <id>\", \"Games application ID (numeric)\");\n\n /* ---------------------------------------------------------------- */\n /* Achievements */\n /* ---------------------------------------------------------------- */\n\n const achievements = games\n .command(\"achievements\")\n .description(\"Manage achievement configurations\");\n\n achievements\n .command(\"list\")\n .description(\"List achievement configurations\")\n .option(\"--limit <n>\", \"Maximum results per page\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .action(async (options) => {\n const config = await loadConfig();\n const gameId = resolveGameId(games.opts()[\"gameId\"], config);\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const result = await listAchievementConfigs(client, gameId, {\n maxResults: options.limit,\n pageToken: options.nextPage,\n });\n const items = result.items ?? [];\n if (format !== \"json\") {\n if (items.length === 0) {\n console.log(\"No achievement configurations found.\");\n } else {\n console.log(formatOutput(items, format));\n const footer = moreResultsFooter(result.nextPageToken);\n if (footer) console.log(footer);\n }\n } else {\n console.log(\n formatOutput(\n annotateListResult(\n { achievements: items, nextPageToken: result.nextPageToken },\n \"achievements\",\n \"No achievement configurations found\",\n ),\n format,\n ),\n );\n }\n });\n\n achievements\n .command(\"get <achievement-id>\")\n .description(\"Get an achievement configuration\")\n .action(async (achievementId: string) => {\n const config = await loadConfig();\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const result = await getAchievementConfig(client, achievementId);\n console.log(formatOutput(result, format));\n });\n\n achievements\n .command(\"create\")\n .description(\"Create an achievement from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with achievement data\")\n .action(async (options) => {\n const config = await loadConfig();\n const gameId = resolveGameId(games.opts()[\"gameId\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"games achievements create\",\n action: \"create\",\n target: `achievement from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getGamesConfigClientFromConfig(config);\n const data = await readJsonFile(options.file);\n const result = await createAchievementConfig(\n client,\n gameId,\n data as AchievementConfiguration,\n );\n console.log(formatOutput(result, format));\n });\n\n achievements\n .command(\"update <achievement-id>\")\n .description(\"Update an achievement from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with achievement data\")\n .action(async (achievementId: string, options) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"games achievements update\",\n action: \"update\",\n target: achievementId,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getGamesConfigClientFromConfig(config);\n const data = await readJsonFile(options.file);\n const result = await updateAchievementConfig(\n client,\n achievementId,\n data as AchievementConfiguration,\n );\n console.log(formatOutput(result, format));\n });\n\n achievements\n .command(\"delete <achievement-id>\")\n .description(\"Delete an achievement\")\n .action(async (achievementId: string) => {\n const config = await loadConfig();\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"games achievements delete\",\n action: \"delete\",\n target: achievementId,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Delete achievement \"${achievementId}\"? This cannot be undone.`,\n program,\n );\n\n const client = await getGamesConfigClientFromConfig(config);\n await deleteAchievementConfig(client, achievementId);\n console.log(`Achievement ${achievementId} deleted.`);\n });\n\n achievements\n .command(\"diff <achievement-id>\")\n .description(\"Compare local JSON against remote achievement configuration\")\n .requiredOption(\"--file <path>\", \"JSON file with local achievement data\")\n .action(async (achievementId: string, options) => {\n const config = await loadConfig();\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const localData = await readJsonFile(options.file);\n const diffs = await diffAchievementConfig(\n client,\n achievementId,\n localData as AchievementConfiguration,\n );\n if (diffs.length === 0) {\n console.log(\"No differences found.\");\n } else {\n console.log(formatOutput(diffs, format));\n }\n });\n\n /* ---------------------------------------------------------------- */\n /* Leaderboards */\n /* ---------------------------------------------------------------- */\n\n const leaderboards = games\n .command(\"leaderboards\")\n .description(\"Manage leaderboard configurations\");\n\n leaderboards\n .command(\"list\")\n .description(\"List leaderboard configurations\")\n .option(\"--limit <n>\", \"Maximum results per page\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .action(async (options) => {\n const config = await loadConfig();\n const gameId = resolveGameId(games.opts()[\"gameId\"], config);\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const result = await listLeaderboardConfigs(client, gameId, {\n maxResults: options.limit,\n pageToken: options.nextPage,\n });\n const items = result.items ?? [];\n if (format !== \"json\") {\n if (items.length === 0) {\n console.log(\"No leaderboard configurations found.\");\n } else {\n console.log(formatOutput(items, format));\n const footer = moreResultsFooter(result.nextPageToken);\n if (footer) console.log(footer);\n }\n } else {\n console.log(\n formatOutput(\n annotateListResult(\n { leaderboards: items, nextPageToken: result.nextPageToken },\n \"leaderboards\",\n \"No leaderboard configurations found\",\n ),\n format,\n ),\n );\n }\n });\n\n leaderboards\n .command(\"get <leaderboard-id>\")\n .description(\"Get a leaderboard configuration\")\n .action(async (leaderboardId: string) => {\n const config = await loadConfig();\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const result = await getLeaderboardConfig(client, leaderboardId);\n console.log(formatOutput(result, format));\n });\n\n leaderboards\n .command(\"create\")\n .description(\"Create a leaderboard from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with leaderboard data\")\n .action(async (options) => {\n const config = await loadConfig();\n const gameId = resolveGameId(games.opts()[\"gameId\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"games leaderboards create\",\n action: \"create\",\n target: `leaderboard from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getGamesConfigClientFromConfig(config);\n const data = await readJsonFile(options.file);\n const result = await createLeaderboardConfig(\n client,\n gameId,\n data as LeaderboardConfiguration,\n );\n console.log(formatOutput(result, format));\n });\n\n leaderboards\n .command(\"update <leaderboard-id>\")\n .description(\"Update a leaderboard from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with leaderboard data\")\n .action(async (leaderboardId: string, options) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"games leaderboards update\",\n action: \"update\",\n target: leaderboardId,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getGamesConfigClientFromConfig(config);\n const data = await readJsonFile(options.file);\n const result = await updateLeaderboardConfig(\n client,\n leaderboardId,\n data as LeaderboardConfiguration,\n );\n console.log(formatOutput(result, format));\n });\n\n leaderboards\n .command(\"delete <leaderboard-id>\")\n .description(\"Delete a leaderboard\")\n .action(async (leaderboardId: string) => {\n const config = await loadConfig();\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"games leaderboards delete\",\n action: \"delete\",\n target: leaderboardId,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await requireConfirm(\n `Delete leaderboard \"${leaderboardId}\"? This cannot be undone.`,\n program,\n );\n\n const client = await getGamesConfigClientFromConfig(config);\n await deleteLeaderboardConfig(client, leaderboardId);\n console.log(`Leaderboard ${leaderboardId} deleted.`);\n });\n\n leaderboards\n .command(\"diff <leaderboard-id>\")\n .description(\n \"Compare local JSON against remote leaderboard configuration\",\n )\n .requiredOption(\"--file <path>\", \"JSON file with local leaderboard data\")\n .action(async (leaderboardId: string, options) => {\n const config = await loadConfig();\n const client = await getGamesConfigClientFromConfig(config);\n const format = getOutputFormat(program, config);\n\n const localData = await readJsonFile(options.file);\n const diffs = await diffLeaderboardConfig(\n client,\n leaderboardId,\n localData as LeaderboardConfiguration,\n );\n if (diffs.length === 0) {\n console.log(\"No differences found.\");\n } else {\n console.log(formatOutput(diffs, format));\n }\n });\n\n /* ---------------------------------------------------------------- */\n /* Runtime (Games v1) — read-only inspection */\n /* ---------------------------------------------------------------- */\n\n const runtime = games\n .command(\"runtime\")\n .description(\"Inspect runtime player data (Games v1 API, read-only)\");\n\n runtime\n .command(\"leaderboards\")\n .description(\"List runtime leaderboard data\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getGamesClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listLeaderboards(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No leaderboards found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n runtime\n .command(\"achievements\")\n .description(\"List runtime achievement data\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getGamesClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listAchievements(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No achievements found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":"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","names":[]}