void 0.20.0 → 0.20.2

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 (93) hide show
  1. package/README.md +5 -1
  2. package/dist/{auth-W9WII-mN.mjs → auth-DPl6kck4.mjs} +46 -26
  3. package/dist/{auth-cmd-CYVhSNFy.mjs → auth-cmd-gniL2fNt.mjs} +5 -4
  4. package/dist/auth-link-NZdjCmSc.mjs +28 -0
  5. package/dist/{build-cmd-CkVD1uOh.mjs → build-cmd-sI18tX_O.mjs} +3 -3
  6. package/dist/{cache-QcUfR-ff.mjs → cache-IHn5MwBC.mjs} +3 -3
  7. package/dist/{cancel-deploy-DsvWKFTe.mjs → cancel-deploy-C5qTOdLi.mjs} +3 -3
  8. package/dist/cf-access-DRsQRe6k.mjs +75 -0
  9. package/dist/cli/cli.mjs +364 -1883
  10. package/dist/cli/env-schema-probe.mjs +11 -2
  11. package/dist/{client-CyCHWSO_.mjs → client-dHfSJvAN.mjs} +336 -58
  12. package/dist/{cloudflare-auth-DRkGe7-s.mjs → cloudflare-auth-6M5llVPC.mjs} +53 -6
  13. package/dist/{cloudflare-cmd-D3ME2GAe.mjs → cloudflare-cmd-4RPGN3KB.mjs} +2 -2
  14. package/dist/{cloudflare-connect-BivMefMA.mjs → cloudflare-connect-t1UU5svD.mjs} +2 -2
  15. package/dist/{cloudflare-operations-CPTpRW6d.mjs → cloudflare-operations-BzWnlC1_.mjs} +1 -1
  16. package/dist/{config-BQFq7QvD.mjs → config-uNGuFsI2.mjs} +1 -1
  17. package/dist/{connect-D9Yr-T5f.mjs → connect-Bfk31O_8.mjs} +6 -6
  18. package/dist/{create-project-DMV-csEm.mjs → create-project-Bk9Z0-Jg.mjs} +6 -5
  19. package/dist/{db-BxoUWL0F.mjs → db-BkRoptAt.mjs} +75 -48
  20. package/dist/{delete-iJOqxBz1.mjs → delete-DouASY9P.mjs} +3 -3
  21. package/dist/{deploy-CcDoeBIf.mjs → deploy-DTaWUS1S.mjs} +137 -128
  22. package/dist/{dev-inbox-DkgRWLkW.mjs → dev-inbox-P0u4tM8Y.mjs} +1 -1
  23. package/dist/{domain-gu_iaHmn.mjs → domain-1RhhOVrC.mjs} +4 -4
  24. package/dist/email-C-lGh51B.mjs +795 -0
  25. package/dist/{env-D4Emu-M_.mjs → env-DBKmK4vc.mjs} +1 -0
  26. package/dist/{env-DmU2To0C.mjs → env-DJHsPE7Z.mjs} +5 -5
  27. package/dist/{env-validation-ENpMy6Ez.mjs → env-validation-CF6KvTRf.mjs} +3 -1
  28. package/dist/{gen-BKw6qHIg.mjs → gen-B_wPnVTK.mjs} +3 -3
  29. package/dist/generate-RTK8_kK1.mjs +47 -0
  30. package/dist/{github-cmd-DJS5Ab-H.mjs → github-cmd-PW7ZnWTp.mjs} +3 -3
  31. package/dist/{headers-D8QfRX9Y.mjs → headers-BAHwgHdW.mjs} +1 -1
  32. package/dist/help-CwOX-zmI.mjs +2216 -0
  33. package/dist/{inbound-BJ70in1n.d.mts → inbound-CH5Mksyy.d.mts} +37 -42
  34. package/dist/{inbound-CNKxb3FY.mjs → inbound-aVHEUhKo.mjs} +143 -101
  35. package/dist/index.mjs +69 -30
  36. package/dist/{init-Dx5cgKqK.mjs → init-BWZ7q5Z4.mjs} +11 -11
  37. package/dist/{link-D_rm5sRH.mjs → link-Rmvu2Wl_.mjs} +4 -4
  38. package/dist/{list-M8XShti7.mjs → list-DEE2S6mY.mjs} +4 -4
  39. package/dist/{local-d1-BE8KBbMy.mjs → local-d1-D2I6Ox5F.mjs} +1 -1
  40. package/dist/{login-C8-UuLnp.mjs → login-Uvferzmm.mjs} +28 -10
  41. package/dist/{logs-DwFU7dMW.mjs → logs-27FenuiC.mjs} +4 -4
  42. package/dist/{mime-BJD7d_qL.mjs → mime-D5Nmdzf7.mjs} +23 -9
  43. package/dist/{node-BkaXcpAc.mjs → node-Ez5KW5rn.mjs} +3 -3
  44. package/dist/operator-auth-B3e08unv.mjs +52 -0
  45. package/dist/operator-client-LUZnlnYk.mjs +82 -0
  46. package/dist/{operator-cmd-DYWRbWUA.mjs → operator-cmd-CjOTmAYE.mjs} +35 -55
  47. package/dist/{output-tFQLLj26.mjs → output-B0cfNSx5.mjs} +316 -2
  48. package/dist/pages/index.mjs +2 -2
  49. package/dist/platform-auth-config-DrbQXXiW.mjs +368 -0
  50. package/dist/platform-auth-protection-Bhtvp0B_.mjs +219 -0
  51. package/dist/platform-auth-recovery-CeOKGVeJ.mjs +310 -0
  52. package/dist/{platform-cmd-BEOVv1PN.mjs → platform-cmd-BFhieCdV.mjs} +16 -6
  53. package/dist/{platform-domain-BszUfiS8.mjs → platform-domain-C74PULqV.mjs} +4 -4
  54. package/dist/{platform-lifecycle-CjSr6xf0.mjs → platform-lifecycle-BwAIgz-t.mjs} +1667 -191
  55. package/dist/{platform-management-W30iCaTL.mjs → platform-management-COogu_Se.mjs} +33 -7
  56. package/dist/{platform-recovery-pHHv4ZSg.mjs → platform-recovery-ewqLefp1.mjs} +6 -5
  57. package/dist/{prepare-CBetXvsN.mjs → prepare-CtDJjoOj.mjs} +2 -2
  58. package/dist/{prepare-BfJvFUtJ.mjs → prepare-blNRQvQl.mjs} +2 -2
  59. package/dist/prerender-render.d.mts +11 -0
  60. package/dist/prerender-render.mjs +111 -0
  61. package/dist/{project-cmd-DCpk1cDt.mjs → project-cmd-DmZK9Hxf.mjs} +32 -14
  62. package/dist/project-team-D8jOJMUJ.mjs +130 -0
  63. package/dist/project-token-DA34bf-C.mjs +75 -0
  64. package/dist/{provision-Blnstcm2.mjs → provision-CSJOjjQk.mjs} +2 -0
  65. package/dist/{requests-Dn8Vheh1.mjs → requests-CUExwGQQ.mjs} +3 -3
  66. package/dist/{rollback-CtlPXEBi.mjs → rollback-CDNGU1gr.mjs} +4 -4
  67. package/dist/{runner-mysql-CgRFl3s6.mjs → runner-mysql-7BPUNGmL.mjs} +1 -1
  68. package/dist/{runner-pg-DCkWPsWS.mjs → runner-pg-BkEza-dX.mjs} +1 -1
  69. package/dist/runtime/ai.mjs +3 -2
  70. package/dist/runtime/email/testing.d.mts +1 -1
  71. package/dist/runtime/email/testing.mjs +3 -3
  72. package/dist/runtime/email-protocol.d.mts +15 -0
  73. package/dist/runtime/email-protocol.mjs +70 -0
  74. package/dist/runtime/email.d.mts +2 -2
  75. package/dist/runtime/email.mjs +189 -96
  76. package/dist/runtime/remote/index.mjs +5 -3
  77. package/dist/{secret-BqTxGqki.mjs → secret-Bzzi2e9E.mjs} +5 -5
  78. package/dist/{skills-Q46GZMO-.mjs → skills-C0RvGjeE.mjs} +1 -1
  79. package/dist/sqlite-validation-BzKMWnO4.mjs +25 -0
  80. package/dist/{subcommand-prompt-WfySCQ7S.mjs → subcommand-prompt-Bmyn5Rlc.mjs} +1 -1
  81. package/dist/{validate-Bihr8WBi.mjs → validate-tBBN_dXH.mjs} +1 -0
  82. package/package.json +12 -7
  83. package/skills/void/SKILL.md +35 -4
  84. package/skills/void/docs/guide/deployment.md +2 -0
  85. package/skills/void/docs/guide/email.md +121 -98
  86. package/skills/void/docs/guide/platform-administration.md +214 -2
  87. package/skills/void/docs/guide/platform-development.md +93 -2
  88. package/skills/void/docs/guide/project-collaboration.md +94 -0
  89. package/skills/void/docs/guide/self-hosted-platform.md +184 -30
  90. package/skills/void/docs/reference/cli.md +294 -15
  91. package/dist/cf-access-AJ1ehiFR.mjs +0 -42
  92. package/dist/cf-access-DsSsZUPr.mjs +0 -67
  93. package/dist/email-r6DHJyAB.mjs +0 -262
package/README.md CHANGED
@@ -9,6 +9,10 @@ See [Platform Administration](../../docs/guide/platform-administration.md) for a
9
9
  walkthrough and the [CLI reference](../../docs/reference/cli.md#operator-commands)
10
10
  for every command.
11
11
 
12
+ Use `void platform config auth` to manage login methods and company signup.
13
+ Cloudflare Access protection has separate create/connect controls. Users can
14
+ link another enabled login to their account with `void auth link`.
15
+
12
16
  ## What It Covers
13
17
 
14
18
  - file-based API routes from `routes/`
@@ -58,7 +62,7 @@ export default defineConfig({
58
62
  - `void platform *` — list, select, inspect, install, recover, repair, upgrade, disable, and safely uninstall a company platform
59
63
  - `void deploy` — build and deploy to the saved Cloudflare or Void target
60
64
  - `void db *` — local DB and migration commands
61
- - `void project *` — target-aware status, logs, rollback, and managed-project operations
65
+ - `void project *` — target-aware status, logs, rollback, managed-project operations, and scoped CI deploy credentials
62
66
  - `void secret *` / `void domain *` — target-aware Worker secrets and custom domains
63
67
 
64
68
  Runtime helpers include:
@@ -1,8 +1,7 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-rQ84J-ij.mjs";
2
2
  import { n as dirname, o as join } from "./dist-BrsS7cai.mjs";
3
- import { G as normalizePlatformApiUrl, K as platformCredentialAccount, V as getActivePlatformConnection, W as listPlatformConnections, at as readKeyringPassword, it as deleteKeyringPassword, ot as writeKeyringPassword } from "./output-tFQLLj26.mjs";
4
- import { t as cfAccessHeaders } from "./cf-access-AJ1ehiFR.mjs";
5
- import { t as ensureCloudflaredToken } from "./cf-access-DsSsZUPr.mjs";
3
+ import { B as ensureCloudflaredToken, K as getActivePlatformConnection, X as normalizePlatformApiUrl, Y as listPlatformConnections, Z as platformCredentialAccount, dt as writeKeyringPassword, lt as deleteKeyringPassword, ut as readKeyringPassword } from "./output-B0cfNSx5.mjs";
4
+ import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
6
5
  import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
6
  import { createHash, randomBytes } from "node:crypto";
8
7
  import { homedir } from "node:os";
@@ -232,6 +231,7 @@ var auth_exports = /* @__PURE__ */ __exportAll({
232
231
  awaitBrowserCallback: () => awaitBrowserCallback,
233
232
  createCodeChallenge: () => createCodeChallenge,
234
233
  createCodeVerifier: () => createCodeVerifier,
234
+ getAccountCredential: () => getAccountCredential,
235
235
  getApiUrl: () => getApiUrl,
236
236
  getProxyUrl: () => getProxyUrl,
237
237
  getSiteDomain: () => getSiteDomain,
@@ -269,6 +269,22 @@ function writeConfig(config) {
269
269
  mkdirSync(CONFIG_DIR, { recursive: true });
270
270
  writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
271
271
  }
272
+ function readOriginScopedToken(apiUrl, config) {
273
+ const normalizedApiUrl = normalizePlatformApiUrl(apiUrl);
274
+ const account = platformCredentialAccount(normalizedApiUrl);
275
+ const keyringToken = keyringGet(account);
276
+ if (keyringToken) return keyringToken;
277
+ const fileToken = config.tokens?.[normalizedApiUrl];
278
+ if (!fileToken) return null;
279
+ if (keyringSet(account, fileToken)) {
280
+ delete config.tokens[normalizedApiUrl];
281
+ if (Object.keys(config.tokens).length === 0) delete config.tokens;
282
+ try {
283
+ writeConfig(config);
284
+ } catch {}
285
+ }
286
+ return fileToken;
287
+ }
272
288
  function isStagingMode(root = process.cwd()) {
273
289
  return isVoidInternalStaging(root);
274
290
  }
@@ -292,28 +308,28 @@ function getToken(root = process.cwd()) {
292
308
  if (envToken) throw error;
293
309
  return null;
294
310
  }
311
+ const config = readConfig();
312
+ return readTokenForOrigin(apiUrl, config, legacyCredentialAccount(root, apiUrl, config));
313
+ }
314
+ /** Account actions follow the selected connection, independently of application metadata. */
315
+ function getAccountCredential() {
316
+ const config = readConfig();
317
+ const apiUrl = normalizePlatformApiUrl(process.env.VOID_API_URL || (process.env.VOID_TOKEN ? DEFAULT_API_URL : getActivePlatformConnection()?.apiUrl ?? config.api ?? readLegacyHostedPlatformSelection()?.apiUrl ?? (keyringGet("token") ? DEFAULT_API_URL : keyringGet("stagingToken") ? STAGING_API_URL : DEFAULT_API_URL)));
318
+ return {
319
+ apiUrl,
320
+ token: readTokenForOrigin(apiUrl, config, legacyCredentialAccountForMode(apiUrl === STAGING_API_URL, apiUrl, config))
321
+ };
322
+ }
323
+ function readTokenForOrigin(apiUrl, config, legacyAccount) {
324
+ const envToken = process.env.VOID_TOKEN;
295
325
  if (envToken) {
296
- const tokenOrigin = process.env.VOID_API_URL ? normalizePlatformApiUrl(process.env.VOID_API_URL) : DEFAULT_API_URL;
297
- if (apiUrl !== tokenOrigin) throw new Error(`auth: VOID_TOKEN is not bound to ${apiUrl}. Set VOID_API_URL to this platform's URL with its matching token, or unset VOID_TOKEN to use the saved login.`);
326
+ if (apiUrl !== (process.env.VOID_API_URL ? normalizePlatformApiUrl(process.env.VOID_API_URL) : DEFAULT_API_URL)) throw new Error(`auth: VOID_TOKEN is not bound to ${apiUrl}. Set VOID_API_URL to this platform's URL with its matching token, or unset VOID_TOKEN to use the saved login.`);
298
327
  return envToken;
299
328
  }
300
- const account = platformCredentialAccount(apiUrl);
301
- const keyringToken = keyringGet(account);
302
- if (keyringToken) return keyringToken;
303
- const config = readConfig();
304
329
  const normalizedApiUrl = normalizePlatformApiUrl(apiUrl);
305
- const fileToken = config.tokens?.[normalizedApiUrl];
306
- if (fileToken) {
307
- if (keyringSet(account, fileToken)) {
308
- delete config.tokens[normalizedApiUrl];
309
- if (Object.keys(config.tokens).length === 0) delete config.tokens;
310
- try {
311
- writeConfig(config);
312
- } catch {}
313
- }
314
- return fileToken;
315
- }
316
- const legacyAccount = legacyCredentialAccount(root, normalizedApiUrl, config);
330
+ const originToken = readOriginScopedToken(normalizedApiUrl, config);
331
+ if (originToken) return originToken;
332
+ const account = platformCredentialAccount(normalizedApiUrl);
317
333
  if (legacyAccount) {
318
334
  const legacyKeyringToken = keyringGet(legacyAccount);
319
335
  if (legacyKeyringToken) {
@@ -342,7 +358,7 @@ function saveToken(token, root = process.cwd(), dependencies = {}) {
342
358
  savePlatformToken(token, getApiUrl(root), dependencies);
343
359
  }
344
360
  function readPlatformToken(apiUrl) {
345
- return keyringGet(platformCredentialAccount(normalizePlatformApiUrl(apiUrl)));
361
+ return readOriginScopedToken(apiUrl, readConfig());
346
362
  }
347
363
  function savePlatformToken(token, origin, dependencies = {}) {
348
364
  const apiUrl = normalizePlatformApiUrl(origin);
@@ -378,10 +394,13 @@ function removeToken(root = process.cwd()) {
378
394
  const DEFAULT_API_URL = VOID_CLOUD_PLATFORM.apiUrl;
379
395
  const STAGING_API_URL = VOID_CLOUD_STAGING_PLATFORM.apiUrl;
380
396
  function legacyCredentialAccount(root, normalizedApiUrl, config) {
381
- const account = isStagingMode(root) ? "stagingToken" : "token";
397
+ return legacyCredentialAccountForMode(isStagingMode(root), normalizedApiUrl, config);
398
+ }
399
+ function legacyCredentialAccountForMode(staging, normalizedApiUrl, config) {
400
+ const account = staging ? "stagingToken" : "token";
382
401
  let configuredUrl;
383
402
  try {
384
- configuredUrl = normalizePlatformApiUrl(config.api ?? (isStagingMode(root) ? STAGING_API_URL : DEFAULT_API_URL));
403
+ configuredUrl = normalizePlatformApiUrl(config.api ?? (staging ? STAGING_API_URL : DEFAULT_API_URL));
385
404
  } catch {
386
405
  return null;
387
406
  }
@@ -409,7 +428,8 @@ async function exchangeLoginCode(apiUrl, code, state, codeVerifier) {
409
428
  code,
410
429
  state,
411
430
  code_verifier: codeVerifier
412
- })
431
+ }),
432
+ redirect: "manual"
413
433
  });
414
434
  if (!res.ok) throw new Error(`auth: Failed to exchange login code (${res.status}). Try logging in again.`);
415
435
  let body;
@@ -627,4 +647,4 @@ async function runPlatformLogin(origin, provider = "github", onUrl) {
627
647
  });
628
648
  }
629
649
  //#endregion
630
- export { writeDeploymentPlatform as C, STAGING_PROXY_URL as D, DEFAULT_PROXY_URL as E, removeProjectConfig as S, writeProjectConfig as T, saveToken as _, getApiUrl as a, readDeploymentPlatform as b, getToken as c, openBrowser as d, readPlatformToken as f, savePlatformToken as g, runPlatformLogin as h, createCodeVerifier as i, getTokenSource as l, runLogin as m, awaitBrowserCallback as n, getProxyUrl as o, removeToken as p, createCodeChallenge as r, getSiteDomain as s, auth_exports as t, isStagingMode as u, attachSelectedPlatform as v, writePlatformSelection as w, readProjectConfig as x, project_exports as y };
650
+ export { removeProjectConfig as C, DEFAULT_PROXY_URL as D, writeProjectConfig as E, STAGING_PROXY_URL as O, readProjectConfig as S, writePlatformSelection as T, savePlatformToken as _, getAccountCredential as a, project_exports as b, getSiteDomain as c, isStagingMode as d, openBrowser as f, runPlatformLogin as g, runLogin as h, createCodeVerifier as i, getToken as l, removeToken as m, awaitBrowserCallback as n, getApiUrl as o, readPlatformToken as p, createCodeChallenge as r, getProxyUrl as s, auth_exports as t, getTokenSource as u, saveToken as v, writeDeploymentPlatform as w, readDeploymentPlatform as x, attachSelectedPlatform as y };
@@ -1,12 +1,13 @@
1
- import { D as log } from "./output-tFQLLj26.mjs";
2
- import { c as getToken, p as removeToken } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
4
- import { n as runLoginCommand } from "./login-C8-UuLnp.mjs";
1
+ import { D as log } from "./output-B0cfNSx5.mjs";
2
+ import { l as getToken, m as removeToken } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
+ import { r as runLoginCommand } from "./login-Uvferzmm.mjs";
5
5
  import { execSync } from "node:child_process";
6
6
  //#region src/cli/auth-cmd.ts
7
7
  async function runAuthCommand(root, args) {
8
8
  switch (args.subcommand) {
9
9
  case "login": return runLoginCommand(root);
10
+ case "link": return import("./auth-link-NZdjCmSc.mjs").then(({ runAuthLink }) => runAuthLink(root, args.connectionId));
10
11
  case "logout":
11
12
  if (removeToken(root)) log.success("Logged out.");
12
13
  else log.info("Not logged in.");
@@ -0,0 +1,28 @@
1
+ import { D as log } from "./output-B0cfNSx5.mjs";
2
+ import { _ as savePlatformToken, f as openBrowser, g as runPlatformLogin, l as getToken, o as getApiUrl } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
+ import { i as selectPlatformLoginMethod } from "./login-Uvferzmm.mjs";
5
+ import { discoverPlatform } from "./platform-cmd-BFhieCdV.mjs";
6
+ import { execFile } from "node:child_process";
7
+ //#region src/cli/auth-link.ts
8
+ async function runAuthLink(root, connectionId) {
9
+ const token = getToken(root);
10
+ if (!token) throw new Error("auth: Sign in to your existing account with `void auth login` first.");
11
+ const apiUrl = getApiUrl(root);
12
+ const platform = await discoverPlatform(apiUrl);
13
+ if (!platform.authentication) throw new Error("auth: This platform must be upgraded before linking login methods.");
14
+ const target = await selectPlatformLoginMethod(platform, connectionId);
15
+ const existing = await new PlatformClient(token, apiUrl).whoami();
16
+ if (!existing.id) throw new Error("auth: This platform does not support account linking.");
17
+ log.info(`Sign in again to ${existing.login} using an already linked login method.`);
18
+ const source = await selectPlatformLoginMethod(platform);
19
+ const freshToken = await runPlatformLogin(apiUrl, source.id, (url) => log.info(`Sign in: ${url}`));
20
+ const client = new PlatformClient(freshToken, apiUrl);
21
+ if ((await client.whoami()).id !== existing.id) throw new Error("auth: You signed in to a different Void account. Start again with a login method already linked to your original account.");
22
+ savePlatformToken(freshToken, apiUrl);
23
+ const launch = await client.startIdentityLink(target.id);
24
+ log.info(`Authenticate with ${target.label}, then review and confirm the identity in your browser.\n${launch.url}`);
25
+ openBrowser(launch.url, execFile);
26
+ }
27
+ //#endregion
28
+ export { runAuthLink };
@@ -1,6 +1,6 @@
1
- import { D as log, E as intro, a as dim, c as import_picocolors, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
- import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient, t as PlatformApiError } from "./client-CyCHWSO_.mjs";
1
+ import { A as outro, D as log, E as intro, a as dim, c as import_picocolors, r as cliTitle } from "./output-B0cfNSx5.mjs";
2
+ import { S as readProjectConfig, l as getToken } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient, t as PlatformApiError } from "./client-dHfSJvAN.mjs";
4
4
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
5
5
  import { appendFileSync, writeFileSync } from "node:fs";
6
6
  //#region src/cli/build-cmd.ts
@@ -1,6 +1,6 @@
1
- import { D as log, E as intro, a as dim, i as createSpinner, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
- import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
1
+ import { A as outro, D as log, E as intro, a as dim, i as createSpinner, r as cliTitle } from "./output-B0cfNSx5.mjs";
2
+ import { S as readProjectConfig, l as getToken } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
4
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
5
5
  //#region src/cli/cache.ts
6
6
  async function runPurgeCacheCommand(root, projectSlug) {
@@ -1,6 +1,6 @@
1
- import { D as log, E as intro, F as isCancel, k as outro, r as cliTitle, w as confirm } from "./output-tFQLLj26.mjs";
2
- import { c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-CyCHWSO_.mjs";
1
+ import { A as outro, D as log, E as intro, I as isCancel, r as cliTitle, w as confirm } from "./output-B0cfNSx5.mjs";
2
+ import { S as readProjectConfig, l as getToken } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
4
  //#region src/cli/cancel-deploy.ts
5
5
  const ACTIVE_STATUSES = /* @__PURE__ */ new Set([
6
6
  "pending",
@@ -0,0 +1,75 @@
1
+ //#region src/shared/cf-access.ts
2
+ /**
3
+ * Resolve Cloudflare Access headers from an env-like object.
4
+ *
5
+ * Priority:
6
+ * 1. Service token pair (`CF_ACCESS_CLIENT_ID` + `CF_ACCESS_CLIENT_SECRET`) — CI path
7
+ * 2. User JWT (`CF_ACCESS_TOKEN`) — dev path, typically populated via `cloudflared access token`
8
+ * 3. No headers — prod, or unprotected hostnames
9
+ */
10
+ function isVoidAccessGatedUrl(targetUrl) {
11
+ try {
12
+ const url = new URL(targetUrl);
13
+ return url.protocol === "https:" && (url.hostname.endsWith(".staging.void.cloud") || url.hostname.endsWith(".staging.void.app"));
14
+ } catch {
15
+ return false;
16
+ }
17
+ }
18
+ function accessHeaders(env) {
19
+ const id = env.CF_ACCESS_CLIENT_ID;
20
+ const secret = env.CF_ACCESS_CLIENT_SECRET;
21
+ if (typeof id === "string" && typeof secret === "string" && id.length > 0 && secret.length > 0) return {
22
+ "CF-Access-Client-Id": id,
23
+ "CF-Access-Client-Secret": secret
24
+ };
25
+ const token = env.CF_ACCESS_TOKEN;
26
+ if (typeof token === "string" && token.length > 0) return { "cf-access-token": token };
27
+ return {};
28
+ }
29
+ /** Attach shared Void Access credentials only to known hosted staging origins. */
30
+ function cfAccessHeaders(env, targetUrl) {
31
+ let origin;
32
+ try {
33
+ const target = new URL(targetUrl);
34
+ if (target.protocol !== "https:" || target.username || target.password) return {};
35
+ origin = target.origin;
36
+ } catch {
37
+ return {};
38
+ }
39
+ const encoded = env.VOID_ACCESS_CREDENTIALS ?? env.__VOID_ACCESS_CREDENTIALS;
40
+ if (typeof encoded === "string" && encoded) try {
41
+ const records = JSON.parse(encoded);
42
+ if (!records || typeof records !== "object" || Array.isArray(records)) return {};
43
+ const entry = records && typeof records === "object" && !Array.isArray(records) && Object.hasOwn(records, origin) ? records[origin] : void 0;
44
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) return accessHeaders(entry);
45
+ if (Object.hasOwn(records, origin)) return {};
46
+ } catch {
47
+ return {};
48
+ }
49
+ if (typeof env.VOID_ACCESS_ORIGIN === "string" && env.VOID_ACCESS_ORIGIN) try {
50
+ const selected = new URL(env.VOID_ACCESS_ORIGIN);
51
+ return selected.protocol === "https:" && !selected.username && !selected.password && selected.pathname === "/" && !selected.search && !selected.hash && selected.origin === origin ? accessHeaders(env) : {};
52
+ } catch {
53
+ return {};
54
+ }
55
+ return isVoidAccessGatedUrl(targetUrl) ? accessHeaders(env) : {};
56
+ }
57
+ /**
58
+ * Capture credentials for a Cloudflare Worker readiness request whose target
59
+ * is resolved and constrained by the direct-deploy adapter rather than a
60
+ * user-connected Void platform URL.
61
+ */
62
+ function trustedCloudflareWorkerAccessHeaders(env) {
63
+ return accessHeaders(env);
64
+ }
65
+ /** Keep only this recipient's credentials when crossing into a local Worker runtime. */
66
+ function scopedAccessCredentials(env, targetUrl) {
67
+ const headers = cfAccessHeaders(env, targetUrl);
68
+ if (Object.keys(headers).length === 0) return;
69
+ return JSON.stringify({ [new URL(targetUrl).origin]: headers["CF-Access-Client-Id"] ? {
70
+ CF_ACCESS_CLIENT_ID: headers["CF-Access-Client-Id"],
71
+ CF_ACCESS_CLIENT_SECRET: headers["CF-Access-Client-Secret"]
72
+ } : { CF_ACCESS_TOKEN: headers["cf-access-token"] } });
73
+ }
74
+ //#endregion
75
+ export { trustedCloudflareWorkerAccessHeaders as i, isVoidAccessGatedUrl as n, scopedAccessCredentials as r, cfAccessHeaders as t };