@inlang/paraglide-js 2.27.0 → 2.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/bundler-plugins/per-locale-build/index.js +14 -7
- package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +235 -2
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
- package/dist/bundler-plugins/unplugin.d.ts +1 -1
- package/dist/bundler-plugins/unplugin.js +79 -10
- package/dist/bundler-plugins/unplugin.js.map +1 -1
- package/dist/bundler-plugins/unplugin.test.js +334 -1
- package/dist/bundler-plugins/unplugin.test.js.map +1 -1
- package/dist/bundler-plugins/vite.js +2 -1
- package/dist/bundler-plugins/vite.js.map +1 -1
- package/dist/bundler-plugins/vite.test.js +1 -1
- package/dist/bundler-plugins/vite.test.js.map +1 -1
- package/dist/cli/commands/compile/command.js +13 -0
- package/dist/cli/commands/compile/command.js.map +1 -1
- package/dist/cli/commands/compile/command.test.js +87 -3
- package/dist/cli/commands/compile/command.test.js.map +1 -1
- package/dist/cli/commands/init/command.d.ts +5 -0
- package/dist/cli/commands/init/command.js +213 -59
- package/dist/cli/commands/init/command.js.map +1 -1
- package/dist/cli/commands/init/command.test.d.ts +1 -0
- package/dist/cli/commands/init/command.test.js +123 -0
- package/dist/cli/commands/init/command.test.js.map +1 -0
- package/dist/cli/init-options.d.ts +11 -0
- package/dist/cli/init-options.js +2 -0
- package/dist/cli/init-options.js.map +1 -0
- package/dist/cli/steps/add-inlang-check.js +2 -2
- package/dist/cli/steps/add-inlang-check.js.map +1 -1
- package/dist/cli/steps/add-message-lint.d.ts +34 -0
- package/dist/cli/steps/add-message-lint.js +105 -0
- package/dist/cli/steps/add-message-lint.js.map +1 -0
- package/dist/cli/steps/add-message-lint.test.d.ts +1 -0
- package/dist/cli/steps/add-message-lint.test.js +74 -0
- package/dist/cli/steps/add-message-lint.test.js.map +1 -0
- package/dist/cli/steps/add-vite-plugin.d.ts +18 -0
- package/dist/cli/steps/add-vite-plugin.js +34 -6
- package/dist/cli/steps/add-vite-plugin.js.map +1 -1
- package/dist/cli/steps/add-vite-plugin.test.js +25 -9
- package/dist/cli/steps/add-vite-plugin.test.js.map +1 -1
- package/dist/cli/steps/check-for-uncomitted-changes.d.ts +3 -0
- package/dist/cli/steps/check-for-uncomitted-changes.js +15 -3
- package/dist/cli/steps/check-for-uncomitted-changes.js.map +1 -1
- package/dist/cli/steps/detect-bundler.d.ts +1 -0
- package/dist/cli/steps/detect-bundler.js +7 -1
- package/dist/cli/steps/detect-bundler.js.map +1 -1
- package/dist/cli/steps/initialize-inlang-project.d.ts +4 -3
- package/dist/cli/steps/initialize-inlang-project.js +60 -157
- package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
- package/dist/cli/steps/maybe-add-machine-translation.d.ts +4 -0
- package/dist/cli/steps/maybe-add-machine-translation.js +11 -6
- package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.d.ts +2 -0
- package/dist/cli/steps/maybe-add-sherlock.js +12 -6
- package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.test.d.ts +1 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js +44 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js.map +1 -0
- package/dist/cli/steps/prompt-for-outdir.d.ts +2 -0
- package/dist/cli/steps/prompt-for-outdir.js +4 -0
- package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
- package/dist/cli/steps/update-package-json.js +8 -13
- package/dist/cli/steps/update-package-json.js.map +1 -1
- package/dist/cli/steps/update-ts-config.d.ts +6 -0
- package/dist/cli/steps/update-ts-config.js +27 -4
- package/dist/cli/steps/update-ts-config.js.map +1 -1
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.js +6 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/utils.test.d.ts +1 -0
- package/dist/cli/utils.test.js +16 -0
- package/dist/cli/utils.test.js.map +1 -0
- package/dist/compiler/compile-annotation.js +6 -1
- package/dist/compiler/compile-annotation.js.map +1 -1
- package/dist/compiler/compile-bundle.d.ts +4 -0
- package/dist/compiler/compile-bundle.js +67 -2
- package/dist/compiler/compile-bundle.js.map +1 -1
- package/dist/compiler/compile-bundle.test.js +214 -1
- package/dist/compiler/compile-bundle.test.js.map +1 -1
- package/dist/compiler/compile-lifecycle.test.d.ts +1 -0
- package/dist/compiler/compile-lifecycle.test.js +69 -0
- package/dist/compiler/compile-lifecycle.test.js.map +1 -0
- package/dist/compiler/compile-local-variable.test.js +14 -14
- package/dist/compiler/compile-local-variable.test.js.map +1 -1
- package/dist/compiler/compile-message.exact-number.test.js +1 -1
- package/dist/compiler/compile-message.exact-number.test.js.map +1 -1
- package/dist/compiler/compile-message.locals.test.js +1 -1
- package/dist/compiler/compile-message.locals.test.js.map +1 -1
- package/dist/compiler/compile-message.test.js +2 -2
- package/dist/compiler/compile-message.test.js.map +1 -1
- package/dist/compiler/compile-pattern.test.js +5 -5
- package/dist/compiler/compile-pattern.test.js.map +1 -1
- package/dist/compiler/compile-project.js +1 -0
- package/dist/compiler/compile-project.js.map +1 -1
- package/dist/compiler/compile-project.test.js +94 -1
- package/dist/compiler/compile-project.test.js.map +1 -1
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/compile.test.js +70 -0
- package/dist/compiler/compile.test.js.map +1 -1
- package/dist/compiler/compiler-options.d.ts +41 -0
- package/dist/compiler/compiler-options.js.map +1 -1
- package/dist/compiler/output-structure/message-modules.js +1 -1
- package/dist/compiler/output-structure/message-modules.js.map +1 -1
- package/dist/compiler/registry.js +71 -13
- package/dist/compiler/registry.js.map +1 -1
- package/dist/compiler/registry.test.d.ts +1 -0
- package/dist/compiler/registry.test.js +291 -0
- package/dist/compiler/registry.test.js.map +1 -0
- package/dist/compiler/runtime/create-runtime.d.ts +2 -0
- package/dist/compiler/runtime/create-runtime.js +9 -0
- package/dist/compiler/runtime/create-runtime.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js +8 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js +26 -0
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.js +47 -5
- package/dist/compiler/runtime/extract-locale-from-header.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.test.js +58 -0
- package/dist/compiler/runtime/extract-locale-from-header.test.js.map +1 -1
- package/dist/compiler/runtime/get-locale.js +7 -1
- package/dist/compiler/runtime/get-locale.js.map +1 -1
- package/dist/compiler/runtime/get-locale.test.js +95 -0
- package/dist/compiler/runtime/get-locale.test.js.map +1 -1
- package/dist/compiler/runtime/localize-href.d.ts +8 -0
- package/dist/compiler/runtime/localize-href.js +60 -0
- package/dist/compiler/runtime/localize-href.js.map +1 -1
- package/dist/compiler/runtime/localize-href.test.js +227 -1
- package/dist/compiler/runtime/localize-href.test.js.map +1 -1
- package/dist/compiler/runtime/set-locale.js +24 -6
- package/dist/compiler/runtime/set-locale.js.map +1 -1
- package/dist/compiler/runtime/set-locale.test.js +182 -0
- package/dist/compiler/runtime/set-locale.test.js.map +1 -1
- package/dist/compiler/runtime/type.d.ts +2 -0
- package/dist/compiler/runtime/type.js.map +1 -1
- package/dist/compiler/runtime/type.test.js +34 -0
- package/dist/compiler/runtime/type.test.js.map +1 -1
- package/dist/compiler/runtime/variables.d.ts +2 -0
- package/dist/compiler/runtime/variables.js +7 -0
- package/dist/compiler/runtime/variables.js.map +1 -1
- package/dist/compiler/server/middleware.d.ts +8 -2
- package/dist/compiler/server/middleware.js +175 -7
- package/dist/compiler/server/middleware.js.map +1 -1
- package/dist/compiler/server/middleware.test.js +750 -3
- package/dist/compiler/server/middleware.test.js.map +1 -1
- package/dist/eslint/index.d.ts +4 -0
- package/dist/eslint/index.js +8 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.d.ts +3 -0
- package/dist/eslint/no-dynamic-message-access.js +150 -0
- package/dist/eslint/no-dynamic-message-access.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.test.d.ts +1 -0
- package/dist/eslint/no-dynamic-message-access.test.js +126 -0
- package/dist/eslint/no-dynamic-message-access.test.js.map +1 -0
- package/dist/eslint/oxlint.test.d.ts +1 -0
- package/dist/eslint/oxlint.test.js +64 -0
- package/dist/eslint/oxlint.test.js.map +1 -0
- package/dist/services/config/config-schema.d.ts +2 -0
- package/dist/services/config/config-schema.js +2 -0
- package/dist/services/config/config-schema.js.map +1 -1
- package/dist/services/config/load-paraglide-config.test.js +12 -0
- package/dist/services/config/load-paraglide-config.test.js.map +1 -1
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/env-variables/index.js.map +1 -1
- package/dist/services/file-handling/write-output.bench.js +51 -11
- package/dist/services/file-handling/write-output.bench.js.map +1 -1
- package/dist/services/file-handling/write-output.js +60 -20
- package/dist/services/file-handling/write-output.js.map +1 -1
- package/dist/services/file-handling/write-output.test.js +175 -0
- package/dist/services/file-handling/write-output.test.js.map +1 -1
- package/package.json +14 -4
package/dist/compiler/compile.js
CHANGED
|
@@ -37,24 +37,43 @@ export async function compile(options) {
|
|
|
37
37
|
path: withDefaultOptions.project,
|
|
38
38
|
fs,
|
|
39
39
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
40
|
+
let failed = false;
|
|
41
|
+
try {
|
|
42
|
+
const output = await compileProject({
|
|
43
|
+
compilerOptions: withDefaultOptions,
|
|
44
|
+
project,
|
|
45
|
+
projectPath: withDefaultOptions.project,
|
|
46
|
+
});
|
|
47
|
+
const outputHashes = await writeOutput({
|
|
48
|
+
directory: absoluteOutdir,
|
|
49
|
+
output,
|
|
50
|
+
cleanDirectory: withDefaultOptions.cleanOutdir,
|
|
51
|
+
fs: fs.promises,
|
|
52
|
+
previousOutputHashes: options.previousCompilation?.outputHashes,
|
|
53
|
+
});
|
|
54
|
+
const warningsAndErrors = await project.errors.get();
|
|
55
|
+
for (const warningOrError of warningsAndErrors) {
|
|
56
|
+
logger.warn(warningOrError);
|
|
57
|
+
}
|
|
58
|
+
return { outputHashes };
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
failed = true;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
try {
|
|
66
|
+
await project.close();
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// Closing must fail an otherwise successful compilation.
|
|
70
|
+
// eslint-disable-next-line no-unsafe-finally
|
|
71
|
+
if (!failed)
|
|
72
|
+
throw error;
|
|
73
|
+
// Keep the actionable compile/write error if cleanup also fails.
|
|
74
|
+
logger.warn("Failed to close project:", error);
|
|
75
|
+
}
|
|
55
76
|
}
|
|
56
|
-
await project.close();
|
|
57
|
-
return { outputHashes };
|
|
58
77
|
}
|
|
59
78
|
catch (e) {
|
|
60
79
|
// release the lock in case of an error
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,EACN,sBAAsB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAErD,uFAAuF;AACvF,kFAAkF;AAClF,IAAI,qBAAqB,GAEb,IAAI,CAAC;AAMjB,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;AAE5B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC5B,OAEC;IAED,MAAM,kBAAkB,GAAG;QAC1B,GAAG,sBAAsB;QACzB,GAAG,OAAO;KACV,CAAC;IAEF,IAAI,qBAAqB,EAAE,CAAC;QAC3B,MAAM,qBAAqB,CAAC;IAC7B,CAAC;IAED,qBAAqB,GAAG,CAAC,KAAK,IAAI,EAAE;QACnC,IAAI,CAAC;YACJ,MAAM,EAAE,GAAG,kBAAkB,CAAC,EAAE,IAAI,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAClC,OAAO,CAAC,GAAG,EAAE,EACb,kBAAkB,CAAC,MAAM,CACzB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;gBAC9C,IAAI,EAAE,kBAAkB,CAAC,OAAO;gBAChC,EAAE;aACF,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,EACN,sBAAsB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAErD,uFAAuF;AACvF,kFAAkF;AAClF,IAAI,qBAAqB,GAEb,IAAI,CAAC;AAMjB,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;AAE5B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC5B,OAEC;IAED,MAAM,kBAAkB,GAAG;QAC1B,GAAG,sBAAsB;QACzB,GAAG,OAAO;KACV,CAAC;IAEF,IAAI,qBAAqB,EAAE,CAAC;QAC3B,MAAM,qBAAqB,CAAC;IAC7B,CAAC;IAED,qBAAqB,GAAG,CAAC,KAAK,IAAI,EAAE;QACnC,IAAI,CAAC;YACJ,MAAM,EAAE,GAAG,kBAAkB,CAAC,EAAE,IAAI,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAClC,OAAO,CAAC,GAAG,EAAE,EACb,kBAAkB,CAAC,MAAM,CACzB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;gBAC9C,IAAI,EAAE,kBAAkB,CAAC,OAAO;gBAChC,EAAE;aACF,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;oBACnC,eAAe,EAAE,kBAAkB;oBACnC,OAAO;oBACP,WAAW,EAAE,kBAAkB,CAAC,OAAO;iBACvC,CAAC,CAAC;gBAEH,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;oBACtC,SAAS,EAAE,cAAc;oBACzB,MAAM;oBACN,cAAc,EAAE,kBAAkB,CAAC,WAAW;oBAC9C,EAAE,EAAE,EAAE,CAAC,QAAQ;oBACf,oBAAoB,EAAE,OAAO,CAAC,mBAAmB,EAAE,YAAY;iBAC/D,CAAC,CAAC;gBAEH,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAErD,KAAK,MAAM,cAAc,IAAI,iBAAiB,EAAE,CAAC;oBAChD,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7B,CAAC;gBAED,OAAO,EAAE,YAAY,EAAE,CAAC;YACzB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM,KAAK,CAAC;YACb,CAAC;oBAAS,CAAC;gBACV,IAAI,CAAC;oBACJ,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACvB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,yDAAyD;oBACzD,6CAA6C;oBAC7C,IAAI,CAAC,MAAM;wBAAE,MAAM,KAAK,CAAC;oBACzB,iEAAiE;oBACjE,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;gBAChD,CAAC;YACF,CAAC;QACF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,uCAAuC;YACvC,qBAAqB,GAAG,IAAI,CAAC;YAC7B,MAAM,CAAC,CAAC;QACT,CAAC;IACF,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,qBAAqB,CAAC,CAAC;IAC5D,qBAAqB,GAAG,IAAI,CAAC;IAE7B,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import { loadProjectFromDirectory } from \"@inlang/sdk\";\nimport path from \"node:path\";\nimport { compileProject } from \"./compile-project.js\";\nimport { writeOutput } from \"../services/file-handling/write-output.js\";\nimport {\n\tdefaultCompilerOptions,\n\ttype CompilerOptions,\n} from \"./compiler-options.js\";\nimport { Logger } from \"../services/logger/index.js\";\n\n// This is a workaround to prevent multiple compilations from running at the same time.\n// https://github.com/opral/inlang-paraglide-js/issues/320#issuecomment-2596951222\nlet compilationInProgress: Promise<{\n\toutputHashes: Record<string, string> | undefined;\n}> | null = null;\n\nexport type CompilationResult = {\n\toutputHashes: Record<string, string> | undefined;\n};\n\nconst logger = new Logger();\n\n/**\n * Loads, compiles, and writes the output to disk.\n *\n * This is the main function to use when you want to compile a project.\n * If you want to adjust inlang project loading, or the output, use\n * `compileProject()` instead.\n *\n * @example\n * await compile({\n * project: 'path/to/project',\n * outdir: 'path/to/output',\n * })\n */\nexport async function compile(\n\toptions: CompilerOptions & {\n\t\tpreviousCompilation?: CompilationResult;\n\t}\n): Promise<CompilationResult> {\n\tconst withDefaultOptions = {\n\t\t...defaultCompilerOptions,\n\t\t...options,\n\t};\n\n\tif (compilationInProgress) {\n\t\tawait compilationInProgress;\n\t}\n\n\tcompilationInProgress = (async () => {\n\t\ttry {\n\t\t\tconst fs = withDefaultOptions.fs ?? (await import(\"node:fs\"));\n\t\t\tconst absoluteOutdir = path.resolve(\n\t\t\t\tprocess.cwd(),\n\t\t\t\twithDefaultOptions.outdir\n\t\t\t);\n\n\t\t\tconst project = await loadProjectFromDirectory({\n\t\t\t\tpath: withDefaultOptions.project,\n\t\t\t\tfs,\n\t\t\t});\n\n\t\t\tlet failed = false;\n\t\t\ttry {\n\t\t\t\tconst output = await compileProject({\n\t\t\t\t\tcompilerOptions: withDefaultOptions,\n\t\t\t\t\tproject,\n\t\t\t\t\tprojectPath: withDefaultOptions.project,\n\t\t\t\t});\n\n\t\t\t\tconst outputHashes = await writeOutput({\n\t\t\t\t\tdirectory: absoluteOutdir,\n\t\t\t\t\toutput,\n\t\t\t\t\tcleanDirectory: withDefaultOptions.cleanOutdir,\n\t\t\t\t\tfs: fs.promises,\n\t\t\t\t\tpreviousOutputHashes: options.previousCompilation?.outputHashes,\n\t\t\t\t});\n\n\t\t\t\tconst warningsAndErrors = await project.errors.get();\n\n\t\t\t\tfor (const warningOrError of warningsAndErrors) {\n\t\t\t\t\tlogger.warn(warningOrError);\n\t\t\t\t}\n\n\t\t\t\treturn { outputHashes };\n\t\t\t} catch (error) {\n\t\t\t\tfailed = true;\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait project.close();\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Closing must fail an otherwise successful compilation.\n\t\t\t\t\t// eslint-disable-next-line no-unsafe-finally\n\t\t\t\t\tif (!failed) throw error;\n\t\t\t\t\t// Keep the actionable compile/write error if cleanup also fails.\n\t\t\t\t\tlogger.warn(\"Failed to close project:\", error);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// release the lock in case of an error\n\t\t\tcompilationInProgress = null;\n\t\t\tthrow e;\n\t\t}\n\t})();\n\n\tconst result = structuredClone(await compilationInProgress);\n\tcompilationInProgress = null;\n\n\treturn result;\n}\n"]}
|
|
@@ -329,4 +329,74 @@ test("emits warnings for modules that couldn't be imported via http", async () =
|
|
|
329
329
|
}
|
|
330
330
|
expect(mock).toHaveBeenCalled();
|
|
331
331
|
});
|
|
332
|
+
test.each([
|
|
333
|
+
["message-modules", false],
|
|
334
|
+
["locale-modules", false],
|
|
335
|
+
["message-modules", true],
|
|
336
|
+
["locale-modules", true],
|
|
337
|
+
])("writes complete %s output (declarations: %s) with limited filesystem capacity", async (outputStructure, emitTsDeclarations) => {
|
|
338
|
+
const { hashDirectory } = await import("../services/file-handling/write-output.js");
|
|
339
|
+
const fs = memfs().fs;
|
|
340
|
+
const diskFs = await import("node:fs/promises");
|
|
341
|
+
await fs.promises.mkdir("/project.inlang", { recursive: true });
|
|
342
|
+
await fs.promises.mkdir("/messages", { recursive: true });
|
|
343
|
+
await fs.promises.writeFile("/plugin.js", await diskFs.readFile(new URL("../../node_modules/@inlang/plugin-message-format/dist/index.js", import.meta.url)));
|
|
344
|
+
await fs.promises.writeFile("/project.inlang/settings.json", JSON.stringify({
|
|
345
|
+
baseLocale: "en",
|
|
346
|
+
locales: ["en", "de"],
|
|
347
|
+
modules: ["/plugin.js"],
|
|
348
|
+
"plugin.inlang.messageFormat": {
|
|
349
|
+
pathPattern: "/messages/{locale}.json",
|
|
350
|
+
},
|
|
351
|
+
}));
|
|
352
|
+
for (const locale of ["en", "de"]) {
|
|
353
|
+
await fs.promises.writeFile(`/messages/${locale}.json`, JSON.stringify(Object.fromEntries(Array.from({ length: 40 }, (_, i) => [
|
|
354
|
+
`message_${i}`,
|
|
355
|
+
`message ${i} in ${locale}`,
|
|
356
|
+
]))));
|
|
357
|
+
}
|
|
358
|
+
const original = fs.promises.writeFile.bind(fs.promises);
|
|
359
|
+
let active = 0;
|
|
360
|
+
let peak = 0;
|
|
361
|
+
const spy = vi.spyOn(fs.promises, "writeFile").mockImplementation((async (...args) => {
|
|
362
|
+
if (!String(args[0]).startsWith("/output/"))
|
|
363
|
+
return original(...args);
|
|
364
|
+
active++;
|
|
365
|
+
peak = Math.max(peak, active);
|
|
366
|
+
try {
|
|
367
|
+
if (active > 32)
|
|
368
|
+
throw Object.assign(new Error("too many open files"), {
|
|
369
|
+
code: "EMFILE",
|
|
370
|
+
});
|
|
371
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
372
|
+
return await original(...args);
|
|
373
|
+
}
|
|
374
|
+
finally {
|
|
375
|
+
active--;
|
|
376
|
+
}
|
|
377
|
+
}));
|
|
378
|
+
try {
|
|
379
|
+
const result = await compile({
|
|
380
|
+
project: "/project.inlang",
|
|
381
|
+
outdir: "/output",
|
|
382
|
+
fs,
|
|
383
|
+
outputStructure,
|
|
384
|
+
emitTsDeclarations,
|
|
385
|
+
additionalFiles: {
|
|
386
|
+
"nested/additional.js": "export const extra = true;",
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
expect(await hashDirectory("/output", fs.promises)).toEqual(result.outputHashes);
|
|
390
|
+
expect(await fs.promises.readFile("/output/nested/additional.js", "utf8")).toContain("extra");
|
|
391
|
+
expect(Object.keys(result.outputHashes)).toContain(outputStructure === "message-modules"
|
|
392
|
+
? "messages/message_39.js"
|
|
393
|
+
: "messages/de.js");
|
|
394
|
+
expect(Object.keys(result.outputHashes).some((p) => p.endsWith(".d.ts"))).toBe(emitTsDeclarations);
|
|
395
|
+
expect(peak).toBeLessThanOrEqual(32);
|
|
396
|
+
expect(active).toBe(0);
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
spy.mockRestore();
|
|
400
|
+
}
|
|
401
|
+
});
|
|
332
402
|
//# sourceMappingURL=compile.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.test.js","sourceRoot":"","sources":["../../src/compiler/compile.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 { test, expect, vi } from \"vitest\";\nimport { compile } from \"./compile.js\";\nimport type { Runtime } from \"./runtime/type.js\";\nimport { defaultCompilerOptions } from \"./compiler-options.js\";\nimport consola from \"consola\";\n\ntest(\"loads a project and compiles it\", 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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst files = await fs.promises.readdir(\"/output\");\n\n\t//runtime.js and messages.js are always compiled with the default options\n\texpect(files).toEqual(\n\t\texpect.arrayContaining([\"runtime.js\", \"server.js\", \"messages.js\"])\n\t);\n});\n\ntest(\"cleans the output directory\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({}),\n\t});\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait fs.promises.mkdir(\"/output/subdir\", { recursive: true });\n\tawait fs.promises.writeFile(\"/output/subdir/x.js\", \"console.log('hello')\");\n\tawait fs.promises.writeFile(\"/output/y.js\", \"console.log('hello')\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst outputSubDir = fs.existsSync(\"/output/subdir\");\n\n\texpect(outputDir).not.toContain(\"y.js\");\n\texpect(outputSubDir).toBe(false);\n});\n\n// Regression coverage for https://github.com/opral/paraglide-js/issues/581\ntest(\"runtime output strips sourcemap references\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\tconst serverFile = await fs.promises.readFile(\"/output/server.js\", \"utf8\");\n\n\texpect(runtimeFile).not.toMatch(/sourceMappingURL=/);\n\texpect(serverFile).not.toMatch(/sourceMappingURL=/);\n});\n\ntest(\"experimental middleware locale splitting uses globalThis.__paraglide.ssr\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs,\n\t\texperimentalMiddlewareLocaleSplitting: true,\n\t});\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\tconst serverFile = await fs.promises.readFile(\"/output/server.js\", \"utf8\");\n\n\texpect(runtimeFile).toContain(\"(globalThis).__paraglide =\");\n\texpect(runtimeFile).toContain(\"(globalThis).__paraglide.ssr =\");\n\texpect(runtimeFile).not.toContain(\"__paraglide_ssr\");\n\texpect(serverFile).toContain(\"globalThis.__paraglide = globalThis.__paraglide ?? {};\");\n\texpect(serverFile).toContain(\"globalThis.__paraglide.ssr = ${escapedSsr}\");\n\texpect(serverFile).toContain(\n\t\tString.raw`replace(/<\\/(script)/gi, \"<\\\\/$1\")`\n\t);\n\texpect(serverFile).not.toContain(\"__paraglide_ssr\");\n});\n\ntest(\"doesn't clean the output directory if option is set to false\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({}),\n\t});\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait fs.promises.mkdir(\"/output/subdir\", { recursive: true });\n\tawait fs.promises.writeFile(\"/output/subdir/x.js\", \"console.log('hello')\");\n\tawait fs.promises.writeFile(\"/output/y.js\", \"console.log('hello')\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tcleanOutdir: false,\n\t\tfs: fs,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst outputSubDir = fs.existsSync(\"/output/subdir\");\n\n\texpect(outputDir).toContain(\"y.js\");\n\texpect(outputSubDir).toBe(true);\n});\n\ntest(\"multiple compile calls do not interfere with each other\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\t// different project settings to test compile output\n\tawait project.settings.set({\n\t\t...(await project.settings.get()),\n\t\tbaseLocale: \"de\",\n\t\tlocales: [\"de\"],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project2.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst compilations = [\n\t\tcompile({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t}),\n\t\tcompile({\n\t\t\tproject: \"/project2.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t}),\n\t];\n\n\tawait Promise.all(compilations);\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\n\tconst runtime = (await import(\n\t\t\"data:text/javascript;base64,\" +\n\t\t\tBuffer.from(\n\t\t\t\t// replace the\n\t\t\t\truntimeFile.replace(\n\t\t\t\t\t`import \"@inlang/paraglide-js/urlpattern-polyfill\";`,\n\t\t\t\t\t\"\"\n\t\t\t\t),\n\t\t\t\t\"utf-8\"\n\t\t\t).toString(\"base64\")\n\t)) as Runtime;\n\n\t// expecting the second compile step to overwrite the first\n\texpect(runtime.baseLocale).toBe(\"de\");\n\texpect(runtime.locales).toEqual([\"de\"]);\n});\n\ntest(\"emits additional files\", async () => {\n\tconst additionalFiles = {\n\t\t\"adapter/component.svelte\": \"<script>console.log('hello')</script>\",\n\t\t\"adapter.js\": \"console.log('hello')\",\n\t};\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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t\tadditionalFiles,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst adapterDir = await fs.promises.readdir(\"/output/adapter\");\n\n\texpect(outputDir).toEqual(\n\t\texpect.arrayContaining([\n\t\t\t\"runtime.js\",\n\t\t\t\"server.js\",\n\t\t\t\"messages.js\",\n\t\t\t\"adapter.js\",\n\t\t])\n\t);\n\n\texpect(adapterDir).toEqual([\"component.svelte\"]);\n});\n\ntest(\"includes eslint-disable comment\", 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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tincludeEslintDisableComment: true,\n\t\tfs: fs,\n\t});\n\n\tconst messages = await fs.promises.readFile(\"/output/messages.js\", \"utf8\");\n\n\texpect(messages).toContain(\"/* eslint-disable */\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tincludeEslintDisableComment: false,\n\t\tfs: fs,\n\t});\n\n\tconst messagesWithoutComment = await fs.promises.readFile(\n\t\t\"/output/messages.js\",\n\t\t\"utf8\"\n\t);\n\n\texpect(messagesWithoutComment).not.toContain(\"/* eslint-disable */\");\n});\n\ntest(\"default compiler options should include cookied, variable and baseLocale to ensure easy try out of paraglide js, working both in server and browser environemnts\", () => {\n\t// someone trying out paraglide js should be able to call `getLocale()` and `setLocale()`\n\t// without getting an error slammed in their face saying \"define your strategy\".\n\t//\n\t// instead, make the apis work out of the box and once the developer is convinced that\n\t// paraglide js is the right tool for them, they can then define their own strategy.\n\n\texpect(defaultCompilerOptions.strategy).toEqual([\n\t\t\"cookie\",\n\t\t\"globalVariable\",\n\t\t\"baseLocale\",\n\t]);\n});\n\ntest(\"emits warnings for modules that couldn't be imported locally\", 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\tmodules: [\"./non-existent-paraglide-plugin.js\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst mock = vi.fn();\n\n\tconsola.mockTypes(() => mock);\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\texpect(mock).toHaveBeenCalled();\n});\n\ntest(\"emits warnings for modules that couldn't be imported via http\", 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\tmodules: [\"https://example.com/non-existent-paraglide-plugin.js\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst mock = vi.fn();\n\n\tconsola.mockTypes(() => mock);\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tconst fetchMock = vi.fn().mockRejectedValue(new TypeError(\"network error\"));\n\tvi.stubGlobal(\"fetch\", fetchMock);\n\n\tconst errorsSpy = vi.spyOn(project.errors, \"get\").mockResolvedValue([\n\t\t{\n\t\t\tmessage:\n\t\t\t\t\"Failed to import module https://example.com/non-existent-paraglide-plugin.js\",\n\t\t} as any,\n\t]);\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\ttry {\n\t\tawait compile({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t});\n\t} finally {\n\t\tvi.unstubAllGlobals();\n\t\terrorsSpy.mockRestore();\n\t}\n\n\texpect(mock).toHaveBeenCalled();\n});\n"]}
|
|
1
|
+
{"version":3,"file":"compile.test.js","sourceRoot":"","sources":["../../src/compiler/compile.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 { test, expect, vi } from \"vitest\";\nimport { compile } from \"./compile.js\";\nimport type { Runtime } from \"./runtime/type.js\";\nimport { defaultCompilerOptions } from \"./compiler-options.js\";\nimport consola from \"consola\";\n\ntest(\"loads a project and compiles it\", 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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst files = await fs.promises.readdir(\"/output\");\n\n\t//runtime.js and messages.js are always compiled with the default options\n\texpect(files).toEqual(\n\t\texpect.arrayContaining([\"runtime.js\", \"server.js\", \"messages.js\"])\n\t);\n});\n\ntest(\"cleans the output directory\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({}),\n\t});\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait fs.promises.mkdir(\"/output/subdir\", { recursive: true });\n\tawait fs.promises.writeFile(\"/output/subdir/x.js\", \"console.log('hello')\");\n\tawait fs.promises.writeFile(\"/output/y.js\", \"console.log('hello')\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst outputSubDir = fs.existsSync(\"/output/subdir\");\n\n\texpect(outputDir).not.toContain(\"y.js\");\n\texpect(outputSubDir).toBe(false);\n});\n\n// Regression coverage for https://github.com/opral/paraglide-js/issues/581\ntest(\"runtime output strips sourcemap references\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\tconst serverFile = await fs.promises.readFile(\"/output/server.js\", \"utf8\");\n\n\texpect(runtimeFile).not.toMatch(/sourceMappingURL=/);\n\texpect(serverFile).not.toMatch(/sourceMappingURL=/);\n});\n\ntest(\"experimental middleware locale splitting uses globalThis.__paraglide.ssr\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs,\n\t\texperimentalMiddlewareLocaleSplitting: true,\n\t});\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\tconst serverFile = await fs.promises.readFile(\"/output/server.js\", \"utf8\");\n\n\texpect(runtimeFile).toContain(\"(globalThis).__paraglide =\");\n\texpect(runtimeFile).toContain(\"(globalThis).__paraglide.ssr =\");\n\texpect(runtimeFile).not.toContain(\"__paraglide_ssr\");\n\texpect(serverFile).toContain(\n\t\t\"globalThis.__paraglide = globalThis.__paraglide ?? {};\"\n\t);\n\texpect(serverFile).toContain(\"globalThis.__paraglide.ssr = ${escapedSsr}\");\n\texpect(serverFile).toContain(String.raw`replace(/<\\/(script)/gi, \"<\\\\/$1\")`);\n\texpect(serverFile).not.toContain(\"__paraglide_ssr\");\n});\n\ntest(\"doesn't clean the output directory if option is set to false\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({}),\n\t});\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait fs.promises.mkdir(\"/output/subdir\", { recursive: true });\n\tawait fs.promises.writeFile(\"/output/subdir/x.js\", \"console.log('hello')\");\n\tawait fs.promises.writeFile(\"/output/y.js\", \"console.log('hello')\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tcleanOutdir: false,\n\t\tfs: fs,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst outputSubDir = fs.existsSync(\"/output/subdir\");\n\n\texpect(outputDir).toContain(\"y.js\");\n\texpect(outputSubDir).toBe(true);\n});\n\ntest(\"multiple compile calls do not interfere with each other\", async () => {\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\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\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\t// different project settings to test compile output\n\tawait project.settings.set({\n\t\t...(await project.settings.get()),\n\t\tbaseLocale: \"de\",\n\t\tlocales: [\"de\"],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project2.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tconst compilations = [\n\t\tcompile({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t}),\n\t\tcompile({\n\t\t\tproject: \"/project2.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t}),\n\t];\n\n\tawait Promise.all(compilations);\n\n\tconst runtimeFile = await fs.promises.readFile(\"/output/runtime.js\", \"utf8\");\n\n\tconst runtime = (await import(\n\t\t\"data:text/javascript;base64,\" +\n\t\t\tBuffer.from(\n\t\t\t\t// replace the\n\t\t\t\truntimeFile.replace(\n\t\t\t\t\t`import \"@inlang/paraglide-js/urlpattern-polyfill\";`,\n\t\t\t\t\t\"\"\n\t\t\t\t),\n\t\t\t\t\"utf-8\"\n\t\t\t).toString(\"base64\")\n\t)) as Runtime;\n\n\t// expecting the second compile step to overwrite the first\n\texpect(runtime.baseLocale).toBe(\"de\");\n\texpect(runtime.locales).toEqual([\"de\"]);\n});\n\ntest(\"emits additional files\", async () => {\n\tconst additionalFiles = {\n\t\t\"adapter/component.svelte\": \"<script>console.log('hello')</script>\",\n\t\t\"adapter.js\": \"console.log('hello')\",\n\t};\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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t\tadditionalFiles,\n\t});\n\n\tconst outputDir = await fs.promises.readdir(\"/output\");\n\tconst adapterDir = await fs.promises.readdir(\"/output/adapter\");\n\n\texpect(outputDir).toEqual(\n\t\texpect.arrayContaining([\n\t\t\t\"runtime.js\",\n\t\t\t\"server.js\",\n\t\t\t\"messages.js\",\n\t\t\t\"adapter.js\",\n\t\t])\n\t);\n\n\texpect(adapterDir).toEqual([\"component.svelte\"]);\n});\n\ntest(\"includes eslint-disable comment\", 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\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tincludeEslintDisableComment: true,\n\t\tfs: fs,\n\t});\n\n\tconst messages = await fs.promises.readFile(\"/output/messages.js\", \"utf8\");\n\n\texpect(messages).toContain(\"/* eslint-disable */\");\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tincludeEslintDisableComment: false,\n\t\tfs: fs,\n\t});\n\n\tconst messagesWithoutComment = await fs.promises.readFile(\n\t\t\"/output/messages.js\",\n\t\t\"utf8\"\n\t);\n\n\texpect(messagesWithoutComment).not.toContain(\"/* eslint-disable */\");\n});\n\ntest(\"default compiler options should include cookied, variable and baseLocale to ensure easy try out of paraglide js, working both in server and browser environemnts\", () => {\n\t// someone trying out paraglide js should be able to call `getLocale()` and `setLocale()`\n\t// without getting an error slammed in their face saying \"define your strategy\".\n\t//\n\t// instead, make the apis work out of the box and once the developer is convinced that\n\t// paraglide js is the right tool for them, they can then define their own strategy.\n\n\texpect(defaultCompilerOptions.strategy).toEqual([\n\t\t\"cookie\",\n\t\t\"globalVariable\",\n\t\t\"baseLocale\",\n\t]);\n});\n\ntest(\"emits warnings for modules that couldn't be imported locally\", 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\tmodules: [\"./non-existent-paraglide-plugin.js\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst mock = vi.fn();\n\n\tconsola.mockTypes(() => mock);\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\tawait compile({\n\t\tproject: \"/project.inlang\",\n\t\toutdir: \"/output\",\n\t\tfs: fs,\n\t});\n\n\texpect(mock).toHaveBeenCalled();\n});\n\ntest(\"emits warnings for modules that couldn't be imported via http\", 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\tmodules: [\"https://example.com/non-existent-paraglide-plugin.js\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tconst mock = vi.fn();\n\n\tconsola.mockTypes(() => mock);\n\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tconst fetchMock = vi.fn().mockRejectedValue(new TypeError(\"network error\"));\n\tvi.stubGlobal(\"fetch\", fetchMock);\n\n\tconst errorsSpy = vi.spyOn(project.errors, \"get\").mockResolvedValue([\n\t\t{\n\t\t\tmessage:\n\t\t\t\t\"Failed to import module https://example.com/non-existent-paraglide-plugin.js\",\n\t\t} as any,\n\t]);\n\n\t// save project to directory to test loading\n\tawait saveProjectToDirectory({\n\t\tproject,\n\t\tpath: \"/project.inlang\",\n\t\tfs: fs.promises,\n\t});\n\n\ttry {\n\t\tawait compile({\n\t\t\tproject: \"/project.inlang\",\n\t\t\toutdir: \"/output\",\n\t\t\tfs: fs,\n\t\t});\n\t} finally {\n\t\tvi.unstubAllGlobals();\n\t\terrorsSpy.mockRestore();\n\t}\n\n\texpect(mock).toHaveBeenCalled();\n});\n\ntest.each([\n\t[\"message-modules\", false],\n\t[\"locale-modules\", false],\n\t[\"message-modules\", true],\n\t[\"locale-modules\", true],\n] as const)(\n\t\"writes complete %s output (declarations: %s) with limited filesystem capacity\",\n\tasync (outputStructure, emitTsDeclarations) => {\n\t\tconst { hashDirectory } =\n\t\t\tawait import(\"../services/file-handling/write-output.js\");\n\t\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\t\tconst diskFs = await import(\"node:fs/promises\");\n\t\tawait fs.promises.mkdir(\"/project.inlang\", { recursive: true });\n\t\tawait fs.promises.mkdir(\"/messages\", { recursive: true });\n\t\tawait fs.promises.writeFile(\n\t\t\t\"/plugin.js\",\n\t\t\tawait diskFs.readFile(\n\t\t\t\tnew URL(\n\t\t\t\t\t\"../../node_modules/@inlang/plugin-message-format/dist/index.js\",\n\t\t\t\t\timport.meta.url\n\t\t\t\t)\n\t\t\t)\n\t\t);\n\t\tawait fs.promises.writeFile(\n\t\t\t\"/project.inlang/settings.json\",\n\t\t\tJSON.stringify({\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\tmodules: [\"/plugin.js\"],\n\t\t\t\t\"plugin.inlang.messageFormat\": {\n\t\t\t\t\tpathPattern: \"/messages/{locale}.json\",\n\t\t\t\t},\n\t\t\t})\n\t\t);\n\t\tfor (const locale of [\"en\", \"de\"]) {\n\t\t\tawait fs.promises.writeFile(\n\t\t\t\t`/messages/${locale}.json`,\n\t\t\t\tJSON.stringify(\n\t\t\t\t\tObject.fromEntries(\n\t\t\t\t\t\tArray.from({ length: 40 }, (_, i) => [\n\t\t\t\t\t\t\t`message_${i}`,\n\t\t\t\t\t\t\t`message ${i} in ${locale}`,\n\t\t\t\t\t\t])\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\tconst original = fs.promises.writeFile.bind(fs.promises);\n\t\tlet active = 0;\n\t\tlet peak = 0;\n\t\tconst spy = vi.spyOn(fs.promises, \"writeFile\").mockImplementation((async (\n\t\t\t...args\n\t\t) => {\n\t\t\tif (!String(args[0]).startsWith(\"/output/\")) return original(...args);\n\t\t\tactive++;\n\t\t\tpeak = Math.max(peak, active);\n\t\t\ttry {\n\t\t\t\tif (active > 32)\n\t\t\t\t\tthrow Object.assign(new Error(\"too many open files\"), {\n\t\t\t\t\t\tcode: \"EMFILE\",\n\t\t\t\t\t});\n\t\t\t\tawait new Promise<void>((resolve) => setImmediate(resolve));\n\t\t\t\treturn await original(...args);\n\t\t\t} finally {\n\t\t\t\tactive--;\n\t\t\t}\n\t\t}) as typeof fs.promises.writeFile);\n\t\ttry {\n\t\t\tconst result = await compile({\n\t\t\t\tproject: \"/project.inlang\",\n\t\t\t\toutdir: \"/output\",\n\t\t\t\tfs,\n\t\t\t\toutputStructure,\n\t\t\t\temitTsDeclarations,\n\t\t\t\tadditionalFiles: {\n\t\t\t\t\t\"nested/additional.js\": \"export const extra = true;\",\n\t\t\t\t},\n\t\t\t});\n\t\t\texpect(await hashDirectory(\"/output\", fs.promises)).toEqual(\n\t\t\t\tresult.outputHashes\n\t\t\t);\n\t\t\texpect(\n\t\t\t\tawait fs.promises.readFile(\"/output/nested/additional.js\", \"utf8\")\n\t\t\t).toContain(\"extra\");\n\t\t\texpect(Object.keys(result.outputHashes!)).toContain(\n\t\t\t\toutputStructure === \"message-modules\"\n\t\t\t\t\t? \"messages/message_39.js\"\n\t\t\t\t\t: \"messages/de.js\"\n\t\t\t);\n\t\t\texpect(\n\t\t\t\tObject.keys(result.outputHashes!).some((p) => p.endsWith(\".d.ts\"))\n\t\t\t).toBe(emitTsDeclarations);\n\t\t\texpect(peak).toBeLessThanOrEqual(32);\n\t\t\texpect(active).toBe(0);\n\t\t} finally {\n\t\t\tspy.mockRestore();\n\t\t}\n\t}\n);\n"]}
|
|
@@ -205,6 +205,47 @@ export type CompilerOptions = {
|
|
|
205
205
|
* @default "" (no domain attribute, exact domain only)
|
|
206
206
|
*/
|
|
207
207
|
cookieDomain?: string;
|
|
208
|
+
/**
|
|
209
|
+
* The `SameSite` attribute of the cookie.
|
|
210
|
+
*
|
|
211
|
+
* If undefined, the attribute is omitted and the browser applies its own default.
|
|
212
|
+
* Set it when the cookie must match a policy, for example the one a server uses
|
|
213
|
+
* when it writes the same cookie with `Set-Cookie`.
|
|
214
|
+
*
|
|
215
|
+
* `"none"` requires `cookieSecure` to be `true` or `"auto"` because browsers
|
|
216
|
+
* reject `SameSite=None` cookies without the `Secure` attribute. With `"auto"`,
|
|
217
|
+
* the cookie is still dropped on plain `http://` pages.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* cookieSameSite: "lax" // Cookie: "PARAGLIDE_LOCALE=en; path=/; max-age=34560000; samesite=lax"
|
|
222
|
+
* ```
|
|
223
|
+
*
|
|
224
|
+
* @default undefined (no samesite attribute)
|
|
225
|
+
*/
|
|
226
|
+
cookieSameSite?: "lax" | "strict" | "none";
|
|
227
|
+
/**
|
|
228
|
+
* Whether the cookie gets the `Secure` attribute.
|
|
229
|
+
*
|
|
230
|
+
* - `true` always adds it. Pages served over plain `http://` cannot set a
|
|
231
|
+
* `Secure` cookie, except on `localhost`.
|
|
232
|
+
* - `"auto"` adds it only when the page is served over `https:`, so the cookie
|
|
233
|
+
* keeps working on plain `http://` hosts other than localhost, like a LAN IP
|
|
234
|
+
* or an internal staging server. With `cookieSameSite: "none"`, the cookie
|
|
235
|
+
* still needs `https:`.
|
|
236
|
+
* - `false` never adds it.
|
|
237
|
+
*
|
|
238
|
+
* Server code that reads `cookieSecure` from the runtime has to resolve `"auto"`
|
|
239
|
+
* itself, for example from the request protocol or `X-Forwarded-Proto`.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* cookieSecure: "auto" // on https: "PARAGLIDE_LOCALE=en; path=/; max-age=34560000; secure"
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @default false
|
|
247
|
+
*/
|
|
248
|
+
cookieSecure?: boolean | "auto";
|
|
208
249
|
/**
|
|
209
250
|
* The `additionalFiles` option is an array of paths to additional files that should be copied to the output directory.
|
|
210
251
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler-options.js","sourceRoot":"","sources":["../../src/compiler/compiler-options.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACrC,eAAe,EAAE,iBAAiB;IAClC,aAAa,EAAE,IAAI;IACnB,2BAA2B,EAAE,IAAI;IACjC,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI;IAChB,kBAAkB,EAAE,KAAK;IACzB,WAAW,EAAE,IAAI;IACjB,wBAAwB,EAAE,KAAK;IAC/B,qCAAqC,EAAE,KAAK;IAC5C,eAAe,EAAE,kBAAkB;IACnC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,YAAY,CAAC;IACpD,UAAU,EAAE,kBAAkB;IAC9B,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG;IAChC,YAAY,EAAE,EAAE;CAC4B,CAAC","sourcesContent":["import type { Runtime } from \"./runtime/type.js\";\n\nexport type RouteStrategy =\n\t| {\n\t\t\t/**\n\t\t\t * URLPattern-compatible matcher.\n\t\t\t */\n\t\t\tmatch: string;\n\t\t\t/**\n\t\t\t * Strategy override for matching requests.\n\t\t\t */\n\t\t\tstrategy: Runtime[\"strategy\"];\n\t\t\t/**\n\t\t\t * Prevent mutually exclusive configuration (`exclude` + `strategy`).\n\t\t\t */\n\t\t\texclude?: never;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * URLPattern-compatible matcher.\n\t\t\t */\n\t\t\tmatch: string;\n\t\t\t/**\n\t\t\t * Exclude matching requests from i18n middleware behavior.\n\t\t\t */\n\t\t\texclude: true;\n\t\t\t/**\n\t\t\t * Prevent mutually exclusive configuration (`exclude` + `strategy`).\n\t\t\t */\n\t\t\tstrategy?: never;\n\t };\n\nexport const defaultCompilerOptions = {\n\toutputStructure: \"message-modules\",\n\temitGitIgnore: true,\n\tincludeEslintDisableComment: true,\n\temitPrettierIgnore: true,\n\temitReadme: true,\n\temitTsDeclarations: false,\n\tcleanOutdir: true,\n\tdisableAsyncLocalStorage: false,\n\texperimentalMiddlewareLocaleSplitting: false,\n\tlocalStorageKey: \"PARAGLIDE_LOCALE\",\n\tisServer: \"typeof window === 'undefined'\",\n\tstrategy: [\"cookie\", \"globalVariable\", \"baseLocale\"],\n\tcookieName: \"PARAGLIDE_LOCALE\",\n\tcookieMaxAge: 60 * 60 * 24 * 400,\n\tcookieDomain: \"\",\n} as const satisfies Partial<CompilerOptions>;\n\nexport type CompilerOptions = {\n\t/**\n\t * The path to the inlang project.\n\t *\n\t * @example\n\t * ```diff\n\t * await compile({\n\t * + project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\"\n\t * })\n\t * ```\n\t */\n\tproject: string;\n\t/**\n\t * The path to the output directory.\n\t *\n\t * @example\n\t * ```diff\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * + outdir: \"./src/paraglide\"\n\t * })\n\t * ```\n\t */\n\toutdir: string;\n\t/**\n\t * The strategy to use for getting the locale.\n\t *\n\t * The order of the strategy defines the precedence of matches.\n\t *\n\t * For example, in `['url', 'cookie', 'baseLocale']`, the locale will be\n\t * first tried to be detected in the url, then in a cookie, and finally\n\t * fallback to the base locale.\n\t *\n\t * The default ensures that the browser takes a cookie approach,\n\t * server-side takes the globalVariable (because cookie is unavailable),\n\t * whereas both fallback to the base locale if not available.\n\t *\n\t * Custom strategies with the pattern `custom-[A-Za-z0-9_-]+` are supported.\n\t *\n\t * @default [\"cookie\", \"globalVariable\", \"baseLocale\"]\n\t */\n\tstrategy?: Runtime[\"strategy\"];\n\t/**\n\t * Route-level strategy overrides.\n\t *\n\t * Routes are matched in declaration order. The first matching rule wins.\n\t * `match` uses URLPattern syntax.\n\t *\n\t * - `strategy`: Override locale resolution for the matched route.\n\t * - `exclude: true`: Skip i18n middleware behavior for the matched route.\n\t *\n\t * @example\n\t * ```ts\n\t * routeStrategies: [\n\t * { match: \"/dashboard/:path(.*)?\", strategy: [\"cookie\", \"baseLocale\"] },\n\t * { match: \"/api/:path(.*)?\", exclude: true }\n\t * ]\n\t * ```\n\t */\n\trouteStrategies?: RouteStrategy[];\n\t/**\n\t * Whether or not to use experimental middleware locale splitting.\n\t *\n\t * ⚠️ This feature is experimental and only works in SSR/SSG environment\n\t * without client-side routing. Do not rely on this feature for production.\n\t *\n\t * This feature is part of the exploration of per locale splitting. The\n\t * issue is ongoing and can be followed here [#88](https://github.com/opral/inlang-paraglide-js/issues/88).\n\t *\n\t * - The client bundle will tree-shake all messages (have close to 0kb JS).\n\t * - The server middleware will inject the used messages into the HTML.\n\t * - The client will re-trieve the messages from the injected HTML.\n\t *\n\t * @default false\n\t */\n\texperimentalMiddlewareLocaleSplitting?: boolean;\n\t/**\n\t * The name of the localStorage key to use for the localStorage strategy.\n\t *\n\t * @default 'PARAGLIDE_LOCALE'\n\t */\n\tlocalStorageKey?: string;\n\t/**\n\t * Tree-shaking flag if the code is running on the server.\n\t *\n\t * Dependent on the bundler, this flag must be adapted to\n\t * enable tree-shaking.\n\t *\n\t * @example\n\t * // vite\n\t * isServer: \"import.meta.env.SSR\"\n\t *\n\t * @default typeof window === \"undefined\"\n\t */\n\tisServer?: string;\n\t/**\n\t * Compile-time locale constant used for per-locale tree-shaking.\n\t *\n\t * This is experimental and opt-in. It should be a JavaScript expression\n\t * (not a quoted literal) that resolves to a locale or `undefined` at build time.\n\t * You can pass a string literal (e.g. `\"de\"`) for programmatic builds, or an\n\t * injected env/define expression for bundler-driven builds.\n\t *\n\t * High-level flow for per-locale builds:\n\t *\n\t * client request (/)\n\t * |\n\t * v\n\t * +----------------------+\n\t * | detect locale |\n\t * | (cookie/Accept-L) |\n\t * | pick build prefix |\n\t * +----------------------+\n\t * | if \"de\"\n\t * v\n\t * serve dist/de/... <----> serve dist/en/...\n\t * (HTML + assets) (HTML + assets)\n\t *\n\t * @see https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638\n\t *\n\t * @example\n\t * // Vite define\n\t * experimentalStaticLocale: \"typeof __PARAGLIDE_STATIC_LOCALE__ === 'undefined' ? undefined : __PARAGLIDE_STATIC_LOCALE__\"\n\t *\n\t * @example\n\t * // Programmatic compile (literal)\n\t * experimentalStaticLocale: '\"de\"'\n\t */\n\texperimentalStaticLocale?: string;\n\t/**\n\t * The name of the cookie to use for the cookie strategy.\n\t *\n\t * @default 'PARAGLIDE_LOCALE'\n\t */\n\tcookieName?: string;\n\t/**\n\t * The max-age in seconds of the cookie until it expires.\n\t *\n\t * @default 60 * 60 * 24 * 400\n\t */\n\tcookieMaxAge?: number;\n\t/**\n\t * The host to which the cookie will be sent.\n\t * If undefined or empty, the domain attribute is omitted from the cookie, scoping it to the exact current domain only (no subdomains).\n\t * If specified, the cookie will be available to the specified domain and all its subdomains.\n\t *\n\t * Use this when you need cookies to be shared across subdomains (e.g., between `app.example.com` and `api.example.com`).\n\t * The default behavior (no domain) ensures better compatibility with server-side cookies that don't specify a domain attribute.\n\t *\n\t * @example\n\t * ```ts\n\t * // Default: exact domain only (compatible with server-side cookies)\n\t * cookieDomain: undefined // Cookie: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000\"\n\t *\n\t * // Subdomain sharing: available across all subdomains\n\t * cookieDomain: \"example.com\" // Cookie: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; domain=example.com\"\n\t * ```\n\t *\n\t * @default \"\" (no domain attribute, exact domain only)\n\t */\n\tcookieDomain?: string;\n\t/**\n\t * The `additionalFiles` option is an array of paths to additional files that should be copied to the output directory.\n\t *\n\t * @example\n\t *\n\t * ```diff\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\",\n\t * additionalFiles: [\n\t * + \"my-file.js\": \"console.log('hello')\"\n\t * ]\n\t * })\n\t * ```\n\t *\n\t * The output will look like this:\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - my-file.js\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t */\n\tadditionalFiles?: Record<string, string>;\n\t/**\n\t * If `emitPrettierIgnore` is set to `true` a `.prettierignore` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - .prettierignore\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitPrettierIgnore?: boolean;\n\t/**\n\t * If `emitReadme` is set to `true` a `README.md` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * The README helps LLMs understand the compiled output.\n\t * See https://llmstxt.org/ for format guidelines.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - README.md\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitReadme?: boolean;\n\t/**\n\t * Emit `.d.ts` files for the generated output using the TypeScript compiler.\n\t *\n\t * Useful when `allowJs: true` cannot be set in your `tsconfig.json`\n\t * (e.g., due to project constraints or conflicting compiler options), or when\n\t * an editor language server caches stale JSDoc types for generated messages.\n\t *\n\t * Requires `typescript` to be resolvable in your toolchain.\n\t *\n\t * **Note:** Enabling this option reduces compiler speed because TypeScript\n\t * needs to generate declaration files for all output modules.\n\t *\n\t * **Note:** With TypeScript 5/6 the declarations are generated in-process.\n\t * TypeScript 7+ no longer provides the compiler API, so its `tsc` CLI is\n\t * invoked in a child process instead; the emitted declarations are\n\t * semantically equivalent but differ cosmetically between the two.\n\t *\n\t * @example\n\t * ```ts\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\",\n\t * emitTsDeclarations: true,\n\t * });\n\t * ```\n\t *\n\t * @default false\n\t */\n\temitTsDeclarations?: boolean;\n\t/**\n\t * https://paraglidejs.com/strategy#url\n\t */\n\turlPatterns?: Runtime[\"urlPatterns\"];\n\t/**\n\t * Controls trailing slash canonicalization for localized URLs.\n\t *\n\t * Canonicalization happens before URL pattern matching and after URL\n\t * localization. If omitted, Paraglide keeps its existing trailing slash\n\t * behavior.\n\t */\n\ttrailingSlash?: \"always\" | \"never\";\n\t/**\n\t * Whether to include an eslint-disable comment at the top of each .js file.\n\t *\n\t * @default true\n\t */\n\tincludeEslintDisableComment?: boolean;\n\t/**\n\t * Replaces AsyncLocalStorage with a synchronous implementation.\n\t *\n\t * Leave AsyncLocalStorage enabled by default. This option is a\n\t * compatibility fallback for runtimes that do not provide\n\t * AsyncLocalStorage or `node:async_hooks`.\n\t *\n\t * ⚠️ WARNING: Only use this option when your runtime also guarantees\n\t * request isolation. Disabling AsyncLocalStorage in multi-request\n\t * server environments risks cross-request pollution where state from\n\t * one request could leak into another concurrent request.\n\t */\n\tdisableAsyncLocalStorage?: boolean;\n\t/**\n\t * If `emitGitIgnore` is set to `true` a `.gitignore` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - .gitignore\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitGitIgnore?: boolean;\n\t/**\n\t * The `outputStructure` defines how modules are structured in the output.\n\t *\n\t * - `message-modules` - Each module is a message. This is the default.\n\t * - `locale-modules` - Each module is a locale.\n\t *\n\t * It is recommended to use `locale-modules` for development and `message-modules` for production.\n\t * Bundlers speed up the dev mode by bypassing bundling which can lead to many http requests\n\t * during the dev mode with `message-modules`. See https://github.com/opral/inlang-paraglide-js/issues/486.\n\t *\n\t * **`message-modules`**\n\t *\n\t * Messages have their own module which eases tree-shaking for bundlers.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - blue_elephant_tree/\n\t * + - index.js\n\t * + - en.js\n\t * + - fr.js\n\t * + - sky_phone_bottle/\n\t * + - index.js\n\t * + - en.js\n\t * + - fr.js\n\t * - ...\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * **`locale-modules`**\n\t *\n\t * Messages are bundled in a per locale module. Bundlers often struggle with tree-shaking this structure,\n\t * which can lead to more inefficient tree-shaking and larger bundle sizes compared to `message-modules`.\n\t *\n\t * The benefit are substantially fewer files which is needed in large projects.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - de.js\n\t * + - en.js\n\t * + - fr.js\n\t * - ...\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default \"message-modules\"\n\t */\n\toutputStructure?: \"locale-modules\" | \"message-modules\";\n\t/**\n\t * Whether to clean the output directory before writing the new files.\n\t *\n\t * @default true\n\t */\n\tcleanOutdir?: boolean;\n\n\t/**\n\t * The file system to use. Defaults to `await import('node:fs')`.\n\t *\n\t * Useful for testing the paraglide compiler by mocking the fs.\n\t */\n\tfs?: any;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"compiler-options.js","sourceRoot":"","sources":["../../src/compiler/compiler-options.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACrC,eAAe,EAAE,iBAAiB;IAClC,aAAa,EAAE,IAAI;IACnB,2BAA2B,EAAE,IAAI;IACjC,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI;IAChB,kBAAkB,EAAE,KAAK;IACzB,WAAW,EAAE,IAAI;IACjB,wBAAwB,EAAE,KAAK;IAC/B,qCAAqC,EAAE,KAAK;IAC5C,eAAe,EAAE,kBAAkB;IACnC,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,YAAY,CAAC;IACpD,UAAU,EAAE,kBAAkB;IAC9B,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG;IAChC,YAAY,EAAE,EAAE;CAC4B,CAAC","sourcesContent":["import type { Runtime } from \"./runtime/type.js\";\n\nexport type RouteStrategy =\n\t| {\n\t\t\t/**\n\t\t\t * URLPattern-compatible matcher.\n\t\t\t */\n\t\t\tmatch: string;\n\t\t\t/**\n\t\t\t * Strategy override for matching requests.\n\t\t\t */\n\t\t\tstrategy: Runtime[\"strategy\"];\n\t\t\t/**\n\t\t\t * Prevent mutually exclusive configuration (`exclude` + `strategy`).\n\t\t\t */\n\t\t\texclude?: never;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * URLPattern-compatible matcher.\n\t\t\t */\n\t\t\tmatch: string;\n\t\t\t/**\n\t\t\t * Exclude matching requests from i18n middleware behavior.\n\t\t\t */\n\t\t\texclude: true;\n\t\t\t/**\n\t\t\t * Prevent mutually exclusive configuration (`exclude` + `strategy`).\n\t\t\t */\n\t\t\tstrategy?: never;\n\t };\n\nexport const defaultCompilerOptions = {\n\toutputStructure: \"message-modules\",\n\temitGitIgnore: true,\n\tincludeEslintDisableComment: true,\n\temitPrettierIgnore: true,\n\temitReadme: true,\n\temitTsDeclarations: false,\n\tcleanOutdir: true,\n\tdisableAsyncLocalStorage: false,\n\texperimentalMiddlewareLocaleSplitting: false,\n\tlocalStorageKey: \"PARAGLIDE_LOCALE\",\n\tisServer: \"typeof window === 'undefined'\",\n\tstrategy: [\"cookie\", \"globalVariable\", \"baseLocale\"],\n\tcookieName: \"PARAGLIDE_LOCALE\",\n\tcookieMaxAge: 60 * 60 * 24 * 400,\n\tcookieDomain: \"\",\n} as const satisfies Partial<CompilerOptions>;\n\nexport type CompilerOptions = {\n\t/**\n\t * The path to the inlang project.\n\t *\n\t * @example\n\t * ```diff\n\t * await compile({\n\t * + project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\"\n\t * })\n\t * ```\n\t */\n\tproject: string;\n\t/**\n\t * The path to the output directory.\n\t *\n\t * @example\n\t * ```diff\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * + outdir: \"./src/paraglide\"\n\t * })\n\t * ```\n\t */\n\toutdir: string;\n\t/**\n\t * The strategy to use for getting the locale.\n\t *\n\t * The order of the strategy defines the precedence of matches.\n\t *\n\t * For example, in `['url', 'cookie', 'baseLocale']`, the locale will be\n\t * first tried to be detected in the url, then in a cookie, and finally\n\t * fallback to the base locale.\n\t *\n\t * The default ensures that the browser takes a cookie approach,\n\t * server-side takes the globalVariable (because cookie is unavailable),\n\t * whereas both fallback to the base locale if not available.\n\t *\n\t * Custom strategies with the pattern `custom-[A-Za-z0-9_-]+` are supported.\n\t *\n\t * @default [\"cookie\", \"globalVariable\", \"baseLocale\"]\n\t */\n\tstrategy?: Runtime[\"strategy\"];\n\t/**\n\t * Route-level strategy overrides.\n\t *\n\t * Routes are matched in declaration order. The first matching rule wins.\n\t * `match` uses URLPattern syntax.\n\t *\n\t * - `strategy`: Override locale resolution for the matched route.\n\t * - `exclude: true`: Skip i18n middleware behavior for the matched route.\n\t *\n\t * @example\n\t * ```ts\n\t * routeStrategies: [\n\t * { match: \"/dashboard/:path(.*)?\", strategy: [\"cookie\", \"baseLocale\"] },\n\t * { match: \"/api/:path(.*)?\", exclude: true }\n\t * ]\n\t * ```\n\t */\n\trouteStrategies?: RouteStrategy[];\n\t/**\n\t * Whether or not to use experimental middleware locale splitting.\n\t *\n\t * ⚠️ This feature is experimental and only works in SSR/SSG environment\n\t * without client-side routing. Do not rely on this feature for production.\n\t *\n\t * This feature is part of the exploration of per locale splitting. The\n\t * issue is ongoing and can be followed here [#88](https://github.com/opral/inlang-paraglide-js/issues/88).\n\t *\n\t * - The client bundle will tree-shake all messages (have close to 0kb JS).\n\t * - The server middleware will inject the used messages into the HTML.\n\t * - The client will re-trieve the messages from the injected HTML.\n\t *\n\t * @default false\n\t */\n\texperimentalMiddlewareLocaleSplitting?: boolean;\n\t/**\n\t * The name of the localStorage key to use for the localStorage strategy.\n\t *\n\t * @default 'PARAGLIDE_LOCALE'\n\t */\n\tlocalStorageKey?: string;\n\t/**\n\t * Tree-shaking flag if the code is running on the server.\n\t *\n\t * Dependent on the bundler, this flag must be adapted to\n\t * enable tree-shaking.\n\t *\n\t * @example\n\t * // vite\n\t * isServer: \"import.meta.env.SSR\"\n\t *\n\t * @default typeof window === \"undefined\"\n\t */\n\tisServer?: string;\n\t/**\n\t * Compile-time locale constant used for per-locale tree-shaking.\n\t *\n\t * This is experimental and opt-in. It should be a JavaScript expression\n\t * (not a quoted literal) that resolves to a locale or `undefined` at build time.\n\t * You can pass a string literal (e.g. `\"de\"`) for programmatic builds, or an\n\t * injected env/define expression for bundler-driven builds.\n\t *\n\t * High-level flow for per-locale builds:\n\t *\n\t * client request (/)\n\t * |\n\t * v\n\t * +----------------------+\n\t * | detect locale |\n\t * | (cookie/Accept-L) |\n\t * | pick build prefix |\n\t * +----------------------+\n\t * | if \"de\"\n\t * v\n\t * serve dist/de/... <----> serve dist/en/...\n\t * (HTML + assets) (HTML + assets)\n\t *\n\t * @see https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638\n\t *\n\t * @example\n\t * // Vite define\n\t * experimentalStaticLocale: \"typeof __PARAGLIDE_STATIC_LOCALE__ === 'undefined' ? undefined : __PARAGLIDE_STATIC_LOCALE__\"\n\t *\n\t * @example\n\t * // Programmatic compile (literal)\n\t * experimentalStaticLocale: '\"de\"'\n\t */\n\texperimentalStaticLocale?: string;\n\t/**\n\t * The name of the cookie to use for the cookie strategy.\n\t *\n\t * @default 'PARAGLIDE_LOCALE'\n\t */\n\tcookieName?: string;\n\t/**\n\t * The max-age in seconds of the cookie until it expires.\n\t *\n\t * @default 60 * 60 * 24 * 400\n\t */\n\tcookieMaxAge?: number;\n\t/**\n\t * The host to which the cookie will be sent.\n\t * If undefined or empty, the domain attribute is omitted from the cookie, scoping it to the exact current domain only (no subdomains).\n\t * If specified, the cookie will be available to the specified domain and all its subdomains.\n\t *\n\t * Use this when you need cookies to be shared across subdomains (e.g., between `app.example.com` and `api.example.com`).\n\t * The default behavior (no domain) ensures better compatibility with server-side cookies that don't specify a domain attribute.\n\t *\n\t * @example\n\t * ```ts\n\t * // Default: exact domain only (compatible with server-side cookies)\n\t * cookieDomain: undefined // Cookie: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000\"\n\t *\n\t * // Subdomain sharing: available across all subdomains\n\t * cookieDomain: \"example.com\" // Cookie: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; domain=example.com\"\n\t * ```\n\t *\n\t * @default \"\" (no domain attribute, exact domain only)\n\t */\n\tcookieDomain?: string;\n\t/**\n\t * The `SameSite` attribute of the cookie.\n\t *\n\t * If undefined, the attribute is omitted and the browser applies its own default.\n\t * Set it when the cookie must match a policy, for example the one a server uses\n\t * when it writes the same cookie with `Set-Cookie`.\n\t *\n\t * `\"none\"` requires `cookieSecure` to be `true` or `\"auto\"` because browsers\n\t * reject `SameSite=None` cookies without the `Secure` attribute. With `\"auto\"`,\n\t * the cookie is still dropped on plain `http://` pages.\n\t *\n\t * @example\n\t * ```ts\n\t * cookieSameSite: \"lax\" // Cookie: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; samesite=lax\"\n\t * ```\n\t *\n\t * @default undefined (no samesite attribute)\n\t */\n\tcookieSameSite?: \"lax\" | \"strict\" | \"none\";\n\t/**\n\t * Whether the cookie gets the `Secure` attribute.\n\t *\n\t * - `true` always adds it. Pages served over plain `http://` cannot set a\n\t * `Secure` cookie, except on `localhost`.\n\t * - `\"auto\"` adds it only when the page is served over `https:`, so the cookie\n\t * keeps working on plain `http://` hosts other than localhost, like a LAN IP\n\t * or an internal staging server. With `cookieSameSite: \"none\"`, the cookie\n\t * still needs `https:`.\n\t * - `false` never adds it.\n\t *\n\t * Server code that reads `cookieSecure` from the runtime has to resolve `\"auto\"`\n\t * itself, for example from the request protocol or `X-Forwarded-Proto`.\n\t *\n\t * @example\n\t * ```ts\n\t * cookieSecure: \"auto\" // on https: \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; secure\"\n\t * ```\n\t *\n\t * @default false\n\t */\n\tcookieSecure?: boolean | \"auto\";\n\t/**\n\t * The `additionalFiles` option is an array of paths to additional files that should be copied to the output directory.\n\t *\n\t * @example\n\t *\n\t * ```diff\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\",\n\t * additionalFiles: [\n\t * + \"my-file.js\": \"console.log('hello')\"\n\t * ]\n\t * })\n\t * ```\n\t *\n\t * The output will look like this:\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - my-file.js\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t */\n\tadditionalFiles?: Record<string, string>;\n\t/**\n\t * If `emitPrettierIgnore` is set to `true` a `.prettierignore` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - .prettierignore\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitPrettierIgnore?: boolean;\n\t/**\n\t * If `emitReadme` is set to `true` a `README.md` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * The README helps LLMs understand the compiled output.\n\t * See https://llmstxt.org/ for format guidelines.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - README.md\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitReadme?: boolean;\n\t/**\n\t * Emit `.d.ts` files for the generated output using the TypeScript compiler.\n\t *\n\t * Useful when `allowJs: true` cannot be set in your `tsconfig.json`\n\t * (e.g., due to project constraints or conflicting compiler options), or when\n\t * an editor language server caches stale JSDoc types for generated messages.\n\t *\n\t * Requires `typescript` to be resolvable in your toolchain.\n\t *\n\t * **Note:** Enabling this option reduces compiler speed because TypeScript\n\t * needs to generate declaration files for all output modules.\n\t *\n\t * **Note:** With TypeScript 5/6 the declarations are generated in-process.\n\t * TypeScript 7+ no longer provides the compiler API, so its `tsc` CLI is\n\t * invoked in a child process instead; the emitted declarations are\n\t * semantically equivalent but differ cosmetically between the two.\n\t *\n\t * @example\n\t * ```ts\n\t * await compile({\n\t * project: \"./project.inlang\",\n\t * outdir: \"./src/paraglide\",\n\t * emitTsDeclarations: true,\n\t * });\n\t * ```\n\t *\n\t * @default false\n\t */\n\temitTsDeclarations?: boolean;\n\t/**\n\t * https://paraglidejs.com/strategy#url\n\t */\n\turlPatterns?: Runtime[\"urlPatterns\"];\n\t/**\n\t * Controls trailing slash canonicalization for localized URLs.\n\t *\n\t * Canonicalization happens before URL pattern matching and after URL\n\t * localization. If omitted, Paraglide keeps its existing trailing slash\n\t * behavior.\n\t */\n\ttrailingSlash?: \"always\" | \"never\";\n\t/**\n\t * Whether to include an eslint-disable comment at the top of each .js file.\n\t *\n\t * @default true\n\t */\n\tincludeEslintDisableComment?: boolean;\n\t/**\n\t * Replaces AsyncLocalStorage with a synchronous implementation.\n\t *\n\t * Leave AsyncLocalStorage enabled by default. This option is a\n\t * compatibility fallback for runtimes that do not provide\n\t * AsyncLocalStorage or `node:async_hooks`.\n\t *\n\t * ⚠️ WARNING: Only use this option when your runtime also guarantees\n\t * request isolation. Disabling AsyncLocalStorage in multi-request\n\t * server environments risks cross-request pollution where state from\n\t * one request could leak into another concurrent request.\n\t */\n\tdisableAsyncLocalStorage?: boolean;\n\t/**\n\t * If `emitGitIgnore` is set to `true` a `.gitignore` file will be emitted in the output directory. Defaults to `true`.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - .gitignore\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default true\n\t */\n\temitGitIgnore?: boolean;\n\t/**\n\t * The `outputStructure` defines how modules are structured in the output.\n\t *\n\t * - `message-modules` - Each module is a message. This is the default.\n\t * - `locale-modules` - Each module is a locale.\n\t *\n\t * It is recommended to use `locale-modules` for development and `message-modules` for production.\n\t * Bundlers speed up the dev mode by bypassing bundling which can lead to many http requests\n\t * during the dev mode with `message-modules`. See https://github.com/opral/inlang-paraglide-js/issues/486.\n\t *\n\t * **`message-modules`**\n\t *\n\t * Messages have their own module which eases tree-shaking for bundlers.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - blue_elephant_tree/\n\t * + - index.js\n\t * + - en.js\n\t * + - fr.js\n\t * + - sky_phone_bottle/\n\t * + - index.js\n\t * + - en.js\n\t * + - fr.js\n\t * - ...\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * **`locale-modules`**\n\t *\n\t * Messages are bundled in a per locale module. Bundlers often struggle with tree-shaking this structure,\n\t * which can lead to more inefficient tree-shaking and larger bundle sizes compared to `message-modules`.\n\t *\n\t * The benefit are substantially fewer files which is needed in large projects.\n\t *\n\t * ```diff\n\t * - outdir/\n\t * - messages/\n\t * + - de.js\n\t * + - en.js\n\t * + - fr.js\n\t * - ...\n\t * - messages.js\n\t * - runtime.js\n\t * ```\n\t *\n\t * @default \"message-modules\"\n\t */\n\toutputStructure?: \"locale-modules\" | \"message-modules\";\n\t/**\n\t * Whether to clean the output directory before writing the new files.\n\t *\n\t * @default true\n\t */\n\tcleanOutdir?: boolean;\n\n\t/**\n\t * The file system to use. Defaults to `await import('node:fs')`.\n\t *\n\t * Useful for testing the paraglide compiler by mocking the fs.\n\t */\n\tfs?: any;\n};\n"]}
|
|
@@ -30,7 +30,7 @@ export function generateOutput(compiledBundles, settings, fallbackMap, experimen
|
|
|
30
30
|
if (!compiledMessage) {
|
|
31
31
|
needsFallback.push(locale);
|
|
32
32
|
}
|
|
33
|
-
else {
|
|
33
|
+
else if (!compiledBundle.unreferencedMessageLocales?.includes(locale)) {
|
|
34
34
|
messages.push(`const ${safeLocale}_${safeModuleId} = ${compiledMessage.code}`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,UAAU,0BAA0B,CAAC,MAAc,EAAE,QAAgB;IAC1E,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,eAA6C,EAC7C,QAAyD,EACzD,WAA+C,EAC/C,qCAAqC,GAAG,KAAK;IAE7C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,MAAM,MAAM,GACX,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CACxC,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;QAC7C,MAAM,kBAAkB,GACvB,cAAc,CAAC,kBAAkB;YACjC,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,cAAc;QACd,MAAM,QAAQ,GAAG,YAAY,YAAY,KAAK,CAAC;QAE/C,eAAe,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC;QAE1C,2BAA2B;QAC3B,MAAM,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC;QAE9C,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,WAAW;QACX,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAExD,IAAI,CAAC,eAAe,EAAE,CAAC;gBACtB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"message-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport { escapeForSingleQuoteString } from \"../../services/codegen/escape.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport { inputsType } from \"../jsdoc-types.js\";\nimport { toBundleInputTypeAliasName } from \"../compile-bundle.js\";\n\nexport function messageReferenceExpression(locale: string, bundleId: string) {\n\treturn `${toSafeModuleId(locale)}_${toSafeModuleId(bundleId)}`;\n}\n\nexport function generateOutput(\n\tcompiledBundles: CompiledBundleWithMessages[],\n\tsettings: Pick<ProjectSettings, \"locales\" | \"baseLocale\">,\n\tfallbackMap: Record<string, string | undefined>,\n\texperimentalMiddlewareLocaleSplitting = false\n): Record<string, string> {\n\tconst output: Record<string, string> = {};\n\n\tconst moduleFilenames = new Set<string>();\n\n\tfor (const compiledBundle of compiledBundles) {\n\t\tconst bundleId = compiledBundle.bundle.node.id;\n\t\tconst safeModuleId = toSafeModuleId(compiledBundle.bundle.node.id);\n\t\tconst inputs =\n\t\t\tcompiledBundle.bundle.node.declarations?.filter(\n\t\t\t\t(decl) => decl.type === \"input-variable\"\n\t\t\t) ?? [];\n\t\tconst matchTypes = compiledBundle.matchTypes;\n\t\tconst inputTypeAliasName =\n\t\t\tcompiledBundle.inputTypeAliasName ??\n\t\t\ttoBundleInputTypeAliasName(safeModuleId);\n\t\tconst inputTypeDefinition = inputsType(inputs, matchTypes);\n\n\t\t// bundle file\n\t\tconst filename = `messages/${safeModuleId}.js`;\n\n\t\tmoduleFilenames.add(`${safeModuleId}.js`);\n\n\t\t// create fresh bundle file\n\t\toutput[filename] = compiledBundle.bundle.code;\n\n\t\tconst needsFallback: string[] = [];\n\n\t\tconst messages: string[] = [];\n\n\t\t// messages\n\t\tfor (const locale of settings.locales) {\n\t\t\tconst safeLocale = toSafeModuleId(locale);\n\t\t\tconst compiledMessage = compiledBundle.messages[locale];\n\n\t\t\tif (!compiledMessage) {\n\t\t\t\tneedsFallback.push(locale);\n\t\t\t} else if (!compiledBundle.unreferencedMessageLocales?.includes(locale)) {\n\t\t\t\tmessages.push(\n\t\t\t\t\t`const ${safeLocale}_${safeModuleId} = ${compiledMessage.code}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// add the fallbacks (needs to be done after the messages to avoid referencing\n\t\t// the message before they are defined)\n\t\tconst needsFallbackSet = new Set(needsFallback);\n\t\tconst emittedFallbacks = new Set<string>();\n\t\tconst emittingFallbacks = new Set<string>();\n\n\t\t/**\n\t\t * Emits the fallback definition for a locale ensuring that dependent fallbacks\n\t\t * are declared beforehand.\n\t\t *\n\t\t * @example\n\t\t * emitFallback(\"fr-ca\");\n\t\t */\n\t\tconst emitFallback = (locale: string) => {\n\t\t\tif (emittedFallbacks.has(locale)) return;\n\t\t\tif (emittingFallbacks.has(locale)) return;\n\n\t\t\temittingFallbacks.add(locale);\n\n\t\t\tconst safeLocale = toSafeModuleId(locale);\n\t\t\tconst fallbackLocale = fallbackMap[locale];\n\n\t\t\tif (\n\t\t\t\tfallbackLocale &&\n\t\t\t\tneedsFallbackSet.has(fallbackLocale) &&\n\t\t\t\t!compiledBundle.messages[fallbackLocale]\n\t\t\t) {\n\t\t\t\temitFallback(fallbackLocale);\n\t\t\t}\n\n\t\t\tif (fallbackLocale) {\n\t\t\t\tconst safeFallbackLocale = toSafeModuleId(fallbackLocale);\n\t\t\t\tmessages.push(\n\t\t\t\t\t`/** @type {(inputs: ${inputTypeAliasName}) => LocalizedString} */\\nconst ${safeLocale}_${safeModuleId} = ${safeFallbackLocale}_${safeModuleId};`\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tmessages.push(\n\t\t\t\t\t`/** @type {(inputs: ${inputTypeAliasName}) => LocalizedString} */\\nconst ${safeLocale}_${safeModuleId} = () => /** @type {LocalizedString} */ ('${escapeForSingleQuoteString(\n\t\t\t\t\t\tbundleId\n\t\t\t\t\t)}')`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\temittingFallbacks.delete(locale);\n\t\t\temittedFallbacks.add(locale);\n\t\t};\n\n\t\tfor (const locale of needsFallback) {\n\t\t\temitFallback(locale);\n\t\t}\n\n\t\toutput[filename] = messages.join(\"\\n\\n\") + \"\\n\\n\" + output[filename];\n\n\t\t// add the imports and type reference (LocalizedString is defined in runtime.js)\n\t\tconst runtimeImport = experimentalMiddlewareLocaleSplitting\n\t\t\t? `import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer, experimentalStaticLocale } from '../runtime.js';\\n\\n`\n\t\t\t: `import { getLocale, experimentalStaticLocale } from '../runtime.js';\\n\\n`;\n\n\t\toutput[filename] =\n\t\t\truntimeImport +\n\t\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\\n\\n` +\n\t\t\t`/** @typedef {${inputTypeDefinition}} ${inputTypeAliasName} */\\n\\n` +\n\t\t\toutput[filename];\n\n\t\t// Add the registry import to the message file if a message calls the\n\t\t// registry. Decided from compiler metadata, not from the file text,\n\t\t// which also contains message text like \"Open the registry. Now.\"\n\t\tconst usesRegistry = settings.locales.some(\n\t\t\t(locale) =>\n\t\t\t\t(compiledBundle.messages[locale]?.registryFunctions.length ?? 0) > 0\n\t\t);\n\t\tif (usesRegistry) {\n\t\t\toutput[filename] =\n\t\t\t\t`import * as registry from '../registry.js'\\n` + output[filename];\n\t\t}\n\t}\n\n\t// all messages index file\n\toutput[\"messages/_index.js\"] =\n\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\\n` +\n\t\tArray.from(moduleFilenames)\n\t\t\t.map((filename) => `export * from './${filename}'`)\n\t\t\t.join(\"\\n\");\n\n\treturn output;\n}\n"]}
|
|
@@ -11,6 +11,56 @@
|
|
|
11
11
|
* The functions of the generated registry.js file, by name.
|
|
12
12
|
*/
|
|
13
13
|
const registryFunctions = {
|
|
14
|
+
getIntlFormatter: {
|
|
15
|
+
jsdoc: `/**
|
|
16
|
+
* @template T
|
|
17
|
+
* @param {new (locale: string, options?: any) => T} Constructor
|
|
18
|
+
* @param {string} locale
|
|
19
|
+
* @param {any} options
|
|
20
|
+
* @param {boolean} cacheable Compiler-created plain options only.
|
|
21
|
+
* @returns {T}
|
|
22
|
+
*/`,
|
|
23
|
+
code: `function getIntlFormatter(Constructor, locale, options, cacheable) {
|
|
24
|
+
// Arbitrary user options may have getters or Proxy traps. Only inspect
|
|
25
|
+
// the plain data objects the compiler creates, or absent options.
|
|
26
|
+
if (typeof locale !== "string" || (options !== undefined && !cacheable)) {
|
|
27
|
+
return new Constructor(locale, options)
|
|
28
|
+
}
|
|
29
|
+
const state = /** @type {{ caches?: WeakMap<object, Map<string, any>>, prototypeKeys?: Set<string> }} */ (/** @type {unknown} */ (getIntlFormatter));
|
|
30
|
+
// Compiler literals inherit Object.prototype. Extensions to it may supply
|
|
31
|
+
// Intl options, so preserve native reads instead of caching in that case.
|
|
32
|
+
if (options !== undefined) {
|
|
33
|
+
const standardKeys = state.prototypeKeys ??= new Set(["constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]);
|
|
34
|
+
if (Object.getOwnPropertyNames(Object.prototype).some((name) => !standardKeys.has(name))) return new Constructor(locale, options)
|
|
35
|
+
}
|
|
36
|
+
const entries = [];
|
|
37
|
+
for (const name of Object.keys(options ?? {}).sort()) {
|
|
38
|
+
const value = options[name];
|
|
39
|
+
if (value === undefined) continue
|
|
40
|
+
if ((value !== null && !["string", "number", "boolean"].includes(typeof value)) || (typeof value === "number" && !Number.isFinite(value))) {
|
|
41
|
+
return new Constructor(locale, options)
|
|
42
|
+
}
|
|
43
|
+
entries.push([name, value]);
|
|
44
|
+
}
|
|
45
|
+
const key = JSON.stringify([locale, entries]);
|
|
46
|
+
const caches = state.caches ??= new WeakMap();
|
|
47
|
+
let cache = caches.get(Constructor);
|
|
48
|
+
if (!cache) {
|
|
49
|
+
cache = new Map();
|
|
50
|
+
caches.set(Constructor, cache);
|
|
51
|
+
}
|
|
52
|
+
if (cache.has(key)) return cache.get(key)
|
|
53
|
+
const formatter = new Constructor(locale, options);
|
|
54
|
+
// Bound retention when applications use dynamic formatter options.
|
|
55
|
+
if (cache.size >= 256) {
|
|
56
|
+
const oldest = cache.keys().next().value;
|
|
57
|
+
if (oldest !== undefined) cache.delete(oldest);
|
|
58
|
+
}
|
|
59
|
+
cache.set(key, formatter);
|
|
60
|
+
return formatter
|
|
61
|
+
};`,
|
|
62
|
+
dependencies: [],
|
|
63
|
+
},
|
|
14
64
|
plural: {
|
|
15
65
|
jsdoc: `/**
|
|
16
66
|
* Selects the plural category of "input - options.offset". The offset
|
|
@@ -20,24 +70,26 @@ const registryFunctions = {
|
|
|
20
70
|
* @param {import("./runtime.js").Locale} locale
|
|
21
71
|
* @param {unknown} input
|
|
22
72
|
* @param {Intl.PluralRulesOptions & { offset?: unknown }} [options]
|
|
73
|
+
* @param {boolean} [cacheable=false] Internal compiler flag for plain data options.
|
|
23
74
|
* @returns {string}
|
|
24
75
|
*/`,
|
|
25
|
-
code: `function plural(locale, input, options) {
|
|
26
|
-
return
|
|
76
|
+
code: `function plural(locale, input, options, cacheable = false) {
|
|
77
|
+
return getIntlFormatter(Intl.PluralRules, locale, options, cacheable).select(Number(input) - Number(options?.offset ?? 0))
|
|
27
78
|
};`,
|
|
28
|
-
dependencies: [],
|
|
79
|
+
dependencies: ["getIntlFormatter"],
|
|
29
80
|
},
|
|
30
81
|
number: {
|
|
31
82
|
jsdoc: `/**
|
|
32
83
|
* @param {import("./runtime.js").Locale} locale
|
|
33
84
|
* @param {unknown} input
|
|
34
85
|
* @param {Intl.NumberFormatOptions} [options]
|
|
86
|
+
* @param {boolean} [cacheable=false] Internal compiler flag for plain data options.
|
|
35
87
|
* @returns {string}
|
|
36
88
|
*/`,
|
|
37
|
-
code: `function number(locale, input, options) {
|
|
38
|
-
return
|
|
89
|
+
code: `function number(locale, input, options, cacheable = false) {
|
|
90
|
+
return getIntlFormatter(Intl.NumberFormat, locale, options, cacheable).format(Number(input))
|
|
39
91
|
};`,
|
|
40
|
-
dependencies: [],
|
|
92
|
+
dependencies: ["getIntlFormatter"],
|
|
41
93
|
},
|
|
42
94
|
icuPound: {
|
|
43
95
|
jsdoc: `/**
|
|
@@ -63,25 +115,31 @@ const registryFunctions = {
|
|
|
63
115
|
* @param {import("./runtime.js").Locale} locale
|
|
64
116
|
* @param {unknown} input
|
|
65
117
|
* @param {Intl.DateTimeFormatOptions} [options]
|
|
118
|
+
* @param {boolean} [cacheable=false] Internal compiler flag for plain data options.
|
|
66
119
|
* @returns {string}
|
|
67
120
|
*/`,
|
|
68
|
-
code: `function datetime(locale, input, options) {
|
|
69
|
-
|
|
121
|
+
code: `function datetime(locale, input, options, cacheable = false) {
|
|
122
|
+
// The host default zone can change while the app is running.
|
|
123
|
+
const formatter = cacheable && options?.timeZone !== undefined
|
|
124
|
+
? getIntlFormatter(Intl.DateTimeFormat, locale, options, cacheable)
|
|
125
|
+
: new Intl.DateTimeFormat(locale, options);
|
|
126
|
+
return formatter.format(new Date(/** @type {string} */ (input)))
|
|
70
127
|
};`,
|
|
71
|
-
dependencies: [],
|
|
128
|
+
dependencies: ["getIntlFormatter"],
|
|
72
129
|
},
|
|
73
130
|
relativetime: {
|
|
74
131
|
jsdoc: `/**
|
|
75
132
|
* @param {import("./runtime.js").Locale} locale
|
|
76
133
|
* @param {unknown} input
|
|
77
134
|
* @param {Intl.RelativeTimeFormatOptions & { unit: RelativeTimeFormatUnit }} options
|
|
135
|
+
* @param {boolean} [cacheable=false] Internal compiler flag for plain data options.
|
|
78
136
|
* @returns {string}
|
|
79
137
|
*/`,
|
|
80
|
-
code: `function relativetime(locale, input, options) {
|
|
138
|
+
code: `function relativetime(locale, input, options, cacheable = false) {
|
|
81
139
|
const { unit, ...intlOptions } = options;
|
|
82
|
-
return
|
|
140
|
+
return getIntlFormatter(Intl.RelativeTimeFormat, locale, intlOptions, cacheable).format(Number(input), unit);
|
|
83
141
|
};`,
|
|
84
|
-
dependencies: [],
|
|
142
|
+
dependencies: ["getIntlFormatter"],
|
|
85
143
|
},
|
|
86
144
|
};
|
|
87
145
|
/**
|
|
@@ -94,7 +152,7 @@ export function createRegistry() {
|
|
|
94
152
|
*/
|
|
95
153
|
|
|
96
154
|
${Object.values(registryFunctions)
|
|
97
|
-
.map((fn) => `${fn.jsdoc}\
|
|
155
|
+
.map((fn) => `${fn.jsdoc}\n${fn === registryFunctions.getIntlFormatter ? "" : "export "}${fn.code}`)
|
|
98
156
|
.join("\n\n")}`;
|
|
99
157
|
}
|
|
100
158
|
/**
|