vinext 0.0.39 → 0.0.41

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 (100) hide show
  1. package/README.md +1 -1
  2. package/dist/build/standalone.js +7 -0
  3. package/dist/build/standalone.js.map +1 -1
  4. package/dist/check.js +2 -2
  5. package/dist/check.js.map +1 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/entries/app-rsc-entry.d.ts +2 -1
  8. package/dist/entries/app-rsc-entry.js +185 -264
  9. package/dist/entries/app-rsc-entry.js.map +1 -1
  10. package/dist/entries/pages-server-entry.js +205 -199
  11. package/dist/entries/pages-server-entry.js.map +1 -1
  12. package/dist/index.d.ts +32 -1
  13. package/dist/index.js +81 -6
  14. package/dist/index.js.map +1 -1
  15. package/dist/init.d.ts +1 -1
  16. package/dist/init.js +2 -2
  17. package/dist/init.js.map +1 -1
  18. package/dist/plugins/fonts.js +1 -0
  19. package/dist/plugins/fonts.js.map +1 -1
  20. package/dist/plugins/server-externals-manifest.d.ts +11 -1
  21. package/dist/plugins/server-externals-manifest.js +10 -3
  22. package/dist/plugins/server-externals-manifest.js.map +1 -1
  23. package/dist/routing/app-router.d.ts +10 -2
  24. package/dist/routing/app-router.js +37 -22
  25. package/dist/routing/app-router.js.map +1 -1
  26. package/dist/server/app-page-boundary-render.d.ts +1 -0
  27. package/dist/server/app-page-boundary-render.js +1 -0
  28. package/dist/server/app-page-boundary-render.js.map +1 -1
  29. package/dist/server/app-page-render.d.ts +1 -0
  30. package/dist/server/app-page-render.js +2 -0
  31. package/dist/server/app-page-render.js.map +1 -1
  32. package/dist/server/app-page-response.d.ts +4 -1
  33. package/dist/server/app-page-response.js +14 -8
  34. package/dist/server/app-page-response.js.map +1 -1
  35. package/dist/server/app-page-route-wiring.d.ts +79 -0
  36. package/dist/server/app-page-route-wiring.js +167 -0
  37. package/dist/server/app-page-route-wiring.js.map +1 -0
  38. package/dist/server/app-page-stream.d.ts +4 -1
  39. package/dist/server/app-page-stream.js +5 -1
  40. package/dist/server/app-page-stream.js.map +1 -1
  41. package/dist/server/app-route-handler-response.js +6 -2
  42. package/dist/server/app-route-handler-response.js.map +1 -1
  43. package/dist/server/app-router-entry.d.ts +6 -1
  44. package/dist/server/app-router-entry.js +9 -2
  45. package/dist/server/app-router-entry.js.map +1 -1
  46. package/dist/server/app-ssr-entry.d.ts +3 -1
  47. package/dist/server/app-ssr-entry.js +17 -17
  48. package/dist/server/app-ssr-entry.js.map +1 -1
  49. package/dist/server/app-ssr-stream.d.ts +1 -1
  50. package/dist/server/app-ssr-stream.js +4 -4
  51. package/dist/server/app-ssr-stream.js.map +1 -1
  52. package/dist/server/csp.d.ts +12 -0
  53. package/dist/server/csp.js +46 -0
  54. package/dist/server/csp.js.map +1 -0
  55. package/dist/server/dev-server.js +20 -14
  56. package/dist/server/dev-server.js.map +1 -1
  57. package/dist/server/html.d.ts +4 -1
  58. package/dist/server/html.js +11 -1
  59. package/dist/server/html.js.map +1 -1
  60. package/dist/server/middleware-response-headers.d.ts +12 -0
  61. package/dist/server/middleware-response-headers.js +23 -0
  62. package/dist/server/middleware-response-headers.js.map +1 -0
  63. package/dist/server/pages-page-data.d.ts +1 -0
  64. package/dist/server/pages-page-data.js +2 -2
  65. package/dist/server/pages-page-data.js.map +1 -1
  66. package/dist/server/pages-page-response.d.ts +2 -1
  67. package/dist/server/pages-page-response.js +16 -14
  68. package/dist/server/pages-page-response.js.map +1 -1
  69. package/dist/server/prod-server.d.ts +1 -1
  70. package/dist/server/prod-server.js +41 -14
  71. package/dist/server/prod-server.js.map +1 -1
  72. package/dist/server/request-pipeline.d.ts +14 -1
  73. package/dist/server/request-pipeline.js +55 -1
  74. package/dist/server/request-pipeline.js.map +1 -1
  75. package/dist/server/worker-utils.d.ts +4 -1
  76. package/dist/server/worker-utils.js +31 -1
  77. package/dist/server/worker-utils.js.map +1 -1
  78. package/dist/shims/error-boundary.d.ts +14 -5
  79. package/dist/shims/error-boundary.js +23 -3
  80. package/dist/shims/error-boundary.js.map +1 -1
  81. package/dist/shims/head.js.map +1 -1
  82. package/dist/shims/navigation.d.ts +16 -1
  83. package/dist/shims/navigation.js +18 -3
  84. package/dist/shims/navigation.js.map +1 -1
  85. package/dist/shims/router.js +127 -38
  86. package/dist/shims/router.js.map +1 -1
  87. package/dist/shims/script-nonce-context.d.ts +12 -0
  88. package/dist/shims/script-nonce-context.js +17 -0
  89. package/dist/shims/script-nonce-context.js.map +1 -0
  90. package/dist/shims/script.js +41 -10
  91. package/dist/shims/script.js.map +1 -1
  92. package/dist/shims/server.d.ts +17 -4
  93. package/dist/shims/server.js +97 -74
  94. package/dist/shims/server.js.map +1 -1
  95. package/dist/shims/slot.d.ts +28 -0
  96. package/dist/shims/slot.js +49 -0
  97. package/dist/shims/slot.js.map +1 -0
  98. package/dist/shims/url-safety.js +25 -4
  99. package/dist/shims/url-safety.js.map +1 -1
  100. package/package.json +7 -8
@@ -77,6 +77,14 @@ var NextRequest = class extends Request {
77
77
  return this._nextUrl.buildId;
78
78
  }
79
79
  };
80
+ /** Valid HTTP redirect status codes, matching Next.js's REDIRECTS set. */
81
+ const REDIRECT_STATUSES = new Set([
82
+ 301,
83
+ 302,
84
+ 303,
85
+ 307,
86
+ 308
87
+ ]);
80
88
  var NextResponse = class NextResponse extends Response {
81
89
  _cookies;
82
90
  constructor(body, init) {
@@ -102,6 +110,7 @@ var NextResponse = class NextResponse extends Response {
102
110
  */
103
111
  static redirect(url, init) {
104
112
  const status = typeof init === "number" ? init : init?.status ?? 307;
113
+ if (!REDIRECT_STATUSES.has(status)) throw new RangeError(`Failed to execute "redirect" on "response": Invalid status code`);
105
114
  const destination = typeof url === "string" ? url : url.toString();
106
115
  const headers = new Headers(typeof init === "object" ? init?.headers : void 0);
107
116
  headers.set("Location", destination);
@@ -338,16 +347,21 @@ var RequestCookies = class {
338
347
  cookieName = nameOrOptions.name;
339
348
  cookieValue = nameOrOptions.value;
340
349
  }
350
+ validateCookieName(cookieName);
341
351
  this._parsed.set(cookieName, cookieValue);
342
352
  this._syncHeader();
343
353
  return this;
344
354
  }
345
355
  delete(names) {
346
356
  if (Array.isArray(names)) {
347
- const results = names.map((name) => this._parsed.delete(name));
357
+ const results = names.map((name) => {
358
+ validateCookieName(name);
359
+ return this._parsed.delete(name);
360
+ });
348
361
  this._syncHeader();
349
362
  return results;
350
363
  }
364
+ validateCookieName(names);
351
365
  const result = this._parsed.delete(names);
352
366
  this._syncHeader();
353
367
  return result;
@@ -390,54 +404,11 @@ function validateCookieAttributeValue(value, attributeName) {
390
404
  }
391
405
  var ResponseCookies = class {
392
406
  _headers;
407
+ /** Internal map keyed by cookie name — single source of truth. */
408
+ _parsed = /* @__PURE__ */ new Map();
393
409
  constructor(headers) {
394
410
  this._headers = headers;
395
- }
396
- set(name, value, options) {
397
- validateCookieName(name);
398
- const parts = [`${name}=${encodeURIComponent(value)}`];
399
- if (options?.path) {
400
- validateCookieAttributeValue(options.path, "Path");
401
- parts.push(`Path=${options.path}`);
402
- }
403
- if (options?.domain) {
404
- validateCookieAttributeValue(options.domain, "Domain");
405
- parts.push(`Domain=${options.domain}`);
406
- }
407
- if (options?.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
408
- if (options?.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
409
- if (options?.httpOnly) parts.push("HttpOnly");
410
- if (options?.secure) parts.push("Secure");
411
- if (options?.sameSite) parts.push(`SameSite=${options.sameSite}`);
412
- this._headers.append("Set-Cookie", parts.join("; "));
413
- return this;
414
- }
415
- get(name) {
416
- for (const header of this._headers.getSetCookie()) {
417
- const eq = header.indexOf("=");
418
- if (eq === -1) continue;
419
- if (header.slice(0, eq) === name) {
420
- const semi = header.indexOf(";", eq);
421
- const raw = header.slice(eq + 1, semi === -1 ? void 0 : semi);
422
- let value;
423
- try {
424
- value = decodeURIComponent(raw);
425
- } catch {
426
- value = raw;
427
- }
428
- return {
429
- name,
430
- value
431
- };
432
- }
433
- }
434
- }
435
- has(name) {
436
- return this.get(name) !== void 0;
437
- }
438
- getAll() {
439
- const entries = [];
440
- for (const header of this._headers.getSetCookie()) {
411
+ for (const header of headers.getSetCookie()) {
441
412
  const eq = header.indexOf("=");
442
413
  if (eq === -1) continue;
443
414
  const cookieName = header.slice(0, eq);
@@ -449,43 +420,95 @@ var ResponseCookies = class {
449
420
  } catch {
450
421
  value = raw;
451
422
  }
452
- entries.push({
453
- name: cookieName,
454
- value
423
+ this._parsed.set(cookieName, {
424
+ serialized: header,
425
+ entry: {
426
+ name: cookieName,
427
+ value
428
+ }
455
429
  });
456
430
  }
457
- return entries;
458
431
  }
459
- delete(name) {
460
- this.set(name, "", {
461
- maxAge: 0,
462
- path: "/"
432
+ set(...args) {
433
+ const [name, value, opts] = parseCookieSetArgs(args);
434
+ validateCookieName(name);
435
+ const parts = [`${name}=${encodeURIComponent(value)}`];
436
+ const path = opts?.path ?? "/";
437
+ validateCookieAttributeValue(path, "Path");
438
+ parts.push(`Path=${path}`);
439
+ if (opts?.domain) {
440
+ validateCookieAttributeValue(opts.domain, "Domain");
441
+ parts.push(`Domain=${opts.domain}`);
442
+ }
443
+ if (opts?.maxAge !== void 0) parts.push(`Max-Age=${opts.maxAge}`);
444
+ if (opts?.expires) parts.push(`Expires=${opts.expires.toUTCString()}`);
445
+ if (opts?.httpOnly) parts.push("HttpOnly");
446
+ if (opts?.secure) parts.push("Secure");
447
+ if (opts?.sameSite) parts.push(`SameSite=${opts.sameSite}`);
448
+ this._parsed.set(name, {
449
+ serialized: parts.join("; "),
450
+ entry: {
451
+ name,
452
+ value
453
+ }
463
454
  });
455
+ this._syncHeaders();
464
456
  return this;
465
457
  }
458
+ get(...args) {
459
+ const key = typeof args[0] === "string" ? args[0] : args[0].name;
460
+ return this._parsed.get(key)?.entry;
461
+ }
462
+ has(name) {
463
+ return this._parsed.has(name);
464
+ }
465
+ getAll(...args) {
466
+ const all = [...this._parsed.values()].map((v) => v.entry);
467
+ if (args.length === 0) return all;
468
+ const key = typeof args[0] === "string" ? args[0] : args[0].name;
469
+ return all.filter((c) => c.name === key);
470
+ }
471
+ delete(...args) {
472
+ const [name, opts] = typeof args[0] === "string" ? [args[0], void 0] : [args[0].name, args[0]];
473
+ return this.set({
474
+ name,
475
+ value: "",
476
+ expires: /* @__PURE__ */ new Date(0),
477
+ path: opts?.path,
478
+ domain: opts?.domain,
479
+ httpOnly: opts?.httpOnly,
480
+ secure: opts?.secure,
481
+ sameSite: opts?.sameSite
482
+ });
483
+ }
466
484
  [Symbol.iterator]() {
467
- const entries = [];
468
- for (const header of this._headers.getSetCookie()) {
469
- const eq = header.indexOf("=");
470
- if (eq === -1) continue;
471
- const cookieName = header.slice(0, eq);
472
- const semi = header.indexOf(";", eq);
473
- const raw = header.slice(eq + 1, semi === -1 ? void 0 : semi);
474
- let value;
475
- try {
476
- value = decodeURIComponent(raw);
477
- } catch {
478
- value = raw;
479
- }
480
- entries.push([cookieName, {
481
- name: cookieName,
482
- value
483
- }]);
484
- }
485
- return entries[Symbol.iterator]();
485
+ return [...this._parsed.values()].map((v) => [v.entry.name, v.entry])[Symbol.iterator]();
486
+ }
487
+ /** Delete all Set-Cookie headers and re-append from the internal map. */
488
+ _syncHeaders() {
489
+ this._headers.delete("Set-Cookie");
490
+ for (const { serialized } of this._parsed.values()) this._headers.append("Set-Cookie", serialized);
486
491
  }
487
492
  };
488
493
  /**
494
+ * Parse the overloaded arguments for ResponseCookies.set():
495
+ * - (name, value, options?) — positional form
496
+ * - ({ name, value, ...options }) — object form
497
+ */
498
+ function parseCookieSetArgs(args) {
499
+ if (typeof args[0] === "string") return [
500
+ args[0],
501
+ args[1],
502
+ args[2]
503
+ ];
504
+ const { name, value, ...opts } = args[0];
505
+ return [
506
+ name,
507
+ value,
508
+ opts
509
+ ];
510
+ }
511
+ /**
489
512
  * Minimal NextFetchEvent — extends FetchEvent where available,
490
513
  * otherwise provides the waitUntil pattern standalone.
491
514
  */
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../../src/shims/server.ts"],"sourcesContent":["/**\n * next/server shim\n *\n * Provides NextRequest, NextResponse, and related types that work with\n * standard Web APIs (Request/Response). This means they work on Node,\n * Cloudflare Workers, Deno, and any WinterCG-compatible runtime.\n *\n * This is a pragmatic subset — we implement the most commonly used APIs\n * rather than bug-for-bug parity with Next.js internals.\n */\n\nimport { encodeMiddlewareRequestHeaders } from \"../server/middleware-request-headers.js\";\nimport { parseCookieHeader } from \"./internal/parse-cookie-header.js\";\nimport { getRequestExecutionContext } from \"./request-context.js\";\n\n// ---------------------------------------------------------------------------\n// Inlined cache-scope guard for after()\n//\n// We cannot statically import throwIfInsideCacheScope from headers.ts here\n// because headers.ts contains the \"use cache\" directive string in its error\n// message, which causes Vite's use-cache transform to include it in the module\n// graph. If headers.ts is pulled in via static import from server.ts, the\n// transform fires on it in Pages Router fixtures that lack @vitejs/plugin-rsc.\n//\n// The connection() function in this file avoids the same problem by using\n// `await import(\"./headers.js\")` (dynamic import, async function). after()\n// must remain synchronous, so we inline the check using the same Symbol.for\n// keys that cache-runtime.ts and cache.ts register their ALS instances with.\n// ---------------------------------------------------------------------------\n\nconst _USE_CACHE_ALS_KEY = Symbol.for(\"vinext.cacheRuntime.contextAls\");\nconst _UNSTABLE_CACHE_ALS_KEY = Symbol.for(\"vinext.unstableCache.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\n\nfunction _throwIfInsideCacheScope(apiName: string): void {\n const cacheAls = _g[_USE_CACHE_ALS_KEY] as { getStore(): unknown } | undefined;\n if (cacheAls?.getStore() != null) {\n throw new Error(\n `\\`${apiName}\\` cannot be called inside \"use cache\". ` +\n `If you need this data inside a cached function, call \\`${apiName}\\` ` +\n \"outside and pass the required data as an argument.\",\n );\n }\n const unstableAls = _g[_UNSTABLE_CACHE_ALS_KEY] as { getStore(): unknown } | undefined;\n if (unstableAls?.getStore() === true) {\n throw new Error(\n `\\`${apiName}\\` cannot be called inside a function cached with \\`unstable_cache()\\`. ` +\n `If you need this data inside a cached function, call \\`${apiName}\\` ` +\n \"outside and pass the required data as an argument.\",\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextRequest\n// ---------------------------------------------------------------------------\n\nexport class NextRequest extends Request {\n private _nextUrl: NextURL;\n private _cookies: RequestCookies;\n\n constructor(\n input: URL | RequestInfo,\n init?: RequestInit & {\n nextConfig?: {\n basePath?: string;\n i18n?: { locales: string[]; defaultLocale: string };\n };\n },\n ) {\n // Strip nextConfig before passing to super() — it's vinext-internal,\n // not a valid RequestInit property.\n const { nextConfig: _nextConfig, ...requestInit } = init ?? {};\n // Handle the case where input is a Request object - we need to extract URL and init\n // to avoid Node.js undici issues with passing Request objects directly to super()\n if (input instanceof Request) {\n const req = input;\n super(req.url, {\n method: req.method,\n headers: req.headers,\n body: req.body,\n // @ts-expect-error - duplex is not in RequestInit type but needed for streams\n duplex: req.body ? \"half\" : undefined,\n ...requestInit,\n });\n } else {\n super(input, requestInit);\n }\n const url =\n typeof input === \"string\"\n ? new URL(input, \"http://localhost\")\n : input instanceof URL\n ? input\n : new URL(input.url, \"http://localhost\");\n const urlConfig: NextURLConfig | undefined = _nextConfig\n ? { basePath: _nextConfig.basePath, nextConfig: { i18n: _nextConfig.i18n } }\n : undefined;\n this._nextUrl = new NextURL(url, undefined, urlConfig);\n this._cookies = new RequestCookies(this.headers);\n }\n\n get nextUrl(): NextURL {\n return this._nextUrl;\n }\n\n get cookies(): RequestCookies {\n return this._cookies;\n }\n\n /**\n * Client IP address. Prefers Cloudflare's trusted CF-Connecting-IP header\n * over the spoofable X-Forwarded-For. Returns undefined if unavailable.\n */\n get ip(): string | undefined {\n return (\n this.headers.get(\"cf-connecting-ip\") ??\n this.headers.get(\"x-real-ip\") ??\n this.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ??\n undefined\n );\n }\n\n /**\n * Geolocation data. Platform-dependent (e.g., Cloudflare, Vercel).\n * Returns undefined if not available.\n */\n get geo():\n | { city?: string; country?: string; region?: string; latitude?: string; longitude?: string }\n | undefined {\n // Check Cloudflare-style headers, Vercel-style headers\n const country =\n this.headers.get(\"cf-ipcountry\") ?? this.headers.get(\"x-vercel-ip-country\") ?? undefined;\n if (!country) return undefined;\n return {\n country,\n city: this.headers.get(\"cf-ipcity\") ?? this.headers.get(\"x-vercel-ip-city\") ?? undefined,\n region:\n this.headers.get(\"cf-region\") ??\n this.headers.get(\"x-vercel-ip-country-region\") ??\n undefined,\n latitude:\n this.headers.get(\"cf-iplatitude\") ?? this.headers.get(\"x-vercel-ip-latitude\") ?? undefined,\n longitude:\n this.headers.get(\"cf-iplongitude\") ??\n this.headers.get(\"x-vercel-ip-longitude\") ??\n undefined,\n };\n }\n\n /**\n * The build ID of the Next.js application.\n * Delegates to `nextUrl.buildId` to match Next.js API surface.\n * Can be used in middleware to detect deployment skew between client and server.\n */\n get buildId(): string | undefined {\n return this._nextUrl.buildId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextResponse\n// ---------------------------------------------------------------------------\n\nexport class NextResponse<_Body = unknown> extends Response {\n private _cookies: ResponseCookies;\n\n constructor(body?: BodyInit | null, init?: ResponseInit) {\n super(body, init);\n this._cookies = new ResponseCookies(this.headers);\n }\n\n get cookies(): ResponseCookies {\n return this._cookies;\n }\n\n /**\n * Create a JSON response.\n */\n static json<JsonBody>(body: JsonBody, init?: ResponseInit): NextResponse<JsonBody> {\n const headers = new Headers(init?.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n return new NextResponse(JSON.stringify(body), {\n ...init,\n headers,\n }) as NextResponse<JsonBody>;\n }\n\n /**\n * Create a redirect response.\n */\n static redirect(url: string | URL, init?: number | ResponseInit): NextResponse {\n const status = typeof init === \"number\" ? init : (init?.status ?? 307);\n const destination = typeof url === \"string\" ? url : url.toString();\n const headers = new Headers(typeof init === \"object\" ? init?.headers : undefined);\n headers.set(\"Location\", destination);\n return new NextResponse(null, { status, headers });\n }\n\n /**\n * Create a rewrite response (middleware pattern).\n * Sets the x-middleware-rewrite header.\n */\n static rewrite(destination: string | URL, init?: MiddlewareResponseInit): NextResponse {\n const url = typeof destination === \"string\" ? destination : destination.toString();\n const headers = new Headers(init?.headers);\n headers.set(\"x-middleware-rewrite\", url);\n if (init?.request?.headers) {\n encodeMiddlewareRequestHeaders(headers, init.request.headers);\n }\n return new NextResponse(null, { ...init, headers });\n }\n\n /**\n * Continue to the next handler (middleware pattern).\n * Sets the x-middleware-next header.\n */\n static next(init?: MiddlewareResponseInit): NextResponse {\n const headers = new Headers(init?.headers);\n headers.set(\"x-middleware-next\", \"1\");\n if (init?.request?.headers) {\n encodeMiddlewareRequestHeaders(headers, init.request.headers);\n }\n return new NextResponse(null, { ...init, headers });\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextURL — lightweight URL wrapper with pathname helpers\n// ---------------------------------------------------------------------------\n\nexport type NextURLConfig = {\n basePath?: string;\n nextConfig?: {\n i18n?: {\n locales: string[];\n defaultLocale: string;\n };\n };\n};\n\nexport class NextURL {\n /** Internal URL stores the pathname WITHOUT basePath or locale prefix. */\n private _url: URL;\n private _basePath: string;\n private _locale: string | undefined;\n private _defaultLocale: string | undefined;\n private _locales: string[] | undefined;\n\n constructor(input: string | URL, base?: string | URL, config?: NextURLConfig) {\n this._url = new URL(input.toString(), base);\n this._basePath = config?.basePath ?? \"\";\n this._stripBasePath();\n const i18n = config?.nextConfig?.i18n;\n if (i18n) {\n this._locales = [...i18n.locales];\n this._defaultLocale = i18n.defaultLocale;\n this._analyzeLocale(this._locales);\n }\n }\n\n /** Strip basePath prefix from the internal pathname. */\n private _stripBasePath(): void {\n if (!this._basePath) return;\n const { pathname } = this._url;\n if (pathname === this._basePath || pathname.startsWith(this._basePath + \"/\")) {\n this._url.pathname = pathname.slice(this._basePath.length) || \"/\";\n }\n }\n\n /** Extract locale from pathname, stripping it from the internal URL. */\n private _analyzeLocale(locales: string[]): void {\n const segments = this._url.pathname.split(\"/\");\n const candidate = segments[1]?.toLowerCase();\n const match = locales.find((l) => l.toLowerCase() === candidate);\n if (match) {\n this._locale = match;\n this._url.pathname = \"/\" + segments.slice(2).join(\"/\");\n } else {\n this._locale = this._defaultLocale;\n }\n }\n\n /**\n * Reconstruct the full pathname with basePath + locale prefix.\n * Mirrors Next.js's internal formatPathname().\n */\n private _formatPathname(): string {\n // Build prefix: basePath + locale (skip defaultLocale — Next.js omits it)\n let prefix = this._basePath;\n if (this._locale && this._locale !== this._defaultLocale) {\n prefix += \"/\" + this._locale;\n }\n if (!prefix) return this._url.pathname;\n const inner = this._url.pathname;\n return inner === \"/\" ? prefix : prefix + inner;\n }\n\n get href(): string {\n const formatted = this._formatPathname();\n if (formatted === this._url.pathname) return this._url.href;\n // Replace pathname in href via string slicing — avoids URL allocation.\n // URL.href is always <origin+auth><pathname><search><hash>.\n const { href, pathname, search, hash } = this._url;\n const baseEnd = href.length - pathname.length - search.length - hash.length;\n return href.slice(0, baseEnd) + formatted + search + hash;\n }\n set href(value: string) {\n this._url.href = value;\n this._stripBasePath();\n if (this._locales) this._analyzeLocale(this._locales);\n }\n\n get origin(): string {\n return this._url.origin;\n }\n\n get protocol(): string {\n return this._url.protocol;\n }\n set protocol(value: string) {\n this._url.protocol = value;\n }\n\n get username(): string {\n return this._url.username;\n }\n set username(value: string) {\n this._url.username = value;\n }\n\n get password(): string {\n return this._url.password;\n }\n set password(value: string) {\n this._url.password = value;\n }\n\n get host(): string {\n return this._url.host;\n }\n set host(value: string) {\n this._url.host = value;\n }\n\n get hostname(): string {\n return this._url.hostname;\n }\n set hostname(value: string) {\n this._url.hostname = value;\n }\n\n get port(): string {\n return this._url.port;\n }\n set port(value: string) {\n this._url.port = value;\n }\n\n /** Returns the pathname WITHOUT basePath or locale prefix. */\n get pathname(): string {\n return this._url.pathname;\n }\n set pathname(value: string) {\n this._url.pathname = value;\n }\n\n get search(): string {\n return this._url.search;\n }\n set search(value: string) {\n this._url.search = value;\n }\n\n get searchParams(): URLSearchParams {\n return this._url.searchParams;\n }\n\n get hash(): string {\n return this._url.hash;\n }\n set hash(value: string) {\n this._url.hash = value;\n }\n\n get basePath(): string {\n return this._basePath;\n }\n set basePath(value: string) {\n this._basePath = value === \"\" ? \"\" : value.startsWith(\"/\") ? value : \"/\" + value;\n }\n\n get locale(): string {\n return this._locale ?? \"\";\n }\n set locale(value: string | undefined) {\n if (this._locales) {\n if (!value) {\n this._locale = this._defaultLocale;\n return;\n }\n if (!this._locales.includes(value)) {\n throw new TypeError(\n `The locale \"${value}\" is not in the configured locales: ${this._locales.join(\", \")}`,\n );\n }\n }\n this._locale = this._locales ? value : this._locale;\n }\n\n get defaultLocale(): string | undefined {\n return this._defaultLocale;\n }\n\n get locales(): string[] | undefined {\n return this._locales ? [...this._locales] : undefined;\n }\n\n clone(): NextURL {\n const config: NextURLConfig = {\n basePath: this._basePath,\n nextConfig: this._locales\n ? { i18n: { locales: [...this._locales], defaultLocale: this._defaultLocale! } }\n : undefined,\n };\n // Pass the full href (with locale/basePath re-added) so the constructor\n // can re-analyze and extract locale correctly.\n return new NextURL(this.href, undefined, config);\n }\n\n toString(): string {\n return this.href;\n }\n\n /**\n * The build ID of the Next.js application.\n * Set from `generateBuildId` in next.config.js, or a random UUID if not configured.\n * Can be used in middleware to detect deployment skew between client and server.\n * Matches the Next.js API: `request.nextUrl.buildId`.\n */\n get buildId(): string | undefined {\n return process.env.__VINEXT_BUILD_ID ?? undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cookie helpers (minimal implementations)\n// ---------------------------------------------------------------------------\n\ntype CookieEntry = {\n name: string;\n value: string;\n};\n\nexport class RequestCookies {\n private _headers: Headers;\n private _parsed: Map<string, string>;\n\n constructor(headers: Headers) {\n this._headers = headers;\n this._parsed = parseCookieHeader(headers.get(\"cookie\") ?? \"\");\n }\n\n get(name: string): CookieEntry | undefined {\n const value = this._parsed.get(name);\n return value !== undefined ? { name, value } : undefined;\n }\n\n getAll(nameOrOptions?: string | CookieEntry): CookieEntry[] {\n const name = typeof nameOrOptions === \"string\" ? nameOrOptions : nameOrOptions?.name;\n return [...this._parsed.entries()]\n .filter(([cookieName]) => name === undefined || cookieName === name)\n .map(([cookieName, value]) => ({ name: cookieName, value }));\n }\n\n has(name: string): boolean {\n return this._parsed.has(name);\n }\n\n set(nameOrOptions: string | CookieEntry, value?: string): this {\n let cookieName: string;\n let cookieValue: string;\n if (typeof nameOrOptions === \"string\") {\n cookieName = nameOrOptions;\n cookieValue = value ?? \"\";\n } else {\n cookieName = nameOrOptions.name;\n cookieValue = nameOrOptions.value;\n }\n this._parsed.set(cookieName, cookieValue);\n this._syncHeader();\n return this;\n }\n\n delete(names: string | string[]): boolean | boolean[] {\n if (Array.isArray(names)) {\n const results = names.map((name) => this._parsed.delete(name));\n this._syncHeader();\n return results;\n }\n const result = this._parsed.delete(names);\n this._syncHeader();\n return result;\n }\n\n clear(): this {\n this._parsed.clear();\n this._syncHeader();\n return this;\n }\n\n get size(): number {\n return this._parsed.size;\n }\n\n toString(): string {\n return this._serialize();\n }\n\n private _serialize(): string {\n return [...this._parsed.entries()].map(([n, v]) => `${n}=${encodeURIComponent(v)}`).join(\"; \");\n }\n\n private _syncHeader(): void {\n if (this._parsed.size === 0) {\n this._headers.delete(\"cookie\");\n } else {\n this._headers.set(\"cookie\", this._serialize());\n }\n }\n\n [Symbol.iterator](): IterableIterator<[string, CookieEntry]> {\n const entries = this.getAll().map((c) => [c.name, c] as [string, CookieEntry]);\n return entries[Symbol.iterator]();\n }\n}\n\n/**\n * RFC 6265 §4.1.1: cookie-name is a token (RFC 2616 §2.2).\n * Allowed: any visible ASCII (0x21-0x7E) except separators: ()<>@,;:\\\"/[]?={}\n */\nconst VALID_COOKIE_NAME_RE =\n /^[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2E\\x30-\\x39\\x41-\\x5A\\x5E-\\x7A\\x7C\\x7E]+$/;\n\nfunction validateCookieName(name: string): void {\n if (!name || !VALID_COOKIE_NAME_RE.test(name)) {\n throw new Error(`Invalid cookie name: ${JSON.stringify(name)}`);\n }\n}\n\nfunction validateCookieAttributeValue(value: string, attributeName: string): void {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f || value[i] === \";\") {\n throw new Error(`Invalid cookie ${attributeName} value: ${JSON.stringify(value)}`);\n }\n }\n}\n\nexport class ResponseCookies {\n private _headers: Headers;\n\n constructor(headers: Headers) {\n this._headers = headers;\n }\n\n set(name: string, value: string, options?: CookieOptions): this {\n validateCookieName(name);\n const parts = [`${name}=${encodeURIComponent(value)}`];\n if (options?.path) {\n validateCookieAttributeValue(options.path, \"Path\");\n parts.push(`Path=${options.path}`);\n }\n if (options?.domain) {\n validateCookieAttributeValue(options.domain, \"Domain\");\n parts.push(`Domain=${options.domain}`);\n }\n if (options?.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options?.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n if (options?.httpOnly) parts.push(\"HttpOnly\");\n if (options?.secure) parts.push(\"Secure\");\n if (options?.sameSite) parts.push(`SameSite=${options.sameSite}`);\n this._headers.append(\"Set-Cookie\", parts.join(\"; \"));\n return this;\n }\n\n get(name: string): CookieEntry | undefined {\n for (const header of this._headers.getSetCookie()) {\n const eq = header.indexOf(\"=\");\n if (eq === -1) continue;\n const cookieName = header.slice(0, eq);\n if (cookieName === name) {\n const semi = header.indexOf(\";\", eq);\n const raw = header.slice(eq + 1, semi === -1 ? undefined : semi);\n let value: string;\n try {\n value = decodeURIComponent(raw);\n } catch {\n value = raw;\n }\n return { name, value };\n }\n }\n return undefined;\n }\n\n has(name: string): boolean {\n return this.get(name) !== undefined;\n }\n\n getAll(): CookieEntry[] {\n const entries: CookieEntry[] = [];\n for (const header of this._headers.getSetCookie()) {\n const eq = header.indexOf(\"=\");\n if (eq === -1) continue;\n const cookieName = header.slice(0, eq);\n const semi = header.indexOf(\";\", eq);\n const raw = header.slice(eq + 1, semi === -1 ? undefined : semi);\n let value: string;\n try {\n value = decodeURIComponent(raw);\n } catch {\n value = raw;\n }\n entries.push({ name: cookieName, value });\n }\n return entries;\n }\n\n delete(name: string): this {\n this.set(name, \"\", { maxAge: 0, path: \"/\" });\n return this;\n }\n\n [Symbol.iterator](): IterableIterator<[string, CookieEntry]> {\n const entries: [string, CookieEntry][] = [];\n for (const header of this._headers.getSetCookie()) {\n const eq = header.indexOf(\"=\");\n if (eq === -1) continue;\n const cookieName = header.slice(0, eq);\n const semi = header.indexOf(\";\", eq);\n const raw = header.slice(eq + 1, semi === -1 ? undefined : semi);\n let value: string;\n try {\n value = decodeURIComponent(raw);\n } catch {\n value = raw;\n }\n entries.push([cookieName, { name: cookieName, value }]);\n }\n return entries[Symbol.iterator]();\n }\n}\n\ntype CookieOptions = {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n};\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type MiddlewareResponseInit = {\n request?: {\n headers?: Headers;\n };\n} & ResponseInit;\n\nexport type NextMiddlewareResult = NextResponse | Response | null | undefined | void;\n\nexport type NextMiddleware = (\n request: NextRequest,\n event: NextFetchEvent,\n) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\n\n/**\n * Minimal NextFetchEvent — extends FetchEvent where available,\n * otherwise provides the waitUntil pattern standalone.\n */\nexport class NextFetchEvent {\n sourcePage: string;\n private _waitUntilPromises: Promise<unknown>[] = [];\n\n constructor(params: { page: string }) {\n this.sourcePage = params.page;\n }\n\n waitUntil(promise: Promise<unknown>): void {\n this._waitUntilPromises.push(promise);\n }\n\n get waitUntilPromises(): Promise<unknown>[] {\n return this._waitUntilPromises;\n }\n\n /** Drain all waitUntil promises. Returns a single promise that settles when all are done. */\n drainWaitUntil(): Promise<PromiseSettledResult<unknown>[]> {\n return Promise.allSettled(this._waitUntilPromises);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility exports\n// ---------------------------------------------------------------------------\n\n/**\n * Parse user agent string. Minimal implementation — for full UA parsing,\n * apps should use a dedicated library like `ua-parser-js`.\n */\nexport function userAgentFromString(ua: string | undefined): UserAgent {\n const input = ua ?? \"\";\n return {\n isBot: /bot|crawler|spider|crawling/i.test(input),\n ua: input,\n browser: {},\n device: {},\n engine: {},\n os: {},\n cpu: {},\n };\n}\n\nexport function userAgent({ headers }: { headers: Headers }): UserAgent {\n return userAgentFromString(headers.get(\"user-agent\") ?? undefined);\n}\n\nexport type UserAgent = {\n isBot: boolean;\n ua: string;\n browser: { name?: string; version?: string; major?: string };\n device: { model?: string; type?: string; vendor?: string };\n engine: { name?: string; version?: string };\n os: { name?: string; version?: string };\n cpu: { architecture?: string };\n};\n\n/**\n * after() — schedule work after the response is sent.\n *\n * Uses the platform's `waitUntil` (via the per-request ExecutionContext) when\n * available so the task survives past the response on Cloudflare Workers.\n * Falls back to a fire-and-forget microtask on runtimes without an execution\n * context (e.g. Node.js dev server).\n *\n * Throws when called inside a cached scope — request-specific\n * side-effects must not leak into cached results.\n */\nexport function after<T>(task: Promise<T> | (() => T | Promise<T>)): void {\n _throwIfInsideCacheScope(\"after()\");\n\n const promise = typeof task === \"function\" ? Promise.resolve().then(task) : task;\n // NOTE: vinext runs function tasks concurrently with response streaming (next microtask),\n // whereas Next.js queues them to run strictly after the response is sent via onClose.\n // This is a known simplification — function tasks here are not guaranteed to run\n // after the response completes, only after the current synchronous execution.\n //\n // `.catch()` is attached synchronously in the same tick as `promise` is created, so\n // there is no window where a pre-rejected `task` promise could trigger an\n // `unhandledrejection` event before the handler is in place.\n const guarded = promise.catch((err) => {\n console.error(\"[vinext] after() task failed:\", err);\n });\n\n // TODO: Next.js throws when after() is called outside a request context or when\n // waitUntil is unavailable, preventing silent task loss. vinext falls back to\n // fire-and-forget here, which is correct for the Node.js dev server (where\n // getRequestExecutionContext() always returns null). On Workers, a misconfigured\n // entry that omits runWithExecutionContext would silently drop tasks — consider\n // a one-time console.warn on the fallback path, gated to production only (e.g.\n // `process.env.NODE_ENV === 'production'` or `typeof caches !== 'undefined'` for\n // a Workers runtime check) with a module-level `let _warned = false` guard so it\n // fires at most once and doesn't spam the dev-server console.\n getRequestExecutionContext()?.waitUntil(guarded);\n}\n\n/**\n * connection() — signals that the response requires a live connection\n * (not a static/cached response). Opts the page out of ISR caching\n * and sets Cache-Control: no-store on the response.\n */\nexport async function connection(): Promise<void> {\n const { markDynamicUsage, throwIfInsideCacheScope } = await import(\"./headers.js\");\n throwIfInsideCacheScope(\"connection()\");\n markDynamicUsage();\n}\n\n/**\n * URLPattern re-export — used in middleware for route matching.\n * Available natively in Node 20+, Cloudflare Workers, Deno.\n * Falls back to urlpattern-polyfill if the global is not available.\n */\nexport const URLPattern: typeof globalThis.URLPattern =\n globalThis.URLPattern ??\n (() => {\n throw new Error(\n \"URLPattern is not available in this runtime. \" +\n \"Install the `urlpattern-polyfill` package or upgrade to Node 20+.\",\n );\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.js","names":[],"sources":["../../src/shims/server.ts"],"sourcesContent":["/**\n * next/server shim\n *\n * Provides NextRequest, NextResponse, and related types that work with\n * standard Web APIs (Request/Response). This means they work on Node,\n * Cloudflare Workers, Deno, and any WinterCG-compatible runtime.\n *\n * This is a pragmatic subset — we implement the most commonly used APIs\n * rather than bug-for-bug parity with Next.js internals.\n */\n\nimport { encodeMiddlewareRequestHeaders } from \"../server/middleware-request-headers.js\";\nimport { parseCookieHeader } from \"./internal/parse-cookie-header.js\";\nimport { getRequestExecutionContext } from \"./request-context.js\";\n\n// ---------------------------------------------------------------------------\n// Inlined cache-scope guard for after()\n//\n// We cannot statically import throwIfInsideCacheScope from headers.ts here\n// because headers.ts contains the \"use cache\" directive string in its error\n// message, which causes Vite's use-cache transform to include it in the module\n// graph. If headers.ts is pulled in via static import from server.ts, the\n// transform fires on it in Pages Router fixtures that lack @vitejs/plugin-rsc.\n//\n// The connection() function in this file avoids the same problem by using\n// `await import(\"./headers.js\")` (dynamic import, async function). after()\n// must remain synchronous, so we inline the check using the same Symbol.for\n// keys that cache-runtime.ts and cache.ts register their ALS instances with.\n// ---------------------------------------------------------------------------\n\nconst _USE_CACHE_ALS_KEY = Symbol.for(\"vinext.cacheRuntime.contextAls\");\nconst _UNSTABLE_CACHE_ALS_KEY = Symbol.for(\"vinext.unstableCache.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\n\nfunction _throwIfInsideCacheScope(apiName: string): void {\n const cacheAls = _g[_USE_CACHE_ALS_KEY] as { getStore(): unknown } | undefined;\n if (cacheAls?.getStore() != null) {\n throw new Error(\n `\\`${apiName}\\` cannot be called inside \"use cache\". ` +\n `If you need this data inside a cached function, call \\`${apiName}\\` ` +\n \"outside and pass the required data as an argument.\",\n );\n }\n const unstableAls = _g[_UNSTABLE_CACHE_ALS_KEY] as { getStore(): unknown } | undefined;\n if (unstableAls?.getStore() === true) {\n throw new Error(\n `\\`${apiName}\\` cannot be called inside a function cached with \\`unstable_cache()\\`. ` +\n `If you need this data inside a cached function, call \\`${apiName}\\` ` +\n \"outside and pass the required data as an argument.\",\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextRequest\n// ---------------------------------------------------------------------------\n\nexport class NextRequest extends Request {\n private _nextUrl: NextURL;\n private _cookies: RequestCookies;\n\n constructor(\n input: URL | RequestInfo,\n init?: RequestInit & {\n nextConfig?: {\n basePath?: string;\n i18n?: { locales: string[]; defaultLocale: string };\n };\n },\n ) {\n // Strip nextConfig before passing to super() — it's vinext-internal,\n // not a valid RequestInit property.\n const { nextConfig: _nextConfig, ...requestInit } = init ?? {};\n // Handle the case where input is a Request object - we need to extract URL and init\n // to avoid Node.js undici issues with passing Request objects directly to super()\n if (input instanceof Request) {\n const req = input;\n super(req.url, {\n method: req.method,\n headers: req.headers,\n body: req.body,\n // @ts-expect-error - duplex is not in RequestInit type but needed for streams\n duplex: req.body ? \"half\" : undefined,\n ...requestInit,\n });\n } else {\n super(input, requestInit);\n }\n const url =\n typeof input === \"string\"\n ? new URL(input, \"http://localhost\")\n : input instanceof URL\n ? input\n : new URL(input.url, \"http://localhost\");\n const urlConfig: NextURLConfig | undefined = _nextConfig\n ? { basePath: _nextConfig.basePath, nextConfig: { i18n: _nextConfig.i18n } }\n : undefined;\n this._nextUrl = new NextURL(url, undefined, urlConfig);\n this._cookies = new RequestCookies(this.headers);\n }\n\n get nextUrl(): NextURL {\n return this._nextUrl;\n }\n\n get cookies(): RequestCookies {\n return this._cookies;\n }\n\n /**\n * Client IP address. Prefers Cloudflare's trusted CF-Connecting-IP header\n * over the spoofable X-Forwarded-For. Returns undefined if unavailable.\n */\n get ip(): string | undefined {\n return (\n this.headers.get(\"cf-connecting-ip\") ??\n this.headers.get(\"x-real-ip\") ??\n this.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ??\n undefined\n );\n }\n\n /**\n * Geolocation data. Platform-dependent (e.g., Cloudflare, Vercel).\n * Returns undefined if not available.\n */\n get geo():\n | { city?: string; country?: string; region?: string; latitude?: string; longitude?: string }\n | undefined {\n // Check Cloudflare-style headers, Vercel-style headers\n const country =\n this.headers.get(\"cf-ipcountry\") ?? this.headers.get(\"x-vercel-ip-country\") ?? undefined;\n if (!country) return undefined;\n return {\n country,\n city: this.headers.get(\"cf-ipcity\") ?? this.headers.get(\"x-vercel-ip-city\") ?? undefined,\n region:\n this.headers.get(\"cf-region\") ??\n this.headers.get(\"x-vercel-ip-country-region\") ??\n undefined,\n latitude:\n this.headers.get(\"cf-iplatitude\") ?? this.headers.get(\"x-vercel-ip-latitude\") ?? undefined,\n longitude:\n this.headers.get(\"cf-iplongitude\") ??\n this.headers.get(\"x-vercel-ip-longitude\") ??\n undefined,\n };\n }\n\n /**\n * The build ID of the Next.js application.\n * Delegates to `nextUrl.buildId` to match Next.js API surface.\n * Can be used in middleware to detect deployment skew between client and server.\n */\n get buildId(): string | undefined {\n return this._nextUrl.buildId;\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextResponse\n// ---------------------------------------------------------------------------\n\n/** Valid HTTP redirect status codes, matching Next.js's REDIRECTS set. */\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n\nexport class NextResponse<_Body = unknown> extends Response {\n private _cookies: ResponseCookies;\n\n constructor(body?: BodyInit | null, init?: ResponseInit) {\n super(body, init);\n this._cookies = new ResponseCookies(this.headers);\n }\n\n get cookies(): ResponseCookies {\n return this._cookies;\n }\n\n /**\n * Create a JSON response.\n */\n static json<JsonBody>(body: JsonBody, init?: ResponseInit): NextResponse<JsonBody> {\n const headers = new Headers(init?.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n return new NextResponse(JSON.stringify(body), {\n ...init,\n headers,\n }) as NextResponse<JsonBody>;\n }\n\n /**\n * Create a redirect response.\n */\n static redirect(url: string | URL, init?: number | ResponseInit): NextResponse {\n const status = typeof init === \"number\" ? init : (init?.status ?? 307);\n if (!REDIRECT_STATUSES.has(status)) {\n throw new RangeError(`Failed to execute \"redirect\" on \"response\": Invalid status code`);\n }\n const destination = typeof url === \"string\" ? url : url.toString();\n const headers = new Headers(typeof init === \"object\" ? init?.headers : undefined);\n headers.set(\"Location\", destination);\n return new NextResponse(null, { status, headers });\n }\n\n /**\n * Create a rewrite response (middleware pattern).\n * Sets the x-middleware-rewrite header.\n */\n static rewrite(destination: string | URL, init?: MiddlewareResponseInit): NextResponse {\n const url = typeof destination === \"string\" ? destination : destination.toString();\n const headers = new Headers(init?.headers);\n headers.set(\"x-middleware-rewrite\", url);\n if (init?.request?.headers) {\n encodeMiddlewareRequestHeaders(headers, init.request.headers);\n }\n return new NextResponse(null, { ...init, headers });\n }\n\n /**\n * Continue to the next handler (middleware pattern).\n * Sets the x-middleware-next header.\n */\n static next(init?: MiddlewareResponseInit): NextResponse {\n const headers = new Headers(init?.headers);\n headers.set(\"x-middleware-next\", \"1\");\n if (init?.request?.headers) {\n encodeMiddlewareRequestHeaders(headers, init.request.headers);\n }\n return new NextResponse(null, { ...init, headers });\n }\n}\n\n// ---------------------------------------------------------------------------\n// NextURL — lightweight URL wrapper with pathname helpers\n// ---------------------------------------------------------------------------\n\nexport type NextURLConfig = {\n basePath?: string;\n nextConfig?: {\n i18n?: {\n locales: string[];\n defaultLocale: string;\n };\n };\n};\n\nexport class NextURL {\n /** Internal URL stores the pathname WITHOUT basePath or locale prefix. */\n private _url: URL;\n private _basePath: string;\n private _locale: string | undefined;\n private _defaultLocale: string | undefined;\n private _locales: string[] | undefined;\n\n constructor(input: string | URL, base?: string | URL, config?: NextURLConfig) {\n this._url = new URL(input.toString(), base);\n this._basePath = config?.basePath ?? \"\";\n this._stripBasePath();\n const i18n = config?.nextConfig?.i18n;\n if (i18n) {\n this._locales = [...i18n.locales];\n this._defaultLocale = i18n.defaultLocale;\n this._analyzeLocale(this._locales);\n }\n }\n\n /** Strip basePath prefix from the internal pathname. */\n private _stripBasePath(): void {\n if (!this._basePath) return;\n const { pathname } = this._url;\n if (pathname === this._basePath || pathname.startsWith(this._basePath + \"/\")) {\n this._url.pathname = pathname.slice(this._basePath.length) || \"/\";\n }\n }\n\n /** Extract locale from pathname, stripping it from the internal URL. */\n private _analyzeLocale(locales: string[]): void {\n const segments = this._url.pathname.split(\"/\");\n const candidate = segments[1]?.toLowerCase();\n const match = locales.find((l) => l.toLowerCase() === candidate);\n if (match) {\n this._locale = match;\n this._url.pathname = \"/\" + segments.slice(2).join(\"/\");\n } else {\n this._locale = this._defaultLocale;\n }\n }\n\n /**\n * Reconstruct the full pathname with basePath + locale prefix.\n * Mirrors Next.js's internal formatPathname().\n */\n private _formatPathname(): string {\n // Build prefix: basePath + locale (skip defaultLocale — Next.js omits it)\n let prefix = this._basePath;\n if (this._locale && this._locale !== this._defaultLocale) {\n prefix += \"/\" + this._locale;\n }\n if (!prefix) return this._url.pathname;\n const inner = this._url.pathname;\n return inner === \"/\" ? prefix : prefix + inner;\n }\n\n get href(): string {\n const formatted = this._formatPathname();\n if (formatted === this._url.pathname) return this._url.href;\n // Replace pathname in href via string slicing — avoids URL allocation.\n // URL.href is always <origin+auth><pathname><search><hash>.\n const { href, pathname, search, hash } = this._url;\n const baseEnd = href.length - pathname.length - search.length - hash.length;\n return href.slice(0, baseEnd) + formatted + search + hash;\n }\n set href(value: string) {\n this._url.href = value;\n this._stripBasePath();\n if (this._locales) this._analyzeLocale(this._locales);\n }\n\n get origin(): string {\n return this._url.origin;\n }\n\n get protocol(): string {\n return this._url.protocol;\n }\n set protocol(value: string) {\n this._url.protocol = value;\n }\n\n get username(): string {\n return this._url.username;\n }\n set username(value: string) {\n this._url.username = value;\n }\n\n get password(): string {\n return this._url.password;\n }\n set password(value: string) {\n this._url.password = value;\n }\n\n get host(): string {\n return this._url.host;\n }\n set host(value: string) {\n this._url.host = value;\n }\n\n get hostname(): string {\n return this._url.hostname;\n }\n set hostname(value: string) {\n this._url.hostname = value;\n }\n\n get port(): string {\n return this._url.port;\n }\n set port(value: string) {\n this._url.port = value;\n }\n\n /** Returns the pathname WITHOUT basePath or locale prefix. */\n get pathname(): string {\n return this._url.pathname;\n }\n set pathname(value: string) {\n this._url.pathname = value;\n }\n\n get search(): string {\n return this._url.search;\n }\n set search(value: string) {\n this._url.search = value;\n }\n\n get searchParams(): URLSearchParams {\n return this._url.searchParams;\n }\n\n get hash(): string {\n return this._url.hash;\n }\n set hash(value: string) {\n this._url.hash = value;\n }\n\n get basePath(): string {\n return this._basePath;\n }\n set basePath(value: string) {\n this._basePath = value === \"\" ? \"\" : value.startsWith(\"/\") ? value : \"/\" + value;\n }\n\n get locale(): string {\n return this._locale ?? \"\";\n }\n set locale(value: string | undefined) {\n if (this._locales) {\n if (!value) {\n this._locale = this._defaultLocale;\n return;\n }\n if (!this._locales.includes(value)) {\n throw new TypeError(\n `The locale \"${value}\" is not in the configured locales: ${this._locales.join(\", \")}`,\n );\n }\n }\n this._locale = this._locales ? value : this._locale;\n }\n\n get defaultLocale(): string | undefined {\n return this._defaultLocale;\n }\n\n get locales(): string[] | undefined {\n return this._locales ? [...this._locales] : undefined;\n }\n\n clone(): NextURL {\n const config: NextURLConfig = {\n basePath: this._basePath,\n nextConfig: this._locales\n ? { i18n: { locales: [...this._locales], defaultLocale: this._defaultLocale! } }\n : undefined,\n };\n // Pass the full href (with locale/basePath re-added) so the constructor\n // can re-analyze and extract locale correctly.\n return new NextURL(this.href, undefined, config);\n }\n\n toString(): string {\n return this.href;\n }\n\n /**\n * The build ID of the Next.js application.\n * Set from `generateBuildId` in next.config.js, or a random UUID if not configured.\n * Can be used in middleware to detect deployment skew between client and server.\n * Matches the Next.js API: `request.nextUrl.buildId`.\n */\n get buildId(): string | undefined {\n return process.env.__VINEXT_BUILD_ID ?? undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cookie helpers (minimal implementations)\n// ---------------------------------------------------------------------------\n\ntype CookieEntry = {\n name: string;\n value: string;\n};\n\nexport class RequestCookies {\n private _headers: Headers;\n private _parsed: Map<string, string>;\n\n constructor(headers: Headers) {\n this._headers = headers;\n this._parsed = parseCookieHeader(headers.get(\"cookie\") ?? \"\");\n }\n\n get(name: string): CookieEntry | undefined {\n const value = this._parsed.get(name);\n return value !== undefined ? { name, value } : undefined;\n }\n\n getAll(nameOrOptions?: string | CookieEntry): CookieEntry[] {\n const name = typeof nameOrOptions === \"string\" ? nameOrOptions : nameOrOptions?.name;\n return [...this._parsed.entries()]\n .filter(([cookieName]) => name === undefined || cookieName === name)\n .map(([cookieName, value]) => ({ name: cookieName, value }));\n }\n\n has(name: string): boolean {\n return this._parsed.has(name);\n }\n\n set(nameOrOptions: string | CookieEntry, value?: string): this {\n let cookieName: string;\n let cookieValue: string;\n if (typeof nameOrOptions === \"string\") {\n cookieName = nameOrOptions;\n cookieValue = value ?? \"\";\n } else {\n cookieName = nameOrOptions.name;\n cookieValue = nameOrOptions.value;\n }\n validateCookieName(cookieName);\n this._parsed.set(cookieName, cookieValue);\n this._syncHeader();\n return this;\n }\n\n delete(names: string | string[]): boolean | boolean[] {\n if (Array.isArray(names)) {\n const results = names.map((name) => {\n validateCookieName(name);\n return this._parsed.delete(name);\n });\n this._syncHeader();\n return results;\n }\n validateCookieName(names);\n const result = this._parsed.delete(names);\n this._syncHeader();\n return result;\n }\n\n clear(): this {\n this._parsed.clear();\n this._syncHeader();\n return this;\n }\n\n get size(): number {\n return this._parsed.size;\n }\n\n toString(): string {\n return this._serialize();\n }\n\n private _serialize(): string {\n return [...this._parsed.entries()].map(([n, v]) => `${n}=${encodeURIComponent(v)}`).join(\"; \");\n }\n\n private _syncHeader(): void {\n if (this._parsed.size === 0) {\n this._headers.delete(\"cookie\");\n } else {\n this._headers.set(\"cookie\", this._serialize());\n }\n }\n\n [Symbol.iterator](): IterableIterator<[string, CookieEntry]> {\n const entries = this.getAll().map((c) => [c.name, c] as [string, CookieEntry]);\n return entries[Symbol.iterator]();\n }\n}\n\n/**\n * RFC 6265 §4.1.1: cookie-name is a token (RFC 2616 §2.2).\n * Allowed: any visible ASCII (0x21-0x7E) except separators: ()<>@,;:\\\"/[]?={}\n */\nconst VALID_COOKIE_NAME_RE =\n /^[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2E\\x30-\\x39\\x41-\\x5A\\x5E-\\x7A\\x7C\\x7E]+$/;\n\nfunction validateCookieName(name: string): void {\n if (!name || !VALID_COOKIE_NAME_RE.test(name)) {\n throw new Error(`Invalid cookie name: ${JSON.stringify(name)}`);\n }\n}\n\nfunction validateCookieAttributeValue(value: string, attributeName: string): void {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f || value[i] === \";\") {\n throw new Error(`Invalid cookie ${attributeName} value: ${JSON.stringify(value)}`);\n }\n }\n}\n\nexport class ResponseCookies {\n private _headers: Headers;\n /** Internal map keyed by cookie name — single source of truth. */\n private _parsed: Map<string, { serialized: string; entry: CookieEntry }> = new Map();\n\n constructor(headers: Headers) {\n this._headers = headers;\n\n // Hydrate internal map from any existing Set-Cookie headers\n for (const header of headers.getSetCookie()) {\n const eq = header.indexOf(\"=\");\n if (eq === -1) continue;\n const cookieName = header.slice(0, eq);\n const semi = header.indexOf(\";\", eq);\n const raw = header.slice(eq + 1, semi === -1 ? undefined : semi);\n let value: string;\n try {\n value = decodeURIComponent(raw);\n } catch {\n value = raw;\n }\n this._parsed.set(cookieName, { serialized: header, entry: { name: cookieName, value } });\n }\n }\n\n set(\n ...args:\n | [name: string, value: string, options?: CookieOptions]\n | [options: CookieOptions & { name: string; value: string }]\n ): this {\n const [name, value, opts] = parseCookieSetArgs(args);\n validateCookieName(name);\n\n const parts = [`${name}=${encodeURIComponent(value)}`];\n const path = opts?.path ?? \"/\";\n validateCookieAttributeValue(path, \"Path\");\n parts.push(`Path=${path}`);\n if (opts?.domain) {\n validateCookieAttributeValue(opts.domain, \"Domain\");\n parts.push(`Domain=${opts.domain}`);\n }\n if (opts?.maxAge !== undefined) parts.push(`Max-Age=${opts.maxAge}`);\n if (opts?.expires) parts.push(`Expires=${opts.expires.toUTCString()}`);\n if (opts?.httpOnly) parts.push(\"HttpOnly\");\n if (opts?.secure) parts.push(\"Secure\");\n if (opts?.sameSite) parts.push(`SameSite=${opts.sameSite}`);\n\n this._parsed.set(name, { serialized: parts.join(\"; \"), entry: { name, value } });\n this._syncHeaders();\n return this;\n }\n\n get(...args: [name: string] | [options: { name: string }]): CookieEntry | undefined {\n const key = typeof args[0] === \"string\" ? args[0] : args[0].name;\n return this._parsed.get(key)?.entry;\n }\n\n has(name: string): boolean {\n return this._parsed.has(name);\n }\n\n getAll(...args: [name: string] | [options: { name: string }] | []): CookieEntry[] {\n const all = [...this._parsed.values()].map((v) => v.entry);\n if (args.length === 0) return all;\n const key = typeof args[0] === \"string\" ? args[0] : args[0].name;\n return all.filter((c) => c.name === key);\n }\n\n delete(\n ...args:\n | [name: string]\n | [options: Omit<CookieOptions & { name: string }, \"maxAge\" | \"expires\">]\n ): this {\n const [name, opts] =\n typeof args[0] === \"string\" ? [args[0], undefined] : [args[0].name, args[0]];\n return this.set({\n name,\n value: \"\",\n expires: new Date(0),\n path: opts?.path,\n domain: opts?.domain,\n httpOnly: opts?.httpOnly,\n secure: opts?.secure,\n sameSite: opts?.sameSite,\n });\n }\n\n [Symbol.iterator](): IterableIterator<[string, CookieEntry]> {\n const entries: [string, CookieEntry][] = [...this._parsed.values()].map((v) => [\n v.entry.name,\n v.entry,\n ]);\n return entries[Symbol.iterator]();\n }\n\n /** Delete all Set-Cookie headers and re-append from the internal map. */\n private _syncHeaders(): void {\n this._headers.delete(\"Set-Cookie\");\n for (const { serialized } of this._parsed.values()) {\n this._headers.append(\"Set-Cookie\", serialized);\n }\n }\n}\n\ntype CookieOptions = {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n};\n\n/**\n * Parse the overloaded arguments for ResponseCookies.set():\n * - (name, value, options?) — positional form\n * - ({ name, value, ...options }) — object form\n */\nfunction parseCookieSetArgs(\n args:\n | [name: string, value: string, options?: CookieOptions]\n | [options: CookieOptions & { name: string; value: string }],\n): [string, string, CookieOptions | undefined] {\n if (typeof args[0] === \"string\") {\n return [args[0], args[1] as string, args[2] as CookieOptions | undefined];\n }\n const { name, value, ...opts } = args[0];\n return [name, value, opts as CookieOptions];\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type MiddlewareResponseInit = {\n request?: {\n headers?: Headers;\n };\n} & ResponseInit;\n\nexport type NextMiddlewareResult = NextResponse | Response | null | undefined | void;\n\nexport type NextMiddleware = (\n request: NextRequest,\n event: NextFetchEvent,\n) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\n\n/**\n * Minimal NextFetchEvent — extends FetchEvent where available,\n * otherwise provides the waitUntil pattern standalone.\n */\nexport class NextFetchEvent {\n sourcePage: string;\n private _waitUntilPromises: Promise<unknown>[] = [];\n\n constructor(params: { page: string }) {\n this.sourcePage = params.page;\n }\n\n waitUntil(promise: Promise<unknown>): void {\n this._waitUntilPromises.push(promise);\n }\n\n get waitUntilPromises(): Promise<unknown>[] {\n return this._waitUntilPromises;\n }\n\n /** Drain all waitUntil promises. Returns a single promise that settles when all are done. */\n drainWaitUntil(): Promise<PromiseSettledResult<unknown>[]> {\n return Promise.allSettled(this._waitUntilPromises);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility exports\n// ---------------------------------------------------------------------------\n\n/**\n * Parse user agent string. Minimal implementation — for full UA parsing,\n * apps should use a dedicated library like `ua-parser-js`.\n */\nexport function userAgentFromString(ua: string | undefined): UserAgent {\n const input = ua ?? \"\";\n return {\n isBot: /bot|crawler|spider|crawling/i.test(input),\n ua: input,\n browser: {},\n device: {},\n engine: {},\n os: {},\n cpu: {},\n };\n}\n\nexport function userAgent({ headers }: { headers: Headers }): UserAgent {\n return userAgentFromString(headers.get(\"user-agent\") ?? undefined);\n}\n\nexport type UserAgent = {\n isBot: boolean;\n ua: string;\n browser: { name?: string; version?: string; major?: string };\n device: { model?: string; type?: string; vendor?: string };\n engine: { name?: string; version?: string };\n os: { name?: string; version?: string };\n cpu: { architecture?: string };\n};\n\n/**\n * after() — schedule work after the response is sent.\n *\n * Uses the platform's `waitUntil` (via the per-request ExecutionContext) when\n * available so the task survives past the response on Cloudflare Workers.\n * Falls back to a fire-and-forget microtask on runtimes without an execution\n * context (e.g. Node.js dev server).\n *\n * Throws when called inside a cached scope — request-specific\n * side-effects must not leak into cached results.\n */\nexport function after<T>(task: Promise<T> | (() => T | Promise<T>)): void {\n _throwIfInsideCacheScope(\"after()\");\n\n const promise = typeof task === \"function\" ? Promise.resolve().then(task) : task;\n // NOTE: vinext runs function tasks concurrently with response streaming (next microtask),\n // whereas Next.js queues them to run strictly after the response is sent via onClose.\n // This is a known simplification — function tasks here are not guaranteed to run\n // after the response completes, only after the current synchronous execution.\n //\n // `.catch()` is attached synchronously in the same tick as `promise` is created, so\n // there is no window where a pre-rejected `task` promise could trigger an\n // `unhandledrejection` event before the handler is in place.\n const guarded = promise.catch((err) => {\n console.error(\"[vinext] after() task failed:\", err);\n });\n\n // TODO: Next.js throws when after() is called outside a request context or when\n // waitUntil is unavailable, preventing silent task loss. vinext falls back to\n // fire-and-forget here, which is correct for the Node.js dev server (where\n // getRequestExecutionContext() always returns null). On Workers, a misconfigured\n // entry that omits runWithExecutionContext would silently drop tasks — consider\n // a one-time console.warn on the fallback path, gated to production only (e.g.\n // `process.env.NODE_ENV === 'production'` or `typeof caches !== 'undefined'` for\n // a Workers runtime check) with a module-level `let _warned = false` guard so it\n // fires at most once and doesn't spam the dev-server console.\n getRequestExecutionContext()?.waitUntil(guarded);\n}\n\n/**\n * connection() — signals that the response requires a live connection\n * (not a static/cached response). Opts the page out of ISR caching\n * and sets Cache-Control: no-store on the response.\n */\nexport async function connection(): Promise<void> {\n const { markDynamicUsage, throwIfInsideCacheScope } = await import(\"./headers.js\");\n throwIfInsideCacheScope(\"connection()\");\n markDynamicUsage();\n}\n\n/**\n * URLPattern re-export — used in middleware for route matching.\n * Available natively in Node 20+, Cloudflare Workers, Deno.\n * Falls back to urlpattern-polyfill if the global is not available.\n */\nexport const URLPattern: typeof globalThis.URLPattern =\n globalThis.URLPattern ??\n (() => {\n throw new Error(\n \"URLPattern is not available in this runtime. \" +\n \"Install the `urlpattern-polyfill` package or upgrade to Node 20+.\",\n );\n });\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import * as React$1 from "react";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+
4
+ //#region src/shims/slot.d.ts
5
+ type Elements = Record<string, React$1.ReactNode | typeof UNMATCHED_SLOT>;
6
+ declare const UNMATCHED_SLOT: unique symbol;
7
+ declare const ElementsContext: React$1.Context<Promise<Elements>>;
8
+ declare const ChildrenContext: React$1.Context<React$1.ReactNode>;
9
+ declare const ParallelSlotsContext: React$1.Context<Readonly<Record<string, React$1.ReactNode>> | null>;
10
+ declare function mergeElementsPromise(prev: Promise<Elements>, next: Promise<Elements>): Promise<Elements>;
11
+ declare function Slot({
12
+ id,
13
+ children,
14
+ parallelSlots
15
+ }: {
16
+ id: string;
17
+ children?: React$1.ReactNode;
18
+ parallelSlots?: Readonly<Record<string, React$1.ReactNode>>;
19
+ }): react_jsx_runtime0.JSX.Element | null;
20
+ declare function Children(): React$1.ReactNode;
21
+ declare function ParallelSlot({
22
+ name
23
+ }: {
24
+ name: string;
25
+ }): string | number | bigint | boolean | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | Promise<string | number | bigint | boolean | React$1.ReactPortal | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined> | null;
26
+ //#endregion
27
+ export { Children, ChildrenContext, Elements, ElementsContext, ParallelSlot, ParallelSlotsContext, Slot, UNMATCHED_SLOT, mergeElementsPromise };
28
+ //# sourceMappingURL=slot.d.ts.map
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { notFound } from "./navigation.js";
3
+ import * as React$1 from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/shims/slot.tsx
6
+ const EMPTY_ELEMENTS_PROMISE = Promise.resolve(Object.freeze({}));
7
+ const mergeCache = /* @__PURE__ */ new WeakMap();
8
+ const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
9
+ const ElementsContext = React$1.createContext(EMPTY_ELEMENTS_PROMISE);
10
+ const ChildrenContext = React$1.createContext(null);
11
+ const ParallelSlotsContext = React$1.createContext(null);
12
+ function mergeElementsPromise(prev, next) {
13
+ let nextCache = mergeCache.get(prev);
14
+ if (!nextCache) {
15
+ nextCache = /* @__PURE__ */ new WeakMap();
16
+ mergeCache.set(prev, nextCache);
17
+ }
18
+ const cached = nextCache.get(next);
19
+ if (cached) return cached;
20
+ const merged = Promise.all([prev, next]).then(([prevElements, nextElements]) => ({
21
+ ...prevElements,
22
+ ...nextElements
23
+ }));
24
+ nextCache.set(next, merged);
25
+ return merged;
26
+ }
27
+ function Slot({ id, children, parallelSlots }) {
28
+ const elements = React$1.use(React$1.useContext(ElementsContext));
29
+ if (!Object.hasOwn(elements, id)) return null;
30
+ const element = elements[id];
31
+ if (element === UNMATCHED_SLOT) notFound();
32
+ return /* @__PURE__ */ jsx(ParallelSlotsContext.Provider, {
33
+ value: parallelSlots ?? null,
34
+ children: /* @__PURE__ */ jsx(ChildrenContext.Provider, {
35
+ value: children ?? null,
36
+ children: element
37
+ })
38
+ });
39
+ }
40
+ function Children() {
41
+ return React$1.useContext(ChildrenContext);
42
+ }
43
+ function ParallelSlot({ name }) {
44
+ return React$1.useContext(ParallelSlotsContext)?.[name] ?? null;
45
+ }
46
+ //#endregion
47
+ export { Children, ChildrenContext, ElementsContext, ParallelSlot, ParallelSlotsContext, Slot, UNMATCHED_SLOT, mergeElementsPromise };
48
+
49
+ //# sourceMappingURL=slot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot.js","names":["React"],"sources":["../../src/shims/slot.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { notFound } from \"./navigation.js\";\n\nexport type Elements = Record<string, React.ReactNode | typeof UNMATCHED_SLOT>;\n\n// Shared across requests — safe because the resolved value is frozen.\n// A Slot rendered outside an ElementsContext.Provider sees {} and returns null for all IDs.\nconst EMPTY_ELEMENTS_PROMISE = Promise.resolve<Elements>(Object.freeze({}));\n// Client-only optimisation: memoises merged promises by identity so React.use() sees a stable\n// reference across re-renders. During SSR each request creates fresh promises so the cache is\n// never hit, but the WeakMap entries are GC-eligible once the request's promises are collected.\nconst mergeCache = new WeakMap<Promise<Elements>, WeakMap<Promise<Elements>, Promise<Elements>>>();\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nexport const ElementsContext = React.createContext<Promise<Elements>>(EMPTY_ELEMENTS_PROMISE);\n\nexport const ChildrenContext = React.createContext<React.ReactNode>(null);\n\nexport const ParallelSlotsContext = React.createContext<Readonly<\n Record<string, React.ReactNode>\n> | null>(null);\n\nexport function mergeElementsPromise(\n prev: Promise<Elements>,\n next: Promise<Elements>,\n): Promise<Elements> {\n let nextCache = mergeCache.get(prev);\n if (!nextCache) {\n nextCache = new WeakMap();\n mergeCache.set(prev, nextCache);\n }\n\n const cached = nextCache.get(next);\n if (cached) {\n return cached;\n }\n\n // Cached permanently including rejections — intentional because these promises come from\n // createFromFetch() and a rejection means the navigation itself has failed.\n const merged = Promise.all([prev, next]).then(([prevElements, nextElements]) => ({\n ...prevElements,\n ...nextElements,\n }));\n nextCache.set(next, merged);\n return merged;\n}\n\nexport function Slot({\n id,\n children,\n parallelSlots,\n}: {\n id: string;\n children?: React.ReactNode;\n parallelSlots?: Readonly<Record<string, React.ReactNode>>;\n}) {\n const elements = React.use(React.useContext(ElementsContext));\n\n if (!Object.hasOwn(elements, id)) {\n return null;\n }\n\n const element = elements[id];\n if (element === UNMATCHED_SLOT) {\n notFound(); // throws — never reaches the JSX below\n }\n\n return (\n <ParallelSlotsContext.Provider value={parallelSlots ?? null}>\n <ChildrenContext.Provider value={children ?? null}>{element}</ChildrenContext.Provider>\n </ParallelSlotsContext.Provider>\n );\n}\n\nexport function Children() {\n return React.useContext(ChildrenContext);\n}\n\nexport function ParallelSlot({ name }: { name: string }) {\n const slots = React.useContext(ParallelSlotsContext);\n return slots?.[name] ?? null;\n}\n"],"mappings":";;;;;AASA,MAAM,yBAAyB,QAAQ,QAAkB,OAAO,OAAO,EAAE,CAAC,CAAC;AAI3E,MAAM,6BAAa,IAAI,SAA2E;AAElG,MAAa,iBAAiB,OAAO,IAAI,uBAAuB;AAEhE,MAAa,kBAAkBA,QAAM,cAAiC,uBAAuB;AAE7F,MAAa,kBAAkBA,QAAM,cAA+B,KAAK;AAEzE,MAAa,uBAAuBA,QAAM,cAEhC,KAAK;AAEf,SAAgB,qBACd,MACA,MACmB;CACnB,IAAI,YAAY,WAAW,IAAI,KAAK;AACpC,KAAI,CAAC,WAAW;AACd,8BAAY,IAAI,SAAS;AACzB,aAAW,IAAI,MAAM,UAAU;;CAGjC,MAAM,SAAS,UAAU,IAAI,KAAK;AAClC,KAAI,OACF,QAAO;CAKT,MAAM,SAAS,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,mBAAmB;EAC/E,GAAG;EACH,GAAG;EACJ,EAAE;AACH,WAAU,IAAI,MAAM,OAAO;AAC3B,QAAO;;AAGT,SAAgB,KAAK,EACnB,IACA,UACA,iBAKC;CACD,MAAM,WAAWA,QAAM,IAAIA,QAAM,WAAW,gBAAgB,CAAC;AAE7D,KAAI,CAAC,OAAO,OAAO,UAAU,GAAG,CAC9B,QAAO;CAGT,MAAM,UAAU,SAAS;AACzB,KAAI,YAAY,eACd,WAAU;AAGZ,QACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO,iBAAiB;YACrD,oBAAC,gBAAgB,UAAjB;GAA0B,OAAO,YAAY;aAAO;GAAmC,CAAA;EACzD,CAAA;;AAIpC,SAAgB,WAAW;AACzB,QAAOA,QAAM,WAAW,gBAAgB;;AAG1C,SAAgB,aAAa,EAAE,QAA0B;AAEvD,QADcA,QAAM,WAAW,qBAAqB,GACrC,SAAS"}
@@ -7,12 +7,33 @@
7
7
  */
8
8
  /**
9
9
  * Detect dangerous URI schemes that should never be navigated to.
10
- * Strips leading whitespace and zero-width characters before testing,
11
- * since browsers ignore these when interpreting the scheme.
10
+ *
11
+ * Adapted from Next.js's javascript URL detector:
12
+ * packages/next/src/client/lib/javascript-url.ts
13
+ * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/lib/javascript-url.ts
14
+ *
15
+ * URL parsing ignores leading C0 control characters / spaces, and treats
16
+ * embedded tab/newline characters in the scheme as insignificant. We mirror
17
+ * that behavior here so obfuscated values like `java\nscript:` and
18
+ * `\x00javascript:` are still blocked.
19
+ *
20
+ * Vinext intentionally extends this handling to `data:` and `vbscript:` too,
21
+ * since both are also dangerous navigation targets.
12
22
  */
13
- const DANGEROUS_SCHEME_RE = /^[\s\u200B\uFEFF]*(javascript|data|vbscript)\s*:/i;
23
+ const LEADING_IGNORED = "[\\u0000-\\u001F \\u200B\\uFEFF]*";
24
+ const SCHEME_IGNORED = "[\\r\\n\\t]*";
25
+ function buildDangerousSchemeRegex(scheme) {
26
+ const chars = scheme.split("").join(SCHEME_IGNORED);
27
+ return new RegExp(`^${LEADING_IGNORED}${chars}${SCHEME_IGNORED}:`, "i");
28
+ }
29
+ const DANGEROUS_SCHEME_RES = [
30
+ buildDangerousSchemeRegex("javascript"),
31
+ buildDangerousSchemeRegex("data"),
32
+ buildDangerousSchemeRegex("vbscript")
33
+ ];
14
34
  function isDangerousScheme(url) {
15
- return DANGEROUS_SCHEME_RE.test(url);
35
+ const str = "" + url;
36
+ return DANGEROUS_SCHEME_RES.some((re) => re.test(str));
16
37
  }
17
38
  //#endregion
18
39
  export { isDangerousScheme };
@@ -1 +1 @@
1
- {"version":3,"file":"url-safety.js","names":[],"sources":["../../src/shims/url-safety.ts"],"sourcesContent":["/**\n * Shared URL safety utilities for Link, Form, and navigation shims.\n *\n * Centralizes dangerous URI scheme detection so all components and\n * navigation functions use the same validation logic.\n */\n\n/**\n * Detect dangerous URI schemes that should never be navigated to.\n * Strips leading whitespace and zero-width characters before testing,\n * since browsers ignore these when interpreting the scheme.\n */\nconst DANGEROUS_SCHEME_RE = /^[\\s\\u200B\\uFEFF]*(javascript|data|vbscript)\\s*:/i;\n\nexport function isDangerousScheme(url: string): boolean {\n return DANGEROUS_SCHEME_RE.test(url);\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,sBAAsB;AAE5B,SAAgB,kBAAkB,KAAsB;AACtD,QAAO,oBAAoB,KAAK,IAAI"}
1
+ {"version":3,"file":"url-safety.js","names":[],"sources":["../../src/shims/url-safety.ts"],"sourcesContent":["/**\n * Shared URL safety utilities for Link, Form, and navigation shims.\n *\n * Centralizes dangerous URI scheme detection so all components and\n * navigation functions use the same validation logic.\n */\n\n/**\n * Detect dangerous URI schemes that should never be navigated to.\n *\n * Adapted from Next.js's javascript URL detector:\n * packages/next/src/client/lib/javascript-url.ts\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/lib/javascript-url.ts\n *\n * URL parsing ignores leading C0 control characters / spaces, and treats\n * embedded tab/newline characters in the scheme as insignificant. We mirror\n * that behavior here so obfuscated values like `java\\nscript:` and\n * `\\x00javascript:` are still blocked.\n *\n * Vinext intentionally extends this handling to `data:` and `vbscript:` too,\n * since both are also dangerous navigation targets.\n */\nconst LEADING_IGNORED = \"[\\\\u0000-\\\\u001F \\\\u200B\\\\uFEFF]*\";\nconst SCHEME_IGNORED = \"[\\\\r\\\\n\\\\t]*\";\n\nfunction buildDangerousSchemeRegex(scheme: string): RegExp {\n const chars = scheme.split(\"\").join(SCHEME_IGNORED);\n return new RegExp(`^${LEADING_IGNORED}${chars}${SCHEME_IGNORED}:`, \"i\");\n}\n\nconst DANGEROUS_SCHEME_RES = [\n buildDangerousSchemeRegex(\"javascript\"),\n buildDangerousSchemeRegex(\"data\"),\n buildDangerousSchemeRegex(\"vbscript\"),\n];\n\nexport function isDangerousScheme(url: string): boolean {\n const str = \"\" + (url as unknown as string);\n return DANGEROUS_SCHEME_RES.some((re) => re.test(str));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AAEvB,SAAS,0BAA0B,QAAwB;CACzD,MAAM,QAAQ,OAAO,MAAM,GAAG,CAAC,KAAK,eAAe;AACnD,QAAO,IAAI,OAAO,IAAI,kBAAkB,QAAQ,eAAe,IAAI,IAAI;;AAGzE,MAAM,uBAAuB;CAC3B,0BAA0B,aAAa;CACvC,0BAA0B,OAAO;CACjC,0BAA0B,WAAW;CACtC;AAED,SAAgB,kBAAkB,KAAsB;CACtD,MAAM,MAAM,KAAM;AAClB,QAAO,qBAAqB,MAAM,OAAO,GAAG,KAAK,IAAI,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -58,7 +58,6 @@
58
58
  "@unpic/react": "^1.0.2",
59
59
  "@vercel/og": "^0.8.6",
60
60
  "magic-string": "^0.30.21",
61
- "rsc-html-stream": "^0.0.7",
62
61
  "vite-plugin-commonjs": "^0.10.4",
63
62
  "vite-tsconfig-paths": "^6.1.1"
64
63
  },
@@ -67,18 +66,18 @@
67
66
  "@types/react": "^19.2.14",
68
67
  "@types/react-dom": "^19.2.3",
69
68
  "@vitejs/plugin-react": "^6.0.1",
70
- "@vitejs/plugin-rsc": "^0.5.21",
71
- "react-server-dom-webpack": "^19.2.4",
69
+ "@vitejs/plugin-rsc": "^0.5.23",
70
+ "react-server-dom-webpack": "^19.2.5",
72
71
  "vite": "npm:@voidzero-dev/vite-plus-core@0.1.12",
73
72
  "vite-plus": "0.1.12"
74
73
  },
75
74
  "peerDependencies": {
76
75
  "@mdx-js/rollup": "^3.0.0",
77
76
  "@vitejs/plugin-react": "^5.1.4 || ^6.0.0",
78
- "@vitejs/plugin-rsc": "^0.5.21",
79
- "react": ">=19.2.0",
80
- "react-dom": ">=19.2.0",
81
- "react-server-dom-webpack": "^19.2.4",
77
+ "@vitejs/plugin-rsc": "^0.5.23",
78
+ "react": "^19.2.5",
79
+ "react-dom": "^19.2.5",
80
+ "react-server-dom-webpack": "^19.2.5",
82
81
  "vite": "^7.0.0 || ^8.0.0"
83
82
  },
84
83
  "peerDependenciesMeta": {