void 0.9.3 → 0.10.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/dist/{auth-cmd-CPkWrQR9.mjs → auth-cmd-DLvXvN-0.mjs} +2 -2
- package/dist/{better-auth-shared-CmEQZs1T.d.mts → better-auth-shared-a7H3wk9J.d.mts} +2 -2
- package/dist/{cache-1SVxZ7BK.mjs → cache-CHFZmqa5.mjs} +1 -1
- package/dist/{cancel-deploy-JaFClLr7.mjs → cancel-deploy-BwpT4U4a.mjs} +1 -1
- package/dist/cli/cli.mjs +273 -36
- package/dist/{client-DIfOFf1W.mjs → client-CTHvucDv.mjs} +166 -45
- package/dist/{create-project-DCUrFJxa.mjs → create-project-CruTH_TQ.mjs} +1 -1
- package/dist/{db-UW4IYQFw.mjs → db-BxnfKs7f.mjs} +14 -14
- package/dist/{delete-CYknzwXU.mjs → delete-IQe1O4Re.mjs} +1 -1
- package/dist/{deploy-RQXpVBL-.mjs → deploy-CuxXxVgz.mjs} +195 -89
- package/dist/{domain-B7RntQ1r.mjs → domain-Bq6kzr_T.mjs} +1 -1
- package/dist/{env-C_ZcxxED.mjs → env-BD3U_0Av.mjs} +1 -1
- package/dist/{env-helpers-Bd2wVdxz.d.mts → env-helpers-ZatKyjen.d.mts} +1 -1
- package/dist/{gen-O5mXZ76K.mjs → gen-Dgi4D7GC.mjs} +1 -1
- package/dist/git-metadata-Ce0AtSZL.mjs +82 -0
- package/dist/github-cmd-CD0Z8KCF.mjs +441 -0
- package/dist/{handler-hm9KldPP.d.mts → handler-DczZlaXR.d.mts} +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +18 -18
- package/dist/{init-DGrLx2ls.mjs → init-CTe46nIr.mjs} +113 -77
- package/dist/{link-7MoXUMaI.mjs → link-BGFW4pHD.mjs} +2 -2
- package/dist/{list-N2mCHv8q.mjs → list-CbGxdbe7.mjs} +1 -1
- package/dist/{login-tt1OmNVg.mjs → login-v4wle1vn.mjs} +1 -1
- package/dist/{logs-Cl7q2CjZ.mjs → logs-BFgY5Vqc.mjs} +1 -1
- package/dist/{mcp-BXD35N2J.mjs → mcp-STKL-uWs.mjs} +1 -1
- package/dist/{node-Df8UjQ2H.mjs → node-B07cZs0d.mjs} +3 -3
- package/dist/pages/client.d.mts +1 -1
- package/dist/pages/client.mjs +1 -0
- package/dist/pages/head-client.d.mts +1 -1
- package/dist/pages/head.d.mts +1 -1
- package/dist/pages/index.d.mts +2 -2
- package/dist/pages/index.mjs +1 -1
- package/dist/pages/islands-plugin.d.mts +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +1 -1
- package/dist/{plugin-inference--7geW5Z2.mjs → plugin-inference-C3fLzFvP.mjs} +2 -0
- package/dist/{prepare-DT-7QII_.mjs → prepare-DH2WnEpD.mjs} +3 -3
- package/dist/{preset-2aBxMfY1.mjs → preset-B7ZQZn0u.mjs} +2 -2
- package/dist/{project-cmd-CLrqSbqj.mjs → project-cmd-DZh-vbEL.mjs} +8 -8
- package/dist/{protocol-B9GZA4Bn.d.mts → protocol-63PHtCHS.d.mts} +3 -3
- package/dist/{rollback-CEbAwbHK.mjs → rollback-o0M0Qo_n.mjs} +1 -1
- package/dist/{runner-DLZ9E_cX.mjs → runner-BQyKUqAL.mjs} +1 -1
- package/dist/runtime/ai.mjs +1 -1
- package/dist/runtime/auth.d.mts +1 -1
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth-pg.mjs +3 -3
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/better-auth.mjs +2 -2
- package/dist/runtime/client-react.d.mts +2 -2
- package/dist/runtime/client-react.mjs +1 -1
- package/dist/runtime/client-solid.d.mts +2 -2
- package/dist/runtime/client-solid.mjs +1 -1
- package/dist/runtime/client-svelte.d.mts +2 -2
- package/dist/runtime/client-svelte.mjs +1 -1
- package/dist/runtime/client-vue.d.mts +2 -2
- package/dist/runtime/client-vue.mjs +1 -1
- package/dist/runtime/client.d.mts +2 -2
- package/dist/runtime/client.mjs +1 -1
- package/dist/runtime/env-helpers.d.mts +1 -1
- package/dist/runtime/env-public-client.d.mts +1 -1
- package/dist/runtime/env-public.d.mts +2 -2
- package/dist/runtime/env-public.mjs +1 -1
- package/dist/runtime/env.mjs +1 -1
- package/dist/runtime/fetch-stream.d.mts +1 -1
- package/dist/runtime/fetch-stream.mjs +1 -1
- package/dist/runtime/fetch.d.mts +1 -1
- package/dist/runtime/fetch.mjs +1 -1
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +1 -1
- package/dist/runtime/isr.mjs +1 -1
- package/dist/runtime/live.d.mts +2 -2
- package/dist/runtime/live.mjs +1 -1
- package/dist/runtime/migration-handler-pg.mjs +1 -1
- package/dist/runtime/sandbox.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +2 -2
- package/dist/runtime/ws.d.mts +3 -3
- package/dist/{scan-B2H1Vo2C.mjs → scan-DGEp1-1Q.mjs} +17 -9
- package/dist/{secret-C_uTY7xx.mjs → secret-gs_yyGZL.mjs} +1 -1
- package/package.json +2 -2
- package/schema.json +3 -3
- package/skills/void/docs/guide/deployment.md +26 -11
- package/skills/void/docs/guide/edge/headers.md +10 -3
- package/skills/void/docs/guide/edge/rewrites.md +5 -5
- package/skills/void/docs/reference/cli.md +89 -2
- /package/dist/{auth-migrations-CuQkjjWE.mjs → auth-migrations-BP-hMzYl.mjs} +0 -0
- /package/dist/{auth-CDeb2XAl.d.mts → auth-nEUVHuFI.d.mts} +0 -0
- /package/dist/{better-auth-shared-QAfk8CAS.mjs → better-auth-shared-D0Mbmx5V.mjs} +0 -0
- /package/dist/{defer-CouVukrf.mjs → defer-C-bdSM_b.mjs} +0 -0
- /package/dist/{drizzle-DYstYz0j.mjs → drizzle-DqstQTGq.mjs} +0 -0
- /package/dist/{env-raw-RDkMnSTC.mjs → env-raw-Dtj1UAoK.mjs} +0 -0
- /package/dist/{fetch-error-CimrygMq.d.mts → fetch-error-BQMdPvge.d.mts} +0 -0
- /package/dist/{fetch-error-BFIoojjf.mjs → fetch-error-C6qffTl2.mjs} +0 -0
- /package/dist/{head-BsSTGnIe.d.mts → head-JAH2l3fg.d.mts} +0 -0
- /package/dist/{headers-VkAnACKX.mjs → headers-BNWymgnH.mjs} +0 -0
- /package/dist/{package-json-B2TD0JLu.mjs → package-json-Bg_GJdJB.mjs} +0 -0
- /package/dist/{pg-CMZ_5wsC.mjs → pg-CempqvEJ.mjs} +0 -0
- /package/dist/{providers-3Kkv63Ha.d.mts → providers-BkiAlEad.d.mts} +0 -0
- /package/dist/{runner-pg-Cv9V7ydr.mjs → runner-pg-BAheiT6v.mjs} +0 -0
- /package/dist/{skills-BRKc--As.mjs → skills--OMgLmXW.mjs} +0 -0
- /package/dist/{standard-schema-Dnsh2vnl.d.mts → standard-schema-BCBv-QaP.d.mts} +0 -0
- /package/dist/{subcommand-prompt-OD-x_Tsm.mjs → subcommand-prompt-ClwpLlKD.mjs} +0 -0
- /package/dist/{types-DEWCqHtl.d.mts → types-BnHMXezo.d.mts} +0 -0
- /package/dist/{yarn-pnp-0SwYgQxx.mjs → yarn-pnp-DhCHHLAz.mjs} +0 -0
|
@@ -3,12 +3,13 @@ import { a as join, c as resolve, i as isAbsolute, n as dirname, r as extname, s
|
|
|
3
3
|
import { n as cliTitle, r as createSpinner, s as import_picocolors } from "./output-DeiS4oEX.mjs";
|
|
4
4
|
import { i as resolveProjectPaths, n as readProjectPaths } from "./project-paths-CCMrHYQm.mjs";
|
|
5
5
|
import { t as findVoidAuthConfig } from "./config-hhMYPVRT.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { t as cfAccessHeaders } from "./cf-access-DKDsgwOU.mjs";
|
|
7
|
+
import { a as isExpiredTokenError, f as getToken, i as isCliOutdatedError, m as isStagingMode, n as PlatformClient, o as parsePlatformErrorBody, p as getTokenSource, t as PlatformApiError, u as getApiUrl, y as ensureCloudflaredToken } from "./client-CTHvucDv.mjs";
|
|
7
8
|
import { c as R, g as ge, u as Se, v as ue, x as q, y as ye } from "./dist-abzUneor.mjs";
|
|
8
9
|
import { a as writeProjectConfig, r as readProjectConfig } from "./project-CH9pdo16.mjs";
|
|
9
10
|
import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-8dLIngKW.mjs";
|
|
10
|
-
import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes } from "./scan-
|
|
11
|
-
import { i as inferProjectBindings, l as validateSsrEntry, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference
|
|
11
|
+
import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes } from "./scan-DGEp1-1Q.mjs";
|
|
12
|
+
import { i as inferProjectBindings, l as validateSsrEntry, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-C3fLzFvP.mjs";
|
|
12
13
|
import { i as voidWarn, r as voidLog } from "./log-BdD_Fpms.mjs";
|
|
13
14
|
import { t as discoverSchema } from "./discover-C8N1I4tK.mjs";
|
|
14
15
|
import { t as findEnvFile } from "./env-types-CaJaIRXU.mjs";
|
|
@@ -19,18 +20,19 @@ import { n as buildMigrationPlanBundle } from "./plan-aD3wRDqF.mjs";
|
|
|
19
20
|
import { r as validateMigrations, t as assertJournalCoherence } from "./validate-CNWm-PsL.mjs";
|
|
20
21
|
import { t as scanPages } from "./scan-VCAM1oh3.mjs";
|
|
21
22
|
import { n as STAGING_PROXY_URL, t as DEFAULT_PROXY_URL } from "./proxy-M3pxItg2.mjs";
|
|
22
|
-
import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-
|
|
23
|
+
import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-CruTH_TQ.mjs";
|
|
23
24
|
import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-D4O1_fZz.mjs";
|
|
24
|
-
import {
|
|
25
|
-
import { t as
|
|
26
|
-
import {
|
|
25
|
+
import { t as collectGitDeployMetadata } from "./git-metadata-Ce0AtSZL.mjs";
|
|
26
|
+
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-BNWymgnH.mjs";
|
|
27
|
+
import { t as promptForLoginToken } from "./login-v4wle1vn.mjs";
|
|
28
|
+
import { i as resolveProjectCommand, n as detectPreset, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-B7ZQZn0u.mjs";
|
|
27
29
|
import { createRequire } from "node:module";
|
|
28
30
|
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
29
31
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
30
32
|
import { build, loadEnv } from "vite";
|
|
31
33
|
import { createHash } from "node:crypto";
|
|
32
34
|
import { homedir } from "node:os";
|
|
33
|
-
import { execFile,
|
|
35
|
+
import { execFile, execSync, spawnSync } from "node:child_process";
|
|
34
36
|
import { parse } from "jsonc-parser";
|
|
35
37
|
import { hash } from "blake3-jit";
|
|
36
38
|
import ignore from "ignore";
|
|
@@ -1167,84 +1169,127 @@ function sleep(ms) {
|
|
|
1167
1169
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1168
1170
|
}
|
|
1169
1171
|
//#endregion
|
|
1170
|
-
//#region src/cli/
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1172
|
+
//#region src/cli/github-oidc.ts
|
|
1173
|
+
/**
|
|
1174
|
+
* GitHub Actions OIDC → Void deploy-token exchange.
|
|
1175
|
+
*
|
|
1176
|
+
* When `void deploy` runs inside GitHub Actions with no explicit `VOID_TOKEN`,
|
|
1177
|
+
* the CLI mints a short-lived GitHub OIDC token (audience `void`) and exchanges
|
|
1178
|
+
* it at `POST $VOID_API_URL/auth/github-oidc` for a short-lived, project-scoped
|
|
1179
|
+
* Void deploy token. Doing the exchange in-process lets the scaffolded workflow
|
|
1180
|
+
* collapse to a single `void deploy` step — no curl/jq token-exchange step.
|
|
1181
|
+
*
|
|
1182
|
+
* Server contract (platform `POST /auth/github-oidc` handler):
|
|
1183
|
+
* request { oidcToken: string, project: string } (project = slug)
|
|
1184
|
+
* response { token: string, projectId, buildId }
|
|
1185
|
+
*/
|
|
1186
|
+
const OIDC_AUDIENCE = "void";
|
|
1187
|
+
/**
|
|
1188
|
+
* True when the process is running inside GitHub Actions with the OIDC token
|
|
1189
|
+
* request endpoint available — i.e. the workflow granted
|
|
1190
|
+
* `permissions: id-token: write`, so GitHub injected the request URL + token.
|
|
1191
|
+
*/
|
|
1192
|
+
function isGithubActionsOidcAvailable(env = process.env) {
|
|
1193
|
+
return env.GITHUB_ACTIONS === "true" && typeof env.ACTIONS_ID_TOKEN_REQUEST_URL === "string" && env.ACTIONS_ID_TOKEN_REQUEST_URL.length > 0 && typeof env.ACTIONS_ID_TOKEN_REQUEST_TOKEN === "string" && env.ACTIONS_ID_TOKEN_REQUEST_TOKEN.length > 0;
|
|
1185
1194
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1195
|
+
/**
|
|
1196
|
+
* Mint a GitHub Actions OIDC token (audience `void`) and exchange it for a
|
|
1197
|
+
* short-lived, project-scoped Void deploy token.
|
|
1198
|
+
*
|
|
1199
|
+
* Two hops:
|
|
1200
|
+
* 1. GET $ACTIONS_ID_TOKEN_REQUEST_URL&audience=void (Bearer request token)
|
|
1201
|
+
* → `.value` is the OIDC JWT.
|
|
1202
|
+
* 2. POST $apiUrl/auth/github-oidc { oidcToken, project }
|
|
1203
|
+
* → `.token` is the Void deploy token.
|
|
1204
|
+
*
|
|
1205
|
+
* Throws a clear, actionable error (including the HTTP status and server error
|
|
1206
|
+
* body when available) on any non-OK response or missing field.
|
|
1207
|
+
*/
|
|
1208
|
+
async function exchangeGithubOidcForDeployToken(apiUrl, project, env = process.env) {
|
|
1209
|
+
const requestUrl = env.ACTIONS_ID_TOKEN_REQUEST_URL;
|
|
1210
|
+
const requestToken = env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
|
|
1211
|
+
if (!requestUrl || !requestToken) throw new Error("github-oidc: GitHub Actions OIDC is unavailable (missing ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN). Ensure the workflow grants `permissions: id-token: write`.");
|
|
1212
|
+
return exchangeOidcTokenAtApi(apiUrl, project, await requestGithubOidcToken(requestUrl, requestToken));
|
|
1188
1213
|
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1214
|
+
/**
|
|
1215
|
+
* GET the GitHub Actions OIDC token for audience `void`. GitHub's request URL
|
|
1216
|
+
* already carries a query string, so `audience` is appended alongside it.
|
|
1217
|
+
*/
|
|
1218
|
+
async function requestGithubOidcToken(requestUrl, requestToken) {
|
|
1219
|
+
const url = new URL(requestUrl);
|
|
1220
|
+
url.searchParams.set("audience", OIDC_AUDIENCE);
|
|
1221
|
+
let res;
|
|
1222
|
+
try {
|
|
1223
|
+
res = await fetch(url, { headers: { Authorization: `Bearer ${requestToken}` } });
|
|
1224
|
+
} catch (err) {
|
|
1225
|
+
throw new Error(`github-oidc: Failed to reach the GitHub OIDC token endpoint: ${errText(err)}`);
|
|
1198
1226
|
}
|
|
1227
|
+
if (!res.ok) {
|
|
1228
|
+
const body = await safeText(res);
|
|
1229
|
+
throw new Error(`github-oidc: Failed to mint a GitHub OIDC token (${res.status})${body ? `: ${body}` : ""}.`);
|
|
1230
|
+
}
|
|
1231
|
+
let body;
|
|
1199
1232
|
try {
|
|
1200
|
-
|
|
1201
|
-
if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "ssh:") return null;
|
|
1202
|
-
const host = url.hostname.toLowerCase();
|
|
1203
|
-
const path = stripGitSuffix(url.pathname).replace(/^\/+/, "");
|
|
1204
|
-
return host && path ? `https://${host}/${path}` : null;
|
|
1233
|
+
body = await res.json();
|
|
1205
1234
|
} catch {
|
|
1206
|
-
|
|
1235
|
+
throw new Error("github-oidc: GitHub OIDC token endpoint returned an invalid response.");
|
|
1207
1236
|
}
|
|
1237
|
+
const value = body?.value;
|
|
1238
|
+
if (typeof value !== "string" || value.length === 0) throw new Error("github-oidc: GitHub OIDC token endpoint did not return a token value.");
|
|
1239
|
+
return value;
|
|
1208
1240
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1241
|
+
/** POST the OIDC JWT to the Void API and return the minted deploy token. */
|
|
1242
|
+
async function exchangeOidcTokenAtApi(apiUrl, project, oidcToken) {
|
|
1243
|
+
const url = `${apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl}/auth/github-oidc`;
|
|
1244
|
+
ensureCloudflaredToken(apiUrl);
|
|
1245
|
+
let res;
|
|
1246
|
+
try {
|
|
1247
|
+
res = await fetch(url, {
|
|
1248
|
+
method: "POST",
|
|
1249
|
+
headers: {
|
|
1250
|
+
"Content-Type": "application/json",
|
|
1251
|
+
...cfAccessHeaders(process.env)
|
|
1252
|
+
},
|
|
1253
|
+
body: JSON.stringify({
|
|
1254
|
+
oidcToken,
|
|
1255
|
+
project
|
|
1256
|
+
})
|
|
1257
|
+
});
|
|
1258
|
+
} catch (err) {
|
|
1259
|
+
throw new Error(`github-oidc: Failed to reach ${url}: ${errText(err)}`);
|
|
1260
|
+
}
|
|
1261
|
+
if (!res.ok) {
|
|
1262
|
+
const body = await safeText(res);
|
|
1263
|
+
throw new Error(`github-oidc: OIDC token exchange failed (${res.status})${body ? `: ${body}` : ""}. Confirm the repository is connected to project "${project}" with the github_actions executor.`);
|
|
1264
|
+
}
|
|
1265
|
+
let body;
|
|
1211
1266
|
try {
|
|
1212
|
-
|
|
1213
|
-
if (url.hostname === "github.com") return `${repositoryUrl}/commit/${commit}`;
|
|
1214
|
-
if (url.hostname === "gitlab.com") return `${repositoryUrl}/-/commit/${commit}`;
|
|
1215
|
-
if (url.hostname === "bitbucket.org") return `${repositoryUrl}/commits/${commit}`;
|
|
1267
|
+
body = await res.json();
|
|
1216
1268
|
} catch {
|
|
1217
|
-
|
|
1269
|
+
throw new Error("github-oidc: OIDC token exchange returned an invalid response.");
|
|
1218
1270
|
}
|
|
1219
|
-
|
|
1271
|
+
const token = body?.token;
|
|
1272
|
+
if (typeof token !== "string" || token.length === 0) throw new Error("github-oidc: OIDC token exchange did not return a deploy token.");
|
|
1273
|
+
return token;
|
|
1220
1274
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1275
|
+
/**
|
|
1276
|
+
* Emit a GitHub Actions `::add-mask::` workflow command so `value` is redacted
|
|
1277
|
+
* from workflow logs. No-op when not running inside GitHub Actions. GitHub reads
|
|
1278
|
+
* workflow commands from stdout.
|
|
1279
|
+
*/
|
|
1280
|
+
function maskGithubActionsSecret(value, env = process.env) {
|
|
1281
|
+
if (env.GITHUB_ACTIONS !== "true" || !value) return;
|
|
1282
|
+
process.stdout.write(`::add-mask::${value}\n`);
|
|
1226
1283
|
}
|
|
1227
|
-
function
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
"
|
|
1235
|
-
|
|
1236
|
-
]));
|
|
1237
|
-
const gitRef = getGitRefFromEnv(env) ?? git(root, [
|
|
1238
|
-
"rev-parse",
|
|
1239
|
-
"--abbrev-ref",
|
|
1240
|
-
"HEAD"
|
|
1241
|
-
]);
|
|
1242
|
-
return {
|
|
1243
|
-
commit,
|
|
1244
|
-
commitUrl: buildCommitUrl(repositoryUrl, commit),
|
|
1245
|
-
gitRef: gitRef && gitRef !== "HEAD" ? gitRef : null,
|
|
1246
|
-
repositoryUrl
|
|
1247
|
-
};
|
|
1284
|
+
function errText(err) {
|
|
1285
|
+
return err instanceof Error ? err.message : String(err);
|
|
1286
|
+
}
|
|
1287
|
+
async function safeText(res) {
|
|
1288
|
+
try {
|
|
1289
|
+
return (await res.text()).trim();
|
|
1290
|
+
} catch {
|
|
1291
|
+
return "";
|
|
1292
|
+
}
|
|
1248
1293
|
}
|
|
1249
1294
|
//#endregion
|
|
1250
1295
|
//#region src/cli/log-file.ts
|
|
@@ -2292,6 +2337,7 @@ function generateHandlersSource(root, features) {
|
|
|
2292
2337
|
//#region src/cli/deploy.ts
|
|
2293
2338
|
var deploy_exports = /* @__PURE__ */ __exportAll({
|
|
2294
2339
|
applyDeployEvent: () => applyDeployEvent,
|
|
2340
|
+
buildEnv: () => buildEnv,
|
|
2295
2341
|
ensurePreviouslyDeployedLiveBindingConfig: () => ensurePreviouslyDeployedLiveBindingConfig,
|
|
2296
2342
|
generateDeployWrapperIfNeeded: () => generateDeployWrapperIfNeeded,
|
|
2297
2343
|
hasDeploySchemaDrift: () => hasDeploySchemaDrift,
|
|
@@ -2305,7 +2351,9 @@ var deploy_exports = /* @__PURE__ */ __exportAll({
|
|
|
2305
2351
|
resolveWorkerDirName: () => resolveWorkerDirName,
|
|
2306
2352
|
runDeploy: () => runDeploy,
|
|
2307
2353
|
runStaticDeploy: () => runStaticDeploy,
|
|
2308
|
-
|
|
2354
|
+
streamDeployEvents: () => streamDeployEvents,
|
|
2355
|
+
warnRedundantForceOn3xx: () => warnRedundantForceOn3xx,
|
|
2356
|
+
warnUnpublishedRouting: () => warnUnpublishedRouting
|
|
2309
2357
|
});
|
|
2310
2358
|
const drizzleKitBin = join(fileURLToPath(import.meta.resolve("drizzle-kit")), "..", "bin.cjs");
|
|
2311
2359
|
const deployDriftCheckDir = join(".void", "deploy-drift-check");
|
|
@@ -2423,10 +2471,47 @@ async function runDeploy(root, options) {
|
|
|
2423
2471
|
await cliLog.close().catch(() => {});
|
|
2424
2472
|
}
|
|
2425
2473
|
}
|
|
2474
|
+
/**
|
|
2475
|
+
* Build a child-process environment with the CF Access service-token PAIR
|
|
2476
|
+
* removed.
|
|
2477
|
+
*
|
|
2478
|
+
* The deploy flow spawns UNTRUSTED user build code (`vite build`, framework
|
|
2479
|
+
* preset builds, drizzle-kit loading the user schema) which inherits the
|
|
2480
|
+
* spawn env. A shared, long-lived CF Access service token is needed only by
|
|
2481
|
+
* this CLI's own API client (which captures the Access headers once at
|
|
2482
|
+
* construction and reuses them for every request) — never by the build — so it
|
|
2483
|
+
* must not survive into those children, or it would leak to arbitrary repo
|
|
2484
|
+
* build scripts/plugins.
|
|
2485
|
+
*
|
|
2486
|
+
* We scrub it on the CHILD env rather than mutating `process.env`: deleting it
|
|
2487
|
+
* from the parent also breaks interactive expired-token re-auth, which reads
|
|
2488
|
+
* `cfAccessHeaders(process.env)` / the cloudflared pair-guard AFTER the build
|
|
2489
|
+
* step. Only the service-token pair is scrubbed; the cloudflared
|
|
2490
|
+
* `CF_ACCESS_TOKEN` JWT (dev path) is left untouched.
|
|
2491
|
+
*/
|
|
2492
|
+
function buildEnv(extra) {
|
|
2493
|
+
const env = {
|
|
2494
|
+
...process.env,
|
|
2495
|
+
...extra
|
|
2496
|
+
};
|
|
2497
|
+
delete env.CF_ACCESS_CLIENT_ID;
|
|
2498
|
+
delete env.CF_ACCESS_CLIENT_SECRET;
|
|
2499
|
+
return env;
|
|
2500
|
+
}
|
|
2426
2501
|
async function runDeployInner(root, options, cliLog) {
|
|
2427
2502
|
let reauthenticated = false;
|
|
2428
2503
|
while (true) try {
|
|
2429
|
-
|
|
2504
|
+
let token = process.env.VOID_TOKEN ?? null;
|
|
2505
|
+
if (!token && isGithubActionsOidcAvailable()) {
|
|
2506
|
+
const slug = getRequestedProjectSlug(options) ?? readProjectConfig(root)?.slug;
|
|
2507
|
+
if (!slug) throw new Error("deploy: running in GitHub Actions but the project is unknown — pass --project <slug> or link the project.");
|
|
2508
|
+
cliLog.info("github_oidc_exchange_start", { slug });
|
|
2509
|
+
token = await exchangeGithubOidcForDeployToken(getApiUrl(root), slug);
|
|
2510
|
+
maskGithubActionsSecret(token);
|
|
2511
|
+
process.env.VOID_TOKEN = token;
|
|
2512
|
+
cliLog.info("github_oidc_exchange_success", { slug });
|
|
2513
|
+
}
|
|
2514
|
+
token ??= getToken(root);
|
|
2430
2515
|
if (!token) {
|
|
2431
2516
|
R.error("No auth token found. Run `void auth login` first.");
|
|
2432
2517
|
process.exit(1);
|
|
@@ -2598,7 +2683,8 @@ function applyDeployEvent(event, s) {
|
|
|
2598
2683
|
s.message(`Prerendering ${event.pages} pages...`);
|
|
2599
2684
|
return { kind: "continue" };
|
|
2600
2685
|
case "done":
|
|
2601
|
-
s.stop("Deployed
|
|
2686
|
+
if (event.published === false) s.stop("Deployed, but routing was not published — the project may be unreachable or still serving the previous deploy. Re-run `void deploy` to publish routing.");
|
|
2687
|
+
else s.stop("Deployed!");
|
|
2602
2688
|
return {
|
|
2603
2689
|
kind: "done",
|
|
2604
2690
|
event
|
|
@@ -2639,12 +2725,14 @@ async function streamDeployEvents(projectId, events, s, cliLog) {
|
|
|
2639
2725
|
deploymentId = result.deploymentId;
|
|
2640
2726
|
cliLog?.info("stream_deployment_id", { deploymentId });
|
|
2641
2727
|
} else if (result.kind === "done") {
|
|
2642
|
-
|
|
2728
|
+
const degraded = result.event.published === false;
|
|
2729
|
+
cliLog?.info(degraded ? "deploy_degraded" : "deploy_success", {
|
|
2643
2730
|
deploymentId,
|
|
2644
2731
|
url: result.event.url,
|
|
2645
2732
|
assets: result.event.assets,
|
|
2646
2733
|
workers: result.event.workers,
|
|
2647
|
-
durationMs: Date.now() - startedAt
|
|
2734
|
+
durationMs: Date.now() - startedAt,
|
|
2735
|
+
degraded
|
|
2648
2736
|
});
|
|
2649
2737
|
return result.event;
|
|
2650
2738
|
} else if (result.kind === "error") {
|
|
@@ -2784,7 +2872,8 @@ async function runStaticDeploy(root, config, client, preset, skipBuild, gitMetad
|
|
|
2784
2872
|
const buildStartedAt = Date.now();
|
|
2785
2873
|
execSync(preset.buildCommand, {
|
|
2786
2874
|
cwd: root,
|
|
2787
|
-
stdio: "inherit"
|
|
2875
|
+
stdio: "inherit",
|
|
2876
|
+
env: buildEnv()
|
|
2788
2877
|
});
|
|
2789
2878
|
cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
|
|
2790
2879
|
} else if (skipBuild) cliLog?.info("build_skipped", { reason: "skipBuild" });
|
|
@@ -2836,9 +2925,21 @@ async function runStaticDeploy(root, config, client, preset, skipBuild, gitMetad
|
|
|
2836
2925
|
});
|
|
2837
2926
|
const result = await streamDirectR2Deploy(client, config.projectId, manifest, assetManifest, assetFiles, needed, gitMetadata, neededSet !== null, void 0, s, cliLog);
|
|
2838
2927
|
Se([`${typeLabel} — ${formatKnownAssetSummary(result, skipped)}`].join("\n"), result.url);
|
|
2928
|
+
warnUnpublishedRouting(result);
|
|
2839
2929
|
ye("Done!");
|
|
2840
2930
|
}
|
|
2841
2931
|
/**
|
|
2932
|
+
* Surface a persistent warning when a deploy committed live but its routing
|
|
2933
|
+
* KV was not published. Uses `log.warn` (not the spinner) so the warning
|
|
2934
|
+
* survives the following `note`/`outro` calls and the user sees it after the
|
|
2935
|
+
* deploy summary. The deploy is still committed — this is a warning, not a
|
|
2936
|
+
* failure, so the process exit code is unaffected.
|
|
2937
|
+
*/
|
|
2938
|
+
function warnUnpublishedRouting(result) {
|
|
2939
|
+
if (result.published !== false) return;
|
|
2940
|
+
R.warn("Routing was not published for this deploy. The project may be unreachable (first deploy) or still serving the previous deploy. Re-run `void deploy` to publish routing.");
|
|
2941
|
+
}
|
|
2942
|
+
/**
|
|
2842
2943
|
* Emit a single aggregated lint warning when a `_redirects` file contains
|
|
2843
2944
|
* one or more `!` force suffixes on 3xx entries (e.g. `301!`, `302!`).
|
|
2844
2945
|
* The `!` is a no-op on redirects — we parse them as if the `!` weren't
|
|
@@ -2866,7 +2967,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
2866
2967
|
const buildStartedAt = Date.now();
|
|
2867
2968
|
execSync(voidConfig.inference?.build ?? resolveProjectCommand(root, fwPreset.buildCommand), {
|
|
2868
2969
|
cwd: root,
|
|
2869
|
-
stdio: "inherit"
|
|
2970
|
+
stdio: "inherit",
|
|
2971
|
+
env: buildEnv()
|
|
2870
2972
|
});
|
|
2871
2973
|
cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
|
|
2872
2974
|
} else cliLog?.info("build_skipped", { reason: "skipBuild" });
|
|
@@ -3043,6 +3145,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
3043
3145
|
summary.push(`Framework: ${detected.name}`);
|
|
3044
3146
|
Se(summary.join("\n"), result.url);
|
|
3045
3147
|
cleanupWrapper(root);
|
|
3148
|
+
warnUnpublishedRouting(result);
|
|
3046
3149
|
ye("Done!");
|
|
3047
3150
|
}
|
|
3048
3151
|
async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetadata, detected, cliLog) {
|
|
@@ -3059,10 +3162,7 @@ async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetad
|
|
|
3059
3162
|
execSync(resolveProjectCommand(root, "vite build"), {
|
|
3060
3163
|
cwd: root,
|
|
3061
3164
|
stdio: "inherit",
|
|
3062
|
-
env: {
|
|
3063
|
-
...process.env,
|
|
3064
|
-
VOID_DEPLOY_PROJECT_ID: config.projectId
|
|
3065
|
-
}
|
|
3165
|
+
env: buildEnv({ VOID_DEPLOY_PROJECT_ID: config.projectId })
|
|
3066
3166
|
});
|
|
3067
3167
|
cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
|
|
3068
3168
|
} catch (err) {
|
|
@@ -3343,6 +3443,7 @@ async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetad
|
|
|
3343
3443
|
else summary.push(`ISR revalidate: ${Object.keys(revalidate).length} path rule(s)`);
|
|
3344
3444
|
if (isFrameworkMode) summary.push("Framework mode");
|
|
3345
3445
|
Se(summary.join("\n"), result.url);
|
|
3446
|
+
warnUnpublishedRouting(result);
|
|
3346
3447
|
ye("Done!");
|
|
3347
3448
|
}
|
|
3348
3449
|
async function createProjectFromSlug(root, client, slug, cliLog) {
|
|
@@ -3365,17 +3466,21 @@ function getGitCommit(root) {
|
|
|
3365
3466
|
try {
|
|
3366
3467
|
const githubSha = process.env.GITHUB_SHA?.trim();
|
|
3367
3468
|
if (githubSha && /^[0-9a-f]{7,64}$/i.test(githubSha)) return githubSha;
|
|
3469
|
+
const gitEnv = buildEnv();
|
|
3368
3470
|
execSync("git rev-parse --is-inside-work-tree", {
|
|
3369
3471
|
cwd: root,
|
|
3370
|
-
stdio: "ignore"
|
|
3472
|
+
stdio: "ignore",
|
|
3473
|
+
env: gitEnv
|
|
3371
3474
|
});
|
|
3372
3475
|
if (execSync("git status --porcelain", {
|
|
3373
3476
|
cwd: root,
|
|
3374
|
-
encoding: "utf-8"
|
|
3477
|
+
encoding: "utf-8",
|
|
3478
|
+
env: gitEnv
|
|
3375
3479
|
}).trim() !== "") return null;
|
|
3376
3480
|
return execSync("git rev-parse HEAD", {
|
|
3377
3481
|
cwd: root,
|
|
3378
|
-
encoding: "utf-8"
|
|
3482
|
+
encoding: "utf-8",
|
|
3483
|
+
env: gitEnv
|
|
3379
3484
|
}).trim();
|
|
3380
3485
|
} catch {
|
|
3381
3486
|
return null;
|
|
@@ -3421,7 +3526,8 @@ function runDrizzleKitGenerate(root, configPath) {
|
|
|
3421
3526
|
configPath
|
|
3422
3527
|
], {
|
|
3423
3528
|
cwd: root,
|
|
3424
|
-
encoding: "utf-8"
|
|
3529
|
+
encoding: "utf-8",
|
|
3530
|
+
env: buildEnv()
|
|
3425
3531
|
});
|
|
3426
3532
|
const stderr = bufferToString(result.stderr);
|
|
3427
3533
|
const output = [stderr, bufferToString(result.stdout)].filter(Boolean).join("\n").trim();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as import_picocolors } from "./output-DeiS4oEX.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { f as getToken, n as PlatformClient } from "./client-CTHvucDv.mjs";
|
|
3
3
|
import { c as R, u as Se } from "./dist-abzUneor.mjs";
|
|
4
4
|
import { r as readProjectConfig } from "./project-CH9pdo16.mjs";
|
|
5
5
|
//#region src/cli/domain.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as join } from "./pathe.M-eThtNZ-BrPhGF_K.mjs";
|
|
2
2
|
import { n as cliTitle } from "./output-DeiS4oEX.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { f as getToken, n as PlatformClient } from "./client-CTHvucDv.mjs";
|
|
4
4
|
import { c as R, g as ge, u as Se, y as ye } from "./dist-abzUneor.mjs";
|
|
5
5
|
import { r as readProjectConfig } from "./project-CH9pdo16.mjs";
|
|
6
6
|
import { r as generateEnvTypes, t as findEnvFile } from "./env-types-CaJaIRXU.mjs";
|
|
@@ -7,7 +7,7 @@ import { c as getDatabaseDialect, f as readConfig } from "./config-8dLIngKW.mjs"
|
|
|
7
7
|
import { n as writeDrizzleConfig } from "./config--wXmVOoe.mjs";
|
|
8
8
|
import { r as readJournal, t as collectMigrations } from "./collect-9rO3JFNM.mjs";
|
|
9
9
|
import { n as listDrizzleArtifacts, t as assertJournalCoherence } from "./validate-CNWm-PsL.mjs";
|
|
10
|
-
import { t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-
|
|
10
|
+
import { t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-DhCHHLAz.mjs";
|
|
11
11
|
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { spawnSync } from "node:child_process";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
//#region src/cli/git-metadata.ts
|
|
3
|
+
function git(root, args) {
|
|
4
|
+
try {
|
|
5
|
+
return execFileSync("git", args, {
|
|
6
|
+
cwd: root,
|
|
7
|
+
encoding: "utf-8",
|
|
8
|
+
stdio: [
|
|
9
|
+
"ignore",
|
|
10
|
+
"pipe",
|
|
11
|
+
"ignore"
|
|
12
|
+
]
|
|
13
|
+
}).trim();
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function stripGitSuffix(pathname) {
|
|
19
|
+
return pathname.endsWith(".git") ? pathname.slice(0, -4) : pathname;
|
|
20
|
+
}
|
|
21
|
+
function normalizeGitRemoteUrl(remote) {
|
|
22
|
+
if (!remote) return null;
|
|
23
|
+
const trimmed = remote.trim();
|
|
24
|
+
if (!trimmed) return null;
|
|
25
|
+
const scpLike = /^(?:[^@]+@)?([^:]+):(.+)$/.exec(trimmed);
|
|
26
|
+
if (scpLike && !trimmed.includes("://")) {
|
|
27
|
+
const host = scpLike[1]?.toLowerCase();
|
|
28
|
+
const path = stripGitSuffix(scpLike[2] ?? "").replace(/^\/+/, "");
|
|
29
|
+
return host && path ? `https://${host}/${path}` : null;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const url = new URL(trimmed);
|
|
33
|
+
if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "ssh:") return null;
|
|
34
|
+
const host = url.hostname.toLowerCase();
|
|
35
|
+
const path = stripGitSuffix(url.pathname).replace(/^\/+/, "");
|
|
36
|
+
return host && path ? `https://${host}/${path}` : null;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function buildCommitUrl(repositoryUrl, commit) {
|
|
42
|
+
if (!repositoryUrl || !commit) return null;
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(repositoryUrl);
|
|
45
|
+
if (url.hostname === "github.com") return `${repositoryUrl}/commit/${commit}`;
|
|
46
|
+
if (url.hostname === "gitlab.com") return `${repositoryUrl}/-/commit/${commit}`;
|
|
47
|
+
if (url.hostname === "bitbucket.org") return `${repositoryUrl}/commits/${commit}`;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function getGitRefFromEnv(env) {
|
|
54
|
+
if (env.GITHUB_HEAD_REF) return env.GITHUB_HEAD_REF;
|
|
55
|
+
if (env.GITHUB_REF_NAME) return env.GITHUB_REF_NAME;
|
|
56
|
+
if (env.GITHUB_REF) return env.GITHUB_REF.replace(/^refs\/(?:heads|tags|pull)\//, "");
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function getGitHubRepositoryUrl(env) {
|
|
60
|
+
if (!env.GITHUB_REPOSITORY) return null;
|
|
61
|
+
return normalizeGitRemoteUrl(`${env.GITHUB_SERVER_URL ?? "https://github.com"}/${env.GITHUB_REPOSITORY}`);
|
|
62
|
+
}
|
|
63
|
+
function collectGitDeployMetadata(root, commit, env = process.env) {
|
|
64
|
+
const repositoryUrl = getGitHubRepositoryUrl(env) ?? normalizeGitRemoteUrl(git(root, [
|
|
65
|
+
"remote",
|
|
66
|
+
"get-url",
|
|
67
|
+
"origin"
|
|
68
|
+
]));
|
|
69
|
+
const gitRef = getGitRefFromEnv(env) ?? git(root, [
|
|
70
|
+
"rev-parse",
|
|
71
|
+
"--abbrev-ref",
|
|
72
|
+
"HEAD"
|
|
73
|
+
]);
|
|
74
|
+
return {
|
|
75
|
+
commit,
|
|
76
|
+
commitUrl: buildCommitUrl(repositoryUrl, commit),
|
|
77
|
+
gitRef: gitRef && gitRef !== "HEAD" ? gitRef : null,
|
|
78
|
+
repositoryUrl
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
export { collectGitDeployMetadata as t };
|