@gpc-cli/cli 0.9.45 → 0.9.47

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 (172) hide show
  1. package/README.md +36 -15
  2. package/dist/anomalies-V3AFS4LD.js +66 -0
  3. package/dist/anomalies-V3AFS4LD.js.map +1 -0
  4. package/dist/{apps-J2446UDA.js → apps-FKD3ZG5X.js} +31 -35
  5. package/dist/apps-FKD3ZG5X.js.map +1 -0
  6. package/dist/{audit-N2CRHWUN.js → audit-JASSHRWN.js} +47 -62
  7. package/dist/audit-JASSHRWN.js.map +1 -0
  8. package/dist/{auth-XGSTT5G5.js → auth-OTA3SV3J.js} +145 -103
  9. package/dist/auth-OTA3SV3J.js.map +1 -0
  10. package/dist/bin.js +6 -4
  11. package/dist/bin.js.map +1 -1
  12. package/dist/bundle-F7MUVC5J.js +204 -0
  13. package/dist/bundle-F7MUVC5J.js.map +1 -0
  14. package/dist/{cache-SLNFRTI2.js → cache-XKPLZYEB.js} +4 -5
  15. package/dist/cache-XKPLZYEB.js.map +1 -0
  16. package/dist/changelog-QLDFG5TV.js +48 -0
  17. package/dist/changelog-QLDFG5TV.js.map +1 -0
  18. package/dist/{chunk-4O4D5SGL.js → chunk-3SJ6OXCZ.js} +4 -5
  19. package/dist/chunk-3SJ6OXCZ.js.map +1 -0
  20. package/dist/{chunk-U6ZTQ34I.js → chunk-BCBXQC7J.js} +45 -11
  21. package/dist/chunk-BCBXQC7J.js.map +1 -0
  22. package/dist/{chunk-AA577WVQ.js → chunk-NQH4G7BI.js} +9 -3
  23. package/dist/chunk-NQH4G7BI.js.map +1 -0
  24. package/dist/chunk-SLNJEAMK.js +23 -0
  25. package/dist/chunk-SLNJEAMK.js.map +1 -0
  26. package/dist/{chunk-SEVX56VN.js → chunk-WWVURXVO.js} +56 -49
  27. package/dist/chunk-WWVURXVO.js.map +1 -0
  28. package/dist/{chunk-NV75I5VP.js → chunk-YFUBD2XB.js} +10 -8
  29. package/dist/chunk-YFUBD2XB.js.map +1 -0
  30. package/dist/{config-BUXPDN7N.js → config-NY3TZGVS.js} +8 -5
  31. package/dist/config-NY3TZGVS.js.map +1 -0
  32. package/dist/{data-safety-Q7FTCEWU.js → data-safety-AFMD6MYI.js} +12 -27
  33. package/dist/data-safety-AFMD6MYI.js.map +1 -0
  34. package/dist/{device-tiers-MIOQEXYY.js → device-tiers-AQAMUQXI.js} +23 -38
  35. package/dist/device-tiers-AQAMUQXI.js.map +1 -0
  36. package/dist/diff-6EO4ID6W.js +91 -0
  37. package/dist/diff-6EO4ID6W.js.map +1 -0
  38. package/dist/{docs-7DUXIKA3.js → docs-4D2SJ4LY.js} +4 -3
  39. package/dist/docs-4D2SJ4LY.js.map +1 -0
  40. package/dist/doctor-QCCWG6Y3.js +708 -0
  41. package/dist/doctor-QCCWG6Y3.js.map +1 -0
  42. package/dist/{enterprise-7THXNBTC.js → enterprise-7PWXMSUN.js} +11 -21
  43. package/dist/enterprise-7PWXMSUN.js.map +1 -0
  44. package/dist/{external-transactions-2GWIMUVM.js → external-transactions-LCZALS3V.js} +12 -28
  45. package/dist/external-transactions-LCZALS3V.js.map +1 -0
  46. package/dist/{feedback-DPTO6DUT.js → feedback-CET2X67K.js} +4 -4
  47. package/dist/{games-BT777WUO.js → games-ZSNGEI7A.js} +17 -32
  48. package/dist/games-ZSNGEI7A.js.map +1 -0
  49. package/dist/{generated-apks-RJWTIX7L.js → generated-apks-RX2IUWSF.js} +30 -38
  50. package/dist/generated-apks-RX2IUWSF.js.map +1 -0
  51. package/dist/{grants-TKQJ3IER.js → grants-EBPECI26.js} +22 -40
  52. package/dist/grants-EBPECI26.js.map +1 -0
  53. package/dist/{iap-ICAEQLK5.js → iap-OUI5YYN4.js} +30 -51
  54. package/dist/iap-OUI5YYN4.js.map +1 -0
  55. package/dist/index.js +1 -1
  56. package/dist/{init-JZ2THPMS.js → init-WSTQTJOD.js} +5 -4
  57. package/dist/init-WSTQTJOD.js.map +1 -0
  58. package/dist/{install-skills-OV4HVANW.js → install-skills-6QDUXI5F.js} +5 -6
  59. package/dist/{install-skills-OV4HVANW.js.map → install-skills-6QDUXI5F.js.map} +1 -1
  60. package/dist/{internal-sharing-3U2XFHA4.js → internal-sharing-ONNIWIAT.js} +3 -4
  61. package/dist/{internal-sharing-3U2XFHA4.js.map → internal-sharing-ONNIWIAT.js.map} +1 -1
  62. package/dist/{listings-77HZW4S5.js → listings-7SGQ4SRX.js} +118 -157
  63. package/dist/listings-7SGQ4SRX.js.map +1 -0
  64. package/dist/migrate-ZQCJGQQS.js +138 -0
  65. package/dist/migrate-ZQCJGQQS.js.map +1 -0
  66. package/dist/{one-time-products-LHZAXQES.js → one-time-products-MGZTU7OM.js} +65 -120
  67. package/dist/one-time-products-MGZTU7OM.js.map +1 -0
  68. package/dist/{preflight-H3HEBYQW.js → preflight-N7ZRG2JI.js} +58 -55
  69. package/dist/preflight-N7ZRG2JI.js.map +1 -0
  70. package/dist/{pricing-XQSDTTK5.js → pricing-JJZFICFL.js} +8 -8
  71. package/dist/{pricing-XQSDTTK5.js.map → pricing-JJZFICFL.js.map} +1 -1
  72. package/dist/{prompt-BSV22CQZ.js → prompt-GXC2JSLA.js} +2 -2
  73. package/dist/{publish-Q5ZKEKZ5.js → publish-JPTI4EBT.js} +34 -30
  74. package/dist/publish-JPTI4EBT.js.map +1 -0
  75. package/dist/{purchase-options-CKRN4VIW.js → purchase-options-KFWW4JW2.js} +16 -11
  76. package/dist/purchase-options-KFWW4JW2.js.map +1 -0
  77. package/dist/{purchases-43AKV6HG.js → purchases-Z3QBM3UO.js} +121 -194
  78. package/dist/purchases-Z3QBM3UO.js.map +1 -0
  79. package/dist/{quickstart-4HB62YEL.js → quickstart-Z5Y3FYJU.js} +5 -3
  80. package/dist/quickstart-Z5Y3FYJU.js.map +1 -0
  81. package/dist/{quota-UHIQQYOY.js → quota-MZRWYJGR.js} +5 -15
  82. package/dist/quota-MZRWYJGR.js.map +1 -0
  83. package/dist/{recovery-5EV2R476.js → recovery-YE3Z7NIN.js} +32 -61
  84. package/dist/recovery-YE3Z7NIN.js.map +1 -0
  85. package/dist/{releases-C2WC2K4E.js → releases-276W3BR7.js} +188 -187
  86. package/dist/releases-276W3BR7.js.map +1 -0
  87. package/dist/{reports-2YX3RDOS.js → reports-CIB2T3XT.js} +19 -21
  88. package/dist/reports-CIB2T3XT.js.map +1 -0
  89. package/dist/reviews-YCBBM656.js +199 -0
  90. package/dist/reviews-YCBBM656.js.map +1 -0
  91. package/dist/rtdn-LID2B7XZ.js +87 -0
  92. package/dist/rtdn-LID2B7XZ.js.map +1 -0
  93. package/dist/{status-WHGLODGV.js → status-6LH5W4FU.js} +105 -83
  94. package/dist/status-6LH5W4FU.js.map +1 -0
  95. package/dist/{subscriptions-CI3JH3VQ.js → subscriptions-DZP3Y7O7.js} +142 -232
  96. package/dist/subscriptions-DZP3Y7O7.js.map +1 -0
  97. package/dist/{testers-NZOFA3EF.js → testers-LSMBXCA2.js} +24 -44
  98. package/dist/testers-LSMBXCA2.js.map +1 -0
  99. package/dist/tracks-YHMO2A6B.js +98 -0
  100. package/dist/tracks-YHMO2A6B.js.map +1 -0
  101. package/dist/{train-CJJVLY4B.js → train-MDD2EBHS.js} +35 -55
  102. package/dist/train-MDD2EBHS.js.map +1 -0
  103. package/dist/{update-NAK6CMUX.js → update-XAO5EZHC.js} +30 -15
  104. package/dist/update-XAO5EZHC.js.map +1 -0
  105. package/dist/{users-2YTC4Q36.js → users-UKG7VIQH.js} +45 -67
  106. package/dist/users-UKG7VIQH.js.map +1 -0
  107. package/dist/{validate-UOVTM6L3.js → validate-QIYSA3N7.js} +8 -10
  108. package/dist/validate-QIYSA3N7.js.map +1 -0
  109. package/dist/{version-N64UBW7A.js → version-R3P4NHCF.js} +4 -4
  110. package/dist/{vitals-A4CS4MSS.js → vitals-PJEQUUAK.js} +174 -165
  111. package/dist/vitals-PJEQUUAK.js.map +1 -0
  112. package/package.json +6 -6
  113. package/dist/anomalies-NU2IN2GJ.js +0 -54
  114. package/dist/anomalies-NU2IN2GJ.js.map +0 -1
  115. package/dist/apps-J2446UDA.js.map +0 -1
  116. package/dist/audit-N2CRHWUN.js.map +0 -1
  117. package/dist/auth-XGSTT5G5.js.map +0 -1
  118. package/dist/bundle-F43TD2BQ.js +0 -218
  119. package/dist/bundle-F43TD2BQ.js.map +0 -1
  120. package/dist/cache-SLNFRTI2.js.map +0 -1
  121. package/dist/changelog-ZYD6W5IV.js +0 -53
  122. package/dist/changelog-ZYD6W5IV.js.map +0 -1
  123. package/dist/chunk-4O4D5SGL.js.map +0 -1
  124. package/dist/chunk-AA577WVQ.js.map +0 -1
  125. package/dist/chunk-FWKYRLKY.js +0 -19
  126. package/dist/chunk-FWKYRLKY.js.map +0 -1
  127. package/dist/chunk-NV75I5VP.js.map +0 -1
  128. package/dist/chunk-SEVX56VN.js.map +0 -1
  129. package/dist/chunk-U6ZTQ34I.js.map +0 -1
  130. package/dist/config-BUXPDN7N.js.map +0 -1
  131. package/dist/data-safety-Q7FTCEWU.js.map +0 -1
  132. package/dist/device-tiers-MIOQEXYY.js.map +0 -1
  133. package/dist/diff-V77SMKAQ.js +0 -96
  134. package/dist/diff-V77SMKAQ.js.map +0 -1
  135. package/dist/docs-7DUXIKA3.js.map +0 -1
  136. package/dist/doctor-3Z4ARPM2.js +0 -372
  137. package/dist/doctor-3Z4ARPM2.js.map +0 -1
  138. package/dist/enterprise-7THXNBTC.js.map +0 -1
  139. package/dist/external-transactions-2GWIMUVM.js.map +0 -1
  140. package/dist/games-BT777WUO.js.map +0 -1
  141. package/dist/generated-apks-RJWTIX7L.js.map +0 -1
  142. package/dist/grants-TKQJ3IER.js.map +0 -1
  143. package/dist/iap-ICAEQLK5.js.map +0 -1
  144. package/dist/init-JZ2THPMS.js.map +0 -1
  145. package/dist/listings-77HZW4S5.js.map +0 -1
  146. package/dist/migrate-SQT6RD6T.js +0 -143
  147. package/dist/migrate-SQT6RD6T.js.map +0 -1
  148. package/dist/one-time-products-LHZAXQES.js.map +0 -1
  149. package/dist/preflight-H3HEBYQW.js.map +0 -1
  150. package/dist/publish-Q5ZKEKZ5.js.map +0 -1
  151. package/dist/purchase-options-CKRN4VIW.js.map +0 -1
  152. package/dist/purchases-43AKV6HG.js.map +0 -1
  153. package/dist/quickstart-4HB62YEL.js.map +0 -1
  154. package/dist/quota-UHIQQYOY.js.map +0 -1
  155. package/dist/recovery-5EV2R476.js.map +0 -1
  156. package/dist/releases-C2WC2K4E.js.map +0 -1
  157. package/dist/reports-2YX3RDOS.js.map +0 -1
  158. package/dist/reviews-2CWOI5CV.js +0 -213
  159. package/dist/reviews-2CWOI5CV.js.map +0 -1
  160. package/dist/status-WHGLODGV.js.map +0 -1
  161. package/dist/subscriptions-CI3JH3VQ.js.map +0 -1
  162. package/dist/testers-NZOFA3EF.js.map +0 -1
  163. package/dist/tracks-NERFFEDT.js +0 -107
  164. package/dist/tracks-NERFFEDT.js.map +0 -1
  165. package/dist/train-CJJVLY4B.js.map +0 -1
  166. package/dist/update-NAK6CMUX.js.map +0 -1
  167. package/dist/users-2YTC4Q36.js.map +0 -1
  168. package/dist/validate-UOVTM6L3.js.map +0 -1
  169. package/dist/vitals-A4CS4MSS.js.map +0 -1
  170. /package/dist/{feedback-DPTO6DUT.js.map → feedback-CET2X67K.js.map} +0 -0
  171. /package/dist/{prompt-BSV22CQZ.js.map → prompt-GXC2JSLA.js.map} +0 -0
  172. /package/dist/{version-N64UBW7A.js.map → version-R3P4NHCF.js.map} +0 -0
@@ -6,15 +6,31 @@ import {
6
6
  // src/commands/auth.ts
7
7
  import { createInterface } from "readline";
8
8
  import { access } from "fs/promises";
9
+ import { resolve } from "path";
9
10
  import { resolveAuth, loadServiceAccountKey, clearTokenCache, AuthError } from "@gpc-cli/auth";
10
- import { loadConfig, getCacheDir } from "@gpc-cli/config";
11
+ import { loadConfig, getCacheDir, deleteConfigValue, setConfigValue } from "@gpc-cli/config";
11
12
  import { formatOutput } from "@gpc-cli/core";
12
13
  async function askQuestion(rl, question) {
13
- return new Promise((resolve) => {
14
- rl.question(question, (answer) => resolve(answer.trim()));
14
+ return new Promise((resolve2) => {
15
+ rl.question(question, (answer) => resolve2(answer.trim()));
15
16
  });
16
17
  }
17
- async function runLoginWizard() {
18
+ function toAbsolutePath(pathStr) {
19
+ return resolve(pathStr);
20
+ }
21
+ async function verifyToken(serviceAccountPath) {
22
+ try {
23
+ const client = await resolveAuth({ serviceAccountPath });
24
+ const email = client.getClientEmail();
25
+ await client.getAccessToken();
26
+ return { email, ok: true };
27
+ } catch (err) {
28
+ const email = "unknown";
29
+ const msg = err instanceof Error ? err.message : String(err);
30
+ return { email, ok: false, error: msg };
31
+ }
32
+ }
33
+ async function runLoginWizard(program) {
18
34
  const rl = createInterface({ input: process.stdin, output: process.stdout });
19
35
  try {
20
36
  console.log("\nGPC Authentication Setup");
@@ -25,11 +41,10 @@ async function runLoginWizard() {
25
41
  const method = await askQuestion(rl, "\nSelect method [1]: ");
26
42
  const useAdc = method === "2";
27
43
  if (useAdc) {
28
- const { resolveAuth: ra } = await import("@gpc-cli/auth");
29
- const client = await ra();
30
- console.log(`
31
- Authenticated via Application Default Credentials`);
32
- console.log(`Account: ${client.getClientEmail()}`);
44
+ const client = await resolveAuth();
45
+ const email = client.getClientEmail();
46
+ await client.getAccessToken();
47
+ outputLoginResult(program, { account: email, method: "adc", verified: true });
33
48
  return;
34
49
  }
35
50
  let saPath = "";
@@ -41,7 +56,7 @@ Authenticated via Application Default Credentials`);
41
56
  }
42
57
  try {
43
58
  await access(input);
44
- saPath = input;
59
+ saPath = toAbsolutePath(input);
45
60
  } catch {
46
61
  console.log(` File not found: ${input}`);
47
62
  }
@@ -51,84 +66,122 @@ Authenticated via Application Default Credentials`);
51
66
  rl,
52
67
  "Default package name (optional, e.g. com.example.app): "
53
68
  );
54
- const { loadServiceAccountKey: loadKey } = await import("@gpc-cli/auth");
55
- const key = await loadKey(saPath);
69
+ const key = await loadServiceAccountKey(saPath);
56
70
  if (profileName) {
57
71
  const { setProfileConfig } = await import("@gpc-cli/config");
58
72
  await setProfileConfig(profileName, {
59
73
  auth: { serviceAccount: saPath },
60
74
  ...packageName && { app: packageName }
61
75
  });
62
- console.log(`
63
- Profile "${profileName}" configured with ${key.client_email}`);
64
76
  } else {
65
- const { setConfigValue } = await import("@gpc-cli/config");
66
77
  await setConfigValue("auth.serviceAccount", saPath);
67
78
  if (packageName) await setConfigValue("app", packageName);
68
- console.log(`
69
- Authenticated as ${key.client_email}`);
70
79
  }
71
- console.log(`Project: ${key.project_id}`);
72
- console.log("\nRun 'gpc doctor' to verify your setup.");
80
+ const verification = await verifyToken(saPath);
81
+ outputLoginResult(program, {
82
+ account: key.client_email,
83
+ project: key.project_id,
84
+ method: "service-account",
85
+ profile: profileName || void 0,
86
+ verified: verification.ok,
87
+ verifyError: verification.error
88
+ });
73
89
  } finally {
74
90
  rl.close();
75
91
  }
76
92
  }
93
+ function outputLoginResult(program, result) {
94
+ const parentOpts = program.opts() ?? {};
95
+ const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
96
+ if (jsonMode) {
97
+ console.log(
98
+ JSON.stringify({
99
+ success: true,
100
+ account: result.account,
101
+ project: result.project,
102
+ method: result.method,
103
+ profile: result.profile,
104
+ verified: result.verified,
105
+ ...result.verifyError && { verifyError: result.verifyError }
106
+ })
107
+ );
108
+ return;
109
+ }
110
+ if (result.profile) {
111
+ console.log(`
112
+ Profile "${result.profile}" configured with ${result.account}`);
113
+ } else if (result.method === "adc") {
114
+ console.log(`
115
+ Authenticated via Application Default Credentials`);
116
+ console.log(`Account: ${result.account}`);
117
+ } else {
118
+ console.log(`
119
+ Authenticated as ${result.account}`);
120
+ }
121
+ if (result.project) console.log(`Project: ${result.project}`);
122
+ if (result.verified) {
123
+ console.log("Verified: token acquired successfully");
124
+ } else if (result.verifyError) {
125
+ console.log(`Warning: token verification failed: ${result.verifyError}`);
126
+ console.log("Credentials saved, but check your setup with: gpc doctor");
127
+ }
128
+ if (!result.verifyError) {
129
+ console.log("\nRun 'gpc doctor' to verify your full setup.");
130
+ }
131
+ }
77
132
  function registerAuthCommands(program) {
78
133
  const auth = program.command("auth").description("Manage authentication");
79
134
  auth.command("login").description("Authenticate with Google Play Developer API").option("--service-account <path>", "Path to service account JSON key file").option("--adc", "Use Application Default Credentials").option("--profile <name>", "Store credentials under a named profile").action(async (options) => {
80
- try {
81
- if (options.serviceAccount) {
82
- const key = await loadServiceAccountKey(options.serviceAccount);
83
- if (options.profile) {
84
- const { setProfileConfig } = await import("@gpc-cli/config");
85
- await setProfileConfig(options.profile, {
86
- auth: { serviceAccount: options.serviceAccount }
87
- });
88
- console.log(`Profile "${options.profile}" configured with ${key.client_email}`);
89
- } else {
90
- const { setConfigValue } = await import("@gpc-cli/config");
91
- await setConfigValue("auth.serviceAccount", options.serviceAccount);
92
- console.log(`Authenticated as ${key.client_email}`);
93
- }
94
- console.log(`Project: ${key.project_id}`);
95
- } else if (options.adc) {
96
- const client = await resolveAuth();
97
- console.log(`Authenticated via Application Default Credentials`);
98
- console.log(`Account: ${client.getClientEmail()}`);
135
+ if (options.serviceAccount) {
136
+ const absolutePath = toAbsolutePath(options.serviceAccount);
137
+ const key = await loadServiceAccountKey(absolutePath);
138
+ if (options.profile) {
139
+ const { setProfileConfig } = await import("@gpc-cli/config");
140
+ await setProfileConfig(options.profile, {
141
+ auth: { serviceAccount: absolutePath }
142
+ });
99
143
  } else {
100
- const opts = program.opts();
101
- const interactive = opts["interactive"] !== false && opts["ci"] !== true && process.stdin.isTTY;
102
- if (interactive) {
103
- await runLoginWizard();
104
- } else {
105
- console.log("Usage: gpc auth login --service-account <path>");
106
- console.log("");
107
- console.log("Authentication methods:");
108
- console.log(" --service-account <path> Service account JSON key file");
109
- console.log(" --adc Application Default Credentials");
110
- console.log("");
111
- console.log("Options:");
112
- console.log(" --profile <name> Store under a named profile");
113
- }
144
+ await setConfigValue("auth.serviceAccount", absolutePath);
114
145
  }
115
- } catch (error) {
116
- if (error instanceof AuthError) {
117
- console.error(`Error: ${error.message}`);
118
- if (error.suggestion) console.error(`Suggestion: ${error.suggestion}`);
119
- process.exit(3);
146
+ const verification = await verifyToken(absolutePath);
147
+ outputLoginResult(program, {
148
+ account: key.client_email,
149
+ project: key.project_id,
150
+ method: "service-account",
151
+ profile: options.profile,
152
+ verified: verification.ok,
153
+ verifyError: verification.error
154
+ });
155
+ } else if (options.adc) {
156
+ const client = await resolveAuth();
157
+ const email = client.getClientEmail();
158
+ await client.getAccessToken();
159
+ outputLoginResult(program, { account: email, method: "adc", verified: true });
160
+ } else {
161
+ const opts = program.opts();
162
+ const interactive = opts["interactive"] !== false && opts["ci"] !== true && process.stdin.isTTY;
163
+ if (interactive) {
164
+ await runLoginWizard(program);
165
+ } else {
166
+ console.log("Usage: gpc auth login --service-account <path>");
167
+ console.log("");
168
+ console.log("Authentication methods:");
169
+ console.log(" --service-account <path> Service account JSON key file");
170
+ console.log(" --adc Application Default Credentials");
171
+ console.log("");
172
+ console.log("Options:");
173
+ console.log(" --profile <name> Store under a named profile");
120
174
  }
121
- throw error;
122
175
  }
123
176
  });
124
177
  auth.command("status").description("Show current authentication status").action(async () => {
125
178
  const config = await loadConfig();
179
+ const format = getOutputFormat(program, config);
126
180
  try {
127
181
  const client = await resolveAuth({
128
182
  serviceAccountPath: config.auth?.serviceAccount,
129
183
  cachePath: getCacheDir()
130
184
  });
131
- const format = getOutputFormat(program, config);
132
185
  const data = {
133
186
  authenticated: true,
134
187
  account: client.getClientEmail(),
@@ -138,67 +191,56 @@ function registerAuthCommands(program) {
138
191
  console.log(formatOutput(data, format));
139
192
  } catch (error) {
140
193
  if (error instanceof AuthError) {
141
- const format = getOutputFormat(program, config);
142
194
  const data = {
143
195
  authenticated: false,
144
196
  error: error.message,
145
197
  suggestion: error.suggestion
146
198
  };
147
199
  console.log(formatOutput(data, format));
148
- process.exit(3);
149
200
  }
150
201
  throw error;
151
202
  }
152
203
  });
153
- auth.command("logout").description("Clear stored credentials and token cache").action(async () => {
154
- const { setConfigValue } = await import("@gpc-cli/config");
155
- await setConfigValue("auth.serviceAccount", "");
204
+ auth.command("logout").description("Clear stored credentials and token cache").option("--profile <name>", "Clear credentials for a specific profile").action(async (options) => {
205
+ if (options.profile) {
206
+ const { deleteProfile } = await import("@gpc-cli/config");
207
+ const deleted = await deleteProfile(options.profile);
208
+ if (deleted) {
209
+ console.log(`Profile "${options.profile}" removed.`);
210
+ } else {
211
+ console.log(`Profile "${options.profile}" not found.`);
212
+ }
213
+ } else {
214
+ await deleteConfigValue("auth.serviceAccount");
215
+ console.log("Credentials cleared.");
216
+ }
156
217
  await clearTokenCache(getCacheDir());
157
- console.log("Credentials and token cache cleared.");
218
+ console.log("Token cache cleared.");
158
219
  });
159
220
  auth.command("whoami").description("Show current authenticated identity").action(async () => {
160
- try {
161
- const config = await loadConfig();
162
- const client = await resolveAuth({
163
- serviceAccountPath: config.auth?.serviceAccount,
164
- cachePath: getCacheDir()
165
- });
166
- console.log(client.getClientEmail());
167
- } catch {
168
- console.error("Not authenticated. Run: gpc auth login");
169
- process.exit(3);
170
- }
221
+ const config = await loadConfig();
222
+ const client = await resolveAuth({
223
+ serviceAccountPath: config.auth?.serviceAccount,
224
+ cachePath: getCacheDir()
225
+ });
226
+ console.log(client.getClientEmail());
171
227
  });
172
228
  auth.command("switch <profile>").description("Switch to a named profile").action(async (profile) => {
173
- try {
174
- const config = await loadConfig({ profile });
175
- const { setConfigValue } = await import("@gpc-cli/config");
176
- await setConfigValue("profile", profile);
177
- console.log(`Switched to profile "${profile}"`);
178
- if (config.auth?.serviceAccount) {
179
- console.log(`Service account: ${config.auth.serviceAccount}`);
180
- }
181
- } catch (error) {
182
- console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
183
- process.exit(2);
229
+ const config = await loadConfig({ profile });
230
+ await setConfigValue("profile", profile);
231
+ console.log(`Switched to profile "${profile}"`);
232
+ if (config.auth?.serviceAccount) {
233
+ console.log(`Service account: ${config.auth.serviceAccount}`);
184
234
  }
185
235
  });
186
236
  auth.command("token").description("Print the current access token (useful for manual API calls)").action(async () => {
187
- try {
188
- const config = await loadConfig();
189
- const authClient = await resolveAuth({
190
- serviceAccountPath: config.auth?.serviceAccount,
191
- cachePath: getCacheDir()
192
- });
193
- const token = await authClient.getAccessToken();
194
- console.log(token);
195
- } catch (error) {
196
- if (error instanceof AuthError) {
197
- console.error(`Error: ${error.message}`);
198
- process.exit(3);
199
- }
200
- throw error;
201
- }
237
+ const config = await loadConfig();
238
+ const authClient = await resolveAuth({
239
+ serviceAccountPath: config.auth?.serviceAccount,
240
+ cachePath: getCacheDir()
241
+ });
242
+ const token = await authClient.getAccessToken();
243
+ console.log(token);
202
244
  });
203
245
  auth.command("setup-gcp").description("Step-by-step guide to create a Google Cloud service account").action(() => {
204
246
  console.log("\nGPC \u2014 Google Cloud Service Account Setup");
@@ -246,4 +288,4 @@ function registerAuthCommands(program) {
246
288
  export {
247
289
  registerAuthCommands
248
290
  };
249
- //# sourceMappingURL=auth-XGSTT5G5.js.map
291
+ //# sourceMappingURL=auth-OTA3SV3J.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 { 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(serviceAccountPath?: string): 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(\"\\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 // 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 .action(() => {\n console.log(\"\\nGPC \\u2014 Google Cloud Service Account Setup\");\n console.log(\"\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\");\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(\" \\u2022 Click your new service account \\u2192 Keys \\u2192 Add Key \\u2192 Create new key \\u2192 JSON\");\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 console.log(\"\\nStep 6: Authenticate\");\n console.log(\" gpc auth login --service-account ~/gpc-service-account.json\");\n console.log(\"\\nStep 7: Verify\");\n console.log(\" gpc doctor\");\n console.log(\"\\nSee full docs: https://yasserstudio.github.io/gpc/guide/authentication\");\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"]}
package/dist/bin.js CHANGED
@@ -3,11 +3,11 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-SEVX56VN.js";
6
+ } from "./chunk-WWVURXVO.js";
7
7
  import {
8
8
  checkForUpdate,
9
9
  formatUpdateNotification
10
- } from "./chunk-4O4D5SGL.js";
10
+ } from "./chunk-3SJ6OXCZ.js";
11
11
 
12
12
  // src/bin.ts
13
13
  import { existsSync } from "fs";
@@ -39,12 +39,14 @@ if (process.argv.includes("--no-color")) {
39
39
  }
40
40
  var _isJsonMode = process.argv.includes("--json") || process.argv.includes("-j") || process.argv.includes("--ci") || process.argv.includes("--output") && process.argv[process.argv.indexOf("--output") + 1] === "json" || process.argv.includes("-o") && process.argv[process.argv.indexOf("-o") + 1] === "json";
41
41
  var _isQuiet = process.argv.includes("--quiet") || process.argv.includes("-q");
42
- if (!_isJsonMode && !_isQuiet && !existsSync(getUserConfigPath())) {
42
+ var _setupCommands = /* @__PURE__ */ new Set(["config", "auth", "quickstart", "doctor", "init", "setup-gcp"]);
43
+ var _isSetupCommand = _setupCommands.has(process.argv[2] ?? "");
44
+ if (!_isJsonMode && !_isQuiet && !_isSetupCommand && !existsSync(getUserConfigPath())) {
43
45
  process.stderr.write("\u2726 First time? Run gpc config init to get set up.\n\n");
44
46
  }
45
47
  await setupNetworking();
46
48
  initAudit(getConfigDir());
47
- var currentVersion = "0.9.45";
49
+ var currentVersion = "0.9.47";
48
50
  var isUpdateCommand = process.argv[2] === "update";
49
51
  var updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);
50
52
  if (process.argv.includes("--ci")) {
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/networking.ts"],"sourcesContent":["if (process.env[\"GPC_NO_COLOR\"] === \"1\") process.env[\"NO_COLOR\"] = \"1\";\nif (process.argv.includes(\"--no-color\")) {\n process.env[\"NO_COLOR\"] = \"1\";\n}\nimport { existsSync } from \"node:fs\";\nimport { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig, getUserConfigPath } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\n// First-run banner\nconst _isJsonMode =\n process.argv.includes(\"--json\") ||\n process.argv.includes(\"-j\") ||\n process.argv.includes(\"--ci\") ||\n (process.argv.includes(\"--output\") &&\n process.argv[process.argv.indexOf(\"--output\") + 1] === \"json\") ||\n (process.argv.includes(\"-o\") && process.argv[process.argv.indexOf(\"-o\") + 1] === \"json\");\nconst _isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n\nif (!_isJsonMode && !_isQuiet && !existsSync(getUserConfigPath())) {\n process.stderr.write(\" First time? Run gpc config init to get set up.\\n\\n\");\n}\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Skip passive update check when the user is explicitly running `gpc update` —\n// that command does its own check against the GitHub Releases API.\nconst isUpdateCommand = process.argv[2] === \"update\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\n// GPC_DEBUG=1 enables verbose mode without mutating process.argv\nif (process.env[\"GPC_DEBUG\"] === \"1\") {\n program.setOptionValueWithSource(\"verbose\", true, \"env\");\n}\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv\n .slice(2)\n .filter((a) => !a.startsWith(\"--notify\"))\n .join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\n// isUpdateCommand is declared above — update check was skipped for this command\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n !isUpdateCommand &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n","/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAIA,SAAS,kBAAkB;;;ACA3B,eAAsB,kBAAiC;AAErD,QAAM,SAAS,QAAQ,IAAI,aAAa;AACxC,MAAI,UAAU,CAAC,QAAQ,IAAI,qBAAqB,GAAG;AACjD,YAAQ,IAAI,qBAAqB,IAAI;AAAA,EACvC;AAGA,MAAI,QAAQ,IAAI,cAAc,MAAM,IAAK;AAEzC,QAAM,WACJ,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,YAAY,KACxB,QAAQ,IAAI,YAAY;AAC1B,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,EAAE,YAAY,oBAAoB,IAAI,MAAM,OAAO,QAAQ;AACjE,0BAAoB,IAAI,WAAW,QAAQ,CAAC;AAAA,IAC9C,QAAQ;AACN,cAAQ,MAAM,2EAA2E;AAAA,IAC3F;AAAA,EACF;AACF;;;ADnBA,SAAS,WAAW,mBAAmB;AAEvC,SAAS,cAAc,YAAY,yBAAyB;AAX5D,IAAI,QAAQ,IAAI,cAAc,MAAM,IAAK,SAAQ,IAAI,UAAU,IAAI;AACnE,IAAI,QAAQ,KAAK,SAAS,YAAY,GAAG;AACvC,UAAQ,IAAI,UAAU,IAAI;AAC5B;AAYA,IAAM,cACJ,QAAQ,KAAK,SAAS,QAAQ,KAC9B,QAAQ,KAAK,SAAS,IAAI,KAC1B,QAAQ,KAAK,SAAS,MAAM,KAC3B,QAAQ,KAAK,SAAS,UAAU,KAC/B,QAAQ,KAAK,QAAQ,KAAK,QAAQ,UAAU,IAAI,CAAC,MAAM,UACxD,QAAQ,KAAK,SAAS,IAAI,KAAK,QAAQ,KAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM;AACnF,IAAM,WAAW,QAAQ,KAAK,SAAS,SAAS,KAAK,QAAQ,KAAK,SAAS,IAAI;AAE/E,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,WAAW,kBAAkB,CAAC,GAAG;AACjE,UAAQ,OAAO,MAAM,2DAAsD;AAC7E;AAEA,MAAM,gBAAgB;AACtB,UAAU,aAAa,CAAC;AAExB,IAAM,iBAAiB;AAIvB,IAAM,kBAAkB,QAAQ,KAAK,CAAC,MAAM;AAG5C,IAAM,qBAAqB,kBAAkB,QAAQ,QAAQ,IAAI,IAAI,eAAe,cAAc;AAGlG,IAAI,QAAQ,KAAK,SAAS,MAAM,GAAG;AACjC,UAAQ,IAAI,IAAI,IAAI;AAEpB,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,kBAAkB,GAAG;AAC9C,YAAQ,KAAK,KAAK,kBAAkB;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,YAAY,GAAG;AACxC,YAAQ,KAAK,KAAK,YAAY;AAAA,EAChC;AACF;AACA,IAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,KAAK,SAAS,IAAI,GAAG;AAClE,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACF;AAEA,IAAM,gBAAgB,MAAM,YAAY;AACxC,IAAM,UAAU,MAAM,cAAc,aAAa;AAGjD,IAAI,QAAQ,IAAI,WAAW,MAAM,KAAK;AACpC,UAAQ,yBAAyB,WAAW,MAAM,KAAK;AACzD;AAEA,IAAM,YAAY,KAAK,IAAI;AAC3B,IAAI,iBAAiB;AACrB,IAAI;AAEJ,MAAM,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,UAAmB;AAC/D,mBAAiB;AACjB,iBAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,QAAM,WAAW,eAAe,KAAK;AACrC,UAAQ,KAAK,QAAQ;AACvB,CAAC;AAGD,IAAM,YAAY,QAAQ,KAAK,EAAE,QAAQ;AACzC,IAAI,cAAc,UAAa,cAAc,OAAO;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,WAAW;AAChC,QAAI,OAAO,UAAU;AACnB,YAAM,cAAc,QAAQ,KACzB,MAAM,CAAC,EACP,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,UAAU,CAAC,EACvC,KAAK,GAAG;AACX,YAAM,UAA0B;AAAA,QAC9B,SAAS,eAAe;AAAA,QACxB,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,KAAK,QAAQ,KAAK,EAAE,KAAK;AAAA,QACzB,OAAO;AAAA,MACT;AAEA,YAAM,SAAS,OAAO,cAAc,WAAW,YAAY;AAE3D,kBAAY,OAAO,UAAU,SAAS,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC9D;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAIA,IAAI;AACF,QAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,IAChC;AAAA,IACA,IAAI,QAAc,CAAC,YAAY,WAAW,MAAM,QAAQ,IAAI,GAAG,GAAI,CAAC;AAAA,EACtE,CAAC;AAED,MACE,UACA,OAAO,mBACP,CAAC,mBACD,QAAQ,OAAO,SACf,CAAC,QAAQ,KAAK,SAAS,QAAQ,KAC/B,QAAQ,KAAK,EAAE,QAAQ,MAAM,QAC7B;AACA,YAAQ,OAAO,MAAM;AAAA,EAAK,yBAAyB,MAAM,CAAC;AAAA,CAAI;AAAA,EAChE;AACF,QAAQ;AAER;","names":[]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/networking.ts"],"sourcesContent":["if (process.env[\"GPC_NO_COLOR\"] === \"1\") process.env[\"NO_COLOR\"] = \"1\";\nif (process.argv.includes(\"--no-color\")) {\n process.env[\"NO_COLOR\"] = \"1\";\n}\nimport { existsSync } from \"node:fs\";\nimport { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig, getUserConfigPath } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\n// First-run banner\nconst _isJsonMode =\n process.argv.includes(\"--json\") ||\n process.argv.includes(\"-j\") ||\n process.argv.includes(\"--ci\") ||\n (process.argv.includes(\"--output\") &&\n process.argv[process.argv.indexOf(\"--output\") + 1] === \"json\") ||\n (process.argv.includes(\"-o\") && process.argv[process.argv.indexOf(\"-o\") + 1] === \"json\");\nconst _isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n\nconst _setupCommands = new Set([\"config\", \"auth\", \"quickstart\", \"doctor\", \"init\", \"setup-gcp\"]);\nconst _isSetupCommand = _setupCommands.has(process.argv[2] ?? \"\");\n\nif (!_isJsonMode && !_isQuiet && !_isSetupCommand && !existsSync(getUserConfigPath())) {\n process.stderr.write(\"\\u2726 First time? Run gpc config init to get set up.\\n\\n\");\n}\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Skip passive update check when the user is explicitly running `gpc update` —\n// that command does its own check against the GitHub Releases API.\nconst isUpdateCommand = process.argv[2] === \"update\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\n// GPC_DEBUG=1 enables verbose mode without mutating process.argv\nif (process.env[\"GPC_DEBUG\"] === \"1\") {\n program.setOptionValueWithSource(\"verbose\", true, \"env\");\n}\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv\n .slice(2)\n .filter((a) => !a.startsWith(\"--notify\"))\n .join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\n// isUpdateCommand is declared above — update check was skipped for this command\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n !isUpdateCommand &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n","/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAIA,SAAS,kBAAkB;;;ACA3B,eAAsB,kBAAiC;AAErD,QAAM,SAAS,QAAQ,IAAI,aAAa;AACxC,MAAI,UAAU,CAAC,QAAQ,IAAI,qBAAqB,GAAG;AACjD,YAAQ,IAAI,qBAAqB,IAAI;AAAA,EACvC;AAGA,MAAI,QAAQ,IAAI,cAAc,MAAM,IAAK;AAEzC,QAAM,WACJ,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,aAAa,KACzB,QAAQ,IAAI,YAAY,KACxB,QAAQ,IAAI,YAAY;AAC1B,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,EAAE,YAAY,oBAAoB,IAAI,MAAM,OAAO,QAAQ;AACjE,0BAAoB,IAAI,WAAW,QAAQ,CAAC;AAAA,IAC9C,QAAQ;AACN,cAAQ,MAAM,2EAA2E;AAAA,IAC3F;AAAA,EACF;AACF;;;ADnBA,SAAS,WAAW,mBAAmB;AAEvC,SAAS,cAAc,YAAY,yBAAyB;AAX5D,IAAI,QAAQ,IAAI,cAAc,MAAM,IAAK,SAAQ,IAAI,UAAU,IAAI;AACnE,IAAI,QAAQ,KAAK,SAAS,YAAY,GAAG;AACvC,UAAQ,IAAI,UAAU,IAAI;AAC5B;AAYA,IAAM,cACJ,QAAQ,KAAK,SAAS,QAAQ,KAC9B,QAAQ,KAAK,SAAS,IAAI,KAC1B,QAAQ,KAAK,SAAS,MAAM,KAC3B,QAAQ,KAAK,SAAS,UAAU,KAC/B,QAAQ,KAAK,QAAQ,KAAK,QAAQ,UAAU,IAAI,CAAC,MAAM,UACxD,QAAQ,KAAK,SAAS,IAAI,KAAK,QAAQ,KAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM;AACnF,IAAM,WAAW,QAAQ,KAAK,SAAS,SAAS,KAAK,QAAQ,KAAK,SAAS,IAAI;AAE/E,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,QAAQ,cAAc,UAAU,QAAQ,WAAW,CAAC;AAC9F,IAAM,kBAAkB,eAAe,IAAI,QAAQ,KAAK,CAAC,KAAK,EAAE;AAEhE,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,mBAAmB,CAAC,WAAW,kBAAkB,CAAC,GAAG;AACrF,UAAQ,OAAO,MAAM,2DAA2D;AAClF;AAEA,MAAM,gBAAgB;AACtB,UAAU,aAAa,CAAC;AAExB,IAAM,iBAAiB;AAIvB,IAAM,kBAAkB,QAAQ,KAAK,CAAC,MAAM;AAG5C,IAAM,qBAAqB,kBAAkB,QAAQ,QAAQ,IAAI,IAAI,eAAe,cAAc;AAGlG,IAAI,QAAQ,KAAK,SAAS,MAAM,GAAG;AACjC,UAAQ,IAAI,IAAI,IAAI;AAEpB,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,kBAAkB,GAAG;AAC9C,YAAQ,KAAK,KAAK,kBAAkB;AAAA,EACtC;AACA,MAAI,CAAC,QAAQ,KAAK,SAAS,YAAY,GAAG;AACxC,YAAQ,KAAK,KAAK,YAAY;AAAA,EAChC;AACF;AACA,IAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,KAAK,SAAS,IAAI,GAAG;AAClE,MAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG;AAC7E,YAAQ,KAAK,KAAK,YAAY,MAAM;AAAA,EACtC;AACF;AAEA,IAAM,gBAAgB,MAAM,YAAY;AACxC,IAAM,UAAU,MAAM,cAAc,aAAa;AAGjD,IAAI,QAAQ,IAAI,WAAW,MAAM,KAAK;AACpC,UAAQ,yBAAyB,WAAW,MAAM,KAAK;AACzD;AAEA,IAAM,YAAY,KAAK,IAAI;AAC3B,IAAI,iBAAiB;AACrB,IAAI;AAEJ,MAAM,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,UAAmB;AAC/D,mBAAiB;AACjB,iBAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,QAAM,WAAW,eAAe,KAAK;AACrC,UAAQ,KAAK,QAAQ;AACvB,CAAC;AAGD,IAAM,YAAY,QAAQ,KAAK,EAAE,QAAQ;AACzC,IAAI,cAAc,UAAa,cAAc,OAAO;AAClD,MAAI;AACF,UAAM,SAAS,MAAM,WAAW;AAChC,QAAI,OAAO,UAAU;AACnB,YAAM,cAAc,QAAQ,KACzB,MAAM,CAAC,EACP,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,UAAU,CAAC,EACvC,KAAK,GAAG;AACX,YAAM,UAA0B;AAAA,QAC9B,SAAS,eAAe;AAAA,QACxB,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,KAAK,QAAQ,KAAK,EAAE,KAAK;AAAA,QACzB,OAAO;AAAA,MACT;AAEA,YAAM,SAAS,OAAO,cAAc,WAAW,YAAY;AAE3D,kBAAY,OAAO,UAAU,SAAS,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC9D;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAIA,IAAI;AACF,QAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,IAChC;AAAA,IACA,IAAI,QAAc,CAAC,YAAY,WAAW,MAAM,QAAQ,IAAI,GAAG,GAAI,CAAC;AAAA,EACtE,CAAC;AAED,MACE,UACA,OAAO,mBACP,CAAC,mBACD,QAAQ,OAAO,SACf,CAAC,QAAQ,KAAK,SAAS,QAAQ,KAC/B,QAAQ,KAAK,EAAE,QAAQ,MAAM,QAC7B;AACA,YAAQ,OAAO,MAAM;AAAA,EAAK,yBAAyB,MAAM,CAAC;AAAA,CAAI;AAAA,EAChE;AACF,QAAQ;AAER;","names":[]}