@inlang/paraglide-js 2.24.0 → 2.25.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 (85) hide show
  1. package/dist/bundler-plugins/esbuild.d.ts +1 -1
  2. package/dist/bundler-plugins/per-locale-build/index.d.ts +3 -3
  3. package/dist/bundler-plugins/per-locale-build/index.js +59 -15
  4. package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
  5. package/dist/bundler-plugins/rolldown.d.ts +1 -1
  6. package/dist/bundler-plugins/rollup.d.ts +1 -1
  7. package/dist/bundler-plugins/rspack.d.ts +1 -1
  8. package/dist/bundler-plugins/unplugin.d.ts +35 -1
  9. package/dist/bundler-plugins/unplugin.js +404 -123
  10. package/dist/bundler-plugins/unplugin.js.map +1 -1
  11. package/dist/bundler-plugins/unplugin.test.js +357 -202
  12. package/dist/bundler-plugins/unplugin.test.js.map +1 -1
  13. package/dist/bundler-plugins/vite.d.ts +2 -2
  14. package/dist/bundler-plugins/vite.js.map +1 -1
  15. package/dist/bundler-plugins/vite.test.js +2 -1
  16. package/dist/bundler-plugins/vite.test.js.map +1 -1
  17. package/dist/bundler-plugins/webpack.d.ts +1 -1
  18. package/dist/cli/commands/compile/command.js +156 -36
  19. package/dist/cli/commands/compile/command.js.map +1 -1
  20. package/dist/cli/commands/compile/command.test.js +311 -7
  21. package/dist/cli/commands/compile/command.test.js.map +1 -1
  22. package/dist/cli/defaults.d.ts +0 -2
  23. package/dist/cli/defaults.js +0 -2
  24. package/dist/cli/defaults.js.map +1 -1
  25. package/dist/cli/steps/initialize-inlang-project.js +2 -1
  26. package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
  27. package/dist/cli/steps/prompt-for-outdir.js +1 -1
  28. package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
  29. package/dist/compiler/compile-annotation.d.ts +2 -2
  30. package/dist/compiler/compile-annotation.js +9 -9
  31. package/dist/compiler/compile-annotation.js.map +1 -1
  32. package/dist/compiler/compile-local-variable.d.ts +2 -1
  33. package/dist/compiler/compile-local-variable.js +4 -4
  34. package/dist/compiler/compile-local-variable.js.map +1 -1
  35. package/dist/compiler/compile-local-variable.test.js +82 -0
  36. package/dist/compiler/compile-local-variable.test.js.map +1 -1
  37. package/dist/compiler/compile-message.js +10 -2
  38. package/dist/compiler/compile-message.js.map +1 -1
  39. package/dist/compiler/compile-message.test.js +132 -2
  40. package/dist/compiler/compile-message.test.js.map +1 -1
  41. package/dist/compiler/compile-pattern.js +4 -2
  42. package/dist/compiler/compile-pattern.js.map +1 -1
  43. package/dist/compiler/compile-pattern.test.js +31 -0
  44. package/dist/compiler/compile-pattern.test.js.map +1 -1
  45. package/dist/compiler/compiler-options.d.ts +1 -1
  46. package/dist/compiler/compiler-options.js.map +1 -1
  47. package/dist/compiler/server/create-server-file.js +18 -4
  48. package/dist/compiler/server/create-server-file.js.map +1 -1
  49. package/dist/compiler/server/create-server-file.test.js +76 -0
  50. package/dist/compiler/server/create-server-file.test.js.map +1 -1
  51. package/dist/compiler/variable-access.d.ts +2 -0
  52. package/dist/compiler/variable-access.js +6 -0
  53. package/dist/compiler/variable-access.js.map +1 -1
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.js +1 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/services/config/config-schema.d.ts +69 -0
  58. package/dist/services/config/config-schema.js +78 -0
  59. package/dist/services/config/config-schema.js.map +1 -0
  60. package/dist/services/config/defaults.d.ts +11 -0
  61. package/dist/services/config/defaults.js +12 -0
  62. package/dist/services/config/defaults.js.map +1 -0
  63. package/dist/services/config/discover-config-file.d.ts +19 -0
  64. package/dist/services/config/discover-config-file.js +39 -0
  65. package/dist/services/config/discover-config-file.js.map +1 -0
  66. package/dist/services/config/index.d.ts +24 -0
  67. package/dist/services/config/index.js +25 -0
  68. package/dist/services/config/index.js.map +1 -0
  69. package/dist/services/config/load-paraglide-config.d.ts +44 -0
  70. package/dist/services/config/load-paraglide-config.js +109 -0
  71. package/dist/services/config/load-paraglide-config.js.map +1 -0
  72. package/dist/services/config/load-paraglide-config.test.d.ts +1 -0
  73. package/dist/services/config/load-paraglide-config.test.js +201 -0
  74. package/dist/services/config/load-paraglide-config.test.js.map +1 -0
  75. package/dist/services/config/resolve-compiler-options.d.ts +24 -0
  76. package/dist/services/config/resolve-compiler-options.js +51 -0
  77. package/dist/services/config/resolve-compiler-options.js.map +1 -0
  78. package/dist/services/config/resolve-compiler-options.test.d.ts +1 -0
  79. package/dist/services/config/resolve-compiler-options.test.js +60 -0
  80. package/dist/services/config/resolve-compiler-options.test.js.map +1 -0
  81. package/dist/services/env-variables/index.js +1 -1
  82. package/dist/services/env-variables/index.js.map +1 -1
  83. package/dist/services/logger/index.js +2 -0
  84. package/dist/services/logger/index.js.map +1 -1
  85. package/package.json +5 -3
@@ -1 +1 @@
1
- {"version":3,"file":"unplugin.test.js","sourceRoot":"","sources":["../../src/bundler-plugins/unplugin.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACjE,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EACN,mBAAmB,EACnB,UAAU,EACV,sBAAsB,GACtB,MAAM,aAAa,CAAC;AAErB,IAAI,eAAmC,CAAC;AAExC,UAAU,CAAC,GAAG,EAAE;IACf,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAEvC,wDAAwD;IACxD,mDAAmD;IACnD,EAAE,CAAC,YAAY,EAAE,CAAC;IAElB,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACd,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,eAAe,CAAC;IACxC,CAAC;SAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC7B,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;IAC5E,yEAAyE;IACzE,2DAA2D;IAC3D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE3E,8DAA8D;IAC9D,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;QACzC,IAAI,EAAE,MAAM,UAAU,CAAC;YACtB,QAAQ,EAAE;gBACT,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;aAC3B;SACD,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE7D,MAAM,sBAAsB,CAAC;QAC5B,OAAO;QACP,IAAI,EAAE,iBAAiB;QACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;KACf,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,mBAAmB,CAAC;QAClC,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,EAAE;KACN,CAAQ,CAAC;IAEV,MAAM,WAAW,GAAG;QACnB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;KACtB,CAAC;IAEF,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IAClF,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,wDAAwD;IACxD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE7D,MAAM,MAAM,GAAG,mBAAmB,CAAC;QAClC,OAAO,EAAE,8BAA8B;QACvC,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,EAAE;KACN,CAAQ,CAAC;IAEV,MAAM,WAAW,GAAG;QACnB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;KACtB,CAAC;IAEF,0DAA0D;IAC1D,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC;IAEpC,wDAAwD;IACxD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE7D,MAAM,MAAM,GAAG,mBAAmB,CAAC;QAClC,OAAO,EAAE,8BAA8B;QACvC,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,EAAE;KACN,CAAQ,CAAC;IAEV,MAAM,WAAW,GAAG;QACnB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;KACtB,CAAC;IAEF,8CAA8C;IAC9C,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,+EAA+E;AAC/E,2EAA2E;AAC3E,uEAAuE;AACvE,2EAA2E;AAC3E,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IAClF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;QACzC,IAAI,EAAE,MAAM,UAAU,CAAC;YACtB,QAAQ,EAAE;gBACT,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;aAC3B;SACD,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE7D,MAAM,sBAAsB,CAAC;QAC5B,OAAO;QACP,IAAI,EAAE,iBAAiB;QACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;KACf,CAAC,CAAC;IAEH,qEAAqE;IACrE,yCAAyC;IACzC,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG,UAAU,CAAC;QACzB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,cAAc;QACtB,WAAW,EAAE,IAAI;QACjB,EAAE,EAAE,EAAE;KACN,CAAQ,CAAC;IAEV,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAC/C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE3C,qEAAqE;IACrE,oEAAoE;IACpE,mDAAmD;IACnD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACvF,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;QACzC,IAAI,EAAE,MAAM,UAAU,CAAC;YACtB,QAAQ,EAAE;gBACT,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;aAC3B;SACD,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE7D,MAAM,sBAAsB,CAAC;QAC5B,OAAO;QACP,IAAI,EAAE,iBAAiB;QACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;KACf,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAE/C,sDAAsD;IACtD,CAAC;QACA,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,UAAU,CAAC;YACzB,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,cAAc;YACtB,EAAE,EAAE,EAAE;SACN,CAAQ,CAAC;QACV,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,EAAE,CAAC,YAAY,EAAE,CAAC;IAClB,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAE,GAC7C,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,eAAe,CAAC;QAC/B,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,EAAE;KACN,CAAQ,CAAC;IAEV,MAAM,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACxD,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5C,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,wEAAwE;AACxE,6EAA6E;AAC7E,4DAA4D;AAC5D,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;YACzC,IAAI,EAAE,MAAM,UAAU,CAAC;gBACtB,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;aACrD,CAAC;SACF,CAAC,CAAC;QACH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;QAC7D,MAAM,sBAAsB,CAAC;YAC5B,OAAO;YACP,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;SACf,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG;YACf,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,cAAc;YACtB,UAAU,EAAE,IAAI;YAChB,EAAE;SACF,CAAC;QACF,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;QAC/C,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;YACpC,EAAE,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAQ,CAAC;YACnD,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,uEAAuE;QACvE,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,qEAAqE;QACrE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QAC5E,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,8CAA8C;QAC9C,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;QAC3B,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,oEAAoE;QACpE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,yBAAyB,EAAE,UAAU,CAAC,CAAC;QACnE,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CACL,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAC7D,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEvB,6DAA6D;QAC7D,MAAM,cAAc,GAAG,oCAAoC,CAAC;QAC5D,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,GAAG,cAAc,IAAI,SAAS,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;YACxE,KAAK,CAAC,eAAe,GAAG,aAAa,CAAC;YACtC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,kEAAkE;QAClE,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,GAAG,cAAc,IAAI,SAAS,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;YACxE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC1B,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,wEAAwE;AACxE,4EAA4E;AAC5E,4EAA4E;AAC5E,yCAAyC;AACzC,IAAI,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;IACvG,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;YACzC,IAAI,EAAE,MAAM,UAAU,CAAC;gBACtB,QAAQ,EAAE;oBACT,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;iBAC3B;aACD,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;QAE7D,MAAM,sBAAsB,CAAC;YAC5B,OAAO;YACP,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;SACf,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,UAAU,CAAC;YACzB,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,cAAc;YACtB,EAAE,EAAE,EAAE;SACN,CAAQ,CAAC;QAEV,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;QAE/C,4CAA4C;QAC5C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,qEAAqE;QACrE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,gEAAgE;QAChE,MAAM,YAAY,GAAG,+BAA+B,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CACjD,CAAC;QACF,QAAQ,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEpE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,yEAAyE;AACzE,yEAAyE;AACzE,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;IAC5F,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;YACzC,IAAI,EAAE,MAAM,UAAU,CAAC;gBACtB,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;aACrD,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;QAE7D,MAAM,sBAAsB,CAAC;YAC5B,OAAO;YACP,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;SACf,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,UAAU,CAAC;YACzB,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,cAAc;YACtB,EAAE,EAAE,EAAE;SACN,CAAQ,CAAC;QAEV,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;QAE/C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,uEAAuE;QACvE,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QAEtE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,6EAA6E;AAC7E,uDAAuD;AACvD,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IAC1F,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;YACzC,IAAI,EAAE,MAAM,UAAU,CAAC;gBACtB,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;aACrD,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;QAE7D,MAAM,sBAAsB,CAAC;YAC5B,OAAO;YACP,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;SACf,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,UAAU,CAAC;YACzB,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,cAAc;YACtB,EAAE,EAAE,EAAE;SACN,CAAQ,CAAC;QAEV,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;QAE/C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,MAAM,YAAY,GAAG,+BAA+B,CAAC;QACrD,MAAM,gBAAgB,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAE3E,gEAAgE;QAChE,wDAAwD;QACxD,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACxD,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,qEAAqE;QACrE,+DAA+D;QAC/D,uDAAuD;QACvD,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,0EAA0E;AAC1E,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC9F,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE5C,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAChC,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;YACzC,IAAI,EAAE,MAAM,UAAU,CAAC;gBACtB,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE;aAC/C,CAAC;SACF,CAAC,CAAC;QACH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;QAC7D,MAAM,sBAAsB,CAAC;YAC5B,OAAO;YACP,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,EAAE,CAAC,QAAQ;SACf,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAElC,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAE/C,MAAM,OAAO,GAAG,UAAU,CAAC;QAC1B,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,GAAG;KACP,CAAQ,CAAC;IACV,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,UAAU,CAAC;QAC1B,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,cAAc;QACtB,EAAE,EAAE,GAAG;KACP,CAAQ,CAAC;IACV,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5C,wEAAwE;IACxE,qEAAqE;IACrE,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect, beforeEach, afterEach, vi } from \"vitest\";\nimport consola from \"consola\";\nimport { memfs } from \"memfs\";\nimport {\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n} from \"@inlang/sdk\";\n\nlet originalNodeEnv: string | undefined;\n\nbeforeEach(() => {\n\toriginalNodeEnv = process.env.NODE_ENV;\n\n\t// Reset module state between tests so the module-scoped\n\t// `previousCompilation` doesn't leak across tests.\n\tvi.resetModules();\n\n\t// Mock logging methods to suppress error messages in tests\n\tconsola.mockTypes(() => vi.fn());\n});\n\nafterEach(() => {\n\tif (originalNodeEnv !== undefined) {\n\t\tprocess.env.NODE_ENV = originalNodeEnv;\n\t} else {\n\t\tdelete process.env.NODE_ENV;\n\t}\n});\n\ntest(\"vite plugin does not throw when compilation is successful\", async () => {\n\t// Dynamic import so beforeEach's vi.resetModules() yields a fresh module\n\t// (a static import would share module state across tests).\n\tconst { paraglideVitePlugin } = await import(\"../bundler-plugins/vite.js\");\n\n\t// Create and save a viable project to the virtual file system\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst plugin = paraglideVitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fs,\n\t}) as any;\n\n\tconst mockContext = {\n\t\taddWatchFile: () => {},\n\t};\n\n\tawait expect(plugin.buildStart?.call(mockContext)).resolves.toBeUndefined();\n});\n\ntest(\"vite plugin does not throw on compilation errors in development\", async () => {\n\tconst { paraglideVitePlugin } = await import(\"../bundler-plugins/vite.js\");\n\n\tprocess.env.NODE_ENV = \"development\";\n\n\t// Use memfs with no project (simulates missing project)\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst plugin = paraglideVitePlugin({\n\t\tproject: \"/non-existent-project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fs,\n\t}) as any;\n\n\tconst mockContext = {\n\t\taddWatchFile: () => {},\n\t};\n\n\t// In development mode - should catch errors and NOT throw\n\tawait expect(plugin.buildStart?.call(mockContext)).resolves.toBeUndefined();\n});\n\ntest(\"vite plugin throws on compilation errors at build time\", async () => {\n\tconst { paraglideVitePlugin } = await import(\"../bundler-plugins/vite.js\");\n\n\tprocess.env.NODE_ENV = \"production\";\n\n\t// Use memfs with no project (simulates missing project)\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst plugin = paraglideVitePlugin({\n\t\tproject: \"/non-existent-project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fs,\n\t}) as any;\n\n\tconst mockContext = {\n\t\taddWatchFile: () => {},\n\t};\n\n\t// In production mode - should throw the error\n\tawait expect(plugin.buildStart?.call(mockContext)).rejects.toThrow();\n});\n\n// Regression test for https://github.com/opral/inlang-paraglide-js/issues/659:\n// the bundler plugins used to wipe `outdir` on every fresh process, racing\n// concurrent reads (SSR/prerender modules, sibling Vite processes, the\n// config-watcher reload) and producing ENOENT/MISSING_EXPORT/ERR_LOAD_URL.\ntest(\"vite plugin does not wipe outdir during first buildStart (#659)\", async () => {\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\t// Pre-seed outdir with a sentinel file mimicking a prior compilation\n\t// still on disk from an earlier process.\n\tawait fs.promises.mkdir(\"/test-output\", { recursive: true });\n\tawait fs.promises.writeFile(\"/test-output/__sentinel__.txt\", \"kept\");\n\n\tconst rmSpy = vi.spyOn(fs.promises, \"rm\");\n\n\tconst plugin = vitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tcleanOutdir: true,\n\t\tfs: fs,\n\t}) as any;\n\n\tconst mockContext = { addWatchFile: () => {} };\n\tawait plugin.buildStart?.call(mockContext);\n\n\t// The plugin must not recursively remove the outdir during the first\n\t// compile, even though previousCompilation is undefined. Concurrent\n\t// readers may be holding file handles into outdir.\n\tfor (const call of rmSpy.mock.calls) {\n\t\texpect(call[0]).not.toBe(\"/test-output\");\n\t}\n});\n\ntest(\"vite plugin warm-restart writes nothing when inputs unchanged (#659)\", async () => {\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst mockContext = { addWatchFile: () => {} };\n\n\t// First process: compile and persist files to outdir.\n\t{\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\t\tconst plugin = vitePlugin({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/test-output\",\n\t\t\tfs: fs,\n\t\t}) as any;\n\t\tawait plugin.buildStart?.call(mockContext);\n\t}\n\n\t// Second process: simulate a fresh node process by resetting modules so\n\t// the module-scoped `previousCompilation` is undefined again. The plugin\n\t// should seed from on-disk hashes and write zero files (no race window).\n\tvi.resetModules();\n\tconst { paraglideVitePlugin: vitePluginFresh } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin2 = vitePluginFresh({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fs,\n\t}) as any;\n\n\tconst writeFileSpy = vi.spyOn(fs.promises, \"writeFile\");\n\tawait plugin2.buildStart?.call(mockContext);\n\n\texpect(writeFileSpy).not.toHaveBeenCalled();\n});\n\n// Regression test for https://github.com/opral/paraglide-js/issues/741:\n// a new Vite process should validate the persisted inputs and output instead\n// of loading the project and compiling every message again.\ntest(\"vite plugin skips compile on an unchanged fresh process (#741)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject({\n\t\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t\t}),\n\t\t});\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\t\tawait saveProjectToDirectory({\n\t\t\tproject,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tfs: fs.promises,\n\t\t});\n\n\t\tconst options = {\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/test-output\",\n\t\t\temitReadme: true,\n\t\t\tfs,\n\t\t};\n\t\tconst mockContext = { addWatchFile: () => {} };\n\t\tconst startFreshProcess = async () => {\n\t\t\tvi.resetModules();\n\t\t\tconst { paraglideVitePlugin } =\n\t\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\t\t\tconst plugin = paraglideVitePlugin(options) as any;\n\t\t\tawait plugin.buildStart?.call(mockContext);\n\t\t};\n\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// The persisted cache makes the unchanged cold restart skip compile().\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// A file added beside a tracked project input invalidates the cache.\n\t\tawait fs.promises.writeFile(\"/project.inlang/new-project-input.txt\", \"new\");\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\n\t\t// Compiler options are part of the cache key.\n\t\toptions.emitReadme = false;\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(3);\n\n\t\t// Generated output is validated too, so edited output self-repairs.\n\t\tawait fs.promises.writeFile(\"/test-output/runtime.js\", \"tampered\");\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(4);\n\t\texpect(\n\t\t\tawait fs.promises.readFile(\"/test-output/runtime.js\", \"utf8\")\n\t\t).not.toBe(\"tampered\");\n\n\t\t// A compiler version change invalidates the persisted cache.\n\t\tconst cacheDirectory = \"/project.inlang/cache/paraglide-js\";\n\t\tfor (const cacheFile of await fs.promises.readdir(cacheDirectory)) {\n\t\t\tconst cachePath = `${cacheDirectory}/${cacheFile}`;\n\t\t\tconst cache = JSON.parse(await fs.promises.readFile(cachePath, \"utf8\"));\n\t\t\tcache.compilerVersion = \"0.0.0-stale\";\n\t\t\tawait fs.promises.writeFile(cachePath, JSON.stringify(cache));\n\t\t}\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(5);\n\n\t\t// A syntactically valid but malformed cache is treated as a miss.\n\t\tfor (const cacheFile of await fs.promises.readdir(cacheDirectory)) {\n\t\t\tconst cachePath = `${cacheDirectory}/${cacheFile}`;\n\t\t\tconst cache = JSON.parse(await fs.promises.readFile(cachePath, \"utf8\"));\n\t\t\tcache.outputHashes = null;\n\t\t\tawait fs.promises.writeFile(cachePath, JSON.stringify(cache));\n\t\t}\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(6);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// Regression test for https://github.com/opral/paraglide-js/issues/693:\n// `vite build` fires buildStart once per environment (client, ssr) and each\n// run used to do a full compile() — project loading + message compilation —\n// even though the inputs hadn't changed.\ntest(\"vite plugin skips compile() when buildStart fires again with unchanged inputs (#693)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject({\n\t\t\t\tsettings: {\n\t\t\t\t\tbaseLocale: \"en\",\n\t\t\t\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t\tawait saveProjectToDirectory({\n\t\t\tproject,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tfs: fs.promises,\n\t\t});\n\n\t\tconst plugin = vitePlugin({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/test-output\",\n\t\t\tfs: fs,\n\t\t}) as any;\n\n\t\tconst mockContext = { addWatchFile: () => {} };\n\n\t\t// First environment (e.g. client) compiles.\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// Second environment (e.g. ssr) — inputs unchanged, compile skipped.\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// Changing an input file invalidates the digest and recompiles.\n\t\tconst settingsPath = \"/project.inlang/settings.json\";\n\t\tconst settings = JSON.parse(\n\t\t\tawait fs.promises.readFile(settingsPath, \"utf-8\")\n\t\t);\n\t\tsettings.locales = [\"en\", \"de\", \"fr\", \"es\"];\n\t\tawait fs.promises.writeFile(settingsPath, JSON.stringify(settings));\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// A new file added next to tracked inputs must invalidate the digest via\n// the directory-listing part of the hash, not only edits to known files.\ntest(\"vite plugin recompiles when a file is added to a tracked directory (#693)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject({\n\t\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t\t}),\n\t\t});\n\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t\tawait saveProjectToDirectory({\n\t\t\tproject,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tfs: fs.promises,\n\t\t});\n\n\t\tconst plugin = vitePlugin({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/test-output\",\n\t\t\tfs: fs,\n\t\t}) as any;\n\n\t\tconst mockContext = { addWatchFile: () => {} };\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// No tracked file changed, but the listing of a tracked directory did.\n\t\tawait fs.promises.writeFile(\"/project.inlang/added-later.txt\", \"new\");\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// After a failed compile the stored digest must not be reused: restoring an\n// input to its previous content has to trigger a real recompile, because the\n// failed attempt may have left no (or partial) output.\ntest(\"vite plugin does not reuse a digest from before a failed compile (#693)\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject({\n\t\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t\t}),\n\t\t});\n\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t\tawait saveProjectToDirectory({\n\t\t\tproject,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tfs: fs.promises,\n\t\t});\n\n\t\tconst plugin = vitePlugin({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/test-output\",\n\t\t\tfs: fs,\n\t\t}) as any;\n\n\t\tconst mockContext = { addWatchFile: () => {} };\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\tconst settingsPath = \"/project.inlang/settings.json\";\n\t\tconst originalSettings = await fs.promises.readFile(settingsPath, \"utf-8\");\n\n\t\t// Break the settings file — the compile attempt fails (dev mode\n\t\t// swallows the error) and must clear the stored digest.\n\t\tawait fs.promises.writeFile(settingsPath, \"{ not json\");\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\n\t\t// Restore the exact original content. The digest now matches the one\n\t\t// from before the failure — it must have been cleared, so this\n\t\t// buildStart has to compile again instead of skipping.\n\t\tawait fs.promises.writeFile(settingsPath, originalSettings);\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(3);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// Two plugin instances with different filesystems must not share the tracked\n// fs wrapper or cached compilation state — each compiles into its own fs.\ntest(\"vite plugin instances with different fs compile against their own fs (#693)\", async () => {\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\tconst makeProjectFs = async () => {\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject({\n\t\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\"] },\n\t\t\t}),\n\t\t});\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\t\tawait saveProjectToDirectory({\n\t\t\tproject,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tfs: fs.promises,\n\t\t});\n\t\treturn fs;\n\t};\n\n\tconst fsA = await makeProjectFs();\n\tconst fsB = await makeProjectFs();\n\n\tconst mockContext = { addWatchFile: () => {} };\n\n\tconst pluginA = vitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fsA,\n\t}) as any;\n\tawait pluginA.buildStart?.call(mockContext);\n\n\tconst pluginB = vitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/test-output\",\n\t\tfs: fsB,\n\t}) as any;\n\tawait pluginB.buildStart?.call(mockContext);\n\n\t// B's output must exist in B's filesystem — with a shared tracked fs it\n\t// would have been read from and written into A's filesystem instead.\n\tconst outputB = await fsB.promises.readdir(\"/test-output\");\n\texpect(outputB.length).toBeGreaterThan(0);\n});\n"]}
1
+ {"version":3,"file":"unplugin.test.js","sourceRoot":"","sources":["../../src/bundler-plugins/unplugin.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACjE,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EACN,mBAAmB,EACnB,UAAU,EACV,sBAAsB,GACtB,MAAM,aAAa,CAAC;AAErB,IAAI,eAAmC,CAAC;AACxC,IAAI,eAAe,GAAa,EAAE,CAAC;AAEnC,UAAU,CAAC,GAAG,EAAE;IACf,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAEvC,wDAAwD;IACxD,mDAAmD;IACnD,EAAE,CAAC,YAAY,EAAE,CAAC;IAElB,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACpB,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,eAAe,CAAC;IACxC,CAAC;SAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,EAAE,CAAC,eAAe,EAAE,CAAC;IACrB,KAAK,MAAM,SAAS,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;AACF,CAAC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB,CAClC,OAAO,GAUH,EAAE;IAMN,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC1E,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC1D,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC;QACzC,IAAI,EAAE,MAAM,UAAU,CAAC;YACtB,QAAQ,EAAE;gBACT,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;aACxC;SACD,CAAC;KACF,CAAC,CAAC;IACH,MAAM,sBAAsB,CAAC;QAC5B,OAAO;QACP,IAAI,EAAE,UAAU;QAChB,EAAE,EAAE,MAAM,CAAC,QAAQ;KACnB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC9B,MAAM,OAAO,GACZ,OAAO,CAAC,MAAM,EAAE,OAAO;YACvB,CAAC,kBAAkB,EAAE,aAAa,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CACrE,IAAI,CACJ,CAAC;QACH,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,qBAAqB,CAAC,EACxE,OAAO,CACP,CAAC;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC;AAED,iEAAiE;AACjE,SAAS,WAAW,CAAC,MAAW,EAAE,IAAY;IAC7C,MAAM,cAAc,GAClB,MAAM,CAAC,IAAI,EAAE,cAED;QACZ,MAAM,CAAC,cAEK,CAAC;IACf,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AAE/C,IAAI,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;IAC7D,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IACrC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC3D,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;QACpE,MAAM,EAAE,EAAE,QAAQ,EAAE,qBAAqB,EAAE;KAC3C,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAEnD,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAElE,sDAAsD;IACtD,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACvD,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,CAAC,kBAAkB,EAAE,aAAa,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CACvE,IAAI,CACJ,CACD,CAAC;IAEF,MAAM,MAAM,CACX,MAAM,CAAC,WAAW,EAAE,IAAI,CACvB,WAAW,EACX,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAC5C,CACD,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAE3B,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IAClF,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC1E,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,mBAAmB,CAAC;QAClC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC;QACtD,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC;KACnC,CAAQ,CAAC;IAEV,0DAA0D;IAC1D,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC;IAEpC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC1E,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,mBAAmB,CAAC;QAClC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC;QACtD,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC;KACnC,CAAQ,CAAC;IAEV,8CAA8C;IAC9C,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,+EAA+E;AAC/E,2EAA2E;AAC3E,uEAAuE;AACvE,2EAA2E;AAC3E,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IAClF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAE5D,qEAAqE;IACrE,yCAAyC;IACzC,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACrC,MAAM,CACN,CAAC;IAEF,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,UAAU,CAAC;QACzB,OAAO,EAAE,UAAU;QACnB,MAAM;QACN,WAAW,EAAE,IAAI;KACjB,CAAQ,CAAC;IAEV,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE3C,qEAAqE;IACrE,oEAAoE;IACpE,mDAAmD;IACnD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACvF,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAC5D,MAAM,OAAO,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAE3C,sDAAsD;IACtD,CAAC;QACA,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;QAClE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,EAAE,CAAC,YAAY,EAAE,CAAC;IAClB,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAE,GAC7C,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;IAExE,MAAM,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAExC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,wEAAwE;AACxE,6EAA6E;AAC7E,4DAA4D;AAC5D,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,CAAC;YAC5B,UAAU;SACV,CAAC,CAAC;QAEH,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;YACzD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;SACrB,CAAC,CAAC;QACH,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;YACpC,EAAE,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,mBAAmB,CAAC;gBAClC,OAAO,EAAE,UAAU;gBACnB,MAAM;gBACN,GAAG,aAAa,EAAE;aAClB,CAAQ,CAAC;YACV,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,uEAAuE;QACvE,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,qEAAqE;QACrE,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,uBAAuB,CAAC,EAC9C,KAAK,CACL,CAAC;QACF,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,8CAA8C;QAC9C,UAAU,GAAG,KAAK,CAAC;QACnB,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,oEAAoE;QACpE,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,UAAU,CACV,CAAC;QACF,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CACL,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEvB,6DAA6D;QAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QACtE,KAAK,MAAM,SAAS,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACvE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAmB,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACvB,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CACjD,CAAC;YACF,KAAK,CAAC,eAAe,GAAG,aAAa,CAAC;YACtC,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,kEAAkE;QAClE,KAAK,MAAM,SAAS,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACvE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAmB,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACvB,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CACjD,CAAC;YACF,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC1B,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,wEAAwE;AACxE,4EAA4E;AAC5E,yEAAyE;AACzE,IAAI,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;IACvG,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;YACzD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;QAElE,4CAA4C;QAC5C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,qEAAqE;QACrE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,gEAAgE;QAChE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CACrD,CAAC;QACF,QAAQ,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAExE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,yEAAyE;AACzE,yEAAyE;AACzE,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;IAC5F,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;QAE5D,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;QAElE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,uEAAuE;QACvE,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,EACxC,KAAK,CACL,CAAC;QAEF,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,iEAAiE;AACjE,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IAC1F,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,YAAY,CAE/C,wBAAwB,CAAC,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,GAAG,mBAAmB;QACtB,OAAO,EAAE,UAAU;KACnB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACJ,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;QAE5D,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;QAElE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC5D,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CACtD,YAAY,EACZ,OAAO,CACP,CAAC;QAEF,gEAAgE;QAChE,wDAAwD;QACxD,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE5C,oEAAoE;QACpE,eAAe;QACf,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAChE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,0EAA0E;AAC1E,wEAAwE;AACxE,qEAAqE;AACrE,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC9F,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;QACzD,OAAO,EAAE,CAAC,IAAI,CAAC;KACf,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAE9D,uEAAuE;IACvE,uEAAuE;IACvE,KAAK,UAAU,UAAU,CAAC,MAAgC;QACzD,KAAK,UAAU,IAAI,CAAC,GAAW,EAAE,UAAkB;YAClD,KAAK,MAAM,KAAK,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE;gBACtD,aAAa,EAAE,IAAI;aACnB,CAAC,EAAE,CAAC;gBACJ,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACtD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACzB,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC9D,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACP,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC9B,WAAW,EACX,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CACtC,CAAC;gBACH,CAAC;YACF,CAAC;QACF,CAAC;QACD,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACtB,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IAEtB,MAAM,OAAO,GAAG,UAAU,CAAC;QAC1B,OAAO,EAAE,iBAAiB;QAC1B,MAAM;QACN,EAAE,EAAE,GAAG;KACP,CAAQ,CAAC;IACV,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,UAAU,CAAC;QAC1B,OAAO,EAAE,iBAAiB;QAC1B,MAAM;QACN,EAAE,EAAE,GAAG;KACP,CAAQ,CAAC;IACV,MAAM,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,wEAAwE;IACxE,qEAAqE;IACrE,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,2EAA2E;AAC3E,sEAAsE;AACtE,kCAAkC;AAClC,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;QACpE,UAAU,EAAE,aAAa;QACzB,MAAM,EAAE,KAAK;KACb,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAErD,8DAA8D;IAC9D,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,mBAAmB,GAAG,UAAU,CAAC;QACtC,OAAO,EAAE,UAAU;QACnB,MAAM;KACN,CAAQ,CAAC;IACV,WAAW,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACxD,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAElE,kEAAkE;IAClE,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C;QACC,kBAAkB;QAClB,aAAa,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC,GAAG;QACxE,GAAG;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;IACF,MAAM,gBAAgB,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IACpE,WAAW,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IACzC,MAAM,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACrD,MAAM,CACL,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC,CACvE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAEtB,uDAAuD;IACvD,MAAM,kBAAkB,GAAG,UAAU,CAAC;QACrC,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,UAAU;KAClB,CAAQ,CAAC;IACV,WAAW,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,iEAAiE;AACjE,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;IAC3E,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAEvE,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC;QACzB,OAAO,EAAE,kBAAkB,EAAE,uCAAuC;QACpE,MAAM;KACN,CAAQ,CAAC;IACV,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACtE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC;QACpE,UAAU,EAAE,aAAa;KACzB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAErD,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,MAAM,gBAAgB,GAAG;QACxB,YAAY,EAAE,CAAC,CAAS,EAAE,EAAE;YAC3B,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;KACD,CAAC;IACF,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAElE,+CAA+C;IAC/C,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEpE,mDAAmD;IACnD,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,CAAC,kBAAkB,EAAE,aAAa,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CACxE,IAAI,CACJ,CACD,CAAC;IACF,MAAM,MAAM,CAAC,WAAW,EAAE,IAAI,CAC7B,SAAS,EACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAC5C,CAAC;IAEF,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,sCAAsC;AACtC,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IAC1F,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAE5D,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;IAClE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9C,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAElE,iDAAiD;IACjD,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,+BAA+B,CAC/B,CAAC;IACF,MAAM,MAAM,CACX,MAAM,CAAC,WAAW,EAAE,IAAI,CACvB,SAAS,EACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAC5C,CACD,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAE3B,8CAA8C;IAC9C,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,sEAAsE;AACtE,0DAA0D;AAC1D,IAAI,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;IAC3F,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,oBAAoB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,2DAA2D,CAC3D,CAAC;IAEF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9C,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,oEAAoE;AACpE,0EAA0E;AAC1E,0CAA0C;AAC1C,IAAI,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;IAC7F,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,oBAAoB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,2DAA2D,CAC3D,CAAC;IAEF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9C,+DAA+D;IAC/D,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,MAAM,CACX,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CACzD,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEH,2EAA2E;AAC3E,8DAA8D;AAC9D,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,oBAAoB,CAAC;QAC5D,UAAU,EAAE,aAAa;KACzB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAErD,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE3C,wEAAwE;IACxE,yCAAyC;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,CACrC,SAAS,EACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAC5C,CAAC;IACF,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,CAAC,kBAAkB,EAAE,aAAa,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CACxE,IAAI,CACJ,CACD,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,CACtC,SAAS,EACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAC5C,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,CACrC,SAAS,EACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAC5C,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAE1C,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,2EAA2E;AAC3E,6DAA6D;AAC7D,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC7E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC;IAEpC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IACpD,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAC5C,+BAA+B,CAC/B,CAAC;IAEF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9C,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACjE,mBAAmB,CACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,sEAAsE;AACtE,sEAAsE;AACtE,kEAAkE;AAClE,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACvD,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAE5D,mEAAmE;IACnE,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE;QAC9D,SAAS,EAAE,IAAI;KACf,CAAC,CAAC;IACH,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EAC5C,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAClC,CAAC;IACF,MAAM,SAAS,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EAC5C,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAClC,CAAC;IAEF,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAQ,CAAC;IAClE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9C,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC5B,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,0EAA0E;AAC1E,4EAA4E;AAC5E,qCAAqC;AACrC,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;IAC/E,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IAErC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,oBAAoB,CAAC;QAC5D,MAAM,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,GACxC,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAQ,CAAC;IAC1D,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE/B,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAC7B,YAAY,EAAE,CAAC,CAAS,EAAE,EAAE;YAC3B,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;KACD,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI;QAClB,qBAAqB;QACrB,sBAAsB;QACtB,qBAAqB;QACrB,sBAAsB;KACtB,EAAE,CAAC;QACH,MAAM,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;AACF,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect, beforeEach, afterEach, vi } from \"vitest\";\nimport consola from \"consola\";\nimport { memfs } from \"memfs\";\nimport path from \"node:path\";\nimport realFs from \"node:fs\";\nimport {\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n} from \"@inlang/sdk\";\n\nlet originalNodeEnv: string | undefined;\nlet testDirectories: string[] = [];\n\nbeforeEach(() => {\n\toriginalNodeEnv = process.env.NODE_ENV;\n\n\t// Reset module state between tests so the module-scoped\n\t// `previousCompilation` doesn't leak across tests.\n\tvi.resetModules();\n\n\t// Mock logging methods to suppress error messages in tests\n\tconsola.mockTypes(() => vi.fn());\n});\n\nafterEach(async () => {\n\tif (originalNodeEnv !== undefined) {\n\t\tprocess.env.NODE_ENV = originalNodeEnv;\n\t} else {\n\t\tdelete process.env.NODE_ENV;\n\t}\n\tvi.restoreAllMocks();\n\tfor (const directory of testDirectories.splice(0)) {\n\t\tawait realFs.promises.rm(directory, { recursive: true, force: true });\n\t}\n});\n\n/**\n * Creates a real on-disk fixture: `<workspace>/project.inlang` with a\n * saved inlang project. The paraglide config lives inside the project\n * directory and is loaded through jiti, so it must exist on the real\n * filesystem.\n */\nasync function createProjectFixture(\n\toptions: {\n\t\tlocales?: string[];\n\t\toutdirName?: string;\n\t\t/** `false` skips writing a config file entirely. */\n\t\tconfig?:\n\t\t\t| {\n\t\t\t\t\tfileName?: string;\n\t\t\t\t\tcontent?: string;\n\t\t\t }\n\t\t\t| false;\n\t} = {}\n): Promise<{\n\tworkspace: string;\n\tprojectDir: string;\n\toutdir: string;\n}> {\n\tconst { mkdtemp, mkdir, writeFile } = await import(\"node:fs/promises\");\n\tconst { tmpdir } = await import(\"node:os\");\n\tconst workspace = await mkdtemp(path.join(tmpdir(), \"paraglide-plugin-\"));\n\ttestDirectories.push(workspace);\n\tconst projectDir = path.join(workspace, \"project.inlang\");\n\tawait mkdir(projectDir, { recursive: true });\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: options.locales ?? [\"en\", \"de\"],\n\t\t\t},\n\t\t}),\n\t});\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: projectDir,\n\t\tfs: realFs.promises,\n\t});\n\n\tconst outdir = path.join(workspace, options.outdirName ?? \"test-output\");\n\tif (options.config !== false) {\n\t\tconst content =\n\t\t\toptions.config?.content ??\n\t\t\t[\"export default {\", ` outdir: ${JSON.stringify(outdir)},`, \"}\"].join(\n\t\t\t\t\"\\n\"\n\t\t\t);\n\t\tawait writeFile(\n\t\t\tpath.join(projectDir, options.config?.fileName ?? \"paraglide.config.js\"),\n\t\t\tcontent\n\t\t);\n\t}\n\treturn { workspace, projectDir, outdir };\n}\n\n/** Fires Vite's configResolved so the plugin learns its root. */\nfunction setViteRoot(plugin: any, root: string): void {\n\tconst configResolved =\n\t\t(plugin.vite?.configResolved as\n\t\t\t| { handler?: (config: unknown) => void }\n\t\t\t| undefined) ??\n\t\t(plugin.configResolved as\n\t\t\t| { handler?: (config: unknown) => void }\n\t\t\t| undefined);\n\tconfigResolved?.handler?.({ root });\n}\n\nconst mockContext = { addWatchFile: () => {} };\n\ntest(\"watch mode follows config precedence flips\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\tconst { writeFile, rm } = await import(\"node:fs/promises\");\n\tconst { workspace, projectDir, outdir } = await createProjectFixture({\n\t\tconfig: { fileName: \"paraglide.config.ts\" },\n\t});\n\tconst jsOutdir = path.join(workspace, \"js-output\");\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, workspace);\n\n\tawait plugin.buildStart?.call(mockContext);\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n\n\t// Delete the winning .ts config and create a .js one.\n\tawait rm(path.join(projectDir, \"paraglide.config.ts\"));\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t[\"export default {\", ` outdir: ${JSON.stringify(jsOutdir)},`, \"}\"].join(\n\t\t\t\"\\n\"\n\t\t)\n\t);\n\n\tawait expect(\n\t\tplugin.watchChange?.call(\n\t\t\tmockContext,\n\t\t\tpath.join(projectDir, \"paraglide.config.js\")\n\t\t)\n\t).resolves.toBeUndefined();\n\n\texpect(await realFs.promises.readdir(jsOutdir)).not.toHaveLength(0);\n});\n\ntest(\"vite plugin does not throw on compilation errors in development\", async () => {\n\tconst { paraglideVitePlugin } = await import(\"../bundler-plugins/vite.js\");\n\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst { mkdtemp } = await import(\"node:fs/promises\");\n\tconst { tmpdir } = await import(\"node:os\");\n\tconst workspace = await mkdtemp(path.join(tmpdir(), \"paraglide-plugin-\"));\n\ttestDirectories.push(workspace);\n\n\tconst plugin = paraglideVitePlugin({\n\t\tproject: path.join(workspace, \"does-not-exist.inlang\"),\n\t\toutdir: path.join(workspace, \"out\"),\n\t}) as any;\n\n\t// In development mode - should catch errors and NOT throw\n\tawait expect(plugin.buildStart?.call(mockContext)).resolves.toBeUndefined();\n});\n\ntest(\"vite plugin throws on compilation errors at build time\", async () => {\n\tconst { paraglideVitePlugin } = await import(\"../bundler-plugins/vite.js\");\n\n\tprocess.env.NODE_ENV = \"production\";\n\n\tconst { mkdtemp } = await import(\"node:fs/promises\");\n\tconst { tmpdir } = await import(\"node:os\");\n\tconst workspace = await mkdtemp(path.join(tmpdir(), \"paraglide-plugin-\"));\n\ttestDirectories.push(workspace);\n\n\tconst plugin = paraglideVitePlugin({\n\t\tproject: path.join(workspace, \"does-not-exist.inlang\"),\n\t\toutdir: path.join(workspace, \"out\"),\n\t}) as any;\n\n\t// In production mode - should throw the error\n\tawait expect(plugin.buildStart?.call(mockContext)).rejects.toThrow();\n});\n\n// Regression test for https://github.com/opral/inlang-paraglide-js/issues/659:\n// the bundler plugins used to wipe `outdir` on every fresh process, racing\n// concurrent reads (SSR/prerender modules, sibling Vite processes, the\n// config-watcher reload) and producing ENOENT/MISSING_EXPORT/ERR_LOAD_URL.\ntest(\"vite plugin does not wipe outdir during first buildStart (#659)\", async () => {\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\tconst { projectDir, outdir } = await createProjectFixture();\n\n\t// Pre-seed outdir with a sentinel file mimicking a prior compilation\n\t// still on disk from an earlier process.\n\tawait realFs.promises.mkdir(outdir, { recursive: true });\n\tawait realFs.promises.writeFile(\n\t\tpath.join(outdir, \"__sentinel__.txt\"),\n\t\t\"kept\"\n\t);\n\n\tconst rmSpy = vi.spyOn(realFs.promises, \"rm\");\n\n\tconst plugin = vitePlugin({\n\t\tproject: projectDir,\n\t\toutdir,\n\t\tcleanOutdir: true,\n\t}) as any;\n\n\tawait plugin.buildStart?.call(mockContext);\n\n\t// The plugin must not recursively remove the outdir during the first\n\t// compile, even though previousCompilation is undefined. Concurrent\n\t// readers may be holding file handles into outdir.\n\tfor (const call of rmSpy.mock.calls) {\n\t\texpect(String(call[0])).not.toBe(outdir);\n\t}\n});\n\ntest(\"vite plugin warm-restart writes nothing when inputs unchanged (#659)\", async () => {\n\tconst { projectDir, outdir } = await createProjectFixture();\n\tconst mockCtx = { addWatchFile: () => {} };\n\n\t// First process: compile and persist files to outdir.\n\t{\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\t\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\t\tawait plugin.buildStart?.call(mockCtx);\n\t}\n\n\t// Second process: simulate a fresh node process by resetting modules so\n\t// the module-scoped `previousCompilation` is undefined again. The plugin\n\t// should seed from on-disk hashes and write zero files (no race window).\n\tvi.resetModules();\n\tconst { paraglideVitePlugin: vitePluginFresh } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin2 = vitePluginFresh({ project: projectDir, outdir }) as any;\n\n\tconst writeFileSpy = vi.spyOn(realFs.promises, \"writeFile\");\n\tawait plugin2.buildStart?.call(mockCtx);\n\n\texpect(writeFileSpy).not.toHaveBeenCalled();\n});\n\n// Regression test for https://github.com/opral/paraglide-js/issues/741:\n// a new Vite process should validate the persisted inputs and output instead\n// of loading the project and compiling every message again.\ntest(\"vite plugin skips compile on an unchanged fresh process (#741)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tlet emitReadme = true;\n\t\tconst optionsGetter = () => ({\n\t\t\temitReadme,\n\t\t});\n\n\t\tconst { projectDir, outdir } = await createProjectFixture({\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t});\n\t\tconst startFreshProcess = async () => {\n\t\t\tvi.resetModules();\n\t\t\tconst { paraglideVitePlugin } =\n\t\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\t\t\tconst plugin = paraglideVitePlugin({\n\t\t\t\tproject: projectDir,\n\t\t\t\toutdir,\n\t\t\t\t...optionsGetter(),\n\t\t\t}) as any;\n\t\t\tawait plugin.buildStart?.call(mockContext);\n\t\t};\n\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// The persisted cache makes the unchanged cold restart skip compile().\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// A file added beside a tracked project input invalidates the cache.\n\t\tawait realFs.promises.writeFile(\n\t\t\tpath.join(projectDir, \"new-project-input.txt\"),\n\t\t\t\"new\"\n\t\t);\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\n\t\t// Compiler options are part of the cache key.\n\t\temitReadme = false;\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(3);\n\n\t\t// Generated output is validated too, so edited output self-repairs.\n\t\tawait realFs.promises.writeFile(\n\t\t\tpath.join(outdir, \"runtime.js\"),\n\t\t\t\"tampered\"\n\t\t);\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(4);\n\t\texpect(\n\t\t\tawait realFs.promises.readFile(path.join(outdir, \"runtime.js\"), \"utf8\")\n\t\t).not.toBe(\"tampered\");\n\n\t\t// A compiler version change invalidates the persisted cache.\n\t\tconst cacheDirectory = path.join(projectDir, \"cache\", \"paraglide-js\");\n\t\tfor (const cacheFile of await realFs.promises.readdir(cacheDirectory)) {\n\t\t\tconst cachePath = path.join(cacheDirectory, cacheFile as string);\n\t\t\tconst cache = JSON.parse(\n\t\t\t\tawait realFs.promises.readFile(cachePath, \"utf8\")\n\t\t\t);\n\t\t\tcache.compilerVersion = \"0.0.0-stale\";\n\t\t\tawait realFs.promises.writeFile(cachePath, JSON.stringify(cache));\n\t\t}\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(5);\n\n\t\t// A syntactically valid but malformed cache is treated as a miss.\n\t\tfor (const cacheFile of await realFs.promises.readdir(cacheDirectory)) {\n\t\t\tconst cachePath = path.join(cacheDirectory, cacheFile as string);\n\t\t\tconst cache = JSON.parse(\n\t\t\t\tawait realFs.promises.readFile(cachePath, \"utf8\")\n\t\t\t);\n\t\t\tcache.outputHashes = null;\n\t\t\tawait realFs.promises.writeFile(cachePath, JSON.stringify(cache));\n\t\t}\n\t\tawait startFreshProcess();\n\t\texpect(compileSpy).toHaveBeenCalledTimes(6);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// Regression test for https://github.com/opral/paraglide-js/issues/693:\n// `vite build` fires buildStart once per environment (client, ssr) and each\n// run used to do a full compile() even though the inputs hadn't changed.\ntest(\"vite plugin skips compile() when buildStart fires again with unchanged inputs (#693)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst { projectDir, outdir } = await createProjectFixture({\n\t\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\t});\n\n\t\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\n\t\t// First environment (e.g. client) compiles.\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// Second environment (e.g. ssr) — inputs unchanged, compile skipped.\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// Changing an input file invalidates the digest and recompiles.\n\t\tconst settingsPath = path.join(projectDir, \"settings.json\");\n\t\tconst settings = JSON.parse(\n\t\t\tawait realFs.promises.readFile(settingsPath, \"utf-8\")\n\t\t);\n\t\tsettings.locales = [\"en\", \"de\", \"fr\", \"es\"];\n\t\tawait realFs.promises.writeFile(settingsPath, JSON.stringify(settings));\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// A new file added next to tracked inputs must invalidate the digest via\n// the directory-listing part of the hash, not only edits to known files.\ntest(\"vite plugin recompiles when a file is added to a tracked directory (#693)\", async () => {\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst { projectDir, outdir } = await createProjectFixture();\n\n\t\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\t// No tracked file changed, but the listing of a tracked directory did.\n\t\tawait realFs.promises.writeFile(\n\t\t\tpath.join(projectDir, \"added-later.txt\"),\n\t\t\t\"new\"\n\t\t);\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// After a failed compile the stored digest must not be reused: restoring an\n// input to its previous content has to trigger a real recompile.\ntest(\"vite plugin does not reuse a digest from before a failed compile (#693)\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst actualCompileModule = await vi.importActual<\n\t\ttypeof import(\"../compiler/compile.js\")\n\t>(\"../compiler/compile.js\");\n\tconst compileSpy = vi.fn(actualCompileModule.compile);\n\tvi.doMock(\"../compiler/compile.js\", () => ({\n\t\t...actualCompileModule,\n\t\tcompile: compileSpy,\n\t}));\n\n\ttry {\n\t\tconst { paraglideVitePlugin: vitePlugin } =\n\t\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\t\tconst { projectDir, outdir } = await createProjectFixture();\n\n\t\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(1);\n\n\t\tconst settingsPath = path.join(projectDir, \"settings.json\");\n\t\tconst originalSettings = await realFs.promises.readFile(\n\t\t\tsettingsPath,\n\t\t\t\"utf-8\"\n\t\t);\n\n\t\t// Break the settings file — the compile attempt fails (dev mode\n\t\t// swallows the error) and must clear the stored digest.\n\t\tawait realFs.promises.writeFile(settingsPath, \"{ not json\");\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(2);\n\n\t\t// Restore the exact original content. It must compile again instead\n\t\t// of skipping.\n\t\tawait realFs.promises.writeFile(settingsPath, originalSettings);\n\t\tawait plugin.buildStart?.call(mockContext);\n\t\texpect(compileSpy).toHaveBeenCalledTimes(3);\n\t} finally {\n\t\tvi.doUnmock(\"../compiler/compile.js\");\n\t}\n});\n\n// Two plugin instances with different filesystems must not share the tracked\n// fs wrapper or cached compilation state — each compiles into its own fs.\n// The project and config live on the real filesystem (the config loader\n// always uses the native fs); only compiler I/O is virtualized here.\ntest(\"vite plugin instances with different fs compile against their own fs (#693)\", async () => {\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\n\tconst { projectDir, outdir } = await createProjectFixture({\n\t\tlocales: [\"en\"],\n\t});\n\n\tconst fsA = memfs().fs as unknown as typeof import(\"node:fs\");\n\tconst fsB = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t// The compiler reads the project through its own fs, so seed a copy of\n\t// the real project into each instance's filesystem at /project.inlang.\n\tasync function seedIntoFs(target: typeof import(\"node:fs\")) {\n\t\tasync function walk(dir: string, virtualDir: string) {\n\t\t\tfor (const entry of await realFs.promises.readdir(dir, {\n\t\t\t\twithFileTypes: true,\n\t\t\t})) {\n\t\t\t\tconst source = path.join(dir, entry.name);\n\t\t\t\tconst destination = path.join(virtualDir, entry.name);\n\t\t\t\tif (entry.isDirectory()) {\n\t\t\t\t\tawait target.promises.mkdir(destination, { recursive: true });\n\t\t\t\t\tawait walk(source, destination);\n\t\t\t\t} else {\n\t\t\t\t\tawait target.promises.writeFile(\n\t\t\t\t\t\tdestination,\n\t\t\t\t\t\tawait realFs.promises.readFile(source)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait target.promises.mkdir(\"/project.inlang\", { recursive: true });\n\t\tawait walk(projectDir, \"/project.inlang\");\n\t}\n\tawait seedIntoFs(fsA);\n\tawait seedIntoFs(fsB);\n\n\tconst pluginA = vitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir,\n\t\tfs: fsA,\n\t}) as any;\n\tawait pluginA.buildStart?.call(mockContext);\n\n\tconst pluginB = vitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir,\n\t\tfs: fsB,\n\t}) as any;\n\tawait pluginB.buildStart?.call(mockContext);\n\t// B's output must exist in B's filesystem — with a shared tracked fs it\n\t// would have been read from and written into A's filesystem instead.\n\tconst outputB = await fsB.promises.readdir(outdir);\n\texpect(outputB.length).toBeGreaterThan(0);\n});\n\n// The plugins must pick up options from a paraglide.config file inside the\n// project directory when they are not passed explicitly, and explicit\n// options must win over the file.\ntest(\"vite plugin reads options from a paraglide config file\", async () => {\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { workspace, projectDir, outdir } = await createProjectFixture({\n\t\toutdirName: \"from-config\",\n\t\tconfig: false,\n\t});\n\tconst flagOutdir = path.join(workspace, \"from-flag\");\n\n\t// No config yet: the plugin falls back to the default outdir.\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst pluginWithoutConfig = vitePlugin({\n\t\tproject: projectDir,\n\t\toutdir,\n\t}) as any;\n\tsetViteRoot(pluginWithoutConfig, workspace);\n\tawait pluginWithoutConfig.buildStart?.call(mockContext);\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n\n\t// A config inside the project directory wins over the defaults...\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t[\n\t\t\t\"export default {\",\n\t\t\t` outdir: ${JSON.stringify(path.join(workspace, \"from-config-file\"))},`,\n\t\t\t\"}\",\n\t\t].join(\"\\n\")\n\t);\n\tconst pluginWithConfig = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(pluginWithConfig, workspace);\n\tawait pluginWithConfig.buildStart?.call(mockContext);\n\texpect(\n\t\tawait realFs.promises.readdir(path.join(workspace, \"from-config-file\"))\n\t).not.toHaveLength(0);\n\n\t// ...and an explicit option wins over the config file.\n\tconst pluginWithOverride = vitePlugin({\n\t\tproject: projectDir,\n\t\toutdir: flagOutdir,\n\t}) as any;\n\tsetViteRoot(pluginWithOverride, workspace);\n\tawait pluginWithOverride.buildStart?.call(mockContext);\n\texpect(await realFs.promises.readdir(flagOutdir)).not.toHaveLength(0);\n});\n\n// A relative `project` option is resolved against the tool root.\ntest(\"resolves a relative project option against the vite root\", async () => {\n\tconst { workspace, projectDir, outdir } = await createProjectFixture();\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({\n\t\tproject: \"./project.inlang\", // relative — resolved against the root\n\t\toutdir,\n\t}) as any;\n\tsetViteRoot(plugin, workspace);\n\n\texpect(projectDir).toBe(path.join(workspace, \"project.inlang\"));\n\tawait plugin.buildStart?.call(mockContext);\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n});\n\ntest(\"watch mode hot-reloads when the config file changes\", async () => {\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { workspace, projectDir, outdir } = await createProjectFixture({\n\t\toutdirName: \"cold-output\",\n\t});\n\tconst hotOutput = path.join(workspace, \"hot-output\");\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, workspace);\n\n\tconst capturingContext = {\n\t\taddWatchFile: (p: string) => {\n\t\t\taddedWatchFiles.push(p);\n\t\t},\n\t};\n\tconst addedWatchFiles: string[] = [];\n\n\tawait plugin.buildStart?.call(capturingContext);\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n\n\t// Changes to unrelated files do not recompile.\n\tconst outputBefore = await realFs.promises.readdir(outdir);\n\tawait plugin.watchChange?.call(undefined, \"/unrelated.ts\");\n\texpect(await realFs.promises.readdir(outdir)).toEqual(outputBefore);\n\n\t// A config change recompiles with the new options.\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t[\"export default {\", ` outdir: ${JSON.stringify(hotOutput)},`, \"}\"].join(\n\t\t\t\"\\n\"\n\t\t)\n\t);\n\tawait plugin.watchChange?.call(\n\t\tundefined,\n\t\tpath.join(projectDir, \"paraglide.config.js\")\n\t);\n\n\texpect(await realFs.promises.readdir(hotOutput)).not.toHaveLength(0);\n});\n\n// An invalid edited config must not crash the dev server — the previously\n// compiled output keeps being served.\ntest(\"watchChange keeps the previous output when the edited config is invalid\", async () => {\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { projectDir, outdir } = await createProjectFixture();\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\tsetViteRoot(plugin, path.dirname(projectDir));\n\n\tawait plugin.buildStart?.call(mockContext);\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n\n\t// Break the config, then trigger a change on it.\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t\"export default { outdir: 42 }\"\n\t);\n\tawait expect(\n\t\tplugin.watchChange?.call(\n\t\t\tundefined,\n\t\t\tpath.join(projectDir, \"paraglide.config.js\")\n\t\t)\n\t).resolves.toBeUndefined();\n\n\t// The previous compilation is still in place.\n\texpect(await realFs.promises.readdir(outdir)).not.toHaveLength(0);\n});\n\n// An invalid config at startup follows the same policy as compilation\n// errors: swallowed in development, thrown in production.\ntest(\"buildStart does not throw when the config file is invalid in development\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { projectDir } = await createProjectFixture({ config: false });\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.ts\"),\n\t\t'export default { outdir: \"./o\", cookieMaxAge: \"forever\" }'\n\t);\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, path.dirname(projectDir));\n\n\tawait expect(plugin.buildStart?.call(mockContext)).resolves.toBeUndefined();\n});\n\n// Regression: with no valid cached config (dev server started on an\n// invalid config), an unrelated file change must not reject watchChange —\n// that would crash the bundler's watcher.\ntest(\"watchChange does not throw for unrelated files while the config is invalid\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { projectDir } = await createProjectFixture({ config: false });\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.ts\"),\n\t\t'export default { outdir: \"./o\", cookieMaxAge: \"forever\" }'\n\t);\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, path.dirname(projectDir));\n\n\t// Swallowed by buildStart; nothing valid ends up in the cache.\n\tawait plugin.buildStart?.call(mockContext);\n\n\tawait expect(\n\t\tplugin.watchChange?.call(undefined, \"/some/unrelated.ts\")\n\t).resolves.toBeUndefined();\n});\n\n// Regression (review): webpack fires one watchChange per modified file and\n// a config event must never be starved by later input events.\ntest(\"queued config events are applied even when input events follow\", async () => {\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { workspace, projectDir } = await createProjectFixture({\n\t\toutdirName: \"cold-output\",\n\t});\n\tconst hotOutput = path.join(workspace, \"hot-output\");\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, workspace);\n\n\tawait plugin.buildStart?.call(mockContext);\n\n\t// Volley: input, config, input — fired while the first rebuild is still\n\t// in flight (no awaiting between calls).\n\tconst first = plugin.watchChange?.call(\n\t\tundefined,\n\t\tpath.join(projectDir, \"messages\", \"en.json\")\n\t);\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t[\"export default {\", ` outdir: ${JSON.stringify(hotOutput)},`, \"}\"].join(\n\t\t\t\"\\n\"\n\t\t)\n\t);\n\tconst second = plugin.watchChange?.call(\n\t\tundefined,\n\t\tpath.join(projectDir, \"paraglide.config.js\")\n\t);\n\tconst third = plugin.watchChange?.call(\n\t\tundefined,\n\t\tpath.join(projectDir, \"messages\", \"de.json\")\n\t);\n\tawait Promise.all([first, second, third]);\n\n\texpect(await realFs.promises.readdir(hotOutput)).not.toHaveLength(0);\n});\n\n// Regression (review): an invalid config in production must fail the build\n// loudly instead of silently compiling with default options.\ntest(\"buildStart throws when the config is invalid in production\", async () => {\n\tprocess.env.NODE_ENV = \"production\";\n\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { projectDir } = await createProjectFixture();\n\tawait writeFile(\n\t\tpath.join(projectDir, \"paraglide.config.js\"),\n\t\t\"export default { outdir: 42 }\"\n\t);\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, path.dirname(projectDir));\n\n\tawait expect(plugin.buildStart?.call(mockContext)).rejects.toThrow(\n\t\t/paraglide config/i\n\t);\n});\n\n// Regression (review): pinning outputStructure in the shared defaults\n// template killed the development default (#486). Without an explicit\n// structure, plugins must emit locale-modules outside production.\ntest(\"development default output structure is locale-modules\", async () => {\n\tconst { writeFile } = await import(\"node:fs/promises\");\n\tconst { projectDir, outdir } = await createProjectFixture();\n\n\t// Ensure at least one message exists so the two structures differ.\n\tawait realFs.promises.mkdir(path.join(projectDir, \"messages\"), {\n\t\trecursive: true,\n\t});\n\tawait writeFile(\n\t\tpath.join(projectDir, \"messages\", \"en.json\"),\n\t\tJSON.stringify({ hello: \"Hello\" })\n\t);\n\tawait writeFile(\n\t\tpath.join(projectDir, \"messages\", \"de.json\"),\n\t\tJSON.stringify({ hello: \"Hallo\" })\n\t);\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir, outdir }) as any;\n\tsetViteRoot(plugin, path.dirname(projectDir));\n\n\tdelete process.env.NODE_ENV;\n\tawait plugin.buildStart?.call(mockContext);\n\n\tconst messages = await realFs.promises.readdir(path.join(outdir, \"messages\"));\n\texpect(messages).toContain(\"en.js\");\n\texpect(messages).toContain(\"de.js\");\n\texpect(messages).not.toContain(\"hello.js\");\n});\n\n// All four candidate names are registered inside the project directory so\n// renames/format switches are reported even by backends whose watchers only\n// report registered files (webpack).\ntest(\"registers all config candidates inside the project directory\", async () => {\n\tprocess.env.NODE_ENV = \"development\";\n\n\tconst { workspace, projectDir } = await createProjectFixture({\n\t\tconfig: false,\n\t});\n\n\tconst { paraglideVitePlugin: vitePlugin } =\n\t\tawait import(\"../bundler-plugins/vite.js\");\n\tconst plugin = vitePlugin({ project: projectDir }) as any;\n\tsetViteRoot(plugin, workspace);\n\n\tconst addedWatchFiles: string[] = [];\n\tawait plugin.buildStart?.call({\n\t\taddWatchFile: (p: string) => {\n\t\t\taddedWatchFiles.push(p);\n\t\t},\n\t});\n\n\tfor (const name of [\n\t\t\"paraglide.config.js\",\n\t\t\"paraglide.config.mjs\",\n\t\t\"paraglide.config.ts\",\n\t\t\"paraglide.config.cjs\",\n\t]) {\n\t\texpect(addedWatchFiles).toContain(path.join(projectDir, name));\n\t}\n});\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { Plugin } from "vite";
2
- import type { CompilerOptions } from "../compiler/compiler-options.js";
3
- export type ParaglideVitePluginOptions = CompilerOptions & {
2
+ import type { ParaglidePluginOptions } from "./unplugin.js";
3
+ export type ParaglideVitePluginOptions = ParaglidePluginOptions & {
4
4
  /**
5
5
  * Emit one compiler-specialized client asset tree per project locale.
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/bundler-plugins/vite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAiBhD,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAClC,OAAmC;IAEnC,MAAM,EAAE,0BAA0B,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IACnE,IAAI,CAAC,0BAA0B,EAAE,CAAC;QACjC,OAAO,wBAAwB,CAAC,eAAe,CAAW,CAAC;IAC5D,CAAC;IAED,OAAO,2BAA2B,CAAC;QAClC,eAAe;QACf,oBAAoB,EAAE,CAAC,OAAO,EAAE,EAAE,CACjC,wBAAwB,CAAC,OAAO,CAAW;KAC5C,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { createVitePlugin } from \"unplugin\";\nimport type { Plugin } from \"vite\";\nimport type { CompilerOptions } from \"../compiler/compiler-options.js\";\nimport { createPerLocaleBuildPlugins } from \"./per-locale-build/index.js\";\nimport { unpluginFactory } from \"./unplugin.js\";\n\nexport type ParaglideVitePluginOptions = CompilerOptions & {\n\t/**\n\t * Emit one compiler-specialized client asset tree per project locale.\n\t *\n\t * Requires Vite 8+. Builds one untouched Rolldown client environment per\n\t * locale and emits `paraglide-vite-locales.json`. Locale changes need to use\n\t * full-document navigation. Framework SSR graph selection requires a public\n\t * framework integration API.\n\t *\n\t * @experimental\n\t * @default false\n\t */\n\texperimentalPerLocaleBuild?: boolean;\n};\n\nconst createCompilerVitePlugin = createVitePlugin(unpluginFactory);\n\nexport function paraglideVitePlugin(\n\toptions: ParaglideVitePluginOptions\n): Plugin | Plugin[] {\n\tconst { experimentalPerLocaleBuild, ...compilerOptions } = options;\n\tif (!experimentalPerLocaleBuild) {\n\t\treturn createCompilerVitePlugin(compilerOptions) as Plugin;\n\t}\n\n\treturn createPerLocaleBuildPlugins({\n\t\tcompilerOptions,\n\t\tcreateCompilerPlugin: (options) =>\n\t\t\tcreateCompilerVitePlugin(options) as Plugin,\n\t});\n}\n"]}
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/bundler-plugins/vite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAiBhD,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAClC,OAAmC;IAEnC,MAAM,EAAE,0BAA0B,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IACnE,IAAI,CAAC,0BAA0B,EAAE,CAAC;QACjC,OAAO,wBAAwB,CAAC,eAAe,CAAW,CAAC;IAC5D,CAAC;IAED,OAAO,2BAA2B,CAAC;QAClC,eAAe;QACf,oBAAoB,EAAE,CAAC,OAAO,EAAE,EAAE,CACjC,wBAAwB,CAAC,OAAO,CAAW;KAC5C,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { createVitePlugin } from \"unplugin\";\nimport type { Plugin } from \"vite\";\nimport type { ParaglidePluginOptions } from \"./unplugin.js\";\nimport { createPerLocaleBuildPlugins } from \"./per-locale-build/index.js\";\nimport { unpluginFactory } from \"./unplugin.js\";\n\nexport type ParaglideVitePluginOptions = ParaglidePluginOptions & {\n\t/**\n\t * Emit one compiler-specialized client asset tree per project locale.\n\t *\n\t * Requires Vite 8+. Builds one untouched Rolldown client environment per\n\t * locale and emits `paraglide-vite-locales.json`. Locale changes need to use\n\t * full-document navigation. Framework SSR graph selection requires a public\n\t * framework integration API.\n\t *\n\t * @experimental\n\t * @default false\n\t */\n\texperimentalPerLocaleBuild?: boolean;\n};\n\nconst createCompilerVitePlugin = createVitePlugin(unpluginFactory);\n\nexport function paraglideVitePlugin(\n\toptions: ParaglideVitePluginOptions\n): Plugin | Plugin[] {\n\tconst { experimentalPerLocaleBuild, ...compilerOptions } = options;\n\tif (!experimentalPerLocaleBuild) {\n\t\treturn createCompilerVitePlugin(compilerOptions) as Plugin;\n\t}\n\n\treturn createPerLocaleBuildPlugins({\n\t\tcompilerOptions,\n\t\tcreateCompilerPlugin: (options) =>\n\t\t\tcreateCompilerVitePlugin(options) as Plugin,\n\t});\n}\n"]}
@@ -27,10 +27,11 @@ test("experimentalPerLocaleBuild generates locale source modules and installs th
27
27
  throw new Error("Expected multiple Vite plugins");
28
28
  }
29
29
  expect(plugins.map((plugin) => plugin.name)).toEqual([
30
+ "paraglide-config-discovery-root",
30
31
  "unplugin-paraglide-js",
31
32
  "paraglide-vite-locale-environments",
32
33
  ]);
33
- const compiler = plugins[0];
34
+ const compiler = plugins[1];
34
35
  if (typeof compiler.buildStart !== "function") {
35
36
  throw new Error("Expected the compiler buildStart hook");
36
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vite.test.js","sourceRoot":"","sources":["../../src/bundler-plugins/vite.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n} from \"@inlang/sdk\";\nimport { memfs } from \"memfs\";\nimport { expect, test } from \"vitest\";\nimport { perLocaleBuildStaticLocaleExpression } from \"../compiler/per-locale-build.js\";\nimport { paraglideVitePlugin } from \"./vite.js\";\n\ntest(\"experimentalPerLocaleBuild generates locale source modules and installs the Vite environment orchestrator\", async () => {\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t}),\n\t});\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst plugins = paraglideVitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/src/paraglide\",\n\t\tfs,\n\t\texperimentalPerLocaleBuild: true,\n\t\tstrategy: [\"preferredLanguage\", \"baseLocale\"],\n\t\tadditionalFiles: { \"custom.js\": \"export const custom = true;\\n\" },\n\t});\n\tif (!Array.isArray(plugins)) {\n\t\tthrow new Error(\"Expected multiple Vite plugins\");\n\t}\n\texpect(plugins.map((plugin) => plugin.name)).toEqual([\n\t\t\"unplugin-paraglide-js\",\n\t\t\"paraglide-vite-locale-environments\",\n\t]);\n\n\tconst compiler = plugins[0]!;\n\tif (typeof compiler.buildStart !== \"function\") {\n\t\tthrow new Error(\"Expected the compiler buildStart hook\");\n\t}\n\tawait compiler.buildStart.call({ addWatchFile() {} } as never, {} as never);\n\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/messages/en.js\", \"utf8\")\n\t).toBeDefined();\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/messages/de.js\", \"utf8\")\n\t).toBeDefined();\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/runtime.js\", \"utf8\")\n\t).toContain(perLocaleBuildStaticLocaleExpression);\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/custom.js\", \"utf8\")\n\t).toContain(\"export const custom = true;\");\n\tawait expect(\n\t\tfs.promises.readFile(\"/src/paraglide/tanstack-start.server.js\", \"utf8\")\n\t).rejects.toThrow();\n});\n\ntest(\"experimentalPerLocaleBuild rejects conflicting compiler options\", () => {\n\tconst common = { project: \"/project.inlang\", outdir: \"/src/paraglide\" };\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\texperimentalStaticLocale: '\"de\"',\n\t\t})\n\t).toThrow(\"cannot be combined with experimentalStaticLocale\");\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t})\n\t).toThrow(\"cannot be combined with experimentalMiddlewareLocaleSplitting\");\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\toutputStructure: \"message-modules\",\n\t\t})\n\t).toThrow('requires outputStructure: \"locale-modules\"');\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\trouteStrategies: [\n\t\t\t\t{\n\t\t\t\t\tmatch: \"/api/:path(.*)?\",\n\t\t\t\t\texclude: true,\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\t).not.toThrow();\n});\n"]}
1
+ {"version":3,"file":"vite.test.js","sourceRoot":"","sources":["../../src/bundler-plugins/vite.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n} from \"@inlang/sdk\";\nimport { memfs } from \"memfs\";\nimport { expect, test } from \"vitest\";\nimport { perLocaleBuildStaticLocaleExpression } from \"../compiler/per-locale-build.js\";\nimport { paraglideVitePlugin } from \"./vite.js\";\n\ntest(\"experimentalPerLocaleBuild generates locale source modules and installs the Vite environment orchestrator\", async () => {\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: { baseLocale: \"en\", locales: [\"en\", \"de\"] },\n\t\t}),\n\t});\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst plugins = paraglideVitePlugin({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/src/paraglide\",\n\t\tfs,\n\t\texperimentalPerLocaleBuild: true,\n\t\tstrategy: [\"preferredLanguage\", \"baseLocale\"],\n\t\tadditionalFiles: { \"custom.js\": \"export const custom = true;\\n\" },\n\t});\n\tif (!Array.isArray(plugins)) {\n\t\tthrow new Error(\"Expected multiple Vite plugins\");\n\t}\n\texpect(plugins.map((plugin) => plugin.name)).toEqual([\n\t\t\"paraglide-config-discovery-root\",\n\t\t\"unplugin-paraglide-js\",\n\t\t\"paraglide-vite-locale-environments\",\n\t]);\n\n\tconst compiler = plugins[1]!;\n\tif (typeof compiler.buildStart !== \"function\") {\n\t\tthrow new Error(\"Expected the compiler buildStart hook\");\n\t}\n\tawait compiler.buildStart.call({ addWatchFile() {} } as never, {} as never);\n\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/messages/en.js\", \"utf8\")\n\t).toBeDefined();\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/messages/de.js\", \"utf8\")\n\t).toBeDefined();\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/runtime.js\", \"utf8\")\n\t).toContain(perLocaleBuildStaticLocaleExpression);\n\texpect(\n\t\tawait fs.promises.readFile(\"/src/paraglide/custom.js\", \"utf8\")\n\t).toContain(\"export const custom = true;\");\n\tawait expect(\n\t\tfs.promises.readFile(\"/src/paraglide/tanstack-start.server.js\", \"utf8\")\n\t).rejects.toThrow();\n});\n\ntest(\"experimentalPerLocaleBuild rejects conflicting compiler options\", () => {\n\tconst common = { project: \"/project.inlang\", outdir: \"/src/paraglide\" };\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\texperimentalStaticLocale: '\"de\"',\n\t\t})\n\t).toThrow(\"cannot be combined with experimentalStaticLocale\");\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\texperimentalMiddlewareLocaleSplitting: true,\n\t\t})\n\t).toThrow(\"cannot be combined with experimentalMiddlewareLocaleSplitting\");\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\toutputStructure: \"message-modules\",\n\t\t})\n\t).toThrow('requires outputStructure: \"locale-modules\"');\n\texpect(() =>\n\t\tparaglideVitePlugin({\n\t\t\t...common,\n\t\t\texperimentalPerLocaleBuild: true,\n\t\t\trouteStrategies: [\n\t\t\t\t{\n\t\t\t\t\tmatch: \"/api/:path(.*)?\",\n\t\t\t\t\texclude: true,\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\t).not.toThrow();\n});\n"]}
@@ -1 +1 @@
1
- export declare const paraglideWebpackPlugin: (options: import("../index.js").CompilerOptions) => WebpackPluginInstance;
1
+ export declare const paraglideWebpackPlugin: (options: import("./unplugin.js").ParaglidePluginOptions) => WebpackPluginInstance;
@@ -2,11 +2,15 @@ import { Command, InvalidArgumentError } from "commander";
2
2
  import fs from "node:fs";
3
3
  import { resolve, relative } from "node:path";
4
4
  import { Logger } from "../../../services/logger/index.js";
5
- import { DEFAULT_OUTDIR, DEFAULT_PROJECT_PATH } from "../../defaults.js";
5
+ import { DEFAULT_OUTDIR, DEFAULT_PROJECT_PATH, } from "../../../services/config/defaults.js";
6
6
  import { compile } from "../../../compiler/compile.js";
7
+ import { defaultCompilerOptions } from "../../../compiler/compiler-options.js";
7
8
  import { seedPreviousCompilationFromOutdir } from "../../../compiler/seed-previous-compilation.js";
8
- import { defaultCompilerOptions, } from "../../../compiler/compiler-options.js";
9
9
  import { createTrackedFs, getWatchTargets, } from "../../../services/file-watching/tracked-fs.js";
10
+ import * as v from "valibot";
11
+ import { clearParaglideConfigCache, isConfigFileName, loadParaglideConfig, resolveCompilerOptions, resolveConfigCandidate, strategyNameSchema, } from "../../../services/config/index.js";
12
+ import { nodeNormalizePath } from "../../../utilities/node-normalize-path.js";
13
+ const errorMessage = (error) => error instanceof Error ? error.message : String(error);
10
14
  const parseOutputStructure = (value) => {
11
15
  if (value === "message-modules" || value === "locale-modules") {
12
16
  return value;
@@ -16,8 +20,8 @@ const parseOutputStructure = (value) => {
16
20
  export const compileCommand = new Command()
17
21
  .name("compile")
18
22
  .summary("Compiles inlang Paraglide-JS")
19
- .requiredOption("--project <path>", 'The path to the inlang project. Example: "./project.inlang"', DEFAULT_PROJECT_PATH)
20
- .requiredOption("--outdir <path>", 'The path to the output directory. Example: "./src/paraglide"', DEFAULT_OUTDIR)
23
+ .option("--project <path>", `The path to the inlang project. Example: "./project.inlang". Defaults to "${DEFAULT_PROJECT_PATH}".`)
24
+ .option("--outdir <path>", `The path to the output directory. Example: "./src/paraglide". Defaults to "${DEFAULT_OUTDIR}".`)
21
25
  .option("--strategy <items...>", [
22
26
  "The strategy to be used.",
23
27
  "",
@@ -25,49 +29,98 @@ export const compileCommand = new Command()
25
29
  "Read more on https://paraglidejs.com/strategy",
26
30
  ].join("\n"))
27
31
  .requiredOption("--silent", "Only log errors to the console", false)
28
- .option("--emit-ts-declarations", "Emit .d.ts files for the generated output (requires the typescript package)", defaultCompilerOptions.emitTsDeclarations)
32
+ .option("--emit-ts-declarations", `Emit .d.ts files for the generated output (requires the typescript package) (default: ${defaultCompilerOptions.emitTsDeclarations})`)
29
33
  .option("--no-emit-ts-declarations", "Do not emit .d.ts files for the generated output")
30
- .option("--emit-git-ignore", "Emit a .gitignore in the output directory", defaultCompilerOptions.emitGitIgnore)
34
+ .option("--emit-git-ignore", `Emit a .gitignore in the output directory (default: ${defaultCompilerOptions.emitGitIgnore})`)
31
35
  .option("--no-emit-git-ignore", "Do not emit a .gitignore in the output directory")
32
- .option("--emit-prettier-ignore", "Emit a .prettierignore in the output directory", defaultCompilerOptions.emitPrettierIgnore)
36
+ .option("--emit-prettier-ignore", `Emit a .prettierignore in the output directory (default: ${defaultCompilerOptions.emitPrettierIgnore})`)
33
37
  .option("--no-emit-prettier-ignore", "Do not emit a .prettierignore in the output directory")
34
- .option("--emit-readme", "Emit a README.md in the output directory (helps LLMs understand the generated code)", defaultCompilerOptions.emitReadme)
38
+ .option("--emit-readme", `Emit a README.md in the output directory (helps LLMs understand the generated code) (default: ${defaultCompilerOptions.emitReadme})`)
35
39
  .option("--no-emit-readme", "Do not emit README.md in the output directory")
36
40
  .option("--is-server <expression>", [
37
41
  "JavaScript expression for runtime `isServer` (enables server/client tree-shaking).",
38
- 'Quote if the expression contains spaces, e.g. --is-server \'typeof window === "undefined"\'.',
42
+ "Quote if the expression contains spaces, e.g. --is-server 'typeof window === \"undefined\"'.",
39
43
  "Vite SSR example: --is-server 'import.meta.env.SSR'",
40
44
  ].join(" "))
45
+ .option("--clean-outdir", "Remove files in the output directory that are not generated by this compile", defaultCompilerOptions.cleanOutdir)
46
+ .option("--no-clean-outdir", "Preserve files in the output directory that are not generated by this compile")
47
+ .option("--experimental-static-locale <expression>", [
48
+ "JavaScript expression for a compile-time locale constant (experimental).",
49
+ "For a literal locale, include the JavaScript quotes, e.g. --experimental-static-locale '\"de\"'.",
50
+ ].join(" "))
51
+ .option("--disable-async-local-storage", "Use the synchronous request-locale fallback instead of AsyncLocalStorage", defaultCompilerOptions.disableAsyncLocalStorage)
41
52
  .option("--output-structure <structure>", [
42
- 'The output structure for compiled messages. Either "message-modules" or "locale-modules".',
53
+ `The output structure for compiled messages. Either "message-modules" or "locale-modules" (default: "${defaultCompilerOptions.outputStructure}").`,
43
54
  "",
44
55
  '"message-modules" gives each message its own module (better tree-shaking).',
45
56
  '"locale-modules" bundles messages per locale (fewer files, better for large projects in dev).',
46
- ].join("\n"), parseOutputStructure, defaultCompilerOptions.outputStructure)
57
+ ].join("\n"), parseOutputStructure)
47
58
  .option("--watch", "Watch project files and recompile on change", false)
48
59
  .action(async (options) => {
49
60
  const logger = new Logger({ silent: options.silent, prefix: true });
50
- const path = resolve(process.cwd(), options.project);
51
- const compileOptions = {
52
- project: path,
53
- outdir: options.outdir,
54
- strategy: options.strategy ?? defaultCompilerOptions.strategy,
55
- emitTsDeclarations: options.emitTsDeclarations ??
56
- defaultCompilerOptions.emitTsDeclarations,
57
- emitGitIgnore: options.emitGitIgnore ?? defaultCompilerOptions.emitGitIgnore,
58
- emitPrettierIgnore: options.emitPrettierIgnore ??
59
- defaultCompilerOptions.emitPrettierIgnore,
60
- emitReadme: options.emitReadme ?? defaultCompilerOptions.emitReadme,
61
- isServer: options.isServer ?? defaultCompilerOptions.isServer,
62
- outputStructure: options.outputStructure ??
63
- defaultCompilerOptions.outputStructure,
61
+ const projectDir = nodeNormalizePath(resolve(process.cwd(), options.project ?? DEFAULT_PROJECT_PATH));
62
+ const loadConfig = () => loadParaglideConfig({ projectDir, logger });
63
+ let projectOverride = options.project;
64
+ if (projectOverride === undefined) {
65
+ projectOverride = DEFAULT_PROJECT_PATH;
66
+ logger.info(`--project was not provided, using "${DEFAULT_PROJECT_PATH}".`);
67
+ }
68
+ const buildCompileOptions = () => {
69
+ let validatedStrategy;
70
+ if (options.strategy !== undefined) {
71
+ const parsed = v.safeParse(v.array(strategyNameSchema), options.strategy);
72
+ if (!parsed.success) {
73
+ const details = parsed.issues
74
+ .map((i) => `"${v.getDotPath(i) ?? "(root)"}": ${i.message}`)
75
+ .join(", ");
76
+ throw new Error(`Invalid --strategy: ${details}`);
77
+ }
78
+ validatedStrategy = parsed.output;
79
+ }
80
+ let outdirOverride = options.outdir;
81
+ if (outdirOverride === undefined &&
82
+ loadedConfig?.config.outdir === undefined) {
83
+ outdirOverride = DEFAULT_OUTDIR;
84
+ }
85
+ return resolveCompilerOptions({
86
+ config: loadedConfig?.config,
87
+ overrides: {
88
+ project: projectOverride,
89
+ outdir: outdirOverride,
90
+ strategy: validatedStrategy,
91
+ emitTsDeclarations: options.emitTsDeclarations,
92
+ emitGitIgnore: options.emitGitIgnore,
93
+ emitPrettierIgnore: options.emitPrettierIgnore,
94
+ emitReadme: options.emitReadme,
95
+ isServer: options.isServer,
96
+ cleanOutdir: options.cleanOutdir,
97
+ experimentalStaticLocale: options.experimentalStaticLocale,
98
+ disableAsyncLocalStorage: options.disableAsyncLocalStorage,
99
+ // The CLI always uses message-modules unless told otherwise
100
+ // (plugins apply their own development default).
101
+ outputStructure: options.outputStructure ?? defaultCompilerOptions.outputStructure,
102
+ },
103
+ root: process.cwd(),
104
+ });
64
105
  };
106
+ let loadedConfig;
107
+ let compileOptions;
108
+ try {
109
+ loadedConfig = await loadConfig();
110
+ compileOptions = buildCompileOptions();
111
+ }
112
+ catch (error) {
113
+ logger.error(errorMessage(error));
114
+ process.exit(1);
115
+ }
65
116
  if (!options.watch) {
66
117
  logger.info(`Compiling inlang project ...`);
67
118
  try {
68
- const previousCompilation = await seedPreviousCompilationFromOutdir({
69
- outdir: compileOptions.outdir,
70
- });
119
+ const previousCompilation = compileOptions.cleanOutdir
120
+ ? await seedPreviousCompilationFromOutdir({
121
+ outdir: compileOptions.outdir,
122
+ })
123
+ : undefined;
71
124
  await compile({
72
125
  ...compileOptions,
73
126
  previousCompilation,
@@ -89,14 +142,52 @@ export const compileCommand = new Command()
89
142
  let compileTimer;
90
143
  let compileInProgress = false;
91
144
  let compileRequested = false;
145
+ // Set by the project-directory watcher when a config-named file
146
+ // changes — survives debounced coalescing with unrelated events.
147
+ let configChangedSinceLastBuild = false;
148
+ /**
149
+ * Reacts to a config-named event in the project directory:
150
+ * rescans the candidate winner and reloads. A missing config
151
+ * falls back to the built-in defaults; an invalid one fails the
152
+ * reload (caller skips the compilation).
153
+ */
154
+ const refreshConfig = async () => {
155
+ const winner = await resolveConfigCandidate(projectDir);
156
+ if (winner === undefined) {
157
+ if (loadedConfig !== undefined) {
158
+ logger.warn("Paraglide config file was removed, compiling with default options.");
159
+ }
160
+ loadedConfig = undefined;
161
+ compileOptions = buildCompileOptions();
162
+ return true;
163
+ }
164
+ try {
165
+ clearParaglideConfigCache({ projectDir });
166
+ const nextLoadedConfig = await loadConfig();
167
+ if (nextLoadedConfig === undefined)
168
+ return true; // raced deletion
169
+ loadedConfig = nextLoadedConfig;
170
+ compileOptions = buildCompileOptions();
171
+ return true;
172
+ }
173
+ catch (error) {
174
+ logger.error(errorMessage(error));
175
+ logger.error("Skipping compilation because of the invalid paraglide config.");
176
+ return false;
177
+ }
178
+ };
92
179
  const updateWatchers = (files) => {
93
- const { files: nextFiles, directories: nextDirectories, isIgnoredPath, } = getWatchTargets(files, { outdir: options.outdir });
180
+ const { files: nextFiles, directories: nextDirectories, isIgnoredPath, } = getWatchTargets(files, { outdir: compileOptions.outdir });
94
181
  for (const [filePath, watcher] of fileWatchers) {
95
182
  if (!nextFiles.has(filePath)) {
96
183
  watcher.close();
97
184
  fileWatchers.delete(filePath);
98
185
  }
99
186
  }
187
+ // The project directory is always watched: it hosts the config
188
+ // file, and its other contents (settings.json, messages/) are
189
+ // compile inputs anyway.
190
+ nextDirectories.add(projectDir);
100
191
  for (const [directoryPath, watcher] of directoryWatchers) {
101
192
  if (!nextDirectories.has(directoryPath)) {
102
193
  watcher.close();
@@ -105,7 +196,7 @@ export const compileCommand = new Command()
105
196
  }
106
197
  const attachWatcherErrorHandler = (watcher, targetPath, targetType) => {
107
198
  watcher.on("error", (error) => {
108
- logger.warn(`Watch ${targetType} error for ${targetPath}: ${error.message}`);
199
+ logger.warn(`Watch ${targetType} error for ${targetPath}: ${errorMessage(error)}`);
109
200
  });
110
201
  };
111
202
  for (const filePath of nextFiles) {
@@ -119,7 +210,7 @@ export const compileCommand = new Command()
119
210
  attachWatcherErrorHandler(watcher, filePath, "file");
120
211
  fileWatchers.set(filePath, watcher);
121
212
  }
122
- catch (error) {
213
+ catch {
123
214
  logger.warn(`Failed to watch file: ${filePath}`);
124
215
  }
125
216
  }
@@ -129,7 +220,11 @@ export const compileCommand = new Command()
129
220
  }
130
221
  try {
131
222
  const watcher = fs.watch(directoryPath, (eventType, filename) => {
223
+ const isProjectDir = directoryPath === projectDir;
132
224
  if (!filename) {
225
+ if (isProjectDir) {
226
+ configChangedSinceLastBuild = true;
227
+ }
133
228
  scheduleCompile(directoryPath);
134
229
  return;
135
230
  }
@@ -137,12 +232,20 @@ export const compileCommand = new Command()
137
232
  if (isIgnoredPath(changedPath)) {
138
233
  return;
139
234
  }
235
+ // Config-named events must not be lost to debounce
236
+ // coalescing with unrelated files. Ordinary files are
237
+ // still scheduled: new inputs can appear directly in
238
+ // the project directory (e.g. a locale file matching
239
+ // ./messages/{locale}.json patterns rooted there).
240
+ if (isProjectDir && isConfigFileName(changedPath)) {
241
+ configChangedSinceLastBuild = true;
242
+ }
140
243
  scheduleCompile(changedPath);
141
244
  });
142
245
  attachWatcherErrorHandler(watcher, directoryPath, "directory");
143
246
  directoryWatchers.set(directoryPath, watcher);
144
247
  }
145
- catch (error) {
248
+ catch {
146
249
  logger.warn(`Failed to watch directory: ${directoryPath}`);
147
250
  }
148
251
  }
@@ -155,6 +258,21 @@ export const compileCommand = new Command()
155
258
  compileInProgress = true;
156
259
  const previouslyReadFiles = new Set(readFiles);
157
260
  clearReadFiles();
261
+ if (configChangedSinceLastBuild) {
262
+ configChangedSinceLastBuild = false;
263
+ const succeeded = await refreshConfig();
264
+ if (!succeeded) {
265
+ // Invalid config: skip this compilation entirely — the
266
+ // previously compiled output stays on disk untouched.
267
+ compileInProgress = false;
268
+ updateWatchers(new Set(readFiles));
269
+ if (compileRequested) {
270
+ compileRequested = false;
271
+ runCompile();
272
+ }
273
+ return;
274
+ }
275
+ }
158
276
  if (changedPath) {
159
277
  logger.info(`Re-compiling inlang project... File "${relative(process.cwd(), changedPath)}" has changed.`);
160
278
  }
@@ -163,9 +281,11 @@ export const compileCommand = new Command()
163
281
  }
164
282
  try {
165
283
  const seededPrevious = previousCompilation ??
166
- (await seedPreviousCompilationFromOutdir({
167
- outdir: compileOptions.outdir,
168
- }));
284
+ (compileOptions.cleanOutdir
285
+ ? await seedPreviousCompilationFromOutdir({
286
+ outdir: compileOptions.outdir,
287
+ })
288
+ : undefined);
169
289
  previousCompilation = await compile({
170
290
  ...compileOptions,
171
291
  fs: trackedFs,
@@ -191,7 +311,7 @@ export const compileCommand = new Command()
191
311
  logger.error(e);
192
312
  }
193
313
  finally {
194
- updateWatchers(readFiles);
314
+ updateWatchers(new Set(readFiles));
195
315
  compileInProgress = false;
196
316
  if (compileRequested) {
197
317
  compileRequested = false;