@inlang/paraglide-js 2.23.2 → 2.24.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 (72) hide show
  1. package/dist/bundler-plugins/per-locale-build/vite-environments.js +12 -7
  2. package/dist/bundler-plugins/per-locale-build/vite-environments.js.map +1 -1
  3. package/dist/bundler-plugins/unplugin.js +134 -4
  4. package/dist/bundler-plugins/unplugin.js.map +1 -1
  5. package/dist/bundler-plugins/unplugin.test.js +77 -0
  6. package/dist/bundler-plugins/unplugin.test.js.map +1 -1
  7. package/dist/cli/commands/compile/command.js +8 -1
  8. package/dist/cli/commands/compile/command.js.map +1 -1
  9. package/dist/cli/commands/compile/command.test.js +45 -0
  10. package/dist/cli/commands/compile/command.test.js.map +1 -1
  11. package/dist/compiler/compile.js +0 -15
  12. package/dist/compiler/compile.js.map +1 -1
  13. package/dist/compiler/compile.test.js +0 -52
  14. package/dist/compiler/compile.test.js.map +1 -1
  15. package/dist/compiler/compiler-options.d.ts +8 -0
  16. package/dist/compiler/compiler-options.js.map +1 -1
  17. package/dist/compiler/runtime/create-runtime.d.ts +1 -0
  18. package/dist/compiler/runtime/create-runtime.js +11 -0
  19. package/dist/compiler/runtime/create-runtime.js.map +1 -1
  20. package/dist/compiler/runtime/exec-url-pattern.d.ts +9 -0
  21. package/dist/compiler/runtime/exec-url-pattern.js +31 -0
  22. package/dist/compiler/runtime/exec-url-pattern.js.map +1 -0
  23. package/dist/compiler/runtime/extract-locale-from-url.js +8 -3
  24. package/dist/compiler/runtime/extract-locale-from-url.js.map +1 -1
  25. package/dist/compiler/runtime/generate-static-localized-urls.js +12 -6
  26. package/dist/compiler/runtime/generate-static-localized-urls.js.map +1 -1
  27. package/dist/compiler/runtime/generate-static-localized-urls.test.js +46 -0
  28. package/dist/compiler/runtime/generate-static-localized-urls.test.js.map +1 -1
  29. package/dist/compiler/runtime/localize-href.bench.d.ts +1 -0
  30. package/dist/compiler/runtime/localize-href.bench.js +77 -0
  31. package/dist/compiler/runtime/localize-href.bench.js.map +1 -0
  32. package/dist/compiler/runtime/localize-href.test.js +43 -0
  33. package/dist/compiler/runtime/localize-href.test.js.map +1 -1
  34. package/dist/compiler/runtime/localize-url.d.ts +14 -0
  35. package/dist/compiler/runtime/localize-url.js +376 -18
  36. package/dist/compiler/runtime/localize-url.js.map +1 -1
  37. package/dist/compiler/runtime/localize-url.test.js +163 -0
  38. package/dist/compiler/runtime/localize-url.test.js.map +1 -1
  39. package/dist/compiler/runtime/normalize-trailing-slash.d.ts +10 -0
  40. package/dist/compiler/runtime/normalize-trailing-slash.js +23 -0
  41. package/dist/compiler/runtime/normalize-trailing-slash.js.map +1 -0
  42. package/dist/compiler/runtime/route-strategy.js +4 -2
  43. package/dist/compiler/runtime/route-strategy.js.map +1 -1
  44. package/dist/compiler/runtime/should-redirect.js +4 -1
  45. package/dist/compiler/runtime/should-redirect.js.map +1 -1
  46. package/dist/compiler/runtime/should-redirect.test.js +30 -2
  47. package/dist/compiler/runtime/should-redirect.test.js.map +1 -1
  48. package/dist/compiler/runtime/type.d.ts +1 -0
  49. package/dist/compiler/runtime/type.js.map +1 -1
  50. package/dist/compiler/runtime/variables.d.ts +6 -0
  51. package/dist/compiler/runtime/variables.js +6 -0
  52. package/dist/compiler/runtime/variables.js.map +1 -1
  53. package/dist/compiler/server/middleware.js +6 -2
  54. package/dist/compiler/server/middleware.js.map +1 -1
  55. package/dist/compiler/server/middleware.test.js +34 -0
  56. package/dist/compiler/server/middleware.test.js.map +1 -1
  57. package/dist/index.test.d.ts +1 -0
  58. package/dist/index.test.js +9 -0
  59. package/dist/index.test.js.map +1 -0
  60. package/dist/services/env-variables/index.js +1 -1
  61. package/dist/services/env-variables/index.js.map +1 -1
  62. package/dist/services/file-handling/write-output.bench.d.ts +1 -0
  63. package/dist/services/file-handling/write-output.bench.js +24 -0
  64. package/dist/services/file-handling/write-output.bench.js.map +1 -0
  65. package/dist/services/file-handling/write-output.js +16 -20
  66. package/dist/services/file-handling/write-output.js.map +1 -1
  67. package/dist/services/file-handling/write-output.test.js +27 -0
  68. package/dist/services/file-handling/write-output.test.js.map +1 -1
  69. package/package.json +2 -2
  70. package/dist/services/account/index.d.ts +0 -14
  71. package/dist/services/account/index.js +0 -43
  72. package/dist/services/account/index.js.map +0 -1
@@ -1,12 +1,9 @@
1
1
  import nodeFs from "node:fs/promises";
2
2
  import nodePath from "node:path";
3
- import * as vite from "vite";
4
3
  import { PER_LOCALE_BUILD_DEFINE } from "./constants.js";
5
4
  import { getPerLocaleBuildLocaleId } from "./locale-id.js";
6
5
  export const VITE_LOCALE_BUILD_MANIFEST = "paraglide-vite-locales.json";
7
6
  export const VITE_LOCALE_ENVIRONMENT_PREFIX = "paraglide_client_";
8
- const viteVersion = vite.version;
9
- const detectedRolldownVersion = vite.rolldownVersion;
10
7
  export function createViteLocaleBuildPlan(args) {
11
8
  const outputDirectory = normalizeOutputDirectory(args.outputDirectory ?? "dist");
12
9
  return {
@@ -42,6 +39,12 @@ export function createViteLocaleEnvironmentPlugin(args) {
42
39
  async config(config, env) {
43
40
  if (env.command !== "build")
44
41
  return;
42
+ // Vite is an optional peer dependency. Only resolve it when this
43
+ // experimental Vite-specific build path is actually used so importing
44
+ // the package's compiler API does not require Vite to be installed.
45
+ const vite = await import("vite");
46
+ const viteVersion = vite.version;
47
+ const detectedRolldownVersion = vite.rolldownVersion;
45
48
  if (Number.parseInt(viteVersion, 10) < 8) {
46
49
  throw new Error(`experimentalPerLocaleBuild Vite environments require Vite 8 or newer; found ${viteVersion}.`);
47
50
  }
@@ -64,6 +67,10 @@ export function createViteLocaleEnvironmentPlugin(args) {
64
67
  builder,
65
68
  plan: plan,
66
69
  settings: settings,
70
+ viteVersion,
71
+ rolldownVersion: typeof detectedRolldownVersion === "string"
72
+ ? detectedRolldownVersion
73
+ : "unknown",
67
74
  });
68
75
  };
69
76
  return {
@@ -128,10 +135,8 @@ async function buildViteLocaleEnvironments(args) {
128
135
  const manifest = {
129
136
  version: 1,
130
137
  backend: "vite-rolldown-environments",
131
- viteVersion,
132
- rolldownVersion: typeof detectedRolldownVersion === "string"
133
- ? detectedRolldownVersion
134
- : "unknown",
138
+ viteVersion: args.viteVersion,
139
+ rolldownVersion: args.rolldownVersion,
135
140
  baseLocale: args.settings.baseLocale,
136
141
  locales: {},
137
142
  };
@@ -1 +1 @@
1
- {"version":3,"file":"vite-environments.js","sourceRoot":"","sources":["../../../src/bundler-plugins/per-locale-build/vite-environments.ts"],"names":[],"mappings":"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","sourcesContent":["import nodeFs from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport type { EnvironmentOptions, Plugin, UserConfig, ViteBuilder } from \"vite\";\nimport * as vite from \"vite\";\nimport { PER_LOCALE_BUILD_DEFINE } from \"./constants.js\";\nimport { getPerLocaleBuildLocaleId } from \"./locale-id.js\";\nimport type { PerLocaleBuildSettings } from \"./types.js\";\n\nexport const VITE_LOCALE_BUILD_MANIFEST = \"paraglide-vite-locales.json\";\nexport const VITE_LOCALE_ENVIRONMENT_PREFIX = \"paraglide_client_\";\nconst viteVersion = vite.version;\nconst detectedRolldownVersion = (\n\tvite as unknown as { rolldownVersion?: unknown }\n).rolldownVersion;\n\nexport type ViteLocaleBuildPlan = {\n\toutputDirectory: string;\n\tvariants: Array<{\n\t\tlocale: string;\n\t\tenvironmentName: string;\n\t\tdirectory: string;\n\t\toutputDirectory: string;\n\t\tdefine: Record<string, string>;\n\t}>;\n};\n\nexport type ViteLocaleBuildManifest = {\n\tversion: 1;\n\tbackend: \"vite-rolldown-environments\";\n\tviteVersion: string;\n\trolldownVersion: string;\n\tbaseLocale: string;\n\tlocales: Record<\n\t\tstring,\n\t\t{\n\t\t\tenvironment: string;\n\t\t\tdirectory: string;\n\t\t\tentries: Record<string, string>;\n\t\t\tfiles: Array<{\n\t\t\t\tfileName: string;\n\t\t\t\ttype: \"asset\" | \"chunk\";\n\t\t\t\tbytes: number;\n\t\t\t\tentry?: boolean;\n\t\t\t\tdynamicEntry?: boolean;\n\t\t\t\timports?: string[];\n\t\t\t\tdynamicImports?: string[];\n\t\t\t\texternalImports?: string[];\n\t\t\t\texternalDynamicImports?: string[];\n\t\t\t}>;\n\t\t}\n\t>;\n};\n\ntype ViteBuildResult = Awaited<ReturnType<ViteBuilder[\"build\"]>>;\ntype ViteRolldownOutput = Extract<\n\tViteBuildResult extends Array<infer Item> ? Item : ViteBuildResult,\n\t{ output: unknown[] }\n>;\n\nexport function createViteLocaleBuildPlan(args: {\n\tsettings: PerLocaleBuildSettings;\n\toutputDirectory?: string;\n}): ViteLocaleBuildPlan {\n\tconst outputDirectory = normalizeOutputDirectory(\n\t\targs.outputDirectory ?? \"dist\"\n\t);\n\treturn {\n\t\toutputDirectory,\n\t\tvariants: args.settings.locales.map((locale) => {\n\t\t\tconst localeId = getPerLocaleBuildLocaleId(locale);\n\t\t\tconst directory = nodePath.posix.join(\"__paraglide\", localeId);\n\t\t\treturn {\n\t\t\t\tlocale,\n\t\t\t\tenvironmentName: `${VITE_LOCALE_ENVIRONMENT_PREFIX}${localeId.replaceAll(/[^a-zA-Z0-9_$]/g, \"_\")}`,\n\t\t\t\tdirectory,\n\t\t\t\toutputDirectory: nodePath.posix.join(outputDirectory, directory),\n\t\t\t\tdefine: {\n\t\t\t\t\t[PER_LOCALE_BUILD_DEFINE]: JSON.stringify(locale),\n\t\t\t\t},\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Build one untouched Rolldown client graph per locale.\n *\n * This plugin owns app-build orchestration. It deliberately rejects another\n * custom buildApp orchestrator rather than guessing how a framework builds.\n */\nexport function createViteLocaleEnvironmentPlugin(args: {\n\tsettings: () => Promise<PerLocaleBuildSettings>;\n\toutputDirectory?: string;\n}): Plugin {\n\tlet plan: ViteLocaleBuildPlan | undefined;\n\tlet settings: PerLocaleBuildSettings | undefined;\n\tlet buildApp:\n\t\t| NonNullable<NonNullable<UserConfig[\"builder\"]>[\"buildApp\"]>\n\t\t| undefined;\n\n\treturn {\n\t\tname: \"paraglide-vite-locale-environments\",\n\t\tenforce: \"post\",\n\t\tasync config(config, env) {\n\t\t\tif (env.command !== \"build\") return;\n\t\t\tif (Number.parseInt(viteVersion, 10) < 8) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`experimentalPerLocaleBuild Vite environments require Vite 8 or newer; found ${viteVersion}.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (config.builder?.buildApp !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments cannot compose with an existing builder.buildApp orchestrator. A framework must expose a public client-variant API before using this backend.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\tsettings = await args.settings();\n\t\t\tvalidateViteLocaleBuildSettings(settings);\n\t\t\tplan = createViteLocaleBuildPlan({\n\t\t\t\tsettings,\n\t\t\t\toutputDirectory: args.outputDirectory ?? config.build?.outDir,\n\t\t\t});\n\t\t\tfor (const variant of plan.variants) {\n\t\t\t\tif (config.environments?.[variant.environmentName] !== undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`experimentalPerLocaleBuild cannot create Vite environment ${JSON.stringify(variant.environmentName)} because the application already defines it.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuildApp = async (builder) => {\n\t\t\t\tawait buildViteLocaleEnvironments({\n\t\t\t\t\tbuilder,\n\t\t\t\t\tplan: plan!,\n\t\t\t\t\tsettings: settings!,\n\t\t\t\t});\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tbuilder: {\n\t\t\t\t\t...config.builder,\n\t\t\t\t\tbuildApp,\n\t\t\t\t},\n\t\t\t\tenvironments: Object.fromEntries(\n\t\t\t\t\tplan.variants.map((variant) => [\n\t\t\t\t\t\tvariant.environmentName,\n\t\t\t\t\t\tcreateLocaleEnvironment(variant),\n\t\t\t\t\t])\n\t\t\t\t),\n\t\t\t} satisfies UserConfig;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\tif (config.command !== \"build\") return;\n\t\t\tif (config.builder?.buildApp !== buildApp) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments must own builder.buildApp. Another plugin replaced the locale build orchestrator.\"\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\tbuildStart() {\n\t\t\tif (!this.meta.rolldownVersion) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments require a Rolldown-powered Vite build (Vite 8 or newer).\"\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction createLocaleEnvironment(\n\tvariant: ViteLocaleBuildPlan[\"variants\"][number]\n): EnvironmentOptions {\n\treturn {\n\t\tconsumer: \"client\",\n\t\tdefine: variant.define,\n\t\tbuild: {\n\t\t\toutDir: variant.outputDirectory,\n\t\t\temptyOutDir: true,\n\t\t\tmanifest: true,\n\t\t},\n\t};\n}\n\nasync function buildViteLocaleEnvironments(args: {\n\tbuilder: ViteBuilder;\n\tplan: ViteLocaleBuildPlan;\n\tsettings: PerLocaleBuildSettings;\n}): Promise<void> {\n\tconst outputRoot = nodePath.resolve(\n\t\targs.builder.config.root,\n\t\targs.plan.outputDirectory\n\t);\n\tawait Promise.all([\n\t\tnodeFs.rm(nodePath.join(outputRoot, \"__paraglide\"), {\n\t\t\trecursive: true,\n\t\t\tforce: true,\n\t\t}),\n\t\tnodeFs.rm(nodePath.join(outputRoot, VITE_LOCALE_BUILD_MANIFEST), {\n\t\t\tforce: true,\n\t\t}),\n\t]);\n\n\tconst results: Array<{\n\t\tvariant: ViteLocaleBuildPlan[\"variants\"][number];\n\t\toutputs: ViteRolldownOutput[];\n\t}> = [];\n\tfor (const variant of args.plan.variants) {\n\t\tconst environment = args.builder.environments[variant.environmentName];\n\t\tif (!environment) {\n\t\t\tthrow new Error(\n\t\t\t\t`Vite did not create the locale environment ${JSON.stringify(variant.environmentName)}.`\n\t\t\t);\n\t\t}\n\t\tconst result = await args.builder.build(environment);\n\t\tresults.push({\n\t\t\tvariant,\n\t\t\toutputs: getRolldownOutputs(result),\n\t\t});\n\t}\n\n\tconst manifest: ViteLocaleBuildManifest = {\n\t\tversion: 1,\n\t\tbackend: \"vite-rolldown-environments\",\n\t\tviteVersion,\n\t\trolldownVersion:\n\t\t\ttypeof detectedRolldownVersion === \"string\"\n\t\t\t\t? detectedRolldownVersion\n\t\t\t\t: \"unknown\",\n\t\tbaseLocale: args.settings.baseLocale,\n\t\tlocales: {},\n\t};\n\tfor (const { variant, outputs } of results) {\n\t\tmanifest.locales[variant.locale] = createLocaleManifest({\n\t\t\tvariant,\n\t\t\toutputs,\n\t\t});\n\t}\n\n\tawait nodeFs.mkdir(outputRoot, { recursive: true });\n\tawait nodeFs.writeFile(\n\t\tnodePath.join(outputRoot, VITE_LOCALE_BUILD_MANIFEST),\n\t\tJSON.stringify(manifest, undefined, \"\\t\") + \"\\n\"\n\t);\n}\n\nfunction getRolldownOutputs(result: ViteBuildResult): ViteRolldownOutput[] {\n\tif (Array.isArray(result)) {\n\t\treturn result.filter(\n\t\t\t(item): item is ViteRolldownOutput => \"output\" in item\n\t\t);\n\t}\n\tif (\"output\" in result) return [result as ViteRolldownOutput];\n\tthrow new Error(\n\t\t\"experimentalPerLocaleBuild Vite environments do not support watch-mode Rolldown output.\"\n\t);\n}\n\nfunction createLocaleManifest(args: {\n\tvariant: ViteLocaleBuildPlan[\"variants\"][number];\n\toutputs: ViteRolldownOutput[];\n}): ViteLocaleBuildManifest[\"locales\"][string] {\n\tconst outputFiles = args.outputs.flatMap((output) => output.output);\n\tconst emittedFileNames = new Set(\n\t\toutputFiles.map((output) => output.fileName)\n\t);\n\tconst files: ViteLocaleBuildManifest[\"locales\"][string][\"files\"] = outputFiles\n\t\t.map((output) => {\n\t\t\tif (output.type === \"asset\") {\n\t\t\t\treturn {\n\t\t\t\t\tfileName: output.fileName,\n\t\t\t\t\ttype: \"asset\" as const,\n\t\t\t\t\tbytes: getByteLength(output.source),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst staticImports = partitionImports(output.imports, emittedFileNames);\n\t\t\tconst dynamicImports = partitionImports(\n\t\t\t\toutput.dynamicImports,\n\t\t\t\temittedFileNames\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tfileName: output.fileName,\n\t\t\t\ttype: \"chunk\" as const,\n\t\t\t\tbytes: getByteLength(output.code),\n\t\t\t\t...(output.isEntry ? { entry: true } : {}),\n\t\t\t\t...(output.isDynamicEntry ? { dynamicEntry: true } : {}),\n\t\t\t\t...(staticImports.internal.length > 0\n\t\t\t\t\t? { imports: staticImports.internal }\n\t\t\t\t\t: {}),\n\t\t\t\t...(dynamicImports.internal.length > 0\n\t\t\t\t\t? { dynamicImports: dynamicImports.internal }\n\t\t\t\t\t: {}),\n\t\t\t\t...(staticImports.external.length > 0\n\t\t\t\t\t? { externalImports: staticImports.external }\n\t\t\t\t\t: {}),\n\t\t\t\t...(dynamicImports.external.length > 0\n\t\t\t\t\t? {\n\t\t\t\t\t\t\texternalDynamicImports: dynamicImports.external,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t})\n\t\t.sort((left, right) => left.fileName.localeCompare(right.fileName));\n\tconst fileNames = new Set(files.map((file) => file.fileName));\n\tfor (const file of files) {\n\t\tfor (const imported of [\n\t\t\t...(file.imports ?? []),\n\t\t\t...(file.dynamicImports ?? []),\n\t\t]) {\n\t\t\tif (!fileNames.has(imported)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Vite emitted an open locale graph for ${JSON.stringify(args.variant.locale)}: ${file.fileName} imports missing ${imported}.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tconst entryPairs: Array<[string, string]> = [];\n\tfor (const output of args.outputs.flatMap((result) => result.output)) {\n\t\tif (output.type === \"chunk\" && output.isEntry) {\n\t\t\tentryPairs.push([output.facadeModuleId ?? output.name, output.fileName]);\n\t\t}\n\t}\n\tconst entries = Object.fromEntries(\n\t\tentryPairs.sort(([left], [right]) => left.localeCompare(right))\n\t);\n\treturn {\n\t\tenvironment: args.variant.environmentName,\n\t\tdirectory: args.variant.directory,\n\t\tentries,\n\t\tfiles,\n\t};\n}\n\nfunction partitionImports(\n\timports: string[],\n\temittedFileNames: ReadonlySet<string>\n): { internal: string[]; external: string[] } {\n\tconst internal: string[] = [];\n\tconst external: string[] = [];\n\tfor (const imported of imports) {\n\t\t(emittedFileNames.has(imported) ? internal : external).push(imported);\n\t}\n\treturn { internal, external };\n}\n\nfunction getByteLength(source: string | Uint8Array): number {\n\treturn typeof source === \"string\"\n\t\t? new TextEncoder().encode(source).byteLength\n\t\t: source.byteLength;\n}\n\nfunction normalizeOutputDirectory(directory: string): string {\n\tconst normalized = directory.replaceAll(\"\\\\\", \"/\").replace(/\\/+$/, \"\");\n\tif (\n\t\tnormalized === \"\" ||\n\t\tnormalized === \".\" ||\n\t\tnormalized.startsWith(\"/\") ||\n\t\tnormalized === \"..\" ||\n\t\tnormalized.startsWith(\"../\")\n\t) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environment outputDirectory must be a project-relative directory.\"\n\t\t);\n\t}\n\treturn normalized;\n}\n\nfunction validateViteLocaleBuildSettings(\n\tsettings: PerLocaleBuildSettings\n): void {\n\tif (!settings.baseLocale || !settings.locales.includes(settings.baseLocale)) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environments require baseLocale to be present in locales.\"\n\t\t);\n\t}\n\tif (\n\t\tsettings.locales.length === 0 ||\n\t\tnew Set(settings.locales).size !== settings.locales.length\n\t) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environments require at least one unique locale.\"\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"vite-environments.js","sourceRoot":"","sources":["../../../src/bundler-plugins/per-locale-build/vite-environments.ts"],"names":[],"mappings":"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","sourcesContent":["import nodeFs from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport type { EnvironmentOptions, Plugin, UserConfig, ViteBuilder } from \"vite\";\nimport { PER_LOCALE_BUILD_DEFINE } from \"./constants.js\";\nimport { getPerLocaleBuildLocaleId } from \"./locale-id.js\";\nimport type { PerLocaleBuildSettings } from \"./types.js\";\n\nexport const VITE_LOCALE_BUILD_MANIFEST = \"paraglide-vite-locales.json\";\nexport const VITE_LOCALE_ENVIRONMENT_PREFIX = \"paraglide_client_\";\n\nexport type ViteLocaleBuildPlan = {\n\toutputDirectory: string;\n\tvariants: Array<{\n\t\tlocale: string;\n\t\tenvironmentName: string;\n\t\tdirectory: string;\n\t\toutputDirectory: string;\n\t\tdefine: Record<string, string>;\n\t}>;\n};\n\nexport type ViteLocaleBuildManifest = {\n\tversion: 1;\n\tbackend: \"vite-rolldown-environments\";\n\tviteVersion: string;\n\trolldownVersion: string;\n\tbaseLocale: string;\n\tlocales: Record<\n\t\tstring,\n\t\t{\n\t\t\tenvironment: string;\n\t\t\tdirectory: string;\n\t\t\tentries: Record<string, string>;\n\t\t\tfiles: Array<{\n\t\t\t\tfileName: string;\n\t\t\t\ttype: \"asset\" | \"chunk\";\n\t\t\t\tbytes: number;\n\t\t\t\tentry?: boolean;\n\t\t\t\tdynamicEntry?: boolean;\n\t\t\t\timports?: string[];\n\t\t\t\tdynamicImports?: string[];\n\t\t\t\texternalImports?: string[];\n\t\t\t\texternalDynamicImports?: string[];\n\t\t\t}>;\n\t\t}\n\t>;\n};\n\ntype ViteBuildResult = Awaited<ReturnType<ViteBuilder[\"build\"]>>;\ntype ViteRolldownOutput = Extract<\n\tViteBuildResult extends Array<infer Item> ? Item : ViteBuildResult,\n\t{ output: unknown[] }\n>;\n\nexport function createViteLocaleBuildPlan(args: {\n\tsettings: PerLocaleBuildSettings;\n\toutputDirectory?: string;\n}): ViteLocaleBuildPlan {\n\tconst outputDirectory = normalizeOutputDirectory(\n\t\targs.outputDirectory ?? \"dist\"\n\t);\n\treturn {\n\t\toutputDirectory,\n\t\tvariants: args.settings.locales.map((locale) => {\n\t\t\tconst localeId = getPerLocaleBuildLocaleId(locale);\n\t\t\tconst directory = nodePath.posix.join(\"__paraglide\", localeId);\n\t\t\treturn {\n\t\t\t\tlocale,\n\t\t\t\tenvironmentName: `${VITE_LOCALE_ENVIRONMENT_PREFIX}${localeId.replaceAll(/[^a-zA-Z0-9_$]/g, \"_\")}`,\n\t\t\t\tdirectory,\n\t\t\t\toutputDirectory: nodePath.posix.join(outputDirectory, directory),\n\t\t\t\tdefine: {\n\t\t\t\t\t[PER_LOCALE_BUILD_DEFINE]: JSON.stringify(locale),\n\t\t\t\t},\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Build one untouched Rolldown client graph per locale.\n *\n * This plugin owns app-build orchestration. It deliberately rejects another\n * custom buildApp orchestrator rather than guessing how a framework builds.\n */\nexport function createViteLocaleEnvironmentPlugin(args: {\n\tsettings: () => Promise<PerLocaleBuildSettings>;\n\toutputDirectory?: string;\n}): Plugin {\n\tlet plan: ViteLocaleBuildPlan | undefined;\n\tlet settings: PerLocaleBuildSettings | undefined;\n\tlet buildApp:\n\t\t| NonNullable<NonNullable<UserConfig[\"builder\"]>[\"buildApp\"]>\n\t\t| undefined;\n\n\treturn {\n\t\tname: \"paraglide-vite-locale-environments\",\n\t\tenforce: \"post\",\n\t\tasync config(config, env) {\n\t\t\tif (env.command !== \"build\") return;\n\t\t\t// Vite is an optional peer dependency. Only resolve it when this\n\t\t\t// experimental Vite-specific build path is actually used so importing\n\t\t\t// the package's compiler API does not require Vite to be installed.\n\t\t\tconst vite = await import(\"vite\");\n\t\t\tconst viteVersion = vite.version;\n\t\t\tconst detectedRolldownVersion = (\n\t\t\t\tvite as unknown as { rolldownVersion?: unknown }\n\t\t\t).rolldownVersion;\n\t\t\tif (Number.parseInt(viteVersion, 10) < 8) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`experimentalPerLocaleBuild Vite environments require Vite 8 or newer; found ${viteVersion}.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (config.builder?.buildApp !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments cannot compose with an existing builder.buildApp orchestrator. A framework must expose a public client-variant API before using this backend.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\tsettings = await args.settings();\n\t\t\tvalidateViteLocaleBuildSettings(settings);\n\t\t\tplan = createViteLocaleBuildPlan({\n\t\t\t\tsettings,\n\t\t\t\toutputDirectory: args.outputDirectory ?? config.build?.outDir,\n\t\t\t});\n\t\t\tfor (const variant of plan.variants) {\n\t\t\t\tif (config.environments?.[variant.environmentName] !== undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`experimentalPerLocaleBuild cannot create Vite environment ${JSON.stringify(variant.environmentName)} because the application already defines it.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuildApp = async (builder) => {\n\t\t\t\tawait buildViteLocaleEnvironments({\n\t\t\t\t\tbuilder,\n\t\t\t\t\tplan: plan!,\n\t\t\t\t\tsettings: settings!,\n\t\t\t\t\tviteVersion,\n\t\t\t\t\trolldownVersion:\n\t\t\t\t\t\ttypeof detectedRolldownVersion === \"string\"\n\t\t\t\t\t\t\t? detectedRolldownVersion\n\t\t\t\t\t\t\t: \"unknown\",\n\t\t\t\t});\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tbuilder: {\n\t\t\t\t\t...config.builder,\n\t\t\t\t\tbuildApp,\n\t\t\t\t},\n\t\t\t\tenvironments: Object.fromEntries(\n\t\t\t\t\tplan.variants.map((variant) => [\n\t\t\t\t\t\tvariant.environmentName,\n\t\t\t\t\t\tcreateLocaleEnvironment(variant),\n\t\t\t\t\t])\n\t\t\t\t),\n\t\t\t} satisfies UserConfig;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\tif (config.command !== \"build\") return;\n\t\t\tif (config.builder?.buildApp !== buildApp) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments must own builder.buildApp. Another plugin replaced the locale build orchestrator.\"\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\tbuildStart() {\n\t\t\tif (!this.meta.rolldownVersion) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"experimentalPerLocaleBuild Vite environments require a Rolldown-powered Vite build (Vite 8 or newer).\"\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction createLocaleEnvironment(\n\tvariant: ViteLocaleBuildPlan[\"variants\"][number]\n): EnvironmentOptions {\n\treturn {\n\t\tconsumer: \"client\",\n\t\tdefine: variant.define,\n\t\tbuild: {\n\t\t\toutDir: variant.outputDirectory,\n\t\t\temptyOutDir: true,\n\t\t\tmanifest: true,\n\t\t},\n\t};\n}\n\nasync function buildViteLocaleEnvironments(args: {\n\tbuilder: ViteBuilder;\n\tplan: ViteLocaleBuildPlan;\n\tsettings: PerLocaleBuildSettings;\n\tviteVersion: string;\n\trolldownVersion: string;\n}): Promise<void> {\n\tconst outputRoot = nodePath.resolve(\n\t\targs.builder.config.root,\n\t\targs.plan.outputDirectory\n\t);\n\tawait Promise.all([\n\t\tnodeFs.rm(nodePath.join(outputRoot, \"__paraglide\"), {\n\t\t\trecursive: true,\n\t\t\tforce: true,\n\t\t}),\n\t\tnodeFs.rm(nodePath.join(outputRoot, VITE_LOCALE_BUILD_MANIFEST), {\n\t\t\tforce: true,\n\t\t}),\n\t]);\n\n\tconst results: Array<{\n\t\tvariant: ViteLocaleBuildPlan[\"variants\"][number];\n\t\toutputs: ViteRolldownOutput[];\n\t}> = [];\n\tfor (const variant of args.plan.variants) {\n\t\tconst environment = args.builder.environments[variant.environmentName];\n\t\tif (!environment) {\n\t\t\tthrow new Error(\n\t\t\t\t`Vite did not create the locale environment ${JSON.stringify(variant.environmentName)}.`\n\t\t\t);\n\t\t}\n\t\tconst result = await args.builder.build(environment);\n\t\tresults.push({\n\t\t\tvariant,\n\t\t\toutputs: getRolldownOutputs(result),\n\t\t});\n\t}\n\n\tconst manifest: ViteLocaleBuildManifest = {\n\t\tversion: 1,\n\t\tbackend: \"vite-rolldown-environments\",\n\t\tviteVersion: args.viteVersion,\n\t\trolldownVersion: args.rolldownVersion,\n\t\tbaseLocale: args.settings.baseLocale,\n\t\tlocales: {},\n\t};\n\tfor (const { variant, outputs } of results) {\n\t\tmanifest.locales[variant.locale] = createLocaleManifest({\n\t\t\tvariant,\n\t\t\toutputs,\n\t\t});\n\t}\n\n\tawait nodeFs.mkdir(outputRoot, { recursive: true });\n\tawait nodeFs.writeFile(\n\t\tnodePath.join(outputRoot, VITE_LOCALE_BUILD_MANIFEST),\n\t\tJSON.stringify(manifest, undefined, \"\\t\") + \"\\n\"\n\t);\n}\n\nfunction getRolldownOutputs(result: ViteBuildResult): ViteRolldownOutput[] {\n\tif (Array.isArray(result)) {\n\t\treturn result.filter(\n\t\t\t(item): item is ViteRolldownOutput => \"output\" in item\n\t\t);\n\t}\n\tif (\"output\" in result) return [result as ViteRolldownOutput];\n\tthrow new Error(\n\t\t\"experimentalPerLocaleBuild Vite environments do not support watch-mode Rolldown output.\"\n\t);\n}\n\nfunction createLocaleManifest(args: {\n\tvariant: ViteLocaleBuildPlan[\"variants\"][number];\n\toutputs: ViteRolldownOutput[];\n}): ViteLocaleBuildManifest[\"locales\"][string] {\n\tconst outputFiles = args.outputs.flatMap((output) => output.output);\n\tconst emittedFileNames = new Set(\n\t\toutputFiles.map((output) => output.fileName)\n\t);\n\tconst files: ViteLocaleBuildManifest[\"locales\"][string][\"files\"] = outputFiles\n\t\t.map((output) => {\n\t\t\tif (output.type === \"asset\") {\n\t\t\t\treturn {\n\t\t\t\t\tfileName: output.fileName,\n\t\t\t\t\ttype: \"asset\" as const,\n\t\t\t\t\tbytes: getByteLength(output.source),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst staticImports = partitionImports(output.imports, emittedFileNames);\n\t\t\tconst dynamicImports = partitionImports(\n\t\t\t\toutput.dynamicImports,\n\t\t\t\temittedFileNames\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tfileName: output.fileName,\n\t\t\t\ttype: \"chunk\" as const,\n\t\t\t\tbytes: getByteLength(output.code),\n\t\t\t\t...(output.isEntry ? { entry: true } : {}),\n\t\t\t\t...(output.isDynamicEntry ? { dynamicEntry: true } : {}),\n\t\t\t\t...(staticImports.internal.length > 0\n\t\t\t\t\t? { imports: staticImports.internal }\n\t\t\t\t\t: {}),\n\t\t\t\t...(dynamicImports.internal.length > 0\n\t\t\t\t\t? { dynamicImports: dynamicImports.internal }\n\t\t\t\t\t: {}),\n\t\t\t\t...(staticImports.external.length > 0\n\t\t\t\t\t? { externalImports: staticImports.external }\n\t\t\t\t\t: {}),\n\t\t\t\t...(dynamicImports.external.length > 0\n\t\t\t\t\t? {\n\t\t\t\t\t\t\texternalDynamicImports: dynamicImports.external,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t})\n\t\t.sort((left, right) => left.fileName.localeCompare(right.fileName));\n\tconst fileNames = new Set(files.map((file) => file.fileName));\n\tfor (const file of files) {\n\t\tfor (const imported of [\n\t\t\t...(file.imports ?? []),\n\t\t\t...(file.dynamicImports ?? []),\n\t\t]) {\n\t\t\tif (!fileNames.has(imported)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Vite emitted an open locale graph for ${JSON.stringify(args.variant.locale)}: ${file.fileName} imports missing ${imported}.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tconst entryPairs: Array<[string, string]> = [];\n\tfor (const output of args.outputs.flatMap((result) => result.output)) {\n\t\tif (output.type === \"chunk\" && output.isEntry) {\n\t\t\tentryPairs.push([output.facadeModuleId ?? output.name, output.fileName]);\n\t\t}\n\t}\n\tconst entries = Object.fromEntries(\n\t\tentryPairs.sort(([left], [right]) => left.localeCompare(right))\n\t);\n\treturn {\n\t\tenvironment: args.variant.environmentName,\n\t\tdirectory: args.variant.directory,\n\t\tentries,\n\t\tfiles,\n\t};\n}\n\nfunction partitionImports(\n\timports: string[],\n\temittedFileNames: ReadonlySet<string>\n): { internal: string[]; external: string[] } {\n\tconst internal: string[] = [];\n\tconst external: string[] = [];\n\tfor (const imported of imports) {\n\t\t(emittedFileNames.has(imported) ? internal : external).push(imported);\n\t}\n\treturn { internal, external };\n}\n\nfunction getByteLength(source: string | Uint8Array): number {\n\treturn typeof source === \"string\"\n\t\t? new TextEncoder().encode(source).byteLength\n\t\t: source.byteLength;\n}\n\nfunction normalizeOutputDirectory(directory: string): string {\n\tconst normalized = directory.replaceAll(\"\\\\\", \"/\").replace(/\\/+$/, \"\");\n\tif (\n\t\tnormalized === \"\" ||\n\t\tnormalized === \".\" ||\n\t\tnormalized.startsWith(\"/\") ||\n\t\tnormalized === \"..\" ||\n\t\tnormalized.startsWith(\"../\")\n\t) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environment outputDirectory must be a project-relative directory.\"\n\t\t);\n\t}\n\treturn normalized;\n}\n\nfunction validateViteLocaleBuildSettings(\n\tsettings: PerLocaleBuildSettings\n): void {\n\tif (!settings.baseLocale || !settings.locales.includes(settings.baseLocale)) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environments require baseLocale to be present in locales.\"\n\t\t);\n\t}\n\tif (\n\t\tsettings.locales.length === 0 ||\n\t\tnew Set(settings.locales).size !== settings.locales.length\n\t) {\n\t\tthrow new Error(\n\t\t\t\"experimentalPerLocaleBuild Vite environments require at least one unique locale.\"\n\t\t);\n\t}\n}\n"]}
@@ -1,13 +1,21 @@
1
1
  import { compile } from "../compiler/compile.js";
2
- import { relative } from "node:path";
2
+ import { dirname, relative, resolve } from "node:path";
3
3
  import { createHash } from "node:crypto";
4
4
  import nodeFs from "node:fs";
5
5
  import { Logger } from "../services/logger/index.js";
6
+ import { ENV_VARIABLES } from "../services/env-variables/index.js";
6
7
  import { createTrackedFs, getWatchTargets, isPathWithinDirectories, } from "../services/file-watching/tracked-fs.js";
7
8
  import { nodeNormalizePath } from "../utilities/node-normalize-path.js";
8
9
  import { seedPreviousCompilationFromOutdir } from "../compiler/seed-previous-compilation.js";
9
10
  const PLUGIN_NAME = "unplugin-paraglide-js";
10
11
  const logger = new Logger();
12
+ const PERSISTENT_CACHE_VERSION = 1;
13
+ function isStringRecord(value) {
14
+ return (typeof value === "object" &&
15
+ value !== null &&
16
+ !Array.isArray(value) &&
17
+ Object.values(value).every((entry) => typeof entry === "string"));
18
+ }
11
19
  /**
12
20
  * Default isServer which differs per bundler.
13
21
  */
@@ -36,6 +44,16 @@ function withoutCleanOutdir(args) {
36
44
  void cleanOutdir;
37
45
  return compileArgs;
38
46
  }
47
+ function getCompilerConfig(args, outputStructure) {
48
+ const { fs: _fs, ...serializableArgs } = args;
49
+ void _fs;
50
+ return {
51
+ ...serializableArgs,
52
+ outputStructure,
53
+ isServer,
54
+ compilerVersion: ENV_VARIABLES.PARJS_PACKAGE_VERSION,
55
+ };
56
+ }
39
57
  /**
40
58
  * Hashes the files (and directory listings) the last compilation read,
41
59
  * together with the options that affect the output. Returns `undefined`
@@ -63,9 +81,7 @@ async function computeInputsDigest(state, args, outputStructure) {
63
81
  const fsp = (args.fs ?? nodeFs).promises;
64
82
  const hash = createHash("sha256");
65
83
  try {
66
- const { fs: _fs, ...serializableArgs } = args;
67
- void _fs;
68
- hash.update(JSON.stringify({ ...serializableArgs, outputStructure, isServer }));
84
+ hash.update(JSON.stringify(getCompilerConfig(args, outputStructure)));
69
85
  for (const directoryPath of [...targets.directories].sort()) {
70
86
  const entries = await fsp
71
87
  .readdir(directoryPath)
@@ -100,6 +116,106 @@ async function computeInputsDigest(state, args, outputStructure) {
100
116
  }
101
117
  return hash.digest("hex");
102
118
  }
119
+ function getPersistentCachePath(args, outputStructure) {
120
+ const absoluteOutdir = resolve(process.cwd(), args.outdir);
121
+ const cacheKey = createHash("sha256")
122
+ .update(JSON.stringify({
123
+ absoluteOutdir,
124
+ compilerConfig: getCompilerConfig(args, outputStructure),
125
+ }))
126
+ .digest("hex")
127
+ .slice(0, 16);
128
+ return resolve(process.cwd(), args.project, "cache", "paraglide-js", `${cacheKey}.json`);
129
+ }
130
+ async function readPersistentCache(args, outputStructure) {
131
+ const fsp = (args.fs ?? nodeFs).promises;
132
+ try {
133
+ const parsed = JSON.parse(await fsp.readFile(getPersistentCachePath(args, outputStructure), "utf8"));
134
+ if (parsed.version !== PERSISTENT_CACHE_VERSION ||
135
+ parsed.compilerVersion !== ENV_VARIABLES.PARJS_PACKAGE_VERSION ||
136
+ typeof parsed.inputsDigest !== "string" ||
137
+ !Array.isArray(parsed.readFiles) ||
138
+ parsed.readFiles.some((file) => typeof file !== "string") ||
139
+ !isStringRecord(parsed.outputHashes)) {
140
+ return undefined;
141
+ }
142
+ return parsed;
143
+ }
144
+ catch {
145
+ return undefined;
146
+ }
147
+ }
148
+ async function preparePersistentCacheDirectory(args, outputStructure) {
149
+ try {
150
+ await (args.fs ?? nodeFs).promises.mkdir(dirname(getPersistentCachePath(args, outputStructure)), { recursive: true });
151
+ }
152
+ catch {
153
+ // The cache is an optimization. Read-only projects must still compile.
154
+ }
155
+ }
156
+ async function writePersistentCache(state, args, outputStructure) {
157
+ if (state.previousInputsDigest === undefined ||
158
+ state.previousCompilation?.outputHashes === undefined) {
159
+ return;
160
+ }
161
+ const cachePath = getPersistentCachePath(args, outputStructure);
162
+ const cache = {
163
+ version: PERSISTENT_CACHE_VERSION,
164
+ compilerVersion: ENV_VARIABLES.PARJS_PACKAGE_VERSION,
165
+ inputsDigest: state.previousInputsDigest,
166
+ readFiles: [...state.readFiles].sort(),
167
+ outputHashes: state.previousCompilation.outputHashes,
168
+ };
169
+ const fsp = (args.fs ?? nodeFs).promises;
170
+ try {
171
+ await fsp.mkdir(dirname(cachePath), { recursive: true });
172
+ await fsp.writeFile(cachePath, JSON.stringify(cache));
173
+ }
174
+ catch {
175
+ // The cache is an optimization. Read-only projects must still compile.
176
+ }
177
+ }
178
+ function outputHashesMatch(left, right) {
179
+ if (left === undefined)
180
+ return false;
181
+ const leftEntries = Object.entries(left);
182
+ const rightEntries = Object.entries(right);
183
+ if (leftEntries.length !== rightEntries.length)
184
+ return false;
185
+ return leftEntries.every(([file, hash]) => right[file] === hash);
186
+ }
187
+ async function restorePersistentCache(args) {
188
+ const cached = await readPersistentCache(args.compilerOptions, args.outputStructure);
189
+ if (cached === undefined)
190
+ return false;
191
+ const cachedReadFiles = new Set();
192
+ for (const file of cached.readFiles) {
193
+ cachedReadFiles.add(file);
194
+ }
195
+ const validationState = {
196
+ ...args.state,
197
+ readFiles: cachedReadFiles,
198
+ clearReadFiles: () => cachedReadFiles.clear(),
199
+ };
200
+ const [inputsDigest, previousCompilation] = await Promise.all([
201
+ computeInputsDigest(validationState, args.compilerOptions, args.outputStructure),
202
+ seedPreviousCompilationFromOutdir({
203
+ outdir: args.compilerOptions.outdir,
204
+ fs: args.compilerOptions.fs?.promises,
205
+ }),
206
+ ]);
207
+ if (inputsDigest !== cached.inputsDigest ||
208
+ !outputHashesMatch(previousCompilation?.outputHashes, cached.outputHashes)) {
209
+ return false;
210
+ }
211
+ args.state.clearReadFiles();
212
+ for (const file of cachedReadFiles) {
213
+ args.state.readFiles.add(file);
214
+ }
215
+ args.state.previousCompilation = previousCompilation;
216
+ args.state.previousInputsDigest = inputsDigest;
217
+ return true;
218
+ }
103
219
  function rethrowUnlessEnoent(error) {
104
220
  if (error?.code === "ENOENT") {
105
221
  return undefined;
@@ -119,6 +235,18 @@ export const unpluginFactory = (args) => {
119
235
  const outputStructure = args.outputStructure ??
120
236
  (isProduction ? "message-modules" : "locale-modules");
121
237
  try {
238
+ // Stabilize project directory listings before the first digest. The
239
+ // ignored cache directory must not invalidate the cache that creates it.
240
+ await preparePersistentCacheDirectory(args, outputStructure);
241
+ if (state.previousCompilation === undefined &&
242
+ (await restorePersistentCache({
243
+ state,
244
+ compilerOptions: args,
245
+ outputStructure,
246
+ }))) {
247
+ logger.info(`Compilation skipped — inputs unchanged (${outputStructure})`);
248
+ return;
249
+ }
122
250
  // `vite build` calls buildStart once per environment (client, ssr).
123
251
  // Skip the expensive compile when the inputs haven't changed.
124
252
  if (state.previousCompilation && state.previousInputsDigest) {
@@ -147,6 +275,7 @@ export const unpluginFactory = (args) => {
147
275
  fs: trackedFs,
148
276
  });
149
277
  state.previousInputsDigest = await computeInputsDigest(state, args, outputStructure);
278
+ await writePersistentCache(state, args, outputStructure);
150
279
  logger.success(`Compilation complete (${outputStructure})`);
151
280
  }
152
281
  catch (error) {
@@ -197,6 +326,7 @@ export const unpluginFactory = (args) => {
197
326
  fs: trackedFs,
198
327
  });
199
328
  state.previousInputsDigest = await computeInputsDigest(state, args, outputStructure);
329
+ await writePersistentCache(state, args, outputStructure);
200
330
  logger.success(`Re-compilation complete (${outputStructure})`);
201
331
  // Add any new files to watch
202
332
  const nextTargets = getWatchTargets(readFiles, { outdir: args.outdir });
@@ -1 +1 @@
1
- {"version":3,"file":"unplugin.js","sourceRoot":"","sources":["../../src/bundler-plugins/unplugin.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UnpluginFactory } from \"unplugin\";\nimport { compile, type CompilationResult } from \"../compiler/compile.js\";\nimport { relative } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport nodeFs from \"node:fs\";\nimport { Logger } from \"../services/logger/index.js\";\nimport type { CompilerOptions } from \"../compiler/compiler-options.js\";\nimport {\n\tcreateTrackedFs,\n\tgetWatchTargets,\n\tisPathWithinDirectories,\n} from \"../services/file-watching/tracked-fs.js\";\nimport { nodeNormalizePath } from \"../utilities/node-normalize-path.js\";\nimport { seedPreviousCompilationFromOutdir } from \"../compiler/seed-previous-compilation.js\";\n\nconst PLUGIN_NAME = \"unplugin-paraglide-js\";\n\nconst logger = new Logger();\n\n/**\n * Default isServer which differs per bundler.\n */\nlet isServer: string | undefined;\n\ntype PluginState = {\n\t/** Identity of the fs the tracked wrapper was created around. */\n\tbaseFs: typeof nodeFs | undefined;\n\ttrackedFs: typeof nodeFs;\n\treadFiles: Set<string>;\n\tclearReadFiles: () => void;\n\tpreviousCompilation: CompilationResult | undefined;\n\t/**\n\t * Digest of the input files and options of the last successful compilation.\n\t *\n\t * `vite build` fires `buildStart` once per environment (client, ssr, ...).\n\t * When the digest of the current inputs matches, `compile()` is skipped\n\t * entirely — project loading and message compilation are expensive even\n\t * when `previousCompilation` dedupes the writes.\n\t *\n\t * https://github.com/opral/paraglide-js/issues/693\n\t */\n\tpreviousInputsDigest: string | undefined;\n};\n\n// Module-scoped so the warm state survives plugin re-instantiation within\n// one process (e.g. a vite config reload), but recreated when a different\n// fs is passed — the tracked wrapper, read set, and cached compilation are\n// only valid for the filesystem they were produced from.\nlet pluginState: PluginState | undefined;\n\nfunction getPluginState(args: CompilerOptions): PluginState {\n\tif (pluginState === undefined || pluginState.baseFs !== args.fs) {\n\t\tconst tracked = createTrackedFs({ fs: args.fs });\n\t\tpluginState = {\n\t\t\tbaseFs: args.fs,\n\t\t\ttrackedFs: tracked.fs,\n\t\t\treadFiles: tracked.readFiles,\n\t\t\tclearReadFiles: tracked.clearReadFiles,\n\t\t\tpreviousCompilation: undefined,\n\t\t\tpreviousInputsDigest: undefined,\n\t\t};\n\t}\n\treturn pluginState;\n}\n\nfunction withoutCleanOutdir(\n\targs: CompilerOptions\n): Omit<CompilerOptions, \"cleanOutdir\"> {\n\tconst { cleanOutdir, ...compileArgs } = args;\n\tvoid cleanOutdir;\n\treturn compileArgs;\n}\n\n/**\n * Hashes the files (and directory listings) the last compilation read,\n * together with the options that affect the output. Returns `undefined`\n * when the digest can't be computed (no tracked reads yet, an unexpected\n * read error, ...) — `undefined` never matches, so the caller compiles.\n *\n * Directory listings are included so that a message file *added* next to\n * the tracked ones invalidates the digest, not only edits to known files.\n * All components are length-prefixed so distinct input states can't\n * produce the same hash stream.\n *\n * The digest is taken after the compile, by re-reading the inputs. A file\n * edited *during* a compile can therefore be hashed at its new content\n * while the output reflects the old one — accepted: in dev, watchChange\n * recompiles on that edit, and a fresh build process always recompiles.\n */\nasync function computeInputsDigest(\n\tstate: PluginState,\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): Promise<string | undefined> {\n\tif (state.readFiles.size === 0) {\n\t\treturn undefined;\n\t}\n\tconst targets = getWatchTargets(state.readFiles, { outdir: args.outdir });\n\tif (targets.files.size === 0) {\n\t\treturn undefined;\n\t}\n\tconst fsp = (args.fs ?? nodeFs).promises;\n\tconst hash = createHash(\"sha256\");\n\ttry {\n\t\tconst { fs: _fs, ...serializableArgs } = args;\n\t\tvoid _fs;\n\t\thash.update(\n\t\t\tJSON.stringify({ ...serializableArgs, outputStructure, isServer })\n\t\t);\n\t\tfor (const directoryPath of [...targets.directories].sort()) {\n\t\t\tconst entries = await fsp\n\t\t\t\t.readdir(directoryPath)\n\t\t\t\t// tracked reads include probed-but-absent paths (the SDK reads\n\t\t\t\t// optional files and handles ENOENT itself) — a missing entry\n\t\t\t\t// is valid input state, hash it as such\n\t\t\t\t.catch(rethrowUnlessEnoent);\n\t\t\thash.update(`\\0dir:${directoryPath.length}:${directoryPath}:`);\n\t\t\tif (entries === undefined) {\n\t\t\t\thash.update(\"missing\");\n\t\t\t} else {\n\t\t\t\tfor (const entry of [...entries].sort()) {\n\t\t\t\t\thash.update(`${entry.length}:${entry},`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const filePath of [...targets.files].sort()) {\n\t\t\tconst content = await fsp.readFile(filePath).catch(rethrowUnlessEnoent);\n\t\t\thash.update(`\\0file:${filePath.length}:${filePath}:`);\n\t\t\tif (content === undefined) {\n\t\t\t\thash.update(\"missing\");\n\t\t\t} else {\n\t\t\t\thash.update(`${content.length}:`);\n\t\t\t\thash.update(content);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn hash.digest(\"hex\");\n}\n\nfunction rethrowUnlessEnoent(error: unknown): undefined {\n\tif ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n\t\treturn undefined;\n\t}\n\tthrow error;\n}\n\nexport const unpluginFactory: UnpluginFactory<CompilerOptions> = (args) => {\n\tconst state = getPluginState(args);\n\tconst { trackedFs, readFiles, clearReadFiles } = state;\n\treturn {\n\t\tname: PLUGIN_NAME,\n\t\tenforce: \"pre\",\n\t\tasync buildStart() {\n\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\tconst outputStructure =\n\t\t\t\targs.outputStructure ??\n\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\t\t\ttry {\n\t\t\t\t// `vite build` calls buildStart once per environment (client, ssr).\n\t\t\t\t// Skip the expensive compile when the inputs haven't changed.\n\t\t\t\tif (state.previousCompilation && state.previousInputsDigest) {\n\t\t\t\t\tconst currentDigest = await computeInputsDigest(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\toutputStructure\n\t\t\t\t\t);\n\t\t\t\t\tif (currentDigest === state.previousInputsDigest) {\n\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t`Compilation skipped — inputs unchanged (${outputStructure})`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// On a fresh process, seed previousCompilation from on-disk hashes\n\t\t\t\t// so the first compile is a no-op when inputs are unchanged. Avoids\n\t\t\t\t// racing concurrent readers that wiping outdir would interrupt.\n\t\t\t\tconst seededPrevious =\n\t\t\t\t\tstate.previousCompilation ??\n\t\t\t\t\t(await seedPreviousCompilationFromOutdir({\n\t\t\t\t\t\toutdir: args.outdir,\n\t\t\t\t\t\tfs: args.fs?.promises,\n\t\t\t\t\t}));\n\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\tpreviousCompilation: seededPrevious,\n\t\t\t\t\toutputStructure,\n\t\t\t\t\tisServer,\n\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\t// after the args spread so a user-provided fs doesn't bypass\n\t\t\t\t\t// the read tracking (trackedFs wraps args.fs when provided)\n\t\t\t\t\tfs: trackedFs,\n\t\t\t\t});\n\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\tstate,\n\t\t\t\t\targs,\n\t\t\t\t\toutputStructure\n\t\t\t\t);\n\t\t\t\tlogger.success(`Compilation complete (${outputStructure})`);\n\t\t\t} catch (error) {\n\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\tlogger.error(\"Failed to compile project:\", (error as Error).message);\n\t\t\t\tlogger.info(\"Please check your translation files for syntax errors.\");\n\t\t\t\tif (isProduction) throw error;\n\t\t\t} finally {\n\t\t\t\t// in any case add the files to watch\n\t\t\t\tconst targets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\t\tfor (const filePath of targets.files) {\n\t\t\t\t\tthis.addWatchFile(filePath);\n\t\t\t\t}\n\t\t\t\tfor (const directoryPath of targets.directories) {\n\t\t\t\t\tthis.addWatchFile(directoryPath);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync watchChange(path) {\n\t\t\tconst normalizedPath = nodeNormalizePath(path);\n\t\t\tconst targets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\tif (targets.isIgnoredPath(normalizedPath)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst shouldCompile =\n\t\t\t\ttargets.files.has(normalizedPath) ||\n\t\t\t\tisPathWithinDirectories(normalizedPath, targets.directories);\n\t\t\tif (shouldCompile === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\n\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\tconst outputStructure =\n\t\t\t\targs.outputStructure ??\n\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\n\t\t\tconst previouslyReadFiles = new Set(readFiles);\n\n\t\t\ttry {\n\t\t\t\tlogger.info(\n\t\t\t\t\t`Re-compiling inlang project... File \"${relative(process.cwd(), path)}\" has changed.`\n\t\t\t\t);\n\n\t\t\t\t// Clear readFiles to track fresh file reads\n\t\t\t\tclearReadFiles();\n\n\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\tpreviousCompilation: state.previousCompilation,\n\t\t\t\t\toutputStructure,\n\t\t\t\t\tisServer,\n\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\tfs: trackedFs,\n\t\t\t\t});\n\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\tstate,\n\t\t\t\t\targs,\n\t\t\t\t\toutputStructure\n\t\t\t\t);\n\n\t\t\t\tlogger.success(`Re-compilation complete (${outputStructure})`);\n\n\t\t\t\t// Add any new files to watch\n\t\t\t\tconst nextTargets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\t\tfor (const filePath of nextTargets.files) {\n\t\t\t\t\tthis.addWatchFile(filePath);\n\t\t\t\t}\n\t\t\t\tfor (const directoryPath of nextTargets.directories) {\n\t\t\t\t\tthis.addWatchFile(directoryPath);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tclearReadFiles();\n\t\t\t\tfor (const filePath of previouslyReadFiles) {\n\t\t\t\t\treadFiles.add(filePath);\n\t\t\t\t}\n\t\t\t\t// Reset compilation result on error\n\t\t\t\tstate.previousCompilation = undefined;\n\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\tlogger.warn(\"Failed to re-compile project:\", (e as Error).message);\n\t\t\t}\n\t\t},\n\t\tvite: {\n\t\t\tconfig: {\n\t\t\t\thandler: () => {\n\t\t\t\t\tisServer = \"import.meta.env?.SSR ?? typeof window === 'undefined'\";\n\t\t\t\t},\n\t\t\t},\n\t\t\tconfigEnvironment: {\n\t\t\t\thandler: () => {\n\t\t\t\t\tisServer = \"import.meta.env?.SSR ?? typeof window === 'undefined'\";\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\twebpack(compiler) {\n\t\t\tcompiler.options.resolve = {\n\t\t\t\t...compiler.options.resolve,\n\t\t\t\tfallback: {\n\t\t\t\t\t...compiler.options.resolve?.fallback,\n\t\t\t\t\t// https://stackoverflow.com/a/72989932\n\t\t\t\t\tasync_hooks: false,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tcompiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, async () => {\n\t\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\t\tconst outputStructure =\n\t\t\t\t\targs.outputStructure ??\n\t\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\t\t\t\ttry {\n\t\t\t\t\t// Multi-compiler webpack setups (client + server) trigger\n\t\t\t\t\t// beforeRun once per compiler — skip when inputs are unchanged.\n\t\t\t\t\tif (state.previousCompilation && state.previousInputsDigest) {\n\t\t\t\t\t\tconst currentDigest = await computeInputsDigest(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\targs,\n\t\t\t\t\t\t\toutputStructure\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (currentDigest === state.previousInputsDigest) {\n\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t`Compilation skipped — inputs unchanged (${outputStructure})`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst seededPrevious =\n\t\t\t\t\t\tstate.previousCompilation ??\n\t\t\t\t\t\t(await seedPreviousCompilationFromOutdir({\n\t\t\t\t\t\t\toutdir: args.outdir,\n\t\t\t\t\t\t\tfs: args.fs?.promises,\n\t\t\t\t\t\t}));\n\t\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\t\tpreviousCompilation: seededPrevious,\n\t\t\t\t\t\toutputStructure,\n\t\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\t\tfs: trackedFs,\n\t\t\t\t\t});\n\t\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\toutputStructure\n\t\t\t\t\t);\n\t\t\t\t\tlogger.success(`Compilation complete (${outputStructure})`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\t\tlogger.warn(\"Failed to compile project:\", (error as Error).message);\n\t\t\t\t\tlogger.warn(\"Please check your translation files for syntax errors.\");\n\t\t\t\t\tif (isProduction) throw error;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n};\n"]}
1
+ {"version":3,"file":"unplugin.js","sourceRoot":"","sources":["../../src/bundler-plugins/unplugin.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UnpluginFactory } from \"unplugin\";\nimport { compile, type CompilationResult } from \"../compiler/compile.js\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport nodeFs from \"node:fs\";\nimport { Logger } from \"../services/logger/index.js\";\nimport { ENV_VARIABLES } from \"../services/env-variables/index.js\";\nimport type { CompilerOptions } from \"../compiler/compiler-options.js\";\nimport {\n\tcreateTrackedFs,\n\tgetWatchTargets,\n\tisPathWithinDirectories,\n} from \"../services/file-watching/tracked-fs.js\";\nimport { nodeNormalizePath } from \"../utilities/node-normalize-path.js\";\nimport { seedPreviousCompilationFromOutdir } from \"../compiler/seed-previous-compilation.js\";\n\nconst PLUGIN_NAME = \"unplugin-paraglide-js\";\n\nconst logger = new Logger();\n\nconst PERSISTENT_CACHE_VERSION = 1;\n\ntype PersistentCompilationCache = {\n\tversion: typeof PERSISTENT_CACHE_VERSION;\n\tcompilerVersion: string;\n\tinputsDigest: string;\n\treadFiles: string[];\n\toutputHashes: Record<string, string>;\n};\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t!Array.isArray(value) &&\n\t\tObject.values(value).every((entry) => typeof entry === \"string\")\n\t);\n}\n\n/**\n * Default isServer which differs per bundler.\n */\nlet isServer: string | undefined;\n\ntype PluginState = {\n\t/** Identity of the fs the tracked wrapper was created around. */\n\tbaseFs: typeof nodeFs | undefined;\n\ttrackedFs: typeof nodeFs;\n\treadFiles: Set<string>;\n\tclearReadFiles: () => void;\n\tpreviousCompilation: CompilationResult | undefined;\n\t/**\n\t * Digest of the input files and options of the last successful compilation.\n\t *\n\t * `vite build` fires `buildStart` once per environment (client, ssr, ...).\n\t * When the digest of the current inputs matches, `compile()` is skipped\n\t * entirely — project loading and message compilation are expensive even\n\t * when `previousCompilation` dedupes the writes.\n\t *\n\t * https://github.com/opral/paraglide-js/issues/693\n\t */\n\tpreviousInputsDigest: string | undefined;\n};\n\n// Module-scoped so the warm state survives plugin re-instantiation within\n// one process (e.g. a vite config reload), but recreated when a different\n// fs is passed — the tracked wrapper, read set, and cached compilation are\n// only valid for the filesystem they were produced from.\nlet pluginState: PluginState | undefined;\n\nfunction getPluginState(args: CompilerOptions): PluginState {\n\tif (pluginState === undefined || pluginState.baseFs !== args.fs) {\n\t\tconst tracked = createTrackedFs({ fs: args.fs });\n\t\tpluginState = {\n\t\t\tbaseFs: args.fs,\n\t\t\ttrackedFs: tracked.fs,\n\t\t\treadFiles: tracked.readFiles,\n\t\t\tclearReadFiles: tracked.clearReadFiles,\n\t\t\tpreviousCompilation: undefined,\n\t\t\tpreviousInputsDigest: undefined,\n\t\t};\n\t}\n\treturn pluginState;\n}\n\nfunction withoutCleanOutdir(\n\targs: CompilerOptions\n): Omit<CompilerOptions, \"cleanOutdir\"> {\n\tconst { cleanOutdir, ...compileArgs } = args;\n\tvoid cleanOutdir;\n\treturn compileArgs;\n}\n\nfunction getCompilerConfig(\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n) {\n\tconst { fs: _fs, ...serializableArgs } = args;\n\tvoid _fs;\n\treturn {\n\t\t...serializableArgs,\n\t\toutputStructure,\n\t\tisServer,\n\t\tcompilerVersion: ENV_VARIABLES.PARJS_PACKAGE_VERSION,\n\t};\n}\n\n/**\n * Hashes the files (and directory listings) the last compilation read,\n * together with the options that affect the output. Returns `undefined`\n * when the digest can't be computed (no tracked reads yet, an unexpected\n * read error, ...) — `undefined` never matches, so the caller compiles.\n *\n * Directory listings are included so that a message file *added* next to\n * the tracked ones invalidates the digest, not only edits to known files.\n * All components are length-prefixed so distinct input states can't\n * produce the same hash stream.\n *\n * The digest is taken after the compile, by re-reading the inputs. A file\n * edited *during* a compile can therefore be hashed at its new content\n * while the output reflects the old one — accepted: in dev, watchChange\n * recompiles on that edit, and a fresh build process always recompiles.\n */\nasync function computeInputsDigest(\n\tstate: PluginState,\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): Promise<string | undefined> {\n\tif (state.readFiles.size === 0) {\n\t\treturn undefined;\n\t}\n\tconst targets = getWatchTargets(state.readFiles, { outdir: args.outdir });\n\tif (targets.files.size === 0) {\n\t\treturn undefined;\n\t}\n\tconst fsp = (args.fs ?? nodeFs).promises;\n\tconst hash = createHash(\"sha256\");\n\ttry {\n\t\thash.update(JSON.stringify(getCompilerConfig(args, outputStructure)));\n\t\tfor (const directoryPath of [...targets.directories].sort()) {\n\t\t\tconst entries = await fsp\n\t\t\t\t.readdir(directoryPath)\n\t\t\t\t// tracked reads include probed-but-absent paths (the SDK reads\n\t\t\t\t// optional files and handles ENOENT itself) — a missing entry\n\t\t\t\t// is valid input state, hash it as such\n\t\t\t\t.catch(rethrowUnlessEnoent);\n\t\t\thash.update(`\\0dir:${directoryPath.length}:${directoryPath}:`);\n\t\t\tif (entries === undefined) {\n\t\t\t\thash.update(\"missing\");\n\t\t\t} else {\n\t\t\t\tfor (const entry of [...entries].sort()) {\n\t\t\t\t\thash.update(`${entry.length}:${entry},`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const filePath of [...targets.files].sort()) {\n\t\t\tconst content = await fsp.readFile(filePath).catch(rethrowUnlessEnoent);\n\t\t\thash.update(`\\0file:${filePath.length}:${filePath}:`);\n\t\t\tif (content === undefined) {\n\t\t\t\thash.update(\"missing\");\n\t\t\t} else {\n\t\t\t\thash.update(`${content.length}:`);\n\t\t\t\thash.update(content);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn hash.digest(\"hex\");\n}\n\nfunction getPersistentCachePath(\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): string {\n\tconst absoluteOutdir = resolve(process.cwd(), args.outdir);\n\tconst cacheKey = createHash(\"sha256\")\n\t\t.update(\n\t\t\tJSON.stringify({\n\t\t\t\tabsoluteOutdir,\n\t\t\t\tcompilerConfig: getCompilerConfig(args, outputStructure),\n\t\t\t})\n\t\t)\n\t\t.digest(\"hex\")\n\t\t.slice(0, 16);\n\treturn resolve(\n\t\tprocess.cwd(),\n\t\targs.project,\n\t\t\"cache\",\n\t\t\"paraglide-js\",\n\t\t`${cacheKey}.json`\n\t);\n}\n\nasync function readPersistentCache(\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): Promise<PersistentCompilationCache | undefined> {\n\tconst fsp = (args.fs ?? nodeFs).promises;\n\ttry {\n\t\tconst parsed = JSON.parse(\n\t\t\tawait fsp.readFile(getPersistentCachePath(args, outputStructure), \"utf8\")\n\t\t) as Partial<PersistentCompilationCache>;\n\t\tif (\n\t\t\tparsed.version !== PERSISTENT_CACHE_VERSION ||\n\t\t\tparsed.compilerVersion !== ENV_VARIABLES.PARJS_PACKAGE_VERSION ||\n\t\t\ttypeof parsed.inputsDigest !== \"string\" ||\n\t\t\t!Array.isArray(parsed.readFiles) ||\n\t\t\tparsed.readFiles.some((file) => typeof file !== \"string\") ||\n\t\t\t!isStringRecord(parsed.outputHashes)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn parsed as PersistentCompilationCache;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nasync function preparePersistentCacheDirectory(\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): Promise<void> {\n\ttry {\n\t\tawait (args.fs ?? nodeFs).promises.mkdir(\n\t\t\tdirname(getPersistentCachePath(args, outputStructure)),\n\t\t\t{ recursive: true }\n\t\t);\n\t} catch {\n\t\t// The cache is an optimization. Read-only projects must still compile.\n\t}\n}\n\nasync function writePersistentCache(\n\tstate: PluginState,\n\targs: CompilerOptions,\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>\n): Promise<void> {\n\tif (\n\t\tstate.previousInputsDigest === undefined ||\n\t\tstate.previousCompilation?.outputHashes === undefined\n\t) {\n\t\treturn;\n\t}\n\tconst cachePath = getPersistentCachePath(args, outputStructure);\n\tconst cache: PersistentCompilationCache = {\n\t\tversion: PERSISTENT_CACHE_VERSION,\n\t\tcompilerVersion: ENV_VARIABLES.PARJS_PACKAGE_VERSION,\n\t\tinputsDigest: state.previousInputsDigest,\n\t\treadFiles: [...state.readFiles].sort(),\n\t\toutputHashes: state.previousCompilation.outputHashes,\n\t};\n\tconst fsp = (args.fs ?? nodeFs).promises;\n\ttry {\n\t\tawait fsp.mkdir(dirname(cachePath), { recursive: true });\n\t\tawait fsp.writeFile(cachePath, JSON.stringify(cache));\n\t} catch {\n\t\t// The cache is an optimization. Read-only projects must still compile.\n\t}\n}\n\nfunction outputHashesMatch(\n\tleft: Record<string, string> | undefined,\n\tright: Record<string, string>\n): boolean {\n\tif (left === undefined) return false;\n\tconst leftEntries = Object.entries(left);\n\tconst rightEntries = Object.entries(right);\n\tif (leftEntries.length !== rightEntries.length) return false;\n\treturn leftEntries.every(([file, hash]) => right[file] === hash);\n}\n\nasync function restorePersistentCache(args: {\n\tstate: PluginState;\n\tcompilerOptions: CompilerOptions;\n\toutputStructure: NonNullable<CompilerOptions[\"outputStructure\"]>;\n}): Promise<boolean> {\n\tconst cached = await readPersistentCache(\n\t\targs.compilerOptions,\n\t\targs.outputStructure\n\t);\n\tif (cached === undefined) return false;\n\n\tconst cachedReadFiles = new Set<string>();\n\tfor (const file of cached.readFiles) {\n\t\tcachedReadFiles.add(file);\n\t}\n\tconst validationState: PluginState = {\n\t\t...args.state,\n\t\treadFiles: cachedReadFiles,\n\t\tclearReadFiles: () => cachedReadFiles.clear(),\n\t};\n\tconst [inputsDigest, previousCompilation] = await Promise.all([\n\t\tcomputeInputsDigest(\n\t\t\tvalidationState,\n\t\t\targs.compilerOptions,\n\t\t\targs.outputStructure\n\t\t),\n\t\tseedPreviousCompilationFromOutdir({\n\t\t\toutdir: args.compilerOptions.outdir,\n\t\t\tfs: args.compilerOptions.fs?.promises,\n\t\t}),\n\t]);\n\tif (\n\t\tinputsDigest !== cached.inputsDigest ||\n\t\t!outputHashesMatch(previousCompilation?.outputHashes, cached.outputHashes)\n\t) {\n\t\treturn false;\n\t}\n\n\targs.state.clearReadFiles();\n\tfor (const file of cachedReadFiles) {\n\t\targs.state.readFiles.add(file);\n\t}\n\targs.state.previousCompilation = previousCompilation;\n\targs.state.previousInputsDigest = inputsDigest;\n\treturn true;\n}\n\nfunction rethrowUnlessEnoent(error: unknown): undefined {\n\tif ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n\t\treturn undefined;\n\t}\n\tthrow error;\n}\n\nexport const unpluginFactory: UnpluginFactory<CompilerOptions> = (args) => {\n\tconst state = getPluginState(args);\n\tconst { trackedFs, readFiles, clearReadFiles } = state;\n\treturn {\n\t\tname: PLUGIN_NAME,\n\t\tenforce: \"pre\",\n\t\tasync buildStart() {\n\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\tconst outputStructure =\n\t\t\t\targs.outputStructure ??\n\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\t\t\ttry {\n\t\t\t\t// Stabilize project directory listings before the first digest. The\n\t\t\t\t// ignored cache directory must not invalidate the cache that creates it.\n\t\t\t\tawait preparePersistentCacheDirectory(args, outputStructure);\n\t\t\t\tif (\n\t\t\t\t\tstate.previousCompilation === undefined &&\n\t\t\t\t\t(await restorePersistentCache({\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\tcompilerOptions: args,\n\t\t\t\t\t\toutputStructure,\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t`Compilation skipped — inputs unchanged (${outputStructure})`\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// `vite build` calls buildStart once per environment (client, ssr).\n\t\t\t\t// Skip the expensive compile when the inputs haven't changed.\n\t\t\t\tif (state.previousCompilation && state.previousInputsDigest) {\n\t\t\t\t\tconst currentDigest = await computeInputsDigest(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\toutputStructure\n\t\t\t\t\t);\n\t\t\t\t\tif (currentDigest === state.previousInputsDigest) {\n\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t`Compilation skipped — inputs unchanged (${outputStructure})`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// On a fresh process, seed previousCompilation from on-disk hashes\n\t\t\t\t// so the first compile is a no-op when inputs are unchanged. Avoids\n\t\t\t\t// racing concurrent readers that wiping outdir would interrupt.\n\t\t\t\tconst seededPrevious =\n\t\t\t\t\tstate.previousCompilation ??\n\t\t\t\t\t(await seedPreviousCompilationFromOutdir({\n\t\t\t\t\t\toutdir: args.outdir,\n\t\t\t\t\t\tfs: args.fs?.promises,\n\t\t\t\t\t}));\n\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\tpreviousCompilation: seededPrevious,\n\t\t\t\t\toutputStructure,\n\t\t\t\t\tisServer,\n\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\t// after the args spread so a user-provided fs doesn't bypass\n\t\t\t\t\t// the read tracking (trackedFs wraps args.fs when provided)\n\t\t\t\t\tfs: trackedFs,\n\t\t\t\t});\n\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\tstate,\n\t\t\t\t\targs,\n\t\t\t\t\toutputStructure\n\t\t\t\t);\n\t\t\t\tawait writePersistentCache(state, args, outputStructure);\n\t\t\t\tlogger.success(`Compilation complete (${outputStructure})`);\n\t\t\t} catch (error) {\n\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\tlogger.error(\"Failed to compile project:\", (error as Error).message);\n\t\t\t\tlogger.info(\"Please check your translation files for syntax errors.\");\n\t\t\t\tif (isProduction) throw error;\n\t\t\t} finally {\n\t\t\t\t// in any case add the files to watch\n\t\t\t\tconst targets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\t\tfor (const filePath of targets.files) {\n\t\t\t\t\tthis.addWatchFile(filePath);\n\t\t\t\t}\n\t\t\t\tfor (const directoryPath of targets.directories) {\n\t\t\t\t\tthis.addWatchFile(directoryPath);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync watchChange(path) {\n\t\t\tconst normalizedPath = nodeNormalizePath(path);\n\t\t\tconst targets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\tif (targets.isIgnoredPath(normalizedPath)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst shouldCompile =\n\t\t\t\ttargets.files.has(normalizedPath) ||\n\t\t\t\tisPathWithinDirectories(normalizedPath, targets.directories);\n\t\t\tif (shouldCompile === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\n\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\tconst outputStructure =\n\t\t\t\targs.outputStructure ??\n\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\n\t\t\tconst previouslyReadFiles = new Set(readFiles);\n\n\t\t\ttry {\n\t\t\t\tlogger.info(\n\t\t\t\t\t`Re-compiling inlang project... File \"${relative(process.cwd(), path)}\" has changed.`\n\t\t\t\t);\n\n\t\t\t\t// Clear readFiles to track fresh file reads\n\t\t\t\tclearReadFiles();\n\n\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\tpreviousCompilation: state.previousCompilation,\n\t\t\t\t\toutputStructure,\n\t\t\t\t\tisServer,\n\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\tfs: trackedFs,\n\t\t\t\t});\n\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\tstate,\n\t\t\t\t\targs,\n\t\t\t\t\toutputStructure\n\t\t\t\t);\n\t\t\t\tawait writePersistentCache(state, args, outputStructure);\n\n\t\t\t\tlogger.success(`Re-compilation complete (${outputStructure})`);\n\n\t\t\t\t// Add any new files to watch\n\t\t\t\tconst nextTargets = getWatchTargets(readFiles, { outdir: args.outdir });\n\t\t\t\tfor (const filePath of nextTargets.files) {\n\t\t\t\t\tthis.addWatchFile(filePath);\n\t\t\t\t}\n\t\t\t\tfor (const directoryPath of nextTargets.directories) {\n\t\t\t\t\tthis.addWatchFile(directoryPath);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tclearReadFiles();\n\t\t\t\tfor (const filePath of previouslyReadFiles) {\n\t\t\t\t\treadFiles.add(filePath);\n\t\t\t\t}\n\t\t\t\t// Reset compilation result on error\n\t\t\t\tstate.previousCompilation = undefined;\n\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\tlogger.warn(\"Failed to re-compile project:\", (e as Error).message);\n\t\t\t}\n\t\t},\n\t\tvite: {\n\t\t\tconfig: {\n\t\t\t\thandler: () => {\n\t\t\t\t\tisServer = \"import.meta.env?.SSR ?? typeof window === 'undefined'\";\n\t\t\t\t},\n\t\t\t},\n\t\t\tconfigEnvironment: {\n\t\t\t\thandler: () => {\n\t\t\t\t\tisServer = \"import.meta.env?.SSR ?? typeof window === 'undefined'\";\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\twebpack(compiler) {\n\t\t\tcompiler.options.resolve = {\n\t\t\t\t...compiler.options.resolve,\n\t\t\t\tfallback: {\n\t\t\t\t\t...compiler.options.resolve?.fallback,\n\t\t\t\t\t// https://stackoverflow.com/a/72989932\n\t\t\t\t\tasync_hooks: false,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tcompiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, async () => {\n\t\t\t\tconst isProduction = process.env.NODE_ENV === \"production\";\n\t\t\t\t// default to locale-modules for development to speed up the dev server\n\t\t\t\t// https://github.com/opral/inlang-paraglide-js/issues/486\n\t\t\t\tconst outputStructure =\n\t\t\t\t\targs.outputStructure ??\n\t\t\t\t\t(isProduction ? \"message-modules\" : \"locale-modules\");\n\t\t\t\ttry {\n\t\t\t\t\t// Multi-compiler webpack setups (client + server) trigger\n\t\t\t\t\t// beforeRun once per compiler — skip when inputs are unchanged.\n\t\t\t\t\tif (state.previousCompilation && state.previousInputsDigest) {\n\t\t\t\t\t\tconst currentDigest = await computeInputsDigest(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\targs,\n\t\t\t\t\t\t\toutputStructure\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (currentDigest === state.previousInputsDigest) {\n\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t`Compilation skipped — inputs unchanged (${outputStructure})`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst seededPrevious =\n\t\t\t\t\t\tstate.previousCompilation ??\n\t\t\t\t\t\t(await seedPreviousCompilationFromOutdir({\n\t\t\t\t\t\t\toutdir: args.outdir,\n\t\t\t\t\t\t\tfs: args.fs?.promises,\n\t\t\t\t\t\t}));\n\t\t\t\t\tstate.previousCompilation = await compile({\n\t\t\t\t\t\tpreviousCompilation: seededPrevious,\n\t\t\t\t\t\toutputStructure,\n\t\t\t\t\t\t...withoutCleanOutdir(args),\n\t\t\t\t\t\tcleanOutdir: false,\n\t\t\t\t\t\tfs: trackedFs,\n\t\t\t\t\t});\n\t\t\t\t\tstate.previousInputsDigest = await computeInputsDigest(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\toutputStructure\n\t\t\t\t\t);\n\t\t\t\t\tlogger.success(`Compilation complete (${outputStructure})`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.previousInputsDigest = undefined;\n\t\t\t\t\tlogger.warn(\"Failed to compile project:\", (error as Error).message);\n\t\t\t\t\tlogger.warn(\"Please check your translation files for syntax errors.\");\n\t\t\t\t\tif (isProduction) throw error;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n};\n"]}
@@ -160,6 +160,83 @@ test("vite plugin warm-restart writes nothing when inputs unchanged (#659)", asy
160
160
  await plugin2.buildStart?.call(mockContext);
161
161
  expect(writeFileSpy).not.toHaveBeenCalled();
162
162
  });
163
+ // Regression test for https://github.com/opral/paraglide-js/issues/741:
164
+ // a new Vite process should validate the persisted inputs and output instead
165
+ // of loading the project and compiling every message again.
166
+ test("vite plugin skips compile on an unchanged fresh process (#741)", async () => {
167
+ const actualCompileModule = await vi.importActual("../compiler/compile.js");
168
+ const compileSpy = vi.fn(actualCompileModule.compile);
169
+ vi.doMock("../compiler/compile.js", () => ({
170
+ ...actualCompileModule,
171
+ compile: compileSpy,
172
+ }));
173
+ try {
174
+ const project = await loadProjectInMemory({
175
+ blob: await newProject({
176
+ settings: { baseLocale: "en", locales: ["en", "de"] },
177
+ }),
178
+ });
179
+ const fs = memfs().fs;
180
+ await saveProjectToDirectory({
181
+ project,
182
+ path: "/project.inlang",
183
+ fs: fs.promises,
184
+ });
185
+ const options = {
186
+ project: "/project.inlang",
187
+ outdir: "/test-output",
188
+ emitReadme: true,
189
+ fs,
190
+ };
191
+ const mockContext = { addWatchFile: () => { } };
192
+ const startFreshProcess = async () => {
193
+ vi.resetModules();
194
+ const { paraglideVitePlugin } = await import("../bundler-plugins/vite.js");
195
+ const plugin = paraglideVitePlugin(options);
196
+ await plugin.buildStart?.call(mockContext);
197
+ };
198
+ await startFreshProcess();
199
+ expect(compileSpy).toHaveBeenCalledTimes(1);
200
+ // The persisted cache makes the unchanged cold restart skip compile().
201
+ await startFreshProcess();
202
+ expect(compileSpy).toHaveBeenCalledTimes(1);
203
+ // A file added beside a tracked project input invalidates the cache.
204
+ await fs.promises.writeFile("/project.inlang/new-project-input.txt", "new");
205
+ await startFreshProcess();
206
+ expect(compileSpy).toHaveBeenCalledTimes(2);
207
+ // Compiler options are part of the cache key.
208
+ options.emitReadme = false;
209
+ await startFreshProcess();
210
+ expect(compileSpy).toHaveBeenCalledTimes(3);
211
+ // Generated output is validated too, so edited output self-repairs.
212
+ await fs.promises.writeFile("/test-output/runtime.js", "tampered");
213
+ await startFreshProcess();
214
+ expect(compileSpy).toHaveBeenCalledTimes(4);
215
+ expect(await fs.promises.readFile("/test-output/runtime.js", "utf8")).not.toBe("tampered");
216
+ // A compiler version change invalidates the persisted cache.
217
+ const cacheDirectory = "/project.inlang/cache/paraglide-js";
218
+ for (const cacheFile of await fs.promises.readdir(cacheDirectory)) {
219
+ const cachePath = `${cacheDirectory}/${cacheFile}`;
220
+ const cache = JSON.parse(await fs.promises.readFile(cachePath, "utf8"));
221
+ cache.compilerVersion = "0.0.0-stale";
222
+ await fs.promises.writeFile(cachePath, JSON.stringify(cache));
223
+ }
224
+ await startFreshProcess();
225
+ expect(compileSpy).toHaveBeenCalledTimes(5);
226
+ // A syntactically valid but malformed cache is treated as a miss.
227
+ for (const cacheFile of await fs.promises.readdir(cacheDirectory)) {
228
+ const cachePath = `${cacheDirectory}/${cacheFile}`;
229
+ const cache = JSON.parse(await fs.promises.readFile(cachePath, "utf8"));
230
+ cache.outputHashes = null;
231
+ await fs.promises.writeFile(cachePath, JSON.stringify(cache));
232
+ }
233
+ await startFreshProcess();
234
+ expect(compileSpy).toHaveBeenCalledTimes(6);
235
+ }
236
+ finally {
237
+ vi.doUnmock("../compiler/compile.js");
238
+ }
239
+ });
163
240
  // Regression test for https://github.com/opral/paraglide-js/issues/693:
164
241
  // `vite build` fires buildStart once per environment (client, ssr) and each
165
242
  // run used to do a full compile() — project loading + message compilation —