void 1.1.0 → 1.1.11
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/{account-cmd-BTcUzv9L.mjs → account-cmd-R35a4Oa8.mjs} +3 -3
- package/dist/{application-analysis-AB_YYWgH.mjs → application-analysis-D7nNmNJb.mjs} +6 -6
- package/dist/{application-routing-L7V-TFhZ.mjs → application-routing-CZH66gXn.mjs} +1 -1
- package/dist/{auth-link-DUJuvRx5.mjs → auth-link-VHmiKZmP.mjs} +3 -3
- package/dist/{auth-migrations-Cgs0k6lS.mjs → auth-migrations-BO27GDNr.mjs} +38 -2
- package/dist/{auth-router-CIxiMG7i.mjs → auth-router-O_Wrs5kg.mjs} +5 -4
- package/dist/{better-auth-shared-B74NJIus.d.mts → better-auth-shared-Bv18bB-l.d.mts} +2 -0
- package/dist/{better-auth-shared-CMXlZG7W.mjs → better-auth-shared-D-6z0q0f.mjs} +28 -1
- package/dist/{build-cmd-BkIv25PA.mjs → build-cmd-CMZiMn46.mjs} +1 -1
- package/dist/{cache-Ctzfig-W.mjs → cache-TZ5Ab3d7.mjs} +1 -1
- package/dist/{cancel-deploy-CD9o-SsC.mjs → cancel-deploy-DXoR6oC3.mjs} +1 -1
- package/dist/cli/cli.mjs +69 -50
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-DrdeJgHR.mjs +1 -0
- package/dist/{client-DM9Kcf4e.mjs → client-GuSO3v_x.mjs} +1 -1
- package/dist/{cloudflare-auth-CqFBDo52.mjs → cloudflare-auth-DSvBc1Gu.mjs} +1 -1
- package/dist/{cloudflare-cmd-BIAF_BIY.mjs → cloudflare-cmd-ZSErUl6Y.mjs} +3 -3
- package/dist/{cloudflare-config-DV60XFFK.mjs → cloudflare-config-rdFOys4X.mjs} +2 -2
- package/dist/{cloudflare-connect-WjwnVOJA.mjs → cloudflare-connect-BN-k2kD-.mjs} +2 -2
- package/dist/{cloudflare-operations-CrSUFRzJ.mjs → cloudflare-operations-Cm8lVx7W.mjs} +1 -1
- package/dist/{cloudflare-operations-B42EZeJy.mjs → cloudflare-operations-DH3GedbV.mjs} +6 -6
- package/dist/{cloudflare-process-CeDWJRhj.mjs → cloudflare-process-CZJ4viYl.mjs} +2 -2
- package/dist/collect-BWhkgtAn.mjs +1 -0
- package/dist/{collect-xjffdCdk.mjs → collect-Dew86qce.mjs} +4 -3
- package/dist/{config-D0GY5ItR.mjs → config-CyUJzi3q.mjs} +1 -1
- package/dist/{config-Bx_1SpnO.mjs → config-D26zcdKy.mjs} +2 -2
- package/dist/{config-BEm9vRvS.mjs → config-DC5llZaI.mjs} +2 -2
- package/dist/{config-QrJWu0IX.mjs → config-DYJV8aEH.mjs} +1 -1
- package/dist/{connect-CKtk-EZe.mjs → connect-yQuLbuiJ.mjs} +4 -4
- package/dist/{create-project-B-ewF_Af.mjs → create-project-CGOo_OL_.mjs} +1 -1
- package/dist/{create-project-yInGo72M.mjs → create-project-DEEWJX_M.mjs} +1 -1
- package/dist/database-provider.d.mts +6 -0
- package/dist/{db-7I_gfdVq.mjs → db-COI-yTJE.mjs} +255 -110
- package/dist/{db-types-Bb4WBWIs.mjs → db-types-NGxPwnlt.mjs} +1 -1
- package/dist/{delete-Cy-M1u-r.mjs → delete-PgN6L_9N.mjs} +1 -1
- package/dist/deploy-CxNgEYr4.mjs +2 -0
- package/dist/{deploy-BYYlnsiy.mjs → deploy-DsW-PrRQ.mjs} +38 -36
- package/dist/{deploy-managed-static-Ca4TFdmx.mjs → deploy-managed-static-Dqz06S2u.mjs} +20 -20
- package/dist/{deploy-transport-DWlWBe6M.mjs → deploy-transport-nY3vLXPL.mjs} +2 -2
- package/dist/deploy.mjs +5 -5
- package/dist/discover-D4TPKo57.mjs +1 -0
- package/dist/{discover-D2PGT63u.mjs → discover-LaV0tbIu.mjs} +1 -1
- package/dist/{dispatch-DrTTk8Xg.mjs → dispatch-BAbbn3jg.mjs} +6 -6
- package/dist/{domain-CZGxPv9u.mjs → domain-DKlNI0SR.mjs} +2 -2
- package/dist/{drizzle-CF84FOVM.mjs → drizzle-BQfyvQKX.mjs} +13 -2
- package/dist/{email-DzyNVuoU.mjs → email-C0s3OvJk.mjs} +10 -11
- package/dist/{email-cloudflare-DfG6UEMm.mjs → email-cloudflare-etpKiITL.mjs} +7 -10
- package/dist/{entry-ehmBvs5w.mjs → entry-B_0IhV64.mjs} +1 -1
- package/dist/{env-Nx3yf50r.mjs → env-BX2JFsgF.mjs} +4 -4
- package/dist/{env-types-DS2_y4X8.mjs → env-types-GRchm5dw.mjs} +1 -1
- package/dist/{env-validation-BT7z-qpQ.mjs → env-validation-CuGfWRJd.mjs} +1 -1
- package/dist/{env-validation-DYxjz_Wo.mjs → env-validation-D_KyMdab.mjs} +2 -2
- package/dist/{fetch-BPCYVi3H.d.mts → fetch-DHLOuPyk.d.mts} +2 -2
- package/dist/{fetch-stream-obvZ7fvO.d.mts → fetch-stream-CNxOrBdP.d.mts} +1 -1
- package/dist/{gen-CufHEf42.mjs → gen-Bj6ZkOcI.mjs} +25 -19
- package/dist/gen-DsCukhuw.mjs +1 -0
- package/dist/{generate-Dat0UTry.mjs → generate-B1m4Cm4n.mjs} +1 -1
- package/dist/{generate-ClI89brV.mjs → generate-DkEb9rL-.mjs} +1 -1
- package/dist/{github-cmd-FU8EjFyU.mjs → github-cmd-DQDryS-5.mjs} +1 -1
- package/dist/{headers-Di1FsD3e.mjs → headers-Bi4bOAwp.mjs} +1 -1
- package/dist/{help-BT2hovNI.mjs → help-D49SL_lN.mjs} +16 -12
- package/dist/help-DOFygYi4.mjs +1 -0
- package/dist/{inbound-brj2-TM5.d.mts → inbound-Da7XsjH3.d.mts} +6 -12
- package/dist/index.mjs +103 -57
- package/dist/{info-l249eUdH.mjs → info-Bxunp14X.mjs} +4 -4
- package/dist/{init-D0A6M64Q.mjs → init-DyTEY04s.mjs} +50 -27
- package/dist/{link-WMoJFf4i.mjs → link-CgOVn9EC.mjs} +2 -2
- package/dist/{list-CQ2EQEHL.mjs → list-CUfD9RSb.mjs} +2 -2
- package/dist/{local-d1-BxvQYEFi.mjs → local-d1-CpaPbd_L.mjs} +5 -5
- package/dist/{login-C2T1oVG-.mjs → login-BJvGW5Eu.mjs} +2 -2
- package/dist/login-alAlxw4S.mjs +1 -0
- package/dist/{logs-DnC1d7xB.mjs → logs-DeizBI4j.mjs} +2 -2
- package/dist/{migrate-BDIprOYd.mjs → migrate-8rk56vV8.mjs} +4 -4
- package/dist/migrate-D2odrAmh.mjs +1 -0
- package/dist/{neon-n74ta1Pr.mjs → neon-DTZr7Bu7.mjs} +0 -1
- package/dist/nitro.mjs +3 -3
- package/dist/{node-cPadMgUO.mjs → node-uN8_zxJr.mjs} +15 -9
- package/dist/{operator-cmd-DHieWtFp.mjs → operator-cmd-CA5QQyvE.mjs} +3 -3
- package/dist/operator-cmd-D7toMPJ9.mjs +1 -0
- package/dist/pages/client.d.mts +1 -1
- package/dist/pages/index.d.mts +1 -1
- package/dist/pages/index.mjs +4 -4
- package/dist/pages/islands-plugin.d.mts +1 -1
- package/dist/pages/islands-plugin.mjs +1 -1
- package/dist/pages/protocol.d.mts +1 -1
- package/dist/{platform-args-CaCL_1Ch.mjs → platform-args-B7ke06up.mjs} +1 -4
- package/dist/platform-args-B_LrqEZB.mjs +1 -0
- package/dist/{platform-auth-config-Z16-I8nT.mjs → platform-auth-config-CZaY812e.mjs} +3 -3
- package/dist/{platform-auth-protection-BXwZiJSF.mjs → platform-auth-protection-U9HCqoXv.mjs} +2 -2
- package/dist/{platform-auth-recovery-CXjfqyOv.mjs → platform-auth-recovery-B0BV2hfV.mjs} +2 -2
- package/dist/{platform-cmd-DaAOiWTl.mjs → platform-cmd-CXrjk4fb.mjs} +4 -4
- package/dist/{platform-cmd-PT4YwMLM.mjs → platform-cmd-D9lwFpcl.mjs} +1 -1
- package/dist/{platform-domain-CxpvUeo0.mjs → platform-domain-CXyq-68_.mjs} +2 -2
- package/dist/{platform-lifecycle-DBiS0cJd.mjs → platform-lifecycle-D0TdyXbN.mjs} +20 -11
- package/dist/{platform-lifecycle-u9pMOvxC.mjs → platform-lifecycle-Dz2cJsLX.mjs} +1 -1
- package/dist/{platform-management-DvBS83rC.mjs → platform-management-BvgbusqL.mjs} +1 -1
- package/dist/{platform-management-DhEFdQAf.mjs → platform-management-CnXhgxTM.mjs} +1 -3
- package/dist/{platform-recovery-BUGOB4RC.mjs → platform-recovery-CH_fThW6.mjs} +2 -2
- package/dist/{plugin-inference-DsARdQKE.mjs → plugin-inference-Bekzjuqw.mjs} +2 -2
- package/dist/{prepare-PQCgsny0.mjs → prepare-2XD6kh77.mjs} +1 -1
- package/dist/{prepare-DEB5SeVJ.mjs → prepare-DepAGBcV.mjs} +9 -9
- package/dist/prepare-EVEbQ9n2.mjs +1 -0
- package/dist/{project-cmd-DVatD8Ev.mjs → project-cmd-CpLYflCH.mjs} +16 -16
- package/dist/{project-paths-DMvEeSau.mjs → project-paths-DGu_QZ_Q.mjs} +1 -1
- package/dist/{project-team-DJrWEAG1.mjs → project-team-CTSY7W7Q.mjs} +1 -1
- package/dist/{project-token-CBgLBuL6.mjs → project-token-Cybtlfbl.mjs} +1 -1
- package/dist/{project-tsconfig-bveqhlYA.mjs → project-tsconfig-Itv1f4WC.mjs} +1 -1
- package/dist/{project-zero-trust-92gLtZ25.mjs → project-zero-trust-DKOtqyvu.mjs} +1 -1
- package/dist/{protocol-4H7V_3Os.d.mts → protocol-B8sI8dRD.d.mts} +1 -1
- package/dist/{providers-BXuhmuub.mjs → providers-BUHwJlmM.mjs} +10 -1
- package/dist/{provision-BnSSkiED.mjs → provision-BuifYvLc.mjs} +63 -64
- package/dist/provision-UcYjpTRh.mjs +1 -0
- package/dist/r2-conditions-B8xUgJRc.mjs +61 -0
- package/dist/{requests-7W1Pygt2.mjs → requests-Ryiazz9i.mjs} +1 -1
- package/dist/{rollback-BcASVnwP.mjs → rollback-Or0EV3rP.mjs} +2 -2
- package/dist/{runner-CabsQ-iM.mjs → runner-3uGC-oLF.mjs} +9 -7
- package/dist/{runner-So9mYfcm.mjs → runner-WCdfeI0q.mjs} +1 -1
- package/dist/{runner-mysql-BhRaONkO.mjs → runner-mysql-BWmbk5IE.mjs} +1 -1
- package/dist/{runner-mysql-DWwE8jKi.mjs → runner-mysql-BcHnLUuM.mjs} +1 -1
- package/dist/{runner-pg-_Xncr3H5.mjs → runner-pg-Cgp-cr_p.mjs} +1 -1
- package/dist/{runner-pg-BRemq_GX.mjs → runner-pg-Cr3qrqi4.mjs} +1 -1
- package/dist/runtime/ai.d.mts +4 -0
- package/dist/runtime/ai.mjs +2 -37
- package/dist/runtime/better-auth-mysql.d.mts +1 -1
- package/dist/runtime/better-auth-mysql.mjs +2 -2
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth-pg.mjs +2 -2
- 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-solid.d.mts +2 -2
- package/dist/runtime/client-svelte.d.mts +2 -2
- package/dist/runtime/client-vue.d.mts +2 -2
- package/dist/runtime/client.d.mts +2 -2
- package/dist/runtime/email/testing.d.mts +1 -1
- package/dist/runtime/email.d.mts +2 -3
- package/dist/runtime/email.mjs +2 -3
- package/dist/runtime/fetch-stream.d.mts +2 -2
- package/dist/runtime/fetch.d.mts +1 -1
- package/dist/runtime/migration-handler-mysql.mjs +4 -4
- package/dist/runtime/migration-handler-pg.mjs +9 -1
- package/dist/runtime/remote/binding-handler.mjs +25 -25
- package/dist/runtime/remote/index.d.mts +3 -0
- package/dist/runtime/remote/index.mjs +86 -23
- package/dist/runtime/routing.d.mts +2 -2
- package/dist/runtime/sse-client.d.mts +4 -0
- package/dist/runtime/ws-server.d.mts +2 -2
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{scan-C0BMdmEd.mjs → scan-D2-FcLHs.mjs} +13 -5
- package/dist/{secret-bg73f1Ge.mjs → secret-CClHaFxm.mjs} +3 -3
- package/dist/{types-BAp5AEBU.d.mts → types-7AIz0OZu.d.mts} +1 -1
- package/dist/{validate-CheZGRE7.mjs → validate-CnZPMq4q.mjs} +22 -17
- package/dist/validate-D7Wn8PUX.mjs +1 -0
- package/dist/{version-metadata-DIrqEHQo.mjs → version-metadata-B1Bm2wSq.mjs} +1 -1
- package/dist/{wrangler-BYs07Rxy.mjs → wrangler-C9XSzrju.mjs} +3 -3
- package/dist/wrangler-DAdxHEzh.mjs +1 -0
- package/dist/{wrapper-CwhpNWtH.mjs → wrapper-BOigE1xJ.mjs} +4 -4
- package/dist/{ws-aKVYB-fA.d.mts → ws-CsBNxv86.d.mts} +5 -0
- package/docs/guide/auth.md +1 -1
- package/docs/guide/database/d1.md +2 -2
- package/docs/guide/database/mysql.md +1 -1
- package/docs/guide/edge/headers.md +10 -2
- package/docs/guide/edge/revalidation.md +2 -0
- package/docs/guide/email/receiving.md +1 -1
- package/docs/guide/email/sending.md +1 -1
- package/docs/guide/pages-routing/islands.md +2 -2
- package/docs/guide/platform/administration/connected-apps.md +18 -2
- package/docs/guide/remote-dev.md +2 -0
- package/docs/guide/websockets.md +2 -2
- package/docs/index.md +78 -22
- package/docs/reference/api/pages.md +7 -5
- package/docs/reference/api.md +2 -0
- package/docs/reference/cli/database.md +7 -5
- package/docs/reference/cli/deploy.md +12 -10
- package/docs/reference/cli/email.md +1 -1
- package/docs/reference/cli/generate.md +1 -1
- package/docs/reference/cli/platform-installation.md +2 -2
- package/docs/reference/cli/project.md +4 -2
- package/docs/reference/cli.md +1 -1
- package/docs/reference/config.md +11 -1
- package/package.json +7 -7
- package/dist/client-B60PwCC4.mjs +0 -1
- package/dist/collect-Cae8A7Zr.mjs +0 -1
- package/dist/deploy-9lgfhrXS.mjs +0 -2
- package/dist/discover-ClzFSwns.mjs +0 -1
- package/dist/gen-sXyp5DFO.mjs +0 -1
- package/dist/help-i2YGGnTH.mjs +0 -1
- package/dist/login-XD844Xs-.mjs +0 -1
- package/dist/migrate-BRwU-blY.mjs +0 -1
- package/dist/operator-cmd-D6gnZsnK.mjs +0 -1
- package/dist/platform-args-B0HeTh0C.mjs +0 -1
- package/dist/prepare-CYT6tAzD.mjs +0 -1
- package/dist/r2-conditions-D1Wk8i7b.mjs +0 -30
- package/dist/validate-BQFdf0Pi.mjs +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as bytesToBase64 } from "../../base64-DVrOndmI.mjs";
|
|
2
2
|
import { t as cfAccessHeaders } from "../../cf-access-BM9G0lhO.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { a as serializeR2HttpMetadata, i as serializeR2Conditional, t as R2_OBJECT_HEADER } from "../../r2-conditions-B8xUgJRc.mjs";
|
|
4
4
|
//#region src/runtime/remote/client.ts
|
|
5
5
|
function readableMessage(value) {
|
|
6
6
|
if (typeof value !== "string") return;
|
|
@@ -252,6 +252,17 @@ var ProxyKVNamespace = class {
|
|
|
252
252
|
//#endregion
|
|
253
253
|
//#region src/runtime/remote/r2.ts
|
|
254
254
|
/**
|
|
255
|
+
* HTTP metadata that the REST fallback and older deployments do not store.
|
|
256
|
+
* Every path stores `contentType`.
|
|
257
|
+
*/
|
|
258
|
+
const EXTRA_HTTP_METADATA = [
|
|
259
|
+
["contentLanguage", "content-language"],
|
|
260
|
+
["contentDisposition", "content-disposition"],
|
|
261
|
+
["contentEncoding", "content-encoding"],
|
|
262
|
+
["cacheControl", "cache-control"],
|
|
263
|
+
["cacheExpiry", "expires"]
|
|
264
|
+
];
|
|
265
|
+
/**
|
|
255
266
|
* R2Bucket implementation backed by the remote proxy.
|
|
256
267
|
* Used during local development when `remote: true` is set in void.config.ts.
|
|
257
268
|
*/
|
|
@@ -270,7 +281,8 @@ var ProxyR2Bucket = class {
|
|
|
270
281
|
if (!data) return null;
|
|
271
282
|
return makeR2Object(data);
|
|
272
283
|
}
|
|
273
|
-
async get(key) {
|
|
284
|
+
async get(key, options) {
|
|
285
|
+
if (requestsRange(options?.range) || requestsCondition(options?.onlyIf)) throw new Error("remote: R2 get() with range or onlyIf is not supported in remote mode.");
|
|
274
286
|
const res = await this.client.fetch("/r2/get", {
|
|
275
287
|
binding: this.binding,
|
|
276
288
|
key
|
|
@@ -296,6 +308,7 @@ var ProxyR2Bucket = class {
|
|
|
296
308
|
else body.value = textValue;
|
|
297
309
|
if (options?.httpMetadata) {
|
|
298
310
|
const meta = options.httpMetadata;
|
|
311
|
+
body.httpMetadata = serializeR2HttpMetadata(meta);
|
|
299
312
|
if (meta instanceof Headers) body.contentType = meta.get("content-type") ?? void 0;
|
|
300
313
|
else body.contentType = meta.contentType;
|
|
301
314
|
}
|
|
@@ -304,8 +317,11 @@ var ProxyR2Bucket = class {
|
|
|
304
317
|
if (conditional) body.onlyIf = serializeR2Conditional(options.onlyIf);
|
|
305
318
|
const result = await (await this.client.fetch(conditional ? "/r2/put-conditional" : "/r2/put", body)).json();
|
|
306
319
|
if (result === null) return null;
|
|
307
|
-
|
|
308
|
-
if (conditional) throw new Error("remote: R2 conditional put requires a compatible Void platform and deployment.");
|
|
320
|
+
const stored = "key" in result ? result : void 0;
|
|
321
|
+
if (!stored && conditional) throw new Error("remote: R2 conditional put requires a compatible Void platform and deployment.");
|
|
322
|
+
const missing = missingMetadata(options, stored);
|
|
323
|
+
if (missing.length > 0) throw new Error(`remote: R2 put() stored "${key}" without ${missing.join(", ")}. Remote R2 metadata needs a project deployment with the current Void version. Deploy the project, then put the object again.`);
|
|
324
|
+
if (stored) return makeR2Object(stored);
|
|
309
325
|
return makeR2Object({
|
|
310
326
|
key,
|
|
311
327
|
size: 0,
|
|
@@ -326,19 +342,19 @@ var ProxyR2Bucket = class {
|
|
|
326
342
|
prefix: options?.prefix,
|
|
327
343
|
limit: options?.limit,
|
|
328
344
|
cursor: options?.cursor,
|
|
329
|
-
delimiter: options?.delimiter
|
|
345
|
+
delimiter: options?.delimiter,
|
|
346
|
+
startAfter: options?.startAfter,
|
|
347
|
+
include: options?.include
|
|
330
348
|
})).json();
|
|
349
|
+
if (!Array.isArray(data.delimitedPrefixes) && (options?.delimiter || options?.startAfter || options?.include)) throw new Error("remote: R2 list() with delimiter, startAfter or include got no answer from a current project deployment. The deployment uses an older Void version, or the platform could not reach it. Retry. If the error continues, deploy the project with the current Void version.");
|
|
331
350
|
return {
|
|
332
351
|
objects: data.objects.map((o) => makeR2Object({
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
etag: "",
|
|
336
|
-
lastModified: o.lastModified,
|
|
337
|
-
contentType: "application/octet-stream"
|
|
352
|
+
contentType: "application/octet-stream",
|
|
353
|
+
...o
|
|
338
354
|
})),
|
|
339
355
|
truncated: data.truncated,
|
|
340
356
|
cursor: data.cursor ?? void 0,
|
|
341
|
-
delimitedPrefixes: []
|
|
357
|
+
delimitedPrefixes: data.delimitedPrefixes ?? []
|
|
342
358
|
};
|
|
343
359
|
}
|
|
344
360
|
createMultipartUpload() {
|
|
@@ -348,33 +364,77 @@ var ProxyR2Bucket = class {
|
|
|
348
364
|
throw new Error("resumeMultipartUpload() is not supported with remote bindings");
|
|
349
365
|
}
|
|
350
366
|
};
|
|
367
|
+
/**
|
|
368
|
+
* Remote mode ignores a `Headers` value, such as `request.headers`, and returns the whole
|
|
369
|
+
* object, so a reload with If-None-Match or a Range request for media still gets a body.
|
|
370
|
+
* Native R2 ignores fields that are undefined.
|
|
371
|
+
*/
|
|
372
|
+
function requestsRange(range) {
|
|
373
|
+
if (range instanceof Headers) return false;
|
|
374
|
+
return Object.values(range ?? {}).some((value) => value !== void 0);
|
|
375
|
+
}
|
|
376
|
+
/** Same rules as `requestsRange`. `secondsGranularity` alone asks for no condition. */
|
|
377
|
+
function requestsCondition(onlyIf) {
|
|
378
|
+
if (onlyIf instanceof Headers) return false;
|
|
379
|
+
return Object.entries(onlyIf ?? {}).some(([name, value]) => name !== "secondsGranularity" && value !== void 0);
|
|
380
|
+
}
|
|
381
|
+
/** Metadata in `options` that the stored object in the put response does not have. */
|
|
382
|
+
function missingMetadata(options, stored) {
|
|
383
|
+
const meta = options?.httpMetadata;
|
|
384
|
+
const missing = EXTRA_HTTP_METADATA.filter(([field, header]) => (meta instanceof Headers ? meta.has(header) : meta?.[field] !== void 0) && stored?.httpMetadata?.[field] === void 0).map(([field]) => field);
|
|
385
|
+
if (Object.keys(options?.customMetadata ?? {}).some((name) => stored?.customMetadata?.[name] === void 0)) missing.push("customMetadata");
|
|
386
|
+
return missing;
|
|
387
|
+
}
|
|
388
|
+
/** R2 `etag` is unquoted. HTTP headers and older handlers send the quoted form. */
|
|
389
|
+
function normalizeEtag(etag) {
|
|
390
|
+
const value = etag.startsWith("W/") ? etag.slice(2) : etag;
|
|
391
|
+
return value.length >= 2 && value.startsWith("\"") && value.endsWith("\"") ? value.slice(1, -1) : value;
|
|
392
|
+
}
|
|
393
|
+
function readHttpMetadata(data) {
|
|
394
|
+
if (!data.httpMetadata) return { contentType: data.contentType };
|
|
395
|
+
const { cacheExpiry, ...metadata } = data.httpMetadata;
|
|
396
|
+
return cacheExpiry ? {
|
|
397
|
+
...metadata,
|
|
398
|
+
cacheExpiry: new Date(cacheExpiry)
|
|
399
|
+
} : metadata;
|
|
400
|
+
}
|
|
351
401
|
function makeR2Object(data) {
|
|
402
|
+
const etag = normalizeEtag(data.etag ?? "");
|
|
403
|
+
const httpMetadata = readHttpMetadata(data);
|
|
352
404
|
return {
|
|
353
405
|
key: data.key,
|
|
354
406
|
version: data.version ?? "",
|
|
355
407
|
size: data.size,
|
|
356
|
-
etag
|
|
357
|
-
httpEtag:
|
|
408
|
+
etag,
|
|
409
|
+
httpEtag: etag ? `"${etag}"` : "",
|
|
358
410
|
checksums: { toJSON: () => ({}) },
|
|
359
411
|
uploaded: new Date(data.lastModified || Date.now()),
|
|
360
|
-
httpMetadata
|
|
412
|
+
httpMetadata,
|
|
361
413
|
customMetadata: data.customMetadata ?? {},
|
|
362
414
|
storageClass: "Standard",
|
|
363
415
|
range: void 0,
|
|
364
|
-
writeHttpMetadata(
|
|
416
|
+
writeHttpMetadata(headers) {
|
|
417
|
+
const fields = [
|
|
418
|
+
["content-type", httpMetadata.contentType],
|
|
419
|
+
["content-language", httpMetadata.contentLanguage],
|
|
420
|
+
["content-disposition", httpMetadata.contentDisposition],
|
|
421
|
+
["content-encoding", httpMetadata.contentEncoding],
|
|
422
|
+
["cache-control", httpMetadata.cacheControl],
|
|
423
|
+
["expires", httpMetadata.cacheExpiry?.toUTCString()]
|
|
424
|
+
];
|
|
425
|
+
for (const [name, value] of fields) if (value !== void 0) headers.set(name, value);
|
|
426
|
+
}
|
|
365
427
|
};
|
|
366
428
|
}
|
|
367
429
|
function makeR2ObjectBody(key, res) {
|
|
368
|
-
const
|
|
369
|
-
const etag = res.headers.get("etag") ?? "";
|
|
370
|
-
const contentType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
430
|
+
const meta = res.headers.get(R2_OBJECT_HEADER);
|
|
371
431
|
return {
|
|
372
|
-
...makeR2Object({
|
|
432
|
+
...makeR2Object(meta ? JSON.parse(decodeURIComponent(meta)) : {
|
|
373
433
|
key,
|
|
374
|
-
size,
|
|
375
|
-
etag,
|
|
376
|
-
lastModified: res.headers.get("last-modified") ??
|
|
377
|
-
contentType
|
|
434
|
+
size: parseInt(res.headers.get("content-length") ?? "0"),
|
|
435
|
+
etag: res.headers.get("etag") ?? "",
|
|
436
|
+
lastModified: res.headers.get("last-modified") ?? "",
|
|
437
|
+
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
378
438
|
}),
|
|
379
439
|
body: res.body,
|
|
380
440
|
get bodyUsed() {
|
|
@@ -392,6 +452,9 @@ function makeR2ObjectBody(key, res) {
|
|
|
392
452
|
/**
|
|
393
453
|
* Replace local D1/KV/R2 bindings with proxy-backed versions.
|
|
394
454
|
* Called from the generated worker entry point when `__VOID_REMOTE` is set.
|
|
455
|
+
*
|
|
456
|
+
* @deprecated Internal to Void. The generated worker calls this in remote mode.
|
|
457
|
+
* `void/remote` is not a supported import. Removed in the next major version.
|
|
395
458
|
*/
|
|
396
459
|
function createRemoteEnv(env, bindingNames) {
|
|
397
460
|
const client = new ProxyClient(env.__VOID_PROXY_URL, env.__VOID_TOKEN, env.__VOID_PROJECT_ID, env);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as DevCssAsset } from "../types-
|
|
2
|
-
import { a as handlePageMutation, i as handlePageGet } from "../protocol-
|
|
1
|
+
import { t as DevCssAsset } from "../types-7AIz0OZu.mjs";
|
|
2
|
+
import { a as handlePageMutation, i as handlePageGet } from "../protocol-B8sI8dRD.mjs";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
import { Context, ExecutionContext, Hono, MiddlewareHandler } from "hono";
|
|
5
5
|
//#region src/runtime/routing-errors.d.ts
|
|
@@ -14,6 +14,10 @@ export type SseClient<Events extends SseEventMap = SseEventMap> = {
|
|
|
14
14
|
};
|
|
15
15
|
export type ConnectEventStreamOptions = {
|
|
16
16
|
withCredentials?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Has no effect. Register each event with `client.on(name, handler)`.
|
|
19
|
+
* Removed in the next major version.
|
|
20
|
+
*/
|
|
17
21
|
events?: Array<string>;
|
|
18
22
|
parse?: "json" | "text" | ((data: string) => unknown);
|
|
19
23
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as AuthState } from "../auth-DkcFflXV.mjs";
|
|
2
|
-
import { r as VoidAuthRuntimeOptions, t as VoidAuthEnv } from "../better-auth-shared-
|
|
3
|
-
import { f as WebSocketInstanceKey, t as AnyWebSocketDefinition } from "../ws-
|
|
2
|
+
import { r as VoidAuthRuntimeOptions, t as VoidAuthEnv } from "../better-auth-shared-Bv18bB-l.mjs";
|
|
3
|
+
import { f as WebSocketInstanceKey, t as AnyWebSocketDefinition } from "../ws-CsBNxv86.mjs";
|
|
4
4
|
//#region src/runtime/ws-server.d.ts
|
|
5
5
|
export type WebSocketRouteMeta = {
|
|
6
6
|
name?: string;
|
package/dist/runtime/ws.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as RoomDefinition, c as VoidSocket, d as WebSocketConnection, f as WebSocketInstanceKey, h as defineWebSocket, i as RoomController, l as VoidSocketCloseEvent, m as defineRoom, n as ConnectCommonOptions, o as SocketContext, p as connect, r as RoomContext, s as SocketDefinition, t as AnyWebSocketDefinition, u as WebSocketBaseContext } from "../ws-
|
|
1
|
+
import { a as RoomDefinition, c as VoidSocket, d as WebSocketConnection, f as WebSocketInstanceKey, h as defineWebSocket, i as RoomController, l as VoidSocketCloseEvent, m as defineRoom, n as ConnectCommonOptions, o as SocketContext, p as connect, r as RoomContext, s as SocketDefinition, t as AnyWebSocketDefinition, u as WebSocketBaseContext } from "../ws-CsBNxv86.mjs";
|
|
2
2
|
export { AnyWebSocketDefinition, ConnectCommonOptions, RoomContext, RoomController, RoomDefinition, SocketContext, SocketDefinition, VoidSocket, VoidSocketCloseEvent, WebSocketBaseContext, WebSocketConnection, WebSocketInstanceKey, connect, defineRoom, defineWebSocket };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { a as join, n as dirname, r as extname, t as basename } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { n as readProjectPaths } from "./project-paths-
|
|
2
|
+
import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
|
|
3
3
|
import { t as glob } from "./dist-Bn8Kodjp.mjs";
|
|
4
4
|
import { n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
|
|
5
5
|
import { a as staticLiteral, i as staticExportInitializers, n as parseRouteFilename } from "./parse-filename-CUbj-1MP.mjs";
|
|
6
|
+
import { i as voidWarn } from "./log-vqY3pqwI.mjs";
|
|
6
7
|
import { t as MagicString } from "./dist-Cegxq8gs.mjs";
|
|
7
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
9
|
import { parseSync } from "vite";
|
|
@@ -129,9 +130,7 @@ function resolveEffectiveLayoutEntries(page, layouts, namedLayouts) {
|
|
|
129
130
|
}));
|
|
130
131
|
if (page.layout === void 0) return defaultChain;
|
|
131
132
|
const isExclusive = page.layout.startsWith("!");
|
|
132
|
-
const
|
|
133
|
-
if (name.startsWith(".") || name.startsWith("/")) return defaultChain;
|
|
134
|
-
const resolved = resolveNamedLayout(name, page.componentId, namedLayouts, page.componentPath);
|
|
133
|
+
const resolved = resolveNamedLayout(isExclusive ? page.layout.slice(1) : page.layout, page.componentId, namedLayouts, page.componentPath);
|
|
135
134
|
if (!resolved) return defaultChain;
|
|
136
135
|
const namedEntry = {
|
|
137
136
|
id: toLayoutId(resolved),
|
|
@@ -171,6 +170,8 @@ const PAGE_METHODS = /* @__PURE__ */ new Set([
|
|
|
171
170
|
"actions"
|
|
172
171
|
]);
|
|
173
172
|
const MAX_REVALIDATE = 31536e3;
|
|
173
|
+
/** Layout paths already reported; a dev server rescans pages on every file change. */
|
|
174
|
+
const warnedLayoutPaths = /* @__PURE__ */ new Set();
|
|
174
175
|
function componentLayout(source, filename) {
|
|
175
176
|
if (!source.includes("layout")) return;
|
|
176
177
|
for (const script of scriptBlocks(source, filename)) {
|
|
@@ -375,7 +376,14 @@ async function scanPages(root, options) {
|
|
|
375
376
|
for (const page of pages) {
|
|
376
377
|
if (page.layout === void 0 || page.layout === false) continue;
|
|
377
378
|
const name = page.layout.startsWith("!") ? page.layout.slice(1) : page.layout;
|
|
378
|
-
if (name.startsWith(".") || name.startsWith("/"))
|
|
379
|
+
if (name.startsWith(".") || name.startsWith("/")) {
|
|
380
|
+
const key = `${pagesDir}\0${page.componentPath}\0${page.layout}`;
|
|
381
|
+
if (!warnedLayoutPaths.has(key)) {
|
|
382
|
+
warnedLayoutPaths.add(key);
|
|
383
|
+
voidWarn(`pages: Page '${page.componentPath}' specifies layout '${page.layout}'. Layout paths are not supported, so the default layouts are used. Use the name of a file in a _layouts/ directory, such as 'landing'.`);
|
|
384
|
+
}
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
379
387
|
if (!resolveNamedLayout(name, page.componentId, namedLayouts, page.componentPath)) throw new Error(`pages: Page '${page.componentPath}' specifies layout '${page.layout}', but _layouts/${name}.vue was not found in any ancestor directory.`);
|
|
380
388
|
}
|
|
381
389
|
return {
|
|
@@ -2,9 +2,9 @@ import { n as readDeploymentPlatform, r as readProjectConfig } from "./project-r
|
|
|
2
2
|
import { c as getToken } from "./auth-B6iOCjKI.mjs";
|
|
3
3
|
import { A as confirm, H as outro, L as log, O as cancel, U as password, tt as isCancel } from "./dist-BVdsO7Py.mjs";
|
|
4
4
|
import { m as printSuccess, o as formatCount, p as note } from "./output-Ba6ZbrzY.mjs";
|
|
5
|
-
import { r as PlatformClient } from "./client-
|
|
5
|
+
import { r as PlatformClient } from "./client-GuSO3v_x.mjs";
|
|
6
6
|
import { a as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-WpwkCB_c.mjs";
|
|
7
|
-
import { _ as validateSecretValues } from "./env-validation-
|
|
7
|
+
import { _ as validateSecretValues } from "./env-validation-D_KyMdab.mjs";
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
9
|
//#region src/cli/secret.ts
|
|
10
10
|
async function runSecretCommand(root, args) {
|
|
@@ -93,7 +93,7 @@ async function resolveSecretBackend(root, args) {
|
|
|
93
93
|
}
|
|
94
94
|
async function resolveCloudflareSecretBackend(root, args) {
|
|
95
95
|
if (args.projectName) throw new Error("secret: --project selects a Void platform project and is not used for direct Cloudflare apps.");
|
|
96
|
-
const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-
|
|
96
|
+
const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-Cm8lVx7W.mjs");
|
|
97
97
|
const context = resolveCloudflareOperationContext(root);
|
|
98
98
|
return {
|
|
99
99
|
target: "Cloudflare Worker",
|
|
@@ -41,7 +41,7 @@ type PageDefinition = {
|
|
|
41
41
|
title?: string;
|
|
42
42
|
description?: string;
|
|
43
43
|
};
|
|
44
|
-
/** Named layout selection: "name", "!name",
|
|
44
|
+
/** Named layout selection: "name", "!name", or false */
|
|
45
45
|
layout?: string | false;
|
|
46
46
|
};
|
|
47
47
|
type LayoutDefinition = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as join } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { n as readJournal, r as stripSqlExt } from "./collect-
|
|
2
|
+
import { n as readJournal, r as stripSqlExt } from "./collect-Dew86qce.mjs";
|
|
3
3
|
import { i as getExecutableSql, t as DESTRUCTIVE_PRAGMA } from "./plan-BhLO2p4w.mjs";
|
|
4
4
|
import { existsSync, readdirSync } from "node:fs";
|
|
5
5
|
import { hasStandalonePragma } from "@void/deploy-core";
|
|
@@ -74,19 +74,20 @@ function validateMigrations(files) {
|
|
|
74
74
|
/**
|
|
75
75
|
* Enumerate drizzle-kit metadata artifacts in a migrations directory.
|
|
76
76
|
* Returns repo-relative paths like `db/migrations/meta/0000_snapshot.json`
|
|
77
|
-
* and `db/migrations/migrations.js
|
|
77
|
+
* and `db/migrations/migrations.js`, passed through `sourceRelative` so they
|
|
78
|
+
* include the configured `sourceDir`. Empty when none are present.
|
|
78
79
|
*
|
|
79
80
|
* Shared across `assertJournalCoherence`, `void gen migration`, and
|
|
80
81
|
* `void db rename-migrations` so all three agree on what counts as a
|
|
81
82
|
* "partial drizzle-kit state" (journal gone but other metadata lingering).
|
|
82
83
|
*/
|
|
83
|
-
function listDrizzleArtifacts(migrationsDir) {
|
|
84
|
+
function listDrizzleArtifacts(migrationsDir, sourceRelative = (path) => path) {
|
|
84
85
|
const metaDir = join(migrationsDir, "meta");
|
|
85
86
|
const snapshotFiles = existsSync(metaDir) ? readdirSync(metaDir).filter((f) => f.endsWith("_snapshot.json")) : [];
|
|
86
87
|
const bundledPath = join(migrationsDir, "migrations.js");
|
|
87
88
|
const out = [];
|
|
88
|
-
for (const f of snapshotFiles) out.push(`db/migrations/meta/${f}`);
|
|
89
|
-
if (existsSync(bundledPath)) out.push("db/migrations/migrations.js");
|
|
89
|
+
for (const f of snapshotFiles) out.push(sourceRelative(`db/migrations/meta/${f}`));
|
|
90
|
+
if (existsSync(bundledPath)) out.push(sourceRelative("db/migrations/migrations.js"));
|
|
90
91
|
return out;
|
|
91
92
|
}
|
|
92
93
|
/**
|
|
@@ -100,28 +101,32 @@ function listDrizzleArtifacts(migrationsDir) {
|
|
|
100
101
|
* hand-written `.sql` projects without `db/schema.ts` are supported and are
|
|
101
102
|
* tracked by filename in `_void_migrations`. They cannot run
|
|
102
103
|
* `void db generate`, so the check is skipped for them.
|
|
104
|
+
*
|
|
105
|
+
* `sourceRelative` (`ProjectPaths.sourceRelative`) adds the configured
|
|
106
|
+
* `sourceDir` to the paths in error messages.
|
|
103
107
|
*/
|
|
104
|
-
function assertJournalCoherence(migrationsDir, collected) {
|
|
105
|
-
const
|
|
106
|
-
const
|
|
108
|
+
function assertJournalCoherence(migrationsDir, collected, sourceRelative = (path) => path) {
|
|
109
|
+
const dir = sourceRelative("db/migrations");
|
|
110
|
+
const journal = readJournal(migrationsDir, sourceRelative);
|
|
111
|
+
const drizzleArtifacts = listDrizzleArtifacts(migrationsDir, sourceRelative);
|
|
107
112
|
if (journal === void 0) {
|
|
108
113
|
if (drizzleArtifacts.length > 0) throw new Error([
|
|
109
|
-
|
|
114
|
+
`${dir}/meta/_journal.json is missing, but other drizzle-kit metadata is still present:`,
|
|
110
115
|
...drizzleArtifacts.map((p) => ` - ${p}`),
|
|
111
116
|
"",
|
|
112
117
|
"This is a partial drizzle-kit state. Restore _journal.json from version control, or delete the orphaned metadata files above if you intended to revert to hand-written migrations."
|
|
113
118
|
].join("\n"));
|
|
114
119
|
return;
|
|
115
120
|
}
|
|
116
|
-
if (journal === null || typeof journal !== "object" || Array.isArray(journal) || typeof journal.version !== "string" || typeof journal.dialect !== "string" || !Array.isArray(journal.entries)) throw new Error(
|
|
121
|
+
if (journal === null || typeof journal !== "object" || Array.isArray(journal) || typeof journal.version !== "string" || typeof journal.dialect !== "string" || !Array.isArray(journal.entries)) throw new Error(`${dir}/meta/_journal.json is malformed: expected an object with string \`version\`, string \`dialect\`, and an \`entries\` array. Restore the file from version control, or delete it if you intended to revert to hand-written migrations.`);
|
|
117
122
|
for (let i = 0; i < journal.entries.length; i++) {
|
|
118
123
|
const entry = journal.entries[i];
|
|
119
|
-
if (entry === null || typeof entry !== "object" || typeof entry.idx !== "number" || typeof entry.version !== "string" || typeof entry.tag !== "string" || typeof entry.breakpoints !== "boolean") throw new Error(
|
|
124
|
+
if (entry === null || typeof entry !== "object" || typeof entry.idx !== "number" || typeof entry.version !== "string" || typeof entry.tag !== "string" || typeof entry.breakpoints !== "boolean") throw new Error(`${dir}/meta/_journal.json is malformed: entry at index ${i} is missing required fields (\`idx\`, \`version\`, \`tag\`, \`breakpoints\`). Restore the file from version control, or delete it if you intended to revert to hand-written migrations.`);
|
|
120
125
|
}
|
|
121
126
|
if (journal.entries.length === 0) {
|
|
122
127
|
if (drizzleArtifacts.length === 0) return;
|
|
123
128
|
throw new Error([
|
|
124
|
-
|
|
129
|
+
`${dir}/meta/_journal.json has no entries, but drizzle-kit metadata is still present:`,
|
|
125
130
|
...drizzleArtifacts.map((p) => ` - ${p}`),
|
|
126
131
|
"",
|
|
127
132
|
"This is a partial drizzle-kit state. Restore _journal.json from version control (or run `void db generate`), or delete the orphaned metadata files above if you intended to revert to hand-written migrations."
|
|
@@ -131,7 +136,7 @@ function assertJournalCoherence(migrationsDir, collected) {
|
|
|
131
136
|
for (const entry of journal.entries) tagCounts.set(entry.tag, (tagCounts.get(entry.tag) ?? 0) + 1);
|
|
132
137
|
const duplicateTags = [...tagCounts.entries()].filter(([, n]) => n > 1).map(([tag]) => tag);
|
|
133
138
|
if (duplicateTags.length > 0) throw new Error([
|
|
134
|
-
|
|
139
|
+
`${dir}/meta/_journal.json has duplicate migration entries:`,
|
|
135
140
|
...duplicateTags.map((t) => ` - ${t} (appears ${tagCounts.get(t)} times)`),
|
|
136
141
|
"",
|
|
137
142
|
"Each migration must have a unique tag. Restore _journal.json from version control, or hand-edit to remove the duplicates."
|
|
@@ -141,15 +146,15 @@ function assertJournalCoherence(migrationsDir, collected) {
|
|
|
141
146
|
const orphans = collected.map((m) => m.name).filter((name) => !journalTags.has(stripSqlExt(name)));
|
|
142
147
|
const missing = journal.entries.filter((e) => !collectedTags.has(e.tag)).map((e) => `${e.tag}.sql`);
|
|
143
148
|
if (orphans.length === 0 && missing.length === 0) return;
|
|
144
|
-
const lines = [
|
|
149
|
+
const lines = [`Migration drift detected between ${dir}/ and ${dir}/meta/_journal.json.`];
|
|
145
150
|
if (orphans.length > 0) {
|
|
146
151
|
lines.push("", "These files exist on disk but are not tracked in _journal.json:");
|
|
147
|
-
for (const f of orphans) lines.push(` -
|
|
148
|
-
lines.push("",
|
|
152
|
+
for (const f of orphans) lines.push(` - ${dir}/${f}`);
|
|
153
|
+
lines.push("", `Delete the orphan file(s), or move their contents into \`${sourceRelative("db/schema.ts")}\` and re-run \`void db generate\`.`);
|
|
149
154
|
}
|
|
150
155
|
if (missing.length > 0) {
|
|
151
156
|
lines.push("", "These entries are in _journal.json but the matching file is missing:");
|
|
152
|
-
for (const f of missing) lines.push(` -
|
|
157
|
+
for (const f of missing) lines.push(` - ${dir}/${f}`);
|
|
153
158
|
lines.push("", "Restore the missing file(s) from version control, or regenerate migrations.");
|
|
154
159
|
}
|
|
155
160
|
throw new Error(lines.join("\n"));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as validateMigrations } from "./validate-CnZPMq4q.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as join } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-
|
|
2
|
+
import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-C9XSzrju.mjs";
|
|
3
3
|
//#region src/shared/untrusted-env.ts
|
|
4
4
|
/** Authentication inputs that Wrangler may consume from the environment. */
|
|
5
5
|
const WRANGLER_AUTH_CREDENTIAL_ENV_VARS = [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as join, n as dirname, o as normalize, t as basename } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import "./project-paths-
|
|
3
|
-
import { d as readConfig } from "./config-
|
|
4
|
-
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-
|
|
2
|
+
import "./project-paths-DGu_QZ_Q.mjs";
|
|
3
|
+
import { d as readConfig } from "./config-D26zcdKy.mjs";
|
|
4
|
+
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-rdFOys4X.mjs";
|
|
5
5
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { appendSqliteClassMigration, isRecord } from "@void/deploy-core";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { b as readRootWranglerConfig } from "./wrangler-C9XSzrju.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as join, l as toSlash, n as dirname, r as extname } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { n as readProjectPaths } from "./project-paths-
|
|
3
|
-
import { d as readConfig, s as getDatabaseDialect } from "./config-
|
|
2
|
+
import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
|
|
3
|
+
import { d as readConfig, s as getDatabaseDialect } from "./config-D26zcdKy.mjs";
|
|
4
4
|
import { n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
|
|
5
5
|
import { t as MagicString } from "./dist-Cegxq8gs.mjs";
|
|
6
|
-
import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-
|
|
6
|
+
import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-BAbbn3jg.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
@@ -150,7 +150,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
150
150
|
let migrations;
|
|
151
151
|
let migrationPlanBundle;
|
|
152
152
|
if (features.hasMigrations) {
|
|
153
|
-
const { collectMigrations } = await import("./collect-
|
|
153
|
+
const { collectMigrations } = await import("./collect-BWhkgtAn.mjs");
|
|
154
154
|
const { buildMigrationPlanBundle } = await import("./plan-CKX_jWnD.mjs");
|
|
155
155
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
156
156
|
migrations = collectMigrations(migrationsDir);
|
|
@@ -35,6 +35,11 @@ type WebSocketBaseContext = {
|
|
|
35
35
|
readonly id: string;
|
|
36
36
|
readonly params: ParamsRecord;
|
|
37
37
|
readonly user: AuthUser | null;
|
|
38
|
+
/**
|
|
39
|
+
* The HTTP request in `onBeforeConnect`, `onConnect` and `onRequest`. In `onMessage` and
|
|
40
|
+
* `onClose` the connection can resume after hibernation, so this is a placeholder without
|
|
41
|
+
* headers, cookies or query. Use `params`, `user` or the connection `state` there.
|
|
42
|
+
*/
|
|
38
43
|
readonly request: Request;
|
|
39
44
|
readonly env: CloudEnv["Bindings"];
|
|
40
45
|
readonly storage: DurableObjectStorage;
|
package/docs/guide/auth.md
CHANGED
|
@@ -92,7 +92,7 @@ Email/password is enabled by default. To add social providers:
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
Provider credentials come from `AUTH_<PROVIDER>_CLIENT_ID` and `AUTH_<PROVIDER>_CLIENT_SECRET`.
|
|
95
|
+
Provider credentials come from `AUTH_<PROVIDER>_CLIENT_ID` and `AUTH_<PROVIDER>_CLIENT_SECRET`. `cognito` also needs a domain, region, and user pool ID: set `AUTH_COGNITO_DOMAIN`, `AUTH_COGNITO_REGION`, and `AUTH_COGNITO_USER_POOL_ID`, or set them in `auth.ts`.
|
|
96
96
|
|
|
97
97
|
See the full provider list in the [config reference](../reference/config.md#auth).
|
|
98
98
|
|
|
@@ -8,9 +8,9 @@ outline: deep
|
|
|
8
8
|
|
|
9
9
|
## Local Database
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The dev server and local `void db` commands share the same database. If `cloudflare.d1_databases` in `void.config.ts` declares the D1 binding, Void uses its ID. A `preview_database_id` takes precedence during local development.
|
|
12
12
|
|
|
13
|
-
To store local data outside `.void`, set `voidPlugin({ persistTo: 'local-state' })` in your Vite config. Start
|
|
13
|
+
To store local data outside `.void`, set `voidPlugin({ persistTo: 'local-state' })` in your Vite config. Start the dev server once to record that directory before running database commands. After changing the Vite config, start it again to refresh it. Frameworks that manage their own Cloudflare runtime use `.wrangler/state`.
|
|
14
14
|
|
|
15
15
|
## Migrations & Prototyping
|
|
16
16
|
|
|
@@ -22,7 +22,7 @@ Add a direct connection for local development:
|
|
|
22
22
|
DATABASE_URL=mysql://user:password@host:3306/app
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Void reads `.env` for
|
|
25
|
+
Void reads `.env` for the dev server and `void db` commands. In production, the Worker connects through the inferred `HYPERDRIVE` binding.
|
|
26
26
|
|
|
27
27
|
## Define a schema
|
|
28
28
|
|
|
@@ -33,9 +33,17 @@ For hashed assets, you can add headers, but the platform keeps control of cachin
|
|
|
33
33
|
|
|
34
34
|
Header rules do not apply to ISR cache responses.
|
|
35
35
|
|
|
36
|
-
###
|
|
36
|
+
### Cookie headers
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
On a [Void platform](../deployment.md#deploy-to-a-team-platform), apps usually share an application domain, such as `apps.example.com`. Header rules on a platform deploy change two headers on all hostnames of the app, including custom domains:
|
|
39
|
+
|
|
40
|
+
- Void ignores `Set-Cookie` in header rules.
|
|
41
|
+
- Void removes the `"cookies"` directive from `Clear-Site-Data` in header rules. Other directives, such as `"cache"` and `"storage"`, still apply.
|
|
42
|
+
- Void ignores the full value of a `Clear-Site-Data` rule that includes `"*"`. The response then keeps the `Clear-Site-Data` value from your app's response, without `"cookies"`. If that value also includes `"*"`, the response has no `Clear-Site-Data`.
|
|
43
|
+
|
|
44
|
+
This stops a header rule from setting or clearing cookies for other apps on the same domain. These limits apply only to header rules. Your app's own response can set cookies and send `Clear-Site-Data`, and on a shared domain those can affect other apps. See [Domains and Resources](../platform/installation/domains.md#adding-a-domain).
|
|
45
|
+
|
|
46
|
+
In `void dev`, with `void deploy --platform cloudflare`, and on [other runtimes](../deployment.md#other-runtimes), header rules apply both headers as written.
|
|
39
47
|
|
|
40
48
|
## Framework `_headers` files
|
|
41
49
|
|
|
@@ -63,6 +63,8 @@ export const loader = defineHandler(async (c) => {
|
|
|
63
63
|
|
|
64
64
|
Per-page values take precedence over `void.config.ts` patterns.
|
|
65
65
|
|
|
66
|
+
A page's `revalidate` export also applies to `routes/` handlers whose URLs match the page pattern. For example, if `pages/[...slug].server.ts` exports `revalidate`, Void can also cache the `GET` response of `routes/now.ts`. Void never caches paths under `/api`. To keep a route handler's response out of the cache, set `x-revalidate: 0` on it. See [Per-response TTL override](#per-response-ttl-override).
|
|
67
|
+
|
|
66
68
|
## Precedence
|
|
67
69
|
|
|
68
70
|
When multiple sources set a revalidate TTL, the most specific wins:
|
|
@@ -96,7 +96,7 @@ to check current provider routing and any remaining setup steps.
|
|
|
96
96
|
|
|
97
97
|
For direct deployments, follow [Your own Cloudflare account](./domains.md#your-own-cloudflare-account) to configure inbound addresses.
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
`void dev` has no local inbound trigger. It serves only the outbound dev inbox. Test inbound handlers with `createInboundTestHarness` below.
|
|
100
100
|
|
|
101
101
|
## Testing inbound handlers {#testing-inbound-handlers}
|
|
102
102
|
|
|
@@ -195,7 +195,7 @@ The inbox keeps the most recent 100 messages through HMR and clears on a full se
|
|
|
195
195
|
|
|
196
196
|
The dev inbox works in native Void apps, TanStack Start, and React Router. It is unavailable in SvelteKit, Nuxt, Analog, and Astro; sends from those apps return `BINDING_MISSING`. Use `createEmailTestHarness` from `void/email/testing` to capture sends in tests. If a configured inbox cannot be reached, `sendEmail` returns `UPSTREAM_ERROR` without sending.
|
|
197
197
|
|
|
198
|
-
`sendInDev
|
|
198
|
+
`sendInDev` is deprecated. During `void dev` it skips the inbox and returns `BINDING_MISSING`, so it never delivers. Remove it, and deploy the app to test real delivery.
|
|
199
199
|
|
|
200
200
|
## Testing {#testing}
|
|
201
201
|
|
|
@@ -209,7 +209,7 @@ After a successful action, an island page reloads or redirects through `window.l
|
|
|
209
209
|
|
|
210
210
|
## Forms
|
|
211
211
|
|
|
212
|
-
Island pages cannot use `useForm` because it depends on the Void Router. Use `useIslandForm` instead. It has the same
|
|
212
|
+
Island pages cannot use `useForm` because it depends on the Void Router. Use `useIslandForm` instead. It has the same form state, but its submit helpers take the action URL and use `fetch()` directly:
|
|
213
213
|
|
|
214
214
|
::: code-group
|
|
215
215
|
|
|
@@ -344,7 +344,7 @@ export default function PostForm() {
|
|
|
344
344
|
|
|
345
345
|
:::
|
|
346
346
|
|
|
347
|
-
`useIslandForm` provides the same state
|
|
347
|
+
`useIslandForm` provides the same form state as [`useForm`](./actions-and-forms#useform). Pass the action URL to `post`, `put`, `patch`, or `delete` to submit.
|
|
348
348
|
|
|
349
349
|
Successful submissions reload the page; redirects navigate to their destination. A `422` response populates `errors` from `{ errors: { field: "message" } }`. Submit helpers return `Promise<void>`.
|
|
350
350
|
|
|
@@ -4,7 +4,7 @@ A connected app is a separate application registered as an OAuth client on your
|
|
|
4
4
|
|
|
5
5
|
## Register an application
|
|
6
6
|
|
|
7
|
-
Open **Admin → Connected apps**. Enter the app name, its operator, and each exact HTTPS callback URL on a separate line. Wildcards and callback query strings are not supported. Enable individual publish approvals if the app builds and deploys projects.
|
|
7
|
+
Open **Admin → Connected apps**. Enter the app name, its operator, and each exact HTTPS callback URL on a separate line. Wildcards and callback query strings are not supported. Enable individual publish approvals if the app builds and deploys projects. Enable private previews to run checkpoints before publishing. Existing clients have an **Enable private previews** button; users must connect again to consent to that permission.
|
|
8
8
|
|
|
9
9
|
Save the returned client ID and secret on the app's server. Void shows the secret once. The client secret authenticates that application; it does not grant access to users' accounts. Register a new client if you need replacement credentials, then disable the old one.
|
|
10
10
|
|
|
@@ -18,6 +18,22 @@ The app sends users to Void's authorization page, where Void displays its regist
|
|
|
18
18
|
|
|
19
19
|
Users can disconnect applications at `<platform API URL>/oauth/connections`. Grants also expire after an hour and become invalid when their platform login session is revoked or their account is suspended. Applications must request a new sign-in when access expires.
|
|
20
20
|
|
|
21
|
+
## Private previews
|
|
22
|
+
|
|
23
|
+
Sign-in can request `scope=profile preview:deploy` when the administrator has enabled it. After user consent, the app can build private previews without approval for each checkpoint. Production publishing still requires individual approval.
|
|
24
|
+
|
|
25
|
+
Use the granted bearer token to:
|
|
26
|
+
|
|
27
|
+
1. POST `{ workspace: externalWorkspaceId }` to `/oauth/previews`. The response contains a stable `project_id` and preview `url` for that client, owner and workspace.
|
|
28
|
+
2. POST `{ project_id, checkpoint, artifact: prepared.artifact }` to `/oauth/preview-deployment-requests`. Use its `access_token` and `approval_id` with the same asset upload and deployment protocol as publishing.
|
|
29
|
+
3. Once deployment finishes, POST to `/oauth/previews/:id/launch` and open the returned URL. Launch URLs expire after one minute and can be used once. Reload the preview's origin after opening it.
|
|
30
|
+
|
|
31
|
+
Each workspace has a separate preview origin and resources, with no production secrets. Previews support HTTP apps with isolated D1, KV, R2, AI and native Durable Objects. Authentication, external databases, email, schedules, queues and containers require production publishing. Viewing requires the current user grant; disconnecting or disabling the app denies subsequent requests. Preview writes must originate from that preview's own origin.
|
|
32
|
+
|
|
33
|
+
Account Access policies must allow requests to generated preview origins to reach Void. A policy that blocks new Workers hostnames also blocks previews. Void still requires a valid preview grant when the hostname is reachable.
|
|
34
|
+
|
|
35
|
+
Each owner can have ten preview workspaces. Each workspace permits sixty builds per hour and shares the owner's platform resource and usage limits. Inactive previews expire after seven days and Void removes their resources. Opening the workspace through `/oauth/previews` renews that expiry. Disabling preview permission expires its previews.
|
|
36
|
+
|
|
21
37
|
## Approve a publish
|
|
22
38
|
|
|
23
39
|
The app builds first, then sends the user to Void with the prepared artifact. Void displays the project name, checkpoint label, resources, manifest, and artifact digest. The user must explicitly approve on Void.
|
|
@@ -30,7 +46,7 @@ Disabling the app or disconnecting its grant stops authorization for subsequent
|
|
|
30
46
|
|
|
31
47
|
## Build an OAuth client
|
|
32
48
|
|
|
33
|
-
Discover endpoints at `/.well-known/oauth-authorization-server` on the platform API origin. Use authorization code flow with `scope=profile`, a random `state`, and S256 PKCE. Authenticate token exchanges using HTTP Basic client authentication. Send access tokens as Bearer credentials to `/oauth/userinfo`; its response contains `sub` and `
|
|
49
|
+
Discover endpoints at `/.well-known/oauth-authorization-server` on the platform API origin. Use authorization code flow with `scope=profile`, a random `state`, and S256 PKCE. Authenticate token exchanges using HTTP Basic client authentication. Send access tokens as Bearer credentials to `/oauth/userinfo`; its response contains `sub`, `preferred_username`, and the consented `scope`.
|
|
34
50
|
|
|
35
51
|
For publishing, package the built app with [`prepareDeployArtifact`](/reference/api/deploy). POST to `/oauth/deployment-requests` using the profile token:
|
|
36
52
|
|