@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.
- package/README.md +2 -2
- package/dist/bin.js +2 -2
- package/dist/{chunk-IAPAEPDL.js → chunk-E2NRW3TQ.js} +11 -11
- package/dist/{config-XOJX2NCA.js → config-7SLPBJI3.js} +2 -2
- package/dist/{doctor-PFLPGPM3.js → doctor-3MJZSIGX.js} +2 -2
- package/dist/{feedback-FF3CBERM.js → feedback-TXDXWK7N.js} +2 -2
- package/dist/games-7K5RKXCO.js +361 -0
- package/dist/games-7K5RKXCO.js.map +1 -0
- package/dist/generated/docs-bundle.json +1 -1
- package/dist/{grants-Q3FWJYGR.js → grants-ANDUST7O.js} +13 -9
- package/dist/grants-ANDUST7O.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{testers-YQZ2XHI6.js → testers-OQNP43O6.js} +14 -4
- package/dist/testers-OQNP43O6.js.map +1 -0
- package/dist/{tracks-N7KPBVPC.js → tracks-E7RUNA3C.js} +16 -4
- package/dist/tracks-E7RUNA3C.js.map +1 -0
- package/dist/{update-JGLB2ELN.js → update-UMNA6KMP.js} +2 -2
- package/dist/{version-B4AE5NVE.js → version-PFYWZWJC.js} +2 -2
- package/package.json +5 -5
- package/dist/games-SVFN2YIS.js +0 -60
- package/dist/games-SVFN2YIS.js.map +0 -1
- package/dist/grants-Q3FWJYGR.js.map +0 -1
- package/dist/testers-YQZ2XHI6.js.map +0 -1
- package/dist/tracks-N7KPBVPC.js.map +0 -1
- /package/dist/{chunk-IAPAEPDL.js.map → chunk-E2NRW3TQ.js.map} +0 -0
- /package/dist/{config-XOJX2NCA.js.map → config-7SLPBJI3.js.map} +0 -0
- /package/dist/{doctor-PFLPGPM3.js.map → doctor-3MJZSIGX.js.map} +0 -0
- /package/dist/{feedback-FF3CBERM.js.map → feedback-TXDXWK7N.js.map} +0 -0
- /package/dist/{update-JGLB2ELN.js.map → update-UMNA6KMP.js.map} +0 -0
- /package/dist/{version-B4AE5NVE.js.map → version-PFYWZWJC.js.map} +0 -0
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
updateGrant,
|
|
21
21
|
deleteGrant,
|
|
22
22
|
formatOutput,
|
|
23
|
+
annotateListResult,
|
|
23
24
|
GpcError
|
|
24
25
|
} from "@gpc-cli/core";
|
|
25
26
|
function resolveDeveloperId(devIdArg, config) {
|
|
@@ -46,15 +47,18 @@ function registerGrantsCommands(program) {
|
|
|
46
47
|
const client = await getClient(config);
|
|
47
48
|
const format = getOutputFormat(program, config);
|
|
48
49
|
const result = await listGrants(client, developerId, email);
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
if (format === "json") {
|
|
51
|
+
console.log(
|
|
52
|
+
formatOutput(
|
|
53
|
+
annotateListResult({ grants: result }, "grants", `No grants found for ${email}.`),
|
|
54
|
+
format
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
} else if (result.length === 0) {
|
|
58
|
+
console.log(`No grants found for ${email}.`);
|
|
59
|
+
} else {
|
|
60
|
+
console.log(formatOutput(result, format));
|
|
56
61
|
}
|
|
57
|
-
console.log(formatOutput(result, format));
|
|
58
62
|
});
|
|
59
63
|
grants.command("create <email>").description("Grant app-level permissions to a user").requiredOption("--package <packageName>", "App package name").requiredOption(
|
|
60
64
|
"--permissions <list>",
|
|
@@ -128,4 +132,4 @@ function registerGrantsCommands(program) {
|
|
|
128
132
|
export {
|
|
129
133
|
registerGrantsCommands
|
|
130
134
|
};
|
|
131
|
-
//# sourceMappingURL=grants-
|
|
135
|
+
//# sourceMappingURL=grants-ANDUST7O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/grants.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createUsersClient } from \"@gpc-cli/api\";\nimport {\n listGrants,\n createGrant,\n updateGrant,\n deleteGrant,\n formatOutput,\n annotateListResult,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nfunction resolveDeveloperId(devIdArg: string | undefined, config: GpcConfig): string {\n const id = devIdArg || config.developerId;\n if (!id) {\n throw new GpcError(\n \"No developer ID. Use --developer-id <id> or gpc config set developerId <id>\",\n \"MISSING_DEVELOPER_ID\",\n 2,\n \"gpc config set developerId <id>\",\n );\n }\n return id;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createUsersClient({ auth });\n}\n\nexport function registerGrantsCommands(program: Command): void {\n const grants = program\n .command(\"grants\")\n .description(\"Manage per-app permission grants for developer account users\")\n .option(\"--developer-id <id>\", \"Developer account ID\");\n\n grants\n .command(\"list <email>\")\n .description(\"List all per-app grants for a user\")\n .action(async (email: string) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listGrants(client, developerId, email);\n if (format === \"json\") {\n console.log(\n formatOutput(\n annotateListResult({ grants: result }, \"grants\", `No grants found for ${email}.`),\n format,\n ),\n );\n } else if (result.length === 0) {\n console.log(`No grants found for ${email}.`);\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n grants\n .command(\"create <email>\")\n .description(\"Grant app-level permissions to a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\n \"--permissions <list>\",\n \"Comma-separated permissions (e.g. CAN_MANAGE_RELEASES,VIEW_APP_INFORMATION)\",\n )\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants create\",\n action: \"grant permissions\",\n target: `${email}/${options.package}`,\n details: { permissions: perms },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await createGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n });\n\n grants\n .command(\"update <email>\")\n .description(\"Update app-level permissions for a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\"--permissions <list>\", \"New comma-separated permissions\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants update\",\n action: \"update permissions\",\n target: `${email}/${options.package}`,\n details: { permissions: perms },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await updateGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n });\n\n grants\n .command(\"delete <email>\")\n .description(\"Remove a per-app grant from a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n\n await requireConfirm(`Remove grant for \"${email}\" on ${options.package}?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants delete\",\n action: \"remove grant\",\n target: `${email}/${options.package}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteGrant(client, developerId, email, options.package);\n console.log(`Grant removed for ${email} on ${options.package}.`);\n });\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,8 @@ import {
|
|
|
26
26
|
addTesters,
|
|
27
27
|
removeTesters,
|
|
28
28
|
importTestersFromCsv,
|
|
29
|
-
formatOutput
|
|
29
|
+
formatOutput,
|
|
30
|
+
annotateListResult
|
|
30
31
|
} from "@gpc-cli/core";
|
|
31
32
|
function registerTestersCommands(program) {
|
|
32
33
|
const testers = program.command("testers").description("Manage testers and tester groups");
|
|
@@ -58,10 +59,19 @@ function registerTestersCommands(program) {
|
|
|
58
59
|
if (rows.length > 0) {
|
|
59
60
|
console.log(formatOutput(rows, format));
|
|
60
61
|
} else {
|
|
61
|
-
console.log(
|
|
62
|
+
console.log(`No tester groups configured for ${options.track}.`);
|
|
62
63
|
}
|
|
63
64
|
} else {
|
|
64
|
-
console.log(
|
|
65
|
+
console.log(
|
|
66
|
+
formatOutput(
|
|
67
|
+
annotateListResult(
|
|
68
|
+
{ ...result, googleGroups: result.googleGroups ?? [] },
|
|
69
|
+
"googleGroups",
|
|
70
|
+
`No tester groups configured for ${options.track}.`
|
|
71
|
+
),
|
|
72
|
+
format
|
|
73
|
+
)
|
|
74
|
+
);
|
|
65
75
|
}
|
|
66
76
|
});
|
|
67
77
|
testers.command("add <emails...>").description("Add testers (Google Group emails) to a track").option("--track <track>", "Track name (e.g., internal, alpha, beta)").option("--changes-not-sent-for-review", "Commit changes without sending for review").option("--error-if-in-review", "Fail if changes are already in review").action(async (emails, options) => {
|
|
@@ -188,4 +198,4 @@ function registerTestersCommands(program) {
|
|
|
188
198
|
export {
|
|
189
199
|
registerTestersCommands
|
|
190
200
|
};
|
|
191
|
-
//# sourceMappingURL=testers-
|
|
201
|
+
//# sourceMappingURL=testers-OQNP43O6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/testers.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport {\n listTesters,\n addTesters,\n removeTesters,\n importTestersFromCsv,\n formatOutput,\n annotateListResult,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\nimport { buildCommitOptions } from \"../commit-options.js\";\n\nexport function registerTestersCommands(program: Command): void {\n const testers = program.command(\"testers\").description(\"Manage testers and tester groups\");\n\n testers\n .command(\"list\")\n .description(\"List testers for a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending, e.g., email or -email)\")\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listTesters(client, packageName, options.track);\n if (options.sort && result.googleGroups) {\n const descending = options.sort.startsWith(\"-\");\n result.googleGroups = [...result.googleGroups].sort((a: string, b: string) =>\n descending ? b.localeCompare(a) : a.localeCompare(b),\n );\n }\n if (format !== \"json\") {\n const groups = (result.googleGroups || []) as string[];\n const rows = groups.map((g: string) => ({ googleGroup: g }));\n if (rows.length > 0) {\n console.log(formatOutput(rows, format));\n } else {\n console.log(`No tester groups configured for ${options.track}.`);\n }\n } else {\n console.log(\n formatOutput(\n annotateListResult(\n { ...result, googleGroups: result.googleGroups ?? [] },\n \"googleGroups\",\n `No tester groups configured for ${options.track}.`,\n ),\n format,\n ),\n );\n }\n });\n\n testers\n .command(\"add <emails...>\")\n .description(\"Add testers (Google Group emails) to a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (emails: string[], options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers add\",\n action: \"add testers to\",\n target: options.track,\n details: { emails },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await addTesters(\n client,\n packageName,\n options.track,\n emails,\n buildCommitOptions(options),\n );\n console.log(formatOutput(result, format));\n });\n\n testers\n .command(\"remove <emails...>\")\n .description(\"Remove testers (Google Group emails) from a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (emails: string[], options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n await requireConfirm(`Remove ${emails.length} tester(s) from ${options.track}?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers remove\",\n action: \"remove testers from\",\n target: options.track,\n details: { emails },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await removeTesters(\n client,\n packageName,\n options.track,\n emails,\n buildCommitOptions(options),\n );\n console.log(formatOutput(result, format));\n });\n\n testers\n .command(\"import\")\n .description(\"Import testers from a CSV file\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--file <path>\", \"CSV file with email addresses\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n options.file = await requireOption(\n \"file\",\n options.file,\n {\n message: \"CSV file path:\",\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers import\",\n action: \"import testers to\",\n target: options.track,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await importTestersFromCsv(\n client,\n packageName,\n options.track,\n options.file,\n buildCommitOptions(options),\n );\n console.log(formatOutput({ added: result.added, testers: result.testers }, format));\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -16,10 +16,13 @@ import { loadConfig } from "@gpc-cli/config";
|
|
|
16
16
|
import { resolveAuth } from "@gpc-cli/auth";
|
|
17
17
|
import { createApiClient } from "@gpc-cli/api";
|
|
18
18
|
import { listTracks, createTrack, updateTrackConfig, GpcError } from "@gpc-cli/core";
|
|
19
|
-
import { formatOutput, maybePaginate } from "@gpc-cli/core";
|
|
19
|
+
import { formatOutput, maybePaginate, annotateListResult } from "@gpc-cli/core";
|
|
20
20
|
function registerTracksCommands(program) {
|
|
21
21
|
const tracks = program.command("tracks").description("Manage tracks");
|
|
22
|
-
tracks.command("list").description("List all tracks").option("--limit <n>", "
|
|
22
|
+
tracks.command("list").description("List all tracks").option("--limit <n>", "Accepted for consistency; tracks are returned in full (no pagination)").option(
|
|
23
|
+
"--next-page <token>",
|
|
24
|
+
"Accepted for consistency; tracks are returned in full (no pagination)"
|
|
25
|
+
).action(async (_options) => {
|
|
23
26
|
const config = await loadConfig();
|
|
24
27
|
const packageName = program.opts()["app"] || config.app;
|
|
25
28
|
if (!packageName) {
|
|
@@ -40,7 +43,16 @@ function registerTracksCommands(program) {
|
|
|
40
43
|
latestStatus: t.releases?.[0]?.status || "none",
|
|
41
44
|
latestVersion: t.releases?.[0]?.versionCodes?.[0] || "-"
|
|
42
45
|
}));
|
|
43
|
-
|
|
46
|
+
if (format === "json") {
|
|
47
|
+
console.log(
|
|
48
|
+
formatOutput(
|
|
49
|
+
annotateListResult({ tracks: summary }, "tracks", "No tracks found."),
|
|
50
|
+
format
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
await maybePaginate(formatOutput(summary, format));
|
|
55
|
+
}
|
|
44
56
|
});
|
|
45
57
|
tracks.command("create <name>").description("Create a custom track").option("--changes-not-sent-for-review", "Commit changes without sending for review").option("--error-if-in-review", "Fail if changes are already in review").action(async (name, options) => {
|
|
46
58
|
const config = await loadConfig();
|
|
@@ -104,4 +116,4 @@ function registerTracksCommands(program) {
|
|
|
104
116
|
export {
|
|
105
117
|
registerTracksCommands
|
|
106
118
|
};
|
|
107
|
-
//# sourceMappingURL=tracks-
|
|
119
|
+
//# sourceMappingURL=tracks-E7RUNA3C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/tracks.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport { listTracks, createTrack, updateTrackConfig, GpcError } from \"@gpc-cli/core\";\nimport { formatOutput, maybePaginate, annotateListResult } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { buildCommitOptions } from \"../commit-options.js\";\n\nexport function registerTracksCommands(program: Command): void {\n const tracks = program.command(\"tracks\").description(\"Manage tracks\");\n\n tracks\n .command(\"list\")\n .description(\"List all tracks\")\n .option(\"--limit <n>\", \"Accepted for consistency; tracks are returned in full (no pagination)\")\n .option(\n \"--next-page <token>\",\n \"Accepted for consistency; tracks are returned in full (no pagination)\",\n )\n .action(async (_options) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const trackList = await listTracks(client, packageName);\n const format = getOutputFormat(program, config);\n\n const summary = trackList.map((t) => ({\n track: t.track,\n releases: t.releases?.length || 0,\n latestStatus: t.releases?.[0]?.status || \"none\",\n latestVersion: t.releases?.[0]?.versionCodes?.[0] || \"-\",\n }));\n\n if (format === \"json\") {\n console.log(\n formatOutput(\n annotateListResult({ tracks: summary }, \"tracks\", \"No tracks found.\"),\n format,\n ),\n );\n } else {\n await maybePaginate(formatOutput(summary, format));\n }\n });\n\n tracks\n .command(\"create <name>\")\n .description(\"Create a custom track\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (name: string, options: Record<string, unknown>) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"tracks create\", action: \"create custom track\", target: name },\n format,\n formatOutput,\n );\n return;\n }\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const track = await createTrack(client, packageName, name, buildCommitOptions(options));\n console.log(formatOutput(track, format));\n });\n\n tracks\n .command(\"update <name>\")\n .description(\"Update track configuration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to JSON config file\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (name: string, options: { file: string } & Record<string, unknown>) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"tracks update\", action: \"update track config from\", target: options.file },\n format,\n formatOutput,\n );\n return;\n }\n\n const raw = await readFile(options.file, \"utf-8\");\n const trackConfig = JSON.parse(raw) as Record<string, unknown>;\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const track = await updateTrackConfig(\n client,\n packageName,\n name,\n trackConfig,\n buildCommitOptions(options),\n );\n console.log(formatOutput(track, format));\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AAEzB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC,SAAS,YAAY,aAAa,mBAAmB,gBAAgB;AACrE,SAAS,cAAc,eAAe,0BAA0B;AAKzD,SAAS,uBAAuB,SAAwB;AAC7D,QAAM,SAAS,QAAQ,QAAQ,QAAQ,EAAE,YAAY,eAAe;AAEpE,SACG,QAAQ,MAAM,EACd,YAAY,iBAAiB,EAC7B,OAAO,eAAe,uEAAuE,EAC7F;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,OAAO,aAAa;AAC1B,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,QAAQ,KAAK,EAAE,KAAK,KAAK,OAAO;AACpD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,UAAM,SAAS,gBAAgB,EAAE,KAAK,CAAC;AACvC,UAAM,YAAY,MAAM,WAAW,QAAQ,WAAW;AACtD,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,UAAU,UAAU,IAAI,CAAC,OAAO;AAAA,MACpC,OAAO,EAAE;AAAA,MACT,UAAU,EAAE,UAAU,UAAU;AAAA,MAChC,cAAc,EAAE,WAAW,CAAC,GAAG,UAAU;AAAA,MACzC,eAAe,EAAE,WAAW,CAAC,GAAG,eAAe,CAAC,KAAK;AAAA,IACvD,EAAE;AAEF,QAAI,WAAW,QAAQ;AACrB,cAAQ;AAAA,QACN;AAAA,UACE,mBAAmB,EAAE,QAAQ,QAAQ,GAAG,UAAU,kBAAkB;AAAA,UACpE;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,cAAc,aAAa,SAAS,MAAM,CAAC;AAAA,IACnD;AAAA,EACF,CAAC;AAEH,SACG,QAAQ,eAAe,EACvB,YAAY,uBAAuB,EACnC,OAAO,iCAAiC,2CAA2C,EACnF,OAAO,wBAAwB,uCAAuC,EACtE,OAAO,OAAO,MAAc,YAAqC;AAChE,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,QAAQ,KAAK,EAAE,KAAK,KAAK,OAAO;AACpD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE,EAAE,SAAS,iBAAiB,QAAQ,uBAAuB,QAAQ,KAAK;AAAA,QACxE;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,UAAM,SAAS,gBAAgB,EAAE,KAAK,CAAC;AACvC,UAAM,QAAQ,MAAM,YAAY,QAAQ,aAAa,MAAM,mBAAmB,OAAO,CAAC;AACtF,YAAQ,IAAI,aAAa,OAAO,MAAM,CAAC;AAAA,EACzC,CAAC;AAEH,SACG,QAAQ,eAAe,EACvB,YAAY,6CAA6C,EACzD,eAAe,iBAAiB,0BAA0B,EAC1D,OAAO,iCAAiC,2CAA2C,EACnF,OAAO,wBAAwB,uCAAuC,EACtE,OAAO,OAAO,MAAc,YAAwD;AACnF,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,QAAQ,KAAK,EAAE,KAAK,KAAK,OAAO;AACpD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE,EAAE,SAAS,iBAAiB,QAAQ,4BAA4B,QAAQ,QAAQ,KAAK;AAAA,QACrF;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,SAAS,QAAQ,MAAM,OAAO;AAChD,UAAM,cAAc,KAAK,MAAM,GAAG;AAElC,UAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,UAAM,SAAS,gBAAgB,EAAE,KAAK,CAAC;AACvC,UAAM,QAAQ,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,OAAO;AAAA,IAC5B;AACA,YAAQ,IAAI,aAAa,OAAO,MAAM,CAAC;AAAA,EACzC,CAAC;AACL;","names":[]}
|
|
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
|
|
|
17
17
|
program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
|
|
18
18
|
const parentOpts = cmd.parent?.opts() ?? {};
|
|
19
19
|
const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
|
|
20
|
-
const currentVersion = "0.9.
|
|
20
|
+
const currentVersion = "0.9.87";
|
|
21
21
|
if (currentVersion === "0.0.0") {
|
|
22
22
|
if (jsonMode) {
|
|
23
23
|
console.log(
|
|
@@ -172,4 +172,4 @@ Run: gpc update`);
|
|
|
172
172
|
export {
|
|
173
173
|
registerUpdateCommand
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=update-
|
|
175
|
+
//# sourceMappingURL=update-UMNA6KMP.js.map
|
|
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
|
|
|
7
7
|
// src/commands/version.ts
|
|
8
8
|
function registerVersionCommand(program) {
|
|
9
9
|
program.command("version").description("Show version information").action(() => {
|
|
10
|
-
const version = "0.9.
|
|
10
|
+
const version = "0.9.87";
|
|
11
11
|
if (program.opts()["output"] === "json") {
|
|
12
12
|
console.log(
|
|
13
13
|
JSON.stringify({
|
|
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
|
|
|
25
25
|
export {
|
|
26
26
|
registerVersionCommand
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=version-
|
|
28
|
+
//# sourceMappingURL=version-PFYWZWJC.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpc-cli/cli",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "GPC — Google Play Console CLI.
|
|
3
|
+
"version": "0.9.87",
|
|
4
|
+
"description": "GPC — Google Play Console CLI. 227 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"gpc": "./dist/bin.js"
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"clean": "rm -rf dist"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@gpc-cli/api": "1.0.
|
|
32
|
+
"@gpc-cli/api": "1.0.45",
|
|
33
33
|
"@gpc-cli/auth": "0.9.16",
|
|
34
|
-
"@gpc-cli/config": "0.9.
|
|
35
|
-
"@gpc-cli/core": "0.9.
|
|
34
|
+
"@gpc-cli/config": "0.9.19",
|
|
35
|
+
"@gpc-cli/core": "0.9.72",
|
|
36
36
|
"@gpc-cli/plugin-sdk": "0.9.10",
|
|
37
37
|
"commander": "^14.0.3"
|
|
38
38
|
},
|
package/dist/games-SVFN2YIS.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
resolvePackageName
|
|
4
|
-
} from "./chunk-JDRY7HK5.js";
|
|
5
|
-
import {
|
|
6
|
-
getOutputFormat
|
|
7
|
-
} from "./chunk-ELXAK7GI.js";
|
|
8
|
-
|
|
9
|
-
// src/commands/games.ts
|
|
10
|
-
import { loadConfig } from "@gpc-cli/config";
|
|
11
|
-
import { resolveAuth } from "@gpc-cli/auth";
|
|
12
|
-
import { createGamesClient } from "@gpc-cli/api";
|
|
13
|
-
import { listLeaderboards, listAchievements, listEvents, formatOutput } from "@gpc-cli/core";
|
|
14
|
-
async function getGamesClient(config) {
|
|
15
|
-
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
16
|
-
return createGamesClient({ auth });
|
|
17
|
-
}
|
|
18
|
-
function registerGamesCommands(program) {
|
|
19
|
-
const games = program.command("games").description("Manage Play Games Services \u2014 leaderboards, achievements, events");
|
|
20
|
-
games.command("leaderboards").description("List leaderboards for the app").action(async () => {
|
|
21
|
-
const config = await loadConfig();
|
|
22
|
-
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
23
|
-
const client = await getGamesClient(config);
|
|
24
|
-
const format = getOutputFormat(program, config);
|
|
25
|
-
const result = await listLeaderboards(client, packageName);
|
|
26
|
-
if (result.length === 0 && format !== "json") {
|
|
27
|
-
console.log("No leaderboards found.");
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
console.log(formatOutput(result, format));
|
|
31
|
-
});
|
|
32
|
-
games.command("achievements").description("List achievements for the app").action(async () => {
|
|
33
|
-
const config = await loadConfig();
|
|
34
|
-
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
35
|
-
const client = await getGamesClient(config);
|
|
36
|
-
const format = getOutputFormat(program, config);
|
|
37
|
-
const result = await listAchievements(client, packageName);
|
|
38
|
-
if (result.length === 0 && format !== "json") {
|
|
39
|
-
console.log("No achievements found.");
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
console.log(formatOutput(result, format));
|
|
43
|
-
});
|
|
44
|
-
games.command("events").description("List events for the app").action(async () => {
|
|
45
|
-
const config = await loadConfig();
|
|
46
|
-
const packageName = resolvePackageName(program.opts()["app"], config);
|
|
47
|
-
const client = await getGamesClient(config);
|
|
48
|
-
const format = getOutputFormat(program, config);
|
|
49
|
-
const result = await listEvents(client, packageName);
|
|
50
|
-
if (result.length === 0 && format !== "json") {
|
|
51
|
-
console.log("No events found.");
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
console.log(formatOutput(result, format));
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
export {
|
|
58
|
-
registerGamesCommands
|
|
59
|
-
};
|
|
60
|
-
//# sourceMappingURL=games-SVFN2YIS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/games.ts"],"sourcesContent":["import { resolvePackageName } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createGamesClient } from \"@gpc-cli/api\";\nimport { listLeaderboards, listAchievements, listEvents, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nasync function getGamesClient(config: { auth?: { serviceAccount?: string } }) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createGamesClient({ auth });\n}\n\nexport function registerGamesCommands(program: Command): void {\n const games = program\n .command(\"games\")\n .description(\"Manage Play Games Services — leaderboards, achievements, events\");\n\n games\n .command(\"leaderboards\")\n .description(\"List leaderboards for the app\")\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 games\n .command(\"achievements\")\n .description(\"List achievements for the app\")\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 games\n .command(\"events\")\n .description(\"List events for the app\")\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 listEvents(client, packageName);\n if (result.length === 0 && format !== \"json\") {\n console.log(\"No events found.\");\n return;\n }\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kBAAkB,kBAAkB,YAAY,oBAAoB;AAG7E,eAAe,eAAe,QAAgD;AAC5E,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,kBAAkB,EAAE,KAAK,CAAC;AACnC;AAEO,SAAS,sBAAsB,SAAwB;AAC5D,QAAM,QAAQ,QACX,QAAQ,OAAO,EACf,YAAY,sEAAiE;AAEhF,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,wBAAwB;AACpC;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,QACG,QAAQ,cAAc,EACtB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,iBAAiB,QAAQ,WAAW;AACzD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,wBAAwB;AACpC;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,eAAe,MAAM;AAC1C,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,WAAW,QAAQ,WAAW;AACnD,QAAI,OAAO,WAAW,KAAK,WAAW,QAAQ;AAC5C,cAAQ,IAAI,kBAAkB;AAC9B;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/grants.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createUsersClient } from \"@gpc-cli/api\";\nimport {\n listGrants,\n createGrant,\n updateGrant,\n deleteGrant,\n formatOutput,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nfunction resolveDeveloperId(devIdArg: string | undefined, config: GpcConfig): string {\n const id = devIdArg || config.developerId;\n if (!id) {\n throw new GpcError(\n \"No developer ID. Use --developer-id <id> or gpc config set developerId <id>\",\n \"MISSING_DEVELOPER_ID\",\n 2,\n \"gpc config set developerId <id>\",\n );\n }\n return id;\n}\n\nasync function getClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createUsersClient({ auth });\n}\n\nexport function registerGrantsCommands(program: Command): void {\n const grants = program\n .command(\"grants\")\n .description(\"Manage per-app permission grants for developer account users\")\n .option(\"--developer-id <id>\", \"Developer account ID\");\n\n grants\n .command(\"list <email>\")\n .description(\"List all per-app grants for a user\")\n .action(async (email: string) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listGrants(client, developerId, email);\n if (result.length === 0) {\n if (format === \"json\") {\n console.log(formatOutput([], format));\n } else {\n console.log(`No grants found for ${email}.`);\n }\n return;\n }\n console.log(formatOutput(result, format));\n });\n\n grants\n .command(\"create <email>\")\n .description(\"Grant app-level permissions to a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\n \"--permissions <list>\",\n \"Comma-separated permissions (e.g. CAN_MANAGE_RELEASES,VIEW_APP_INFORMATION)\",\n )\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants create\",\n action: \"grant permissions\",\n target: `${email}/${options.package}`,\n details: { permissions: perms },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await createGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n });\n\n grants\n .command(\"update <email>\")\n .description(\"Update app-level permissions for a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .requiredOption(\"--permissions <list>\", \"New comma-separated permissions\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n const perms = (options.permissions as string).split(\",\").map((p: string) => p.trim());\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants update\",\n action: \"update permissions\",\n target: `${email}/${options.package}`,\n details: { permissions: perms },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await updateGrant(client, developerId, email, options.package, perms);\n console.log(formatOutput(result, format));\n });\n\n grants\n .command(\"delete <email>\")\n .description(\"Remove a per-app grant from a user\")\n .requiredOption(\"--package <packageName>\", \"App package name\")\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(grants.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n\n await requireConfirm(`Remove grant for \"${email}\" on ${options.package}?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"grants delete\",\n action: \"remove grant\",\n target: `${email}/${options.package}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteGrant(client, developerId, email, options.package);\n console.log(`Grant removed for ${email} on ${options.package}.`);\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAKP,SAAS,mBAAmB,UAA8B,QAA2B;AACnF,QAAM,KAAK,YAAY,OAAO;AAC9B,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,UAAU,QAAmB;AAC1C,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,kBAAkB,EAAE,KAAK,CAAC;AACnC;AAEO,SAAS,uBAAuB,SAAwB;AAC7D,QAAM,SAAS,QACZ,QAAQ,QAAQ,EAChB,YAAY,8DAA8D,EAC1E,OAAO,uBAAuB,sBAAsB;AAEvD,SACG,QAAQ,cAAc,EACtB,YAAY,oCAAoC,EAChD,OAAO,OAAO,UAAkB;AAC/B,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,OAAO,KAAK,EAAE,aAAa,GAAG,MAAM;AAC3E,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,WAAW,QAAQ,aAAa,KAAK;AAC1D,QAAI,OAAO,WAAW,GAAG;AACvB,UAAI,WAAW,QAAQ;AACrB,gBAAQ,IAAI,aAAa,CAAC,GAAG,MAAM,CAAC;AAAA,MACtC,OAAO;AACL,gBAAQ,IAAI,uBAAuB,KAAK,GAAG;AAAA,MAC7C;AACA;AAAA,IACF;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,SACG,QAAQ,gBAAgB,EACxB,YAAY,uCAAuC,EACnD,eAAe,2BAA2B,kBAAkB,EAC5D;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,OAAO,OAAe,YAAY;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,OAAO,KAAK,EAAE,aAAa,GAAG,MAAM;AAC3E,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,QAAS,QAAQ,YAAuB,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC;AAEpF,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,GAAG,KAAK,IAAI,QAAQ,OAAO;AAAA,UACnC,SAAS,EAAE,aAAa,MAAM;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM,YAAY,QAAQ,aAAa,OAAO,QAAQ,SAAS,KAAK;AACnF,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,SACG,QAAQ,gBAAgB,EACxB,YAAY,yCAAyC,EACrD,eAAe,2BAA2B,kBAAkB,EAC5D,eAAe,wBAAwB,iCAAiC,EACxE,OAAO,OAAO,OAAe,YAAY;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,OAAO,KAAK,EAAE,aAAa,GAAG,MAAM;AAC3E,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,QAAS,QAAQ,YAAuB,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC;AAEpF,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,GAAG,KAAK,IAAI,QAAQ,OAAO;AAAA,UACnC,SAAS,EAAE,aAAa,MAAM;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM,YAAY,QAAQ,aAAa,OAAO,QAAQ,SAAS,KAAK;AACnF,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,SACG,QAAQ,gBAAgB,EACxB,YAAY,oCAAoC,EAChD,eAAe,2BAA2B,kBAAkB,EAC5D,OAAO,OAAO,OAAe,YAAY;AACxC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,OAAO,KAAK,EAAE,aAAa,GAAG,MAAM;AAC3E,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,eAAe,qBAAqB,KAAK,QAAQ,QAAQ,OAAO,KAAK,OAAO;AAElF,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,GAAG,KAAK,IAAI,QAAQ,OAAO;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,YAAY,QAAQ,aAAa,OAAO,QAAQ,OAAO;AAC7D,YAAQ,IAAI,qBAAqB,KAAK,OAAO,QAAQ,OAAO,GAAG;AAAA,EACjE,CAAC;AACL;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/testers.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport {\n listTesters,\n addTesters,\n removeTesters,\n importTestersFromCsv,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption, requireConfirm } from \"../prompt.js\";\nimport { buildCommitOptions } from \"../commit-options.js\";\n\nexport function registerTestersCommands(program: Command): void {\n const testers = program.command(\"testers\").description(\"Manage testers and tester groups\");\n\n testers\n .command(\"list\")\n .description(\"List testers for a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending, e.g., email or -email)\")\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listTesters(client, packageName, options.track);\n if (options.sort && result.googleGroups) {\n const descending = options.sort.startsWith(\"-\");\n result.googleGroups = [...result.googleGroups].sort((a: string, b: string) =>\n descending ? b.localeCompare(a) : a.localeCompare(b),\n );\n }\n if (format !== \"json\") {\n const groups = (result.googleGroups || []) as string[];\n const rows = groups.map((g: string) => ({ googleGroup: g }));\n if (rows.length > 0) {\n console.log(formatOutput(rows, format));\n } else {\n console.log(\"No testers found.\");\n }\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n testers\n .command(\"add <emails...>\")\n .description(\"Add testers (Google Group emails) to a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (emails: string[], options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers add\",\n action: \"add testers to\",\n target: options.track,\n details: { emails },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await addTesters(\n client,\n packageName,\n options.track,\n emails,\n buildCommitOptions(options),\n );\n console.log(formatOutput(result, format));\n });\n\n testers\n .command(\"remove <emails...>\")\n .description(\"Remove testers (Google Group emails) from a track\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (emails: string[], options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n await requireConfirm(`Remove ${emails.length} tester(s) from ${options.track}?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers remove\",\n action: \"remove testers from\",\n target: options.track,\n details: { emails },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await removeTesters(\n client,\n packageName,\n options.track,\n emails,\n buildCommitOptions(options),\n );\n console.log(formatOutput(result, format));\n });\n\n testers\n .command(\"import\")\n .description(\"Import testers from a CSV file\")\n .option(\"--track <track>\", \"Track name (e.g., internal, alpha, beta)\")\n .option(\"--file <path>\", \"CSV file with email addresses\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.track = await requireOption(\n \"track\",\n options.track,\n {\n message: \"Track:\",\n choices: [\"internal\", \"alpha\", \"beta\"],\n },\n interactive,\n );\n\n options.file = await requireOption(\n \"file\",\n options.file,\n {\n message: \"CSV file path:\",\n },\n interactive,\n );\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"testers import\",\n action: \"import testers to\",\n target: options.track,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await importTestersFromCsv(\n client,\n packageName,\n options.track,\n options.file,\n buildCommitOptions(options),\n );\n console.log(formatOutput({ added: result.added, testers: result.testers }, format));\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMA,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,kCAAkC;AAEzF,UACG,QAAQ,MAAM,EACd,YAAY,0BAA0B,EACtC,OAAO,mBAAmB,0CAA0C,EACpE,OAAO,kBAAkB,qEAAqE,EAC9F,OAAO,eAAe,2BAA2B,EACjD,OAAO,uBAAuB,gCAAgC,EAC9D,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,QAAQ,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS,CAAC,YAAY,SAAS,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,YAAY,QAAQ,aAAa,QAAQ,KAAK;AACnE,QAAI,QAAQ,QAAQ,OAAO,cAAc;AACvC,YAAM,aAAa,QAAQ,KAAK,WAAW,GAAG;AAC9C,aAAO,eAAe,CAAC,GAAG,OAAO,YAAY,EAAE;AAAA,QAAK,CAAC,GAAW,MAC9D,aAAa,EAAE,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC;AAAA,MACrD;AAAA,IACF;AACA,QAAI,WAAW,QAAQ;AACrB,YAAM,SAAU,OAAO,gBAAgB,CAAC;AACxC,YAAM,OAAO,OAAO,IAAI,CAAC,OAAe,EAAE,aAAa,EAAE,EAAE;AAC3D,UAAI,KAAK,SAAS,GAAG;AACnB,gBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,MACxC,OAAO;AACL,gBAAQ,IAAI,mBAAmB;AAAA,MACjC;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C;AAAA,EACF,CAAC;AAEH,UACG,QAAQ,iBAAiB,EACzB,YAAY,8CAA8C,EAC1D,OAAO,mBAAmB,0CAA0C,EACpE,OAAO,iCAAiC,2CAA2C,EACnF,OAAO,wBAAwB,uCAAuC,EACtE,OAAO,OAAO,QAAkB,YAAY;AAC3C,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,QAAQ,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS,CAAC,YAAY,SAAS,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,QAAQ;AAAA,UAChB,SAAS,EAAE,OAAO;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,mBAAmB,OAAO;AAAA,IAC5B;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,UACG,QAAQ,oBAAoB,EAC5B,YAAY,mDAAmD,EAC/D,OAAO,mBAAmB,0CAA0C,EACpE,OAAO,iCAAiC,2CAA2C,EACnF,OAAO,wBAAwB,uCAAuC,EACtE,OAAO,OAAO,QAAkB,YAAY;AAC3C,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,QAAQ,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS,CAAC,YAAY,SAAS,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,UAAM,eAAe,UAAU,OAAO,MAAM,mBAAmB,QAAQ,KAAK,KAAK,OAAO;AAExF,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,QAAQ;AAAA,UAChB,SAAS,EAAE,OAAO;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,mBAAmB,OAAO;AAAA,IAC5B;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,gCAAgC,EAC5C,OAAO,mBAAmB,0CAA0C,EACpE,OAAO,iBAAiB,+BAA+B,EACvD,OAAO,iCAAiC,2CAA2C,EACnF,OAAO,wBAAwB,uCAAuC,EACtE,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,cAAc,OAAO;AAEzC,YAAQ,QAAQ,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,SAAS,CAAC,YAAY,SAAS,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,QAAQ;AAAA,UAChB,SAAS,EAAE,MAAM,QAAQ,KAAK;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,mBAAmB,OAAO;AAAA,IAC5B;AACA,YAAQ,IAAI,aAAa,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,GAAG,MAAM,CAAC;AAAA,EACpF,CAAC;AACL;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/tracks.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient } from \"@gpc-cli/api\";\nimport { listTracks, createTrack, updateTrackConfig, GpcError } from \"@gpc-cli/core\";\nimport { formatOutput, maybePaginate } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { buildCommitOptions } from \"../commit-options.js\";\n\nexport function registerTracksCommands(program: Command): void {\n const tracks = program.command(\"tracks\").description(\"Manage tracks\");\n\n tracks\n .command(\"list\")\n .description(\"List all tracks\")\n .option(\"--limit <n>\", \"Maximum results to return\")\n .option(\"--next-page <token>\", \"Pagination token for next page\")\n .action(async (_options) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const trackList = await listTracks(client, packageName);\n const format = getOutputFormat(program, config);\n\n const summary = trackList.map((t) => ({\n track: t.track,\n releases: t.releases?.length || 0,\n latestStatus: t.releases?.[0]?.status || \"none\",\n latestVersion: t.releases?.[0]?.versionCodes?.[0] || \"-\",\n }));\n\n await maybePaginate(formatOutput(summary, format));\n });\n\n tracks\n .command(\"create <name>\")\n .description(\"Create a custom track\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (name: string, options: Record<string, unknown>) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"tracks create\", action: \"create custom track\", target: name },\n format,\n formatOutput,\n );\n return;\n }\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const track = await createTrack(client, packageName, name, buildCommitOptions(options));\n console.log(formatOutput(track, format));\n });\n\n tracks\n .command(\"update <name>\")\n .description(\"Update track configuration from a JSON file\")\n .requiredOption(\"--file <path>\", \"Path to JSON config file\")\n .option(\"--changes-not-sent-for-review\", \"Commit changes without sending for review\")\n .option(\"--error-if-in-review\", \"Fail if changes are already in review\")\n .action(async (name: string, options: { file: string } & Record<string, unknown>) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n throw new GpcError(\n \"No package name. Use --app <package> or gpc config set app <package>\",\n \"MISSING_PACKAGE\",\n 2,\n \"gpc config set app com.example.app\",\n );\n }\n\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n { command: \"tracks update\", action: \"update track config from\", target: options.file },\n format,\n formatOutput,\n );\n return;\n }\n\n const raw = await readFile(options.file, \"utf-8\");\n const trackConfig = JSON.parse(raw) as Record<string, unknown>;\n\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const track = await updateTrackConfig(\n client,\n packageName,\n name,\n trackConfig,\n buildCommitOptions(options),\n );\n console.log(formatOutput(track, format));\n });\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|