@inlang/paraglide-js 2.25.4 → 2.27.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 (124) hide show
  1. package/README.md +2 -1
  2. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +2 -2
  3. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
  4. package/dist/cli/commands/init/command.js +19 -1
  5. package/dist/cli/commands/init/command.js.map +1 -1
  6. package/dist/cli/defaults.js +2 -2
  7. package/dist/cli/defaults.js.map +1 -1
  8. package/dist/cli/steps/add-inlang-check.d.ts +19 -0
  9. package/dist/cli/steps/add-inlang-check.js +60 -0
  10. package/dist/cli/steps/add-inlang-check.js.map +1 -0
  11. package/dist/cli/steps/add-inlang-check.test.d.ts +1 -0
  12. package/dist/cli/steps/add-inlang-check.test.js +88 -0
  13. package/dist/cli/steps/add-inlang-check.test.js.map +1 -0
  14. package/dist/cli/steps/agents-md-suggestion.d.ts +11 -0
  15. package/dist/cli/steps/agents-md-suggestion.js +19 -0
  16. package/dist/cli/steps/agents-md-suggestion.js.map +1 -0
  17. package/dist/cli/steps/agents-md-suggestion.test.d.ts +1 -0
  18. package/dist/cli/steps/agents-md-suggestion.test.js +36 -0
  19. package/dist/cli/steps/agents-md-suggestion.test.js.map +1 -0
  20. package/dist/cli/steps/maybe-add-machine-translation.js +3 -2
  21. package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
  22. package/dist/cli/steps/maybe-add-sherlock.js +1 -1
  23. package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
  24. package/dist/cli/utils.d.ts +9 -0
  25. package/dist/cli/utils.js +15 -0
  26. package/dist/cli/utils.js.map +1 -1
  27. package/dist/compiler/compile-annotation.d.ts +48 -1
  28. package/dist/compiler/compile-annotation.js +238 -10
  29. package/dist/compiler/compile-annotation.js.map +1 -1
  30. package/dist/compiler/compile-bundle.d.ts +3 -2
  31. package/dist/compiler/compile-bundle.js +30 -1
  32. package/dist/compiler/compile-bundle.js.map +1 -1
  33. package/dist/compiler/compile-bundle.test.js +18 -18
  34. package/dist/compiler/compile-bundle.test.js.map +1 -1
  35. package/dist/compiler/compile-local-variable.d.ts +3 -0
  36. package/dist/compiler/compile-local-variable.js +5 -2
  37. package/dist/compiler/compile-local-variable.js.map +1 -1
  38. package/dist/compiler/compile-local-variable.test.js +44 -4
  39. package/dist/compiler/compile-local-variable.test.js.map +1 -1
  40. package/dist/compiler/compile-message.d.ts +29 -1
  41. package/dist/compiler/compile-message.exact-number.test.d.ts +1 -0
  42. package/dist/compiler/compile-message.exact-number.test.js +786 -0
  43. package/dist/compiler/compile-message.exact-number.test.js.map +1 -0
  44. package/dist/compiler/compile-message.js +162 -66
  45. package/dist/compiler/compile-message.js.map +1 -1
  46. package/dist/compiler/compile-message.locals.test.d.ts +1 -0
  47. package/dist/compiler/compile-message.locals.test.js +498 -0
  48. package/dist/compiler/compile-message.locals.test.js.map +1 -0
  49. package/dist/compiler/compile-message.test.js +111 -20
  50. package/dist/compiler/compile-message.test.js.map +1 -1
  51. package/dist/compiler/compile-pattern.d.ts +5 -0
  52. package/dist/compiler/compile-pattern.js +6 -18
  53. package/dist/compiler/compile-pattern.js.map +1 -1
  54. package/dist/compiler/compile-pattern.test.js +165 -1
  55. package/dist/compiler/compile-pattern.test.js.map +1 -1
  56. package/dist/compiler/compile-project.js +4 -1
  57. package/dist/compiler/compile-project.js.map +1 -1
  58. package/dist/compiler/compile-project.test.js +1013 -31
  59. package/dist/compiler/compile-project.test.js.map +1 -1
  60. package/dist/compiler/compile.test.js +1 -1
  61. package/dist/compiler/compile.test.js.map +1 -1
  62. package/dist/compiler/create-readme.d.ts +4 -1
  63. package/dist/compiler/create-readme.js +33 -125
  64. package/dist/compiler/create-readme.js.map +1 -1
  65. package/dist/compiler/emit-ts-declarations.interop.test.js +2 -2
  66. package/dist/compiler/emit-ts-declarations.interop.test.js.map +1 -1
  67. package/dist/compiler/emit-ts-declarations.test.js +4 -4
  68. package/dist/compiler/emit-ts-declarations.test.js.map +1 -1
  69. package/dist/compiler/index.d.ts +1 -1
  70. package/dist/compiler/index.js +1 -1
  71. package/dist/compiler/index.js.map +1 -1
  72. package/dist/compiler/input-alias.d.ts +21 -0
  73. package/dist/compiler/input-alias.js +42 -0
  74. package/dist/compiler/input-alias.js.map +1 -0
  75. package/dist/compiler/input-alias.test.d.ts +1 -0
  76. package/dist/compiler/input-alias.test.js +58 -0
  77. package/dist/compiler/input-alias.test.js.map +1 -0
  78. package/dist/compiler/message-locals.d.ts +46 -0
  79. package/dist/compiler/message-locals.js +129 -0
  80. package/dist/compiler/message-locals.js.map +1 -0
  81. package/dist/compiler/output-structure/locale-modules.js +7 -1
  82. package/dist/compiler/output-structure/locale-modules.js.map +1 -1
  83. package/dist/compiler/output-structure/locale-modules.test.js +35 -0
  84. package/dist/compiler/output-structure/locale-modules.test.js.map +1 -1
  85. package/dist/compiler/output-structure/message-modules.js +5 -3
  86. package/dist/compiler/output-structure/message-modules.js.map +1 -1
  87. package/dist/compiler/output-structure/message-modules.test.js +35 -0
  88. package/dist/compiler/output-structure/message-modules.test.js.map +1 -1
  89. package/dist/compiler/registry.d.ts +12 -0
  90. package/dist/compiler/registry.js +97 -28
  91. package/dist/compiler/registry.js.map +1 -1
  92. package/dist/compiler/runtime/create-runtime.js +24 -1
  93. package/dist/compiler/runtime/create-runtime.js.map +1 -1
  94. package/dist/compiler/runtime/extract-locale-from-url.js +11 -4
  95. package/dist/compiler/runtime/extract-locale-from-url.js.map +1 -1
  96. package/dist/compiler/runtime/generate-static-localized-urls.js +5 -3
  97. package/dist/compiler/runtime/generate-static-localized-urls.js.map +1 -1
  98. package/dist/compiler/runtime/localize-url.js +25 -54
  99. package/dist/compiler/runtime/localize-url.js.map +1 -1
  100. package/dist/compiler/runtime/route-strategy.js +9 -3
  101. package/dist/compiler/runtime/route-strategy.js.map +1 -1
  102. package/dist/compiler/runtime/type.test.js +9 -0
  103. package/dist/compiler/runtime/type.test.js.map +1 -1
  104. package/dist/compiler/runtime/url-pattern-cache.d.ts +11 -0
  105. package/dist/compiler/runtime/url-pattern-cache.js +42 -0
  106. package/dist/compiler/runtime/url-pattern-cache.js.map +1 -0
  107. package/dist/compiler/runtime/url-pattern-index.d.ts +24 -0
  108. package/dist/compiler/runtime/url-pattern-index.differential.test.d.ts +1 -0
  109. package/dist/compiler/runtime/url-pattern-index.differential.test.js +152 -0
  110. package/dist/compiler/runtime/url-pattern-index.differential.test.js.map +1 -0
  111. package/dist/compiler/runtime/url-pattern-index.js +168 -0
  112. package/dist/compiler/runtime/url-pattern-index.js.map +1 -0
  113. package/dist/compiler/runtime/url-pattern-index.test.d.ts +1 -0
  114. package/dist/compiler/runtime/url-pattern-index.test.js +262 -0
  115. package/dist/compiler/runtime/url-pattern-index.test.js.map +1 -0
  116. package/dist/compiler/server/create-server-file.js +25 -1
  117. package/dist/compiler/server/create-server-file.js.map +1 -1
  118. package/dist/compiler/server/create-server-file.test.js +20 -2
  119. package/dist/compiler/server/create-server-file.test.js.map +1 -1
  120. package/dist/compiler/server/middleware.js +29 -4
  121. package/dist/compiler/server/middleware.js.map +1 -1
  122. package/dist/services/env-variables/index.js +1 -1
  123. package/dist/services/env-variables/index.js.map +1 -1
  124. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-pattern-index.test.js","sourceRoot":"","sources":["../../../src/compiler/runtime/url-pattern-index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, test } from \"vitest\";\nimport { URLPattern as PolyfillURLPattern } from \"urlpattern-polyfill\";\nimport { createParaglide } from \"../create-paraglide.js\";\nimport type { CompilerOptions } from \"../compiler-options.js\";\nimport { newProject } from \"@inlang/sdk\";\n\ntype PatternCtor = typeof URLPattern;\n\nconst nativeURLPattern = Reflect.get(globalThis, \"URLPattern\") as\n\t| PatternCtor\n\t| undefined;\nconst engines: Array<[string, PatternCtor]> = [];\nlet runtimeModuleNonce = 0;\nif (\n\ttypeof nativeURLPattern === \"function\" &&\n\tnativeURLPattern !== PolyfillURLPattern\n) {\n\tengines.push([\"native\", nativeURLPattern]);\n}\nengines.push([\"polyfill\", PolyfillURLPattern as unknown as PatternCtor]);\n\nasync function withURLPattern<T>(ctor: PatternCtor, fn: () => Promise<T>) {\n\tconst descriptor = Object.getOwnPropertyDescriptor(globalThis, \"URLPattern\");\n\tObject.defineProperty(globalThis, \"URLPattern\", {\n\t\tconfigurable: true,\n\t\twritable: true,\n\t\tvalue: ctor,\n\t});\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\tif (descriptor) {\n\t\t\tObject.defineProperty(globalThis, \"URLPattern\", descriptor);\n\t\t} else {\n\t\t\tReflect.deleteProperty(globalThis, \"URLPattern\");\n\t\t}\n\t}\n}\n\nasync function withRuntime(\n\toptions: {\n\t\turlPatterns: Array<{\n\t\t\tpattern: string;\n\t\t\tlocalized: Array<[string, string]>;\n\t\t}>;\n\t\trouteStrategies?: CompilerOptions[\"routeStrategies\"];\n\t\ttrailingSlash?: \"always\" | \"never\";\n\t},\n\tctor: PatternCtor,\n\tfn: (runtime: Awaited<ReturnType<typeof createParaglide>>) => Promise<void>\n) {\n\treturn withURLPattern(ctor, async () =>\n\t\tfn(\n\t\t\tawait createParaglide({\n\t\t\t\tblob: await newProject({\n\t\t\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t\t\t}),\n\t\t\t\tcookieName: `pattern-index-test-${runtimeModuleNonce++}`,\n\t\t\t\tstrategy: [\"url\", \"baseLocale\"],\n\t\t\t\t...options,\n\t\t\t})\n\t\t)\n\t);\n}\n\nfor (const [engineName, ctor] of engines) {\n\ttest(`${engineName} URLPattern keeps ordered routing and URL parts`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/specific-path\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/specific-path\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/404\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/:path(.*)?\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/:path(.*)?\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/:path(.*)?\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\trouteStrategies: [\n\t\t\t\t\t{ match: \"/specific-path\", exclude: true },\n\t\t\t\t\t{ match: \"/:path(.*)?\", strategy: [\"url\"] },\n\t\t\t\t],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\tconst input =\n\t\t\t\t\t\"https://alice:secret@example.com/specific-path?redirect=%2Faccount#section\";\n\t\t\t\texpect(runtime.localizeUrl(input, { locale: \"de\" }).href).toBe(\n\t\t\t\t\t\"https://alice:secret@example.com/de/404?redirect=%2Faccount#section\"\n\t\t\t\t);\n\t\t\t\texpect(\n\t\t\t\t\truntime.deLocalizeUrl(\n\t\t\t\t\t\t\"https://alice:secret@example.com/de/404?redirect=%2Faccount#section\"\n\t\t\t\t\t).href\n\t\t\t\t).toBe(\n\t\t\t\t\t\"https://alice:secret@example.com/specific-path?redirect=%2Faccount#section\"\n\t\t\t\t);\n\t\t\t\texpect(runtime.extractLocaleFromUrl(input)).toBe(\"en\");\n\t\t\t\texpect(\n\t\t\t\t\truntime.isExcludedByRouteStrategy(\"https://example.com/specific-path\")\n\t\t\t\t).toBe(true);\n\t\t\t\texpect(runtime.getStrategyForUrl(\"https://example.com/other\")).toEqual([\n\t\t\t\t\t\"url\",\n\t\t\t\t]);\n\t\t\t\texpect(\n\t\t\t\t\truntime\n\t\t\t\t\t\t.generateStaticLocalizedUrls([\"https://example.com/specific-path\"])\n\t\t\t\t\t\t.map((url) => url.href)\n\t\t\t\t).toEqual([\n\t\t\t\t\t\"https://example.com/specific-path\",\n\t\t\t\t\t\"https://example.com/de/404\",\n\t\t\t\t]);\n\t\t\t}\n\t\t);\n\t});\n\n\ttest(`${engineName} URLPattern refreshes ordered indexes and same-URL caches after edits`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/:path(.*)?\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/:path(.*)?\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/:path(.*)?\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\trouteStrategies: [{ match: \"/old/:slug\", exclude: true }],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\tconst url = \"https://example.com/old/story\";\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(\"en\");\n\t\t\t\texpect(runtime.localizeUrl(url, { locale: \"de\" }).pathname).toBe(\n\t\t\t\t\t\"/de/old/story\"\n\t\t\t\t);\n\t\t\t\texpect(runtime.isExcludedByRouteStrategy(url)).toBe(true);\n\n\t\t\t\tconst pattern = runtime.urlPatterns[0]! as {\n\t\t\t\t\tpattern: string;\n\t\t\t\t\tlocalized: Array<[string, string]>;\n\t\t\t\t};\n\t\t\t\tpattern.pattern = \"/new/:path(.*)?\";\n\t\t\t\tpattern.localized[0]![1] = \"/new/:path(.*)?\";\n\t\t\t\tpattern.localized[1]![1] = \"/de/new/:path(.*)?\";\n\t\t\t\t(runtime.routeStrategies[0] as { match: string }).match = \"/new/:slug\";\n\n\t\t\t\t// Reuse the exact href so both one-entry result caches must notice\n\t\t\t\t// the config version change and the fast-path parse must be refreshed.\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(undefined);\n\t\t\t\texpect(runtime.localizeUrl(url, { locale: \"de\" }).href).toBe(url);\n\t\t\t\texpect(runtime.isExcludedByRouteStrategy(url)).toBe(false);\n\t\t\t\texpect(\n\t\t\t\t\truntime.localizeUrl(\"https://example.com/new/story\", { locale: \"de\" })\n\t\t\t\t\t\t.pathname\n\t\t\t\t).toBe(\"/de/new/story\");\n\t\t\t}\n\t\t);\n\t});\n\n\ttest(`${engineName} URLPattern refreshes warmed winners after collection and reference edits`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/same/:slug\",\n\t\t\t\t\t\tlocalized: [[\"de\", \"/same/:slug\"]],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\trouteStrategies: [{ match: \"/same/:slug\", strategy: [\"url\"] }],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\tconst url = \"https://example.com/same/story\";\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(\"de\");\n\t\t\t\texpect(runtime.getStrategyForUrl(url)).toEqual([\"url\"]);\n\n\t\t\t\t// A pushed earlier pattern changes the extraction winner. Splicing it\n\t\t\t\t// back out must restore the original winner on this same cached URL.\n\t\t\t\t(\n\t\t\t\t\truntime.urlPatterns as Array<{\n\t\t\t\t\t\tpattern: string;\n\t\t\t\t\t\tlocalized: Array<[string, string]>;\n\t\t\t\t\t}>\n\t\t\t\t).unshift({\n\t\t\t\t\tpattern: \"/same/:slug\",\n\t\t\t\t\tlocalized: [[\"en\", \"/same/:slug\"]],\n\t\t\t\t});\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(\"en\");\n\t\t\t\truntime.urlPatterns.splice(0, 1);\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(\"de\");\n\n\t\t\t\t// Replacing the localized array and its locale string changes the\n\t\t\t\t// first matching locale even though its pattern text is unchanged.\n\t\t\t\tconst entry = runtime.urlPatterns[0]!;\n\t\t\t\tentry.localized = [[\"en\", \"/same/:slug\"]];\n\t\t\t\texpect(runtime.extractLocaleFromUrl(url)).toBe(\"en\");\n\n\t\t\t\t// Replacing a strategy object with the same match string must refresh\n\t\t\t\t// the warmed rule result as well as the candidate index snapshot.\n\t\t\t\truntime.routeStrategies[0] = {\n\t\t\t\t\tmatch: \"/same/:slug\",\n\t\t\t\t\tstrategy: [\"baseLocale\"],\n\t\t\t\t};\n\t\t\t\texpect(runtime.getStrategyForUrl(url)).toEqual([\"baseLocale\"]);\n\t\t\t}\n\t\t);\n\t});\n\n\ttest(`${engineName} URLPattern keeps invalid-pattern errors ahead of later matches`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{ pattern: \"/broken/:id(\", localized: [] },\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/valid/:id\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/valid/:id\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/valid/:id\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\texpect(() =>\n\t\t\t\t\truntime.localizeUrl(\"https://example.com/valid/7\", { locale: \"de\" })\n\t\t\t\t).toThrow();\n\t\t\t}\n\t\t);\n\t});\n\n\ttest(`${engineName} URLPattern keeps malformed localized entries unconditional`, async () => {\n\t\tawait withRuntime({ urlPatterns: [] }, ctor, async (runtime) => {\n\t\t\t(\n\t\t\t\truntime.urlPatterns as unknown as Array<{\n\t\t\t\t\tpattern: string;\n\t\t\t\t\tlocalized: Array<[string, string]>;\n\t\t\t\t}>\n\t\t\t).push({\n\t\t\t\tpattern: \"/unrelated/:slug\",\n\t\t\t\tlocalized: [null as unknown as [string, string]],\n\t\t\t});\n\n\t\t\t// This route cannot be pruned by its path prefix: the original generic\n\t\t\t// scan would encounter the malformed localized entry and throw.\n\t\t\texpect(() =>\n\t\t\t\truntime.localizeUrl(\"https://example.com/elsewhere\", { locale: \"de\" })\n\t\t\t).toThrow();\n\t\t});\n\t});\n\n\ttest(`${engineName} URLPattern preserves trailing-slash alias captures`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\ttrailingSlash: \"always\",\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/:path(.*)\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/:path(.*)\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/:path(.*)/details\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\texpect(\n\t\t\t\t\truntime.localizeUrl(\"https://example.com/foo\", { locale: \"de\" }).href\n\t\t\t\t).toBe(\"https://example.com/de/foo/details/\");\n\t\t\t}\n\t\t);\n\t});\n\n\ttest(`${engineName} URLPattern keeps file-host bases separate`, async () => {\n\t\tawait withRuntime(\n\t\t\t{\n\t\t\t\turlPatterns: [\n\t\t\t\t\t{\n\t\t\t\t\t\tpattern: \"/section/:slug\",\n\t\t\t\t\t\tlocalized: [\n\t\t\t\t\t\t\t[\"en\", \"/section/:slug\"],\n\t\t\t\t\t\t\t[\"de\", \"/de/section/:slug\"],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\trouteStrategies: [{ match: \"/section/:slug\", exclude: true }],\n\t\t\t},\n\t\t\tctor,\n\t\t\tasync (runtime) => {\n\t\t\t\tconst first = new URL(\"file://server-one/section/story\");\n\t\t\t\tconst second = new URL(\"file://server-two/section/story\");\n\t\t\t\texpect(runtime.extractLocaleFromUrl(first)).toBe(\"en\");\n\t\t\t\texpect(runtime.extractLocaleFromUrl(second)).toBe(\"en\");\n\t\t\t\t// Policy matching uses url.origin (\"null\" for both file hosts) as a\n\t\t\t\t// URLPattern base and therefore retains the preexisting Invalid URL\n\t\t\t\t// error. The locale extraction above exercises cache isolation safely.\n\t\t\t}\n\t\t);\n\t});\n}\n\nfor (const [engineName, ctor] of engines) {\n\ttest(`${engineName} URLPattern avoids unrelated late-route scans across APIs`, async () => {\n\t\tlet constructions = 0;\n\t\tlet executions = 0;\n\t\tclass CountingURLPattern extends ctor {\n\t\t\tconstructor(pattern?: string | URLPatternInit, baseURL?: string | URL) {\n\t\t\t\tif (baseURL === undefined) super(pattern as string | URLPatternInit);\n\t\t\t\telse super(pattern as string | URLPatternInit, String(baseURL));\n\t\t\t\tconstructions++;\n\t\t\t}\n\n\t\t\toverride exec(input: string | URL, baseURL?: string) {\n\t\t\t\texecutions++;\n\t\t\t\treturn baseURL === undefined\n\t\t\t\t\t? super.exec(input)\n\t\t\t\t\t: super.exec(input, baseURL);\n\t\t\t}\n\t\t}\n\n\t\tconst urlPatterns = Array.from({ length: 67 }, (_, index) => ({\n\t\t\tpattern: `/route${index}/:slug`,\n\t\t\tlocalized: [\n\t\t\t\t[\"en\", `/route${index}/:slug`] as [string, string],\n\t\t\t\t[\"de\", `/de/route${index}/:slug`] as [string, string],\n\t\t\t],\n\t\t}));\n\t\tconst routeStrategies = Array.from({ length: 67 }, (_, index) => ({\n\t\t\tmatch: `/route${index}/:slug`,\n\t\t\texclude: true as const,\n\t\t}));\n\n\t\tawait withRuntime(\n\t\t\t{ urlPatterns, routeStrategies },\n\t\t\tCountingURLPattern as unknown as PatternCtor,\n\t\t\tasync (runtime) => {\n\t\t\t\texpect(\n\t\t\t\t\truntime.localizeUrl(\"https://example.com/route66/story\", {\n\t\t\t\t\t\tlocale: \"de\",\n\t\t\t\t\t}).pathname\n\t\t\t\t).toBe(\"/de/route66/story\");\n\t\t\t\texpect(\n\t\t\t\t\truntime.deLocalizeUrl(\"https://example.com/de/route66/story\").pathname\n\t\t\t\t).toBe(\"/route66/story\");\n\t\t\t\texpect(\n\t\t\t\t\truntime.extractLocaleFromUrl(\"https://example.com/de/route66/story\")\n\t\t\t\t).toBe(\"de\");\n\t\t\t\texpect(\n\t\t\t\t\truntime.isExcludedByRouteStrategy(\"https://example.com/route66/story\")\n\t\t\t\t).toBe(true);\n\t\t\t\texpect(\n\t\t\t\t\truntime\n\t\t\t\t\t\t.generateStaticLocalizedUrls([\"https://example.com/route66/story\"])\n\t\t\t\t\t\t.map((url) => url.pathname)\n\t\t\t\t).toEqual([\"/route66/story\", \"/de/route66/story\"]);\n\n\t\t\t\t// Includes createParaglide's capability probe. URLPattern work across\n\t\t\t\t// five APIs stays proportional to the few matching patterns, not 67.\n\t\t\t\texpect(constructions).toBeLessThanOrEqual(4);\n\t\t\t\texpect(executions).toBeLessThanOrEqual(20);\n\t\t\t}\n\t\t);\n\t});\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import { toSafeModuleId } from "../safe-module-id.js";
3
+ import { registryFunctionCode, withRegistryDependencies } from "../registry.js";
3
4
  /**
4
5
  * Returns the code for the `runtime.js` module
5
6
  */
@@ -57,6 +58,7 @@ ${injectCode("./middleware.js")}
57
58
  // corrupting the generated server file. A function's return value is
58
59
  // used literally, with no pattern expansion.
59
60
  code = code.replace("const compiledBundles = {};", () => `const compiledBundles = ${JSON.stringify(createCompiledMessagesObject(args.compiledBundles))};`);
61
+ code = code.replace("const compiledRegistry = { functions: {}, messages: {} };", () => `const compiledRegistry = ${JSON.stringify(createCompiledRegistryObject(args.compiledBundles))};`);
60
62
  }
61
63
  return code.replace(/\t/g, " ");
62
64
  }
@@ -81,6 +83,28 @@ function createCompiledMessagesObject(compiledBundles) {
81
83
  }
82
84
  return result;
83
85
  }
86
+ /**
87
+ * The registry functions each compiled message calls, and their code, for
88
+ * the messages the middleware injects into the page. Those run without
89
+ * registry.js.
90
+ */
91
+ function createCompiledRegistryObject(compiledBundles) {
92
+ const messages = {};
93
+ const used = new Set();
94
+ for (const compiledBundle of compiledBundles) {
95
+ const safeModuleId = toSafeModuleId(compiledBundle.bundle.node.id);
96
+ for (const [locale, compiledMessage] of Object.entries(compiledBundle.messages)) {
97
+ const names = withRegistryDependencies(compiledMessage.registryFunctions);
98
+ if (names.length === 0)
99
+ continue;
100
+ messages[safeModuleId] ??= {};
101
+ messages[safeModuleId][locale] = names;
102
+ for (const name of names)
103
+ used.add(name);
104
+ }
105
+ }
106
+ return { functions: registryFunctionCode(used), messages };
107
+ }
84
108
  /**
85
109
  * Load a file from the current directory.
86
110
  *
@@ -93,7 +117,7 @@ function createCompiledMessagesObject(compiledBundles) {
93
117
  function injectCode(path) {
94
118
  const code = fs.readFileSync(new URL(path, import.meta.url), "utf-8");
95
119
  // Regex to match single-line and multi-line imports
96
- const importRegex = /import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?/g;
120
+ const importRegex = /^\s*import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?/gm;
97
121
  const sourceMapRegex = /\/\/# sourceMappingURL=.*$/gm;
98
122
  const blockSourceMapRegex = /\/\*# sourceMappingURL=.*?\*\//g;
99
123
  return code
@@ -1 +1 @@
1
- {"version":3,"file":"create-server-file.js","sourceRoot":"","sources":["../../../src/compiler/server/create-server-file.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport type { CompilerOptions } from \"../compiler-options.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport type { Locale } from \"./runtime.d.ts\";\n\n/**\n * Returns the code for the `runtime.js` module\n */\nexport function createServerFile(args: {\n\tcompiledBundles: CompiledBundleWithMessages[];\n\tcompilerOptions: {\n\t\texperimentalMiddlewareLocaleSplitting: NonNullable<\n\t\t\tCompilerOptions[\"experimentalMiddlewareLocaleSplitting\"]\n\t\t>;\n\t\tdisableAsyncLocalStorage: NonNullable<\n\t\t\tCompilerOptions[\"disableAsyncLocalStorage\"]\n\t\t>;\n\t};\n}): string {\n\tlet code = `\nimport * as runtime from \"./runtime.js\";\n\n${injectCode(\"./middleware.js\")}\n`;\n\n\tconst asyncLocalStorageMarker = \"// %async-local-storage\";\n\tconst markerIndex = code.indexOf(asyncLocalStorageMarker);\n\tif (markerIndex === -1) {\n\t\tthrow new Error(\n\t\t\t\"Expected a single %async-local-storage marker in server middleware.\"\n\t\t);\n\t}\n\n\tconst lineStart = code.lastIndexOf(\"\\n\", markerIndex) + 1;\n\tconst indent = code.slice(lineStart, markerIndex).replace(/\\t/g, \" \");\n\tconst innerIndent = `${indent} `;\n\tconst asyncLocalStorageBlock = args.compilerOptions.disableAsyncLocalStorage\n\t\t? [\n\t\t\t\t`${indent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${indent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = createMockAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${indent}}`,\n\t\t\t]\n\t\t: [\n\t\t\t\t`${indent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${indent}if (!runtime.disableAsyncLocalStorage && !requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}const { AsyncLocalStorage } = await import(\"async_hooks\");`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent} requestAsyncLocalStorage = new AsyncLocalStorage();`,\n\t\t\t\t`${innerIndent} runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${innerIndent}}`,\n\t\t\t\t`${indent}}`,\n\t\t\t\t`${indent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = createMockAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${indent}}`,\n\t\t\t];\n\n\tconst lineEnd = code.indexOf(\"\\n\", markerIndex);\n\tconst endOfMarkerLine = lineEnd === -1 ? code.length : lineEnd + 1;\n\n\tcode =\n\t\tcode.slice(0, lineStart) +\n\t\t`${asyncLocalStorageBlock.join(\"\\n\")}\\n` +\n\t\tcode.slice(endOfMarkerLine);\n\n\tif (args.compilerOptions.experimentalMiddlewareLocaleSplitting) {\n\t\t// Use a replacer function, not a replacement string. `String.replace()`\n\t\t// treats a string replacement as a pattern where `$&`, `` $` ``, `$'`,\n\t\t// `$$`, and `$<name>` have special meaning. A translated message value\n\t\t// that contains a literal `$` (a price, a currency symbol) can produce\n\t\t// one of these sequences inside the JSON payload, which `String.replace`\n\t\t// then expands - e.g. `` $` `` is replaced with \"everything before the\n\t\t// match\", splicing the file's own header into the string being built and\n\t\t// corrupting the generated server file. A function's return value is\n\t\t// used literally, with no pattern expansion.\n\t\tcode = code.replace(\n\t\t\t\"const compiledBundles = {};\",\n\t\t\t() =>\n\t\t\t\t`const compiledBundles = ${JSON.stringify(createCompiledMessagesObject(args.compiledBundles))};`\n\t\t);\n\t}\n\n\treturn code.replace(/\\t/g, \" \");\n}\n\nfunction createCompiledMessagesObject(\n\tcompiledBundles: CompiledBundleWithMessages[]\n): Record<string, Record<Locale, string>> {\n\tconst result = {} as Record<string, Record<Locale, string>>;\n\n\tfor (const compiledBundle of compiledBundles) {\n\t\tconst bundleId = compiledBundle.bundle.node.id;\n\t\tconst safeModuleId = toSafeModuleId(bundleId);\n\t\t// Key by the safe module id, not the raw bundle id: trackMessageCall()\n\t\t// records calls under safeModuleId, the client reads\n\t\t// globalThis.__paraglide.ssr[safeModuleId], and middleware.js looks up\n\t\t// compiledBundles[id] with that same safe id. Keying by the raw\n\t\t// bundleId here made every split-mode lookup miss.\n\t\tif (result[safeModuleId] === undefined) {\n\t\t\tresult[safeModuleId] = {};\n\t\t}\n\t\tfor (const [locale, compiledMessage] of Object.entries(\n\t\t\tcompiledBundle.messages\n\t\t)) {\n\t\t\tresult[safeModuleId][locale] = compiledMessage.code\n\t\t\t\t.replace(`export const ${safeModuleId} = `, \"\")\n\t\t\t\t.replace(/;$/, \"\");\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Load a file from the current directory.\n *\n * Prunes the imports on top of the file as the runtime is\n * self-contained.\n *\n * @param {string} path\n * @returns {string}\n */\nfunction injectCode(path: string): string {\n\tconst code = fs.readFileSync(new URL(path, import.meta.url), \"utf-8\");\n\t// Regex to match single-line and multi-line imports\n\tconst importRegex = /import\\s+[\\s\\S]*?from\\s+['\"][^'\"]+['\"]\\s*;?/g;\n\tconst sourceMapRegex = /\\/\\/# sourceMappingURL=.*$/gm;\n\tconst blockSourceMapRegex = /\\/\\*# sourceMappingURL=.*?\\*\\//g;\n\treturn code\n\t\t.replace(importRegex, \"\")\n\t\t.replace(sourceMapRegex, \"\")\n\t\t.replace(blockSourceMapRegex, \"\")\n\t\t.trim();\n}\n"]}
1
+ {"version":3,"file":"create-server-file.js","sourceRoot":"","sources":["../../../src/compiler/server/create-server-file.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport type { CompilerOptions } from \"../compiler-options.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport type { Locale } from \"./runtime.d.ts\";\nimport { registryFunctionCode, withRegistryDependencies } from \"../registry.js\";\n\n/**\n * Returns the code for the `runtime.js` module\n */\nexport function createServerFile(args: {\n\tcompiledBundles: CompiledBundleWithMessages[];\n\tcompilerOptions: {\n\t\texperimentalMiddlewareLocaleSplitting: NonNullable<\n\t\t\tCompilerOptions[\"experimentalMiddlewareLocaleSplitting\"]\n\t\t>;\n\t\tdisableAsyncLocalStorage: NonNullable<\n\t\t\tCompilerOptions[\"disableAsyncLocalStorage\"]\n\t\t>;\n\t};\n}): string {\n\tlet code = `\nimport * as runtime from \"./runtime.js\";\n\n${injectCode(\"./middleware.js\")}\n`;\n\n\tconst asyncLocalStorageMarker = \"// %async-local-storage\";\n\tconst markerIndex = code.indexOf(asyncLocalStorageMarker);\n\tif (markerIndex === -1) {\n\t\tthrow new Error(\n\t\t\t\"Expected a single %async-local-storage marker in server middleware.\"\n\t\t);\n\t}\n\n\tconst lineStart = code.lastIndexOf(\"\\n\", markerIndex) + 1;\n\tconst indent = code.slice(lineStart, markerIndex).replace(/\\t/g, \" \");\n\tconst innerIndent = `${indent} `;\n\tconst asyncLocalStorageBlock = args.compilerOptions.disableAsyncLocalStorage\n\t\t? [\n\t\t\t\t`${indent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${indent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = createMockAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${indent}}`,\n\t\t\t]\n\t\t: [\n\t\t\t\t`${indent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${indent}if (!runtime.disableAsyncLocalStorage && !requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}const { AsyncLocalStorage } = await import(\"async_hooks\");`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = runtime.getServerAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent} requestAsyncLocalStorage = new AsyncLocalStorage();`,\n\t\t\t\t`${innerIndent} runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${innerIndent}}`,\n\t\t\t\t`${indent}}`,\n\t\t\t\t`${indent}if (!requestAsyncLocalStorage) {`,\n\t\t\t\t`${innerIndent}requestAsyncLocalStorage = createMockAsyncLocalStorage();`,\n\t\t\t\t`${innerIndent}runtime.overwriteServerAsyncLocalStorage(requestAsyncLocalStorage);`,\n\t\t\t\t`${indent}}`,\n\t\t\t];\n\n\tconst lineEnd = code.indexOf(\"\\n\", markerIndex);\n\tconst endOfMarkerLine = lineEnd === -1 ? code.length : lineEnd + 1;\n\n\tcode =\n\t\tcode.slice(0, lineStart) +\n\t\t`${asyncLocalStorageBlock.join(\"\\n\")}\\n` +\n\t\tcode.slice(endOfMarkerLine);\n\n\tif (args.compilerOptions.experimentalMiddlewareLocaleSplitting) {\n\t\t// Use a replacer function, not a replacement string. `String.replace()`\n\t\t// treats a string replacement as a pattern where `$&`, `` $` ``, `$'`,\n\t\t// `$$`, and `$<name>` have special meaning. A translated message value\n\t\t// that contains a literal `$` (a price, a currency symbol) can produce\n\t\t// one of these sequences inside the JSON payload, which `String.replace`\n\t\t// then expands - e.g. `` $` `` is replaced with \"everything before the\n\t\t// match\", splicing the file's own header into the string being built and\n\t\t// corrupting the generated server file. A function's return value is\n\t\t// used literally, with no pattern expansion.\n\t\tcode = code.replace(\n\t\t\t\"const compiledBundles = {};\",\n\t\t\t() =>\n\t\t\t\t`const compiledBundles = ${JSON.stringify(createCompiledMessagesObject(args.compiledBundles))};`\n\t\t);\n\t\tcode = code.replace(\n\t\t\t\"const compiledRegistry = { functions: {}, messages: {} };\",\n\t\t\t() =>\n\t\t\t\t`const compiledRegistry = ${JSON.stringify(createCompiledRegistryObject(args.compiledBundles))};`\n\t\t);\n\t}\n\n\treturn code.replace(/\\t/g, \" \");\n}\n\nfunction createCompiledMessagesObject(\n\tcompiledBundles: CompiledBundleWithMessages[]\n): Record<string, Record<Locale, string>> {\n\tconst result = {} as Record<string, Record<Locale, string>>;\n\n\tfor (const compiledBundle of compiledBundles) {\n\t\tconst bundleId = compiledBundle.bundle.node.id;\n\t\tconst safeModuleId = toSafeModuleId(bundleId);\n\t\t// Key by the safe module id, not the raw bundle id: trackMessageCall()\n\t\t// records calls under safeModuleId, the client reads\n\t\t// globalThis.__paraglide.ssr[safeModuleId], and middleware.js looks up\n\t\t// compiledBundles[id] with that same safe id. Keying by the raw\n\t\t// bundleId here made every split-mode lookup miss.\n\t\tif (result[safeModuleId] === undefined) {\n\t\t\tresult[safeModuleId] = {};\n\t\t}\n\t\tfor (const [locale, compiledMessage] of Object.entries(\n\t\t\tcompiledBundle.messages\n\t\t)) {\n\t\t\tresult[safeModuleId][locale] = compiledMessage.code\n\t\t\t\t.replace(`export const ${safeModuleId} = `, \"\")\n\t\t\t\t.replace(/;$/, \"\");\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * The registry functions each compiled message calls, and their code, for\n * the messages the middleware injects into the page. Those run without\n * registry.js.\n */\nfunction createCompiledRegistryObject(\n\tcompiledBundles: CompiledBundleWithMessages[]\n): {\n\tfunctions: Record<string, string>;\n\tmessages: Record<string, Record<string, string[]>>;\n} {\n\tconst messages: Record<string, Record<string, string[]>> = {};\n\tconst used = new Set<string>();\n\n\tfor (const compiledBundle of compiledBundles) {\n\t\tconst safeModuleId = toSafeModuleId(compiledBundle.bundle.node.id);\n\t\tfor (const [locale, compiledMessage] of Object.entries(\n\t\t\tcompiledBundle.messages\n\t\t)) {\n\t\t\tconst names = withRegistryDependencies(compiledMessage.registryFunctions);\n\t\t\tif (names.length === 0) continue;\n\t\t\tmessages[safeModuleId] ??= {};\n\t\t\tmessages[safeModuleId][locale] = names;\n\t\t\tfor (const name of names) used.add(name);\n\t\t}\n\t}\n\n\treturn { functions: registryFunctionCode(used), messages };\n}\n\n/**\n * Load a file from the current directory.\n *\n * Prunes the imports on top of the file as the runtime is\n * self-contained.\n *\n * @param {string} path\n * @returns {string}\n */\nfunction injectCode(path: string): string {\n\tconst code = fs.readFileSync(new URL(path, import.meta.url), \"utf-8\");\n\t// Regex to match single-line and multi-line imports\n\tconst importRegex = /^\\s*import\\s+[\\s\\S]*?from\\s+['\"][^'\"]+['\"]\\s*;?/gm;\n\tconst sourceMapRegex = /\\/\\/# sourceMappingURL=.*$/gm;\n\tconst blockSourceMapRegex = /\\/\\*# sourceMappingURL=.*?\\*\\//g;\n\treturn code\n\t\t.replace(importRegex, \"\")\n\t\t.replace(sourceMapRegex, \"\")\n\t\t.replace(blockSourceMapRegex, \"\")\n\t\t.trim();\n}\n"]}
@@ -46,6 +46,18 @@ export const isExcludedByRouteStrategy = runtime.isExcludedByRouteStrategy;`);
46
46
  expect(response.status).toBe(200);
47
47
  expect(await response.text()).toBe("ready");
48
48
  });
49
+ test("import statements in JSDoc examples survive in the generated server file", () => {
50
+ const serverCode = createServerFile({
51
+ compiledBundles: [],
52
+ compilerOptions: {
53
+ disableAsyncLocalStorage: false,
54
+ experimentalMiddlewareLocaleSplitting: false,
55
+ },
56
+ });
57
+ expect(serverCode).toContain(` * import { paraglideMiddleware } from './paraglide/server.js'\n * import handler from '@tanstack/react-start/server-entry'\n *\n * export default {`);
58
+ // only the `import * as runtime` line that createServerFile itself prepends
59
+ expect(serverCode.match(/^\s*import\s/gm)).toHaveLength(1);
60
+ });
49
61
  test("keys compiledBundles by the safe module id, not the raw bundle id (experimentalMiddlewareLocaleSplitting)", () => {
50
62
  // A bundle id that changes under toSafeModuleId (case-folded + a numeric
51
63
  // suffix appended for the uppercase letters). trackMessageCall(), the
@@ -59,7 +71,10 @@ test("keys compiledBundles by the safe module id, not the raw bundle id (experim
59
71
  {
60
72
  bundle: { node: { id: bundleId } },
61
73
  messages: {
62
- en: { code: `export const ${safeModuleId} = () => "hello";` },
74
+ en: {
75
+ code: `export const ${safeModuleId} = () => "hello";`,
76
+ registryFunctions: [],
77
+ },
63
78
  },
64
79
  },
65
80
  ];
@@ -87,7 +102,10 @@ test("a literal '$' in a compiled message does not corrupt the generated file (e
87
102
  {
88
103
  bundle: { node: { id: "price_symbol" } },
89
104
  messages: {
90
- en: { code: "export const price_symbol = () => `$`;" },
105
+ en: {
106
+ code: "export const price_symbol = () => `$`;",
107
+ registryFunctions: [],
108
+ },
91
109
  },
92
110
  },
93
111
  ];
@@ -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(\"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":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,oBAAoB,GAAa,EAAE,CAAC;AAE1C,SAAS,CAAC,KAAK,IAAI,EAAE;IACpB,MAAM,OAAO,CAAC,GAAG,CAChB,oBAAoB;SAClB,MAAM,CAAC,CAAC,CAAC;SACT,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CACrE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gGAAgG,EAAE,KAAK,IAAI,EAAE;IACjH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACrE,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAErC,MAAM,UAAU,GAAG,gBAAgB,CAAC;QACnC,eAAe,EAAE,EAAE;QACnB,eAAe,EAAE;YAChB,wBAAwB,EAAE,KAAK;YAC/B,qCAAqC,EAAE,KAAK;SAC5C;KACD,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;IAExD,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,SAAS,CACd,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,EACnC;;;;;;;;;;;EAWA,CACA,CAAC;IACF,MAAM,SAAS,CACd,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EACtC;;;;;;4EAM0E,CAC1E,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAC1B,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CACjD,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAChD,IAAI,OAAO,CAAC,+BAA+B,CAAC,EAC5C,GAAG,EAAE,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAC3B,CAAC;IAEF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0EAA0E,EAAE,GAAG,EAAE;IACrF,MAAM,UAAU,GAAG,gBAAgB,CAAC;QACnC,eAAe,EAAE,EAAE;QACnB,eAAe,EAAE;YAChB,wBAAwB,EAAE,KAAK;YAC/B,qCAAqC,EAAE,KAAK;SAC5C;KACD,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAC3B,sJAAsJ,CACtJ,CAAC;IACF,4EAA4E;IAC5E,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2GAA2G,EAAE,GAAG,EAAE;IACtH,yEAAyE;IACzE,sEAAsE;IACtE,4DAA4D;IAC5D,sEAAsE;IACtE,qDAAqD;IACrD,MAAM,QAAQ,GAAG,UAAU,CAAC;IAC5B,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,eAAe,GAAG;QACvB;YACC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE;YAClC,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,gBAAgB,YAAY,mBAAmB;oBACrD,iBAAiB,EAAE,EAAE;iBACrB;aACD;SACD;KAC0C,CAAC;IAE7C,MAAM,UAAU,GAAG,gBAAgB,CAAC;QACnC,eAAe;QACf,eAAe,EAAE;YAChB,wBAAwB,EAAE,KAAK;YAC/B,qCAAqC,EAAE,IAAI;SAC3C;KACD,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,IAAI,YAAY,UAAU,CAAC,CAAC;IACzD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,UAAU,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iHAAiH,EAAE,KAAK,IAAI,EAAE;IAClI,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAC5E,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAErC,uEAAuE;IACvE,mEAAmE;IACnE,yEAAyE;IACzE,2EAA2E;IAC3E,kEAAkE;IAClE,qEAAqE;IACrE,gDAAgD;IAChD,MAAM,eAAe,GAAG;QACvB;YACC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE;YACxC,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,wCAAwC;oBAC9C,iBAAiB,EAAE,EAAE;iBACrB;aACD;SACD;KAC0C,CAAC;IAE7C,MAAM,UAAU,GAAG,gBAAgB,CAAC;QACnC,eAAe;QACf,eAAe,EAAE;YAChB,wBAAwB,EAAE,KAAK;YAC/B,qCAAqC,EAAE,IAAI;SAC3C;KACD,CAAC,CAAC;IAEH,+DAA+D;IAC/D,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAElE,sEAAsE;IACtE,0DAA0D;IAC1D,MAAM,SAAS,CACd,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAC7B;;;;;;;;;;;;;;;EAeA,CACA,CAAC;IACF,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;IAE3D,MAAM,MAAM,CACX,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CACzD,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC","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"]}
@@ -151,23 +151,35 @@ export async function paraglideMiddleware(request, resolve, options) {
151
151
  response.headers.get("Content-Type")?.includes("html")) {
152
152
  const body = await response.text();
153
153
  const messages = [];
154
+ /** @type {Set<string>} */
155
+ const registryFunctionNames = new Set();
154
156
  // using .values() to avoid polyfilling in older projects. else the following error is thrown
155
157
  // Type 'Set<string>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.
156
158
  for (const messageCall of Array.from(messageCalls)) {
157
159
  const [id, locale] =
158
160
  /** @type {[string, import("./runtime.js").Locale]} */ (messageCall.split(":"));
159
161
  messages.push(`${id}: ${compiledBundles[id]?.[locale]}`);
162
+ for (const name of compiledRegistry.messages[id]?.[locale] ?? []) {
163
+ registryFunctionNames.add(name);
164
+ }
165
+ }
166
+ // The injected messages run without registry.js. Declare the registry
167
+ // functions they call (including the ones those call) in a closure.
168
+ let ssr = `{ ${messages.join(",")} }`;
169
+ if (registryFunctionNames.size > 0) {
170
+ const names = Array.from(registryFunctionNames);
171
+ ssr = `(() => { ${names
172
+ .map((name) => compiledRegistry.functions[name])
173
+ .join("\n")}\nconst registry = { ${names.join(", ")} };\nreturn ${ssr} })()`;
160
174
  }
161
175
  // Prevent translated content from terminating the inline script tag.
162
- const escapedMessages = messages
163
- .join(",")
164
- .replace(/<\/(script)/gi, "<\\/$1");
176
+ const escapedSsr = ssr.replace(/<\/(script)/gi, "<\\/$1");
165
177
  // Reuse the request's CSP nonce (if any) so the injected script is allowed under a strict CSP
166
178
  const nonce = response.headers
167
179
  .get("Content-Security-Policy")
168
180
  ?.match(/'nonce-([\w+/=-]+)'/)?.[1];
169
181
  const nonceAttr = nonce ? `nonce="${nonce}"` : "";
170
- const script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = { ${escapedMessages} }</script>`;
182
+ const script = `<script ${nonceAttr}>globalThis.__paraglide = globalThis.__paraglide ?? {}; globalThis.__paraglide.ssr = ${escapedSsr}</script>`;
171
183
  // Insert the script before the closing head tag
172
184
  const newBody = body.replace("</head>", `${script}</head>`);
173
185
  // Create a new response with the modified body
@@ -279,4 +291,17 @@ void createMockAsyncLocalStorage;
279
291
  * @type {Record<string, Record<import("./runtime.js").Locale, string>>}
280
292
  */
281
293
  const compiledBundles = {};
294
+ /**
295
+ * The registry functions the compiled messages call, for the injected
296
+ * messages that run without registry.js.
297
+ *
298
+ * `messages[id][locale]` lists the registry functions a message calls,
299
+ * including the ones those call. `functions[name]` is the code of a registry
300
+ * function.
301
+ *
302
+ * Only populated if `enableMiddlewareOptimizations` is set to `true`.
303
+ *
304
+ * @type {{ functions: Record<string, string>, messages: Record<string, Record<string, string[]>> }}
305
+ */
306
+ const compiledRegistry = { functions: {}, messages: {} };
282
307
  //# 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)\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\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 {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"]}
@@ -1,4 +1,4 @@
1
1
  export const ENV_VARIABLES = {
2
- PARJS_PACKAGE_VERSION: "2.25.4",
2
+ PARJS_PACKAGE_VERSION: "2.27.0",
3
3
  };
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,qBAAqB,EAAE,QAAQ;CAC/B,CAAA","sourcesContent":["\nexport const ENV_VARIABLES = {\n\tPARJS_PACKAGE_VERSION: \"2.25.4\",\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,qBAAqB,EAAE,QAAQ;CAC/B,CAAA","sourcesContent":["\nexport const ENV_VARIABLES = {\n\tPARJS_PACKAGE_VERSION: \"2.27.0\",\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inlang/paraglide-js",
3
3
  "type": "module",
4
- "version": "2.25.4",
4
+ "version": "2.27.0",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@inlang/recommend-sherlock": "^0.2.1",
30
- "@inlang/sdk": "^3.0.6",
30
+ "@inlang/sdk": "^4.0.0",
31
31
  "commander": "11.1.0",
32
32
  "consola": "3.4.0",
33
33
  "jiti": "^2.7.0",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@changesets/cli": "^2.29.7",
53
- "@inlang/plugin-message-format": "^4.3.0",
53
+ "@inlang/plugin-message-format": "^4.5.0",
54
54
  "@rollup/plugin-virtual": "3.0.2",
55
55
  "@ts-morph/bootstrap": "0.26.0",
56
56
  "@types/node": "^22.10.6",