void 0.7.3 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{better-auth-shared-APuDaPqW.mjs → better-auth-shared-CjnJZFC0.mjs} +51 -5
  2. package/dist/cli/cli.mjs +8 -8
  3. package/dist/{db-ClNu7vYQ.mjs → db-RqxhOT2E.mjs} +1 -1
  4. package/dist/{deploy-BkjqNk9U.mjs → deploy-CRIz77mw.mjs} +243 -56
  5. package/dist/index.mjs +56 -22
  6. package/dist/{init-CPny6w9D.mjs → init-FMZ29UZW.mjs} +2 -2
  7. package/dist/pages/client.d.mts +4 -3
  8. package/dist/pages/client.mjs +18 -6
  9. package/dist/pages/protocol.d.mts +1 -1
  10. package/dist/pages/protocol.mjs +5 -0
  11. package/dist/{plugin-inference-oZ6Ybu2_.mjs → plugin-inference-CCtRkt9O.mjs} +41 -12
  12. package/dist/{prepare-DKkx-2Kt.mjs → prepare-PqAbhLte.mjs} +2 -2
  13. package/dist/{preset-DFvePt0l.mjs → preset-jKn1hQwP.mjs} +1 -1
  14. package/dist/{protocol-CK4OFwfR.d.mts → protocol-DxGzKEz2.d.mts} +1 -0
  15. package/dist/runtime/better-auth-pg.mjs +1 -1
  16. package/dist/runtime/better-auth.mjs +1 -1
  17. package/dist/runtime/live-client.d.mts +34 -0
  18. package/dist/runtime/live-client.mjs +283 -0
  19. package/dist/runtime/live-server.d.mts +13 -0
  20. package/dist/runtime/live-server.mjs +417 -0
  21. package/dist/runtime/live.d.mts +107 -0
  22. package/dist/runtime/live.mjs +409 -0
  23. package/dist/runtime/migration-handler.mjs +34 -1
  24. package/dist/runtime/sse-client.d.mts +22 -0
  25. package/dist/runtime/sse-client.mjs +36 -0
  26. package/dist/runtime/sse.d.mts +35 -0
  27. package/dist/runtime/sse.mjs +172 -0
  28. package/dist/{scan-C6HMEIdW.mjs → scan-QtRTdh94.mjs} +1 -1
  29. package/package.json +27 -2
  30. package/skills/void/docs/guide/live.md +230 -0
  31. package/skills/void/docs/guide/pages-routing/overview.md +11 -0
  32. package/skills/void/docs/guide/sse.md +187 -0
  33. package/skills/void/docs/index.md +12 -15
  34. package/skills/void/docs/reference/api.md +12 -4
package/dist/index.mjs CHANGED
@@ -4,10 +4,10 @@ import { u as require_picocolors } from "./output-BwlcIYSR.mjs";
4
4
  import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-CvHtTM0q.mjs";
5
5
  import { r as readProjectConfig } from "./project-TqORyHn8.mjs";
6
6
  import { c as getToken, u as isStagingMode } from "./client-DCqnMpDt.mjs";
7
- import { _ as resolveSandboxConfig, a as prerenderPagesNode, c as filterLoadedEnv, d as ensureWranglerCompatibilityDate, f as ensureWranglerNodejsAlsFlag, g as isSandboxEnabled, h as SANDBOX_MIGRATION_TAG, i as prerenderPages, l as resolveRemoteMode, m as syncWranglerBindings, n as resolveDistDir, o as DEFAULT_PROXY_URL, p as readWranglerCompat, r as resolveWorkerDirName, s as STAGING_PROXY_URL, u as stripInternalEnvKeys } from "./deploy-BkjqNk9U.mjs";
7
+ import { C as resolveSandboxConfig, S as isSandboxEnabled, _ as readExistingLiveBindingConfig, a as prerenderPagesNode, b as syncWranglerBindings, c as filterLoadedEnv, d as LIVE_MIGRATION_TAG, f as ensureWranglerCompatibilityDate, g as normalizeWranglerCompatibilityFlags, h as nextDurableObjectMigrationTag, i as prerenderPages, l as resolveRemoteMode, m as hasDurableObjectSqliteMigration, n as resolveDistDir, o as DEFAULT_PROXY_URL, p as ensureWranglerNodejsAlsFlag, r as resolveWorkerDirName, s as STAGING_PROXY_URL, u as stripInternalEnvKeys, v as readWranglerCompat, x as SANDBOX_MIGRATION_TAG, y as resolveLiveBindingConfig } from "./deploy-CRIz77mw.mjs";
8
8
  import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-BIa9HwVX.mjs";
9
- import { i as scanJobsSync, n as scanWebSocketRoutesSync, r as scanQueuesSync, t as scanRoutes } from "./scan-C6HMEIdW.mjs";
10
- import { a as SSR_SERVER_ENTRY_RELATIVE_PATHS, c as validateSsrEntry, d as isIdentifier, f as isLiteral, h as walk, i as SSR_CLIENT_ENTRY_RELATIVE_PATHS, l as inferBindingsFromSource, n as detectFramework, p as isMemberExpression, r as inferProjectBindings, s as validateSsrEntries, t as FRAMEWORK_SCAN_DIRS } from "./plugin-inference-oZ6Ybu2_.mjs";
9
+ import { i as scanJobsSync, n as scanWebSocketRoutesSync, r as scanQueuesSync, t as scanRoutes } from "./scan-QtRTdh94.mjs";
10
+ import { a as SSR_CLIENT_ENTRY_RELATIVE_PATHS, c as validateSsrEntries, f as isIdentifier, g as walk, i as inferProjectBindings, l as validateSsrEntry, m as isMemberExpression, n as FRAMEWORK_SCAN_DIRS, o as SSR_SERVER_ENTRY_RELATIVE_PATHS, p as isLiteral, r as detectFramework, t as DEFAULT_SCAN_DIRS, u as inferBindingsFromSource } from "./plugin-inference-CCtRkt9O.mjs";
11
11
  import { i as voidWarn, n as voidError, r as voidLog, t as setShowTimestamp } from "./log-DXdqnmhF.mjs";
12
12
  import { r as parseDotenvFile } from "./dotenv-DwO4ti0Z.mjs";
13
13
  import { i as generateDbDts, n as generateQueueTypes, r as DRIZZLE_OPERATORS, t as generateRouteTypes } from "./route-types-DReF1gUY.mjs";
@@ -2062,6 +2062,7 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
2062
2062
  if (auth.authConfigPath) lines.push(`import __voidAuthConfig from ${JSON.stringify(auth.authConfigPath)};`);
2063
2063
  }
2064
2064
  if (webSockets.length > 0 && options.webSocketRuntimePath) lines.push(`import { createWebSocketDurableObject as __createWebSocketDurableObject, handleWebSocketUpgrade as __handleWebSocketUpgrade, forwardWebSocketRequest as __forwardWebSocketRequest } from ${JSON.stringify(options.webSocketRuntimePath)};`);
2065
+ if (options.hasLive && options.liveRuntimePath) lines.push(`import { createLiveDurableObject as __createLiveDurableObject } from ${JSON.stringify(options.liveRuntimePath)};`);
2065
2066
  lines.push("");
2066
2067
  for (let i = 0; i < scan.middleware.length; i++) {
2067
2068
  const mw = scan.middleware[i];
@@ -2278,6 +2279,10 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
2278
2279
  lines.push("export async function __voidHandleWebSocket() { return null; }");
2279
2280
  lines.push("");
2280
2281
  }
2282
+ if (options.hasLive) {
2283
+ lines.push("export const VoidLiveStreamDurableObject = __createLiveDurableObject();");
2284
+ lines.push("");
2285
+ }
2281
2286
  if (pages && scan.pages.pages.length > 0) compilePageRoutes(lines, scan, pages, options);
2282
2287
  compilePrerenderCollector(lines, scan, ssr, options);
2283
2288
  if (ssr) {
@@ -2954,7 +2959,7 @@ function compilePageRoutes(lines, scan, pages, options) {
2954
2959
  * remote mode (`__VOID_REMOTE`) and replace local bindings with
2955
2960
  * proxy-backed versions.
2956
2961
  */
2957
- function compileWorkerEntry(hasQueues = false, remote, assetsDir = "assets", webSocketClasses = [], runtimeEnvPath = "void/_env", envSchemaModule, sandbox, serveSpaFallback = false) {
2962
+ function compileWorkerEntry(hasQueues = false, remote, assetsDir = "assets", webSocketClasses = [], runtimeEnvPath = "void/_env", envSchemaModule, sandbox, serveSpaFallback = false, live) {
2958
2963
  const remotePath = remote?.remotePath;
2959
2964
  const hasSandbox = sandbox === true || typeof sandbox === "object";
2960
2965
  const sandboxClassName = typeof sandbox === "object" ? sandbox.className ?? "Sandbox" : "Sandbox";
@@ -2962,6 +2967,12 @@ function compileWorkerEntry(hasQueues = false, remote, assetsDir = "assets", web
2962
2967
  const sandboxRuntimePath = typeof sandbox === "object" ? sandbox.runtimePath ?? "void/sandbox" : "void/sandbox";
2963
2968
  const sandboxImport = hasSandbox ? `import { Sandbox as __VoidSandbox } from "@cloudflare/sandbox";\nimport { __setSandboxBindingName } from ${JSON.stringify(sandboxRuntimePath)};\n` : "";
2964
2969
  const sandboxExport = hasSandbox ? sandboxClassName === "Sandbox" ? `export { __VoidSandbox as Sandbox };\n__setSandboxBindingName(${JSON.stringify(sandboxBindingName)});\n` : `export class ${sandboxClassName} extends __VoidSandbox {}\n__setSandboxBindingName(${JSON.stringify(sandboxBindingName)});\n` : "";
2970
+ const hasLive = live === true || typeof live === "object";
2971
+ const liveBindingName = typeof live === "object" ? live.bindingName ?? "VOID_LIVE" : "VOID_LIVE";
2972
+ const liveClassName = typeof live === "object" ? live.className ?? "VoidLiveStreamDurableObject" : "VoidLiveStreamDurableObject";
2973
+ const liveRouteImport = hasLive ? ", VoidLiveStreamDurableObject" : "";
2974
+ const liveRuntimeImport = hasLive ? `import { __setLiveBindingName } from "void/live";\n` : "";
2975
+ const liveExport = hasLive ? liveClassName === "VoidLiveStreamDurableObject" ? `export { VoidLiveStreamDurableObject };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : `export { VoidLiveStreamDurableObject as ${liveClassName} };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : "";
2965
2976
  const runtimeEnvImport = `import { withRuntimeEnv } from ${JSON.stringify(runtimeEnvPath)};\n`;
2966
2977
  const remoteImport = remote ? `import { createRemoteEnv } from ${JSON.stringify(remote.remotePath)};\n` : "";
2967
2978
  const envSchemaImport = envSchemaModule ? `import ${JSON.stringify(envSchemaModule.importPath)};\nimport { _validateEnvOnce } from ${JSON.stringify(envSchemaModule.helperPath)};\n` : "";
@@ -3076,7 +3087,7 @@ ${envValidateCall} if (env.__VOID_REMOTE === "1") env = createRemoteEnv(env);
3076
3087
  ${envValidateCall} const userEnv = __filterInternalBindings(env);
3077
3088
  return withRuntimeEnv(env, () => scheduled(controller, userEnv, ctx));
3078
3089
  }`;
3079
- if (hasQueues) return `${sandboxImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleWebSocket, __withRawEnv, __processQueue${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""} } from 'virtual:void-routes';
3090
+ if (hasQueues) return `${sandboxImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleWebSocket, __withRawEnv, __processQueue${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
3080
3091
  ${runtimeEnvImport}${envSchemaImport}${remoteImport}${filterBindingsHelper}${assetHelper}
3081
3092
  ${internalRouteHelper}
3082
3093
  ${scheduledHandler}
@@ -3102,13 +3113,15 @@ ${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = createR
3102
3113
  }
3103
3114
 
3104
3115
  ${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
3116
+ ${liveExport}
3105
3117
  ${sandboxExport}
3106
3118
  export default { fetch: ${fetchHandler}, scheduled: handleScheduled, queue };`;
3107
- return `${sandboxImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleWebSocket, __withRawEnv${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""} } from 'virtual:void-routes';
3119
+ return `${sandboxImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleWebSocket, __withRawEnv${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
3108
3120
  ${runtimeEnvImport}${envSchemaImport}${remoteImport}${filterBindingsHelper}${assetHelper}
3109
3121
  ${internalRouteHelper}
3110
3122
  ${scheduledHandler}
3111
3123
  ${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
3124
+ ${liveExport}
3112
3125
  ${sandboxExport}
3113
3126
  export default { fetch: ${fetchHandler}, scheduled: handleScheduled };`;
3114
3127
  }
@@ -3628,6 +3641,8 @@ function routingPlugin(root, options) {
3628
3641
  projectRoot: root,
3629
3642
  homeDir: homedir(),
3630
3643
  webSocketRuntimePath: resolveFile("#self/runtime/ws-server"),
3644
+ liveRuntimePath: resolveFile("#self/runtime/live-server"),
3645
+ hasLive: options.live !== void 0,
3631
3646
  reactRefresh: false,
3632
3647
  dev: false,
3633
3648
  devTriggerToken: options.devTriggerToken,
@@ -3727,7 +3742,7 @@ function routingPlugin(root, options) {
3727
3742
  bindingName: options.sandboxBindingName,
3728
3743
  className: options.sandboxClassName,
3729
3744
  runtimePath: sandboxRuntimePath
3730
- } : false));
3745
+ } : false, void 0, options.live));
3731
3746
  return {
3732
3747
  name: "void:routing",
3733
3748
  enforce: "pre",
@@ -3791,7 +3806,7 @@ function routingPlugin(root, options) {
3791
3806
  bindingName: options.sandboxBindingName,
3792
3807
  className: options.sandboxClassName,
3793
3808
  runtimePath: sandboxRuntimePath
3794
- } : false, shouldServeSpaFallback()));
3809
+ } : false, shouldServeSpaFallback(), options.live));
3795
3810
  },
3796
3811
  resolveId: {
3797
3812
  filter: { id: RESOLVE_ID_FILTER },
@@ -3834,7 +3849,7 @@ function routingPlugin(root, options) {
3834
3849
  bindingName: options.sandboxBindingName,
3835
3850
  className: options.sandboxClassName,
3836
3851
  runtimePath: sandboxRuntimePath
3837
- } : false, shouldServeSpaFallback()));
3852
+ } : false, shouldServeSpaFallback(), options.live));
3838
3853
  const structural = event !== "change";
3839
3854
  for (const env of Object.values(devServer.environments)) {
3840
3855
  const mod = env.moduleGraph.getModuleById(VIRTUAL_ROUTES_ID);
@@ -4250,6 +4265,7 @@ function voidPlugin(options) {
4250
4265
  const authEnabled = bindings.needsAuth || authConfigPath !== null || config.auth !== void 0;
4251
4266
  if (detected && authEnabled) throw new Error("auth: Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
4252
4267
  if (detected && bindings.needsSandbox) throw new Error("sandbox: Cloudflare Sandboxes are currently supported in Void apps only.");
4268
+ if (detected && bindings.needsLive) throw new Error("live: void/live is currently supported in Void apps only.");
4253
4269
  const STUB_PREFIX = "\0void-client-stub:";
4254
4270
  const SERVER_ONLY_STUBS = {
4255
4271
  "void/db": "export const db = {}; export const createDb = () => ({});",
@@ -4258,7 +4274,8 @@ function voidPlugin(options) {
4258
4274
  "void/queues": "export const queues = {};",
4259
4275
  "void/storage": "export const storage = {}; export const createStorage = () => ({});",
4260
4276
  "void/isr": "export const revalidate = async () => {};",
4261
- "void/sandbox": "export const sandbox = {}; export const getSandbox = () => ({});"
4277
+ "void/sandbox": "export const sandbox = {}; export const getSandbox = () => ({});",
4278
+ "void/live": ""
4262
4279
  };
4263
4280
  const STUB_RESOLVE_FILTER = new RegExp(`^(${Object.keys(SERVER_ONLY_STUBS).join("|").replaceAll("/", "\\/")})$`);
4264
4281
  const STUB_LOAD_FILTER = new RegExp(`^\\0void-client-stub:`);
@@ -4268,7 +4285,10 @@ function voidPlugin(options) {
4268
4285
  resolveId: {
4269
4286
  filter: { id: STUB_RESOLVE_FILTER },
4270
4287
  handler(id) {
4271
- if (this.environment?.name === "client") return STUB_PREFIX + id;
4288
+ if (this.environment?.name === "client") {
4289
+ if (id === "void/live") this.error("void/live is server-only and cannot be imported by browser code. Import void/live/client instead.");
4290
+ return STUB_PREFIX + id;
4291
+ }
4272
4292
  }
4273
4293
  },
4274
4294
  load: {
@@ -4280,6 +4300,10 @@ function voidPlugin(options) {
4280
4300
  };
4281
4301
  const queues = framework ? [] : scanQueuesSync(root);
4282
4302
  const websocketRoutes = framework ? [] : scanWebSocketRoutesSync(root);
4303
+ const liveConfig = !isNodeTarget(config.target) ? bindings.needsLive ? resolveLiveBindingConfig(root, {
4304
+ reservedBindings: websocketRoutes.map((route) => route.bindingName),
4305
+ reservedClasses: [...websocketRoutes.map((route) => route.className), sandboxConfig?.className]
4306
+ }) : readExistingLiveBindingConfig(root) : void 0;
4283
4307
  if (detected && (detected.class === "b" || detected.class === "c")) {
4284
4308
  const bindingNames = resolveBindingNames(config.inference?.bindings);
4285
4309
  const frameworkPersistRoot = join(root, ".wrangler", "state");
@@ -4305,7 +4329,8 @@ function voidPlugin(options) {
4305
4329
  if (syncWranglerBindings(root, bindings, {
4306
4330
  bindingNames,
4307
4331
  websockets: websocketRoutes,
4308
- sandbox: sandboxConfig
4332
+ sandbox: sandboxConfig,
4333
+ live: liveConfig
4309
4334
  })) voidLog("Synced bindings to wrangler.jsonc");
4310
4335
  }
4311
4336
  },
@@ -4417,6 +4442,19 @@ function voidPlugin(options) {
4417
4442
  new_sqlite_classes: [sandboxConfig.className]
4418
4443
  }];
4419
4444
  }
4445
+ if (liveConfig) {
4446
+ const existingDurableObjectBindings = (result.durable_objects ?? resolved.durable_objects)?.bindings ?? [];
4447
+ if (!existingDurableObjectBindings.some((binding) => binding.name === liveConfig.bindingName)) result.durable_objects = { bindings: [...existingDurableObjectBindings, {
4448
+ name: liveConfig.bindingName,
4449
+ class_name: liveConfig.className
4450
+ }] };
4451
+ const currentMigrations = result.migrations ?? resolved.migrations;
4452
+ const existingMigrations = Array.isArray(currentMigrations) ? currentMigrations : [];
4453
+ if (!hasDurableObjectSqliteMigration(existingMigrations, liveConfig.className)) result.migrations = [...existingMigrations, {
4454
+ tag: nextDurableObjectMigrationTag(existingMigrations, LIVE_MIGRATION_TAG),
4455
+ new_sqlite_classes: [liveConfig.className]
4456
+ }];
4457
+ }
4420
4458
  if (viteCommand === "serve" && bindings.needsAI) {
4421
4459
  const credentials = readVoidDevCredentials(root);
4422
4460
  if (credentials.status === "ok") {
@@ -4519,13 +4557,7 @@ function voidPlugin(options) {
4519
4557
  apply: "serve",
4520
4558
  configureServer(server) {
4521
4559
  if (!autoDetectBindings && !autoDetectAuth) return;
4522
- const watchDirs = [...new Set([...scanDirs ?? [
4523
- "routes",
4524
- "middleware",
4525
- "queues",
4526
- "pages",
4527
- "crons"
4528
- ], "src"])].map((d) => join(root, d));
4560
+ const watchDirs = [...new Set([...scanDirs ?? DEFAULT_SCAN_DIRS, "src"])].map((d) => join(root, d));
4529
4561
  let hintShown = false;
4530
4562
  const check = (path) => {
4531
4563
  if (hintShown) return;
@@ -4618,6 +4650,7 @@ function voidPlugin(options) {
4618
4650
  if (config.worker) voidWarn("\"worker\" in void.json is ignored with target: \"" + config.target + "\"");
4619
4651
  if (config.remote) voidWarn("\"remote\" in void.json is ignored with target: \"" + config.target + "\"");
4620
4652
  if (bindings.needsSandbox) throw new Error(`sandbox: Cloudflare Sandboxes require target: "cloudflare". They are not available with target: '${config.target}'.`);
4653
+ if (bindings.needsLive) throw new Error(`live: void/live requires target: "cloudflare". It is not available with target: '${config.target}'.`);
4621
4654
  if (config.routing?.revalidate) voidWarn("\"routing.revalidate\" in void.json is ignored with target: \"" + config.target + "\" (edge caching is CF-only)");
4622
4655
  return [
4623
4656
  restartPlugin(),
@@ -4638,8 +4671,8 @@ function voidPlugin(options) {
4638
4671
  ];
4639
4672
  }
4640
4673
  const existingFlags = workerConfig.compatibility_flags ?? [];
4641
- if ((dialect === "postgresql" || bindings.needsSandbox) && !existingFlags.includes("nodejs_compat")) workerConfig.compatibility_flags = [...existingFlags.filter((f) => f !== "nodejs_als"), "nodejs_compat"];
4642
- else if (!existingFlags.includes("nodejs_als") && !existingFlags.includes("nodejs_compat")) workerConfig.compatibility_flags = [...existingFlags, "nodejs_als"];
4674
+ const normalizedFlags = normalizeWranglerCompatibilityFlags(existingFlags, { needsNodejsCompat: authEnabled || dialect === "postgresql" || bindings.needsSandbox });
4675
+ if (normalizedFlags && normalizedFlags !== existingFlags) workerConfig.compatibility_flags = normalizedFlags;
4643
4676
  const jobs = scanJobsSync(root);
4644
4677
  const ssrEntry = validateSsrEntry(root);
4645
4678
  const hasPages = existsSync(join(root, "pages"));
@@ -4671,7 +4704,8 @@ function voidPlugin(options) {
4671
4704
  routing: config.routing,
4672
4705
  hasSandbox: bindings.needsSandbox,
4673
4706
  sandboxBindingName: sandboxConfig?.binding,
4674
- sandboxClassName: sandboxConfig?.className
4707
+ sandboxClassName: sandboxConfig?.className,
4708
+ live: liveConfig
4675
4709
  }),
4676
4710
  drizzlePlugin(root, true, dialect, { forceVirtualDb: authEnabled }),
4677
4711
  migrationPlugin(root, dialect, "local", join(root, ".void"), {
@@ -4,7 +4,7 @@ import { _ as me, c as R, g as ge, i as Ee, u as Se, v as ue, x as q, y as ye }
4
4
  import { a as writeProjectConfig, r as readProjectConfig } from "./project-TqORyHn8.mjs";
5
5
  import { c as getToken, n as PlatformClient, u as isStagingMode } from "./client-DCqnMpDt.mjs";
6
6
  import { c as getDatabaseDialect, f as readConfig } from "./config-BIa9HwVX.mjs";
7
- import { n as detectFramework } from "./plugin-inference-oZ6Ybu2_.mjs";
7
+ import { r as detectFramework } from "./plugin-inference-CCtRkt9O.mjs";
8
8
  import { r as parseDotenvFile, t as expandDotenv } from "./dotenv-DwO4ti0Z.mjs";
9
9
  import { n as ensureProjectTsconfig, t as createProjectTsconfig } from "./project-tsconfig-DfkESbDL.mjs";
10
10
  import { t as MagicString } from "./magic-string.es-D6g9UnIy.mjs";
@@ -12,7 +12,7 @@ import { n as writeDrizzleConfig } from "./config-BzM9Dy7T.mjs";
12
12
  import { n as getAgentById, r as getPackageDir, t as detectAgents } from "./agents-DqkFfc2c.mjs";
13
13
  import { n as promptProjectSelection, t as promptAndCreateProject } from "./create-project-Bg88Kq_I.mjs";
14
14
  import { t as promptForLoginToken } from "./login-B5HHT32i.mjs";
15
- import { r as formatProjectCommand } from "./preset-DFvePt0l.mjs";
15
+ import { r as formatProjectCommand } from "./preset-jKn1hQwP.mjs";
16
16
  import { n as findInstalledYarnPnpRuntime, r as hasLocalLockfile, t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-6LD6_3Ej.mjs";
17
17
  import { createRequire } from "node:module";
18
18
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
@@ -1,4 +1,4 @@
1
- import { t as PageObject } from "../protocol-CK4OFwfR.mjs";
1
+ import { t as PageObject } from "../protocol-DxGzKEz2.mjs";
2
2
  import { CacheForInput, CacheForResult } from "./prefetch.mjs";
3
3
 
4
4
  //#region src/pages/action-result.d.ts
@@ -147,6 +147,7 @@ interface VoidRouter {
147
147
  readonly url: URL;
148
148
  readonly path: string;
149
149
  readonly query: URLSearchParams;
150
+ readonly params: Record<string, string>;
150
151
  visit(url: string | URL, options?: VisitOptions): Promise<unknown>;
151
152
  refresh(options?: VisitOptions): Promise<unknown>;
152
153
  prefetch(url: string | URL, options?: PrefetchOptions): Promise<unknown>;
@@ -178,8 +179,8 @@ interface VoidRouterConfig {
178
179
  onNavigationChange?(navigation: NavigationState): void;
179
180
  }
180
181
  declare function idleNavigationState(): NavigationState;
181
- declare function createRouterFacade(router: VoidRouter, getCurrentUrl: () => string): VoidRouter;
182
- declare function createSsrRouter(url?: string): VoidRouter;
182
+ declare function createRouterFacade(router: VoidRouter, getCurrentUrl: () => string, getCurrentParams?: () => Record<string, string>): VoidRouter;
183
+ declare function createSsrRouter(url?: string, params?: Record<string, string>): VoidRouter;
183
184
  declare function isFile(value: unknown): boolean;
184
185
  declare function hasFiles(data: unknown): boolean;
185
186
  declare function objectToFormData(source: Record<string, unknown>, form?: FormData, parentKey?: string): FormData;
@@ -756,7 +756,7 @@ function idleNavigationState() {
756
756
  method: null
757
757
  };
758
758
  }
759
- function createRouterFacade(router, getCurrentUrl) {
759
+ function createRouterFacade(router, getCurrentUrl, getCurrentParams = () => router.params) {
760
760
  return {
761
761
  get _hoverDelay() {
762
762
  return router._hoverDelay;
@@ -770,6 +770,9 @@ function createRouterFacade(router, getCurrentUrl) {
770
770
  get query() {
771
771
  return this.url.searchParams;
772
772
  },
773
+ get params() {
774
+ return getCurrentParams();
775
+ },
773
776
  visit(url, options = {}) {
774
777
  return router.visit(url, options);
775
778
  },
@@ -787,7 +790,7 @@ function createRouterFacade(router, getCurrentUrl) {
787
790
  }
788
791
  };
789
792
  }
790
- function createSsrRouter(url = "/") {
793
+ function createSsrRouter(url = "/", params = {}) {
791
794
  return {
792
795
  _hoverDelay: 75,
793
796
  get url() {
@@ -799,6 +802,9 @@ function createSsrRouter(url = "/") {
799
802
  get query() {
800
803
  return this.url.searchParams;
801
804
  },
805
+ get params() {
806
+ return params;
807
+ },
802
808
  visit() {
803
809
  throw new Error("Void Router: visit() is not available during SSR.");
804
810
  },
@@ -870,9 +876,11 @@ async function createVoidRouter(config) {
870
876
  {
871
877
  const engine = await createPageNavigationEngine(config);
872
878
  let routeUrl = currentUrl();
879
+ let routeParams = engine.initialPageData.params ?? {};
873
880
  let activeNavigationId = null;
874
- const setRouteUrl = (url) => {
881
+ const setRouteState = (url, params = routeParams) => {
875
882
  routeUrl = url;
883
+ routeParams = params;
876
884
  config.onRouteChange?.(url);
877
885
  };
878
886
  const setNavigation = (navigation) => {
@@ -884,11 +892,12 @@ async function createVoidRouter(config) {
884
892
  try {
885
893
  const result = await resource.shell;
886
894
  if (!result) return;
895
+ setRouteState(result.pageData.url || resource.fetchUrl + resource.hash, result.pageData.params ?? {});
887
896
  const applyUpdate = () => config.adapter.applyUpdate(result.pageData, result.component, result.layouts);
888
897
  if ((resource.options.viewTransition ?? config.viewTransitions) && document.startViewTransition) await document.startViewTransition(() => applyUpdate()).updateCallbackDone;
889
898
  else await applyUpdate();
890
899
  await resource.commit();
891
- if (activeNavigationId === resource.id) setRouteUrl(currentUrl());
900
+ if (activeNavigationId === resource.id) setRouteState(currentUrl(), result.pageData.params ?? {});
892
901
  return result.pageData;
893
902
  } catch (error) {
894
903
  if (resource.method.toUpperCase() === "GET" && !resource.options._resolveOnShell && isAbortError(error)) return;
@@ -896,7 +905,7 @@ async function createVoidRouter(config) {
896
905
  } finally {
897
906
  if (activeNavigationId === resource.id) {
898
907
  activeNavigationId = null;
899
- setRouteUrl(currentUrl());
908
+ setRouteState(currentUrl());
900
909
  setNavigation(idleNavigationState());
901
910
  }
902
911
  }
@@ -912,6 +921,9 @@ async function createVoidRouter(config) {
912
921
  get query() {
913
922
  return this.url.searchParams;
914
923
  },
924
+ get params() {
925
+ return routeParams;
926
+ },
915
927
  visit(url, options = {}) {
916
928
  return applyNavigationResource(engine.prepareVisit(normalizeUrl(url), options));
917
929
  },
@@ -932,7 +944,7 @@ async function createVoidRouter(config) {
932
944
  engine.flushAll();
933
945
  }
934
946
  };
935
- const router = createRouterFacade(rawRouter, () => routeUrl);
947
+ const router = createRouterFacade(rawRouter, () => routeUrl, () => routeParams);
936
948
  engine.setPopStateHandler((url, options) => {
937
949
  router.visit(url, options);
938
950
  });
@@ -1,3 +1,3 @@
1
1
  import { S as ValidationError } from "../handler-dKQWyF-G.mjs";
2
- import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-CK4OFwfR.mjs";
2
+ import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-DxGzKEz2.mjs";
3
3
  export { PageObject, PageRenderResult, ValidationError, flattenValidationErrors, handlePageGet, handlePageMutation, safeJsonStringify };
@@ -25,6 +25,9 @@ function pageJsonResponse(c, pageObj) {
25
25
  function requestPathWithSearch(c) {
26
26
  return c.req.path + new URL(c.req.url).search;
27
27
  }
28
+ function requestParams(c) {
29
+ return c.req.param();
30
+ }
28
31
  /** Extract props from a handler result, handling Response wrapping from withValidator */
29
32
  async function extractProps(result) {
30
33
  if (result instanceof Response) {
@@ -107,6 +110,7 @@ async function handlePageGet(handler, headFn, c, componentId, renderFn, getAsset
107
110
  const pageObj = {
108
111
  component: componentId,
109
112
  props: immediateProps,
113
+ params: requestParams(c),
110
114
  shared,
111
115
  url: requestPathWithSearch(c),
112
116
  errors: null,
@@ -159,6 +163,7 @@ async function handlePageMutation(mutationHandler, getHandler, headFn, c, compon
159
163
  return {
160
164
  component: componentId,
161
165
  props,
166
+ params: requestParams(c),
162
167
  shared,
163
168
  url: requestPathWithSearch(c),
164
169
  errors,
@@ -2120,7 +2120,8 @@ function inferBindingsFromSource(code, filename) {
2120
2120
  needsAuth: false,
2121
2121
  needsQueues: false,
2122
2122
  needsAI: false,
2123
- needsSandbox: false
2123
+ needsSandbox: false,
2124
+ needsLive: false
2124
2125
  };
2125
2126
  try {
2126
2127
  const [imports] = parse(code);
@@ -2149,6 +2150,9 @@ function inferBindingsFromSource(code, filename) {
2149
2150
  case "void/sandbox":
2150
2151
  result.needsSandbox = true;
2151
2152
  break;
2153
+ case "void/live":
2154
+ if (!isTypeOnlyImportStatement(code.slice(imp.ss, imp.se + 1))) result.needsLive = true;
2155
+ break;
2152
2156
  case "void/client": {
2153
2157
  const stmt = code.slice(imp.ss, imp.se + 1);
2154
2158
  if (/\bauth\b/.test(stmt)) result.needsAuth = true;
@@ -2164,9 +2168,10 @@ function inferBindingsFromSource(code, filename) {
2164
2168
  if (/\bfrom\s+["']void\/queue["']/.test(code)) result.needsQueues = true;
2165
2169
  if (/\bfrom\s+["']void\/ai["']/.test(code)) result.needsAI = true;
2166
2170
  if (/\bfrom\s+["']void\/sandbox["']/.test(code)) result.needsSandbox = true;
2171
+ if (hasRuntimeImportFrom(code, "void/live")) result.needsLive = true;
2167
2172
  if (/\bfrom\s+["']void\/client["']/.test(code) && /\bauth\b/.test(code)) result.needsAuth = true;
2168
2173
  }
2169
- if (result.needsD1 && result.needsKV && result.needsR2 && result.needsAI && result.needsSandbox) return result;
2174
+ if (result.needsD1 && result.needsKV && result.needsR2 && result.needsAI && result.needsSandbox && result.needsLive) return result;
2170
2175
  if (!ENV_BINDING_RE.test(code)) return result;
2171
2176
  let parsed;
2172
2177
  try {
@@ -2208,6 +2213,25 @@ function inferBindingsFromSource(code, filename) {
2208
2213
  } });
2209
2214
  return result;
2210
2215
  }
2216
+ function isTypeOnlyImportStatement(statement) {
2217
+ if (/^\s*import\s+type\b/.test(statement)) return true;
2218
+ const specifierStart = statement.indexOf("{");
2219
+ const specifierEnd = statement.lastIndexOf("}");
2220
+ if (specifierStart === -1 || specifierEnd === -1 || specifierEnd < specifierStart) return false;
2221
+ const beforeSpecifiers = statement.slice(0, specifierStart);
2222
+ if (!/^\s*import\s*$/.test(beforeSpecifiers)) return false;
2223
+ const specifiers = statement.slice(specifierStart + 1, specifierEnd).split(",").map((specifier) => specifier.trim()).filter(Boolean);
2224
+ return specifiers.length > 0 && specifiers.every((specifier) => specifier.startsWith("type "));
2225
+ }
2226
+ function hasRuntimeImportFrom(code, source) {
2227
+ const escapedSource = source.replaceAll("/", "\\/");
2228
+ const importRe = new RegExp(`\\bimport\\s+(?:[\\s\\S]*?\\bfrom\\s+)?["']${escapedSource}["']\\s*;?`, "g");
2229
+ for (const match of code.matchAll(importRe)) {
2230
+ const statement = match[0];
2231
+ if (!isTypeOnlyImportStatement(statement)) return true;
2232
+ }
2233
+ return false;
2234
+ }
2211
2235
  /**
2212
2236
  * Merge multiple InferredBindings into a single result (union).
2213
2237
  */
@@ -2219,7 +2243,8 @@ function mergeBindings(bindings) {
2219
2243
  needsAuth: bindings.some((b) => b.needsAuth),
2220
2244
  needsQueues: bindings.some((b) => b.needsQueues),
2221
2245
  needsAI: bindings.some((b) => b.needsAI),
2222
- needsSandbox: bindings.some((b) => b.needsSandbox)
2246
+ needsSandbox: bindings.some((b) => b.needsSandbox),
2247
+ needsLive: bindings.some((b) => b.needsLive)
2223
2248
  };
2224
2249
  }
2225
2250
  //#endregion
@@ -2309,6 +2334,15 @@ const FRAMEWORK_SCAN_DIRS = [
2309
2334
  "crons",
2310
2335
  "queues"
2311
2336
  ];
2337
+ /** Directories to scan for binding inference in Void app mode. */
2338
+ const DEFAULT_SCAN_DIRS = [
2339
+ "routes",
2340
+ "middleware",
2341
+ "queues",
2342
+ "pages",
2343
+ "crons",
2344
+ "src"
2345
+ ];
2312
2346
  /**
2313
2347
  * Map from npm package name to framework identifier.
2314
2348
  * Only packages that unambiguously indicate framework mode are listed.
@@ -2393,15 +2427,10 @@ function inferProjectBindings(root, options, scanDirs) {
2393
2427
  needsAuth: false,
2394
2428
  needsQueues: false,
2395
2429
  needsAI: Boolean(options.bindings.ai),
2396
- needsSandbox: false
2430
+ needsSandbox: false,
2431
+ needsLive: false
2397
2432
  };
2398
- const dirs = scanDirs ?? [
2399
- "routes",
2400
- "middleware",
2401
- "queues",
2402
- "pages",
2403
- "crons"
2404
- ];
2433
+ const dirs = scanDirs ?? DEFAULT_SCAN_DIRS;
2405
2434
  const allBindings = [];
2406
2435
  for (const dir of dirs) {
2407
2436
  const dirPath = join(root, dir);
@@ -2444,4 +2473,4 @@ function inferProjectBindings(root, options, scanDirs) {
2444
2473
  return mergeBindings(allBindings);
2445
2474
  }
2446
2475
  //#endregion
2447
- export { SSR_SERVER_ENTRY_RELATIVE_PATHS as a, validateSsrEntry as c, isIdentifier as d, isLiteral as f, walk as h, SSR_CLIENT_ENTRY_RELATIVE_PATHS as i, inferBindingsFromSource as l, isObjectExpression as m, detectFramework as n, hasSsrEntry as o, isMemberExpression as p, inferProjectBindings as r, validateSsrEntries as s, FRAMEWORK_SCAN_DIRS as t, isCallExpression as u };
2476
+ export { SSR_CLIENT_ENTRY_RELATIVE_PATHS as a, validateSsrEntries as c, isCallExpression as d, isIdentifier as f, walk as g, isObjectExpression as h, inferProjectBindings as i, validateSsrEntry as l, isMemberExpression as m, FRAMEWORK_SCAN_DIRS as n, SSR_SERVER_ENTRY_RELATIVE_PATHS as o, isLiteral as p, detectFramework as r, hasSsrEntry as s, DEFAULT_SCAN_DIRS as t, inferBindingsFromSource as u };
@@ -3,8 +3,8 @@ import { n as cliTitle } from "./output-BwlcIYSR.mjs";
3
3
  import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-CvHtTM0q.mjs";
4
4
  import { c as R, g as ge, u as Se, y as ye } from "./dist-Dayj3gCK.mjs";
5
5
  import { c as getDatabaseDialect, f as readConfig } from "./config-BIa9HwVX.mjs";
6
- import { t as scanRoutes } from "./scan-C6HMEIdW.mjs";
7
- import { n as detectFramework, r as inferProjectBindings, t as FRAMEWORK_SCAN_DIRS } from "./plugin-inference-oZ6Ybu2_.mjs";
6
+ import { t as scanRoutes } from "./scan-QtRTdh94.mjs";
7
+ import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-CCtRkt9O.mjs";
8
8
  import { i as generateDbDts, n as generateQueueTypes, t as generateRouteTypes } from "./route-types-DReF1gUY.mjs";
9
9
  import { n as ensureProjectTsconfig } from "./project-tsconfig-DfkESbDL.mjs";
10
10
  import { t as discoverSchema } from "./discover-B7FkXBLB.mjs";
@@ -1,5 +1,5 @@
1
1
  import { a as join, s as resolve } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
2
- import { o as hasSsrEntry } from "./plugin-inference-oZ6Ybu2_.mjs";
2
+ import { s as hasSsrEntry } from "./plugin-inference-CCtRkt9O.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  //#region src/cli/preset.ts
5
5
  /**
@@ -7,6 +7,7 @@ declare function safeJsonStringify(value: unknown): string;
7
7
  interface PageObject {
8
8
  component: string;
9
9
  props: Record<string, unknown>;
10
+ params: Record<string, string>;
10
11
  shared: Record<string, unknown>;
11
12
  url: string;
12
13
  errors: Record<string, string> | null;
@@ -1,5 +1,5 @@
1
1
  import { t as applyPgAuthMigrations } from "../auth-migrations-BwLPwRgH.mjs";
2
- import { t as createVoidAuthRuntime } from "../better-auth-shared-APuDaPqW.mjs";
2
+ import { t as createVoidAuthRuntime } from "../better-auth-shared-CjnJZFC0.mjs";
3
3
  //#region src/runtime/better-auth-pg.ts
4
4
  function resolveConnectionString(env) {
5
5
  const connectionString = typeof env.DATABASE_URL === "string" && env.DATABASE_URL.length > 0 ? env.DATABASE_URL : typeof env.HYPERDRIVE?.connectionString === "string" && env.HYPERDRIVE.connectionString.length > 0 ? env.HYPERDRIVE.connectionString : void 0;
@@ -1,5 +1,5 @@
1
1
  import { n as applySqliteAuthMigrations } from "../auth-migrations-BwLPwRgH.mjs";
2
- import { t as createVoidAuthRuntime } from "../better-auth-shared-APuDaPqW.mjs";
2
+ import { t as createVoidAuthRuntime } from "../better-auth-shared-CjnJZFC0.mjs";
3
3
  //#region src/runtime/better-auth.ts
4
4
  async function resolveDatabase(env) {
5
5
  if (!env.DB) throw new Error("auth: Better Auth requires the \"DB\" D1 binding for sqlite apps.");
@@ -0,0 +1,34 @@
1
+ import { LiveClientEvent } from "./live.mjs";
2
+
3
+ //#region src/runtime/live-client.d.ts
4
+ type LiveSubscribeOptions<Data = unknown> = {
5
+ id: string;
6
+ topic: string;
7
+ lastEventId?: string;
8
+ onEvent?: (event: LiveClientEvent<Data>) => void;
9
+ };
10
+ type ConnectLiveStreamOptions = {
11
+ withCredentials?: boolean;
12
+ fetch?: typeof fetch;
13
+ headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
14
+ eventSource?: EventSourceConstructor;
15
+ keepOpen?: boolean;
16
+ retryDelay?: number;
17
+ onError?: (error: Event | Error) => void;
18
+ };
19
+ type LiveClient = {
20
+ readonly connectionId: string;
21
+ subscribe<Data = unknown>(options: LiveSubscribeOptions<Data>): Promise<() => Promise<void>>;
22
+ close(): void;
23
+ };
24
+ type EventSourceLike = {
25
+ addEventListener(type: string, listener: (event: Event) => void): void;
26
+ removeEventListener(type: string, listener: (event: Event) => void): void;
27
+ close(): void;
28
+ };
29
+ type EventSourceConstructor = new (url: string, options?: {
30
+ withCredentials?: boolean;
31
+ }) => EventSourceLike;
32
+ declare function connectLiveStream(url: string | URL, options?: ConnectLiveStreamOptions): LiveClient;
33
+ //#endregion
34
+ export { ConnectLiveStreamOptions, LiveClient, LiveSubscribeOptions, connectLiveStream };