vinext 0.0.54 → 0.0.55

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 (135) hide show
  1. package/README.md +1 -0
  2. package/dist/check.js +15 -3
  3. package/dist/check.js.map +1 -1
  4. package/dist/client/navigation-runtime.d.ts +1 -0
  5. package/dist/client/navigation-runtime.js +1 -1
  6. package/dist/client/navigation-runtime.js.map +1 -1
  7. package/dist/config/next-config.d.ts +14 -1
  8. package/dist/config/next-config.js +24 -4
  9. package/dist/config/next-config.js.map +1 -1
  10. package/dist/config/tsconfig-paths.d.ts +12 -3
  11. package/dist/config/tsconfig-paths.js +55 -24
  12. package/dist/config/tsconfig-paths.js.map +1 -1
  13. package/dist/entries/app-rsc-entry.d.ts +2 -1
  14. package/dist/entries/app-rsc-entry.js +12 -0
  15. package/dist/entries/app-rsc-entry.js.map +1 -1
  16. package/dist/entries/app-rsc-manifest.js +22 -5
  17. package/dist/entries/app-rsc-manifest.js.map +1 -1
  18. package/dist/entries/pages-server-entry.js +41 -4
  19. package/dist/entries/pages-server-entry.js.map +1 -1
  20. package/dist/index.js +81 -39
  21. package/dist/index.js.map +1 -1
  22. package/dist/plugins/import-meta-url.d.ts +16 -0
  23. package/dist/plugins/import-meta-url.js +193 -0
  24. package/dist/plugins/import-meta-url.js.map +1 -0
  25. package/dist/server/app-browser-action-result.d.ts +9 -16
  26. package/dist/server/app-browser-action-result.js +25 -14
  27. package/dist/server/app-browser-action-result.js.map +1 -1
  28. package/dist/server/app-browser-entry.js +171 -45
  29. package/dist/server/app-browser-entry.js.map +1 -1
  30. package/dist/server/app-browser-mpa-navigation.d.ts +16 -0
  31. package/dist/server/app-browser-mpa-navigation.js +36 -0
  32. package/dist/server/app-browser-mpa-navigation.js.map +1 -0
  33. package/dist/server/app-browser-popstate.d.ts +3 -1
  34. package/dist/server/app-browser-popstate.js +15 -1
  35. package/dist/server/app-browser-popstate.js.map +1 -1
  36. package/dist/server/app-browser-state.js +2 -1
  37. package/dist/server/app-browser-state.js.map +1 -1
  38. package/dist/server/app-layout-param-observation.d.ts +30 -0
  39. package/dist/server/app-layout-param-observation.js +130 -0
  40. package/dist/server/app-layout-param-observation.js.map +1 -0
  41. package/dist/server/app-page-boundary-render.js +2 -2
  42. package/dist/server/app-page-boundary-render.js.map +1 -1
  43. package/dist/server/app-page-dispatch.js +1 -1
  44. package/dist/server/app-page-params.d.ts +2 -1
  45. package/dist/server/app-page-params.js +14 -1
  46. package/dist/server/app-page-params.js.map +1 -1
  47. package/dist/server/app-page-probe.d.ts +12 -1
  48. package/dist/server/app-page-probe.js +116 -1
  49. package/dist/server/app-page-probe.js.map +1 -1
  50. package/dist/server/app-route-handler-response.js +1 -1
  51. package/dist/server/app-route-handler-response.js.map +1 -1
  52. package/dist/server/app-rsc-cache-busting.d.ts +3 -2
  53. package/dist/server/app-rsc-cache-busting.js +9 -7
  54. package/dist/server/app-rsc-cache-busting.js.map +1 -1
  55. package/dist/server/app-rsc-handler.js +11 -1
  56. package/dist/server/app-rsc-handler.js.map +1 -1
  57. package/dist/server/app-segment-config.d.ts +1 -1
  58. package/dist/server/app-segment-config.js +4 -1
  59. package/dist/server/app-segment-config.js.map +1 -1
  60. package/dist/server/app-server-action-execution.d.ts +5 -0
  61. package/dist/server/app-server-action-execution.js +198 -22
  62. package/dist/server/app-server-action-execution.js.map +1 -1
  63. package/dist/server/artifact-compatibility.d.ts +2 -1
  64. package/dist/server/artifact-compatibility.js +10 -1
  65. package/dist/server/artifact-compatibility.js.map +1 -1
  66. package/dist/server/client-reuse-manifest.d.ts +9 -4
  67. package/dist/server/client-reuse-manifest.js +2 -1
  68. package/dist/server/client-reuse-manifest.js.map +1 -1
  69. package/dist/server/dev-server.js +52 -10
  70. package/dist/server/dev-server.js.map +1 -1
  71. package/dist/server/document-initial-head.d.ts +7 -0
  72. package/dist/server/document-initial-head.js +35 -0
  73. package/dist/server/document-initial-head.js.map +1 -0
  74. package/dist/server/pages-document-initial-props.d.ts +84 -2
  75. package/dist/server/pages-document-initial-props.js +127 -1
  76. package/dist/server/pages-document-initial-props.js.map +1 -1
  77. package/dist/server/pages-node-compat.js +1 -1
  78. package/dist/server/pages-page-response.d.ts +14 -0
  79. package/dist/server/pages-page-response.js +31 -8
  80. package/dist/server/pages-page-response.js.map +1 -1
  81. package/dist/server/prod-server.js +13 -6
  82. package/dist/server/prod-server.js.map +1 -1
  83. package/dist/server/skip-cache-proof.d.ts +23 -2
  84. package/dist/server/skip-cache-proof.js +81 -12
  85. package/dist/server/skip-cache-proof.js.map +1 -1
  86. package/dist/server/static-layout-client-reuse-proof.d.ts +16 -0
  87. package/dist/server/static-layout-client-reuse-proof.js +35 -0
  88. package/dist/server/static-layout-client-reuse-proof.js.map +1 -0
  89. package/dist/shims/cache.d.ts +21 -1
  90. package/dist/shims/cache.js +101 -6
  91. package/dist/shims/cache.js.map +1 -1
  92. package/dist/shims/document.d.ts +6 -0
  93. package/dist/shims/document.js +7 -8
  94. package/dist/shims/document.js.map +1 -1
  95. package/dist/shims/error-boundary.d.ts +4 -4
  96. package/dist/shims/error-boundary.js +27 -28
  97. package/dist/shims/error-boundary.js.map +1 -1
  98. package/dist/shims/fetch-cache.d.ts +3 -1
  99. package/dist/shims/fetch-cache.js +16 -5
  100. package/dist/shims/fetch-cache.js.map +1 -1
  101. package/dist/shims/hash-scroll.d.ts +4 -1
  102. package/dist/shims/hash-scroll.js +13 -1
  103. package/dist/shims/hash-scroll.js.map +1 -1
  104. package/dist/shims/head-state.d.ts +1 -0
  105. package/dist/shims/head-state.js +18 -3
  106. package/dist/shims/head-state.js.map +1 -1
  107. package/dist/shims/head.d.ts +35 -1
  108. package/dist/shims/head.js +113 -14
  109. package/dist/shims/head.js.map +1 -1
  110. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +56 -0
  111. package/dist/shims/internal/pages-data-fetch-dedup.js +70 -0
  112. package/dist/shims/internal/pages-data-fetch-dedup.js.map +1 -0
  113. package/dist/shims/link.js +28 -2
  114. package/dist/shims/link.js.map +1 -1
  115. package/dist/shims/navigation.d.ts +39 -1
  116. package/dist/shims/navigation.js +61 -13
  117. package/dist/shims/navigation.js.map +1 -1
  118. package/dist/shims/router.js +37 -17
  119. package/dist/shims/router.js.map +1 -1
  120. package/dist/shims/thenable-params.d.ts +5 -2
  121. package/dist/shims/thenable-params.js +25 -1
  122. package/dist/shims/thenable-params.js.map +1 -1
  123. package/dist/shims/unified-request-context.js +3 -0
  124. package/dist/shims/unified-request-context.js.map +1 -1
  125. package/dist/utils/client-build-manifest.d.ts +15 -0
  126. package/dist/utils/client-build-manifest.js +54 -0
  127. package/dist/utils/client-build-manifest.js.map +1 -0
  128. package/dist/utils/hash.js +1 -1
  129. package/dist/utils/hash.js.map +1 -1
  130. package/dist/utils/lazy-chunks.d.ts +1 -1
  131. package/dist/utils/lazy-chunks.js.map +1 -1
  132. package/dist/utils/vite-version.d.ts +11 -0
  133. package/dist/utils/vite-version.js +36 -0
  134. package/dist/utils/vite-version.js.map +1 -0
  135. package/package.json +2 -2
@@ -25,16 +25,38 @@ const wellKnownProperties = new Set([
25
25
  function isWellKnownProperty(prop) {
26
26
  return wellKnownProperties.has(prop);
27
27
  }
28
- function makeThenableParams(obj) {
28
+ function observeParamKeys(observer, keys) {
29
+ if (observer) observer.observeParamAccess(keys);
30
+ }
31
+ function observeAllParamKeys(observer, plain) {
32
+ observeParamKeys(observer, Object.keys(plain));
33
+ }
34
+ function observeReadableParamKeys(observer, plain) {
35
+ observeParamKeys(observer, Object.keys(plain).filter((key) => !isWellKnownProperty(key)));
36
+ }
37
+ function isPromiseContinuation(prop) {
38
+ return prop === "then" || prop === "catch" || prop === "finally";
39
+ }
40
+ function makeThenableParams(obj, observer) {
29
41
  const plain = { ...obj };
30
42
  const promise = Promise.resolve(plain);
31
43
  return new Proxy(promise, {
32
44
  get(target, prop, receiver) {
45
+ if (isPromiseContinuation(prop)) {
46
+ const value = Reflect.get(target, prop, receiver);
47
+ if (typeof value !== "function") return value;
48
+ return (...args) => {
49
+ observeAllParamKeys(observer, plain);
50
+ return Reflect.apply(value, target, args);
51
+ };
52
+ }
53
+ if (typeof prop === "string" && !isWellKnownProperty(prop)) observeParamKeys(observer, [prop]);
33
54
  if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) return Reflect.get(plain, prop);
34
55
  const value = Reflect.get(target, prop, receiver);
35
56
  return typeof value === "function" ? value.bind(target) : value;
36
57
  },
37
58
  getOwnPropertyDescriptor(target, prop) {
59
+ if (typeof prop === "string" && !isWellKnownProperty(prop)) observeParamKeys(observer, [prop]);
38
60
  if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) return {
39
61
  configurable: true,
40
62
  enumerable: true,
@@ -44,9 +66,11 @@ function makeThenableParams(obj) {
44
66
  return Reflect.getOwnPropertyDescriptor(target, prop);
45
67
  },
46
68
  has(target, prop) {
69
+ if (typeof prop === "string" && !isWellKnownProperty(prop)) observeParamKeys(observer, [prop]);
47
70
  return Reflect.has(target, prop) || !isWellKnownProperty(prop) && hasParamProperty(plain, prop);
48
71
  },
49
72
  ownKeys() {
73
+ observeReadableParamKeys(observer, plain);
50
74
  return Reflect.ownKeys(plain).filter((prop) => !isWellKnownProperty(prop));
51
75
  }
52
76
  });
@@ -1 +1 @@
1
- {"version":3,"file":"thenable-params.js","names":[],"sources":["../../src/shims/thenable-params.ts"],"sourcesContent":["function hasParamProperty<T extends Record<string, unknown>>(obj: T, prop: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n// Properties that cannot be shadowed by param names because they need to\n// remain the true underlying value for Promises / React to work correctly.\n//\n// Next.js comments out `value` and `error` in reflect-utils.ts because they\n// use `Promise.resolve(underlyingParams)` directly in production, so React\n// mutations on the promise object are never shadowed. vinext uses a Proxy\n// that intercepts sync reads through a separate `plain` object, which means\n// a param named `value` or `error` would shadow React's `.status`/`.value`\n// attachments that React adds to resolved promises for `use()` caching.\n// https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/utils/reflect-utils.ts\nconst WELL_KNOWN_PROPERTIES = [\n // Object prototype\n \"hasOwnProperty\",\n \"isPrototypeOf\",\n \"propertyIsEnumerable\",\n \"toString\",\n \"valueOf\",\n \"toLocaleString\",\n\n // Promise prototype\n \"then\",\n \"catch\",\n \"finally\",\n\n // React Promise extension (status is explicitly reserved by Next.js;\n // value/error are reserved here because our Proxy-based approach creates\n // a shadowing risk that native Promise does not have)\n \"status\",\n \"value\",\n \"error\",\n\n // React introspection\n \"displayName\",\n \"_debugInfo\",\n\n // Common tested properties\n \"toJSON\",\n \"$$typeof\",\n \"__esModule\",\n\n // Tested by flight when checking for iterables\n \"@@iterator\",\n] as const;\n\n// The type-level set of well-known properties is derived directly from the\n// runtime array above, so they can never drift out of sync. These properties\n// are omitted from the synchronous intersection because the Proxy returns\n// Promise/React internals for them, not the param value. After awaiting, the\n// resolved object contains the actual param values for all keys.\ntype WellKnownProperty = (typeof WELL_KNOWN_PROPERTIES)[number];\n\nconst wellKnownProperties = new Set<PropertyKey>(WELL_KNOWN_PROPERTIES);\n\nfunction isWellKnownProperty(prop: PropertyKey): boolean {\n return wellKnownProperties.has(prop);\n}\n\nexport type ThenableParams<T extends Record<string, unknown>> = Promise<T> &\n Omit<T, WellKnownProperty>;\n\nexport function makeThenableParams<T extends Record<string, unknown>>(obj: T): ThenableParams<T> {\n const plain = { ...obj };\n const promise = Promise.resolve(plain);\n\n // The Proxy implements both Promise and plain-object behaviour so that\n // `await params` and `params.id` both work. TypeScript's Proxy type\n // cannot express this intersection precisely — the cast is isolated to\n // the boundary so the handler above stays fully type-checked.\n return new Proxy(promise, {\n get(target, prop, receiver) {\n if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) {\n return Reflect.get(plain, prop);\n }\n\n const value = Reflect.get(target, prop, receiver);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n getOwnPropertyDescriptor(target, prop) {\n if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: Reflect.get(plain, prop),\n writable: true,\n };\n }\n\n return Reflect.getOwnPropertyDescriptor(target, prop);\n },\n has(target, prop) {\n return (\n Reflect.has(target, prop) || (!isWellKnownProperty(prop) && hasParamProperty(plain, prop))\n );\n },\n ownKeys() {\n return Reflect.ownKeys(plain).filter((prop) => !isWellKnownProperty(prop));\n },\n }) as unknown as ThenableParams<T>;\n}\n"],"mappings":";AAAA,SAAS,iBAAoD,KAAQ,MAA4B;CAC/F,OAAO,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK;;AAsDxD,MAAM,sBAAsB,IAAI,IAAiB;CAvC/C;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAKA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CAGA;CAUoE,CAAC;AAEvE,SAAS,oBAAoB,MAA4B;CACvD,OAAO,oBAAoB,IAAI,KAAK;;AAMtC,SAAgB,mBAAsD,KAA2B;CAC/F,MAAM,QAAQ,EAAE,GAAG,KAAK;CACxB,MAAM,UAAU,QAAQ,QAAQ,MAAM;CAMtC,OAAO,IAAI,MAAM,SAAS;EACxB,IAAI,QAAQ,MAAM,UAAU;GAC1B,IAAI,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK,EAC7D,OAAO,QAAQ,IAAI,OAAO,KAAK;GAGjC,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,SAAS;GACjD,OAAO,OAAO,UAAU,aAAa,MAAM,KAAK,OAAO,GAAG;;EAE5D,yBAAyB,QAAQ,MAAM;GACrC,IAAI,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK,EAC7D,OAAO;IACL,cAAc;IACd,YAAY;IACZ,OAAO,QAAQ,IAAI,OAAO,KAAK;IAC/B,UAAU;IACX;GAGH,OAAO,QAAQ,yBAAyB,QAAQ,KAAK;;EAEvD,IAAI,QAAQ,MAAM;GAChB,OACE,QAAQ,IAAI,QAAQ,KAAK,IAAK,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK;;EAG7F,UAAU;GACR,OAAO,QAAQ,QAAQ,MAAM,CAAC,QAAQ,SAAS,CAAC,oBAAoB,KAAK,CAAC;;EAE7E,CAAC"}
1
+ {"version":3,"file":"thenable-params.js","names":[],"sources":["../../src/shims/thenable-params.ts"],"sourcesContent":["function hasParamProperty<T extends Record<string, unknown>>(obj: T, prop: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n// Properties that cannot be shadowed by param names because they need to\n// remain the true underlying value for Promises / React to work correctly.\n//\n// Next.js comments out `value` and `error` in reflect-utils.ts because they\n// use `Promise.resolve(underlyingParams)` directly in production, so React\n// mutations on the promise object are never shadowed. vinext uses a Proxy\n// that intercepts sync reads through a separate `plain` object, which means\n// a param named `value` or `error` would shadow React's `.status`/`.value`\n// attachments that React adds to resolved promises for `use()` caching.\n// https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/utils/reflect-utils.ts\nconst WELL_KNOWN_PROPERTIES = [\n // Object prototype\n \"hasOwnProperty\",\n \"isPrototypeOf\",\n \"propertyIsEnumerable\",\n \"toString\",\n \"valueOf\",\n \"toLocaleString\",\n\n // Promise prototype\n \"then\",\n \"catch\",\n \"finally\",\n\n // React Promise extension (status is explicitly reserved by Next.js;\n // value/error are reserved here because our Proxy-based approach creates\n // a shadowing risk that native Promise does not have)\n \"status\",\n \"value\",\n \"error\",\n\n // React introspection\n \"displayName\",\n \"_debugInfo\",\n\n // Common tested properties\n \"toJSON\",\n \"$$typeof\",\n \"__esModule\",\n\n // Tested by flight when checking for iterables\n \"@@iterator\",\n] as const;\n\n// The type-level set of well-known properties is derived directly from the\n// runtime array above, so they can never drift out of sync. These properties\n// are omitted from the synchronous intersection because the Proxy returns\n// Promise/React internals for them, not the param value. After awaiting, the\n// resolved object contains the actual param values for all keys.\ntype WellKnownProperty = (typeof WELL_KNOWN_PROPERTIES)[number];\n\nconst wellKnownProperties = new Set<PropertyKey>(WELL_KNOWN_PROPERTIES);\n\nfunction isWellKnownProperty(prop: PropertyKey): boolean {\n return wellKnownProperties.has(prop);\n}\n\nexport type ThenableParams<T extends Record<string, unknown>> = Promise<T> &\n Omit<T, WellKnownProperty>;\n\nexport type ThenableParamsObserver = Readonly<{\n observeParamAccess: (keys: readonly string[]) => void;\n}>;\n\nfunction observeParamKeys(\n observer: ThenableParamsObserver | undefined,\n keys: readonly string[],\n): void {\n if (observer) {\n observer.observeParamAccess(keys);\n }\n}\n\nfunction observeAllParamKeys<T extends Record<string, unknown>>(\n observer: ThenableParamsObserver | undefined,\n plain: T,\n): void {\n observeParamKeys(observer, Object.keys(plain));\n}\n\nfunction observeReadableParamKeys<T extends Record<string, unknown>>(\n observer: ThenableParamsObserver | undefined,\n plain: T,\n): void {\n const keys = Object.keys(plain).filter((key) => !isWellKnownProperty(key));\n observeParamKeys(observer, keys);\n}\n\nfunction isPromiseContinuation(prop: PropertyKey): boolean {\n return prop === \"then\" || prop === \"catch\" || prop === \"finally\";\n}\n\nexport function makeThenableParams<T extends Record<string, unknown>>(\n obj: T,\n observer?: ThenableParamsObserver,\n): ThenableParams<T> {\n const plain = { ...obj };\n const promise = Promise.resolve(plain);\n\n // The Proxy implements both Promise and plain-object behaviour so that\n // `await params` and `params.id` both work. TypeScript's Proxy type\n // cannot express this intersection precisely — the cast is isolated to\n // the boundary so the handler above stays fully type-checked.\n return new Proxy(promise, {\n get(target, prop, receiver) {\n if (isPromiseContinuation(prop)) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== \"function\") return value;\n return (...args: unknown[]) => {\n observeAllParamKeys(observer, plain);\n return Reflect.apply(value, target, args);\n };\n }\n\n if (typeof prop === \"string\" && !isWellKnownProperty(prop)) {\n observeParamKeys(observer, [prop]);\n }\n\n if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) {\n return Reflect.get(plain, prop);\n }\n\n const value = Reflect.get(target, prop, receiver);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n getOwnPropertyDescriptor(target, prop) {\n if (typeof prop === \"string\" && !isWellKnownProperty(prop)) {\n observeParamKeys(observer, [prop]);\n }\n\n if (!isWellKnownProperty(prop) && hasParamProperty(plain, prop)) {\n return {\n configurable: true,\n enumerable: true,\n value: Reflect.get(plain, prop),\n writable: true,\n };\n }\n\n return Reflect.getOwnPropertyDescriptor(target, prop);\n },\n has(target, prop) {\n if (typeof prop === \"string\" && !isWellKnownProperty(prop)) {\n observeParamKeys(observer, [prop]);\n }\n\n return (\n Reflect.has(target, prop) || (!isWellKnownProperty(prop) && hasParamProperty(plain, prop))\n );\n },\n ownKeys() {\n observeReadableParamKeys(observer, plain);\n return Reflect.ownKeys(plain).filter((prop) => !isWellKnownProperty(prop));\n },\n }) as unknown as ThenableParams<T>;\n}\n"],"mappings":";AAAA,SAAS,iBAAoD,KAAQ,MAA4B;CAC/F,OAAO,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK;;AAsDxD,MAAM,sBAAsB,IAAI,IAAiB;CAvC/C;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAKA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CAGA;CAUoE,CAAC;AAEvE,SAAS,oBAAoB,MAA4B;CACvD,OAAO,oBAAoB,IAAI,KAAK;;AAUtC,SAAS,iBACP,UACA,MACM;CACN,IAAI,UACF,SAAS,mBAAmB,KAAK;;AAIrC,SAAS,oBACP,UACA,OACM;CACN,iBAAiB,UAAU,OAAO,KAAK,MAAM,CAAC;;AAGhD,SAAS,yBACP,UACA,OACM;CAEN,iBAAiB,UADJ,OAAO,KAAK,MAAM,CAAC,QAAQ,QAAQ,CAAC,oBAAoB,IAAI,CAC1C,CAAC;;AAGlC,SAAS,sBAAsB,MAA4B;CACzD,OAAO,SAAS,UAAU,SAAS,WAAW,SAAS;;AAGzD,SAAgB,mBACd,KACA,UACmB;CACnB,MAAM,QAAQ,EAAE,GAAG,KAAK;CACxB,MAAM,UAAU,QAAQ,QAAQ,MAAM;CAMtC,OAAO,IAAI,MAAM,SAAS;EACxB,IAAI,QAAQ,MAAM,UAAU;GAC1B,IAAI,sBAAsB,KAAK,EAAE;IAC/B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,SAAS;IACjD,IAAI,OAAO,UAAU,YAAY,OAAO;IACxC,QAAQ,GAAG,SAAoB;KAC7B,oBAAoB,UAAU,MAAM;KACpC,OAAO,QAAQ,MAAM,OAAO,QAAQ,KAAK;;;GAI7C,IAAI,OAAO,SAAS,YAAY,CAAC,oBAAoB,KAAK,EACxD,iBAAiB,UAAU,CAAC,KAAK,CAAC;GAGpC,IAAI,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK,EAC7D,OAAO,QAAQ,IAAI,OAAO,KAAK;GAGjC,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,SAAS;GACjD,OAAO,OAAO,UAAU,aAAa,MAAM,KAAK,OAAO,GAAG;;EAE5D,yBAAyB,QAAQ,MAAM;GACrC,IAAI,OAAO,SAAS,YAAY,CAAC,oBAAoB,KAAK,EACxD,iBAAiB,UAAU,CAAC,KAAK,CAAC;GAGpC,IAAI,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK,EAC7D,OAAO;IACL,cAAc;IACd,YAAY;IACZ,OAAO,QAAQ,IAAI,OAAO,KAAK;IAC/B,UAAU;IACX;GAGH,OAAO,QAAQ,yBAAyB,QAAQ,KAAK;;EAEvD,IAAI,QAAQ,MAAM;GAChB,IAAI,OAAO,SAAS,YAAY,CAAC,oBAAoB,KAAK,EACxD,iBAAiB,UAAU,CAAC,KAAK,CAAC;GAGpC,OACE,QAAQ,IAAI,QAAQ,KAAK,IAAK,CAAC,oBAAoB,KAAK,IAAI,iBAAiB,OAAO,KAAK;;EAG7F,UAAU;GACR,yBAAyB,UAAU,MAAM;GACzC,OAAO,QAAQ,QAAQ,MAAM,CAAC,QAAQ,SAAS,CAAC,oBAAoB,KAAK,CAAC;;EAE7E,CAAC"}
@@ -26,8 +26,10 @@ function createRequestContext(opts) {
26
26
  serverContext: null,
27
27
  serverInsertedHTMLCallbacks: [],
28
28
  requestScopedCacheLife: null,
29
+ unstableCacheObservations: /* @__PURE__ */ new Map(),
29
30
  unstableCacheRevalidation: "foreground",
30
31
  _privateCache: null,
32
+ cacheableFetchUrls: /* @__PURE__ */ new Set(),
31
33
  currentRequestTags: [],
32
34
  currentFetchSoftTags: [],
33
35
  currentFetchCacheMode: null,
@@ -38,6 +40,7 @@ function createRequestContext(opts) {
38
40
  requestCache: /* @__PURE__ */ new WeakMap(),
39
41
  ssrContext: null,
40
42
  ssrHeadChildren: [],
43
+ documentInitialHead: [],
41
44
  rootParams: null,
42
45
  ...opts
43
46
  };
@@ -1 +1 @@
1
- {"version":3,"file":"unified-request-context.js","names":[],"sources":["../../src/shims/unified-request-context.ts"],"sourcesContent":["/**\n * Unified per-request context backed by a single AsyncLocalStorage.\n *\n * Consolidates the 5–6 nested ALS scopes that previously wrapped every\n * App Router request (headers, navigation, cache-state, private-cache,\n * fetch-cache, execution-context) into one flat store.\n *\n * Each shim module checks `isInsideUnifiedScope()` and reads its sub-fields\n * from the unified store, falling back to its own standalone ALS when\n * outside (SSR environment, Pages Router, tests).\n */\n\nimport type { AsyncLocalStorage } from \"node:async_hooks\";\nimport { getOrCreateAls } from \"./internal/als-registry.js\";\nimport type {\n CacheState,\n ExecutionContextLike,\n FetchCacheState,\n HeadState,\n I18nState,\n NavigationState,\n PrivateCacheState,\n RouterState,\n RootParamsState,\n VinextHeadersShimState,\n} from \"./request-state-types.js\";\n\n// ---------------------------------------------------------------------------\n// Unified context shape\n// ---------------------------------------------------------------------------\n\n/**\n * Flat union of all per-request state previously spread across\n * VinextHeadersShimState, NavigationState, CacheState, PrivateCacheState,\n * FetchCacheState, and ExecutionContextLike.\n *\n * Each field group is documented with its source shim module.\n */\nexport type UnifiedRequestContext = {\n // ── request-context.ts ─────────────────────────────────────────────\n /** Cloudflare Workers ExecutionContext, or null on Node.js dev. */\n executionContext: ExecutionContextLike | null;\n\n // ── cache-for-request.ts ──────────────────────────────────────────\n /** Per-request cache for cacheForRequest(). Keyed by factory function reference. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n requestCache: WeakMap<(...args: any[]) => any, unknown>;\n} & VinextHeadersShimState &\n I18nState &\n NavigationState &\n CacheState &\n PrivateCacheState &\n FetchCacheState &\n RouterState &\n HeadState &\n RootParamsState;\n\n// ---------------------------------------------------------------------------\n// ALS setup — stored on globalThis via Symbol.for so all Vite environments\n// (RSC/SSR/client) share the same instance.\n// ---------------------------------------------------------------------------\n\nconst _REQUEST_CONTEXT_ALS_KEY = Symbol.for(\"vinext.requestContext.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = getOrCreateAls<UnifiedRequestContext>(\"vinext.unifiedRequestContext.als\");\n\nfunction _getInheritedExecutionContext(): ExecutionContextLike | null {\n const unifiedStore = _als.getStore();\n if (unifiedStore) return unifiedStore.executionContext;\n\n const executionContextAls = _g[_REQUEST_CONTEXT_ALS_KEY] as\n | AsyncLocalStorage<ExecutionContextLike | null>\n | undefined;\n return executionContextAls?.getStore() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a fresh `UnifiedRequestContext` with defaults for all fields.\n * Pass partial overrides for the fields you need to pre-populate.\n */\nexport function createRequestContext(opts?: Partial<UnifiedRequestContext>): UnifiedRequestContext {\n return {\n headersContext: null,\n actionRevalidationKind: 0,\n dynamicUsageDetected: false,\n renderRequestApiUsage: new Set(),\n invalidDynamicUsageError: null,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n phase: \"render\",\n i18nContext: null,\n serverContext: null,\n serverInsertedHTMLCallbacks: [],\n requestScopedCacheLife: null,\n unstableCacheRevalidation: \"foreground\",\n _privateCache: null,\n currentRequestTags: [],\n currentFetchSoftTags: [],\n currentFetchCacheMode: null,\n dynamicFetchUrls: new Set<string>(),\n isFetchDedupeActive: false,\n currentFetchDedupeEntries: new Map(),\n executionContext: _getInheritedExecutionContext(), // inherits from standalone ALS if present\n requestCache: new WeakMap(),\n ssrContext: null,\n ssrHeadChildren: [],\n rootParams: null,\n ...opts,\n };\n}\n\n/**\n * Run `fn` within a unified request context scope.\n * All shim modules will read/write their state from `ctx` for the\n * duration of the call, including async continuations.\n */\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return _als.run(ctx, fn);\n}\n\n/**\n * Run `fn` in a nested unified scope derived from the current request context.\n * Used by legacy runWith* wrappers to reset or override one sub-state while\n * preserving proper async isolation for continuations created inside `fn`.\n * The child scope is a shallow clone of the parent store, so untouched fields\n * keep sharing their existing references while overridden slices can be reset.\n *\n * @internal\n */\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const parentCtx = _als.getStore();\n if (!parentCtx) return fn();\n\n const childCtx = { ...parentCtx };\n // NOTE: This is a shallow clone. Array fields (pendingSetCookies,\n // serverInsertedHTMLCallbacks, currentRequestTags, ssrHeadChildren), Set\n // fields (renderRequestApiUsage, dynamicFetchUrls), the _privateCache Map,\n // requestCache WeakMap, and object fields (headersContext,\n // i18nContext, serverContext, ssrContext, executionContext,\n // requestScopedCacheLife) still share references with the parent until\n // replaced. requestCache is intentionally shared — nested scopes within\n // the same request should see the same cached values. The mutate\n // callback must replace those reference-typed slices (for example\n // `ctx.currentRequestTags = []` or `ctx.renderRequestApiUsage = new Set()`)\n // rather than mutating them in-place (for\n // example `ctx.currentRequestTags.push(...)`) or the parent scope will\n // observe those changes too. Keep this enumeration in sync with\n // UnifiedRequestContext: when adding a new reference-typed field, add it\n // here too and verify callers still follow the replace-not-mutate rule.\n mutate(childCtx);\n return _als.run(childCtx, fn);\n}\n\n/**\n * Get the current unified request context.\n * Returns the ALS store when inside a `runWithRequestContext()` scope,\n * or a fresh detached context otherwise. Unlike the legacy per-shim fallback\n * singletons, this detached value is ephemeral — mutations do not persist\n * across calls. This is intentional to prevent state leakage outside request\n * scopes.\n *\n * Only direct callers observe this detached fallback. Shim `_getState()`\n * helpers should continue to gate on `isInsideUnifiedScope()` and fall back\n * to their standalone ALS/fallback singletons outside the unified scope.\n * If called inside a standalone `runWithExecutionContext()` scope, the\n * detached context still reflects that inherited `executionContext`.\n */\nexport function getRequestContext(): UnifiedRequestContext {\n return _als.getStore() ?? createRequestContext();\n}\n\n/**\n * Check whether the current execution is inside a `runWithRequestContext()` scope.\n * Shim modules use this to decide whether to read from the unified store\n * or fall back to their own standalone ALS.\n */\nexport function isInsideUnifiedScope(): boolean {\n return _als.getStore() != null;\n}\n"],"mappings":";;AA8DA,MAAM,2BAA2B,OAAO,IAAI,4BAA4B;AACxE,MAAM,KAAK;AACX,MAAM,OAAO,eAAsC,mCAAmC;AAEtF,SAAS,gCAA6D;CACpE,MAAM,eAAe,KAAK,UAAU;CACpC,IAAI,cAAc,OAAO,aAAa;CAKtC,OAH4B,GAAG,2BAGH,UAAU,IAAI;;;;;;AAW5C,SAAgB,qBAAqB,MAA8D;CACjG,OAAO;EACL,gBAAgB;EAChB,wBAAwB;EACxB,sBAAsB;EACtB,uCAAuB,IAAI,KAAK;EAChC,0BAA0B;EAC1B,mBAAmB,EAAE;EACrB,uBAAuB;EACvB,OAAO;EACP,aAAa;EACb,eAAe;EACf,6BAA6B,EAAE;EAC/B,wBAAwB;EACxB,2BAA2B;EAC3B,eAAe;EACf,oBAAoB,EAAE;EACtB,sBAAsB,EAAE;EACxB,uBAAuB;EACvB,kCAAkB,IAAI,KAAa;EACnC,qBAAqB;EACrB,2CAA2B,IAAI,KAAK;EACpC,kBAAkB,+BAA+B;EACjD,8BAAc,IAAI,SAAS;EAC3B,YAAY;EACZ,iBAAiB,EAAE;EACnB,YAAY;EACZ,GAAG;EACJ;;AAgBH,SAAgB,sBACd,KACA,IACgB;CAChB,OAAO,KAAK,IAAI,KAAK,GAAG;;AAoB1B,SAAgB,4BACd,QACA,IACgB;CAChB,MAAM,YAAY,KAAK,UAAU;CACjC,IAAI,CAAC,WAAW,OAAO,IAAI;CAE3B,MAAM,WAAW,EAAE,GAAG,WAAW;CAgBjC,OAAO,SAAS;CAChB,OAAO,KAAK,IAAI,UAAU,GAAG;;;;;;;;;;;;;;;;AAiB/B,SAAgB,oBAA2C;CACzD,OAAO,KAAK,UAAU,IAAI,sBAAsB;;;;;;;AAQlD,SAAgB,uBAAgC;CAC9C,OAAO,KAAK,UAAU,IAAI"}
1
+ {"version":3,"file":"unified-request-context.js","names":[],"sources":["../../src/shims/unified-request-context.ts"],"sourcesContent":["/**\n * Unified per-request context backed by a single AsyncLocalStorage.\n *\n * Consolidates the 5–6 nested ALS scopes that previously wrapped every\n * App Router request (headers, navigation, cache-state, private-cache,\n * fetch-cache, execution-context) into one flat store.\n *\n * Each shim module checks `isInsideUnifiedScope()` and reads its sub-fields\n * from the unified store, falling back to its own standalone ALS when\n * outside (SSR environment, Pages Router, tests).\n */\n\nimport type { AsyncLocalStorage } from \"node:async_hooks\";\nimport { getOrCreateAls } from \"./internal/als-registry.js\";\nimport type {\n CacheState,\n ExecutionContextLike,\n FetchCacheState,\n HeadState,\n I18nState,\n NavigationState,\n PrivateCacheState,\n RouterState,\n RootParamsState,\n VinextHeadersShimState,\n} from \"./request-state-types.js\";\n\n// ---------------------------------------------------------------------------\n// Unified context shape\n// ---------------------------------------------------------------------------\n\n/**\n * Flat union of all per-request state previously spread across\n * VinextHeadersShimState, NavigationState, CacheState, PrivateCacheState,\n * FetchCacheState, and ExecutionContextLike.\n *\n * Each field group is documented with its source shim module.\n */\nexport type UnifiedRequestContext = {\n // ── request-context.ts ─────────────────────────────────────────────\n /** Cloudflare Workers ExecutionContext, or null on Node.js dev. */\n executionContext: ExecutionContextLike | null;\n\n // ── cache-for-request.ts ──────────────────────────────────────────\n /** Per-request cache for cacheForRequest(). Keyed by factory function reference. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n requestCache: WeakMap<(...args: any[]) => any, unknown>;\n} & VinextHeadersShimState &\n I18nState &\n NavigationState &\n CacheState &\n PrivateCacheState &\n FetchCacheState &\n RouterState &\n HeadState &\n RootParamsState;\n\n// ---------------------------------------------------------------------------\n// ALS setup — stored on globalThis via Symbol.for so all Vite environments\n// (RSC/SSR/client) share the same instance.\n// ---------------------------------------------------------------------------\n\nconst _REQUEST_CONTEXT_ALS_KEY = Symbol.for(\"vinext.requestContext.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = getOrCreateAls<UnifiedRequestContext>(\"vinext.unifiedRequestContext.als\");\n\nfunction _getInheritedExecutionContext(): ExecutionContextLike | null {\n const unifiedStore = _als.getStore();\n if (unifiedStore) return unifiedStore.executionContext;\n\n const executionContextAls = _g[_REQUEST_CONTEXT_ALS_KEY] as\n | AsyncLocalStorage<ExecutionContextLike | null>\n | undefined;\n return executionContextAls?.getStore() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a fresh `UnifiedRequestContext` with defaults for all fields.\n * Pass partial overrides for the fields you need to pre-populate.\n */\nexport function createRequestContext(opts?: Partial<UnifiedRequestContext>): UnifiedRequestContext {\n return {\n headersContext: null,\n actionRevalidationKind: 0,\n dynamicUsageDetected: false,\n renderRequestApiUsage: new Set(),\n invalidDynamicUsageError: null,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n phase: \"render\",\n i18nContext: null,\n serverContext: null,\n serverInsertedHTMLCallbacks: [],\n requestScopedCacheLife: null,\n unstableCacheObservations: new Map(),\n unstableCacheRevalidation: \"foreground\",\n _privateCache: null,\n cacheableFetchUrls: new Set<string>(),\n currentRequestTags: [],\n currentFetchSoftTags: [],\n currentFetchCacheMode: null,\n dynamicFetchUrls: new Set<string>(),\n isFetchDedupeActive: false,\n currentFetchDedupeEntries: new Map(),\n executionContext: _getInheritedExecutionContext(), // inherits from standalone ALS if present\n requestCache: new WeakMap(),\n ssrContext: null,\n ssrHeadChildren: [],\n documentInitialHead: [],\n rootParams: null,\n ...opts,\n };\n}\n\n/**\n * Run `fn` within a unified request context scope.\n * All shim modules will read/write their state from `ctx` for the\n * duration of the call, including async continuations.\n */\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return _als.run(ctx, fn);\n}\n\n/**\n * Run `fn` in a nested unified scope derived from the current request context.\n * Used by legacy runWith* wrappers to reset or override one sub-state while\n * preserving proper async isolation for continuations created inside `fn`.\n * The child scope is a shallow clone of the parent store, so untouched fields\n * keep sharing their existing references while overridden slices can be reset.\n *\n * @internal\n */\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const parentCtx = _als.getStore();\n if (!parentCtx) return fn();\n\n const childCtx = { ...parentCtx };\n // NOTE: This is a shallow clone. Array fields (pendingSetCookies,\n // serverInsertedHTMLCallbacks, currentRequestTags, ssrHeadChildren), Set\n // fields (renderRequestApiUsage, cacheableFetchUrls, dynamicFetchUrls),\n // Map fields (unstableCacheObservations, _privateCache),\n // requestCache WeakMap, and object fields (headersContext,\n // i18nContext, serverContext, ssrContext, executionContext,\n // requestScopedCacheLife) still share references with the parent until\n // replaced. requestCache is intentionally shared — nested scopes within\n // the same request should see the same cached values. The mutate\n // callback must replace those reference-typed slices (for example\n // `ctx.currentRequestTags = []` or `ctx.renderRequestApiUsage = new Set()`)\n // rather than mutating them in-place (for\n // example `ctx.currentRequestTags.push(...)`) or the parent scope will\n // observe those changes too. Keep this enumeration in sync with\n // UnifiedRequestContext: when adding a new reference-typed field, add it\n // here too and verify callers still follow the replace-not-mutate rule.\n mutate(childCtx);\n return _als.run(childCtx, fn);\n}\n\n/**\n * Get the current unified request context.\n * Returns the ALS store when inside a `runWithRequestContext()` scope,\n * or a fresh detached context otherwise. Unlike the legacy per-shim fallback\n * singletons, this detached value is ephemeral — mutations do not persist\n * across calls. This is intentional to prevent state leakage outside request\n * scopes.\n *\n * Only direct callers observe this detached fallback. Shim `_getState()`\n * helpers should continue to gate on `isInsideUnifiedScope()` and fall back\n * to their standalone ALS/fallback singletons outside the unified scope.\n * If called inside a standalone `runWithExecutionContext()` scope, the\n * detached context still reflects that inherited `executionContext`.\n */\nexport function getRequestContext(): UnifiedRequestContext {\n return _als.getStore() ?? createRequestContext();\n}\n\n/**\n * Check whether the current execution is inside a `runWithRequestContext()` scope.\n * Shim modules use this to decide whether to read from the unified store\n * or fall back to their own standalone ALS.\n */\nexport function isInsideUnifiedScope(): boolean {\n return _als.getStore() != null;\n}\n"],"mappings":";;AA8DA,MAAM,2BAA2B,OAAO,IAAI,4BAA4B;AACxE,MAAM,KAAK;AACX,MAAM,OAAO,eAAsC,mCAAmC;AAEtF,SAAS,gCAA6D;CACpE,MAAM,eAAe,KAAK,UAAU;CACpC,IAAI,cAAc,OAAO,aAAa;CAKtC,OAH4B,GAAG,2BAGH,UAAU,IAAI;;;;;;AAW5C,SAAgB,qBAAqB,MAA8D;CACjG,OAAO;EACL,gBAAgB;EAChB,wBAAwB;EACxB,sBAAsB;EACtB,uCAAuB,IAAI,KAAK;EAChC,0BAA0B;EAC1B,mBAAmB,EAAE;EACrB,uBAAuB;EACvB,OAAO;EACP,aAAa;EACb,eAAe;EACf,6BAA6B,EAAE;EAC/B,wBAAwB;EACxB,2CAA2B,IAAI,KAAK;EACpC,2BAA2B;EAC3B,eAAe;EACf,oCAAoB,IAAI,KAAa;EACrC,oBAAoB,EAAE;EACtB,sBAAsB,EAAE;EACxB,uBAAuB;EACvB,kCAAkB,IAAI,KAAa;EACnC,qBAAqB;EACrB,2CAA2B,IAAI,KAAK;EACpC,kBAAkB,+BAA+B;EACjD,8BAAc,IAAI,SAAS;EAC3B,YAAY;EACZ,iBAAiB,EAAE;EACnB,qBAAqB,EAAE;EACvB,YAAY;EACZ,GAAG;EACJ;;AAgBH,SAAgB,sBACd,KACA,IACgB;CAChB,OAAO,KAAK,IAAI,KAAK,GAAG;;AAoB1B,SAAgB,4BACd,QACA,IACgB;CAChB,MAAM,YAAY,KAAK,UAAU;CACjC,IAAI,CAAC,WAAW,OAAO,IAAI;CAE3B,MAAM,WAAW,EAAE,GAAG,WAAW;CAiBjC,OAAO,SAAS;CAChB,OAAO,KAAK,IAAI,UAAU,GAAG;;;;;;;;;;;;;;;;AAiB/B,SAAgB,oBAA2C;CACzD,OAAO,KAAK,UAAU,IAAI,sBAAsB;;;;;;;AAQlD,SAAgB,uBAAgC;CAC9C,OAAO,KAAK,UAAU,IAAI"}
@@ -0,0 +1,15 @@
1
+ import { BuildManifestChunk } from "./lazy-chunks.js";
2
+
3
+ //#region src/utils/client-build-manifest.d.ts
4
+ type ClientBuildManifest = Record<string, BuildManifestChunk>;
5
+ declare function readClientBuildManifest(manifestPath: string): ClientBuildManifest | undefined;
6
+ declare function findClientEntryFileFromManifest(buildManifest: ClientBuildManifest, assetBase: string): string | undefined;
7
+ declare function findClientEntryFile(options: {
8
+ buildManifest?: ClientBuildManifest;
9
+ clientDir: string;
10
+ assetsSubdir: string;
11
+ assetBase: string;
12
+ }): string | undefined;
13
+ //#endregion
14
+ export { findClientEntryFile, findClientEntryFileFromManifest, readClientBuildManifest };
15
+ //# sourceMappingURL=client-build-manifest.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { isUnknownRecord } from "./record.js";
2
+ import { manifestFileWithBase } from "./manifest-paths.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/utils/client-build-manifest.ts
6
+ const CLIENT_ENTRY_MARKERS = ["vinext-client-entry", "vinext-app-browser-entry"];
7
+ function readClientBuildManifest(manifestPath) {
8
+ if (!fs.existsSync(manifestPath)) return void 0;
9
+ try {
10
+ const value = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
11
+ if (!isUnknownRecord(value)) return void 0;
12
+ const manifest = {};
13
+ for (const [key, entry] of Object.entries(value)) {
14
+ if (!isUnknownRecord(entry) || typeof entry.file !== "string") continue;
15
+ const imports = readStringArray(entry.imports);
16
+ const dynamicImports = readStringArray(entry.dynamicImports);
17
+ const css = readStringArray(entry.css);
18
+ const assets = readStringArray(entry.assets);
19
+ manifest[key] = {
20
+ file: entry.file,
21
+ ...entry.isEntry === true ? { isEntry: true } : {},
22
+ ...entry.isDynamicEntry === true ? { isDynamicEntry: true } : {},
23
+ ...imports ? { imports } : {},
24
+ ...dynamicImports ? { dynamicImports } : {},
25
+ ...css ? { css } : {},
26
+ ...assets ? { assets } : {}
27
+ };
28
+ }
29
+ return manifest;
30
+ } catch {
31
+ return;
32
+ }
33
+ }
34
+ function findClientEntryFileFromManifest(buildManifest, assetBase) {
35
+ const entries = Object.values(buildManifest).filter((entry) => entry.isEntry && entry.file);
36
+ const chosen = entries.find((entry) => CLIENT_ENTRY_MARKERS.some((marker) => entry.file.includes(marker))) ?? entries[0];
37
+ return chosen ? manifestFileWithBase(chosen.file, assetBase) : void 0;
38
+ }
39
+ function findClientEntryFileInAssetsDir(options) {
40
+ const assetsDir = path.join(options.clientDir, options.assetsSubdir);
41
+ if (!fs.existsSync(assetsDir)) return void 0;
42
+ const entry = fs.readdirSync(assetsDir).find((file) => CLIENT_ENTRY_MARKERS.some((marker) => file.includes(marker)) && file.endsWith(".js"));
43
+ return entry ? manifestFileWithBase(`${options.assetsSubdir}/${entry}`, options.assetBase) : void 0;
44
+ }
45
+ function findClientEntryFile(options) {
46
+ return (options.buildManifest ? findClientEntryFileFromManifest(options.buildManifest, options.assetBase) : void 0) ?? findClientEntryFileInAssetsDir(options);
47
+ }
48
+ function readStringArray(value) {
49
+ return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
50
+ }
51
+ //#endregion
52
+ export { findClientEntryFile, findClientEntryFileFromManifest, readClientBuildManifest };
53
+
54
+ //# sourceMappingURL=client-build-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-build-manifest.js","names":[],"sources":["../../src/utils/client-build-manifest.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { manifestFileWithBase } from \"./manifest-paths.js\";\nimport type { BuildManifestChunk } from \"./lazy-chunks.js\";\nimport { isUnknownRecord } from \"./record.js\";\n\ntype ClientBuildManifest = Record<string, BuildManifestChunk>;\n\nconst CLIENT_ENTRY_MARKERS = [\"vinext-client-entry\", \"vinext-app-browser-entry\"] as const;\n\nexport function readClientBuildManifest(manifestPath: string): ClientBuildManifest | undefined {\n if (!fs.existsSync(manifestPath)) return undefined;\n\n try {\n const value: unknown = JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\n if (!isUnknownRecord(value)) return undefined;\n\n const manifest: ClientBuildManifest = {};\n for (const [key, entry] of Object.entries(value)) {\n if (!isUnknownRecord(entry) || typeof entry.file !== \"string\") continue;\n\n const imports = readStringArray(entry.imports);\n const dynamicImports = readStringArray(entry.dynamicImports);\n const css = readStringArray(entry.css);\n const assets = readStringArray(entry.assets);\n manifest[key] = {\n file: entry.file,\n ...(entry.isEntry === true ? { isEntry: true } : {}),\n ...(entry.isDynamicEntry === true ? { isDynamicEntry: true } : {}),\n ...(imports ? { imports } : {}),\n ...(dynamicImports ? { dynamicImports } : {}),\n ...(css ? { css } : {}),\n ...(assets ? { assets } : {}),\n };\n }\n\n return manifest;\n } catch {\n return undefined;\n }\n}\n\nexport function findClientEntryFileFromManifest(\n buildManifest: ClientBuildManifest,\n assetBase: string,\n): string | undefined {\n const entries = Object.values(buildManifest).filter((entry) => entry.isEntry && entry.file);\n // A client build can emit more than one `isEntry` chunk (e.g. the client\n // entry plus instrumentation or middleware entries), and the manifest's\n // iteration order is not guaranteed to surface the client entry first.\n // Prefer the chunk whose file carries a known client-entry marker — matching\n // the precise on-disk scan in findClientEntryFileInAssetsDir — and only fall\n // back to the first entry when nothing is marked.\n const markedEntry = entries.find((entry) =>\n CLIENT_ENTRY_MARKERS.some((marker) => entry.file.includes(marker)),\n );\n const chosen = markedEntry ?? entries[0];\n\n return chosen ? manifestFileWithBase(chosen.file, assetBase) : undefined;\n}\n\nfunction findClientEntryFileInAssetsDir(options: {\n clientDir: string;\n assetsSubdir: string;\n assetBase: string;\n}): string | undefined {\n const assetsDir = path.join(options.clientDir, options.assetsSubdir);\n if (!fs.existsSync(assetsDir)) return undefined;\n\n const entry = fs\n .readdirSync(assetsDir)\n .find(\n (file) =>\n CLIENT_ENTRY_MARKERS.some((marker) => file.includes(marker)) && file.endsWith(\".js\"),\n );\n\n return entry\n ? manifestFileWithBase(`${options.assetsSubdir}/${entry}`, options.assetBase)\n : undefined;\n}\n\nexport function findClientEntryFile(options: {\n buildManifest?: ClientBuildManifest;\n clientDir: string;\n assetsSubdir: string;\n assetBase: string;\n}): string | undefined {\n return (\n (options.buildManifest\n ? findClientEntryFileFromManifest(options.buildManifest, options.assetBase)\n : undefined) ?? findClientEntryFileInAssetsDir(options)\n );\n}\n\nfunction readStringArray(value: unknown): string[] | undefined {\n return Array.isArray(value) && value.every((item): item is string => typeof item === \"string\")\n ? value\n : undefined;\n}\n"],"mappings":";;;;;AAQA,MAAM,uBAAuB,CAAC,uBAAuB,2BAA2B;AAEhF,SAAgB,wBAAwB,cAAuD;CAC7F,IAAI,CAAC,GAAG,WAAW,aAAa,EAAE,OAAO,KAAA;CAEzC,IAAI;EACF,MAAM,QAAiB,KAAK,MAAM,GAAG,aAAa,cAAc,QAAQ,CAAC;EACzE,IAAI,CAAC,gBAAgB,MAAM,EAAE,OAAO,KAAA;EAEpC,MAAM,WAAgC,EAAE;EACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,EAAE;GAChD,IAAI,CAAC,gBAAgB,MAAM,IAAI,OAAO,MAAM,SAAS,UAAU;GAE/D,MAAM,UAAU,gBAAgB,MAAM,QAAQ;GAC9C,MAAM,iBAAiB,gBAAgB,MAAM,eAAe;GAC5D,MAAM,MAAM,gBAAgB,MAAM,IAAI;GACtC,MAAM,SAAS,gBAAgB,MAAM,OAAO;GAC5C,SAAS,OAAO;IACd,MAAM,MAAM;IACZ,GAAI,MAAM,YAAY,OAAO,EAAE,SAAS,MAAM,GAAG,EAAE;IACnD,GAAI,MAAM,mBAAmB,OAAO,EAAE,gBAAgB,MAAM,GAAG,EAAE;IACjE,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;IAC9B,GAAI,iBAAiB,EAAE,gBAAgB,GAAG,EAAE;IAC5C,GAAI,MAAM,EAAE,KAAK,GAAG,EAAE;IACtB,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;IAC7B;;EAGH,OAAO;SACD;EACN;;;AAIJ,SAAgB,gCACd,eACA,WACoB;CACpB,MAAM,UAAU,OAAO,OAAO,cAAc,CAAC,QAAQ,UAAU,MAAM,WAAW,MAAM,KAAK;CAU3F,MAAM,SAHc,QAAQ,MAAM,UAChC,qBAAqB,MAAM,WAAW,MAAM,KAAK,SAAS,OAAO,CAAC,CAE1C,IAAI,QAAQ;CAEtC,OAAO,SAAS,qBAAqB,OAAO,MAAM,UAAU,GAAG,KAAA;;AAGjE,SAAS,+BAA+B,SAIjB;CACrB,MAAM,YAAY,KAAK,KAAK,QAAQ,WAAW,QAAQ,aAAa;CACpE,IAAI,CAAC,GAAG,WAAW,UAAU,EAAE,OAAO,KAAA;CAEtC,MAAM,QAAQ,GACX,YAAY,UAAU,CACtB,MACE,SACC,qBAAqB,MAAM,WAAW,KAAK,SAAS,OAAO,CAAC,IAAI,KAAK,SAAS,MAAM,CACvF;CAEH,OAAO,QACH,qBAAqB,GAAG,QAAQ,aAAa,GAAG,SAAS,QAAQ,UAAU,GAC3E,KAAA;;AAGN,SAAgB,oBAAoB,SAKb;CACrB,QACG,QAAQ,gBACL,gCAAgC,QAAQ,eAAe,QAAQ,UAAU,GACzE,KAAA,MAAc,+BAA+B,QAAQ;;AAI7D,SAAS,gBAAgB,OAAsC;CAC7D,OAAO,MAAM,QAAQ,MAAM,IAAI,MAAM,OAAO,SAAyB,OAAO,SAAS,SAAS,GAC1F,QACA,KAAA"}
@@ -14,7 +14,7 @@ function fnv1a64(input) {
14
14
  h2 ^= input.charCodeAt(i);
15
15
  h2 = h2 * 16777619 >>> 0;
16
16
  }
17
- return h1.toString(36) + h2.toString(36);
17
+ return h1.toString(16).padStart(8, "0") + h2.toString(16).padStart(8, "0");
18
18
  }
19
19
  //#endregion
20
20
  export { fnv1a64 };
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","names":[],"sources":["../../src/utils/hash.ts"],"sourcesContent":["/**\n * FNV-1a hash producing a 64-bit result (two 32-bit rounds with different seeds).\n * Used for deterministic key generation where collisions must be rare.\n */\nexport function fnv1a64(input: string): string {\n // First 32-bit round with standard FNV offset basis\n let h1 = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h1 ^= input.charCodeAt(i);\n h1 = (h1 * 0x01000193) >>> 0;\n }\n // Second 32-bit round with different seed\n let h2 = 0x050c5d1f;\n for (let i = 0; i < input.length; i++) {\n h2 ^= input.charCodeAt(i);\n h2 = (h2 * 0x01000193) >>> 0;\n }\n return h1.toString(36) + h2.toString(36);\n}\n"],"mappings":";;;;;AAIA,SAAgB,QAAQ,OAAuB;CAE7C,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,WAAW,EAAE;EACzB,KAAM,KAAK,aAAgB;;CAG7B,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,WAAW,EAAE;EACzB,KAAM,KAAK,aAAgB;;CAE7B,OAAO,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG"}
1
+ {"version":3,"file":"hash.js","names":[],"sources":["../../src/utils/hash.ts"],"sourcesContent":["/**\n * FNV-1a hash producing a 64-bit result (two 32-bit rounds with different seeds).\n * Used for deterministic key generation where collisions must be rare.\n */\nexport function fnv1a64(input: string): string {\n // First 32-bit round with standard FNV offset basis\n let h1 = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h1 ^= input.charCodeAt(i);\n h1 = (h1 * 0x01000193) >>> 0;\n }\n // Second 32-bit round with different seed\n let h2 = 0x050c5d1f;\n for (let i = 0; i < input.length; i++) {\n h2 ^= input.charCodeAt(i);\n h2 = (h2 * 0x01000193) >>> 0;\n }\n return h1.toString(16).padStart(8, \"0\") + h2.toString(16).padStart(8, \"0\");\n}\n"],"mappings":";;;;;AAIA,SAAgB,QAAQ,OAAuB;CAE7C,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,WAAW,EAAE;EACzB,KAAM,KAAK,aAAgB;;CAG7B,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,WAAW,EAAE;EACzB,KAAM,KAAK,aAAgB;;CAE7B,OAAO,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,GAAG,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI"}
@@ -30,5 +30,5 @@ type BuildManifestChunk = {
30
30
  */
31
31
  declare function computeLazyChunks(buildManifest: Record<string, BuildManifestChunk>): string[];
32
32
  //#endregion
33
- export { computeLazyChunks };
33
+ export { BuildManifestChunk, computeLazyChunks };
34
34
  //# sourceMappingURL=lazy-chunks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-chunks.js","names":[],"sources":["../../src/utils/lazy-chunks.ts"],"sourcesContent":["/**\n * Build-manifest chunk metadata used to compute lazy chunks.\n */\ntype BuildManifestChunk = {\n file: string;\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n};\n\n/**\n * Compute the set of chunk filenames that are ONLY reachable through dynamic\n * imports (i.e. behind React.lazy(), next/dynamic, or manual import()).\n *\n * These chunks should NOT be modulepreloaded in the HTML — they will be\n * fetched on demand when the dynamic import executes.\n *\n * Algorithm: Starting from all entry chunks in the build manifest, walk the\n * static `imports` tree (breadth-first). Any chunk file NOT reached by this\n * walk is only reachable through `dynamicImports` and is therefore \"lazy\".\n *\n * @param buildManifest - Vite's build manifest (manifest.json), which is a\n * Record<string, ManifestChunk> where each chunk has `file`, `imports`,\n * `dynamicImports`, `isEntry`, and `isDynamicEntry` fields.\n * @returns Array of chunk filenames (e.g. \"_next/static/mermaid-NOHMQCX5.js\") that\n * should be excluded from modulepreload hints.\n */\nexport function computeLazyChunks(buildManifest: Record<string, BuildManifestChunk>): string[] {\n // Collect all chunk files that are statically reachable from entries\n const eagerFiles = new Set<string>();\n const visited = new Set<string>();\n const queue: string[] = [];\n\n // Start BFS from all entry chunks\n for (const key of Object.keys(buildManifest)) {\n const chunk = buildManifest[key];\n if (chunk.isEntry) {\n queue.push(key);\n }\n }\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || visited.has(key)) continue;\n visited.add(key);\n\n const chunk = buildManifest[key];\n if (!chunk) continue;\n\n // Mark this chunk's file as eager\n eagerFiles.add(chunk.file);\n\n // Also mark its CSS as eager (CSS should always be preloaded to avoid FOUC)\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n eagerFiles.add(cssFile);\n }\n }\n\n // Follow only static imports — NOT dynamicImports\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n if (!visited.has(imp)) {\n queue.push(imp);\n }\n }\n }\n }\n\n // Any JS file in the manifest that's NOT in eagerFiles is a lazy chunk\n const lazyChunks: string[] = [];\n const allFiles = new Set<string>();\n for (const key of Object.keys(buildManifest)) {\n const chunk = buildManifest[key];\n if (chunk.file && !allFiles.has(chunk.file)) {\n allFiles.add(chunk.file);\n if (!eagerFiles.has(chunk.file) && chunk.file.endsWith(\".js\")) {\n lazyChunks.push(chunk.file);\n }\n }\n }\n\n return lazyChunks;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8BA,SAAgB,kBAAkB,eAA6D;CAE7F,MAAM,6BAAa,IAAI,KAAa;CACpC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAkB,EAAE;CAG1B,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,EAE1C,IADc,cAAc,KAClB,SACR,MAAM,KAAK,IAAI;CAInB,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,MAAM,MAAM,OAAO;EACzB,IAAI,CAAC,OAAO,QAAQ,IAAI,IAAI,EAAE;EAC9B,QAAQ,IAAI,IAAI;EAEhB,MAAM,QAAQ,cAAc;EAC5B,IAAI,CAAC,OAAO;EAGZ,WAAW,IAAI,MAAM,KAAK;EAG1B,IAAI,MAAM,KACR,KAAK,MAAM,WAAW,MAAM,KAC1B,WAAW,IAAI,QAAQ;EAK3B,IAAI,MAAM;QACH,MAAM,OAAO,MAAM,SACtB,IAAI,CAAC,QAAQ,IAAI,IAAI,EACnB,MAAM,KAAK,IAAI;;;CAOvB,MAAM,aAAuB,EAAE;CAC/B,MAAM,2BAAW,IAAI,KAAa;CAClC,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,EAAE;EAC5C,MAAM,QAAQ,cAAc;EAC5B,IAAI,MAAM,QAAQ,CAAC,SAAS,IAAI,MAAM,KAAK,EAAE;GAC3C,SAAS,IAAI,MAAM,KAAK;GACxB,IAAI,CAAC,WAAW,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK,SAAS,MAAM,EAC3D,WAAW,KAAK,MAAM,KAAK;;;CAKjC,OAAO"}
1
+ {"version":3,"file":"lazy-chunks.js","names":[],"sources":["../../src/utils/lazy-chunks.ts"],"sourcesContent":["/**\n * Build-manifest chunk metadata used to compute lazy chunks.\n */\nexport type BuildManifestChunk = {\n file: string;\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: string[];\n};\n\n/**\n * Compute the set of chunk filenames that are ONLY reachable through dynamic\n * imports (i.e. behind React.lazy(), next/dynamic, or manual import()).\n *\n * These chunks should NOT be modulepreloaded in the HTML — they will be\n * fetched on demand when the dynamic import executes.\n *\n * Algorithm: Starting from all entry chunks in the build manifest, walk the\n * static `imports` tree (breadth-first). Any chunk file NOT reached by this\n * walk is only reachable through `dynamicImports` and is therefore \"lazy\".\n *\n * @param buildManifest - Vite's build manifest (manifest.json), which is a\n * Record<string, ManifestChunk> where each chunk has `file`, `imports`,\n * `dynamicImports`, `isEntry`, and `isDynamicEntry` fields.\n * @returns Array of chunk filenames (e.g. \"_next/static/mermaid-NOHMQCX5.js\") that\n * should be excluded from modulepreload hints.\n */\nexport function computeLazyChunks(buildManifest: Record<string, BuildManifestChunk>): string[] {\n // Collect all chunk files that are statically reachable from entries\n const eagerFiles = new Set<string>();\n const visited = new Set<string>();\n const queue: string[] = [];\n\n // Start BFS from all entry chunks\n for (const key of Object.keys(buildManifest)) {\n const chunk = buildManifest[key];\n if (chunk.isEntry) {\n queue.push(key);\n }\n }\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || visited.has(key)) continue;\n visited.add(key);\n\n const chunk = buildManifest[key];\n if (!chunk) continue;\n\n // Mark this chunk's file as eager\n eagerFiles.add(chunk.file);\n\n // Also mark its CSS as eager (CSS should always be preloaded to avoid FOUC)\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n eagerFiles.add(cssFile);\n }\n }\n\n // Follow only static imports — NOT dynamicImports\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n if (!visited.has(imp)) {\n queue.push(imp);\n }\n }\n }\n }\n\n // Any JS file in the manifest that's NOT in eagerFiles is a lazy chunk\n const lazyChunks: string[] = [];\n const allFiles = new Set<string>();\n for (const key of Object.keys(buildManifest)) {\n const chunk = buildManifest[key];\n if (chunk.file && !allFiles.has(chunk.file)) {\n allFiles.add(chunk.file);\n if (!eagerFiles.has(chunk.file) && chunk.file.endsWith(\".js\")) {\n lazyChunks.push(chunk.file);\n }\n }\n }\n\n return lazyChunks;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8BA,SAAgB,kBAAkB,eAA6D;CAE7F,MAAM,6BAAa,IAAI,KAAa;CACpC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAkB,EAAE;CAG1B,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,EAE1C,IADc,cAAc,KAClB,SACR,MAAM,KAAK,IAAI;CAInB,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,MAAM,MAAM,OAAO;EACzB,IAAI,CAAC,OAAO,QAAQ,IAAI,IAAI,EAAE;EAC9B,QAAQ,IAAI,IAAI;EAEhB,MAAM,QAAQ,cAAc;EAC5B,IAAI,CAAC,OAAO;EAGZ,WAAW,IAAI,MAAM,KAAK;EAG1B,IAAI,MAAM,KACR,KAAK,MAAM,WAAW,MAAM,KAC1B,WAAW,IAAI,QAAQ;EAK3B,IAAI,MAAM;QACH,MAAM,OAAO,MAAM,SACtB,IAAI,CAAC,QAAQ,IAAI,IAAI,EACnB,MAAM,KAAK,IAAI;;;CAOvB,MAAM,aAAuB,EAAE;CAC/B,MAAM,2BAAW,IAAI,KAAa;CAClC,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,EAAE;EAC5C,MAAM,QAAQ,cAAc;EAC5B,IAAI,MAAM,QAAQ,CAAC,SAAS,IAAI,MAAM,KAAK,EAAE;GAC3C,SAAS,IAAI,MAAM,KAAK;GACxB,IAAI,CAAC,WAAW,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK,SAAS,MAAM,EAC3D,WAAW,KAAK,MAAM,KAAK;;;CAKjC,OAAO"}
@@ -0,0 +1,11 @@
1
+ //#region src/utils/vite-version.d.ts
2
+ /**
3
+ * Detect Vite major version at runtime by resolving from cwd.
4
+ * The plugin may be installed in a workspace root with Vite 7 but used
5
+ * by a project that has Vite 8 — so we resolve from cwd, not from
6
+ * the plugin's own location.
7
+ */
8
+ declare function getViteMajorVersion(): number;
9
+ //#endregion
10
+ export { getViteMajorVersion };
11
+ //# sourceMappingURL=vite-version.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ //#region src/utils/vite-version.ts
4
+ /**
5
+ * Vite major-version detection.
6
+ *
7
+ * Several vinext behaviors depend on whether the host project is running Vite 8
8
+ * (Rolldown-based, with native `resolve.tsconfigPaths`, `oxc` transforms, and
9
+ * `rolldownOptions`) or Vite 7 (Rollup/esbuild). This helper centralizes the
10
+ * detection so the Vite-major gate is computed the same way everywhere.
11
+ */
12
+ /**
13
+ * Detect Vite major version at runtime by resolving from cwd.
14
+ * The plugin may be installed in a workspace root with Vite 7 but used
15
+ * by a project that has Vite 8 — so we resolve from cwd, not from
16
+ * the plugin's own location.
17
+ */
18
+ function getViteMajorVersion() {
19
+ try {
20
+ const vitePkg = createRequire(path.join(process.cwd(), "package.json"))("vite/package.json");
21
+ const viteMajor = parseInt(vitePkg?.version, 10);
22
+ if (vitePkg?.name === "vite" && Number.isFinite(viteMajor)) return viteMajor;
23
+ const bundledViteMajor = parseInt(vitePkg?.bundledVersions?.vite, 10);
24
+ if (Number.isFinite(bundledViteMajor)) return bundledViteMajor;
25
+ console.warn(`[vinext] Could not determine Vite major version from ${vitePkg?.name ?? "vite/package.json"}; assuming Vite 7`);
26
+ return 7;
27
+ } catch (error) {
28
+ const message = error instanceof Error ? error.message : String(error);
29
+ console.warn(`[vinext] Failed to resolve vite/package.json (${message}); assuming Vite 7`);
30
+ return 7;
31
+ }
32
+ }
33
+ //#endregion
34
+ export { getViteMajorVersion };
35
+
36
+ //# sourceMappingURL=vite-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-version.js","names":[],"sources":["../../src/utils/vite-version.ts"],"sourcesContent":["/**\n * Vite major-version detection.\n *\n * Several vinext behaviors depend on whether the host project is running Vite 8\n * (Rolldown-based, with native `resolve.tsconfigPaths`, `oxc` transforms, and\n * `rolldownOptions`) or Vite 7 (Rollup/esbuild). This helper centralizes the\n * detection so the Vite-major gate is computed the same way everywhere.\n */\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\n\n/**\n * Detect Vite major version at runtime by resolving from cwd.\n * The plugin may be installed in a workspace root with Vite 7 but used\n * by a project that has Vite 8 — so we resolve from cwd, not from\n * the plugin's own location.\n */\nexport function getViteMajorVersion(): number {\n try {\n const require = createRequire(path.join(process.cwd(), \"package.json\"));\n const vitePkg = require(\"vite/package.json\");\n\n const viteMajor = parseInt(vitePkg?.version, 10);\n if (vitePkg?.name === \"vite\" && Number.isFinite(viteMajor)) {\n return viteMajor;\n }\n\n const bundledViteMajor = parseInt(vitePkg?.bundledVersions?.vite, 10);\n if (Number.isFinite(bundledViteMajor)) {\n return bundledViteMajor;\n }\n\n // npm aliases like `vite: npm:@voidzero-dev/vite-plus-core@...` expose the\n // aliased package.json, whose own version is not Vite's version.\n console.warn(\n `[vinext] Could not determine Vite major version from ${vitePkg?.name ?? \"vite/package.json\"}; assuming Vite 7`,\n );\n return 7;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.warn(`[vinext] Failed to resolve vite/package.json (${message}); assuming Vite 7`);\n return 7;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,sBAA8B;CAC5C,IAAI;EAEF,MAAM,UADU,cAAc,KAAK,KAAK,QAAQ,KAAK,EAAE,eAAe,CAC/C,CAAC,oBAAoB;EAE5C,MAAM,YAAY,SAAS,SAAS,SAAS,GAAG;EAChD,IAAI,SAAS,SAAS,UAAU,OAAO,SAAS,UAAU,EACxD,OAAO;EAGT,MAAM,mBAAmB,SAAS,SAAS,iBAAiB,MAAM,GAAG;EACrE,IAAI,OAAO,SAAS,iBAAiB,EACnC,OAAO;EAKT,QAAQ,KACN,wDAAwD,SAAS,QAAQ,oBAAoB,mBAC9F;EACD,OAAO;UACA,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;EACtE,QAAQ,KAAK,iDAAiD,QAAQ,oBAAoB;EAC1F,OAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "0.0.54",
3
+ "version": "0.0.55",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -81,7 +81,7 @@
81
81
  "@types/react": "^19.2.14",
82
82
  "@types/react-dom": "^19.2.3",
83
83
  "@vitejs/plugin-react": "^6.0.1",
84
- "@vitejs/plugin-rsc": "^0.5.26",
84
+ "@vitejs/plugin-rsc": "^0.5.27",
85
85
  "react-server-dom-webpack": "^19.2.6",
86
86
  "vite": "npm:@voidzero-dev/vite-plus-core@0.1.22",
87
87
  "vite-plus": "0.1.22"