@gpc-cli/cli 0.9.79 → 0.9.80

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 (33) hide show
  1. package/dist/{auth-4DRT7ZH2.js → auth-C6K563I5.js} +4 -3
  2. package/dist/auth-C6K563I5.js.map +1 -0
  3. package/dist/bin.js +2 -2
  4. package/dist/{bundles-6F3AD4QM.js → bundles-6NNRCBQE.js} +2 -2
  5. package/dist/bundles-6NNRCBQE.js.map +1 -0
  6. package/dist/{chunk-TPSF4BAR.js → chunk-OWV66STK.js} +13 -13
  7. package/dist/{config-WSKL2CK6.js → config-LCXU67JD.js} +2 -2
  8. package/dist/{doctor-JGJO52HH.js → doctor-YLCBYIGK.js} +2 -2
  9. package/dist/{enterprise-NP3EVLCN.js → enterprise-T5NWQS2R.js} +2 -2
  10. package/dist/{enterprise-NP3EVLCN.js.map → enterprise-T5NWQS2R.js.map} +1 -1
  11. package/dist/{feedback-56LWTSEP.js → feedback-CRWHXWAL.js} +2 -2
  12. package/dist/generated/docs-bundle.json +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/{purchases-LHGBIZNF.js → purchases-3KUR5YR3.js} +3 -4
  15. package/dist/purchases-3KUR5YR3.js.map +1 -0
  16. package/dist/{setup-IKHZQJIH.js → setup-XC4X323X.js} +4 -3
  17. package/dist/setup-XC4X323X.js.map +1 -0
  18. package/dist/{update-4SKKZHXQ.js → update-DRC5YFZI.js} +2 -2
  19. package/dist/{users-CJ23I3IS.js → users-HJAXLZPM.js} +2 -2
  20. package/dist/users-HJAXLZPM.js.map +1 -0
  21. package/dist/{version-YJSTOXO5.js → version-4U7XZV37.js} +2 -2
  22. package/package.json +1 -1
  23. package/dist/auth-4DRT7ZH2.js.map +0 -1
  24. package/dist/bundles-6F3AD4QM.js.map +0 -1
  25. package/dist/purchases-LHGBIZNF.js.map +0 -1
  26. package/dist/setup-IKHZQJIH.js.map +0 -1
  27. package/dist/users-CJ23I3IS.js.map +0 -1
  28. /package/dist/{chunk-TPSF4BAR.js.map → chunk-OWV66STK.js.map} +0 -0
  29. /package/dist/{config-WSKL2CK6.js.map → config-LCXU67JD.js.map} +0 -0
  30. /package/dist/{doctor-JGJO52HH.js.map → doctor-YLCBYIGK.js.map} +0 -0
  31. /package/dist/{feedback-56LWTSEP.js.map → feedback-CRWHXWAL.js.map} +0 -0
  32. /package/dist/{update-4SKKZHXQ.js.map → update-DRC5YFZI.js.map} +0 -0
  33. /package/dist/{version-YJSTOXO5.js.map → version-4U7XZV37.js.map} +0 -0
@@ -6,6 +6,7 @@ import {
6
6
  // src/commands/auth.ts
7
7
  import { createInterface } from "readline";
8
8
  import { access } from "fs/promises";
9
+ import { homedir } from "os";
9
10
  import { resolve } from "path";
10
11
  import { resolveAuth, loadServiceAccountKey, clearTokenCache, AuthError } from "@gpc-cli/auth";
11
12
  import { loadConfig, getCacheDir, deleteConfigValue, setConfigValue } from "@gpc-cli/config";
@@ -274,7 +275,7 @@ function registerAuthCommands(program) {
274
275
  "./service-account.json",
275
276
  "./gpc-service-account.json",
276
277
  "~/.config/gpc/service-account.json"
277
- ].map((p) => resolve2(p.replace("~", process.env["HOME"] || "")));
278
+ ].map((p) => resolve2(p.replace("~", homedir())));
278
279
  for (const p of commonPaths) {
279
280
  if (existsSync(p)) {
280
281
  console.log(`
@@ -292,7 +293,7 @@ function registerAuthCommands(program) {
292
293
  return;
293
294
  }
294
295
  }
295
- const absPath = resolve2(keyPath.replace("~", process.env["HOME"] || ""));
296
+ const absPath = resolve2(keyPath.replace("~", homedir()));
296
297
  if (!existsSync(absPath)) {
297
298
  console.error(`
298
299
  \u2717 File not found: ${absPath}`);
@@ -355,4 +356,4 @@ Step 7: Verifying setup...`);
355
356
  export {
356
357
  registerAuthCommands
357
358
  };
358
- //# sourceMappingURL=auth-4DRT7ZH2.js.map
359
+ //# sourceMappingURL=auth-C6K563I5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/auth.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport { access } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { resolve } from \"node:path\";\nimport { resolveAuth, loadServiceAccountKey, clearTokenCache, AuthError } from \"@gpc-cli/auth\";\nimport { loadConfig, getCacheDir, deleteConfigValue, setConfigValue } from \"@gpc-cli/config\";\nimport { formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function askQuestion(\n rl: ReturnType<typeof createInterface>,\n question: string,\n): Promise<string> {\n return new Promise((resolve) => {\n rl.question(question, (answer) => resolve(answer.trim()));\n });\n}\n\n/** Resolve a path to absolute (prevents CWD-dependent config). */\nfunction toAbsolutePath(pathStr: string): string {\n return resolve(pathStr);\n}\n\n/** Verify that the saved credentials can acquire a token. */\nasync function verifyToken(\n serviceAccountPath?: string,\n): Promise<{ email: string; ok: boolean; error?: string }> {\n try {\n const client = await resolveAuth({ serviceAccountPath });\n const email = client.getClientEmail();\n await client.getAccessToken();\n return { email, ok: true };\n } catch (err) {\n const email = \"unknown\";\n const msg = err instanceof Error ? err.message : String(err);\n return { email, ok: false, error: msg };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Interactive login wizard\n// ---------------------------------------------------------------------------\n\nasync function runLoginWizard(program: Command): Promise<void> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n console.log(\"\\nGPC Authentication Setup\");\n console.log(\n \"\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\",\n );\n\n // Step 1: auth method\n console.log(\"\\nAuthentication methods:\");\n console.log(\" 1. Service account key file (recommended)\");\n console.log(\" 2. Application Default Credentials (ADC)\");\n const method = await askQuestion(rl, \"\\nSelect method [1]: \");\n const useAdc = method === \"2\";\n\n if (useAdc) {\n const client = await resolveAuth();\n const email = client.getClientEmail();\n // Verify token works\n await client.getAccessToken();\n outputLoginResult(program, { account: email, method: \"adc\", verified: true });\n return;\n }\n\n // Step 2: credentials path with validation loop\n let saPath = \"\";\n while (!saPath) {\n const input = await askQuestion(rl, \"\\nPath to service account JSON key: \");\n if (!input) {\n console.log(\" Path is required.\");\n continue;\n }\n try {\n await access(input);\n saPath = toAbsolutePath(input);\n } catch {\n console.log(` File not found: ${input}`);\n }\n }\n\n // Step 3: optional profile name\n const profileName = await askQuestion(rl, \"\\nProfile name (optional, press Enter to skip): \");\n\n // Step 4: default package name\n const packageName = await askQuestion(\n rl,\n \"Default package name (optional, e.g. com.example.app): \",\n );\n\n // Apply settings\n const key = await loadServiceAccountKey(saPath);\n\n if (profileName) {\n const { setProfileConfig } = await import(\"@gpc-cli/config\");\n await setProfileConfig(profileName, {\n auth: { serviceAccount: saPath },\n ...(packageName && { app: packageName }),\n });\n } else {\n await setConfigValue(\"auth.serviceAccount\", saPath);\n if (packageName) await setConfigValue(\"app\", packageName);\n }\n\n // Verify token\n const verification = await verifyToken(saPath);\n\n outputLoginResult(program, {\n account: key.client_email,\n project: key.project_id,\n method: \"service-account\",\n profile: profileName || undefined,\n verified: verification.ok,\n verifyError: verification.error,\n });\n } finally {\n rl.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Structured login output\n// ---------------------------------------------------------------------------\n\ninterface LoginResult {\n account: string;\n project?: string;\n method: string;\n profile?: string;\n verified: boolean;\n verifyError?: string;\n}\n\nfunction outputLoginResult(program: Command, result: LoginResult): void {\n const parentOpts = program.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n if (jsonMode) {\n console.log(\n JSON.stringify({\n success: true,\n account: result.account,\n project: result.project,\n method: result.method,\n profile: result.profile,\n verified: result.verified,\n ...(result.verifyError && { verifyError: result.verifyError }),\n }),\n );\n return;\n }\n\n if (result.profile) {\n console.log(`\\nProfile \"${result.profile}\" configured with ${result.account}`);\n } else if (result.method === \"adc\") {\n console.log(`\\nAuthenticated via Application Default Credentials`);\n console.log(`Account: ${result.account}`);\n } else {\n console.log(`\\nAuthenticated as ${result.account}`);\n }\n if (result.project) console.log(`Project: ${result.project}`);\n\n if (result.verified) {\n console.log(\"Verified: token acquired successfully\");\n } else if (result.verifyError) {\n console.log(`Warning: token verification failed: ${result.verifyError}`);\n console.log(\"Credentials saved, but check your setup with: gpc doctor\");\n }\n\n if (!result.verifyError) {\n console.log(\"\\nRun 'gpc doctor' to verify your full setup.\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage authentication\");\n\n auth\n .command(\"login\")\n .description(\"Authenticate with Google Play Developer API\")\n .option(\"--service-account <path>\", \"Path to service account JSON key file\")\n .option(\"--adc\", \"Use Application Default Credentials\")\n .option(\"--profile <name>\", \"Store credentials under a named profile\")\n .action(async (options: { serviceAccount?: string; adc?: boolean; profile?: string }) => {\n if (options.serviceAccount) {\n const absolutePath = toAbsolutePath(options.serviceAccount);\n const key = await loadServiceAccountKey(absolutePath);\n\n if (options.profile) {\n const { setProfileConfig } = await import(\"@gpc-cli/config\");\n await setProfileConfig(options.profile, {\n auth: { serviceAccount: absolutePath },\n });\n } else {\n await setConfigValue(\"auth.serviceAccount\", absolutePath);\n }\n\n // Verify token works\n const verification = await verifyToken(absolutePath);\n\n outputLoginResult(program, {\n account: key.client_email,\n project: key.project_id,\n method: \"service-account\",\n profile: options.profile,\n verified: verification.ok,\n verifyError: verification.error,\n });\n } else if (options.adc) {\n const client = await resolveAuth();\n const email = client.getClientEmail();\n await client.getAccessToken();\n outputLoginResult(program, { account: email, method: \"adc\", verified: true });\n } else {\n // Interactive wizard when no flags provided and in interactive mode\n const opts = program.opts();\n const interactive =\n opts[\"interactive\"] !== false && opts[\"ci\"] !== true && process.stdin.isTTY;\n if (interactive) {\n await runLoginWizard(program);\n } else {\n console.log(\"Usage: gpc auth login --service-account <path>\");\n console.log(\"\");\n console.log(\"Authentication methods:\");\n console.log(\" --service-account <path> Service account JSON key file\");\n console.log(\" --adc Application Default Credentials\");\n console.log(\"\");\n console.log(\"Options:\");\n console.log(\" --profile <name> Store under a named profile\");\n }\n }\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(async () => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n try {\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n const data = {\n authenticated: true,\n account: client.getClientEmail(),\n project: client.getProjectId(),\n ...(config.profile && { profile: config.profile }),\n };\n console.log(formatOutput(data, format));\n } catch (error) {\n if (error instanceof AuthError) {\n const data = {\n authenticated: false,\n error: error.message,\n suggestion: error.suggestion,\n };\n console.log(formatOutput(data, format));\n }\n throw error; // Let error handler set exit code 3\n }\n });\n\n auth\n .command(\"logout\")\n .description(\"Clear stored credentials and token cache\")\n .option(\"--profile <name>\", \"Clear credentials for a specific profile\")\n .action(async (options: { profile?: string }) => {\n if (options.profile) {\n const { deleteProfile } = await import(\"@gpc-cli/config\");\n const deleted = await deleteProfile(options.profile);\n if (deleted) {\n console.log(`Profile \"${options.profile}\" removed.`);\n } else {\n console.log(`Profile \"${options.profile}\" not found.`);\n }\n } else {\n await deleteConfigValue(\"auth.serviceAccount\");\n console.log(\"Credentials cleared.\");\n }\n await clearTokenCache(getCacheDir());\n console.log(\"Token cache cleared.\");\n });\n\n auth\n .command(\"whoami\")\n .description(\"Show current authenticated identity\")\n .action(async () => {\n const config = await loadConfig();\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n console.log(client.getClientEmail());\n });\n\n auth\n .command(\"switch <profile>\")\n .description(\"Switch to a named profile\")\n .action(async (profile: string) => {\n // loadConfig with the profile will throw ConfigError if profile doesn't exist\n const config = await loadConfig({ profile });\n await setConfigValue(\"profile\", profile);\n console.log(`Switched to profile \"${profile}\"`);\n if (config.auth?.serviceAccount) {\n console.log(`Service account: ${config.auth.serviceAccount}`);\n }\n });\n\n auth\n .command(\"token\")\n .description(\"Print the current access token (useful for manual API calls)\")\n .action(async () => {\n const config = await loadConfig();\n const authClient = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n const token = await authClient.getAccessToken();\n console.log(token);\n });\n\n auth\n .command(\"setup-gcp\")\n .description(\"Step-by-step guide to create a Google Cloud service account\")\n .option(\"--key <path>\", \"Path to an already-downloaded service account JSON key\")\n .action(async (options: { key?: string }) => {\n const { existsSync, readFileSync } = await import(\"node:fs\");\n const { resolve } = await import(\"node:path\");\n\n console.log(\"\\nGPC \\u2014 Google Cloud Service Account Setup\");\n console.log(\"\\u2550\".repeat(50));\n\n // If key path provided or user already has one, skip to validation\n let keyPath = options.key;\n\n if (!keyPath) {\n console.log(\"\\nStep 1: Open the Google Cloud Console\");\n console.log(\" https://console.cloud.google.com/iam-admin/serviceaccounts\");\n console.log(\"\\nStep 2: Create a service account\");\n console.log(\" \\u2022 Click 'Create Service Account'\");\n console.log(\" \\u2022 Name it: gpc-deploy (or any name you like)\");\n console.log(\" \\u2022 Description: GPC Google Play Console access\");\n console.log(\"\\nStep 3: Grant roles\");\n console.log(\" No GCP roles needed \\u2014 permissions are managed in Google Play Console.\");\n console.log(\"\\nStep 4: Download the JSON key\");\n console.log(\n \" \\u2022 Click your new service account \\u2192 Keys \\u2192 Add Key \\u2192 Create new key \\u2192 JSON\",\n );\n console.log(\" \\u2022 Save as: ~/gpc-service-account.json\");\n console.log(\"\\nStep 5: Add to Google Play Console\");\n console.log(\" https://play.google.com/console/developers\");\n console.log(\" \\u2022 Users and Permissions \\u2192 Invite new users\");\n console.log(\" \\u2022 Paste the service account email (ends with @...gserviceaccount.com)\");\n console.log(\" \\u2022 Grant: Release manager + View app info + Reply to reviews\");\n\n // Try to auto-detect a key file\n const commonPaths = [\n \"~/gpc-service-account.json\",\n \"./service-account.json\",\n \"./gpc-service-account.json\",\n \"~/.config/gpc/service-account.json\",\n ].map((p) => resolve(p.replace(\"~\", homedir())));\n\n for (const p of commonPaths) {\n if (existsSync(p)) {\n console.log(`\\n\\u2713 Found key file: ${p}`);\n keyPath = p;\n break;\n }\n }\n\n if (!keyPath) {\n console.log(\"\\nOnce you've downloaded the key, run:\");\n console.log(\" gpc auth setup-gcp --key <path/to/key.json>\");\n console.log(\"\\nOr authenticate directly:\");\n console.log(\" gpc auth login --service-account <path/to/key.json>\");\n console.log(\"\\nSee full docs: https://yasserstudio.github.io/gpc/guide/authentication\");\n return;\n }\n }\n\n // Validate the key file\n const absPath = resolve(keyPath.replace(\"~\", homedir()));\n if (!existsSync(absPath)) {\n console.error(`\\n\\u2717 File not found: ${absPath}`);\n return;\n }\n\n try {\n const content = JSON.parse(readFileSync(absPath, \"utf-8\"));\n if (content.type !== \"service_account\") {\n console.error(`\\n\\u2717 Not a service account key (type: ${content.type})`);\n return;\n }\n console.log(`\\n\\u2713 Valid service account key`);\n console.log(` Email: ${content.client_email}`);\n console.log(` Project: ${content.project_id}`);\n } catch {\n console.error(`\\n\\u2717 Invalid JSON file: ${absPath}`);\n return;\n }\n\n // Auto-login\n console.log(`\\nStep 6: Authenticating...`);\n try {\n const auth = await resolveAuth({ serviceAccountPath: absPath });\n await auth.getAccessToken();\n const { setConfigValue } = await import(\"@gpc-cli/config\");\n await setConfigValue(\"auth.serviceAccount\", absPath);\n console.log(`\\u2713 Authenticated and saved to config`);\n } catch (err) {\n console.error(\n `\\u2717 Authentication failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n console.log(`\\nTry manually: gpc auth login --service-account ${absPath}`);\n return;\n }\n\n // Auto-run doctor\n console.log(`\\nStep 7: Verifying setup...`);\n console.log(` Run: gpc doctor`);\n });\n\n auth\n .command(\"profiles\")\n .description(\"List configured profiles\")\n .action(async () => {\n const { listProfiles } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const profiles = await listProfiles();\n const format = getOutputFormat(program, config);\n\n if (profiles.length === 0) {\n console.log(\n \"No profiles configured. Use: gpc auth login --service-account <path> --profile <name>\",\n );\n return;\n }\n\n const data = profiles.map((name) => ({\n name,\n active: name === config.profile,\n }));\n console.log(formatOutput(data, format));\n });\n}\n"],"mappings":"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","names":["resolve","auth","setConfigValue"]}
package/dist/bin.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-TPSF4BAR.js";
6
+ } from "./chunk-OWV66STK.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.79";
60
+ var currentVersion = "0.9.80";
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);
@@ -48,7 +48,7 @@ function registerBundlesCommands(program) {
48
48
  } else {
49
49
  console.error(`Bundle with version code ${options.versionCode} not found.`);
50
50
  }
51
- process.exit(1);
51
+ throw new Error(`Bundle with version code ${options.versionCode} not found.`);
52
52
  }
53
53
  console.log(formatOutput(result, format));
54
54
  });
@@ -79,4 +79,4 @@ function registerBundlesCommands(program) {
79
79
  export {
80
80
  registerBundlesCommands
81
81
  };
82
- //# sourceMappingURL=bundles-6F3AD4QM.js.map
82
+ //# sourceMappingURL=bundles-6NNRCBQE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/bundles.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { listBundles, findBundle, waitForBundle, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { resolvePackageName, getClient } from \"../resolve.js\";\n\nexport function registerBundlesCommands(program: Command): void {\n const bundles = program.command(\"bundles\").description(\"Manage uploaded app bundles (API)\");\n\n bundles\n .command(\"list\")\n .description(\"List all processed bundles\")\n .action(async () => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n\n const result = await listBundles(client, packageName);\n\n if (format === \"json\") {\n console.log(formatOutput(result, \"json\"));\n } else {\n if (result.length === 0) {\n console.log(\"No bundles found.\");\n return;\n }\n console.log(\n formatOutput(\n result.map((b) => ({\n versionCode: b.versionCode,\n sha256: b.sha256.slice(0, 12) + \"...\",\n })),\n format,\n ),\n );\n }\n });\n\n bundles\n .command(\"find\")\n .description(\"Find a specific bundle by version code\")\n .requiredOption(\"--version-code <n>\", \"Version code to find\", (v) => parseInt(v, 10))\n .action(async (options: { versionCode: number }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n\n const result = await findBundle(client, packageName, options.versionCode);\n\n if (!result) {\n if (format === \"json\") {\n console.log(formatOutput(null, \"json\"));\n } else {\n console.error(`Bundle with version code ${options.versionCode} not found.`);\n }\n throw new Error(`Bundle with version code ${options.versionCode} not found.`);\n }\n\n console.log(formatOutput(result, format));\n });\n\n bundles\n .command(\"wait\")\n .description(\"Wait for a bundle to finish server-side processing\")\n .requiredOption(\"--version-code <n>\", \"Version code to wait for\", (v) => parseInt(v, 10))\n .option(\"--timeout <seconds>\", \"Timeout in seconds (default: 600)\", (v) => parseInt(v, 10))\n .option(\"--interval <seconds>\", \"Poll interval in seconds (default: 15)\", (v) =>\n parseInt(v, 10),\n )\n .action(async (options: { versionCode: number; timeout?: number; interval?: number }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n\n if (format !== \"json\") {\n process.stderr.write(`Waiting for bundle ${options.versionCode} to finish processing...\\n`);\n }\n\n const result = await waitForBundle(client, packageName, options.versionCode, {\n timeout: options.timeout ? options.timeout * 1000 : undefined,\n interval: options.interval ? options.interval * 1000 : undefined,\n });\n\n if (format !== \"json\") {\n process.stderr.write(`Bundle ${result.versionCode} is ready.\\n`);\n }\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,aAAa,YAAY,eAAe,oBAAoB;AAI9D,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,mCAAmC;AAE1F,UACG,QAAQ,MAAM,EACd,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM,YAAY,QAAQ,WAAW;AAEpD,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC1C,OAAO;AACL,UAAI,OAAO,WAAW,GAAG;AACvB,gBAAQ,IAAI,mBAAmB;AAC/B;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,UACE,OAAO,IAAI,CAAC,OAAO;AAAA,YACjB,aAAa,EAAE;AAAA,YACf,QAAQ,EAAE,OAAO,MAAM,GAAG,EAAE,IAAI;AAAA,UAClC,EAAE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAEH,UACG,QAAQ,MAAM,EACd,YAAY,wCAAwC,EACpD,eAAe,sBAAsB,wBAAwB,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EACnF,OAAO,OAAO,YAAqC;AAClD,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM,WAAW,QAAQ,aAAa,QAAQ,WAAW;AAExE,QAAI,CAAC,QAAQ;AACX,UAAI,WAAW,QAAQ;AACrB,gBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,MACxC,OAAO;AACL,gBAAQ,MAAM,4BAA4B,QAAQ,WAAW,aAAa;AAAA,MAC5E;AACA,YAAM,IAAI,MAAM,4BAA4B,QAAQ,WAAW,aAAa;AAAA,IAC9E;AAEA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,UACG,QAAQ,MAAM,EACd,YAAY,oDAAoD,EAChE,eAAe,sBAAsB,4BAA4B,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EACvF,OAAO,uBAAuB,qCAAqC,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EACzF;AAAA,IAAO;AAAA,IAAwB;AAAA,IAA0C,CAAC,MACzE,SAAS,GAAG,EAAE;AAAA,EAChB,EACC,OAAO,OAAO,YAA0E;AACvF,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAC9C,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,QAAI,WAAW,QAAQ;AACrB,cAAQ,OAAO,MAAM,sBAAsB,QAAQ,WAAW;AAAA,CAA4B;AAAA,IAC5F;AAEA,UAAM,SAAS,MAAM,cAAc,QAAQ,aAAa,QAAQ,aAAa;AAAA,MAC3E,SAAS,QAAQ,UAAU,QAAQ,UAAU,MAAO;AAAA,MACpD,UAAU,QAAQ,WAAW,QAAQ,WAAW,MAAO;AAAA,IACzD,CAAC;AAED,QAAI,WAAW,QAAQ;AACrB,cAAQ,OAAO,MAAM,UAAU,OAAO,WAAW;AAAA,CAAc;AAAA,IACjE;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
@@ -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.79", "-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.80", "-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
- (await import("./auth-4DRT7ZH2.js")).registerAuthCommands(program);
65
+ (await import("./auth-C6K563I5.js")).registerAuthCommands(program);
66
66
  },
67
67
  config: async () => {
68
- (await import("./config-WSKL2CK6.js")).registerConfigCommands(program);
68
+ (await import("./config-LCXU67JD.js")).registerConfigCommands(program);
69
69
  },
70
70
  doctor: async () => {
71
- (await import("./doctor-JGJO52HH.js")).registerDoctorCommand(program);
71
+ (await import("./doctor-YLCBYIGK.js")).registerDoctorCommand(program);
72
72
  },
73
73
  update: async () => {
74
- (await import("./update-4SKKZHXQ.js")).registerUpdateCommand(program);
74
+ (await import("./update-DRC5YFZI.js")).registerUpdateCommand(program);
75
75
  },
76
76
  docs: async () => {
77
77
  (await import("./docs-OU6LSSJD.js")).registerDocsCommand(program);
@@ -117,7 +117,7 @@ async function createProgram(pluginManager) {
117
117
  (await import("./iap-S5X4O7XF.js")).registerIapCommands(program);
118
118
  },
119
119
  purchases: async () => {
120
- (await import("./purchases-LHGBIZNF.js")).registerPurchasesCommands(program);
120
+ (await import("./purchases-3KUR5YR3.js")).registerPurchasesCommands(program);
121
121
  },
122
122
  pricing: async () => {
123
123
  (await import("./pricing-HYQRXKNO.js")).registerPricingCommands(program);
@@ -126,7 +126,7 @@ async function createProgram(pluginManager) {
126
126
  (await import("./reports-CIB2T3XT.js")).registerReportsCommands(program);
127
127
  },
128
128
  users: async () => {
129
- (await import("./users-CJ23I3IS.js")).registerUsersCommands(program);
129
+ (await import("./users-HJAXLZPM.js")).registerUsersCommands(program);
130
130
  },
131
131
  testers: async () => {
132
132
  (await import("./testers-YQZ2XHI6.js")).registerTestersCommands(program);
@@ -170,7 +170,7 @@ async function createProgram(pluginManager) {
170
170
  (await import("./bundle-PFTE7XMU.js")).registerBundleCommands(program);
171
171
  },
172
172
  bundles: async () => {
173
- (await import("./bundles-6F3AD4QM.js")).registerBundlesCommands(program);
173
+ (await import("./bundles-6NNRCBQE.js")).registerBundlesCommands(program);
174
174
  },
175
175
  audit: async () => {
176
176
  (await import("./audit-D54TYDFD.js")).registerAuditCommands(program);
@@ -191,16 +191,16 @@ async function createProgram(pluginManager) {
191
191
  (await import("./verify-O2PSBTIC.js")).registerVerifyCommand(program);
192
192
  },
193
193
  version: async () => {
194
- (await import("./version-YJSTOXO5.js")).registerVersionCommand(program);
194
+ (await import("./version-4U7XZV37.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-56LWTSEP.js")).registerFeedbackCommand(program);
200
+ (await import("./feedback-CRWHXWAL.js")).registerFeedbackCommand(program);
201
201
  },
202
202
  setup: async () => {
203
- (await import("./setup-IKHZQJIH.js")).registerSetupCommand(program);
203
+ (await import("./setup-XC4X323X.js")).registerSetupCommand(program);
204
204
  },
205
205
  quickstart: async () => {
206
206
  (await import("./quickstart-FOWM3OKT.js")).registerQuickstartCommand(program);
@@ -218,7 +218,7 @@ async function createProgram(pluginManager) {
218
218
  (await import("./games-SVFN2YIS.js")).registerGamesCommands(program);
219
219
  },
220
220
  enterprise: async () => {
221
- (await import("./enterprise-NP3EVLCN.js")).registerEnterpriseCommands(program);
221
+ (await import("./enterprise-T5NWQS2R.js")).registerEnterpriseCommands(program);
222
222
  },
223
223
  diff: async () => {
224
224
  (await import("./diff-OBSHUSTL.js")).registerDiffCommand(program);
@@ -471,4 +471,4 @@ export {
471
471
  createProgram,
472
472
  handleCliError
473
473
  };
474
- //# sourceMappingURL=chunk-TPSF4BAR.js.map
474
+ //# sourceMappingURL=chunk-OWV66STK.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-JGJO52HH.js");
81
+ const { registerDoctorCommand } = await import("./doctor-YLCBYIGK.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-WSKL2CK6.js.map
110
+ //# sourceMappingURL=config-LCXU67JD.js.map
@@ -144,7 +144,7 @@ function checkCiEnvironment() {
144
144
  };
145
145
  }
146
146
  async function checkGpcVersion() {
147
- const currentVersion = "0.9.79";
147
+ const currentVersion = "0.9.80";
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-JGJO52HH.js.map
1141
+ //# sourceMappingURL=doctor-YLCBYIGK.js.map
@@ -210,10 +210,10 @@ function registerEnterpriseCommands(program) {
210
210
  "public apps. Use `gpc apps list` to see them."
211
211
  ].join("\n")
212
212
  );
213
- process.exit(2);
213
+ throw new Error("enterprise list is not supported by the Play Custom App Publishing API");
214
214
  });
215
215
  }
216
216
  export {
217
217
  registerEnterpriseCommands
218
218
  };
219
- //# sourceMappingURL=enterprise-NP3EVLCN.js.map
219
+ //# sourceMappingURL=enterprise-T5NWQS2R.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/enterprise.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createEnterpriseClient } from \"@gpc-cli/api\";\nimport { createEnterpriseApp, publishEnterpriseApp, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { yellow, dim, bold } from \"../colors.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function getClient() {\n const config = await loadConfig();\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return { client: createEnterpriseClient({ auth }), config };\n}\n\n/** Matches a developer account ID — Google uses int64-shaped integers. */\nconst ACCOUNT_ID_RE = /^\\d+$/;\n\n/**\n * Resolve and validate the developer account ID from either `--account`\n * (preferred) or `--org` (deprecated alias). Emits a warning if `--org` is\n * used. Throws a clear error if neither is provided or the value isn't\n * numeric.\n *\n * Numeric validation happens here — BEFORE the permanent-private confirmation\n * prompt prints — so a user with a malformed account ID sees the error\n * immediately instead of typing \"y\" to a prompt showing the wrong target.\n * The api-client's `assertAccountId` still runs as defense-in-depth in case\n * this helper is bypassed.\n */\nfunction resolveAccountId(opts: Record<string, unknown>): string {\n const account = opts[\"account\"];\n const org = opts[\"org\"];\n let raw: string | undefined;\n\n if (typeof account === \"string\" && account.length > 0) {\n raw = account;\n } else if (typeof org === \"string\" && org.length > 0) {\n console.warn(\n yellow(\"warning: --org is deprecated, use --account instead\"),\n dim(\"(will be removed in a future version)\"),\n );\n raw = org;\n }\n\n if (!raw) {\n throw Object.assign(\n new Error(\n \"Missing required option --account. Provide your developer account ID from the Play Console URL.\",\n ),\n { code: \"MISSING_REQUIRED_OPTION\", exitCode: 2 },\n );\n }\n\n if (!ACCOUNT_ID_RE.test(raw)) {\n throw Object.assign(\n new Error(\n [\n `Developer account ID must be numeric (got \"${raw}\").`,\n \"Find your developer account ID in the Play Console URL:\",\n \" https://play.google.com/console/developers/[ID]\",\n \"The ID is a long integer, not your Workspace or Cloud Identity organization ID.\",\n ].join(\"\\n\"),\n ),\n { code: \"ENTERPRISE_INVALID_ACCOUNT_ID\", exitCode: 2 },\n );\n }\n\n return raw;\n}\n\n/**\n * Accumulator for commander's repeatable options.\n * Example: `--org-id a --org-id b` → `[\"a\", \"b\"]`.\n */\nfunction collect(value: string, previous: string[] | undefined): string[] {\n return [...(previous ?? []), value];\n}\n\ninterface CreateOptions {\n bundle?: string;\n title: string;\n lang?: string;\n orgId?: string[];\n orgName?: string[];\n}\n\n/**\n * Zip `--org-id` and `--org-name` into the shape the core function expects.\n * Missing names produce undefined entries — that's fine, organizationName is optional.\n */\nfunction zipOrganizations(\n orgIds?: string[],\n orgNames?: string[],\n): Array<{ organizationId: string; organizationName?: string }> | undefined {\n if (!orgIds || orgIds.length === 0) return undefined;\n return orgIds.map((organizationId, i) => ({\n organizationId,\n organizationName: orgNames?.[i],\n }));\n}\n\n/**\n * Print the permanent-private confirmation prompt and block until user confirms.\n * Honors `--yes` and non-interactive environments via `requireConfirm`.\n */\nasync function confirmPermanentPrivate(\n program: Command,\n summary: {\n accountId: string;\n title: string;\n languageCode: string;\n bundlePath: string;\n organizations?: Array<{ organizationId: string; organizationName?: string }>;\n },\n): Promise<void> {\n const orgSummary =\n summary.organizations && summary.organizations.length > 0\n ? summary.organizations\n .map((o) =>\n o.organizationName ? `${o.organizationId} (${o.organizationName})` : o.organizationId,\n )\n .join(\", \")\n : dim(\"none specified — add later via Play Console\");\n\n console.error(\"\");\n console.error(bold(yellow(\"⚠ This will publish a PRIVATE app to Managed Google Play.\")));\n console.error(\"\");\n console.error(\n \" Private apps created via this API are permanently private and cannot be converted\",\n );\n console.error(\n \" to public apps later. You can update versions, tracks, and listings via regular\",\n );\n console.error(\n \" GPC commands (gpc releases, gpc tracks, gpc listings) — but the app will never\",\n );\n console.error(\" appear on the public Play Store.\");\n console.error(\"\");\n console.error(` Developer account: ${summary.accountId}`);\n console.error(` Title: ${summary.title}`);\n console.error(` Language: ${summary.languageCode}`);\n console.error(` Bundle: ${summary.bundlePath}`);\n console.error(` Organizations: ${orgSummary}`);\n console.error(\"\");\n\n await requireConfirm(\"Continue with private app creation?\", program);\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerEnterpriseCommands(program: Command): void {\n const enterprise = program\n .command(\"enterprise\")\n .description(\"Manage private enterprise apps via Managed Google Play (Play Custom App API)\")\n .option(\"--account <id>\", \"Developer account ID (int64, from Play Console URL)\")\n .option(\"--org <id>\", \"[DEPRECATED] Alias for --account — will be removed in a future version\");\n\n // ----------------------------- create --------------------------------\n enterprise\n .command(\"create\")\n .description(\"Create a new private enterprise app\")\n .requiredOption(\"--title <title>\", \"App title (required)\")\n .requiredOption(\"--bundle <path>\", \"Path to AAB or APK file to upload (required)\")\n .option(\"--lang <code>\", \"Default listing language code (BCP 47)\", \"en_US\")\n .option(\n \"--org-id <id>\",\n \"Target enterprise organization ID (repeatable — use once per org)\",\n collect,\n )\n .option(\n \"--org-name <name>\",\n \"Human-readable organization name (repeatable, matched by position with --org-id)\",\n collect,\n )\n .action(async (options: CreateOptions) => {\n const { client, config } = await getClient();\n const parentOpts = enterprise.opts();\n const accountId = resolveAccountId(parentOpts);\n const format = getOutputFormat(program, config);\n\n const languageCode = options.lang ?? \"en_US\";\n const organizations = zipOrganizations(options.orgId, options.orgName);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"enterprise create\",\n action: \"create private custom app (dry-run)\",\n target: options.title,\n details: {\n accountId,\n bundlePath: options.bundle,\n title: options.title,\n languageCode,\n organizations: organizations ?? [],\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await confirmPermanentPrivate(program, {\n accountId,\n title: options.title,\n languageCode,\n bundlePath: options.bundle ?? \"\",\n organizations,\n });\n\n const result = await createEnterpriseApp(client, {\n accountId,\n bundlePath: options.bundle ?? \"\",\n title: options.title,\n languageCode,\n organizations,\n });\n\n console.log(formatOutput(result, format));\n });\n\n // ----------------------------- publish -------------------------------\n enterprise\n .command(\"publish <bundle>\")\n .description(\"One-shot publish: validate, create, and return a private custom app package name\")\n .requiredOption(\"--title <title>\", \"App title (required)\")\n .option(\"--lang <code>\", \"Default listing language code (BCP 47)\", \"en_US\")\n .option(\n \"--org-id <id>\",\n \"Target enterprise organization ID (repeatable — use once per org)\",\n collect,\n )\n .option(\n \"--org-name <name>\",\n \"Human-readable organization name (repeatable, matched by position with --org-id)\",\n collect,\n )\n .action(async (bundlePath: string, options: Omit<CreateOptions, \"bundle\">) => {\n const { client, config } = await getClient();\n const parentOpts = enterprise.opts();\n const accountId = resolveAccountId(parentOpts);\n const format = getOutputFormat(program, config);\n\n const languageCode = options.lang ?? \"en_US\";\n const organizations = zipOrganizations(options.orgId, options.orgName);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"enterprise publish\",\n action: \"publish private custom app (dry-run)\",\n target: options.title,\n details: {\n accountId,\n bundlePath,\n title: options.title,\n languageCode,\n organizations: organizations ?? [],\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await confirmPermanentPrivate(program, {\n accountId,\n title: options.title,\n languageCode,\n bundlePath,\n organizations,\n });\n\n const result = await publishEnterpriseApp(client, {\n accountId,\n bundlePath,\n title: options.title,\n languageCode,\n organizations,\n });\n\n console.log(formatOutput(result, format));\n });\n\n // ------------------------------- list --------------------------------\n // Explicitly errors with a helpful message. The Play Custom App Publishing\n // API has no list method. Private apps appear in your regular developer\n // account — use `gpc apps list`.\n enterprise\n .command(\"list\")\n .description(\"[REMOVED] Use `gpc apps list` — private apps appear in your regular account\")\n .action(() => {\n console.error(\n [\n \"gpc enterprise list was removed in v0.9.56.\",\n \"\",\n \"Google's Play Custom App Publishing API has no list method — private apps\",\n \"created via this API appear in your regular developer account alongside\",\n \"public apps. Use `gpc apps list` to see them.\",\n ].join(\"\\n\"),\n );\n process.exit(2);\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/enterprise.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createEnterpriseClient } from \"@gpc-cli/api\";\nimport { createEnterpriseApp, publishEnterpriseApp, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { yellow, dim, bold } from \"../colors.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function getClient() {\n const config = await loadConfig();\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return { client: createEnterpriseClient({ auth }), config };\n}\n\n/** Matches a developer account ID — Google uses int64-shaped integers. */\nconst ACCOUNT_ID_RE = /^\\d+$/;\n\n/**\n * Resolve and validate the developer account ID from either `--account`\n * (preferred) or `--org` (deprecated alias). Emits a warning if `--org` is\n * used. Throws a clear error if neither is provided or the value isn't\n * numeric.\n *\n * Numeric validation happens here — BEFORE the permanent-private confirmation\n * prompt prints — so a user with a malformed account ID sees the error\n * immediately instead of typing \"y\" to a prompt showing the wrong target.\n * The api-client's `assertAccountId` still runs as defense-in-depth in case\n * this helper is bypassed.\n */\nfunction resolveAccountId(opts: Record<string, unknown>): string {\n const account = opts[\"account\"];\n const org = opts[\"org\"];\n let raw: string | undefined;\n\n if (typeof account === \"string\" && account.length > 0) {\n raw = account;\n } else if (typeof org === \"string\" && org.length > 0) {\n console.warn(\n yellow(\"warning: --org is deprecated, use --account instead\"),\n dim(\"(will be removed in a future version)\"),\n );\n raw = org;\n }\n\n if (!raw) {\n throw Object.assign(\n new Error(\n \"Missing required option --account. Provide your developer account ID from the Play Console URL.\",\n ),\n { code: \"MISSING_REQUIRED_OPTION\", exitCode: 2 },\n );\n }\n\n if (!ACCOUNT_ID_RE.test(raw)) {\n throw Object.assign(\n new Error(\n [\n `Developer account ID must be numeric (got \"${raw}\").`,\n \"Find your developer account ID in the Play Console URL:\",\n \" https://play.google.com/console/developers/[ID]\",\n \"The ID is a long integer, not your Workspace or Cloud Identity organization ID.\",\n ].join(\"\\n\"),\n ),\n { code: \"ENTERPRISE_INVALID_ACCOUNT_ID\", exitCode: 2 },\n );\n }\n\n return raw;\n}\n\n/**\n * Accumulator for commander's repeatable options.\n * Example: `--org-id a --org-id b` → `[\"a\", \"b\"]`.\n */\nfunction collect(value: string, previous: string[] | undefined): string[] {\n return [...(previous ?? []), value];\n}\n\ninterface CreateOptions {\n bundle?: string;\n title: string;\n lang?: string;\n orgId?: string[];\n orgName?: string[];\n}\n\n/**\n * Zip `--org-id` and `--org-name` into the shape the core function expects.\n * Missing names produce undefined entries — that's fine, organizationName is optional.\n */\nfunction zipOrganizations(\n orgIds?: string[],\n orgNames?: string[],\n): Array<{ organizationId: string; organizationName?: string }> | undefined {\n if (!orgIds || orgIds.length === 0) return undefined;\n return orgIds.map((organizationId, i) => ({\n organizationId,\n organizationName: orgNames?.[i],\n }));\n}\n\n/**\n * Print the permanent-private confirmation prompt and block until user confirms.\n * Honors `--yes` and non-interactive environments via `requireConfirm`.\n */\nasync function confirmPermanentPrivate(\n program: Command,\n summary: {\n accountId: string;\n title: string;\n languageCode: string;\n bundlePath: string;\n organizations?: Array<{ organizationId: string; organizationName?: string }>;\n },\n): Promise<void> {\n const orgSummary =\n summary.organizations && summary.organizations.length > 0\n ? summary.organizations\n .map((o) =>\n o.organizationName ? `${o.organizationId} (${o.organizationName})` : o.organizationId,\n )\n .join(\", \")\n : dim(\"none specified — add later via Play Console\");\n\n console.error(\"\");\n console.error(bold(yellow(\"⚠ This will publish a PRIVATE app to Managed Google Play.\")));\n console.error(\"\");\n console.error(\n \" Private apps created via this API are permanently private and cannot be converted\",\n );\n console.error(\n \" to public apps later. You can update versions, tracks, and listings via regular\",\n );\n console.error(\n \" GPC commands (gpc releases, gpc tracks, gpc listings) — but the app will never\",\n );\n console.error(\" appear on the public Play Store.\");\n console.error(\"\");\n console.error(` Developer account: ${summary.accountId}`);\n console.error(` Title: ${summary.title}`);\n console.error(` Language: ${summary.languageCode}`);\n console.error(` Bundle: ${summary.bundlePath}`);\n console.error(` Organizations: ${orgSummary}`);\n console.error(\"\");\n\n await requireConfirm(\"Continue with private app creation?\", program);\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerEnterpriseCommands(program: Command): void {\n const enterprise = program\n .command(\"enterprise\")\n .description(\"Manage private enterprise apps via Managed Google Play (Play Custom App API)\")\n .option(\"--account <id>\", \"Developer account ID (int64, from Play Console URL)\")\n .option(\"--org <id>\", \"[DEPRECATED] Alias for --account — will be removed in a future version\");\n\n // ----------------------------- create --------------------------------\n enterprise\n .command(\"create\")\n .description(\"Create a new private enterprise app\")\n .requiredOption(\"--title <title>\", \"App title (required)\")\n .requiredOption(\"--bundle <path>\", \"Path to AAB or APK file to upload (required)\")\n .option(\"--lang <code>\", \"Default listing language code (BCP 47)\", \"en_US\")\n .option(\n \"--org-id <id>\",\n \"Target enterprise organization ID (repeatable — use once per org)\",\n collect,\n )\n .option(\n \"--org-name <name>\",\n \"Human-readable organization name (repeatable, matched by position with --org-id)\",\n collect,\n )\n .action(async (options: CreateOptions) => {\n const { client, config } = await getClient();\n const parentOpts = enterprise.opts();\n const accountId = resolveAccountId(parentOpts);\n const format = getOutputFormat(program, config);\n\n const languageCode = options.lang ?? \"en_US\";\n const organizations = zipOrganizations(options.orgId, options.orgName);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"enterprise create\",\n action: \"create private custom app (dry-run)\",\n target: options.title,\n details: {\n accountId,\n bundlePath: options.bundle,\n title: options.title,\n languageCode,\n organizations: organizations ?? [],\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await confirmPermanentPrivate(program, {\n accountId,\n title: options.title,\n languageCode,\n bundlePath: options.bundle ?? \"\",\n organizations,\n });\n\n const result = await createEnterpriseApp(client, {\n accountId,\n bundlePath: options.bundle ?? \"\",\n title: options.title,\n languageCode,\n organizations,\n });\n\n console.log(formatOutput(result, format));\n });\n\n // ----------------------------- publish -------------------------------\n enterprise\n .command(\"publish <bundle>\")\n .description(\"One-shot publish: validate, create, and return a private custom app package name\")\n .requiredOption(\"--title <title>\", \"App title (required)\")\n .option(\"--lang <code>\", \"Default listing language code (BCP 47)\", \"en_US\")\n .option(\n \"--org-id <id>\",\n \"Target enterprise organization ID (repeatable — use once per org)\",\n collect,\n )\n .option(\n \"--org-name <name>\",\n \"Human-readable organization name (repeatable, matched by position with --org-id)\",\n collect,\n )\n .action(async (bundlePath: string, options: Omit<CreateOptions, \"bundle\">) => {\n const { client, config } = await getClient();\n const parentOpts = enterprise.opts();\n const accountId = resolveAccountId(parentOpts);\n const format = getOutputFormat(program, config);\n\n const languageCode = options.lang ?? \"en_US\";\n const organizations = zipOrganizations(options.orgId, options.orgName);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"enterprise publish\",\n action: \"publish private custom app (dry-run)\",\n target: options.title,\n details: {\n accountId,\n bundlePath,\n title: options.title,\n languageCode,\n organizations: organizations ?? [],\n },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n await confirmPermanentPrivate(program, {\n accountId,\n title: options.title,\n languageCode,\n bundlePath,\n organizations,\n });\n\n const result = await publishEnterpriseApp(client, {\n accountId,\n bundlePath,\n title: options.title,\n languageCode,\n organizations,\n });\n\n console.log(formatOutput(result, format));\n });\n\n // ------------------------------- list --------------------------------\n // Explicitly errors with a helpful message. The Play Custom App Publishing\n // API has no list method. Private apps appear in your regular developer\n // account — use `gpc apps list`.\n enterprise\n .command(\"list\")\n .description(\"[REMOVED] Use `gpc apps list` — private apps appear in your regular account\")\n .action(() => {\n console.error(\n [\n \"gpc enterprise list was removed in v0.9.56.\",\n \"\",\n \"Google's Play Custom App Publishing API has no list method — private apps\",\n \"created via this API appear in your regular developer account alongside\",\n \"public apps. Use `gpc apps list` to see them.\",\n ].join(\"\\n\"),\n );\n throw new Error(\"enterprise list is not supported by the Play Custom App Publishing API\");\n });\n}\n"],"mappings":"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","names":[]}
@@ -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.79";
12
+ const version = "0.9.80";
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-56LWTSEP.js.map
70
+ //# sourceMappingURL=feedback-CRWHXWAL.js.map