@extension.dev/deploy 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0
4
+
5
+ - Chrome: service account authentication (`CHROME_SERVICE_ACCOUNT_JSON` /
6
+ `--chrome-service-account-json`, JSON key content or file path) as an
7
+ alternative to the OAuth client/secret/refresh-token trio. The service
8
+ account wins when both are set. Avoids the 7-day refresh-token expiry of
9
+ OAuth clients whose consent screen is in "Testing" status. Add the
10
+ account's email to your publisher in the dev console (Account section).
11
+
12
+ ## 1.0.0
13
+
14
+ - BREAKING: Chrome Web Store API v2 only (`chromewebstore.googleapis.com`).
15
+ `CHROME_PUBLISHER_ID` is required; the v1.1 path, `publishTarget`, and the
16
+ trusted-testers target were removed (staged rollout via
17
+ `CHROME_DEPLOY_PERCENTAGE` replaces them).
18
+
19
+ ## 0.3.0
20
+
21
+ - Chrome Web Store API v2 support, opt-in via `CHROME_PUBLISHER_ID`
22
+ (v1.1 fallback retained).
23
+
3
24
  ## 0.2.5
4
25
 
5
26
  Current release. Earlier history is tracked in the source monorepo; entries
package/README.md CHANGED
@@ -79,6 +79,7 @@ Run `extension-deploy --help` for the full list of flags.
79
79
  | `--chrome-zip <path>` | `CHROME_ZIP` | Path to the extension ZIP file |
80
80
  | `--chrome-extension-id <id>` | `CHROME_EXTENSION_ID` | Chrome Web Store extension ID |
81
81
  | `--chrome-publisher-id <uuid>` | `CHROME_PUBLISHER_ID` | Publisher UUID from the dev console (required) |
82
+ | `--chrome-service-account-json <v>` | `CHROME_SERVICE_ACCOUNT_JSON` | Service account JSON key (content or file path); alternative to the OAuth trio below |
82
83
  | `--chrome-client-id <id>` | `CHROME_CLIENT_ID` | OAuth2 client ID |
83
84
  | `--chrome-client-secret <secret>` | `CHROME_CLIENT_SECRET` | OAuth2 client secret |
84
85
  | `--chrome-refresh-token <token>` | `CHROME_REFRESH_TOKEN` | OAuth2 refresh token |
@@ -86,6 +87,13 @@ Run `extension-deploy --help` for the full list of flags.
86
87
  | `--chrome-review-exemption` | `CHROME_REVIEW_EXEMPTION` | Request expedited review |
87
88
  | `--chrome-skip-submit-review` | `CHROME_SKIP_SUBMIT_REVIEW` | Upload only, skip publish step |
88
89
 
90
+ Chrome accepts two credential shapes: a Google Cloud **service account** JSON key
91
+ (recommended for CI; add the account's email to your publisher under
92
+ dev console > Account, one per publisher) or the classic OAuth2
93
+ client ID / client secret / refresh token trio. When both are set, the service
94
+ account is used. Service accounts avoid the 7-day refresh-token expiry that
95
+ affects OAuth clients whose consent screen is in "Testing" status.
96
+
89
97
  ### Firefox AMO
90
98
 
91
99
  | Flag | Env var | Description |
@@ -156,7 +164,7 @@ const result = await deploy({
156
164
  clientId: "123.apps.googleusercontent.com",
157
165
  clientSecret: "GOCSPX-xxx",
158
166
  refreshToken: "1//0xxx",
159
- publishTarget: "default",
167
+ publisherId: "00000000-0000-0000-0000-000000000000", // required
160
168
  deployPercentage: 10, // optional: staged rollout
161
169
  },
162
170
  firefox: {
package/dist/module.js CHANGED
@@ -59,13 +59,28 @@ const external_zod_namespaceObject = require("zod");
59
59
  const chromeOptionsSchema = external_zod_namespaceObject.z.object({
60
60
  zip: external_zod_namespaceObject.z.string().min(1),
61
61
  extensionId: external_zod_namespaceObject.z.string().min(1).trim(),
62
- clientId: external_zod_namespaceObject.z.string().min(1).trim(),
63
- clientSecret: external_zod_namespaceObject.z.string().min(1).trim(),
64
- refreshToken: external_zod_namespaceObject.z.string().min(1).trim(),
62
+ serviceAccountJson: external_zod_namespaceObject.z.string().trim().default(""),
63
+ clientId: external_zod_namespaceObject.z.string().trim().default(""),
64
+ clientSecret: external_zod_namespaceObject.z.string().trim().default(""),
65
+ refreshToken: external_zod_namespaceObject.z.string().trim().default(""),
65
66
  publisherId: external_zod_namespaceObject.z.string().min(1).trim(),
66
67
  deployPercentage: external_zod_namespaceObject.z.number().int().min(1).max(100).optional(),
67
68
  reviewExemption: external_zod_namespaceObject.z.boolean().default(false),
68
69
  skipSubmitReview: external_zod_namespaceObject.z.boolean().default(false)
70
+ }).superRefine((val, ctx)=>{
71
+ if (val.serviceAccountJson) return;
72
+ const missing = [
73
+ "clientId",
74
+ "clientSecret",
75
+ "refreshToken"
76
+ ].filter((k)=>!val[k]);
77
+ for (const key of missing)ctx.addIssue({
78
+ code: external_zod_namespaceObject.z.ZodIssueCode.custom,
79
+ path: [
80
+ key
81
+ ],
82
+ message: "Required unless a service account key is provided (CHROME_SERVICE_ACCOUNT_JSON)."
83
+ });
69
84
  });
70
85
  const firefoxOptionsSchema = external_zod_namespaceObject.z.object({
71
86
  zip: external_zod_namespaceObject.z.string().min(1),
@@ -109,6 +124,7 @@ function resolveConfig(flags) {
109
124
  chrome: null == chromeZip ? void 0 : {
110
125
  zip: chromeZip,
111
126
  extensionId: flags.chromeExtensionId ?? envStr("CHROME_EXTENSION_ID") ?? "",
127
+ serviceAccountJson: flags.chromeServiceAccountJson ?? envStr("CHROME_SERVICE_ACCOUNT_JSON") ?? "",
112
128
  clientId: flags.chromeClientId ?? envStr("CHROME_CLIENT_ID") ?? "",
113
129
  clientSecret: flags.chromeClientSecret ?? envStr("CHROME_CLIENT_SECRET") ?? "",
114
130
  refreshToken: flags.chromeRefreshToken ?? envStr("CHROME_REFRESH_TOKEN") ?? "",
@@ -139,6 +155,7 @@ function pathToEnvName(segments) {
139
155
  }
140
156
  const SETUP_HINTS = {
141
157
  CHROME_EXTENSION_ID: "Find this in the Chrome Web Store Developer Dashboard URL for your extension.",
158
+ CHROME_SERVICE_ACCOUNT_JSON: "Optional alternative to OAuth: a Google Cloud service account JSON key (content or file path), added to your publisher under dev console > Account.",
142
159
  CHROME_CLIENT_ID: "Create OAuth 2.0 credentials at https://console.cloud.google.com/apis/credentials",
143
160
  CHROME_CLIENT_SECRET: "Generated alongside the Client ID in the Google Cloud Console.",
144
161
  CHROME_REFRESH_TOKEN: "Obtain by completing the OAuth consent flow. See the Chrome Web Store API docs.",
@@ -183,6 +200,8 @@ function envInt(name) {
183
200
  const val = process.env[name];
184
201
  return null == val ? void 0 : parseInt(val, 10);
185
202
  }
203
+ const external_node_crypto_namespaceObject = require("node:crypto");
204
+ var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
186
205
  const promises_namespaceObject = require("node:fs/promises");
187
206
  var promises_default = /*#__PURE__*/ __webpack_require__.n(promises_namespaceObject);
188
207
  const DEFAULT_TIMEOUT_MS = 60000;
@@ -271,7 +290,51 @@ function requirePublisherId(publisherId, op) {
271
290
  function chromeStoreUrl(extensionId) {
272
291
  return `https://chromewebstore.google.com/detail/${extensionId}`;
273
292
  }
274
- async function authenticate(clientId, clientSecret, refreshToken) {
293
+ const CWS_SCOPE = "https://www.googleapis.com/auth/chromewebstore";
294
+ async function resolveServiceAccountKey(value) {
295
+ const trimmed = value.trim();
296
+ const raw = trimmed.startsWith("{") ? trimmed : await promises_default().readFile(trimmed, "utf-8").catch(()=>{
297
+ throw new Error(`Chrome service account key: "${trimmed.slice(0, 80)}" is neither JSON nor a readable file path.`);
298
+ });
299
+ let parsed;
300
+ try {
301
+ parsed = JSON.parse(raw);
302
+ } catch {
303
+ throw new Error("Chrome service account key is not valid JSON.");
304
+ }
305
+ if (!parsed.client_email || !parsed.private_key) throw new Error("Chrome service account key is missing client_email or private_key. Download the JSON key from the Google Cloud Console.");
306
+ return {
307
+ client_email: parsed.client_email,
308
+ private_key: parsed.private_key
309
+ };
310
+ }
311
+ async function authenticateServiceAccount(serviceAccountJson) {
312
+ const key = await resolveServiceAccountKey(serviceAccountJson);
313
+ const iat = Math.floor(Date.now() / 1000);
314
+ const encode = (obj)=>Buffer.from(JSON.stringify(obj)).toString("base64url");
315
+ const unsigned = `${encode({
316
+ alg: "RS256",
317
+ typ: "JWT"
318
+ })}.${encode({
319
+ iss: key.client_email,
320
+ scope: CWS_SCOPE,
321
+ aud: CWS_OAUTH_URL,
322
+ iat,
323
+ exp: iat + 3600
324
+ })}`;
325
+ const signature = external_node_crypto_default().createSign("RSA-SHA256").update(unsigned).sign(key.private_key).toString("base64url");
326
+ return fetchJson(CWS_OAUTH_URL, {
327
+ method: "POST",
328
+ body: new URLSearchParams({
329
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
330
+ assertion: `${unsigned}.${signature}`
331
+ }).toString(),
332
+ headers: {
333
+ "Content-Type": "application/x-www-form-urlencoded"
334
+ }
335
+ });
336
+ }
337
+ async function authenticateOauth(clientId, clientSecret, refreshToken) {
275
338
  return fetchJson(CWS_OAUTH_URL, {
276
339
  method: "POST",
277
340
  body: JSON.stringify({
@@ -286,6 +349,11 @@ async function authenticate(clientId, clientSecret, refreshToken) {
286
349
  }
287
350
  });
288
351
  }
352
+ async function authenticate(creds) {
353
+ if (creds.serviceAccountJson) return authenticateServiceAccount(creds.serviceAccountJson);
354
+ if (creds.clientId && creds.clientSecret && creds.refreshToken) return authenticateOauth(creds.clientId, creds.clientSecret, creds.refreshToken);
355
+ throw new Error("Chrome credentials missing: provide a service account key (CHROME_SERVICE_ACCOUNT_JSON) or the OAuth client ID, client secret, and refresh token.");
356
+ }
289
357
  async function chrome_upload(extensionId, publisherId, zipPath, token) {
290
358
  const body = await promises_default().readFile(zipPath);
291
359
  const url = `${CWS_V2_UPLOAD_BASE}/${v2ItemName(publisherId, extensionId)}:upload`;
@@ -331,8 +399,8 @@ async function publishChrome(options, dryRun) {
331
399
  await assertFilePresent(options.zip);
332
400
  const zipSize = await getFileSize(options.zip);
333
401
  const publisherId = requirePublisherId(options.publisherId, "submit");
334
- log("chrome", "Authenticating with Chrome Web Store (API v2)");
335
- const token = await authenticate(options.clientId, options.clientSecret, options.refreshToken);
402
+ log("chrome", `Authenticating with Chrome Web Store (API v2, ${options.serviceAccountJson ? "service account" : "OAuth"})`);
403
+ const token = await authenticate(options);
336
404
  const outcome = {
337
405
  storeUrl: chromeStoreUrl(options.extensionId),
338
406
  submissionId: options.extensionId
@@ -371,7 +439,7 @@ async function publishChrome(options, dryRun) {
371
439
  }
372
440
  async function getChromeItem(params) {
373
441
  var _rev_distributionChannels_, _rev_distributionChannels;
374
- const token = await authenticate(params.clientId, params.clientSecret, params.refreshToken);
442
+ const token = await authenticate(params);
375
443
  const auth = {
376
444
  Authorization: `${token.token_type} ${token.access_token}`
377
445
  };
@@ -390,11 +458,12 @@ async function getChromeItem(params) {
390
458
  async function verifyChromeCredentials(params) {
391
459
  let token;
392
460
  try {
393
- token = await authenticate(params.clientId, params.clientSecret, params.refreshToken);
461
+ token = await authenticate(params);
394
462
  } catch (err) {
463
+ const detail = err instanceof Error ? err.message : String(err);
395
464
  return {
396
465
  ok: false,
397
- message: `OAuth token exchange failed. Verify your Client ID, Client Secret, and Refresh Token are correct.\n${err instanceof Error ? err.message : err}`
466
+ message: params.serviceAccountJson ? `Service account token exchange failed. Verify the JSON key is intact and the account was added to your publisher (dev console > Account).\n${detail}` : `OAuth token exchange failed. Verify your Client ID, Client Secret, and Refresh Token are correct.\n${detail}`
398
467
  };
399
468
  }
400
469
  const auth = {
@@ -418,7 +487,7 @@ async function verifyChromeCredentials(params) {
418
487
  };
419
488
  if (msg.includes("403")) return {
420
489
  ok: false,
421
- message: "Access denied. Check the publisher ID matches this extension's account, and that the extension ID is correct."
490
+ message: params.serviceAccountJson ? "Access denied. Check the publisher ID, and that this service account's email was added to the publisher (dev console > Account)." : "Access denied. Check the publisher ID matches this extension's account, and that the extension ID is correct."
422
491
  };
423
492
  return {
424
493
  ok: false,
@@ -431,8 +500,6 @@ function delay(ms) {
431
500
  setTimeout(resolve, ms);
432
501
  });
433
502
  }
434
- const external_node_crypto_namespaceObject = require("node:crypto");
435
- var external_node_crypto_default = /*#__PURE__*/ __webpack_require__.n(external_node_crypto_namespaceObject);
436
503
  const AMO_BASE = "https://addons.mozilla.org/api/v5/addons";
437
504
  function signJwt(issuer, secret, expiresInSeconds = 30) {
438
505
  const header = {
@@ -909,6 +976,8 @@ CHROME
909
976
  --chrome-zip <path> Path to Chrome extension ZIP
910
977
  --chrome-extension-id <id> Chrome extension ID
911
978
  --chrome-publisher-id <uuid> Publisher UUID from the dev console (required)
979
+ --chrome-service-account-json <v> Service account JSON key content or file path
980
+ (alternative to the OAuth flags below)
912
981
  --chrome-client-id <id> OAuth2 client ID
913
982
  --chrome-client-secret <secret> OAuth2 client secret
914
983
  --chrome-refresh-token <token> OAuth2 refresh token
@@ -1504,17 +1573,21 @@ async function runWatch(flags) {
1504
1573
  const timeoutMs = (flags.watchTimeout ?? 3600) * 1000;
1505
1574
  let terminal;
1506
1575
  try {
1507
- terminal = "chrome" === store ? await watchChromeSubmission({
1508
- clientId: mustEnv("CHROME_CLIENT_ID", flags.chromeClientId),
1509
- clientSecret: mustEnv("CHROME_CLIENT_SECRET", flags.chromeClientSecret),
1510
- refreshToken: mustEnv("CHROME_REFRESH_TOKEN", flags.chromeRefreshToken),
1511
- extensionId: mustEnv("CHROME_EXTENSION_ID", flags.chromeExtensionId),
1512
- publisherId: mustEnv("CHROME_PUBLISHER_ID", flags.chromePublisherId)
1513
- }, {
1514
- pollIntervalMs,
1515
- timeoutMs,
1516
- onEvent
1517
- }) : "firefox" === store ? await watchFirefoxSubmission({
1576
+ if ("chrome" === store) {
1577
+ const serviceAccountJson = flags.chromeServiceAccountJson ?? process.env.CHROME_SERVICE_ACCOUNT_JSON;
1578
+ terminal = await watchChromeSubmission({
1579
+ serviceAccountJson,
1580
+ clientId: serviceAccountJson ? flags.chromeClientId : mustEnv("CHROME_CLIENT_ID", flags.chromeClientId),
1581
+ clientSecret: serviceAccountJson ? flags.chromeClientSecret : mustEnv("CHROME_CLIENT_SECRET", flags.chromeClientSecret),
1582
+ refreshToken: serviceAccountJson ? flags.chromeRefreshToken : mustEnv("CHROME_REFRESH_TOKEN", flags.chromeRefreshToken),
1583
+ extensionId: mustEnv("CHROME_EXTENSION_ID", flags.chromeExtensionId),
1584
+ publisherId: mustEnv("CHROME_PUBLISHER_ID", flags.chromePublisherId)
1585
+ }, {
1586
+ pollIntervalMs,
1587
+ timeoutMs,
1588
+ onEvent
1589
+ });
1590
+ } else terminal = "firefox" === store ? await watchFirefoxSubmission({
1518
1591
  jwtIssuer: mustEnv("FIREFOX_JWT_ISSUER", flags.firefoxJwtIssuer),
1519
1592
  jwtSecret: mustEnv("FIREFOX_JWT_SECRET", flags.firefoxJwtSecret),
1520
1593
  extensionId: mustEnv("FIREFOX_EXTENSION_ID", flags.firefoxExtensionId),
package/dist/module.mjs CHANGED
@@ -1,20 +1,35 @@
1
1
  import external_node_fs_default from "node:fs";
2
2
  import external_node_path_default from "node:path";
3
3
  import { z } from "zod";
4
+ import external_node_crypto_default from "node:crypto";
4
5
  import promises_default from "node:fs/promises";
5
6
  import external_pintor_default from "pintor";
6
- import external_node_crypto_default from "node:crypto";
7
7
  import external_node_readline_default from "node:readline";
8
8
  const chromeOptionsSchema = z.object({
9
9
  zip: z.string().min(1),
10
10
  extensionId: z.string().min(1).trim(),
11
- clientId: z.string().min(1).trim(),
12
- clientSecret: z.string().min(1).trim(),
13
- refreshToken: z.string().min(1).trim(),
11
+ serviceAccountJson: z.string().trim().default(""),
12
+ clientId: z.string().trim().default(""),
13
+ clientSecret: z.string().trim().default(""),
14
+ refreshToken: z.string().trim().default(""),
14
15
  publisherId: z.string().min(1).trim(),
15
16
  deployPercentage: z.number().int().min(1).max(100).optional(),
16
17
  reviewExemption: z.boolean().default(false),
17
18
  skipSubmitReview: z.boolean().default(false)
19
+ }).superRefine((val, ctx)=>{
20
+ if (val.serviceAccountJson) return;
21
+ const missing = [
22
+ "clientId",
23
+ "clientSecret",
24
+ "refreshToken"
25
+ ].filter((k)=>!val[k]);
26
+ for (const key of missing)ctx.addIssue({
27
+ code: z.ZodIssueCode.custom,
28
+ path: [
29
+ key
30
+ ],
31
+ message: "Required unless a service account key is provided (CHROME_SERVICE_ACCOUNT_JSON)."
32
+ });
18
33
  });
19
34
  const firefoxOptionsSchema = z.object({
20
35
  zip: z.string().min(1),
@@ -58,6 +73,7 @@ function resolveConfig(flags) {
58
73
  chrome: null == chromeZip ? void 0 : {
59
74
  zip: chromeZip,
60
75
  extensionId: flags.chromeExtensionId ?? envStr("CHROME_EXTENSION_ID") ?? "",
76
+ serviceAccountJson: flags.chromeServiceAccountJson ?? envStr("CHROME_SERVICE_ACCOUNT_JSON") ?? "",
61
77
  clientId: flags.chromeClientId ?? envStr("CHROME_CLIENT_ID") ?? "",
62
78
  clientSecret: flags.chromeClientSecret ?? envStr("CHROME_CLIENT_SECRET") ?? "",
63
79
  refreshToken: flags.chromeRefreshToken ?? envStr("CHROME_REFRESH_TOKEN") ?? "",
@@ -88,6 +104,7 @@ function pathToEnvName(segments) {
88
104
  }
89
105
  const SETUP_HINTS = {
90
106
  CHROME_EXTENSION_ID: "Find this in the Chrome Web Store Developer Dashboard URL for your extension.",
107
+ CHROME_SERVICE_ACCOUNT_JSON: "Optional alternative to OAuth: a Google Cloud service account JSON key (content or file path), added to your publisher under dev console > Account.",
91
108
  CHROME_CLIENT_ID: "Create OAuth 2.0 credentials at https://console.cloud.google.com/apis/credentials",
92
109
  CHROME_CLIENT_SECRET: "Generated alongside the Client ID in the Google Cloud Console.",
93
110
  CHROME_REFRESH_TOKEN: "Obtain by completing the OAuth consent flow. See the Chrome Web Store API docs.",
@@ -216,7 +233,51 @@ function requirePublisherId(publisherId, op) {
216
233
  function chromeStoreUrl(extensionId) {
217
234
  return `https://chromewebstore.google.com/detail/${extensionId}`;
218
235
  }
219
- async function authenticate(clientId, clientSecret, refreshToken) {
236
+ const CWS_SCOPE = "https://www.googleapis.com/auth/chromewebstore";
237
+ async function resolveServiceAccountKey(value) {
238
+ const trimmed = value.trim();
239
+ const raw = trimmed.startsWith("{") ? trimmed : await promises_default.readFile(trimmed, "utf-8").catch(()=>{
240
+ throw new Error(`Chrome service account key: "${trimmed.slice(0, 80)}" is neither JSON nor a readable file path.`);
241
+ });
242
+ let parsed;
243
+ try {
244
+ parsed = JSON.parse(raw);
245
+ } catch {
246
+ throw new Error("Chrome service account key is not valid JSON.");
247
+ }
248
+ if (!parsed.client_email || !parsed.private_key) throw new Error("Chrome service account key is missing client_email or private_key. Download the JSON key from the Google Cloud Console.");
249
+ return {
250
+ client_email: parsed.client_email,
251
+ private_key: parsed.private_key
252
+ };
253
+ }
254
+ async function authenticateServiceAccount(serviceAccountJson) {
255
+ const key = await resolveServiceAccountKey(serviceAccountJson);
256
+ const iat = Math.floor(Date.now() / 1000);
257
+ const encode = (obj)=>Buffer.from(JSON.stringify(obj)).toString("base64url");
258
+ const unsigned = `${encode({
259
+ alg: "RS256",
260
+ typ: "JWT"
261
+ })}.${encode({
262
+ iss: key.client_email,
263
+ scope: CWS_SCOPE,
264
+ aud: CWS_OAUTH_URL,
265
+ iat,
266
+ exp: iat + 3600
267
+ })}`;
268
+ const signature = external_node_crypto_default.createSign("RSA-SHA256").update(unsigned).sign(key.private_key).toString("base64url");
269
+ return fetchJson(CWS_OAUTH_URL, {
270
+ method: "POST",
271
+ body: new URLSearchParams({
272
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
273
+ assertion: `${unsigned}.${signature}`
274
+ }).toString(),
275
+ headers: {
276
+ "Content-Type": "application/x-www-form-urlencoded"
277
+ }
278
+ });
279
+ }
280
+ async function authenticateOauth(clientId, clientSecret, refreshToken) {
220
281
  return fetchJson(CWS_OAUTH_URL, {
221
282
  method: "POST",
222
283
  body: JSON.stringify({
@@ -231,6 +292,11 @@ async function authenticate(clientId, clientSecret, refreshToken) {
231
292
  }
232
293
  });
233
294
  }
295
+ async function authenticate(creds) {
296
+ if (creds.serviceAccountJson) return authenticateServiceAccount(creds.serviceAccountJson);
297
+ if (creds.clientId && creds.clientSecret && creds.refreshToken) return authenticateOauth(creds.clientId, creds.clientSecret, creds.refreshToken);
298
+ throw new Error("Chrome credentials missing: provide a service account key (CHROME_SERVICE_ACCOUNT_JSON) or the OAuth client ID, client secret, and refresh token.");
299
+ }
234
300
  async function chrome_upload(extensionId, publisherId, zipPath, token) {
235
301
  const body = await promises_default.readFile(zipPath);
236
302
  const url = `${CWS_V2_UPLOAD_BASE}/${v2ItemName(publisherId, extensionId)}:upload`;
@@ -276,8 +342,8 @@ async function publishChrome(options, dryRun) {
276
342
  await assertFilePresent(options.zip);
277
343
  const zipSize = await getFileSize(options.zip);
278
344
  const publisherId = requirePublisherId(options.publisherId, "submit");
279
- log("chrome", "Authenticating with Chrome Web Store (API v2)");
280
- const token = await authenticate(options.clientId, options.clientSecret, options.refreshToken);
345
+ log("chrome", `Authenticating with Chrome Web Store (API v2, ${options.serviceAccountJson ? "service account" : "OAuth"})`);
346
+ const token = await authenticate(options);
281
347
  const outcome = {
282
348
  storeUrl: chromeStoreUrl(options.extensionId),
283
349
  submissionId: options.extensionId
@@ -316,7 +382,7 @@ async function publishChrome(options, dryRun) {
316
382
  }
317
383
  async function getChromeItem(params) {
318
384
  var _rev_distributionChannels_, _rev_distributionChannels;
319
- const token = await authenticate(params.clientId, params.clientSecret, params.refreshToken);
385
+ const token = await authenticate(params);
320
386
  const auth = {
321
387
  Authorization: `${token.token_type} ${token.access_token}`
322
388
  };
@@ -335,11 +401,12 @@ async function getChromeItem(params) {
335
401
  async function verifyChromeCredentials(params) {
336
402
  let token;
337
403
  try {
338
- token = await authenticate(params.clientId, params.clientSecret, params.refreshToken);
404
+ token = await authenticate(params);
339
405
  } catch (err) {
406
+ const detail = err instanceof Error ? err.message : String(err);
340
407
  return {
341
408
  ok: false,
342
- message: `OAuth token exchange failed. Verify your Client ID, Client Secret, and Refresh Token are correct.\n${err instanceof Error ? err.message : err}`
409
+ message: params.serviceAccountJson ? `Service account token exchange failed. Verify the JSON key is intact and the account was added to your publisher (dev console > Account).\n${detail}` : `OAuth token exchange failed. Verify your Client ID, Client Secret, and Refresh Token are correct.\n${detail}`
343
410
  };
344
411
  }
345
412
  const auth = {
@@ -363,7 +430,7 @@ async function verifyChromeCredentials(params) {
363
430
  };
364
431
  if (msg.includes("403")) return {
365
432
  ok: false,
366
- message: "Access denied. Check the publisher ID matches this extension's account, and that the extension ID is correct."
433
+ message: params.serviceAccountJson ? "Access denied. Check the publisher ID, and that this service account's email was added to the publisher (dev console > Account)." : "Access denied. Check the publisher ID matches this extension's account, and that the extension ID is correct."
367
434
  };
368
435
  return {
369
436
  ok: false,
@@ -852,6 +919,8 @@ CHROME
852
919
  --chrome-zip <path> Path to Chrome extension ZIP
853
920
  --chrome-extension-id <id> Chrome extension ID
854
921
  --chrome-publisher-id <uuid> Publisher UUID from the dev console (required)
922
+ --chrome-service-account-json <v> Service account JSON key content or file path
923
+ (alternative to the OAuth flags below)
855
924
  --chrome-client-id <id> OAuth2 client ID
856
925
  --chrome-client-secret <secret> OAuth2 client secret
857
926
  --chrome-refresh-token <token> OAuth2 refresh token
@@ -1445,17 +1514,21 @@ async function runWatch(flags) {
1445
1514
  const timeoutMs = (flags.watchTimeout ?? 3600) * 1000;
1446
1515
  let terminal;
1447
1516
  try {
1448
- terminal = "chrome" === store ? await watchChromeSubmission({
1449
- clientId: mustEnv("CHROME_CLIENT_ID", flags.chromeClientId),
1450
- clientSecret: mustEnv("CHROME_CLIENT_SECRET", flags.chromeClientSecret),
1451
- refreshToken: mustEnv("CHROME_REFRESH_TOKEN", flags.chromeRefreshToken),
1452
- extensionId: mustEnv("CHROME_EXTENSION_ID", flags.chromeExtensionId),
1453
- publisherId: mustEnv("CHROME_PUBLISHER_ID", flags.chromePublisherId)
1454
- }, {
1455
- pollIntervalMs,
1456
- timeoutMs,
1457
- onEvent
1458
- }) : "firefox" === store ? await watchFirefoxSubmission({
1517
+ if ("chrome" === store) {
1518
+ const serviceAccountJson = flags.chromeServiceAccountJson ?? process.env.CHROME_SERVICE_ACCOUNT_JSON;
1519
+ terminal = await watchChromeSubmission({
1520
+ serviceAccountJson,
1521
+ clientId: serviceAccountJson ? flags.chromeClientId : mustEnv("CHROME_CLIENT_ID", flags.chromeClientId),
1522
+ clientSecret: serviceAccountJson ? flags.chromeClientSecret : mustEnv("CHROME_CLIENT_SECRET", flags.chromeClientSecret),
1523
+ refreshToken: serviceAccountJson ? flags.chromeRefreshToken : mustEnv("CHROME_REFRESH_TOKEN", flags.chromeRefreshToken),
1524
+ extensionId: mustEnv("CHROME_EXTENSION_ID", flags.chromeExtensionId),
1525
+ publisherId: mustEnv("CHROME_PUBLISHER_ID", flags.chromePublisherId)
1526
+ }, {
1527
+ pollIntervalMs,
1528
+ timeoutMs,
1529
+ onEvent
1530
+ });
1531
+ } else terminal = "firefox" === store ? await watchFirefoxSubmission({
1459
1532
  jwtIssuer: mustEnv("FIREFOX_JWT_ISSUER", flags.firefoxJwtIssuer),
1460
1533
  jwtSecret: mustEnv("FIREFOX_JWT_SECRET", flags.firefoxJwtSecret),
1461
1534
  extensionId: mustEnv("FIREFOX_EXTENSION_ID", flags.firefoxExtensionId),
@@ -5,8 +5,9 @@ export declare function chromeStoreUrl(extensionId: string): string;
5
5
  export interface CwsAccessToken {
6
6
  access_token: string;
7
7
  expires_in: number;
8
- refresh_token: string;
9
- scope: string;
8
+ /** Absent for service-account (JWT bearer) grants. */
9
+ refresh_token?: string;
10
+ scope?: string;
10
11
  token_type: string;
11
12
  }
12
13
  export interface ChromeVerifyResult {
@@ -14,6 +15,14 @@ export interface ChromeVerifyResult {
14
15
  message: string;
15
16
  extensionTitle?: string;
16
17
  }
18
+ /** Credential fields shared by every Chrome API entry point. */
19
+ export interface ChromeCredentials {
20
+ serviceAccountJson?: string;
21
+ clientId?: string;
22
+ clientSecret?: string;
23
+ refreshToken?: string;
24
+ }
25
+ export declare function authenticate(creds: ChromeCredentials): Promise<CwsAccessToken>;
17
26
  export interface ChromePublishOutcome {
18
27
  storeUrl: string;
19
28
  submissionId: string;
@@ -30,17 +39,11 @@ export interface ChromeItemStatus {
30
39
  /** v2 review state (PENDING_REVIEW | STAGED | PUBLISHED | REJECTED | ...). */
31
40
  state?: string;
32
41
  }
33
- export declare function getChromeItem(params: {
34
- clientId: string;
35
- clientSecret: string;
36
- refreshToken: string;
42
+ export declare function getChromeItem(params: ChromeCredentials & {
37
43
  extensionId: string;
38
44
  publisherId: string;
39
45
  }): Promise<ChromeItemStatus>;
40
- export declare function verifyChromeCredentials(params: {
41
- clientId: string;
42
- clientSecret: string;
43
- refreshToken: string;
46
+ export declare function verifyChromeCredentials(params: ChromeCredentials & {
44
47
  extensionId: string;
45
48
  publisherId: string;
46
49
  }): Promise<ChromeVerifyResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAoB7C,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAI3E;AAeD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA+ED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,oBAAoB,CAAC,CAwD/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwBD,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoB5B;AAED,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkD9B"}
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/chrome.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAoB7C,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAI3E;AAeD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsFD,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,cAAc,CAAC,CAczB;AA6DD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,oBAAoB,CAAC,CAuD/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwBD,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,GACA,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,GACA,OAAO,CAAC,kBAAkB,CAAC,CAkD7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/cli-commands.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAGxE;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFtE;AAmBD,wBAAsB,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB5E"}
1
+ {"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/cli-commands.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAGxE;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFtE;AAmBD,wBAAsB,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"cli-usage.d.ts","sourceRoot":"","sources":["../../src/cli-usage.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAI,MAAM,CA0D9B"}
1
+ {"version":3,"file":"cli-usage.d.ts","sourceRoot":"","sources":["../../src/cli-usage.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAI,MAAM,CA4D9B"}
@@ -5,6 +5,7 @@ export declare function validateConfig(raw: DeployConfig): {
5
5
  chrome?: {
6
6
  zip: string;
7
7
  extensionId: string;
8
+ serviceAccountJson: string;
8
9
  clientId: string;
9
10
  clientSecret: string;
10
11
  refreshToken: string;
@@ -46,6 +47,8 @@ export interface CliFlags {
46
47
  watchTimeout: number;
47
48
  chromeZip: string;
48
49
  chromeExtensionId: string;
50
+ /** Service account JSON key content or file path (alternative to OAuth). */
51
+ chromeServiceAccountJson: string;
49
52
  chromeClientId: string;
50
53
  chromeClientSecret: string;
51
54
  chromeRefreshToken: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,YAAY,CA8DpE;AAyCD,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB/C;AAiBD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,8CAA8C;IAC9C,UAAU,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAC1C,4EAA4E;IAC5E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sBAAsB,EAAE,OAAO,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,SAAS,EAAE,OAAO,CAAC;CACpB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,YAAY,CAkEpE;AA2CD,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB/C;AAiBD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,8CAA8C;IAC9C,UAAU,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAC1C,4EAA4E;IAC5E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,sBAAsB,EAAE,OAAO,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,SAAS,EAAE,OAAO,CAAC;CACpB"}
@@ -1,11 +1,12 @@
1
1
  import { z } from "zod";
2
2
  export type StoreKey = "chrome" | "firefox" | "edge";
3
- export declare const chromeOptionsSchema: z.ZodObject<{
3
+ export declare const chromeOptionsSchema: z.ZodEffects<z.ZodObject<{
4
4
  zip: z.ZodString;
5
5
  extensionId: z.ZodString;
6
- clientId: z.ZodString;
7
- clientSecret: z.ZodString;
8
- refreshToken: z.ZodString;
6
+ serviceAccountJson: z.ZodDefault<z.ZodString>;
7
+ clientId: z.ZodDefault<z.ZodString>;
8
+ clientSecret: z.ZodDefault<z.ZodString>;
9
+ refreshToken: z.ZodDefault<z.ZodString>;
9
10
  publisherId: z.ZodString;
10
11
  deployPercentage: z.ZodOptional<z.ZodNumber>;
11
12
  reviewExemption: z.ZodDefault<z.ZodBoolean>;
@@ -13,6 +14,7 @@ export declare const chromeOptionsSchema: z.ZodObject<{
13
14
  }, "strip", z.ZodTypeAny, {
14
15
  zip: string;
15
16
  extensionId: string;
17
+ serviceAccountJson: string;
16
18
  clientId: string;
17
19
  clientSecret: string;
18
20
  refreshToken: string;
@@ -23,10 +25,33 @@ export declare const chromeOptionsSchema: z.ZodObject<{
23
25
  }, {
24
26
  zip: string;
25
27
  extensionId: string;
28
+ publisherId: string;
29
+ serviceAccountJson?: string | undefined;
30
+ clientId?: string | undefined;
31
+ clientSecret?: string | undefined;
32
+ refreshToken?: string | undefined;
33
+ deployPercentage?: number | undefined;
34
+ reviewExemption?: boolean | undefined;
35
+ skipSubmitReview?: boolean | undefined;
36
+ }>, {
37
+ zip: string;
38
+ extensionId: string;
39
+ serviceAccountJson: string;
26
40
  clientId: string;
27
41
  clientSecret: string;
28
42
  refreshToken: string;
29
43
  publisherId: string;
44
+ reviewExemption: boolean;
45
+ skipSubmitReview: boolean;
46
+ deployPercentage?: number | undefined;
47
+ }, {
48
+ zip: string;
49
+ extensionId: string;
50
+ publisherId: string;
51
+ serviceAccountJson?: string | undefined;
52
+ clientId?: string | undefined;
53
+ clientSecret?: string | undefined;
54
+ refreshToken?: string | undefined;
30
55
  deployPercentage?: number | undefined;
31
56
  reviewExemption?: boolean | undefined;
32
57
  skipSubmitReview?: boolean | undefined;
@@ -91,12 +116,13 @@ export declare const edgeOptionsSchema: z.ZodObject<{
91
116
  export type EdgeOptions = z.infer<typeof edgeOptionsSchema>;
92
117
  export declare const deployConfigSchema: z.ZodObject<{
93
118
  dryRun: z.ZodDefault<z.ZodBoolean>;
94
- chrome: z.ZodOptional<z.ZodObject<{
119
+ chrome: z.ZodOptional<z.ZodEffects<z.ZodObject<{
95
120
  zip: z.ZodString;
96
121
  extensionId: z.ZodString;
97
- clientId: z.ZodString;
98
- clientSecret: z.ZodString;
99
- refreshToken: z.ZodString;
122
+ serviceAccountJson: z.ZodDefault<z.ZodString>;
123
+ clientId: z.ZodDefault<z.ZodString>;
124
+ clientSecret: z.ZodDefault<z.ZodString>;
125
+ refreshToken: z.ZodDefault<z.ZodString>;
100
126
  publisherId: z.ZodString;
101
127
  deployPercentage: z.ZodOptional<z.ZodNumber>;
102
128
  reviewExemption: z.ZodDefault<z.ZodBoolean>;
@@ -104,6 +130,7 @@ export declare const deployConfigSchema: z.ZodObject<{
104
130
  }, "strip", z.ZodTypeAny, {
105
131
  zip: string;
106
132
  extensionId: string;
133
+ serviceAccountJson: string;
107
134
  clientId: string;
108
135
  clientSecret: string;
109
136
  refreshToken: string;
@@ -114,10 +141,33 @@ export declare const deployConfigSchema: z.ZodObject<{
114
141
  }, {
115
142
  zip: string;
116
143
  extensionId: string;
144
+ publisherId: string;
145
+ serviceAccountJson?: string | undefined;
146
+ clientId?: string | undefined;
147
+ clientSecret?: string | undefined;
148
+ refreshToken?: string | undefined;
149
+ deployPercentage?: number | undefined;
150
+ reviewExemption?: boolean | undefined;
151
+ skipSubmitReview?: boolean | undefined;
152
+ }>, {
153
+ zip: string;
154
+ extensionId: string;
155
+ serviceAccountJson: string;
117
156
  clientId: string;
118
157
  clientSecret: string;
119
158
  refreshToken: string;
120
159
  publisherId: string;
160
+ reviewExemption: boolean;
161
+ skipSubmitReview: boolean;
162
+ deployPercentage?: number | undefined;
163
+ }, {
164
+ zip: string;
165
+ extensionId: string;
166
+ publisherId: string;
167
+ serviceAccountJson?: string | undefined;
168
+ clientId?: string | undefined;
169
+ clientSecret?: string | undefined;
170
+ refreshToken?: string | undefined;
121
171
  deployPercentage?: number | undefined;
122
172
  reviewExemption?: boolean | undefined;
123
173
  skipSubmitReview?: boolean | undefined;
@@ -182,6 +232,7 @@ export declare const deployConfigSchema: z.ZodObject<{
182
232
  chrome?: {
183
233
  zip: string;
184
234
  extensionId: string;
235
+ serviceAccountJson: string;
185
236
  clientId: string;
186
237
  clientSecret: string;
187
238
  refreshToken: string;
@@ -209,10 +260,11 @@ export declare const deployConfigSchema: z.ZodObject<{
209
260
  chrome?: {
210
261
  zip: string;
211
262
  extensionId: string;
212
- clientId: string;
213
- clientSecret: string;
214
- refreshToken: string;
215
263
  publisherId: string;
264
+ serviceAccountJson?: string | undefined;
265
+ clientId?: string | undefined;
266
+ clientSecret?: string | undefined;
267
+ refreshToken?: string | undefined;
216
268
  deployPercentage?: number | undefined;
217
269
  reviewExemption?: boolean | undefined;
218
270
  skipSubmitReview?: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqB7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,WAAW,GACX,YAAY,GACZ,WAAW,GACX,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC5B,CAAC;AACL,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqB7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,WAAW,GACX,YAAY,GACZ,WAAW,GACX,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC"}
@@ -15,9 +15,10 @@ export interface WatchLoopOptions {
15
15
  onEvent?: (event: WatchEvent) => void;
16
16
  }
17
17
  export interface ChromeWatchInput {
18
- clientId: string;
19
- clientSecret: string;
20
- refreshToken: string;
18
+ serviceAccountJson?: string;
19
+ clientId?: string;
20
+ clientSecret?: string;
21
+ refreshToken?: string;
21
22
  extensionId: string;
22
23
  publisherId: string;
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAY,UAAU,EAAe,MAAM,SAAS,CAAC;AAajE,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAUD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,UAAU,CAAC,CAqCrB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAgBD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAUD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAMrB"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAY,UAAU,EAAe,MAAM,SAAS,CAAC;AAajE,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAUD,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,UAAU,CAAC,CAqCrB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAgBD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAUD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAMrB"}
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "ci",
20
20
  "manifest-v3"
21
21
  ],
22
- "version": "1.0.0",
22
+ "version": "1.1.0",
23
23
  "repository": {
24
24
  "type": "git",
25
25
  "url": "git+https://github.com/extensiondev/deploy.git"
@@ -60,6 +60,7 @@
60
60
  "compile": "rslib build",
61
61
  "test": "vitest run",
62
62
  "build": "pnpm run compile",
63
+ "prepare": "pnpm run compile",
63
64
  "prepublishOnly": "pnpm run test && pnpm run compile"
64
65
  },
65
66
  "publishConfig": {