@inlang/paraglide-js 2.26.0 → 2.28.0

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 (225) hide show
  1. package/README.md +11 -1
  2. package/dist/bundler-plugins/per-locale-build/index.js +14 -7
  3. package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
  4. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +237 -4
  5. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
  6. package/dist/bundler-plugins/unplugin.d.ts +1 -1
  7. package/dist/bundler-plugins/unplugin.js +79 -10
  8. package/dist/bundler-plugins/unplugin.js.map +1 -1
  9. package/dist/bundler-plugins/unplugin.test.js +334 -1
  10. package/dist/bundler-plugins/unplugin.test.js.map +1 -1
  11. package/dist/bundler-plugins/vite.js +2 -1
  12. package/dist/bundler-plugins/vite.js.map +1 -1
  13. package/dist/bundler-plugins/vite.test.js +1 -1
  14. package/dist/bundler-plugins/vite.test.js.map +1 -1
  15. package/dist/cli/commands/compile/command.js +13 -0
  16. package/dist/cli/commands/compile/command.js.map +1 -1
  17. package/dist/cli/commands/compile/command.test.js +87 -3
  18. package/dist/cli/commands/compile/command.test.js.map +1 -1
  19. package/dist/cli/commands/init/command.d.ts +5 -0
  20. package/dist/cli/commands/init/command.js +216 -44
  21. package/dist/cli/commands/init/command.js.map +1 -1
  22. package/dist/cli/commands/init/command.test.d.ts +1 -0
  23. package/dist/cli/commands/init/command.test.js +123 -0
  24. package/dist/cli/commands/init/command.test.js.map +1 -0
  25. package/dist/cli/defaults.js +2 -2
  26. package/dist/cli/defaults.js.map +1 -1
  27. package/dist/cli/init-options.d.ts +11 -0
  28. package/dist/cli/init-options.js +2 -0
  29. package/dist/cli/init-options.js.map +1 -0
  30. package/dist/cli/steps/add-inlang-check.d.ts +19 -0
  31. package/dist/cli/steps/add-inlang-check.js +60 -0
  32. package/dist/cli/steps/add-inlang-check.js.map +1 -0
  33. package/dist/cli/steps/add-inlang-check.test.d.ts +1 -0
  34. package/dist/cli/steps/add-inlang-check.test.js +88 -0
  35. package/dist/cli/steps/add-inlang-check.test.js.map +1 -0
  36. package/dist/cli/steps/add-message-lint.d.ts +34 -0
  37. package/dist/cli/steps/add-message-lint.js +105 -0
  38. package/dist/cli/steps/add-message-lint.js.map +1 -0
  39. package/dist/cli/steps/add-message-lint.test.d.ts +1 -0
  40. package/dist/cli/steps/add-message-lint.test.js +74 -0
  41. package/dist/cli/steps/add-message-lint.test.js.map +1 -0
  42. package/dist/cli/steps/add-vite-plugin.d.ts +18 -0
  43. package/dist/cli/steps/add-vite-plugin.js +34 -6
  44. package/dist/cli/steps/add-vite-plugin.js.map +1 -1
  45. package/dist/cli/steps/add-vite-plugin.test.js +25 -9
  46. package/dist/cli/steps/add-vite-plugin.test.js.map +1 -1
  47. package/dist/cli/steps/agents-md-suggestion.d.ts +11 -0
  48. package/dist/cli/steps/agents-md-suggestion.js +19 -0
  49. package/dist/cli/steps/agents-md-suggestion.js.map +1 -0
  50. package/dist/cli/steps/agents-md-suggestion.test.d.ts +1 -0
  51. package/dist/cli/steps/agents-md-suggestion.test.js +36 -0
  52. package/dist/cli/steps/agents-md-suggestion.test.js.map +1 -0
  53. package/dist/cli/steps/check-for-uncomitted-changes.d.ts +3 -0
  54. package/dist/cli/steps/check-for-uncomitted-changes.js +15 -3
  55. package/dist/cli/steps/check-for-uncomitted-changes.js.map +1 -1
  56. package/dist/cli/steps/detect-bundler.d.ts +1 -0
  57. package/dist/cli/steps/detect-bundler.js +7 -1
  58. package/dist/cli/steps/detect-bundler.js.map +1 -1
  59. package/dist/cli/steps/initialize-inlang-project.d.ts +4 -3
  60. package/dist/cli/steps/initialize-inlang-project.js +60 -157
  61. package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
  62. package/dist/cli/steps/maybe-add-machine-translation.d.ts +4 -0
  63. package/dist/cli/steps/maybe-add-machine-translation.js +14 -8
  64. package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
  65. package/dist/cli/steps/maybe-add-sherlock.d.ts +2 -0
  66. package/dist/cli/steps/maybe-add-sherlock.js +13 -7
  67. package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
  68. package/dist/cli/steps/maybe-add-sherlock.test.d.ts +1 -0
  69. package/dist/cli/steps/maybe-add-sherlock.test.js +44 -0
  70. package/dist/cli/steps/maybe-add-sherlock.test.js.map +1 -0
  71. package/dist/cli/steps/prompt-for-outdir.d.ts +2 -0
  72. package/dist/cli/steps/prompt-for-outdir.js +4 -0
  73. package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
  74. package/dist/cli/steps/update-package-json.js +8 -13
  75. package/dist/cli/steps/update-package-json.js.map +1 -1
  76. package/dist/cli/steps/update-ts-config.d.ts +6 -0
  77. package/dist/cli/steps/update-ts-config.js +27 -4
  78. package/dist/cli/steps/update-ts-config.js.map +1 -1
  79. package/dist/cli/utils.d.ts +11 -0
  80. package/dist/cli/utils.js +21 -0
  81. package/dist/cli/utils.js.map +1 -1
  82. package/dist/cli/utils.test.d.ts +1 -0
  83. package/dist/cli/utils.test.js +16 -0
  84. package/dist/cli/utils.test.js.map +1 -0
  85. package/dist/compiler/compile-annotation.d.ts +48 -1
  86. package/dist/compiler/compile-annotation.js +243 -10
  87. package/dist/compiler/compile-annotation.js.map +1 -1
  88. package/dist/compiler/compile-bundle.d.ts +7 -2
  89. package/dist/compiler/compile-bundle.js +97 -3
  90. package/dist/compiler/compile-bundle.js.map +1 -1
  91. package/dist/compiler/compile-bundle.test.js +232 -19
  92. package/dist/compiler/compile-bundle.test.js.map +1 -1
  93. package/dist/compiler/compile-lifecycle.test.d.ts +1 -0
  94. package/dist/compiler/compile-lifecycle.test.js +69 -0
  95. package/dist/compiler/compile-lifecycle.test.js.map +1 -0
  96. package/dist/compiler/compile-local-variable.d.ts +3 -0
  97. package/dist/compiler/compile-local-variable.js +5 -2
  98. package/dist/compiler/compile-local-variable.js.map +1 -1
  99. package/dist/compiler/compile-local-variable.test.js +55 -15
  100. package/dist/compiler/compile-local-variable.test.js.map +1 -1
  101. package/dist/compiler/compile-message.d.ts +29 -1
  102. package/dist/compiler/compile-message.exact-number.test.d.ts +1 -0
  103. package/dist/compiler/compile-message.exact-number.test.js +786 -0
  104. package/dist/compiler/compile-message.exact-number.test.js.map +1 -0
  105. package/dist/compiler/compile-message.js +162 -66
  106. package/dist/compiler/compile-message.js.map +1 -1
  107. package/dist/compiler/compile-message.locals.test.d.ts +1 -0
  108. package/dist/compiler/compile-message.locals.test.js +498 -0
  109. package/dist/compiler/compile-message.locals.test.js.map +1 -0
  110. package/dist/compiler/compile-message.test.js +113 -22
  111. package/dist/compiler/compile-message.test.js.map +1 -1
  112. package/dist/compiler/compile-pattern.d.ts +5 -0
  113. package/dist/compiler/compile-pattern.js +6 -18
  114. package/dist/compiler/compile-pattern.js.map +1 -1
  115. package/dist/compiler/compile-pattern.test.js +169 -5
  116. package/dist/compiler/compile-pattern.test.js.map +1 -1
  117. package/dist/compiler/compile-project.js +5 -1
  118. package/dist/compiler/compile-project.js.map +1 -1
  119. package/dist/compiler/compile-project.test.js +1260 -185
  120. package/dist/compiler/compile-project.test.js.map +1 -1
  121. package/dist/compiler/compile.js +36 -17
  122. package/dist/compiler/compile.js.map +1 -1
  123. package/dist/compiler/compile.test.js +71 -1
  124. package/dist/compiler/compile.test.js.map +1 -1
  125. package/dist/compiler/compiler-options.d.ts +41 -0
  126. package/dist/compiler/compiler-options.js.map +1 -1
  127. package/dist/compiler/create-readme.d.ts +4 -1
  128. package/dist/compiler/create-readme.js +33 -125
  129. package/dist/compiler/create-readme.js.map +1 -1
  130. package/dist/compiler/emit-ts-declarations.interop.test.js +2 -2
  131. package/dist/compiler/emit-ts-declarations.interop.test.js.map +1 -1
  132. package/dist/compiler/emit-ts-declarations.test.js +4 -4
  133. package/dist/compiler/emit-ts-declarations.test.js.map +1 -1
  134. package/dist/compiler/index.d.ts +1 -1
  135. package/dist/compiler/index.js +1 -1
  136. package/dist/compiler/index.js.map +1 -1
  137. package/dist/compiler/input-alias.d.ts +21 -0
  138. package/dist/compiler/input-alias.js +42 -0
  139. package/dist/compiler/input-alias.js.map +1 -0
  140. package/dist/compiler/input-alias.test.d.ts +1 -0
  141. package/dist/compiler/input-alias.test.js +58 -0
  142. package/dist/compiler/input-alias.test.js.map +1 -0
  143. package/dist/compiler/message-locals.d.ts +46 -0
  144. package/dist/compiler/message-locals.js +129 -0
  145. package/dist/compiler/message-locals.js.map +1 -0
  146. package/dist/compiler/output-structure/locale-modules.js +7 -1
  147. package/dist/compiler/output-structure/locale-modules.js.map +1 -1
  148. package/dist/compiler/output-structure/locale-modules.test.js +35 -0
  149. package/dist/compiler/output-structure/locale-modules.test.js.map +1 -1
  150. package/dist/compiler/output-structure/message-modules.js +6 -4
  151. package/dist/compiler/output-structure/message-modules.js.map +1 -1
  152. package/dist/compiler/output-structure/message-modules.test.js +35 -0
  153. package/dist/compiler/output-structure/message-modules.test.js.map +1 -1
  154. package/dist/compiler/registry.d.ts +12 -0
  155. package/dist/compiler/registry.js +158 -31
  156. package/dist/compiler/registry.js.map +1 -1
  157. package/dist/compiler/registry.test.d.ts +1 -0
  158. package/dist/compiler/registry.test.js +291 -0
  159. package/dist/compiler/registry.test.js.map +1 -0
  160. package/dist/compiler/runtime/create-runtime.d.ts +2 -0
  161. package/dist/compiler/runtime/create-runtime.js +9 -0
  162. package/dist/compiler/runtime/create-runtime.js.map +1 -1
  163. package/dist/compiler/runtime/extract-locale-from-cookie.js +8 -1
  164. package/dist/compiler/runtime/extract-locale-from-cookie.js.map +1 -1
  165. package/dist/compiler/runtime/extract-locale-from-cookie.test.js +26 -0
  166. package/dist/compiler/runtime/extract-locale-from-cookie.test.js.map +1 -1
  167. package/dist/compiler/runtime/extract-locale-from-header.js +47 -5
  168. package/dist/compiler/runtime/extract-locale-from-header.js.map +1 -1
  169. package/dist/compiler/runtime/extract-locale-from-header.test.js +58 -0
  170. package/dist/compiler/runtime/extract-locale-from-header.test.js.map +1 -1
  171. package/dist/compiler/runtime/get-locale.js +7 -1
  172. package/dist/compiler/runtime/get-locale.js.map +1 -1
  173. package/dist/compiler/runtime/get-locale.test.js +95 -0
  174. package/dist/compiler/runtime/get-locale.test.js.map +1 -1
  175. package/dist/compiler/runtime/localize-href.d.ts +8 -0
  176. package/dist/compiler/runtime/localize-href.js +60 -0
  177. package/dist/compiler/runtime/localize-href.js.map +1 -1
  178. package/dist/compiler/runtime/localize-href.test.js +227 -1
  179. package/dist/compiler/runtime/localize-href.test.js.map +1 -1
  180. package/dist/compiler/runtime/set-locale.js +24 -6
  181. package/dist/compiler/runtime/set-locale.js.map +1 -1
  182. package/dist/compiler/runtime/set-locale.test.js +182 -0
  183. package/dist/compiler/runtime/set-locale.test.js.map +1 -1
  184. package/dist/compiler/runtime/type.d.ts +2 -0
  185. package/dist/compiler/runtime/type.js.map +1 -1
  186. package/dist/compiler/runtime/type.test.js +34 -0
  187. package/dist/compiler/runtime/type.test.js.map +1 -1
  188. package/dist/compiler/runtime/variables.d.ts +2 -0
  189. package/dist/compiler/runtime/variables.js +7 -0
  190. package/dist/compiler/runtime/variables.js.map +1 -1
  191. package/dist/compiler/server/create-server-file.js +24 -0
  192. package/dist/compiler/server/create-server-file.js.map +1 -1
  193. package/dist/compiler/server/create-server-file.test.js +8 -2
  194. package/dist/compiler/server/create-server-file.test.js.map +1 -1
  195. package/dist/compiler/server/middleware.d.ts +8 -2
  196. package/dist/compiler/server/middleware.js +204 -11
  197. package/dist/compiler/server/middleware.js.map +1 -1
  198. package/dist/compiler/server/middleware.test.js +750 -3
  199. package/dist/compiler/server/middleware.test.js.map +1 -1
  200. package/dist/eslint/index.d.ts +4 -0
  201. package/dist/eslint/index.js +8 -0
  202. package/dist/eslint/index.js.map +1 -0
  203. package/dist/eslint/no-dynamic-message-access.d.ts +3 -0
  204. package/dist/eslint/no-dynamic-message-access.js +150 -0
  205. package/dist/eslint/no-dynamic-message-access.js.map +1 -0
  206. package/dist/eslint/no-dynamic-message-access.test.d.ts +1 -0
  207. package/dist/eslint/no-dynamic-message-access.test.js +126 -0
  208. package/dist/eslint/no-dynamic-message-access.test.js.map +1 -0
  209. package/dist/eslint/oxlint.test.d.ts +1 -0
  210. package/dist/eslint/oxlint.test.js +64 -0
  211. package/dist/eslint/oxlint.test.js.map +1 -0
  212. package/dist/services/config/config-schema.d.ts +2 -0
  213. package/dist/services/config/config-schema.js +2 -0
  214. package/dist/services/config/config-schema.js.map +1 -1
  215. package/dist/services/config/load-paraglide-config.test.js +12 -0
  216. package/dist/services/config/load-paraglide-config.test.js.map +1 -1
  217. package/dist/services/env-variables/index.js +1 -1
  218. package/dist/services/env-variables/index.js.map +1 -1
  219. package/dist/services/file-handling/write-output.bench.js +51 -11
  220. package/dist/services/file-handling/write-output.bench.js.map +1 -1
  221. package/dist/services/file-handling/write-output.js +60 -20
  222. package/dist/services/file-handling/write-output.js.map +1 -1
  223. package/dist/services/file-handling/write-output.test.js +175 -0
  224. package/dist/services/file-handling/write-output.test.js.map +1 -1
  225. package/package.json +15 -5
@@ -1 +1 @@
1
- {"version":3,"file":"create-server-file.test.js","sourceRoot":"","sources":["../../../src/compiler/server/create-server-file.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { afterEach, expect, test } from \"vitest\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport { createServerFile } from \"./create-server-file.js\";\n\nconst temporaryDirectories: string[] = [];\n\nafterEach(async () => {\n\tawait Promise.all(\n\t\ttemporaryDirectories\n\t\t\t.splice(0)\n\t\t\t.map((directory) => rm(directory, { recursive: true, force: true }))\n\t);\n});\n\ntest(\"uses the initialized AsyncLocalStorage when an import interceptor snapshots the initial export\", async () => {\n\tconst directory = await mkdtemp(join(tmpdir(), \"paraglide-server-\"));\n\ttemporaryDirectories.push(directory);\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles: [],\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: false,\n\t\t},\n\t}).replace('\"./runtime.js\"', '\"./runtime-wrapper.mjs\"');\n\n\tawait writeFile(join(directory, \"server.mjs\"), serverCode);\n\tawait writeFile(\n\t\tjoin(directory, \"runtime-real.mjs\"),\n\t\t`export let serverAsyncLocalStorage;\nexport const disableAsyncLocalStorage = false;\nexport function overwriteServerAsyncLocalStorage(value) {\n serverAsyncLocalStorage = value;\n}\nexport function getServerAsyncLocalStorage() {\n return serverAsyncLocalStorage;\n}\nexport const baseLocale = \"en\";\nexport function isExcludedByRouteStrategy() {\n return true;\n}`\n\t);\n\tawait writeFile(\n\t\tjoin(directory, \"runtime-wrapper.mjs\"),\n\t\t`import * as runtime from \"./runtime-real.mjs\";\nexport const serverAsyncLocalStorage = runtime.serverAsyncLocalStorage;\nexport const disableAsyncLocalStorage = runtime.disableAsyncLocalStorage;\nexport const overwriteServerAsyncLocalStorage = runtime.overwriteServerAsyncLocalStorage;\nexport const getServerAsyncLocalStorage = runtime.getServerAsyncLocalStorage;\nexport const baseLocale = runtime.baseLocale;\nexport const isExcludedByRouteStrategy = runtime.isExcludedByRouteStrategy;`\n\t);\n\n\tconst server = await import(\n\t\tpathToFileURL(join(directory, \"server.mjs\")).href\n\t);\n\tconst response = await server.paraglideMiddleware(\n\t\tnew Request(\"https://example.com/api/ready\"),\n\t\t() => new Response(\"ready\")\n\t);\n\n\texpect(response.status).toBe(200);\n\texpect(await response.text()).toBe(\"ready\");\n});\n\ntest(\"import statements in JSDoc examples survive in the generated server file\", () => {\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles: [],\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: false,\n\t\t},\n\t});\n\n\texpect(serverCode).toContain(\n\t\t` * import { paraglideMiddleware } from './paraglide/server.js'\\n * import handler from '@tanstack/react-start/server-entry'\\n *\\n * export default {`\n\t);\n\t// only the `import * as runtime` line that createServerFile itself prepends\n\texpect(serverCode.match(/^\\s*import\\s/gm)).toHaveLength(1);\n});\n\ntest(\"keys compiledBundles by the safe module id, not the raw bundle id (experimentalMiddlewareLocaleSplitting)\", () => {\n\t// A bundle id that changes under toSafeModuleId (case-folded + a numeric\n\t// suffix appended for the uppercase letters). trackMessageCall(), the\n\t// client's SSR message guard, and middleware.js all look up\n\t// compiledBundles by this safe id - only createCompiledMessagesObject\n\t// (inside createServerFile) used the raw id instead.\n\tconst bundleId = \"GREETING\";\n\tconst safeModuleId = toSafeModuleId(bundleId);\n\texpect(safeModuleId).not.toBe(bundleId);\n\n\tconst compiledBundles = [\n\t\t{\n\t\t\tbundle: { node: { id: bundleId } },\n\t\t\tmessages: {\n\t\t\t\ten: { code: `export const ${safeModuleId} = () => \"hello\";` },\n\t\t\t},\n\t\t},\n\t] as unknown as CompiledBundleWithMessages[];\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles,\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t},\n\t});\n\n\texpect(serverCode).toContain(`\"${safeModuleId}\":{\"en\":`);\n\texpect(serverCode).not.toContain(`\"${bundleId}\":{\"en\":`);\n});\n\ntest(\"a literal '$' in a compiled message does not corrupt the generated file (experimentalMiddlewareLocaleSplitting)\", async () => {\n\tconst directory = await mkdtemp(join(tmpdir(), \"paraglide-server-dollar-\"));\n\ttemporaryDirectories.push(directory);\n\n\t// The compiled message source for locale \"en\" evaluates to the literal\n\t// text \"$\", wrapped in a template literal by the compiler (i.e. it\n\t// contains a backtick immediately followed by a `$` immediately followed\n\t// by another backtick). Passed as a *string* to `code.replace()`, `` $` ``\n\t// is a special replacement pattern (\"insert everything before the\n\t// match\"), which splices the file's own header into the string being\n\t// built and corrupts the generated server file.\n\tconst compiledBundles = [\n\t\t{\n\t\t\tbundle: { node: { id: \"price_symbol\" } },\n\t\t\tmessages: {\n\t\t\t\ten: { code: \"export const price_symbol = () => `$`;\" },\n\t\t\t},\n\t\t},\n\t] as unknown as CompiledBundleWithMessages[];\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles,\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t},\n\t});\n\n\t// The message value must survive JSON serialization untouched.\n\texpect(serverCode).toContain('\"price_symbol\":{\"en\":\"() => `$`\"}');\n\n\t// The generated file must still be syntactically valid and importable\n\t// (the bug produces an unterminated string / invalid JS).\n\tawait writeFile(\n\t\tjoin(directory, \"runtime.js\"),\n\t\t`export const serverAsyncLocalStorage = undefined;\nexport const disableAsyncLocalStorage = false;\nexport const experimentalMiddlewareLocaleSplitting = true;\nexport const baseLocale = \"en\";\nexport function isExcludedByRouteStrategy() {\n return true;\n}\nexport function getStrategyForUrl() {\n return [];\n}\nexport async function shouldRedirect() {\n return { locale: \"en\", shouldRedirect: false };\n}\nexport function deLocalizeUrl(url) {\n return url;\n}`\n\t);\n\tawait writeFile(join(directory, \"server.mjs\"), serverCode);\n\n\tawait expect(\n\t\timport(pathToFileURL(join(directory, \"server.mjs\")).href)\n\t).resolves.toBeDefined();\n});\n"]}
1
+ {"version":3,"file":"create-server-file.test.js","sourceRoot":"","sources":["../../../src/compiler/server/create-server-file.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { afterEach, expect, test } from \"vitest\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport { createServerFile } from \"./create-server-file.js\";\n\nconst temporaryDirectories: string[] = [];\n\nafterEach(async () => {\n\tawait Promise.all(\n\t\ttemporaryDirectories\n\t\t\t.splice(0)\n\t\t\t.map((directory) => rm(directory, { recursive: true, force: true }))\n\t);\n});\n\ntest(\"uses the initialized AsyncLocalStorage when an import interceptor snapshots the initial export\", async () => {\n\tconst directory = await mkdtemp(join(tmpdir(), \"paraglide-server-\"));\n\ttemporaryDirectories.push(directory);\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles: [],\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: false,\n\t\t},\n\t}).replace('\"./runtime.js\"', '\"./runtime-wrapper.mjs\"');\n\n\tawait writeFile(join(directory, \"server.mjs\"), serverCode);\n\tawait writeFile(\n\t\tjoin(directory, \"runtime-real.mjs\"),\n\t\t`export let serverAsyncLocalStorage;\nexport const disableAsyncLocalStorage = false;\nexport function overwriteServerAsyncLocalStorage(value) {\n serverAsyncLocalStorage = value;\n}\nexport function getServerAsyncLocalStorage() {\n return serverAsyncLocalStorage;\n}\nexport const baseLocale = \"en\";\nexport function isExcludedByRouteStrategy() {\n return true;\n}`\n\t);\n\tawait writeFile(\n\t\tjoin(directory, \"runtime-wrapper.mjs\"),\n\t\t`import * as runtime from \"./runtime-real.mjs\";\nexport const serverAsyncLocalStorage = runtime.serverAsyncLocalStorage;\nexport const disableAsyncLocalStorage = runtime.disableAsyncLocalStorage;\nexport const overwriteServerAsyncLocalStorage = runtime.overwriteServerAsyncLocalStorage;\nexport const getServerAsyncLocalStorage = runtime.getServerAsyncLocalStorage;\nexport const baseLocale = runtime.baseLocale;\nexport const isExcludedByRouteStrategy = runtime.isExcludedByRouteStrategy;`\n\t);\n\n\tconst server = await import(\n\t\tpathToFileURL(join(directory, \"server.mjs\")).href\n\t);\n\tconst response = await server.paraglideMiddleware(\n\t\tnew Request(\"https://example.com/api/ready\"),\n\t\t() => new Response(\"ready\")\n\t);\n\n\texpect(response.status).toBe(200);\n\texpect(await response.text()).toBe(\"ready\");\n});\n\ntest(\"import statements in JSDoc examples survive in the generated server file\", () => {\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles: [],\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: false,\n\t\t},\n\t});\n\n\texpect(serverCode).toContain(\n\t\t` * import { paraglideMiddleware } from './paraglide/server.js'\\n * import handler from '@tanstack/react-start/server-entry'\\n *\\n * export default {`\n\t);\n\t// only the `import * as runtime` line that createServerFile itself prepends\n\texpect(serverCode.match(/^\\s*import\\s/gm)).toHaveLength(1);\n});\n\ntest(\"keys compiledBundles by the safe module id, not the raw bundle id (experimentalMiddlewareLocaleSplitting)\", () => {\n\t// A bundle id that changes under toSafeModuleId (case-folded + a numeric\n\t// suffix appended for the uppercase letters). trackMessageCall(), the\n\t// client's SSR message guard, and middleware.js all look up\n\t// compiledBundles by this safe id - only createCompiledMessagesObject\n\t// (inside createServerFile) used the raw id instead.\n\tconst bundleId = \"GREETING\";\n\tconst safeModuleId = toSafeModuleId(bundleId);\n\texpect(safeModuleId).not.toBe(bundleId);\n\n\tconst compiledBundles = [\n\t\t{\n\t\t\tbundle: { node: { id: bundleId } },\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: `export const ${safeModuleId} = () => \"hello\";`,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t] as unknown as CompiledBundleWithMessages[];\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles,\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t},\n\t});\n\n\texpect(serverCode).toContain(`\"${safeModuleId}\":{\"en\":`);\n\texpect(serverCode).not.toContain(`\"${bundleId}\":{\"en\":`);\n});\n\ntest(\"a literal '$' in a compiled message does not corrupt the generated file (experimentalMiddlewareLocaleSplitting)\", async () => {\n\tconst directory = await mkdtemp(join(tmpdir(), \"paraglide-server-dollar-\"));\n\ttemporaryDirectories.push(directory);\n\n\t// The compiled message source for locale \"en\" evaluates to the literal\n\t// text \"$\", wrapped in a template literal by the compiler (i.e. it\n\t// contains a backtick immediately followed by a `$` immediately followed\n\t// by another backtick). Passed as a *string* to `code.replace()`, `` $` ``\n\t// is a special replacement pattern (\"insert everything before the\n\t// match\"), which splices the file's own header into the string being\n\t// built and corrupts the generated server file.\n\tconst compiledBundles = [\n\t\t{\n\t\t\tbundle: { node: { id: \"price_symbol\" } },\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: \"export const price_symbol = () => `$`;\",\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t] as unknown as CompiledBundleWithMessages[];\n\n\tconst serverCode = createServerFile({\n\t\tcompiledBundles,\n\t\tcompilerOptions: {\n\t\t\tdisableAsyncLocalStorage: false,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t},\n\t});\n\n\t// The message value must survive JSON serialization untouched.\n\texpect(serverCode).toContain('\"price_symbol\":{\"en\":\"() => `$`\"}');\n\n\t// The generated file must still be syntactically valid and importable\n\t// (the bug produces an unterminated string / invalid JS).\n\tawait writeFile(\n\t\tjoin(directory, \"runtime.js\"),\n\t\t`export const serverAsyncLocalStorage = undefined;\nexport const disableAsyncLocalStorage = false;\nexport const experimentalMiddlewareLocaleSplitting = true;\nexport const baseLocale = \"en\";\nexport function isExcludedByRouteStrategy() {\n return true;\n}\nexport function getStrategyForUrl() {\n return [];\n}\nexport async function shouldRedirect() {\n return { locale: \"en\", shouldRedirect: false };\n}\nexport function deLocalizeUrl(url) {\n return url;\n}`\n\t);\n\tawait writeFile(join(directory, \"server.mjs\"), serverCode);\n\n\tawait expect(\n\t\timport(pathToFileURL(join(directory, \"server.mjs\")).href)\n\t).resolves.toBeDefined();\n});\n"]}
@@ -10,13 +10,13 @@
10
10
  * This middleware performs several key functions:
11
11
  *
12
12
  * 1. Determines the locale for the incoming request using configured strategies
13
- * 2. Handles URL localization and redirects (only for document requests)
13
+ * 2. Handles URL localization and redirects (only for document requests by default)
14
14
  * 3. Maintains locale state using AsyncLocalStorage to prevent request interference
15
15
  *
16
16
  * When URL strategy is used:
17
17
  *
18
18
  * - The locale is extracted from the URL for all request types
19
- * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests)
19
+ * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests by default)
20
20
  * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)
21
21
  *
22
22
  * @see https://paraglidejs.com/middleware
@@ -31,8 +31,13 @@
31
31
  * - `locale`: The determined locale for this request.
32
32
  * @param {{
33
33
  * effectiveRequestUrl?: string | URL | ((request: Request) => string | URL),
34
+ * redirect?: "document" | "navigation",
34
35
  * onRedirect?: (response: Response) => void
35
36
  * }} [options] - Options to control middleware behavior. `effectiveRequestUrl` sets the effective request URL used for route matching, URL-based locale detection, redirects, and `getUrlOrigin()`.
37
+ * `redirect` defaults to `"document"`, which requires `Sec-Fetch-Dest: document`.
38
+ * Unrecognized values keep that default behavior.
39
+ * `"navigation"` only redirects GET/HEAD requests, accepting either that destination
40
+ * or an absent destination with an explicit `Accept` header that allows `text/html`.
36
41
  * @returns {Promise<Response>}
37
42
  *
38
43
  * @example
@@ -94,5 +99,6 @@ export declare function paraglideMiddleware<T>(request: Request, resolve: (args:
94
99
  locale: import("./runtime.js").Locale;
95
100
  }) => T | Promise<T>, options?: {
96
101
  effectiveRequestUrl?: string | URL | ((request: Request) => string | URL);
102
+ redirect?: "document" | "navigation";
97
103
  onRedirect?: (response: Response) => void;
98
104
  }): Promise<Response>;
@@ -11,13 +11,13 @@ import * as runtime from "./runtime.js";
11
11
  * This middleware performs several key functions:
12
12
  *
13
13
  * 1. Determines the locale for the incoming request using configured strategies
14
- * 2. Handles URL localization and redirects (only for document requests)
14
+ * 2. Handles URL localization and redirects (only for document requests by default)
15
15
  * 3. Maintains locale state using AsyncLocalStorage to prevent request interference
16
16
  *
17
17
  * When URL strategy is used:
18
18
  *
19
19
  * - The locale is extracted from the URL for all request types
20
- * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests)
20
+ * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests by default)
21
21
  * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)
22
22
  *
23
23
  * @see https://paraglidejs.com/middleware
@@ -32,8 +32,13 @@ import * as runtime from "./runtime.js";
32
32
  * - `locale`: The determined locale for this request.
33
33
  * @param {{
34
34
  * effectiveRequestUrl?: string | URL | ((request: Request) => string | URL),
35
+ * redirect?: "document" | "navigation",
35
36
  * onRedirect?: (response: Response) => void
36
37
  * }} [options] - Options to control middleware behavior. `effectiveRequestUrl` sets the effective request URL used for route matching, URL-based locale detection, redirects, and `getUrlOrigin()`.
38
+ * `redirect` defaults to `"document"`, which requires `Sec-Fetch-Dest: document`.
39
+ * Unrecognized values keep that default behavior.
40
+ * `"navigation"` only redirects GET/HEAD requests, accepting either that destination
41
+ * or an absent destination with an explicit `Accept` header that allows `text/html`.
37
42
  * @returns {Promise<Response>}
38
43
  *
39
44
  * @example
@@ -103,21 +108,29 @@ export async function paraglideMiddleware(request, resolve, options) {
103
108
  return /** @type {Response} */ (await requestAsyncLocalStorage?.run({ locale, origin, messageCalls }, () => resolve({ locale, request: newRequest })));
104
109
  }
105
110
  const strategy = runtime.getStrategyForUrl(url.href);
111
+ const vary = getVaryFields(strategy);
106
112
  const decision = await runtime.shouldRedirect({
107
113
  request,
108
114
  effectiveRequestUrl: url,
109
115
  });
110
116
  const locale = decision.locale;
117
+ // Custom server strategies run before built-in strategies, regardless of order.
118
+ const hasCustomStrategy = strategy.some((strat) => strat.startsWith("custom-"));
119
+ const urlDecidesLocale = options?.redirect === "navigation" &&
120
+ strategy[0] === "url" &&
121
+ !hasCustomStrategy &&
122
+ runtime.extractLocaleFromUrl(url) !== undefined;
123
+ const navigationVary = options?.redirect === "navigation" ? ["Accept", "Sec-Fetch-Dest"] : [];
111
124
  // if the client makes a request to a URL that doesn't match
112
125
  // the localizedUrl, redirect the client to the localized URL
113
- if (request.headers.get("Sec-Fetch-Dest") === "document" &&
126
+ if (shouldRedirectRequest(request, options?.redirect) &&
114
127
  decision.shouldRedirect &&
115
128
  decision.redirectUrl) {
116
- // Create headers object with Vary header if preferredLanguage strategy is used
117
129
  /** @type {Record<string, string>} */
118
130
  const headers = {};
119
- if (strategy.includes("preferredLanguage")) {
120
- headers["Vary"] = "Accept-Language";
131
+ const redirectVary = [...(urlDecidesLocale ? [] : vary), ...navigationVary];
132
+ if (redirectVary.length > 0) {
133
+ headers["Vary"] = redirectVary.join(", ");
121
134
  }
122
135
  const response = new Response(null, {
123
136
  status: 307,
@@ -145,29 +158,58 @@ export async function paraglideMiddleware(request, resolve, options) {
145
158
  // the message functions that have been called in this request
146
159
  /** @type {Set<string>} */
147
160
  const messageCalls = new Set();
148
- const response = await requestAsyncLocalStorage?.run({ locale, origin, messageCalls }, () => resolve({ locale, request: newRequest }));
161
+ let response = await requestAsyncLocalStorage?.run({ locale, origin, messageCalls }, () => resolve({ locale, request: newRequest }));
162
+ if (response instanceof Response) {
163
+ const urlIndex = strategy.indexOf("url");
164
+ const responseVary = urlIndex !== -1 && !hasCustomStrategy && runtime.extractLocaleFromUrl(url)
165
+ ? getVaryFields(strategy.slice(0, urlIndex))
166
+ : [...vary];
167
+ // Classifying navigations can change a cached 200 into a redirect.
168
+ if ((request.method === "GET" || request.method === "HEAD") &&
169
+ urlIndex !== -1 &&
170
+ (!urlDecidesLocale || decision.shouldRedirect)) {
171
+ responseVary.push(...navigationVary);
172
+ }
173
+ response = withVary(response, responseVary);
174
+ }
149
175
  // Only modify HTML responses
150
176
  if (runtime.experimentalMiddlewareLocaleSplitting &&
177
+ typeof response?.headers?.get === "function" &&
178
+ typeof response.text === "function" &&
179
+ !response.bodyUsed &&
180
+ !response.body?.locked &&
151
181
  response.headers.get("Content-Type")?.includes("html")) {
152
182
  const body = await response.text();
153
183
  const messages = [];
184
+ /** @type {Set<string>} */
185
+ const registryFunctionNames = new Set();
154
186
  // using .values() to avoid polyfilling in older projects. else the following error is thrown
155
187
  // Type 'Set<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
156
188
  for (const messageCall of Array.from(messageCalls)) {
157
189
  const [id, locale] =
158
190
  /** @type {[string, import("./runtime.js").Locale]} */ (messageCall.split(":"));
159
191
  messages.push(`${id}: ${compiledBundles[id]?.[locale]}`);
192
+ for (const name of compiledRegistry.messages[id]?.[locale] ?? []) {
193
+ registryFunctionNames.add(name);
194
+ }
195
+ }
196
+ // The injected messages run without registry.js. Declare the registry
197
+ // functions they call (including the ones those call) in a closure.
198
+ let ssr = `{ ${messages.join(",")} }`;
199
+ if (registryFunctionNames.size > 0) {
200
+ const names = Array.from(registryFunctionNames);
201
+ ssr = `(() => { ${names
202
+ .map((name) => compiledRegistry.functions[name])
203
+ .join("\n")}\nconst registry = { ${names.join(", ")} };\nreturn ${ssr} })()`;
160
204
  }
161
205
  // Prevent translated content from terminating the inline script tag.
162
- const escapedMessages = messages
163
- .join(",")
164
- .replace(/<\/(script)/gi, "<\\/$1");
206
+ const escapedSsr = ssr.replace(/<\/(script)/gi, "<\\/$1");
165
207
  // Reuse the request's CSP nonce (if any) so the injected script is allowed under a strict CSP
166
208
  const nonce = response.headers
167
209
  .get("Content-Security-Policy")
168
210
  ?.match(/'nonce-([\w+/=-]+)'/)?.[1];
169
211
  const nonceAttr = nonce ? `nonce="${nonce}"` : "";
170
- const script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = { ${escapedMessages} }</script>`;
212
+ const script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = ${escapedSsr}</script>`;
171
213
  // Insert the script before the closing head tag
172
214
  const newBody = body.replace("</head>", `${script}</head>`);
173
215
  // Create a new response with the modified body
@@ -182,6 +224,144 @@ export async function paraglideMiddleware(request, resolve, options) {
182
224
  }
183
225
  return response;
184
226
  }
227
+ /**
228
+ * @param {string[]} strategy
229
+ * @returns {string[]}
230
+ */
231
+ function getVaryFields(strategy) {
232
+ /** @type {string[]} */
233
+ const vary = [];
234
+ if (strategy.includes("cookie"))
235
+ vary.push("Cookie");
236
+ if (strategy.includes("preferredLanguage"))
237
+ vary.push("Accept-Language");
238
+ return vary;
239
+ }
240
+ /**
241
+ * @param {Response} response
242
+ * @param {string[]} vary
243
+ * @returns {Response}
244
+ */
245
+ function withVary(response, vary) {
246
+ // Network errors and protocol upgrades are not ordinary HTTP responses.
247
+ if (response.status < 200 || response.status > 599)
248
+ return response;
249
+ const existing = response.headers.get("Vary");
250
+ const fields = existing?.split(",").map((field) => field.trim().toLowerCase()) ?? [];
251
+ if (fields.includes("*"))
252
+ return response;
253
+ const missing = vary.filter((field) => !fields.includes(field.toLowerCase()));
254
+ if (missing.length === 0)
255
+ return response;
256
+ const value = [existing, ...missing].filter(Boolean).join(", ");
257
+ try {
258
+ response.headers.set("Vary", value);
259
+ return response;
260
+ }
261
+ catch (error) {
262
+ if (!(error instanceof TypeError))
263
+ throw error;
264
+ }
265
+ // Responses from fetch() or Response.redirect() can have immutable headers.
266
+ try {
267
+ // Preserve runtime-specific response state, including Workers body encoding.
268
+ const copy = new Response(response.body, response);
269
+ copy.headers.set("Vary", value);
270
+ return copyResponseMetadata(copy, response);
271
+ }
272
+ catch {
273
+ // Keep callback responses whose body cannot be reused.
274
+ return response;
275
+ }
276
+ }
277
+ /**
278
+ * @param {Response} target
279
+ * @param {Response} source
280
+ * @returns {Response}
281
+ */
282
+ function copyResponseMetadata(target, source) {
283
+ // ResponseInit omits fetch metadata, so clones need to retain it as well.
284
+ return Object.defineProperties(target, {
285
+ url: { value: source.url, configurable: true },
286
+ redirected: { value: source.redirected, configurable: true },
287
+ type: { value: source.type, configurable: true },
288
+ clone: {
289
+ configurable: true,
290
+ writable: true,
291
+ /** @this {Response} */
292
+ value() {
293
+ return copyResponseMetadata(Response.prototype.clone.call(this), this);
294
+ },
295
+ },
296
+ });
297
+ }
298
+ /**
299
+ * @param {Request} request
300
+ * @param {"document" | "navigation"} [redirect]
301
+ * @returns {boolean}
302
+ */
303
+ function shouldRedirectRequest(request, redirect) {
304
+ const destination = request.headers.get("Sec-Fetch-Dest");
305
+ if (redirect !== "navigation")
306
+ return destination === "document";
307
+ if (request.method !== "GET" && request.method !== "HEAD")
308
+ return false;
309
+ if (destination !== null)
310
+ return destination === "document";
311
+ let specificity = -1;
312
+ let quality = 0;
313
+ for (const range of splitHeaderValue(request.headers.get("Accept") ?? "", ",")) {
314
+ const [type, ...parameters] = splitHeaderValue(range, ";").map((part) => part.trim().toLowerCase());
315
+ const rangeSpecificity = type === "text/html"
316
+ ? 2
317
+ : type === "text/*"
318
+ ? 1
319
+ : type === "*/*"
320
+ ? 0
321
+ : -1;
322
+ if (rangeSpecificity < 0 || rangeSpecificity < specificity)
323
+ continue;
324
+ const weight = parameters.find((parameter) => /^q\s*=/.test(parameter));
325
+ const value = weight ? weight.slice(weight.indexOf("=") + 1).trim() : "1";
326
+ const rangeQuality = /^(?:0(?:\.\d{0,3})?|1(?:\.0{0,3})?)$/.test(value)
327
+ ? Number(value)
328
+ : 0;
329
+ // A specific q=0 exclusion takes precedence over an acceptable wildcard.
330
+ quality =
331
+ rangeSpecificity > specificity
332
+ ? rangeQuality
333
+ : Math.max(quality, rangeQuality);
334
+ specificity = rangeSpecificity;
335
+ }
336
+ return quality > 0;
337
+ }
338
+ /**
339
+ * @param {string} value
340
+ * @param {string} separator
341
+ * @returns {string[]}
342
+ */
343
+ function splitHeaderValue(value, separator) {
344
+ const parts = [];
345
+ let start = 0;
346
+ let quoted = false;
347
+ for (let index = 0; index < value.length; index++) {
348
+ const character = value[index];
349
+ if (quoted && character === "\\") {
350
+ index++;
351
+ }
352
+ else if (character === '"') {
353
+ quoted = !quoted;
354
+ }
355
+ else if (!quoted && character === separator) {
356
+ parts.push(value.slice(start, index));
357
+ start = index + 1;
358
+ }
359
+ }
360
+ if (quoted)
361
+ return [];
362
+ parts.push(value.slice(start));
363
+ return parts;
364
+ }
185
365
  /**
186
366
  * @param {Request} request
187
367
  * @param {string | URL | ((request: Request) => string | URL) | undefined} effectiveRequestUrl
@@ -279,4 +459,17 @@ void createMockAsyncLocalStorage;
279
459
  * @type {Record<string, Record<import("./runtime.js").Locale, string>>}
280
460
  */
281
461
  const compiledBundles = {};
462
+ /**
463
+ * The registry functions the compiled messages call, for the injected
464
+ * messages that run without registry.js.
465
+ *
466
+ * `messages[id][locale]` lists the registry functions a message calls,
467
+ * including the ones those call. `functions[name]` is the code of a registry
468
+ * function.
469
+ *
470
+ * Only populated if `enableMiddlewareOptimizations` is set to `true`.
471
+ *
472
+ * @type {{ functions: Record<string, string>, messages: Record<string, Record<string, string[]>> }}
473
+ */
474
+ const compiledRegistry = { functions: {}, messages: {} };
282
475
  //# sourceMappingURL=middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/compiler/server/middleware.js"],"names":[],"mappings":"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","sourcesContent":["import * as runtime from \"./runtime.js\";\n\n/**\n * Server middleware that handles locale-based routing and request processing.\n *\n * Configure `disableAsyncLocalStorage` when generating Paraglide with\n * `paraglideVitePlugin()` or `compile()`, not when calling\n * `paraglideMiddleware()`. Keep AsyncLocalStorage enabled by default and\n * only disable it for runtimes that lack `AsyncLocalStorage` support and\n * guarantee request isolation.\n *\n * This middleware performs several key functions:\n *\n * 1. Determines the locale for the incoming request using configured strategies\n * 2. Handles URL localization and redirects (only for document requests)\n * 3. Maintains locale state using AsyncLocalStorage to prevent request interference\n *\n * When URL strategy is used:\n *\n * - The locale is extracted from the URL for all request types\n * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests)\n * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)\n *\n * @see https://paraglidejs.com/middleware\n *\n * @template T - The return type of the resolve function\n *\n * @param {Request} request - The incoming request object\n * @param {(args: { request: Request, locale: import(\"./runtime.js\").Locale }) => T | Promise<T>} resolve - Function to handle the request. The callback receives:\n * - `request`: A modified request with a delocalized URL when the URL strategy is used (e.g., `/fr/about` → `/about`).\n * If your framework handles URL localization itself (e.g., TanStack Router's `rewrite` option), use the original\n * request instead to avoid redirect loops.\n * - `locale`: The determined locale for this request.\n * @param {{\n * effectiveRequestUrl?: string | URL | ((request: Request) => string | URL),\n * onRedirect?: (response: Response) => void\n * }} [options] - Options to control middleware behavior. `effectiveRequestUrl` sets the effective request URL used for route matching, URL-based locale detection, redirects, and `getUrlOrigin()`.\n * @returns {Promise<Response>}\n *\n * @example\n * ```typescript\n * // Basic usage in metaframeworks like NextJS, SvelteKit, Astro, Nuxt, etc.\n * export const handle = async ({ event, resolve }) => {\n * return paraglideMiddleware(event.request, ({ request, locale }) => {\n * // let the framework further resolve the request\n * return resolve(request);\n * });\n * };\n * ```\n *\n * @example\n * ```typescript\n * // Usage in a framework like Express JS or Hono\n * app.use(async (req, res, next) => {\n * const result = await paraglideMiddleware(req, ({ request, locale }) => {\n * // If a redirect happens this won't be called\n * return next(request);\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Usage with frameworks that handle URL localization/delocalization themselves\n * //\n * // Some frameworks like TanStack Router handle URL localization and delocalization\n * // themselves via their own rewrite APIs (e.g., `rewrite.input`/`rewrite.output`).\n * //\n * // When the framework handles this, the middleware's URL delocalization is not needed.\n * // Using the modified `request` from the callback would cause a redirect loop because\n * // both the middleware and the framework would attempt to delocalize the URL.\n * //\n * // Solution: Pass the original request to the handler instead of the modified one.\n * // The middleware still handles locale detection, cookies, and AsyncLocalStorage context.\n * //\n * // ❌ WRONG - causes redirect loop when framework handles URL rewriting:\n * // paraglideMiddleware(req, ({ request }) => handler.fetch(request))\n * //\n * // ✅ CORRECT - use original request when framework handles URL localization:\n * // paraglideMiddleware(req, () => handler.fetch(req))\n *\n * import { paraglideMiddleware } from './paraglide/server.js'\n * import handler from '@tanstack/react-start/server-entry'\n *\n * export default {\n * fetch(req: Request): Promise<Response> {\n * // TanStack Router handles URL rewriting via deLocalizeUrl/localizeUrl\n * // so we pass the original `req` instead of the modified `request`\n * return paraglideMiddleware(req, () => handler.fetch(req))\n * },\n * }\n * ```\n */\nexport async function paraglideMiddleware(request, resolve, options) {\n\tlet requestAsyncLocalStorage = runtime.serverAsyncLocalStorage;\n\t// %async-local-storage\n\tconst url = resolveMiddlewareUrl(request, options?.effectiveRequestUrl);\n\tconst origin = url.origin;\n\n\tif (runtime.isExcludedByRouteStrategy(url.href)) {\n\t\tconst locale = runtime.baseLocale;\n\t\tconst newRequest = cloneRequestWithFallback(request, url);\n\t\t/** @type {Set<string>} */\n\t\tconst messageCalls = new Set();\n\t\treturn /** @type {Response} */ (\n\t\t\tawait requestAsyncLocalStorage?.run(\n\t\t\t\t{ locale, origin, messageCalls },\n\t\t\t\t() => resolve({ locale, request: newRequest })\n\t\t\t)\n\t\t);\n\t}\n\n\tconst strategy = runtime.getStrategyForUrl(url.href);\n\tconst decision = await runtime.shouldRedirect({\n\t\trequest,\n\t\teffectiveRequestUrl: url,\n\t});\n\tconst locale = decision.locale;\n\n\t// if the client makes a request to a URL that doesn't match\n\t// the localizedUrl, redirect the client to the localized URL\n\tif (\n\t\trequest.headers.get(\"Sec-Fetch-Dest\") === \"document\" &&\n\t\tdecision.shouldRedirect &&\n\t\tdecision.redirectUrl\n\t) {\n\t\t// Create headers object with Vary header if preferredLanguage strategy is used\n\t\t/** @type {Record<string, string>} */\n\t\tconst headers = {};\n\t\tif (strategy.includes(\"preferredLanguage\")) {\n\t\t\theaders[\"Vary\"] = \"Accept-Language\";\n\t\t}\n\n\t\tconst response = new Response(null, {\n\t\t\tstatus: 307,\n\t\t\theaders: {\n\t\t\t\tLocation: decision.redirectUrl.href,\n\t\t\t\t...headers,\n\t\t\t},\n\t\t});\n\n\t\toptions?.onRedirect?.(response);\n\t\treturn response;\n\t}\n\n\t// If the strategy includes \"url\", we need to de-localize the URL\n\t// before passing it to the server middleware.\n\t//\n\t// The middleware is responsible for mapping a localized URL to the\n\t// de-localized URL e.g. `/en/about` to `/about`. Otherwise,\n\t// the server can't render the correct page.\n\tlet newRequest;\n\tif (strategy.includes(\"url\")) {\n\t\tnewRequest = cloneRequestWithFallback(request, runtime.deLocalizeUrl(url));\n\t} else {\n\t\tnewRequest = cloneRequestWithFallback(request, url);\n\t}\n\n\t// the message functions that have been called in this request\n\t/** @type {Set<string>} */\n\tconst messageCalls = new Set();\n\n\tconst response = await requestAsyncLocalStorage?.run(\n\t\t{ locale, origin, messageCalls },\n\t\t() => resolve({ locale, request: newRequest })\n\t);\n\n\t// Only modify HTML responses\n\tif (\n\t\truntime.experimentalMiddlewareLocaleSplitting &&\n\t\tresponse.headers.get(\"Content-Type\")?.includes(\"html\")\n\t) {\n\t\tconst body = await response.text();\n\n\t\tconst messages = [];\n\n\t\t// using .values() to avoid polyfilling in older projects. else the following error is thrown\n\t\t// Type 'Set<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.\n\t\tfor (const messageCall of Array.from(messageCalls)) {\n\t\t\tconst [id, locale] =\n\t\t\t\t/** @type {[string, import(\"./runtime.js\").Locale]} */ (\n\t\t\t\t\tmessageCall.split(\":\")\n\t\t\t\t);\n\t\t\tmessages.push(`${id}: ${compiledBundles[id]?.[locale]}`);\n\t\t}\n\n\t\t// Prevent translated content from terminating the inline script tag.\n\t\tconst escapedMessages = messages\n\t\t\t.join(\",\")\n\t\t\t.replace(/<\\/(script)/gi, \"<\\\\/$1\");\n\t\t// Reuse the request's CSP nonce (if any) so the injected script is allowed under a strict CSP\n\t\tconst nonce = response.headers\n\t\t\t.get(\"Content-Security-Policy\")\n\t\t\t?.match(/'nonce-([\\w+/=-]+)'/)?.[1];\n\t\tconst nonceAttr = nonce ? `nonce=\"${nonce}\"` : \"\";\n\t\tconst script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = { ${escapedMessages} }</script>`;\n\n\t\t// Insert the script before the closing head tag\n\t\tconst newBody = body.replace(\"</head>\", `${script}</head>`);\n\n\t\t// Create a new response with the modified body\n\t\t// Clone all headers except Content-Length which will be set automatically\n\t\tconst newHeaders = new Headers(response.headers);\n\t\tnewHeaders.delete(\"Content-Length\"); // Let the browser calculate the correct length\n\n\t\treturn new Response(newBody, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: newHeaders,\n\t\t});\n\t}\n\n\treturn response;\n}\n\n/**\n * @param {Request} request\n * @param {string | URL | ((request: Request) => string | URL) | undefined} effectiveRequestUrl\n * @returns {URL}\n */\nfunction resolveMiddlewareUrl(request, effectiveRequestUrl) {\n\tif (typeof effectiveRequestUrl === \"function\") {\n\t\treturn new URL(effectiveRequestUrl(request), request.url);\n\t}\n\n\tif (\n\t\ttypeof effectiveRequestUrl === \"string\" ||\n\t\teffectiveRequestUrl instanceof URL\n\t) {\n\t\treturn new URL(effectiveRequestUrl, request.url);\n\t}\n\n\treturn new URL(request.url);\n}\n\n/**\n * Some metaframeworks (NextJS) require a new Request object.\n * https://github.com/opral/inlang-paraglide-js/issues/411\n *\n * However, some frameworks (TanStack Start 1.143+) use custom Request\n * implementations that cannot be cloned with `new Request(request)`.\n * https://github.com/opral/paraglide-js/issues/573\n *\n * Effective request URL overrides behind proxies:\n * https://github.com/opral/paraglide-js/issues/652\n *\n * @param {Request} request\n * @param {string | URL} [url]\n * @returns {Request}\n */\nfunction cloneRequestWithFallback(request, url = request.url) {\n\tconst targetUrl = typeof url === \"string\" ? url : url.href;\n\tif (targetUrl === request.url) {\n\t\ttry {\n\t\t\t// Clone first so building a new Request does not consume the original body stream.\n\t\t\treturn new Request(request.clone());\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\treturn new Request(request);\n\t\t\t} catch {\n\t\t\t\treturn request;\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\t// Clone first so building a new Request does not consume the original body stream.\n\t\treturn new Request(targetUrl, request.clone());\n\t} catch {\n\t\ttry {\n\t\t\treturn new Request(targetUrl, request);\n\t\t} catch {\n\t\t\treturn request;\n\t\t}\n\t}\n}\n\n/**\n * Creates a mock AsyncLocalStorage implementation for environments where\n * native AsyncLocalStorage is not available or disabled.\n *\n * This mock implementation mimics the behavior of the native AsyncLocalStorage\n * but doesn't require the async_hooks module. It's used as a fallback when\n * the runtime does not expose AsyncLocalStorage or when it has been disabled.\n *\n * @returns {import(\"./runtime.js\").ParaglideAsyncLocalStorage}\n */\nfunction createMockAsyncLocalStorage() {\n\t/** @type {any} */\n\tlet currentStore = undefined;\n\treturn {\n\t\tgetStore() {\n\t\t\treturn currentStore;\n\t\t},\n\t\tasync run(store, callback) {\n\t\t\tcurrentStore = store;\n\t\t\ttry {\n\t\t\t\treturn await callback();\n\t\t\t} finally {\n\t\t\t\tcurrentStore = undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// Used in generated server.js when async local storage is disabled.\nvoid createMockAsyncLocalStorage;\n\n/**\n * The compiled messages for the server middleware.\n *\n * Only populated if `enableMiddlewareOptimizations` is set to `true`.\n *\n * @type {Record<string, Record<import(\"./runtime.js\").Locale, string>>}\n */\nconst compiledBundles = {};\n"]}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/compiler/server/middleware.js"],"names":[],"mappings":"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","sourcesContent":["import * as runtime from \"./runtime.js\";\n\n/**\n * Server middleware that handles locale-based routing and request processing.\n *\n * Configure `disableAsyncLocalStorage` when generating Paraglide with\n * `paraglideVitePlugin()` or `compile()`, not when calling\n * `paraglideMiddleware()`. Keep AsyncLocalStorage enabled by default and\n * only disable it for runtimes that lack `AsyncLocalStorage` support and\n * guarantee request isolation.\n *\n * This middleware performs several key functions:\n *\n * 1. Determines the locale for the incoming request using configured strategies\n * 2. Handles URL localization and redirects (only for document requests by default)\n * 3. Maintains locale state using AsyncLocalStorage to prevent request interference\n *\n * When URL strategy is used:\n *\n * - The locale is extracted from the URL for all request types\n * - If URL doesn't match the determined locale, redirects to localized URL (only for document requests by default)\n * - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)\n *\n * @see https://paraglidejs.com/middleware\n *\n * @template T - The return type of the resolve function\n *\n * @param {Request} request - The incoming request object\n * @param {(args: { request: Request, locale: import(\"./runtime.js\").Locale }) => T | Promise<T>} resolve - Function to handle the request. The callback receives:\n * - `request`: A modified request with a delocalized URL when the URL strategy is used (e.g., `/fr/about` → `/about`).\n * If your framework handles URL localization itself (e.g., TanStack Router's `rewrite` option), use the original\n * request instead to avoid redirect loops.\n * - `locale`: The determined locale for this request.\n * @param {{\n * effectiveRequestUrl?: string | URL | ((request: Request) => string | URL),\n * redirect?: \"document\" | \"navigation\",\n * onRedirect?: (response: Response) => void\n * }} [options] - Options to control middleware behavior. `effectiveRequestUrl` sets the effective request URL used for route matching, URL-based locale detection, redirects, and `getUrlOrigin()`.\n * `redirect` defaults to `\"document\"`, which requires `Sec-Fetch-Dest: document`.\n * Unrecognized values keep that default behavior.\n * `\"navigation\"` only redirects GET/HEAD requests, accepting either that destination\n * or an absent destination with an explicit `Accept` header that allows `text/html`.\n * @returns {Promise<Response>}\n *\n * @example\n * ```typescript\n * // Basic usage in metaframeworks like NextJS, SvelteKit, Astro, Nuxt, etc.\n * export const handle = async ({ event, resolve }) => {\n * return paraglideMiddleware(event.request, ({ request, locale }) => {\n * // let the framework further resolve the request\n * return resolve(request);\n * });\n * };\n * ```\n *\n * @example\n * ```typescript\n * // Usage in a framework like Express JS or Hono\n * app.use(async (req, res, next) => {\n * const result = await paraglideMiddleware(req, ({ request, locale }) => {\n * // If a redirect happens this won't be called\n * return next(request);\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Usage with frameworks that handle URL localization/delocalization themselves\n * //\n * // Some frameworks like TanStack Router handle URL localization and delocalization\n * // themselves via their own rewrite APIs (e.g., `rewrite.input`/`rewrite.output`).\n * //\n * // When the framework handles this, the middleware's URL delocalization is not needed.\n * // Using the modified `request` from the callback would cause a redirect loop because\n * // both the middleware and the framework would attempt to delocalize the URL.\n * //\n * // Solution: Pass the original request to the handler instead of the modified one.\n * // The middleware still handles locale detection, cookies, and AsyncLocalStorage context.\n * //\n * // ❌ WRONG - causes redirect loop when framework handles URL rewriting:\n * // paraglideMiddleware(req, ({ request }) => handler.fetch(request))\n * //\n * // ✅ CORRECT - use original request when framework handles URL localization:\n * // paraglideMiddleware(req, () => handler.fetch(req))\n *\n * import { paraglideMiddleware } from './paraglide/server.js'\n * import handler from '@tanstack/react-start/server-entry'\n *\n * export default {\n * fetch(req: Request): Promise<Response> {\n * // TanStack Router handles URL rewriting via deLocalizeUrl/localizeUrl\n * // so we pass the original `req` instead of the modified `request`\n * return paraglideMiddleware(req, () => handler.fetch(req))\n * },\n * }\n * ```\n */\nexport async function paraglideMiddleware(request, resolve, options) {\n\tlet requestAsyncLocalStorage = runtime.serverAsyncLocalStorage;\n\t// %async-local-storage\n\tconst url = resolveMiddlewareUrl(request, options?.effectiveRequestUrl);\n\tconst origin = url.origin;\n\n\tif (runtime.isExcludedByRouteStrategy(url.href)) {\n\t\tconst locale = runtime.baseLocale;\n\t\tconst newRequest = cloneRequestWithFallback(request, url);\n\t\t/** @type {Set<string>} */\n\t\tconst messageCalls = new Set();\n\t\treturn /** @type {Response} */ (\n\t\t\tawait requestAsyncLocalStorage?.run(\n\t\t\t\t{ locale, origin, messageCalls },\n\t\t\t\t() => resolve({ locale, request: newRequest })\n\t\t\t)\n\t\t);\n\t}\n\n\tconst strategy = runtime.getStrategyForUrl(url.href);\n\tconst vary = getVaryFields(strategy);\n\tconst decision = await runtime.shouldRedirect({\n\t\trequest,\n\t\teffectiveRequestUrl: url,\n\t});\n\tconst locale = decision.locale;\n\t// Custom server strategies run before built-in strategies, regardless of order.\n\tconst hasCustomStrategy = strategy.some((strat) =>\n\t\tstrat.startsWith(\"custom-\")\n\t);\n\tconst urlDecidesLocale =\n\t\toptions?.redirect === \"navigation\" &&\n\t\tstrategy[0] === \"url\" &&\n\t\t!hasCustomStrategy &&\n\t\truntime.extractLocaleFromUrl(url) !== undefined;\n\tconst navigationVary =\n\t\toptions?.redirect === \"navigation\" ? [\"Accept\", \"Sec-Fetch-Dest\"] : [];\n\n\t// if the client makes a request to a URL that doesn't match\n\t// the localizedUrl, redirect the client to the localized URL\n\tif (\n\t\tshouldRedirectRequest(request, options?.redirect) &&\n\t\tdecision.shouldRedirect &&\n\t\tdecision.redirectUrl\n\t) {\n\t\t/** @type {Record<string, string>} */\n\t\tconst headers = {};\n\t\tconst redirectVary = [...(urlDecidesLocale ? [] : vary), ...navigationVary];\n\t\tif (redirectVary.length > 0) {\n\t\t\theaders[\"Vary\"] = redirectVary.join(\", \");\n\t\t}\n\n\t\tconst response = new Response(null, {\n\t\t\tstatus: 307,\n\t\t\theaders: {\n\t\t\t\tLocation: decision.redirectUrl.href,\n\t\t\t\t...headers,\n\t\t\t},\n\t\t});\n\n\t\toptions?.onRedirect?.(response);\n\t\treturn response;\n\t}\n\n\t// If the strategy includes \"url\", we need to de-localize the URL\n\t// before passing it to the server middleware.\n\t//\n\t// The middleware is responsible for mapping a localized URL to the\n\t// de-localized URL e.g. `/en/about` to `/about`. Otherwise,\n\t// the server can't render the correct page.\n\tlet newRequest;\n\tif (strategy.includes(\"url\")) {\n\t\tnewRequest = cloneRequestWithFallback(request, runtime.deLocalizeUrl(url));\n\t} else {\n\t\tnewRequest = cloneRequestWithFallback(request, url);\n\t}\n\n\t// the message functions that have been called in this request\n\t/** @type {Set<string>} */\n\tconst messageCalls = new Set();\n\n\tlet response = await requestAsyncLocalStorage?.run(\n\t\t{ locale, origin, messageCalls },\n\t\t() => resolve({ locale, request: newRequest })\n\t);\n\n\tif (response instanceof Response) {\n\t\tconst urlIndex = strategy.indexOf(\"url\");\n\t\tconst responseVary =\n\t\t\turlIndex !== -1 && !hasCustomStrategy && runtime.extractLocaleFromUrl(url)\n\t\t\t\t? getVaryFields(strategy.slice(0, urlIndex))\n\t\t\t\t: [...vary];\n\t\t// Classifying navigations can change a cached 200 into a redirect.\n\t\tif (\n\t\t\t(request.method === \"GET\" || request.method === \"HEAD\") &&\n\t\t\turlIndex !== -1 &&\n\t\t\t(!urlDecidesLocale || decision.shouldRedirect)\n\t\t) {\n\t\t\tresponseVary.push(...navigationVary);\n\t\t}\n\t\tresponse = withVary(response, responseVary);\n\t}\n\n\t// Only modify HTML responses\n\tif (\n\t\truntime.experimentalMiddlewareLocaleSplitting &&\n\t\ttypeof response?.headers?.get === \"function\" &&\n\t\ttypeof response.text === \"function\" &&\n\t\t!response.bodyUsed &&\n\t\t!response.body?.locked &&\n\t\tresponse.headers.get(\"Content-Type\")?.includes(\"html\")\n\t) {\n\t\tconst body = await response.text();\n\n\t\tconst messages = [];\n\t\t/** @type {Set<string>} */\n\t\tconst registryFunctionNames = new Set();\n\n\t\t// using .values() to avoid polyfilling in older projects. else the following error is thrown\n\t\t// Type 'Set<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.\n\t\tfor (const messageCall of Array.from(messageCalls)) {\n\t\t\tconst [id, locale] =\n\t\t\t\t/** @type {[string, import(\"./runtime.js\").Locale]} */ (\n\t\t\t\t\tmessageCall.split(\":\")\n\t\t\t\t);\n\t\t\tmessages.push(`${id}: ${compiledBundles[id]?.[locale]}`);\n\t\t\tfor (const name of compiledRegistry.messages[id]?.[locale] ?? []) {\n\t\t\t\tregistryFunctionNames.add(name);\n\t\t\t}\n\t\t}\n\n\t\t// The injected messages run without registry.js. Declare the registry\n\t\t// functions they call (including the ones those call) in a closure.\n\t\tlet ssr = `{ ${messages.join(\",\")} }`;\n\t\tif (registryFunctionNames.size > 0) {\n\t\t\tconst names = Array.from(registryFunctionNames);\n\t\t\tssr = `(() => { ${names\n\t\t\t\t.map((name) => compiledRegistry.functions[name])\n\t\t\t\t.join(\n\t\t\t\t\t\"\\n\"\n\t\t\t\t)}\\nconst registry = { ${names.join(\", \")} };\\nreturn ${ssr} })()`;\n\t\t}\n\n\t\t// Prevent translated content from terminating the inline script tag.\n\t\tconst escapedSsr = ssr.replace(/<\\/(script)/gi, \"<\\\\/$1\");\n\t\t// Reuse the request's CSP nonce (if any) so the injected script is allowed under a strict CSP\n\t\tconst nonce = response.headers\n\t\t\t.get(\"Content-Security-Policy\")\n\t\t\t?.match(/'nonce-([\\w+/=-]+)'/)?.[1];\n\t\tconst nonceAttr = nonce ? `nonce=\"${nonce}\"` : \"\";\n\t\tconst script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = ${escapedSsr}</script>`;\n\n\t\t// Insert the script before the closing head tag\n\t\tconst newBody = body.replace(\"</head>\", `${script}</head>`);\n\n\t\t// Create a new response with the modified body\n\t\t// Clone all headers except Content-Length which will be set automatically\n\t\tconst newHeaders = new Headers(response.headers);\n\t\tnewHeaders.delete(\"Content-Length\"); // Let the browser calculate the correct length\n\n\t\treturn new Response(newBody, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: newHeaders,\n\t\t});\n\t}\n\n\treturn response;\n}\n\n/**\n * @param {string[]} strategy\n * @returns {string[]}\n */\nfunction getVaryFields(strategy) {\n\t/** @type {string[]} */\n\tconst vary = [];\n\tif (strategy.includes(\"cookie\")) vary.push(\"Cookie\");\n\tif (strategy.includes(\"preferredLanguage\")) vary.push(\"Accept-Language\");\n\treturn vary;\n}\n\n/**\n * @param {Response} response\n * @param {string[]} vary\n * @returns {Response}\n */\nfunction withVary(response, vary) {\n\t// Network errors and protocol upgrades are not ordinary HTTP responses.\n\tif (response.status < 200 || response.status > 599) return response;\n\tconst existing = response.headers.get(\"Vary\");\n\tconst fields =\n\t\texisting?.split(\",\").map((field) => field.trim().toLowerCase()) ?? [];\n\tif (fields.includes(\"*\")) return response;\n\tconst missing = vary.filter((field) => !fields.includes(field.toLowerCase()));\n\tif (missing.length === 0) return response;\n\tconst value = [existing, ...missing].filter(Boolean).join(\", \");\n\n\ttry {\n\t\tresponse.headers.set(\"Vary\", value);\n\t\treturn response;\n\t} catch (error) {\n\t\tif (!(error instanceof TypeError)) throw error;\n\t}\n\n\t// Responses from fetch() or Response.redirect() can have immutable headers.\n\ttry {\n\t\t// Preserve runtime-specific response state, including Workers body encoding.\n\t\tconst copy = new Response(response.body, response);\n\t\tcopy.headers.set(\"Vary\", value);\n\t\treturn copyResponseMetadata(copy, response);\n\t} catch {\n\t\t// Keep callback responses whose body cannot be reused.\n\t\treturn response;\n\t}\n}\n\n/**\n * @param {Response} target\n * @param {Response} source\n * @returns {Response}\n */\nfunction copyResponseMetadata(target, source) {\n\t// ResponseInit omits fetch metadata, so clones need to retain it as well.\n\treturn Object.defineProperties(target, {\n\t\turl: { value: source.url, configurable: true },\n\t\tredirected: { value: source.redirected, configurable: true },\n\t\ttype: { value: source.type, configurable: true },\n\t\tclone: {\n\t\t\tconfigurable: true,\n\t\t\twritable: true,\n\t\t\t/** @this {Response} */\n\t\t\tvalue() {\n\t\t\t\treturn copyResponseMetadata(Response.prototype.clone.call(this), this);\n\t\t\t},\n\t\t},\n\t});\n}\n\n/**\n * @param {Request} request\n * @param {\"document\" | \"navigation\"} [redirect]\n * @returns {boolean}\n */\nfunction shouldRedirectRequest(request, redirect) {\n\tconst destination = request.headers.get(\"Sec-Fetch-Dest\");\n\tif (redirect !== \"navigation\") return destination === \"document\";\n\tif (request.method !== \"GET\" && request.method !== \"HEAD\") return false;\n\tif (destination !== null) return destination === \"document\";\n\n\tlet specificity = -1;\n\tlet quality = 0;\n\tfor (const range of splitHeaderValue(\n\t\trequest.headers.get(\"Accept\") ?? \"\",\n\t\t\",\"\n\t)) {\n\t\tconst [type, ...parameters] = splitHeaderValue(range, \";\").map((part) =>\n\t\t\tpart.trim().toLowerCase()\n\t\t);\n\t\tconst rangeSpecificity =\n\t\t\ttype === \"text/html\"\n\t\t\t\t? 2\n\t\t\t\t: type === \"text/*\"\n\t\t\t\t\t? 1\n\t\t\t\t\t: type === \"*/*\"\n\t\t\t\t\t\t? 0\n\t\t\t\t\t\t: -1;\n\t\tif (rangeSpecificity < 0 || rangeSpecificity < specificity) continue;\n\n\t\tconst weight = parameters.find((parameter) => /^q\\s*=/.test(parameter));\n\t\tconst value = weight ? weight.slice(weight.indexOf(\"=\") + 1).trim() : \"1\";\n\t\tconst rangeQuality = /^(?:0(?:\\.\\d{0,3})?|1(?:\\.0{0,3})?)$/.test(value)\n\t\t\t? Number(value)\n\t\t\t: 0;\n\t\t// A specific q=0 exclusion takes precedence over an acceptable wildcard.\n\t\tquality =\n\t\t\trangeSpecificity > specificity\n\t\t\t\t? rangeQuality\n\t\t\t\t: Math.max(quality, rangeQuality);\n\t\tspecificity = rangeSpecificity;\n\t}\n\treturn quality > 0;\n}\n\n/**\n * @param {string} value\n * @param {string} separator\n * @returns {string[]}\n */\nfunction splitHeaderValue(value, separator) {\n\tconst parts = [];\n\tlet start = 0;\n\tlet quoted = false;\n\tfor (let index = 0; index < value.length; index++) {\n\t\tconst character = value[index];\n\t\tif (quoted && character === \"\\\\\") {\n\t\t\tindex++;\n\t\t} else if (character === '\"') {\n\t\t\tquoted = !quoted;\n\t\t} else if (!quoted && character === separator) {\n\t\t\tparts.push(value.slice(start, index));\n\t\t\tstart = index + 1;\n\t\t}\n\t}\n\tif (quoted) return [];\n\tparts.push(value.slice(start));\n\treturn parts;\n}\n\n/**\n * @param {Request} request\n * @param {string | URL | ((request: Request) => string | URL) | undefined} effectiveRequestUrl\n * @returns {URL}\n */\nfunction resolveMiddlewareUrl(request, effectiveRequestUrl) {\n\tif (typeof effectiveRequestUrl === \"function\") {\n\t\treturn new URL(effectiveRequestUrl(request), request.url);\n\t}\n\n\tif (\n\t\ttypeof effectiveRequestUrl === \"string\" ||\n\t\teffectiveRequestUrl instanceof URL\n\t) {\n\t\treturn new URL(effectiveRequestUrl, request.url);\n\t}\n\n\treturn new URL(request.url);\n}\n\n/**\n * Some metaframeworks (NextJS) require a new Request object.\n * https://github.com/opral/inlang-paraglide-js/issues/411\n *\n * However, some frameworks (TanStack Start 1.143+) use custom Request\n * implementations that cannot be cloned with `new Request(request)`.\n * https://github.com/opral/paraglide-js/issues/573\n *\n * Effective request URL overrides behind proxies:\n * https://github.com/opral/paraglide-js/issues/652\n *\n * @param {Request} request\n * @param {string | URL} [url]\n * @returns {Request}\n */\nfunction cloneRequestWithFallback(request, url = request.url) {\n\tconst targetUrl = typeof url === \"string\" ? url : url.href;\n\tif (targetUrl === request.url) {\n\t\ttry {\n\t\t\t// Clone first so building a new Request does not consume the original body stream.\n\t\t\treturn new Request(request.clone());\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\treturn new Request(request);\n\t\t\t} catch {\n\t\t\t\treturn request;\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\t// Clone first so building a new Request does not consume the original body stream.\n\t\treturn new Request(targetUrl, request.clone());\n\t} catch {\n\t\ttry {\n\t\t\treturn new Request(targetUrl, request);\n\t\t} catch {\n\t\t\treturn request;\n\t\t}\n\t}\n}\n\n/**\n * Creates a mock AsyncLocalStorage implementation for environments where\n * native AsyncLocalStorage is not available or disabled.\n *\n * This mock implementation mimics the behavior of the native AsyncLocalStorage\n * but doesn't require the async_hooks module. It's used as a fallback when\n * the runtime does not expose AsyncLocalStorage or when it has been disabled.\n *\n * @returns {import(\"./runtime.js\").ParaglideAsyncLocalStorage}\n */\nfunction createMockAsyncLocalStorage() {\n\t/** @type {any} */\n\tlet currentStore = undefined;\n\treturn {\n\t\tgetStore() {\n\t\t\treturn currentStore;\n\t\t},\n\t\tasync run(store, callback) {\n\t\t\tcurrentStore = store;\n\t\t\ttry {\n\t\t\t\treturn await callback();\n\t\t\t} finally {\n\t\t\t\tcurrentStore = undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// Used in generated server.js when async local storage is disabled.\nvoid createMockAsyncLocalStorage;\n\n/**\n * The compiled messages for the server middleware.\n *\n * Only populated if `enableMiddlewareOptimizations` is set to `true`.\n *\n * @type {Record<string, Record<import(\"./runtime.js\").Locale, string>>}\n */\nconst compiledBundles = {};\n\n/**\n * The registry functions the compiled messages call, for the injected\n * messages that run without registry.js.\n *\n * `messages[id][locale]` lists the registry functions a message calls,\n * including the ones those call. `functions[name]` is the code of a registry\n * function.\n *\n * Only populated if `enableMiddlewareOptimizations` is set to `true`.\n *\n * @type {{ functions: Record<string, string>, messages: Record<string, Record<string, string[]>> }}\n */\nconst compiledRegistry = { functions: {}, messages: {} };\n"]}