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.
- package/README.md +5 -1
- package/dist/{auth-W9WII-mN.mjs → auth-DPl6kck4.mjs} +46 -26
- package/dist/{auth-cmd-CYVhSNFy.mjs → auth-cmd-gniL2fNt.mjs} +5 -4
- package/dist/auth-link-NZdjCmSc.mjs +28 -0
- package/dist/{build-cmd-CkVD1uOh.mjs → build-cmd-sI18tX_O.mjs} +3 -3
- package/dist/{cache-QcUfR-ff.mjs → cache-IHn5MwBC.mjs} +3 -3
- package/dist/{cancel-deploy-DsvWKFTe.mjs → cancel-deploy-C5qTOdLi.mjs} +3 -3
- package/dist/cf-access-DRsQRe6k.mjs +75 -0
- package/dist/cli/cli.mjs +364 -1883
- package/dist/cli/env-schema-probe.mjs +11 -2
- package/dist/{client-CyCHWSO_.mjs → client-dHfSJvAN.mjs} +336 -58
- package/dist/{cloudflare-auth-DRkGe7-s.mjs → cloudflare-auth-6M5llVPC.mjs} +53 -6
- package/dist/{cloudflare-cmd-D3ME2GAe.mjs → cloudflare-cmd-4RPGN3KB.mjs} +2 -2
- package/dist/{cloudflare-connect-BivMefMA.mjs → cloudflare-connect-t1UU5svD.mjs} +2 -2
- package/dist/{cloudflare-operations-CPTpRW6d.mjs → cloudflare-operations-BzWnlC1_.mjs} +1 -1
- package/dist/{config-BQFq7QvD.mjs → config-uNGuFsI2.mjs} +1 -1
- package/dist/{connect-D9Yr-T5f.mjs → connect-Bfk31O_8.mjs} +6 -6
- package/dist/{create-project-DMV-csEm.mjs → create-project-Bk9Z0-Jg.mjs} +6 -5
- package/dist/{db-BxoUWL0F.mjs → db-BkRoptAt.mjs} +75 -48
- package/dist/{delete-iJOqxBz1.mjs → delete-DouASY9P.mjs} +3 -3
- package/dist/{deploy-CcDoeBIf.mjs → deploy-DTaWUS1S.mjs} +137 -128
- package/dist/{dev-inbox-DkgRWLkW.mjs → dev-inbox-P0u4tM8Y.mjs} +1 -1
- package/dist/{domain-gu_iaHmn.mjs → domain-1RhhOVrC.mjs} +4 -4
- package/dist/email-C-lGh51B.mjs +795 -0
- package/dist/{env-D4Emu-M_.mjs → env-DBKmK4vc.mjs} +1 -0
- package/dist/{env-DmU2To0C.mjs → env-DJHsPE7Z.mjs} +5 -5
- package/dist/{env-validation-ENpMy6Ez.mjs → env-validation-CF6KvTRf.mjs} +3 -1
- package/dist/{gen-BKw6qHIg.mjs → gen-B_wPnVTK.mjs} +3 -3
- package/dist/generate-RTK8_kK1.mjs +47 -0
- package/dist/{github-cmd-DJS5Ab-H.mjs → github-cmd-PW7ZnWTp.mjs} +3 -3
- package/dist/{headers-D8QfRX9Y.mjs → headers-BAHwgHdW.mjs} +1 -1
- package/dist/help-CwOX-zmI.mjs +2216 -0
- package/dist/{inbound-BJ70in1n.d.mts → inbound-CH5Mksyy.d.mts} +37 -42
- package/dist/{inbound-CNKxb3FY.mjs → inbound-aVHEUhKo.mjs} +143 -101
- package/dist/index.mjs +69 -30
- package/dist/{init-Dx5cgKqK.mjs → init-BWZ7q5Z4.mjs} +11 -11
- package/dist/{link-D_rm5sRH.mjs → link-Rmvu2Wl_.mjs} +4 -4
- package/dist/{list-M8XShti7.mjs → list-DEE2S6mY.mjs} +4 -4
- package/dist/{local-d1-BE8KBbMy.mjs → local-d1-D2I6Ox5F.mjs} +1 -1
- package/dist/{login-C8-UuLnp.mjs → login-Uvferzmm.mjs} +28 -10
- package/dist/{logs-DwFU7dMW.mjs → logs-27FenuiC.mjs} +4 -4
- package/dist/{mime-BJD7d_qL.mjs → mime-D5Nmdzf7.mjs} +23 -9
- package/dist/{node-BkaXcpAc.mjs → node-Ez5KW5rn.mjs} +3 -3
- package/dist/operator-auth-B3e08unv.mjs +52 -0
- package/dist/operator-client-LUZnlnYk.mjs +82 -0
- package/dist/{operator-cmd-DYWRbWUA.mjs → operator-cmd-CjOTmAYE.mjs} +35 -55
- package/dist/{output-tFQLLj26.mjs → output-B0cfNSx5.mjs} +316 -2
- package/dist/pages/index.mjs +2 -2
- package/dist/platform-auth-config-DrbQXXiW.mjs +368 -0
- package/dist/platform-auth-protection-Bhtvp0B_.mjs +219 -0
- package/dist/platform-auth-recovery-CeOKGVeJ.mjs +310 -0
- package/dist/{platform-cmd-BEOVv1PN.mjs → platform-cmd-BFhieCdV.mjs} +16 -6
- package/dist/{platform-domain-BszUfiS8.mjs → platform-domain-C74PULqV.mjs} +4 -4
- package/dist/{platform-lifecycle-CjSr6xf0.mjs → platform-lifecycle-BwAIgz-t.mjs} +1667 -191
- package/dist/{platform-management-W30iCaTL.mjs → platform-management-COogu_Se.mjs} +33 -7
- package/dist/{platform-recovery-pHHv4ZSg.mjs → platform-recovery-ewqLefp1.mjs} +6 -5
- package/dist/{prepare-CBetXvsN.mjs → prepare-CtDJjoOj.mjs} +2 -2
- package/dist/{prepare-BfJvFUtJ.mjs → prepare-blNRQvQl.mjs} +2 -2
- package/dist/prerender-render.d.mts +11 -0
- package/dist/prerender-render.mjs +111 -0
- package/dist/{project-cmd-DCpk1cDt.mjs → project-cmd-DmZK9Hxf.mjs} +32 -14
- package/dist/project-team-D8jOJMUJ.mjs +130 -0
- package/dist/project-token-DA34bf-C.mjs +75 -0
- package/dist/{provision-Blnstcm2.mjs → provision-CSJOjjQk.mjs} +2 -0
- package/dist/{requests-Dn8Vheh1.mjs → requests-CUExwGQQ.mjs} +3 -3
- package/dist/{rollback-CtlPXEBi.mjs → rollback-CDNGU1gr.mjs} +4 -4
- package/dist/{runner-mysql-CgRFl3s6.mjs → runner-mysql-7BPUNGmL.mjs} +1 -1
- package/dist/{runner-pg-DCkWPsWS.mjs → runner-pg-BkEza-dX.mjs} +1 -1
- package/dist/runtime/ai.mjs +3 -2
- package/dist/runtime/email/testing.d.mts +1 -1
- package/dist/runtime/email/testing.mjs +3 -3
- package/dist/runtime/email-protocol.d.mts +15 -0
- package/dist/runtime/email-protocol.mjs +70 -0
- package/dist/runtime/email.d.mts +2 -2
- package/dist/runtime/email.mjs +189 -96
- package/dist/runtime/remote/index.mjs +5 -3
- package/dist/{secret-BqTxGqki.mjs → secret-Bzzi2e9E.mjs} +5 -5
- package/dist/{skills-Q46GZMO-.mjs → skills-C0RvGjeE.mjs} +1 -1
- package/dist/sqlite-validation-BzKMWnO4.mjs +25 -0
- package/dist/{subcommand-prompt-WfySCQ7S.mjs → subcommand-prompt-Bmyn5Rlc.mjs} +1 -1
- package/dist/{validate-Bihr8WBi.mjs → validate-tBBN_dXH.mjs} +1 -0
- package/package.json +12 -7
- package/skills/void/SKILL.md +35 -4
- package/skills/void/docs/guide/deployment.md +2 -0
- package/skills/void/docs/guide/email.md +121 -98
- package/skills/void/docs/guide/platform-administration.md +214 -2
- package/skills/void/docs/guide/platform-development.md +93 -2
- package/skills/void/docs/guide/project-collaboration.md +94 -0
- package/skills/void/docs/guide/self-hosted-platform.md +184 -30
- package/skills/void/docs/reference/cli.md +294 -15
- package/dist/cf-access-AJ1ehiFR.mjs +0 -42
- package/dist/cf-access-DsSsZUPr.mjs +0 -67
- package/dist/email-r6DHJyAB.mjs +0 -262
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import { n as __exportAll, r as __toESM, t as __commonJSMin } from "./rolldown-runtime-rQ84J-ij.mjs";
|
|
2
2
|
import { c as relative, i as extname, l as resolve, n as dirname, o as join, s as normalize, t as basename } from "./dist-BrsS7cai.mjs";
|
|
3
|
-
import { D as log$1, E as intro,
|
|
3
|
+
import { A as outro, B as ensureCloudflaredToken, D as log$1, E as intro, H as ensurePlatformProxyAccess, I as isCancel, M as select, c as import_picocolors$1, d as formatCloudflareUserMessage, ft as require_picocolors, i as createSpinner, k as note, r as cliTitle, w as confirm } from "./output-B0cfNSx5.mjs";
|
|
4
4
|
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-SK8nMHPp.mjs";
|
|
5
5
|
import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig } from "./scan-BMH4rzlv.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as ensureCloudflaredToken } from "./cf-access-DsSsZUPr.mjs";
|
|
6
|
+
import { i as trustedCloudflareWorkerAccessHeaders, r as scopedAccessCredentials, t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
|
|
7
|
+
import { E as writeProjectConfig, S as readProjectConfig, d as isStagingMode, l as getToken, o as getApiUrl, s as getProxyUrl, u as getTokenSource, w as writeDeploymentPlatform, x as readDeploymentPlatform, y as attachSelectedPlatform } from "./auth-DPl6kck4.mjs";
|
|
9
8
|
import { A as writeWranglerPublishedTrafficSnapshot, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, M as isSandboxEnabled, N as requiresSandboxPlatformImage, P as resolveSandboxConfig, S as readWranglerPublishedTrafficSnapshot, T as syncWranglerBindings, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, f as findBindingNameOwner, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, k as writeProvisionedWranglerConfig, l as ensureWranglerCompat, o as acknowledgeWranglerManagedQueueRemovals, r as FRIENDLY_BINDING_NAMES, w as resolveLiveBindingConfig, x as readWranglerManagedQueueCleanupCandidates } from "./wrangler--imS8n0d.mjs";
|
|
10
|
-
import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-
|
|
9
|
+
import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-uNGuFsI2.mjs";
|
|
11
10
|
import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
|
|
12
|
-
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-
|
|
11
|
+
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-BAHwgHdW.mjs";
|
|
13
12
|
import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-BDRfZngg.mjs";
|
|
14
13
|
import { o as validateSsrEntry } from "./entry-DU3oDoQ3.mjs";
|
|
15
|
-
import { a as buildMigrationPlanBundle, c as collectMigrations, r as validateMigrations, t as assertJournalCoherence } from "./validate-
|
|
14
|
+
import { a as buildMigrationPlanBundle, c as collectMigrations, r as validateMigrations, t as assertJournalCoherence } from "./validate-tBBN_dXH.mjs";
|
|
16
15
|
import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
|
|
17
16
|
import { t as discoverSchema } from "./discover-xvfrgJeo.mjs";
|
|
18
17
|
import { t as findEnvFile } from "./env-types-BNPhro-M.mjs";
|
|
19
|
-
import { a as deriveSelfHostEnvContextFromVars, c as fetchRemoteSecretNames, d as readEmittedWorkerVars, f as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as formatEnvReport, n as SelfHostFirstDeployError, o as dischargeSelfHostEnvContext, p as validateProdEnv, r as SelfHostSchemaError, t as SelfHostEnvValidationError, u as listSelfHostSecretNames } from "./env-validation-
|
|
20
|
-
import { n as CLOUDFLARE_DEPLOY_BUILD_ENV, o as resolveRemoteMode, s as stripInternalEnvKeys } from "./env-
|
|
18
|
+
import { a as deriveSelfHostEnvContextFromVars, c as fetchRemoteSecretNames, d as readEmittedWorkerVars, f as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as formatEnvReport, n as SelfHostFirstDeployError, o as dischargeSelfHostEnvContext, p as validateProdEnv, r as SelfHostSchemaError, t as SelfHostEnvValidationError, u as listSelfHostSecretNames } from "./env-validation-CF6KvTRf.mjs";
|
|
19
|
+
import { n as CLOUDFLARE_DEPLOY_BUILD_ENV, o as resolveRemoteMode, s as stripInternalEnvKeys } from "./env-DBKmK4vc.mjs";
|
|
21
20
|
import { n as writeDrizzleConfig } from "./config-NOG_U1aK.mjs";
|
|
22
|
-
import { t as runMySqlMigrations } from "./runner-mysql-
|
|
23
|
-
import { t as runPgMigrations } from "./runner-pg-
|
|
21
|
+
import { t as runMySqlMigrations } from "./runner-mysql-7BPUNGmL.mjs";
|
|
22
|
+
import { t as runPgMigrations } from "./runner-pg-BkEza-dX.mjs";
|
|
23
|
+
import { n as openMigrationValidationDatabase, t as SqliteMigrationError } from "./sqlite-validation-BzKMWnO4.mjs";
|
|
24
24
|
import { t as scanPages } from "./scan-CpK-57ug.mjs";
|
|
25
|
+
import { renderPrerenderPaths } from "./prerender-render.mjs";
|
|
25
26
|
import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email-Ce6SQq-i.mjs";
|
|
26
|
-
import { a as isExpiredTokenError, i as isCliOutdatedError, n as PlatformClient, o as parsePlatformErrorBody, t as PlatformApiError } from "./client-
|
|
27
|
+
import { a as isExpiredTokenError, i as isCliOutdatedError, n as PlatformClient, o as parsePlatformErrorBody, t as PlatformApiError } from "./client-dHfSJvAN.mjs";
|
|
27
28
|
import { a as resolveProjectCommand, i as hasBackendFiles, n as detectPreset, o as resolveWranglerArgv, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-lAy0B0BQ.mjs";
|
|
28
|
-
import {
|
|
29
|
-
import { n as createCloudflareEmptyDomainPublisher } from "./cloudflare-operations-
|
|
30
|
-
import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-
|
|
29
|
+
import { i as cloudflareKeyringNeedsTerminal, s as ensureCloudflareAuthentication, t as CloudflareAuthenticationError } from "./cloudflare-auth-6M5llVPC.mjs";
|
|
30
|
+
import { n as createCloudflareEmptyDomainPublisher } from "./cloudflare-operations-BzWnlC1_.mjs";
|
|
31
|
+
import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-Bk9Z0-Jg.mjs";
|
|
31
32
|
import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project--Vxawf7z.mjs";
|
|
32
33
|
import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
|
|
33
|
-
import {
|
|
34
|
+
import { n as promptForLoginToken } from "./login-Uvferzmm.mjs";
|
|
34
35
|
import { createRequire } from "node:module";
|
|
35
36
|
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
36
37
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -42,7 +43,7 @@ import { applyEdits, modify, parse } from "jsonc-parser";
|
|
|
42
43
|
import { build } from "vite";
|
|
43
44
|
import { Minimatch } from "minimatch";
|
|
44
45
|
import { isDeepStrictEqual } from "node:util";
|
|
45
|
-
import { activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
|
|
46
|
+
import { activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, createCloudflareMetadataRunner, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
|
|
46
47
|
import { hash } from "blake3-jit";
|
|
47
48
|
import ignore from "ignore";
|
|
48
49
|
//#region src/asset-routing.ts
|
|
@@ -596,7 +597,7 @@ async function preflightEmail(inputs) {
|
|
|
596
597
|
status: settings.status,
|
|
597
598
|
enabled: settings.enabled
|
|
598
599
|
};
|
|
599
|
-
if (
|
|
600
|
+
if (settings.status === "unlocked") block("all", `Email Routing on ${apex} is ${settings.status} — fix it in the Cloudflare dashboard; Void never re-locks records you unlocked`);
|
|
600
601
|
}
|
|
601
602
|
}
|
|
602
603
|
if (pre.routing.state !== "ready") {
|
|
@@ -1506,6 +1507,8 @@ const UNTRUSTED_PROJECT_CODE_ENV_VARS = [
|
|
|
1506
1507
|
...WRANGLER_AUTH_CREDENTIAL_ENV_VARS,
|
|
1507
1508
|
"CF_ACCESS_CLIENT_ID",
|
|
1508
1509
|
"CF_ACCESS_CLIENT_SECRET",
|
|
1510
|
+
"VOID_ACCESS_CREDENTIALS",
|
|
1511
|
+
"VOID_ACCESS_ORIGIN",
|
|
1509
1512
|
"VOID_TOKEN",
|
|
1510
1513
|
"DATABASE_URL",
|
|
1511
1514
|
"ACTIONS_ID_TOKEN_REQUEST_URL",
|
|
@@ -1533,61 +1536,16 @@ function buildEnv(extra, options) {
|
|
|
1533
1536
|
//#endregion
|
|
1534
1537
|
//#region src/prerender.ts
|
|
1535
1538
|
const PRERENDER_PATHS_ENDPOINT = "/__void/prerender-paths";
|
|
1536
|
-
const
|
|
1539
|
+
const nodeRendererUrl = new URL(import.meta.url.endsWith(".ts") ? "./prerender-render.ts" : "./prerender-render.mjs", import.meta.url).href;
|
|
1537
1540
|
function outputFileForPath(path) {
|
|
1538
1541
|
return path === "/" ? "index.html" : `${path.slice(1)}.html`;
|
|
1539
1542
|
}
|
|
1540
|
-
function pageDataFileForPath(path) {
|
|
1541
|
-
return path === "/" ? `${STATIC_PAGE_DATA_DIR}/index.json` : `${STATIC_PAGE_DATA_DIR}/${path.slice(1)}.json`;
|
|
1542
|
-
}
|
|
1543
1543
|
async function readPrerenderPathsResponse(response) {
|
|
1544
1544
|
if (!response.ok) throw new Error(`prerender: Failed to collect prerender paths. HTTP ${response.status}.`);
|
|
1545
1545
|
const payload = await response.json();
|
|
1546
1546
|
if (!Array.isArray(payload.paths) || !payload.paths.every((path) => typeof path === "string")) throw new Error("prerender: Failed to collect prerender paths. Response payload is invalid.");
|
|
1547
1547
|
return payload.paths;
|
|
1548
1548
|
}
|
|
1549
|
-
async function renderPrerenderPaths(paths, clientDir, fetchPath, fetchPageData) {
|
|
1550
|
-
const result = {
|
|
1551
|
-
rendered: [],
|
|
1552
|
-
failed: []
|
|
1553
|
-
};
|
|
1554
|
-
for (const path of paths) try {
|
|
1555
|
-
const response = await fetchPath(path);
|
|
1556
|
-
const html = await response.text();
|
|
1557
|
-
if (!response.ok) {
|
|
1558
|
-
result.failed.push({
|
|
1559
|
-
path,
|
|
1560
|
-
error: `HTTP ${response.status}`
|
|
1561
|
-
});
|
|
1562
|
-
voidWarn(`prerender ${path} failed: HTTP ${response.status}`);
|
|
1563
|
-
continue;
|
|
1564
|
-
}
|
|
1565
|
-
const outputFile = outputFileForPath(path);
|
|
1566
|
-
const outputPath = join(clientDir, outputFile);
|
|
1567
|
-
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1568
|
-
writeFileSync(outputPath, html);
|
|
1569
|
-
if (fetchPageData) {
|
|
1570
|
-
const pageDataResponse = await fetchPageData(path);
|
|
1571
|
-
if (pageDataResponse.headers.get("X-VoidPages")) {
|
|
1572
|
-
const pageData = await pageDataResponse.json();
|
|
1573
|
-
const pageDataFile = pageDataFileForPath(path);
|
|
1574
|
-
const pageDataPath = join(clientDir, pageDataFile);
|
|
1575
|
-
mkdirSync(dirname(pageDataPath), { recursive: true });
|
|
1576
|
-
writeFileSync(pageDataPath, JSON.stringify(pageData));
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
result.rendered.push(path);
|
|
1580
|
-
voidLog(`prerender \x1b[36m${outputFile}\x1b[39m`);
|
|
1581
|
-
} catch (err) {
|
|
1582
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
1583
|
-
result.failed.push({
|
|
1584
|
-
path,
|
|
1585
|
-
error
|
|
1586
|
-
});
|
|
1587
|
-
voidWarn(`prerender ${path} failed: ${error}`);
|
|
1588
|
-
}
|
|
1589
|
-
return result;
|
|
1590
|
-
}
|
|
1591
1549
|
function normalizeWorkerModulePath(path) {
|
|
1592
1550
|
return path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1593
1551
|
}
|
|
@@ -1645,6 +1603,8 @@ function buildPrerenderBindings(input) {
|
|
|
1645
1603
|
voidBindings.__VOID_PROJECT_ID = input.voidProjectId;
|
|
1646
1604
|
if (input.voidStaging) voidBindings.__VOID_STAGING = "1";
|
|
1647
1605
|
voidBindings.__VOID_PROXY_URL = input.voidProxyUrl ?? (input.voidStaging ? "https://proxy.staging.void.cloud" : "https://proxy.void.cloud");
|
|
1606
|
+
const access = scopedAccessCredentials(input.accessEnv ?? {}, voidBindings.__VOID_PROXY_URL);
|
|
1607
|
+
if (access) voidBindings.__VOID_ACCESS_CREDENTIALS = access;
|
|
1648
1608
|
if (input.remoteMode) voidBindings.__VOID_REMOTE = "1";
|
|
1649
1609
|
}
|
|
1650
1610
|
return {
|
|
@@ -1672,7 +1632,9 @@ async function createCloudflarePrerenderRunner(options) {
|
|
|
1672
1632
|
const voidToken = voidProjectId ? options.voidToken ?? getToken(root) : null;
|
|
1673
1633
|
const voidStaging = isStagingMode(root);
|
|
1674
1634
|
const voidProxyUrl = voidToken && voidProjectId ? getProxyUrl(root) : void 0;
|
|
1635
|
+
if (voidProxyUrl) ensurePlatformProxyAccess(getApiUrl(root), voidProxyUrl);
|
|
1675
1636
|
const bindings = buildPrerenderBindings({
|
|
1637
|
+
accessEnv: process.env,
|
|
1676
1638
|
wranglerVars: wranglerConfig.vars,
|
|
1677
1639
|
env,
|
|
1678
1640
|
voidToken,
|
|
@@ -1770,7 +1732,10 @@ async function prerenderPages(options) {
|
|
|
1770
1732
|
};
|
|
1771
1733
|
return {
|
|
1772
1734
|
paths,
|
|
1773
|
-
...await renderPrerenderPaths(paths, options.clientDir, (path) => runner.fetchPath(path), (path) => runner.fetchPageData(path))
|
|
1735
|
+
...await renderPrerenderPaths(paths, options.clientDir, (path) => runner.fetchPath(path), (path) => runner.fetchPageData(path), (path, outputFile, error) => {
|
|
1736
|
+
if (error !== void 0) voidWarn(`prerender ${path} failed: ${error}`);
|
|
1737
|
+
else voidLog(`prerender \x1b[36m${outputFile}\x1b[39m`);
|
|
1738
|
+
})
|
|
1774
1739
|
};
|
|
1775
1740
|
} finally {
|
|
1776
1741
|
await runner.close();
|
|
@@ -1782,7 +1747,7 @@ async function runNodePrerenderRunner(root, config) {
|
|
|
1782
1747
|
writeFileSync(runnerPath, `
|
|
1783
1748
|
import { pathToFileURL } from "node:url";
|
|
1784
1749
|
import { dirname, join } from "node:path";
|
|
1785
|
-
import {
|
|
1750
|
+
import { renderPrerenderPaths } from ${JSON.stringify(nodeRendererUrl)};
|
|
1786
1751
|
|
|
1787
1752
|
const config = JSON.parse(process.argv[2]);
|
|
1788
1753
|
const { mode, ssrDir, clientDir } = config;
|
|
@@ -1813,37 +1778,13 @@ async function collectPaths() {
|
|
|
1813
1778
|
|
|
1814
1779
|
async function renderPaths(paths) {
|
|
1815
1780
|
if (!clientDir) return { rendered: [], failed: [] };
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
result.failed.push({ path, error: "HTTP " + response.status });
|
|
1824
|
-
continue;
|
|
1825
|
-
}
|
|
1826
|
-
const outputFile = path === "/" ? "index.html" : path.slice(1) + ".html";
|
|
1827
|
-
const outputPath = join(clientDir, outputFile);
|
|
1828
|
-
mkdirSync(dirname(outputPath), { recursive: true });
|
|
1829
|
-
writeFileSync(outputPath, html);
|
|
1830
|
-
const pageDataResponse = await fetch(new Request("http://localhost" + path, {
|
|
1831
|
-
headers: { "Accept": "application/json", "Purpose": "prefetch", "X-VoidPages": "true" },
|
|
1832
|
-
}));
|
|
1833
|
-
if (pageDataResponse.headers.get("X-VoidPages")) {
|
|
1834
|
-
const pageData = await pageDataResponse.json();
|
|
1835
|
-
const pageDataFile = path === "/" ? "_void/pages/index.json" : "_void/pages/" + path.slice(1) + ".json";
|
|
1836
|
-
const pageDataPath = join(clientDir, pageDataFile);
|
|
1837
|
-
mkdirSync(dirname(pageDataPath), { recursive: true });
|
|
1838
|
-
writeFileSync(pageDataPath, JSON.stringify(pageData));
|
|
1839
|
-
}
|
|
1840
|
-
result.rendered.push(path);
|
|
1841
|
-
} catch (err) {
|
|
1842
|
-
result.failed.push({ path, error: err instanceof Error ? err.message : String(err) });
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
return result;
|
|
1781
|
+
return renderPrerenderPaths(
|
|
1782
|
+
paths, clientDir,
|
|
1783
|
+
(path) => fetch(new Request("http://localhost" + path)),
|
|
1784
|
+
(path) => fetch(new Request("http://localhost" + path, {
|
|
1785
|
+
headers: { "Accept": "application/json", "Purpose": "prefetch", "X-VoidPages": "true" },
|
|
1786
|
+
})),
|
|
1787
|
+
);
|
|
1847
1788
|
}
|
|
1848
1789
|
|
|
1849
1790
|
if (mode === "collect") {
|
|
@@ -2409,7 +2350,10 @@ async function requestGithubOidcToken(requestUrl, requestToken) {
|
|
|
2409
2350
|
url.searchParams.set("audience", OIDC_AUDIENCE);
|
|
2410
2351
|
let res;
|
|
2411
2352
|
try {
|
|
2412
|
-
res = await fetch(url, {
|
|
2353
|
+
res = await fetch(url, {
|
|
2354
|
+
headers: { Authorization: `Bearer ${requestToken}` },
|
|
2355
|
+
redirect: "manual"
|
|
2356
|
+
});
|
|
2413
2357
|
} catch (err) {
|
|
2414
2358
|
throw new Error(`github-oidc: Failed to reach the GitHub OIDC token endpoint: ${errText(err)}`);
|
|
2415
2359
|
}
|
|
@@ -2442,7 +2386,8 @@ async function exchangeOidcTokenAtApi(apiUrl, project, oidcToken) {
|
|
|
2442
2386
|
body: JSON.stringify({
|
|
2443
2387
|
oidcToken,
|
|
2444
2388
|
project
|
|
2445
|
-
})
|
|
2389
|
+
}),
|
|
2390
|
+
redirect: "manual"
|
|
2446
2391
|
});
|
|
2447
2392
|
} catch (err) {
|
|
2448
2393
|
throw new Error(`github-oidc: Failed to reach ${url}: ${errText(err)}`);
|
|
@@ -3168,6 +3113,7 @@ function buildVoidManifest(opts) {
|
|
|
3168
3113
|
assetManifestVersion: 2,
|
|
3169
3114
|
bindings: {}
|
|
3170
3115
|
};
|
|
3116
|
+
if (opts.hasEmailHandlers) manifest.emailProtocolVersion = 1;
|
|
3171
3117
|
if (bindings.needsAuth) manifest.auth = true;
|
|
3172
3118
|
const hasMigrations = migrations && migrations.length > 0;
|
|
3173
3119
|
if (bindings.needsD1 || bindings.needsAuth || hasMigrations) {
|
|
@@ -3471,8 +3417,8 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3471
3417
|
let migrations;
|
|
3472
3418
|
let migrationPlanBundle;
|
|
3473
3419
|
if (features.hasMigrations) {
|
|
3474
|
-
const { collectMigrations } = await import("./validate-
|
|
3475
|
-
const { buildMigrationPlanBundle } = await import("./validate-
|
|
3420
|
+
const { collectMigrations } = await import("./validate-tBBN_dXH.mjs").then((n) => n.l);
|
|
3421
|
+
const { buildMigrationPlanBundle } = await import("./validate-tBBN_dXH.mjs").then((n) => n.s);
|
|
3476
3422
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
3477
3423
|
migrations = collectMigrations(migrationsDir);
|
|
3478
3424
|
migrationPlanBundle = features.migrationDialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
@@ -3898,7 +3844,7 @@ let loadedProvisionModule;
|
|
|
3898
3844
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
3899
3845
|
*/
|
|
3900
3846
|
async function loadProvisionModule() {
|
|
3901
|
-
loadedProvisionModule ??= await import("./provision-
|
|
3847
|
+
loadedProvisionModule ??= await import("./provision-CSJOjjQk.mjs").then((n) => n.a);
|
|
3902
3848
|
return loadedProvisionModule;
|
|
3903
3849
|
}
|
|
3904
3850
|
/**
|
|
@@ -5361,8 +5307,7 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5361
5307
|
* `required` set is passed in, so this needs no Better Auth resolution).
|
|
5362
5308
|
*/
|
|
5363
5309
|
async function assertMigrationsProduceAuthSchema(migrations, required) {
|
|
5364
|
-
const
|
|
5365
|
-
const db = new DatabaseSync(":memory:");
|
|
5310
|
+
const db = await openMigrationValidationDatabase(migrations);
|
|
5366
5311
|
const quote = (identifier) => `"${identifier.replace(/"/g, "\"\"")}"`;
|
|
5367
5312
|
const foldIdentifier = (identifier) => identifier.toLowerCase();
|
|
5368
5313
|
const sameIdentifier = (a, b) => foldIdentifier(a) === foldIdentifier(b);
|
|
@@ -5380,11 +5325,6 @@ async function assertMigrationsProduceAuthSchema(migrations, required) {
|
|
|
5380
5325
|
return primaryKey.length === 1 && primaryKey[0] ? primaryKey[0].name : null;
|
|
5381
5326
|
};
|
|
5382
5327
|
try {
|
|
5383
|
-
for (const migration of migrations) try {
|
|
5384
|
-
db.exec(migration.sql);
|
|
5385
|
-
} catch (err) {
|
|
5386
|
-
throw new Error(`checked-in migration ${migration.name} could not be applied to a fresh SQLite database, so the auth schema cannot be verified: ${getErrorMessage(err)}`);
|
|
5387
|
-
}
|
|
5388
5328
|
const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map((row) => foldIdentifier(row.name)));
|
|
5389
5329
|
const problems = [];
|
|
5390
5330
|
for (const req of required) {
|
|
@@ -5701,11 +5641,16 @@ function createDeployWranglerRunner(root, accountId, apiBaseUrl) {
|
|
|
5701
5641
|
const [command, ...prefix] = resolveWranglerArgv(root);
|
|
5702
5642
|
return (args, opts) => {
|
|
5703
5643
|
const childEnv = deployChildEnv(accountId, apiBaseUrl);
|
|
5704
|
-
|
|
5644
|
+
const keyringTerminal = cloudflareKeyringNeedsTerminal(args);
|
|
5645
|
+
if (!opts.capture || keyringTerminal) childEnv.WRANGLER_LOG = "none";
|
|
5705
5646
|
if (opts.env) Object.assign(childEnv, opts.env);
|
|
5706
5647
|
const result = spawnSync(command, [...prefix, ...args], {
|
|
5707
5648
|
cwd: root,
|
|
5708
|
-
stdio:
|
|
5649
|
+
stdio: keyringTerminal ? [
|
|
5650
|
+
"inherit",
|
|
5651
|
+
"inherit",
|
|
5652
|
+
"ignore"
|
|
5653
|
+
] : opts.input === void 0 ? opts.capture ? [
|
|
5709
5654
|
"ignore",
|
|
5710
5655
|
"pipe",
|
|
5711
5656
|
"pipe"
|
|
@@ -5809,14 +5754,27 @@ async function runWranglerAuthToken(runWrangler, configPath) {
|
|
|
5809
5754
|
return (type === "oauth" || type === "api_token") && typeof token === "string" && token.length > 0 ? token : null;
|
|
5810
5755
|
}
|
|
5811
5756
|
/**
|
|
5757
|
+
* Immediately after setup, the local resolver can retain ENODATA while Cloudflare's public DNS
|
|
5758
|
+
* already serves the new subdomain MX. When the committed config is exactly setup's plan and
|
|
5759
|
+
* every other inbound prerequisite is still ready, DNS is ambiguous: deleting `addresses`
|
|
5760
|
+
* destroys the handoff, while deploying it could fail after upload if routing is genuinely off.
|
|
5761
|
+
*/
|
|
5762
|
+
function isCommittedSubdomainPlanWaitingForDns(pre, rootConfig) {
|
|
5763
|
+
if (pre.mode !== "subdomain" || pre.domainMx.state !== "empty" && pre.domainMx.state !== "unknown" || pre.routing.enabled !== true || pre.subaddressing.state !== "on" || pre.binding.state !== "present" || pre.sender.state !== "ready" || pre.addressesOwnership.state !== "mine" || pre.addressesStale || pre.rules.state === "unknown" || pre.rules.foreign.length > 0 || !Array.isArray(rootConfig.addresses) || rootConfig.addresses.length === 0) return false;
|
|
5764
|
+
const allBlockers = pre.blockers.filter((blocker) => blocker.scope === "all");
|
|
5765
|
+
if (pre.domainMx.state === "empty") return allBlockers.length === 0;
|
|
5766
|
+
return allBlockers.length === 1;
|
|
5767
|
+
}
|
|
5768
|
+
/**
|
|
5812
5769
|
* Step 3b-ii — Mode B email on the developer's own account (design doc 0078, "One keystroke").
|
|
5813
5770
|
* Preflight is read-only; the checklist is shown; ONE `confirm` (default Yes) authorizes the
|
|
5814
5771
|
* apply, which runs only the rows not ready and returns the root-config patch this writes.
|
|
5815
|
-
*
|
|
5816
|
-
*
|
|
5817
|
-
*
|
|
5818
|
-
*
|
|
5819
|
-
* module borrows it through `getSessionBearer` inside its
|
|
5772
|
+
* Most branches that cannot finish return `satisfied: false`, leaving `--require-email` to
|
|
5773
|
+
* decide whether deployment continues. One ambiguous handoff fails closed for every deploy:
|
|
5774
|
+
* an exact committed subdomain plan whose new MX is still empty or unreadable. It is preserved,
|
|
5775
|
+
* and the caller stops before build/upload until DNS can be verified. No output of this step
|
|
5776
|
+
* ever contains the session bearer: the module borrows it through `getSessionBearer` inside its
|
|
5777
|
+
* own closures and drops it.
|
|
5820
5778
|
*/
|
|
5821
5779
|
async function runCloudflareEmailStep(input) {
|
|
5822
5780
|
const without = {
|
|
@@ -5905,6 +5863,19 @@ async function runCloudflareEmailStep(input) {
|
|
|
5905
5863
|
};
|
|
5906
5864
|
}
|
|
5907
5865
|
log.message(renderEmailChecklist(pre));
|
|
5866
|
+
if (isCommittedSubdomainPlanWaitingForDns(pre, rootConfig)) {
|
|
5867
|
+
const dnsState = pre.domainMx.state === "empty" ? "this resolver sees no MX records yet" : "the MX lookup failed";
|
|
5868
|
+
log.error([
|
|
5869
|
+
`deploy: cannot verify Email Routing on ${pre.domain} because ${dnsState}.`,
|
|
5870
|
+
`The existing addresses plan in ${configName} is preserved. DNS may still be propagating after \`void email setup\`; run \`void email status --platform cloudflare\` and retry the deploy when this resolver sees Cloudflare's MX records.`,
|
|
5871
|
+
"Nothing was built or uploaded."
|
|
5872
|
+
].join("\n"));
|
|
5873
|
+
return {
|
|
5874
|
+
...without,
|
|
5875
|
+
abortDeploy: true,
|
|
5876
|
+
map: mapFor(existingAddresses(rootConfig, pre), pre.sending.state === "ready")
|
|
5877
|
+
};
|
|
5878
|
+
}
|
|
5908
5879
|
const shipsBinding = pre.binding.state === "present";
|
|
5909
5880
|
const leaveAccount = (reason) => {
|
|
5910
5881
|
let configWritten = false;
|
|
@@ -6159,6 +6130,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6159
6130
|
fetchImpl: deps.emailFetch ?? fetch,
|
|
6160
6131
|
dns: deps.emailDns ?? await createNodeEmailDns()
|
|
6161
6132
|
});
|
|
6133
|
+
if (email.abortDeploy) return exit(1);
|
|
6162
6134
|
if (options.requireEmail && !email.satisfied) {
|
|
6163
6135
|
log.error(["deploy: --require-email — email is not fully set up for this deploy (see above); refusing to deploy.", "Nothing was built or uploaded. Set email up, or drop --require-email."].join("\n"));
|
|
6164
6136
|
return exit(1);
|
|
@@ -6506,9 +6478,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6506
6478
|
"they must already produce the Better Auth schema — tables, columns, and the primary",
|
|
6507
6479
|
"keys, unique constraints and foreign keys it declares:",
|
|
6508
6480
|
` ${getErrorMessage(err)}`,
|
|
6509
|
-
"`void db generate` includes the production Better Auth schema automatically. Run it,"
|
|
6510
|
-
"review and commit the generated migration, then rerun deploy — or deploy this app",
|
|
6511
|
-
"with `void deploy` (the managed platform)."
|
|
6481
|
+
...err instanceof SqliteMigrationError ? ["Repair the unapplied migration named above, then rerun deploy.", "`void db generate` diffs snapshots and cannot repair existing invalid SQL."] : ["`void db generate` includes the production Better Auth schema automatically.", "Run it, review and commit the generated migration, then rerun deploy."]
|
|
6512
6482
|
].join("\n"));
|
|
6513
6483
|
return exit(1);
|
|
6514
6484
|
}
|
|
@@ -6713,8 +6683,18 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6713
6683
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
6714
6684
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
6715
6685
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
6716
|
-
const
|
|
6686
|
+
const activationRunner = preBuildRootConfig.compliance_region ? runWrangler : createCloudflareMetadataRunner({
|
|
6717
6687
|
runWrangler,
|
|
6688
|
+
accountId,
|
|
6689
|
+
apiBaseUrl,
|
|
6690
|
+
workerName,
|
|
6691
|
+
configPath: generatedConfigPath,
|
|
6692
|
+
fetch: deps.metadataFetch,
|
|
6693
|
+
verifyUploader: assertUploaderStillPinned,
|
|
6694
|
+
getToken: () => runWranglerAuthToken(runWrangler, generatedConfigPath)
|
|
6695
|
+
});
|
|
6696
|
+
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
6697
|
+
runWrangler: activationRunner,
|
|
6718
6698
|
verifyUploader: assertUploaderStillPinned,
|
|
6719
6699
|
workerName,
|
|
6720
6700
|
configPath: generatedConfigPath,
|
|
@@ -7105,8 +7085,18 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7105
7085
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7106
7086
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7107
7087
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7108
|
-
const
|
|
7088
|
+
const activationRunner = rootConfig.compliance_region ? runWrangler : createCloudflareMetadataRunner({
|
|
7109
7089
|
runWrangler,
|
|
7090
|
+
accountId,
|
|
7091
|
+
apiBaseUrl,
|
|
7092
|
+
workerName,
|
|
7093
|
+
configPath: staticConfigPath,
|
|
7094
|
+
fetch: deps.metadataFetch,
|
|
7095
|
+
verifyUploader: uploaderIsPinned,
|
|
7096
|
+
getToken: () => runWranglerAuthToken(runWrangler, staticConfigPath)
|
|
7097
|
+
});
|
|
7098
|
+
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
7099
|
+
runWrangler: activationRunner,
|
|
7110
7100
|
verifyUploader: uploaderIsPinned,
|
|
7111
7101
|
configPath: staticConfigPath,
|
|
7112
7102
|
preserveTriggers: existingWorker !== null,
|
|
@@ -7120,7 +7110,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7120
7110
|
workerName,
|
|
7121
7111
|
versionId
|
|
7122
7112
|
});
|
|
7123
|
-
assertCloudflareBindingsPreserved(existingWorker, uploaded);
|
|
7113
|
+
assertCloudflareBindingsPreserved(existingWorker, uploaded, [], { staticAssetsBinding: "ASSETS" });
|
|
7124
7114
|
} : void 0,
|
|
7125
7115
|
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) : void 0,
|
|
7126
7116
|
workerName,
|
|
@@ -7272,6 +7262,7 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7272
7262
|
let config = null;
|
|
7273
7263
|
if (requestedProjectSlug) {
|
|
7274
7264
|
const projects = await client.listProjects();
|
|
7265
|
+
assertProjectDeployAccess(projects.find((project) => project.slug === requestedProjectSlug));
|
|
7275
7266
|
config = resolveProjectBySlug(projects, requestedProjectSlug);
|
|
7276
7267
|
if (!config) {
|
|
7277
7268
|
if (!process.stdin.isTTY) config = await createProjectFromSlug(root, client, requestedProjectSlug, cliLog);
|
|
@@ -7284,7 +7275,16 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7284
7275
|
config = await createProjectFromSlug(root, client, requestedProjectSlug, cliLog);
|
|
7285
7276
|
}
|
|
7286
7277
|
}
|
|
7287
|
-
} else
|
|
7278
|
+
} else {
|
|
7279
|
+
config = readProjectConfig(root);
|
|
7280
|
+
if (config) {
|
|
7281
|
+
const projects = await client.listProjects();
|
|
7282
|
+
const { projectId, slug } = config;
|
|
7283
|
+
const project = projects.find((project) => project.id === projectId);
|
|
7284
|
+
if (!project) throw new Error(`deploy: The linked project "${slug}" is unavailable or you no longer have access. Ask a project admin or owner to restore access, or choose another project with \`--project <slug>\`.`);
|
|
7285
|
+
assertProjectDeployAccess(project);
|
|
7286
|
+
}
|
|
7287
|
+
}
|
|
7288
7288
|
if (!config && !process.stdin.isTTY) {
|
|
7289
7289
|
log.error("No project specified. Set `VOID_PROJECT`, pass `--project <slug>`, or commit `.void/project.json`.");
|
|
7290
7290
|
process.exit(1);
|
|
@@ -7347,10 +7347,15 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7347
7347
|
throw error;
|
|
7348
7348
|
}
|
|
7349
7349
|
}
|
|
7350
|
+
function assertProjectDeployAccess(project) {
|
|
7351
|
+
if (project?.role === "reader") throw new Error(`deploy: You have reader access to "${project.slug}" and cannot deploy. Ask a project admin or owner to grant collaborator access, or choose another project with \`--project <slug>\`.`);
|
|
7352
|
+
}
|
|
7350
7353
|
async function promptDeployProjectConfig(root, client, cliLog) {
|
|
7351
7354
|
const projects = await client.listProjects();
|
|
7352
|
-
|
|
7353
|
-
|
|
7355
|
+
const deployableProjects = projects.filter((project) => project.role !== "reader");
|
|
7356
|
+
if (deployableProjects.length !== projects.length) log.warn("Projects with reader access are hidden from deploy selection. Ask a project admin or owner to grant collaborator access to deploy to them.");
|
|
7357
|
+
if (await promptProjectSetupAction("Set up a Void project for deploy:", { includeLink: deployableProjects.length > 0 }) === "create") return promptAndCreateProject(root, client);
|
|
7358
|
+
const result = await promptProjectSelection(deployableProjects, "Select a project to deploy to:", root, {
|
|
7354
7359
|
confirmExisting: true,
|
|
7355
7360
|
includeCreate: false
|
|
7356
7361
|
});
|
|
@@ -7647,7 +7652,10 @@ async function streamDirectR2Deploy(client, projectId, manifest, assetManifest,
|
|
|
7647
7652
|
await uploadAssetsToR2(items, cliLog, void 0, (item) => {
|
|
7648
7653
|
assetFiles.delete(item.path);
|
|
7649
7654
|
});
|
|
7650
|
-
} else
|
|
7655
|
+
} else {
|
|
7656
|
+
assetFiles.clear();
|
|
7657
|
+
cliLog?.info("presign_skipped", { reason: "no_needed_assets" });
|
|
7658
|
+
}
|
|
7651
7659
|
let encodedWorkerFiles;
|
|
7652
7660
|
if (workerFiles && workerFiles.size > 0) {
|
|
7653
7661
|
encodedWorkerFiles = {};
|
|
@@ -7896,7 +7904,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
7896
7904
|
} catch {}
|
|
7897
7905
|
if (resources) {
|
|
7898
7906
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
7899
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./output-
|
|
7907
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./output-B0cfNSx5.mjs").then((n) => n.T);
|
|
7900
7908
|
const connectionString = await promptText({
|
|
7901
7909
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
7902
7910
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -8142,7 +8150,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8142
8150
|
} catch {}
|
|
8143
8151
|
if (resources) {
|
|
8144
8152
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
8145
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./output-
|
|
8153
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./output-B0cfNSx5.mjs").then((n) => n.T);
|
|
8146
8154
|
const connectionString = await promptText({
|
|
8147
8155
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
8148
8156
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -8298,6 +8306,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8298
8306
|
...effectiveBindings,
|
|
8299
8307
|
needsLive: true
|
|
8300
8308
|
} : effectiveBindings,
|
|
8309
|
+
hasEmailHandlers: !isFrameworkMode && routeScan.email !== void 0 && hasEmailHandlers(routeScan.email),
|
|
8301
8310
|
migrations: validatedMigrations,
|
|
8302
8311
|
schedules,
|
|
8303
8312
|
ssr: isSsr || hasRoutes || hasMiddleware || hasWebSockets || authEnabled,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as log,
|
|
2
|
-
import {
|
|
3
|
-
import { n as PlatformClient } from "./client-
|
|
1
|
+
import { D as log, c as import_picocolors, k as note } from "./output-B0cfNSx5.mjs";
|
|
2
|
+
import { S as readProjectConfig, l as getToken, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
|
|
3
|
+
import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
|
|
4
4
|
//#region src/cli/domain.ts
|
|
5
5
|
async function runDomainCommand(root, args) {
|
|
6
6
|
const platform = readDeploymentPlatform(root);
|
|
@@ -38,7 +38,7 @@ async function runDomainCommand(root, args) {
|
|
|
38
38
|
}
|
|
39
39
|
async function runCloudflareDomainCommand(root, args) {
|
|
40
40
|
if (args.projectSlug) throw new Error("domain: --project selects a Void platform project and is not used for direct Cloudflare apps.");
|
|
41
|
-
const { changeCloudflareDomain, listCloudflareDomains } = await import("./cloudflare-operations-
|
|
41
|
+
const { changeCloudflareDomain, listCloudflareDomains } = await import("./cloudflare-operations-BzWnlC1_.mjs").then((n) => n.t);
|
|
42
42
|
if (args.subcommand === "add") {
|
|
43
43
|
const result = await changeCloudflareDomain(root, args.hostname, "add");
|
|
44
44
|
log.success(result.modified ? `Domain ${args.hostname} added and activated on Cloudflare.` : `Domain ${args.hostname} is already configured.`);
|