@intlayer/engine 9.1.3 → 9.3.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/dist/assets/initConfig/templates/cjs.txt +4 -1
- package/dist/assets/initConfig/templates/json.txt +4 -1
- package/dist/assets/initConfig/templates/mjs.txt +4 -1
- package/dist/assets/initConfig/templates/ts.txt +4 -1
- package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs +14 -2
- package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +24 -4
- package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +43 -6
- package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +96 -0
- package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -0
- package/dist/cjs/docReview/alignBlocks.cjs +57 -8
- package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
- package/dist/cjs/docReview/rebuildDocument.cjs +37 -9
- package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
- package/dist/cjs/docReview/segmentDocument.cjs +19 -2
- package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
- package/dist/cjs/fetchDistantDictionaries.cjs +107 -13
- package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadDictionaries.cjs +4 -2
- package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +3 -2
- package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/log.cjs +28 -5
- package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
- package/dist/cjs/prepareIntlayer.cjs +7 -3
- package/dist/cjs/prepareIntlayer.cjs.map +1 -1
- package/dist/cjs/utils/chunkArray.cjs +24 -0
- package/dist/cjs/utils/chunkArray.cjs.map +1 -0
- package/dist/cjs/utils/index.cjs +2 -0
- package/dist/cjs/utils/runOnce.cjs +129 -50
- package/dist/cjs/utils/runOnce.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +153 -92
- package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
- package/dist/cjs/writeFileIfChanged.cjs +14 -7
- package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs +15 -3
- package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +24 -4
- package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +43 -6
- package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +92 -0
- package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs.map +1 -0
- package/dist/esm/docReview/alignBlocks.mjs +57 -8
- package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
- package/dist/esm/docReview/rebuildDocument.mjs +37 -9
- package/dist/esm/docReview/rebuildDocument.mjs.map +1 -1
- package/dist/esm/docReview/segmentDocument.mjs +19 -2
- package/dist/esm/docReview/segmentDocument.mjs.map +1 -1
- package/dist/esm/fetchDistantDictionaries.mjs +107 -13
- package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
- package/dist/esm/loadDictionaries/loadDictionaries.mjs +4 -2
- package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
- package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +3 -2
- package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
- package/dist/esm/loadDictionaries/log.mjs +28 -5
- package/dist/esm/loadDictionaries/log.mjs.map +1 -1
- package/dist/esm/prepareIntlayer.mjs +7 -3
- package/dist/esm/prepareIntlayer.mjs.map +1 -1
- package/dist/esm/utils/chunkArray.mjs +22 -0
- package/dist/esm/utils/chunkArray.mjs.map +1 -0
- package/dist/esm/utils/index.mjs +2 -1
- package/dist/esm/utils/runOnce.mjs +129 -50
- package/dist/esm/utils/runOnce.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/transformJSFile.mjs +153 -92
- package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
- package/dist/esm/writeFileIfChanged.mjs +15 -8
- package/dist/esm/writeFileIfChanged.mjs.map +1 -1
- package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts.map +1 -1
- package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts +14 -2
- package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts.map +1 -1
- package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts +16 -2
- package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts.map +1 -1
- package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts +54 -0
- package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts.map +1 -0
- package/dist/types/docReview/alignBlocks.d.ts +4 -2
- package/dist/types/docReview/alignBlocks.d.ts.map +1 -1
- package/dist/types/docReview/rebuildDocument.d.ts.map +1 -1
- package/dist/types/docReview/segmentDocument.d.ts.map +1 -1
- package/dist/types/docReview/types.d.ts +9 -0
- package/dist/types/docReview/types.d.ts.map +1 -1
- package/dist/types/fetchDistantDictionaries.d.ts +26 -0
- package/dist/types/fetchDistantDictionaries.d.ts.map +1 -1
- package/dist/types/formatDictionary.d.ts +2 -0
- package/dist/types/formatDictionary.d.ts.map +1 -1
- package/dist/types/loadDictionaries/log.d.ts +16 -1
- package/dist/types/loadDictionaries/log.d.ts.map +1 -1
- package/dist/types/utils/chunkArray.d.ts +16 -0
- package/dist/types/utils/chunkArray.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +3 -2
- package/dist/types/utils/runOnce.d.ts +30 -6
- package/dist/types/utils/runOnce.d.ts.map +1 -1
- package/dist/types/writeContentDeclaration/transformJSFile.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -28,7 +28,10 @@ const config = {
|
|
|
28
28
|
/**
|
|
29
29
|
* Enables the Intlayer locale-routing proxy (middleware).
|
|
30
30
|
* Handles locale detection, redirects and rewrites in dev, preview and SSR.
|
|
31
|
-
*
|
|
31
|
+
* Leave unset for auto mode: dev and preview servers keep locale routing
|
|
32
|
+
* URL-driven by ignoring the stored locale. `true` forces the full
|
|
33
|
+
* behaviour everywhere, `false` disables the proxy.
|
|
34
|
+
* Default: undefined (auto)
|
|
32
35
|
*/
|
|
33
36
|
enableProxy: false,
|
|
34
37
|
},
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
/**
|
|
24
24
|
* Enables the Intlayer locale-routing proxy (middleware).
|
|
25
25
|
* Handles locale detection, redirects and rewrites in dev, preview and SSR.
|
|
26
|
-
*
|
|
26
|
+
* Leave unset for auto mode: dev and preview servers keep locale routing
|
|
27
|
+
* URL-driven by ignoring the stored locale. `true` forces the full
|
|
28
|
+
* behaviour everywhere, `false` disables the proxy.
|
|
29
|
+
* Default: undefined (auto)
|
|
27
30
|
*/
|
|
28
31
|
"enableProxy": false
|
|
29
32
|
},
|
|
@@ -28,7 +28,10 @@ const config = {
|
|
|
28
28
|
/**
|
|
29
29
|
* Enables the Intlayer locale-routing proxy (middleware).
|
|
30
30
|
* Handles locale detection, redirects and rewrites in dev, preview and SSR.
|
|
31
|
-
*
|
|
31
|
+
* Leave unset for auto mode: dev and preview servers keep locale routing
|
|
32
|
+
* URL-driven by ignoring the stored locale. `true` forces the full
|
|
33
|
+
* behaviour everywhere, `false` disables the proxy.
|
|
34
|
+
* Default: undefined (auto)
|
|
32
35
|
*/
|
|
33
36
|
enableProxy: false,
|
|
34
37
|
},
|
|
@@ -27,7 +27,10 @@ const config: IntlayerConfig = {
|
|
|
27
27
|
/**
|
|
28
28
|
* Enables the Intlayer locale-routing proxy (middleware).
|
|
29
29
|
* Handles locale detection, redirects and rewrites in dev, preview and SSR.
|
|
30
|
-
*
|
|
30
|
+
* Leave unset for auto mode: dev and preview servers keep locale routing
|
|
31
|
+
* URL-driven by ignoring the stored locale. `true` forces the full
|
|
32
|
+
* behaviour everywhere, `false` disables the proxy.
|
|
33
|
+
* Default: undefined (auto)
|
|
31
34
|
*/
|
|
32
35
|
enableProxy: false,
|
|
33
36
|
},
|
|
@@ -3,6 +3,7 @@ const require_utils_readDictionariesFromDisk = require('../utils/readDictionarie
|
|
|
3
3
|
const require_buildIntlayerDictionary_writeDynamicDictionary = require('./writeDynamicDictionary.cjs');
|
|
4
4
|
const require_buildIntlayerDictionary_writeFetchDictionary = require('./writeFetchDictionary.cjs');
|
|
5
5
|
const require_buildIntlayerDictionary_writeMergedDictionary = require('./writeMergedDictionary.cjs');
|
|
6
|
+
const require_buildIntlayerDictionary_writeNestedDictionary = require('./writeNestedDictionary.cjs');
|
|
6
7
|
const require_buildIntlayerDictionary_writeUnmergedDictionary = require('./writeUnmergedDictionary.cjs');
|
|
7
8
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
8
9
|
let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
|
|
@@ -36,6 +37,8 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
|
|
|
36
37
|
}
|
|
37
38
|
const unmergedDictionaries = await require_buildIntlayerDictionary_writeUnmergedDictionary.writeUnmergedDictionaries(unmergedDictionariesToUpdate, configuration, env);
|
|
38
39
|
const mergedDictionaries = await require_buildIntlayerDictionary_writeMergedDictionary.writeMergedDictionaries(unmergedDictionaries, configuration);
|
|
40
|
+
const nestedDictionaryGraph = (0, _intlayer_core_dictionaryManipulator.getNestedDictionaryGraph)(Object.values(require_utils_readDictionariesFromDisk.readDictionariesFromDisk(configuration.system.dictionariesDir)));
|
|
41
|
+
await require_buildIntlayerDictionary_writeNestedDictionary.writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);
|
|
39
42
|
const dictionariesToBuildDynamic = {};
|
|
40
43
|
const qualifiedDictionariesToBuildDynamic = {};
|
|
41
44
|
const keysToBuildFetch = /* @__PURE__ */ new Set();
|
|
@@ -57,14 +60,23 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
|
|
|
57
60
|
};
|
|
58
61
|
if (mode === "fetch") keysToBuildFetch.add(key);
|
|
59
62
|
}
|
|
63
|
+
for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {
|
|
64
|
+
if (dictionariesToBuildDynamic[nestedKey]) continue;
|
|
65
|
+
const nestedResult = mergedDictionaries[nestedKey];
|
|
66
|
+
if (!nestedResult || (0, _intlayer_core_dictionaryManipulator.isQualifiedDictionaryGroup)(nestedResult.dictionary)) continue;
|
|
67
|
+
dictionariesToBuildDynamic[nestedKey] = {
|
|
68
|
+
dictionaryPath: nestedResult.dictionaryPath,
|
|
69
|
+
dictionary: nestedResult.dictionary
|
|
70
|
+
};
|
|
71
|
+
}
|
|
60
72
|
let dynamicDictionaries = null;
|
|
61
|
-
if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats);
|
|
73
|
+
if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats, nestedDictionaryGraph);
|
|
62
74
|
if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) await require_buildIntlayerDictionary_writeDynamicDictionary.writeDynamicQualifiedDictionaries(qualifiedDictionariesToBuildDynamic, configuration, formats);
|
|
63
75
|
let fetchDictionaries = null;
|
|
64
76
|
if (dynamicDictionaries && keysToBuildFetch.size > 0) {
|
|
65
77
|
const dictionariesToBuildFetch = {};
|
|
66
78
|
for (const key of keysToBuildFetch) if (dynamicDictionaries[key]) dictionariesToBuildFetch[key] = dynamicDictionaries[key];
|
|
67
|
-
if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await require_buildIntlayerDictionary_writeFetchDictionary.writeFetchDictionary(dictionariesToBuildFetch, configuration, formats);
|
|
79
|
+
if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await require_buildIntlayerDictionary_writeFetchDictionary.writeFetchDictionary(dictionariesToBuildFetch, configuration, formats, nestedDictionaryGraph);
|
|
68
80
|
}
|
|
69
81
|
return {
|
|
70
82
|
unmergedDictionaries,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildIntlayerDictionary.cjs","names":["OUTPUT_FORMAT","IMPORT_MODE","readDictionariesFromDisk","writeUnmergedDictionaries","writeMergedDictionaries","writeDynamicDictionary","writeDynamicQualifiedDictionaries","writeFetchDictionary"],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {
|
|
1
|
+
{"version":3,"file":"buildIntlayerDictionary.cjs","names":["OUTPUT_FORMAT","IMPORT_MODE","readDictionariesFromDisk","writeUnmergedDictionaries","writeMergedDictionaries","writeNestedDictionaries","writeDynamicDictionary","writeDynamicQualifiedDictionaries","writeFetchDictionary"],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {\n getNestedDictionaryGraph,\n isQualifiedDictionaryGroup,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport {\n type LocalizedDictionaryOutput,\n type QualifiedMergedDictionaryOutput,\n writeDynamicDictionary,\n writeDynamicQualifiedDictionaries,\n} from './writeDynamicDictionary';\nimport { writeFetchDictionary } from './writeFetchDictionary';\nimport {\n type PlainMergedDictionaryOutput,\n writeMergedDictionaries,\n} from './writeMergedDictionary';\nimport { writeNestedDictionaries } from './writeNestedDictionary';\nimport { writeUnmergedDictionaries } from './writeUnmergedDictionary';\n\nexport type BuildDictionariesOptions = Partial<{\n formats: typeof OUTPUT_FORMAT;\n importOtherDictionaries: boolean;\n env: 'prod' | 'dev';\n}>;\n\nconst defaultOptions = {\n formats: OUTPUT_FORMAT,\n importOtherDictionaries: true,\n env: 'dev',\n} as const satisfies BuildDictionariesOptions;\n\n/**\n * This function transpile the bundled code to to make dictionaries as JSON files\n */\nexport const buildDictionary = async (\n localDictionariesEntries: Dictionary[],\n configuration: IntlayerConfig,\n options?: BuildDictionariesOptions\n) => {\n const importMode =\n configuration?.build?.importMode ??\n configuration?.dictionary?.importMode ??\n IMPORT_MODE;\n\n const { importOtherDictionaries, env, formats } = {\n ...defaultOptions,\n ...options,\n };\n\n const unmergedDictionariesToUpdate: Dictionary[] = [\n ...localDictionariesEntries,\n ];\n\n if (importOtherDictionaries) {\n const prevUnmergedDictionaries: Record<string, Dictionary[]> =\n readDictionariesFromDisk(configuration.system.unmergedDictionariesDir);\n\n // Reinsert other dictionaries with the same key to avoid merging errors\n for (const dictionaryToWrite of localDictionariesEntries) {\n const allPrebuiltUnmergedDictionaries =\n prevUnmergedDictionaries[dictionaryToWrite.key]!;\n\n if (allPrebuiltUnmergedDictionaries?.length > 0) {\n // Do not add the same dictionary again by filtering out the one with the same localId\n const otherUnmergedDictionaries =\n allPrebuiltUnmergedDictionaries?.filter(\n (unmergedDictionary) =>\n unmergedDictionary.localId !== dictionaryToWrite.localId\n );\n\n unmergedDictionariesToUpdate.push(...(otherUnmergedDictionaries ?? []));\n }\n }\n }\n\n const unmergedDictionaries = await writeUnmergedDictionaries(\n unmergedDictionariesToUpdate,\n configuration,\n env\n );\n\n const mergedDictionaries = await writeMergedDictionaries(\n unmergedDictionaries,\n configuration\n );\n\n // `nest()` dependency graph, read back from disk so it stays complete on\n // incremental rebuilds where only a subset of dictionaries was regenerated.\n // Every artifact kind attaches its dependencies, letting `getNesting` resolve\n // them locally instead of through the registry the optimizer strips.\n const nestedDictionaryGraph = getNestedDictionaryGraph(\n Object.values(\n readDictionariesFromDisk<Record<string, Dictionary>>(\n configuration.system.dictionariesDir\n )\n )\n );\n\n await writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);\n\n const dictionariesToBuildDynamic: PlainMergedDictionaryOutput = {};\n const qualifiedDictionariesToBuildDynamic: QualifiedMergedDictionaryOutput =\n {};\n const keysToBuildFetch = new Set<string>();\n\n for (const [key, mergedResult] of Object.entries(mergedDictionaries)) {\n const dictionary = mergedResult.dictionary;\n\n if (isQualifiedDictionaryGroup(dictionary)) {\n // Collections / variants resolve their qualifier at\n // runtime from a selector. Static mode keeps every entry in one JSON;\n // dynamic mode splits them into one chunk per (locale, qualifierId).\n const entryMode = dictionary.importMode ?? importMode;\n\n if (entryMode === 'dynamic') {\n qualifiedDictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n } else if (entryMode === 'fetch') {\n const appLogger = getAppLogger(configuration);\n appLogger(\n `Dictionary ${colorizeKey(key)} uses 'fetch' import mode with (${dictionary.qualifierTypes.join(', ')}) entries — fetch mode is not qualifier-aware yet, falling back to static import.`,\n { level: 'warn' }\n );\n }\n\n continue;\n }\n\n const mode = dictionary.importMode ?? importMode;\n\n if (mode === 'dynamic' || mode === 'fetch') {\n dictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n }\n\n if (mode === 'fetch') {\n keysToBuildFetch.add(key);\n }\n }\n\n // A lazily loaded dictionary resolves its `nest()` references from chunks\n // loaded by the same loader, so its nest targets need dynamic artifacts of\n // their own — whatever import mode they declare for their own call sites.\n for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) {\n for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {\n if (dictionariesToBuildDynamic[nestedKey]) continue;\n\n const nestedResult = mergedDictionaries[nestedKey];\n if (\n !nestedResult ||\n isQualifiedDictionaryGroup(nestedResult.dictionary)\n ) {\n continue;\n }\n\n dictionariesToBuildDynamic[nestedKey] = {\n dictionaryPath: nestedResult.dictionaryPath,\n dictionary: nestedResult.dictionary,\n };\n }\n }\n\n let dynamicDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (Object.keys(dictionariesToBuildDynamic).length > 0) {\n dynamicDictionaries = await writeDynamicDictionary(\n dictionariesToBuildDynamic,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n\n if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) {\n await writeDynamicQualifiedDictionaries(\n qualifiedDictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n let fetchDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (dynamicDictionaries && keysToBuildFetch.size > 0) {\n const dictionariesToBuildFetch: LocalizedDictionaryOutput = {};\n\n for (const key of keysToBuildFetch) {\n if (dynamicDictionaries[key]) {\n dictionariesToBuildFetch[key] = dynamicDictionaries[key];\n }\n }\n\n if (Object.keys(dictionariesToBuildFetch).length > 0) {\n fetchDictionaries = await writeFetchDictionary(\n dictionariesToBuildFetch,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n }\n\n return {\n unmergedDictionaries,\n mergedDictionaries,\n dynamicDictionaries,\n fetchDictionaries,\n };\n};\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAM,iBAAiB;CACrB,SAASA;CACT,yBAAyB;CACzB,KAAK;AACP;;;;AAKA,MAAa,kBAAkB,OAC7B,0BACA,eACA,YACG;CACH,MAAM,aACJ,eAAe,OAAO,cACtB,eAAe,YAAY,cAC3BC;CAEF,MAAM,EAAE,yBAAyB,KAAK,YAAY;EAChD,GAAG;EACH,GAAG;CACL;CAEA,MAAM,+BAA6C,CACjD,GAAG,wBACL;CAEA,IAAI,yBAAyB;EAC3B,MAAM,2BACJC,gEAAyB,cAAc,OAAO,uBAAuB;EAGvE,KAAK,MAAM,qBAAqB,0BAA0B;GACxD,MAAM,kCACJ,yBAAyB,kBAAkB;GAE7C,IAAI,iCAAiC,SAAS,GAAG;IAE/C,MAAM,4BACJ,iCAAiC,QAC9B,uBACC,mBAAmB,YAAY,kBAAkB,OACrD;IAEF,6BAA6B,KAAK,GAAI,6BAA6B,CAAC,CAAE;GACxE;EACF;CACF;CAEA,MAAM,uBAAuB,MAAMC,kFACjC,8BACA,eACA,GACF;CAEA,MAAM,qBAAqB,MAAMC,8EAC/B,sBACA,aACF;CAMA,MAAM,2FACJ,OAAO,OACLF,gEACE,cAAc,OAAO,eACvB,CACF,CACF;CAEA,MAAMG,8EAAwB,uBAAuB,eAAe,OAAO;CAE3E,MAAM,6BAA0D,CAAC;CACjE,MAAM,sCACJ,CAAC;CACH,MAAM,mCAAmB,IAAI,IAAY;CAEzC,KAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,kBAAkB,GAAG;EACpE,MAAM,aAAa,aAAa;EAEhC,yEAA+B,UAAU,GAAG;GAI1C,MAAM,YAAY,WAAW,cAAc;GAE3C,IAAI,cAAc,WAChB,oCAAoC,OAAO;IACzC,gBAAgB,aAAa;IAC7B;GACF;QACK,IAAI,cAAc,SAEvB,0CAD+B,aACvB,CAAC,CACP,uDAA0B,GAAG,EAAE,kCAAkC,WAAW,eAAe,KAAK,IAAI,EAAE,oFACtG,EAAE,OAAO,OAAO,CAClB;GAGF;EACF;EAEA,MAAM,OAAO,WAAW,cAAc;EAEtC,IAAI,SAAS,aAAa,SAAS,SACjC,2BAA2B,OAAO;GAChC,gBAAgB,aAAa;GAC7B;EACF;EAGF,IAAI,SAAS,SACX,iBAAiB,IAAI,GAAG;CAE5B;CAKA,KAAK,MAAM,eAAe,OAAO,KAAK,0BAA0B,GAC9D,KAAK,MAAM,aAAa,sBAAsB,IAAI,WAAW,KAAK,CAAC,GAAG;EACpE,IAAI,2BAA2B,YAAY;EAE3C,MAAM,eAAe,mBAAmB;EACxC,IACE,CAAC,qFAC0B,aAAa,UAAU,GAElD;EAGF,2BAA2B,aAAa;GACtC,gBAAgB,aAAa;GAC7B,YAAY,aAAa;EAC3B;CACF;CAGF,IAAI,sBAAwD;CAE5D,IAAI,OAAO,KAAK,0BAA0B,CAAC,CAAC,SAAS,GACnD,sBAAsB,MAAMC,8EAC1B,4BACA,eACA,SACA,qBACF;CAGF,IAAI,OAAO,KAAK,mCAAmC,CAAC,CAAC,SAAS,GAC5D,MAAMC,yFACJ,qCACA,eACA,OACF;CAGF,IAAI,oBAAsD;CAE1D,IAAI,uBAAuB,iBAAiB,OAAO,GAAG;EACpD,MAAM,2BAAsD,CAAC;EAE7D,KAAK,MAAM,OAAO,kBAChB,IAAI,oBAAoB,MACtB,yBAAyB,OAAO,oBAAoB;EAIxD,IAAI,OAAO,KAAK,wBAAwB,CAAC,CAAC,SAAS,GACjD,oBAAoB,MAAMC,0EACxB,0BACA,eACA,SACA,qBACF;CAEJ;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -18,15 +18,35 @@ const DICTIONARIES_SUBDIR = "json";
|
|
|
18
18
|
* emitted JavaScript.
|
|
19
19
|
*/
|
|
20
20
|
const escapeJsLiteral = (value) => value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
21
|
+
/** Loader expression for one `(key, locale)` per-locale chunk. */
|
|
22
|
+
const buildPerLocaleLoader = (key, locale, format) => {
|
|
23
|
+
const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;
|
|
24
|
+
return format === "esm" ? `import('${path}').then(m => m.default)` : `Promise.resolve(require('${path}'))`;
|
|
25
|
+
};
|
|
21
26
|
/**
|
|
22
27
|
* Generates the content of a dictionary entry point file.
|
|
28
|
+
*
|
|
29
|
+
* When the dictionary references other dictionaries through `nest()`, the
|
|
30
|
+
* loader for a locale resolves the referenced dictionaries alongside it and
|
|
31
|
+
* attaches them as `nestedDictionaries`. The nest targets then travel in the
|
|
32
|
+
* same lazy chunk as their consumer, and `getNesting` resolves them from that
|
|
33
|
+
* local reference instead of the global registry — which the build
|
|
34
|
+
* optimization strips.
|
|
35
|
+
*
|
|
36
|
+
* @param key - The dictionary key.
|
|
37
|
+
* @param locales - Locales to emit a loader for.
|
|
38
|
+
* @param format - Output module format.
|
|
39
|
+
* @param nestedKeys - Keys referenced through `nest()`, transitively.
|
|
23
40
|
*/
|
|
24
|
-
const generateDictionaryEntryPoint = (key, locales, format = "esm") => {
|
|
41
|
+
const generateDictionaryEntryPoint = (key, locales, format = "esm", nestedKeys = []) => {
|
|
25
42
|
const sortedLocales = [...locales].sort((a, b) => String(a).localeCompare(String(b)));
|
|
43
|
+
const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));
|
|
26
44
|
const safeKey = escapeJsLiteral(key);
|
|
27
45
|
const localeEntries = sortedLocales.map((locale) => {
|
|
28
46
|
const safeLocale = escapeJsLiteral(locale);
|
|
29
|
-
|
|
47
|
+
const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);
|
|
48
|
+
if (sortedNestedKeys.length === 0) return ` '${safeLocale}': () => ${ownLoader}`;
|
|
49
|
+
return ` '${safeLocale}': () => Promise.all([\n ${ownLoader},\n ${sortedNestedKeys.map((nestedKey) => buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)).join(",\n ")}\n ]).then(([_dictionary, ..._nested]) => ({\n ..._dictionary,\n nestedDictionaries: { ${sortedNestedKeys.map((nestedKey, index) => `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`).join(", ")} }\n }))`;
|
|
30
50
|
}).join(",\n");
|
|
31
51
|
if (format === "esm") return `const content = {\n${localeEntries}\n};\n\nexport default content;\n`;
|
|
32
52
|
return `module.exports = {\n${localeEntries}\n};\n`;
|
|
@@ -95,7 +115,7 @@ const generateQualifiedDictionaryEntryPoint = (key, qualifierTypes, entries, loc
|
|
|
95
115
|
* // .intlayer/dynamic_dictionary/dictionaries/fr_home.json
|
|
96
116
|
* ```
|
|
97
117
|
*/
|
|
98
|
-
const writeDynamicDictionary = async (mergedDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT) => {
|
|
118
|
+
const writeDynamicDictionary = async (mergedDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT, nestedDictionaryGraph = /* @__PURE__ */ new Map()) => {
|
|
99
119
|
const { locales, defaultLocale } = configuration.internationalization;
|
|
100
120
|
const { dynamicDictionariesDir } = configuration.system;
|
|
101
121
|
const dictDir = (0, node_path.resolve)(dynamicDictionariesDir, DICTIONARIES_SUBDIR);
|
|
@@ -121,7 +141,7 @@ const writeDynamicDictionary = async (mergedDictionaries, configuration, formats
|
|
|
121
141
|
resultDictionariesPaths[key] = localizedDictionariesPathsRecord;
|
|
122
142
|
await require_utils_parallelize.parallelize(formats, async (format) => {
|
|
123
143
|
const extension = format === "cjs" ? "cjs" : "mjs";
|
|
124
|
-
const content = generateDictionaryEntryPoint(key, locales, format);
|
|
144
|
+
const content = generateDictionaryEntryPoint(key, locales, format, [...nestedDictionaryGraph.get(key) ?? []]);
|
|
125
145
|
const dynEntryPath = (0, node_path.resolve)(dynamicDictionariesDir, `${key}.${extension}`);
|
|
126
146
|
(0, _intlayer_config_utils.assertPathWithin)(dynEntryPath, dynamicDictionariesDir);
|
|
127
147
|
await require_writeFileIfChanged.writeFileIfChanged(dynEntryPath, content).catch((err) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeDynamicDictionary.cjs","names":["QUALIFIER_DYNAMIC_TYPES_KEY","OUTPUT_FORMAT","parallelize","writeJsonIfChanged","writeFileIfChanged","COMPOSITE_ID_SEPARATOR"],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/**\n * Generates the content of a dictionary entry point file.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n return format === 'esm'\n ? ` '${safeLocale}': () => import('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json').then(m => m.default)`\n : ` '${safeLocale}': () => Promise.resolve(require('./${DICTIONARIES_SUBDIR}/${safeKey}/${safeLocale}.json'))`;\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"writeDynamicDictionary.cjs","names":["QUALIFIER_DYNAMIC_TYPES_KEY","OUTPUT_FORMAT","parallelize","writeJsonIfChanged","writeFileIfChanged","COMPOSITE_ID_SEPARATOR"],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Loader expression for one `(key, locale)` per-locale chunk. */\nconst buildPerLocaleLoader = (\n key: string,\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;\n\n return format === 'esm'\n ? `import('${path}').then(m => m.default)`\n : `Promise.resolve(require('${path}'))`;\n};\n\n/**\n * Generates the content of a dictionary entry point file.\n *\n * When the dictionary references other dictionaries through `nest()`, the\n * loader for a locale resolves the referenced dictionaries alongside it and\n * attaches them as `nestedDictionaries`. The nest targets then travel in the\n * same lazy chunk as their consumer, and `getNesting` resolves them from that\n * local reference instead of the global registry — which the build\n * optimization strips.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);\n\n if (sortedNestedKeys.length === 0) {\n return ` '${safeLocale}': () => ${ownLoader}`;\n }\n\n const nestedLoaders = sortedNestedKeys\n .map((nestedKey) =>\n buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map(\n (nestedKey, index) =>\n `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`\n )\n .join(', ');\n\n return (\n ` '${safeLocale}': () => Promise.all([\\n` +\n ` ${ownLoader},\\n` +\n ` ${nestedLoaders}\\n` +\n ` ]).then(([_dictionary, ..._nested]) => ({\\n` +\n ` ..._dictionary,\\n` +\n ` nestedDictionaries: { ${attachedEntries} }\\n` +\n ` }))`\n );\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format, [\n ...(nestedDictionaryGraph.get(key) ?? []),\n ]);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_utils_parallelize = require('../utils/parallelize.cjs');
|
|
3
3
|
const require_writeFileIfChanged = require('../writeFileIfChanged.cjs');
|
|
4
|
+
const require_utils_getPathHash = require('../utils/getPathHash.cjs');
|
|
4
5
|
let node_fs_promises = require("node:fs/promises");
|
|
5
6
|
let node_path = require("node:path");
|
|
6
7
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
@@ -8,11 +9,47 @@ let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
|
8
9
|
let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
|
|
9
10
|
|
|
10
11
|
//#region src/buildIntlayerDictionary/writeFetchDictionary.ts
|
|
11
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Local identifier of the dynamic loader backing a nest target's fallback.
|
|
14
|
+
* Hashed so any dictionary key yields a valid identifier.
|
|
15
|
+
*/
|
|
16
|
+
const dynamicLoaderIdentifier = (key) => `_dyn${require_utils_getPathHash.getPathHash(key)}`;
|
|
17
|
+
/**
|
|
18
|
+
* Fetches one dictionary for a locale from the live-sync server, falling back
|
|
19
|
+
* to its own build-time dynamic chunk when the request fails.
|
|
20
|
+
*
|
|
21
|
+
* `fallbackLoader` must be the loader of `key` itself — a nest target falling
|
|
22
|
+
* back to its consumer's chunk would attach the wrong content.
|
|
23
|
+
*/
|
|
24
|
+
const buildLiveFetchExpression = (key, locale, fallbackLoader) => `(async () => {
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(\`\${editor.liveSyncURL}/dictionaries/${key}/${locale}\`);\n return await res.json();\n } catch {\n return ${fallbackLoader}['${locale}']();\n }\n })()`;
|
|
27
|
+
/**
|
|
28
|
+
* Generates the live (fetch-mode) entry point of a dictionary.
|
|
29
|
+
*
|
|
30
|
+
* When the dictionary references others through `nest()`, those are fetched
|
|
31
|
+
* live alongside it and attached as `nestedDictionaries`, so a remote edit to a
|
|
32
|
+
* nested dictionary propagates through the reference instead of resolving
|
|
33
|
+
* against the build-time snapshot.
|
|
34
|
+
*
|
|
35
|
+
* @param key - The dictionary key.
|
|
36
|
+
* @param locales - Locales to emit a loader for.
|
|
37
|
+
* @param relativePrefix - Relative path to the dynamic dictionaries directory.
|
|
38
|
+
* @param format - Output module format.
|
|
39
|
+
* @param nestedKeys - Keys referenced through `nest()`, transitively.
|
|
40
|
+
*/
|
|
41
|
+
const generateDictionaryEntryPoint = (key, locales, relativePrefix, format = "esm", nestedKeys = []) => {
|
|
12
42
|
const extension = format === "cjs" ? "cjs" : "mjs";
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
43
|
+
const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));
|
|
44
|
+
const localeEntries = locales.sort((a, b) => String(a).localeCompare(String(b))).map((locale) => {
|
|
45
|
+
if (sortedNestedKeys.length === 0) return ` '${locale}': async () => {\n try {\n const res = await fetch(\`\${editor.liveSyncURL}/dictionaries/${key}/${locale}\`);\n return await res.json();\n } catch {\n return dynContent['${locale}']();\n }\n }`;
|
|
46
|
+
const nestedFetches = sortedNestedKeys.map((nestedKey) => buildLiveFetchExpression(nestedKey, locale, dynamicLoaderIdentifier(nestedKey))).join(",\n ");
|
|
47
|
+
const attachedEntries = sortedNestedKeys.map((nestedKey, index) => `'${nestedKey}': _nested[${index}]`).join(", ");
|
|
48
|
+
return ` '${locale}': async () => {\n const [_dictionary, ..._nested] = await Promise.all([\n ${buildLiveFetchExpression(key, locale, "dynContent")},\n ${nestedFetches}\n ]);\n return { ..._dictionary, nestedDictionaries: { ${attachedEntries} } };\n }`;
|
|
49
|
+
}).join(",\n");
|
|
50
|
+
const nestedImports = sortedNestedKeys.map((nestedKey) => format === "esm" ? `import ${dynamicLoaderIdentifier(nestedKey)} from '${relativePrefix}/${nestedKey}.${extension}';` : `const ${dynamicLoaderIdentifier(nestedKey)} = require('${relativePrefix}/${nestedKey}.${extension}');`).join("\n");
|
|
51
|
+
if (format === "esm") return `import { editor } from 'intlayer';\nimport dynContent from '${relativePrefix}/${key}.${extension}';\n${nestedImports}\n\nconst content = {\n${localeEntries}\n};\n\nexport default content;\n`;
|
|
52
|
+
return `const { editor } = require('intlayer');\nconst dynContent = require('${relativePrefix}/${key}.${extension}');\n${nestedImports}\n\nmodule.exports = {\n${localeEntries}\n};\n`;
|
|
16
53
|
};
|
|
17
54
|
/**
|
|
18
55
|
* Write the localized dictionaries to the dictionariesDir
|
|
@@ -30,7 +67,7 @@ const generateDictionaryEntryPoint = (key, locales, relativePrefix, format = "es
|
|
|
30
67
|
* // .intlayer/fetch_dictionary/home.cjs
|
|
31
68
|
* ```
|
|
32
69
|
*/
|
|
33
|
-
const writeFetchDictionary = async (dynamicDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT) => {
|
|
70
|
+
const writeFetchDictionary = async (dynamicDictionaries, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT, nestedDictionaryGraph = /* @__PURE__ */ new Map()) => {
|
|
34
71
|
const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;
|
|
35
72
|
const { locales } = configuration.internationalization;
|
|
36
73
|
let relativePrefix = (0, _intlayer_config_utils.normalizePath)((0, node_path.relative)(fetchDictionariesDir, dynamicDictionariesDir));
|
|
@@ -41,7 +78,7 @@ const writeFetchDictionary = async (dynamicDictionaries, configuration, formats
|
|
|
41
78
|
if (key === "undefined") return;
|
|
42
79
|
await require_utils_parallelize.parallelize(formats, async (format) => {
|
|
43
80
|
const extension = format === "cjs" ? "cjs" : "mjs";
|
|
44
|
-
const content = generateDictionaryEntryPoint(key, locales, relativePrefix, format);
|
|
81
|
+
const content = generateDictionaryEntryPoint(key, locales, relativePrefix, format, [...nestedDictionaryGraph.get(key) ?? []]);
|
|
45
82
|
const fetchEntryPath = (0, node_path.resolve)(fetchDictionariesDir, `${key}.${extension}`);
|
|
46
83
|
(0, _intlayer_config_utils.assertPathWithin)(fetchEntryPath, fetchDictionariesDir);
|
|
47
84
|
await require_writeFileIfChanged.writeFileIfChanged(fetchEntryPath, content).catch((err) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeFetchDictionary.cjs","names":["OUTPUT_FORMAT","parallelize","writeFileIfChanged"],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin, normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map(\n (
|
|
1
|
+
{"version":3,"file":"writeFetchDictionary.cjs","names":["getPathHash","OUTPUT_FORMAT","parallelize","writeFileIfChanged"],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin, normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getPathHash } from '../utils/getPathHash';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\n/**\n * Local identifier of the dynamic loader backing a nest target's fallback.\n * Hashed so any dictionary key yields a valid identifier.\n */\nconst dynamicLoaderIdentifier = (key: string): string =>\n `_dyn${getPathHash(key)}`;\n\n/**\n * Fetches one dictionary for a locale from the live-sync server, falling back\n * to its own build-time dynamic chunk when the request fails.\n *\n * `fallbackLoader` must be the loader of `key` itself — a nest target falling\n * back to its consumer's chunk would attach the wrong content.\n */\nconst buildLiveFetchExpression = (\n key: string,\n locale: string,\n fallbackLoader: string\n): string =>\n `(async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return ${fallbackLoader}['${locale}']();\\n` +\n ` }\\n` +\n ` })()`;\n\n/**\n * Generates the live (fetch-mode) entry point of a dictionary.\n *\n * When the dictionary references others through `nest()`, those are fetched\n * live alongside it and attached as `nestedDictionaries`, so a remote edit to a\n * nested dictionary propagates through the reference instead of resolving\n * against the build-time snapshot.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param relativePrefix - Relative path to the dynamic dictionaries directory.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map((locale) => {\n if (sortedNestedKeys.length === 0) {\n return (\n ` '${locale}': async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return dynContent['${locale}']();\\n` +\n ` }\\n` +\n ` }`\n );\n }\n\n const nestedFetches = sortedNestedKeys\n .map((nestedKey) =>\n buildLiveFetchExpression(\n nestedKey,\n locale,\n dynamicLoaderIdentifier(nestedKey)\n )\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map((nestedKey, index) => `'${nestedKey}': _nested[${index}]`)\n .join(', ');\n\n return (\n ` '${locale}': async () => {\\n` +\n ` const [_dictionary, ..._nested] = await Promise.all([\\n` +\n ` ${buildLiveFetchExpression(key, locale, 'dynContent')},\\n` +\n ` ${nestedFetches}\\n` +\n ` ]);\\n` +\n ` return { ..._dictionary, nestedDictionaries: { ${attachedEntries} } };\\n` +\n ` }`\n );\n })\n .join(',\\n');\n\n // Each nest target falls back to its own dynamic chunk when the live request\n // fails, so a failure never attaches the consumer's content under its key.\n const nestedImports = sortedNestedKeys\n .map((nestedKey) =>\n format === 'esm'\n ? `import ${dynamicLoaderIdentifier(nestedKey)} from '${relativePrefix}/${nestedKey}.${extension}';`\n : `const ${dynamicLoaderIdentifier(nestedKey)} = require('${relativePrefix}/${nestedKey}.${extension}');`\n )\n .join('\\n');\n\n if (format === 'esm') {\n return (\n `import { editor } from 'intlayer';\\n` +\n `import dynContent from '${relativePrefix}/${key}.${extension}';\\n` +\n `${nestedImports}\\n\\n` +\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return (\n `const { editor } = require('intlayer');\\n` +\n `const dynContent = require('${relativePrefix}/${key}.${extension}');\\n` +\n `${nestedImports}\\n\\n` +\n `module.exports = {\\n${localeEntries}\\n};\\n`\n );\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionary/home.mjs\n * // .intlayer/fetch_dictionary/home.cjs\n * ```\n */\nexport const writeFetchDictionary = async (\n dynamicDictionaries: LocalizedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;\n const { locales } = configuration.internationalization;\n\n // Compute relative path from fetch dir to dynamic dir\n let relativePrefix = normalizePath(\n relative(fetchDictionariesDir, dynamicDictionariesDir)\n );\n if (!relativePrefix.startsWith('.')) {\n relativePrefix = `./${relativePrefix}`;\n }\n\n await mkdir(resolve(fetchDictionariesDir), { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Write entry points for each dictionary in parallel\n await parallelize(Object.entries(dynamicDictionaries), async ([key]) => {\n if (key === 'undefined') return;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(\n key,\n locales,\n relativePrefix,\n format,\n [...(nestedDictionaryGraph.get(key) ?? [])]\n );\n\n const fetchEntryPath = resolve(\n fetchDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(fetchEntryPath, fetchDictionariesDir);\n\n await writeFileIfChanged(fetchEntryPath, content).catch((err) => {\n console.error(\n `Error creating fetch ${colorizePath(fetchEntryPath)}:`,\n err\n );\n });\n });\n });\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,2BAA2B,QAC/B,OAAOA,sCAAY,GAAG;;;;;;;;AASxB,MAAM,4BACJ,KACA,QACA,mBAEA;;wEAEyE,IAAI,GAAG,OAAO,0EAGrE,eAAe,IAAI,OAAO;;;;;;;;;;;;;;;AAkB9C,MAAa,gCACX,KACA,SACA,gBACA,SAAwB,OACxB,aAAuB,CAAC,MACb;CACX,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAC7C,MAAM,mBAAmB,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAE1E,MAAM,gBAAgB,QACnB,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,CAAC,CAAC,CAAC,CAClD,KAAK,WAAW;EACf,IAAI,iBAAiB,WAAW,GAC9B,OACE,MAAM,OAAO,mGAE0D,IAAI,GAAG,OAAO,gFAGzD,OAAO;EAMvC,MAAM,gBAAgB,iBACnB,KAAK,cACJ,yBACE,WACA,QACA,wBAAwB,SAAS,CACnC,CACF,CAAC,CACA,KAAK,SAAS;EAEjB,MAAM,kBAAkB,iBACrB,KAAK,WAAW,UAAU,IAAI,UAAU,aAAa,MAAM,EAAE,CAAC,CAC9D,KAAK,IAAI;EAEZ,OACE,MAAM,OAAO,mFAEN,yBAAyB,KAAK,QAAQ,YAAY,EAAE,SACpD,cAAc,gEAEiC,gBAAgB;CAG1E,CAAC,CAAC,CACD,KAAK,KAAK;CAIb,MAAM,gBAAgB,iBACnB,KAAK,cACJ,WAAW,QACP,UAAU,wBAAwB,SAAS,EAAE,SAAS,eAAe,GAAG,UAAU,GAAG,UAAU,MAC/F,SAAS,wBAAwB,SAAS,EAAE,cAAc,eAAe,GAAG,UAAU,GAAG,UAAU,IACzG,CAAC,CACA,KAAK,IAAI;CAEZ,IAAI,WAAW,OACb,OACE,+DAC2B,eAAe,GAAG,IAAI,GAAG,UAAU,MAC3D,cAAc,yBACK,cAAc;CAIxC,OACE,wEAC+B,eAAe,GAAG,IAAI,GAAG,UAAU,OAC/D,cAAc,0BACM,cAAc;AAEzC;;;;;;;;;;;;;;;;;AAkBA,MAAa,uBAAuB,OAClC,qBACA,eACA,UAA6BC,8CAC7B,wCAAkD,IAAI,IAAI,MACnB;CACvC,MAAM,EAAE,sBAAsB,2BAA2B,cAAc;CACvE,MAAM,EAAE,YAAY,cAAc;CAGlC,IAAI,mFACO,sBAAsB,sBAAsB,CACvD;CACA,IAAI,CAAC,eAAe,WAAW,GAAG,GAChC,iBAAiB,KAAK;CAGxB,yDAAoB,oBAAoB,GAAG,EAAE,WAAW,KAAK,CAAC;CAE9D,MAAM,0BAAqD,CAAC;CAG5D,MAAMC,sCAAY,OAAO,QAAQ,mBAAmB,GAAG,OAAO,CAAC,SAAS;EACtE,IAAI,QAAQ,aAAa;EAEzB,MAAMA,sCAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BACd,KACA,SACA,gBACA,QACA,CAAC,GAAI,sBAAsB,IAAI,GAAG,KAAK,CAAC,CAAE,CAC5C;GAEA,MAAM,wCACJ,sBACA,GAAG,IAAI,GAAG,WACZ;GACA,6CAAiB,gBAAgB,oBAAoB;GAErD,MAAMC,8CAAmB,gBAAgB,OAAO,CAAC,CAAC,OAAO,QAAQ;IAC/D,QAAQ,MACN,kEAAqC,cAAc,EAAE,IACrD,GACF;GACF,CAAC;EACH,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_utils_parallelize = require('../utils/parallelize.cjs');
|
|
3
|
+
const require_writeFileIfChanged = require('../writeFileIfChanged.cjs');
|
|
4
|
+
const require_utils_getPathHash = require('../utils/getPathHash.cjs');
|
|
5
|
+
let node_fs_promises = require("node:fs/promises");
|
|
6
|
+
let node_path = require("node:path");
|
|
7
|
+
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
8
|
+
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
9
|
+
let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
|
|
10
|
+
|
|
11
|
+
//#region src/buildIntlayerDictionary/writeNestedDictionary.ts
|
|
12
|
+
/**
|
|
13
|
+
* Subdirectory of `dictionariesDir` holding the companion modules. Nested under
|
|
14
|
+
* the compiled dictionaries so both stay together and are cleaned as one, and
|
|
15
|
+
* because the `**\/*.json` globs listing compiled dictionaries never match the
|
|
16
|
+
* `.mjs` / `.cjs` files written here.
|
|
17
|
+
*/
|
|
18
|
+
const NESTED_DICTIONARIES_SUBDIR = "nested";
|
|
19
|
+
/**
|
|
20
|
+
* Escapes a value interpolated into a single-quoted literal of a generated
|
|
21
|
+
* module, so keys containing `'` or `\` cannot break the emitted JavaScript.
|
|
22
|
+
*/
|
|
23
|
+
const escapeJsLiteral = (value) => value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
24
|
+
/**
|
|
25
|
+
* Path of the companion module carrying the `nest()` targets of a dictionary.
|
|
26
|
+
*
|
|
27
|
+
* Shared with the bundler plugins, which re-point the static import they inject
|
|
28
|
+
* at a `useIntlayer` call site to this module whenever the dictionary has nest
|
|
29
|
+
* targets.
|
|
30
|
+
*
|
|
31
|
+
* @param dictionariesDir - The compiled dictionaries directory.
|
|
32
|
+
* @param key - The dictionary key.
|
|
33
|
+
* @param extension - Module extension, `'mjs'` (default) or `'cjs'`.
|
|
34
|
+
*/
|
|
35
|
+
const getNestedDictionaryPath = (dictionariesDir, key, extension = "mjs") => (0, node_path.resolve)(dictionariesDir, NESTED_DICTIONARIES_SUBDIR, `${key}.${extension}`);
|
|
36
|
+
/**
|
|
37
|
+
* Generates a companion module that re-exports a compiled dictionary with its
|
|
38
|
+
* `nest()` targets attached.
|
|
39
|
+
*
|
|
40
|
+
* The optimizer imports this instead of the raw JSON, so `getNesting` resolves
|
|
41
|
+
* the reference from `nestedDictionaries` rather from the global registry
|
|
42
|
+
* — which lets the registry be stripped, and puts each nest target in the same
|
|
43
|
+
* chunk as the dictionary that references it.
|
|
44
|
+
*
|
|
45
|
+
* @param key - The dictionary key.
|
|
46
|
+
* @param nestedKeys - Keys of the dictionaries it references, transitively.
|
|
47
|
+
* @param format - Output module format.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```js
|
|
51
|
+
* import _dictionary from '../dashboard.json' with { type: 'json' };
|
|
52
|
+
* import _1a2b3c from '../common.json' with { type: 'json' };
|
|
53
|
+
*
|
|
54
|
+
* export default { ..._dictionary, nestedDictionaries: { 'common': _1a2b3c } };
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
const generateNestedDictionaryEntryPoint = (key, nestedKeys, format = "esm") => {
|
|
58
|
+
const sortedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));
|
|
59
|
+
const identifierOf = (nestedKey) => `_${require_utils_getPathHash.getPathHash(nestedKey)}`;
|
|
60
|
+
const importLines = sortedKeys.map((nestedKey) => format === "esm" ? `import ${identifierOf(nestedKey)} from '../${escapeJsLiteral(nestedKey)}.json' with { type: 'json' };` : `const ${identifierOf(nestedKey)} = require('../${escapeJsLiteral(nestedKey)}.json');`).join("\n");
|
|
61
|
+
const attachedEntries = sortedKeys.map((nestedKey) => ` '${escapeJsLiteral(nestedKey)}': ${identifierOf(nestedKey)}`).join(",\n");
|
|
62
|
+
const safeKey = escapeJsLiteral(key);
|
|
63
|
+
if (format === "esm") return `import _dictionary from '../${safeKey}.json' with { type: 'json' };\n${importLines}\n\nconst nestedDictionaries = {\n${attachedEntries}\n};\n\nexport default { ..._dictionary, nestedDictionaries };\n`;
|
|
64
|
+
return `const _dictionary = require('../${safeKey}.json');\n${importLines}\n\nconst nestedDictionaries = {\n${attachedEntries}\n};\n\nmodule.exports = { ..._dictionary, nestedDictionaries };\n`;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Writes one companion module per dictionary holding `nest()` references.
|
|
68
|
+
*
|
|
69
|
+
* @param nestedDictionaryGraph - Dictionary key → keys it nests, transitively.
|
|
70
|
+
* @param configuration - The resolved intlayer configuration.
|
|
71
|
+
* @param formats - Module formats to emit.
|
|
72
|
+
*/
|
|
73
|
+
const writeNestedDictionaries = async (nestedDictionaryGraph, configuration, formats = _intlayer_config_defaultValues.OUTPUT_FORMAT) => {
|
|
74
|
+
if (nestedDictionaryGraph.size === 0) return;
|
|
75
|
+
const { dictionariesDir } = configuration.system;
|
|
76
|
+
const nestedDir = (0, node_path.resolve)(dictionariesDir, NESTED_DICTIONARIES_SUBDIR);
|
|
77
|
+
await (0, node_fs_promises.mkdir)(nestedDir, { recursive: true });
|
|
78
|
+
await require_utils_parallelize.parallelize([...nestedDictionaryGraph.entries()].sort(([a], [b]) => a.localeCompare(b)), async ([key, nestedKeys]) => {
|
|
79
|
+
await require_utils_parallelize.parallelize(formats, async (format) => {
|
|
80
|
+
const extension = format === "cjs" ? "cjs" : "mjs";
|
|
81
|
+
const content = generateNestedDictionaryEntryPoint(key, [...nestedKeys], format);
|
|
82
|
+
const entryPath = getNestedDictionaryPath(dictionariesDir, key, extension);
|
|
83
|
+
(0, _intlayer_config_utils.assertPathWithin)(entryPath, nestedDir);
|
|
84
|
+
await require_writeFileIfChanged.writeFileIfChanged(entryPath, content).catch((error) => {
|
|
85
|
+
console.error(`Error creating nested ${(0, _intlayer_config_logger.colorizePath)(entryPath)}:`, error);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
exports.NESTED_DICTIONARIES_SUBDIR = NESTED_DICTIONARIES_SUBDIR;
|
|
93
|
+
exports.generateNestedDictionaryEntryPoint = generateNestedDictionaryEntryPoint;
|
|
94
|
+
exports.getNestedDictionaryPath = getNestedDictionaryPath;
|
|
95
|
+
exports.writeNestedDictionaries = writeNestedDictionaries;
|
|
96
|
+
//# sourceMappingURL=writeNestedDictionary.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeNestedDictionary.cjs","names":["getPathHash","OUTPUT_FORMAT","parallelize","writeFileIfChanged"],"sources":["../../../src/buildIntlayerDictionary/writeNestedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getPathHash } from '../utils/getPathHash';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\n\n/**\n * Subdirectory of `dictionariesDir` holding the companion modules. Nested under\n * the compiled dictionaries so both stay together and are cleaned as one, and\n * because the `**\\/*.json` globs listing compiled dictionaries never match the\n * `.mjs` / `.cjs` files written here.\n */\nexport const NESTED_DICTIONARIES_SUBDIR = 'nested';\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * module, so keys containing `'` or `\\` cannot break the emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/**\n * Path of the companion module carrying the `nest()` targets of a dictionary.\n *\n * Shared with the bundler plugins, which re-point the static import they inject\n * at a `useIntlayer` call site to this module whenever the dictionary has nest\n * targets.\n *\n * @param dictionariesDir - The compiled dictionaries directory.\n * @param key - The dictionary key.\n * @param extension - Module extension, `'mjs'` (default) or `'cjs'`.\n */\nexport const getNestedDictionaryPath = (\n dictionariesDir: string,\n key: string,\n extension: 'mjs' | 'cjs' = 'mjs'\n): string =>\n resolve(dictionariesDir, NESTED_DICTIONARIES_SUBDIR, `${key}.${extension}`);\n\n/**\n * Generates a companion module that re-exports a compiled dictionary with its\n * `nest()` targets attached.\n *\n * The optimizer imports this instead of the raw JSON, so `getNesting` resolves\n * the reference from `nestedDictionaries` rather from the global registry\n * — which lets the registry be stripped, and puts each nest target in the same\n * chunk as the dictionary that references it.\n *\n * @param key - The dictionary key.\n * @param nestedKeys - Keys of the dictionaries it references, transitively.\n * @param format - Output module format.\n *\n * @example\n * ```js\n * import _dictionary from '../dashboard.json' with { type: 'json' };\n * import _1a2b3c from '../common.json' with { type: 'json' };\n *\n * export default { ..._dictionary, nestedDictionaries: { 'common': _1a2b3c } };\n * ```\n */\nexport const generateNestedDictionaryEntryPoint = (\n key: string,\n nestedKeys: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n // Hash the key so the generated identifier is a valid one whatever the\n // dictionary key contains (dashes, dots, non-ASCII).\n const identifierOf = (nestedKey: string) => `_${getPathHash(nestedKey)}`;\n\n const importLines = sortedKeys\n .map((nestedKey) =>\n format === 'esm'\n ? `import ${identifierOf(nestedKey)} from '../${escapeJsLiteral(nestedKey)}.json' with { type: 'json' };`\n : `const ${identifierOf(nestedKey)} = require('../${escapeJsLiteral(nestedKey)}.json');`\n )\n .join('\\n');\n\n const attachedEntries = sortedKeys\n .map(\n (nestedKey) =>\n ` '${escapeJsLiteral(nestedKey)}': ${identifierOf(nestedKey)}`\n )\n .join(',\\n');\n\n const safeKey = escapeJsLiteral(key);\n\n if (format === 'esm') {\n return (\n `import _dictionary from '../${safeKey}.json' with { type: 'json' };\\n` +\n `${importLines}\\n\\n` +\n `const nestedDictionaries = {\\n${attachedEntries}\\n};\\n\\n` +\n `export default { ..._dictionary, nestedDictionaries };\\n`\n );\n }\n\n return (\n `const _dictionary = require('../${safeKey}.json');\\n` +\n `${importLines}\\n\\n` +\n `const nestedDictionaries = {\\n${attachedEntries}\\n};\\n\\n` +\n `module.exports = { ..._dictionary, nestedDictionaries };\\n`\n );\n};\n\n/**\n * Writes one companion module per dictionary holding `nest()` references.\n *\n * @param nestedDictionaryGraph - Dictionary key → keys it nests, transitively.\n * @param configuration - The resolved intlayer configuration.\n * @param formats - Module formats to emit.\n */\nexport const writeNestedDictionaries = async (\n nestedDictionaryGraph: Map<string, Set<string>>,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n if (nestedDictionaryGraph.size === 0) return;\n\n const { dictionariesDir } = configuration.system;\n const nestedDir = resolve(dictionariesDir, NESTED_DICTIONARIES_SUBDIR);\n\n await mkdir(nestedDir, { recursive: true });\n\n await parallelize(\n [...nestedDictionaryGraph.entries()].sort(([a], [b]) => a.localeCompare(b)),\n async ([key, nestedKeys]) => {\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateNestedDictionaryEntryPoint(\n key,\n [...nestedKeys],\n format\n );\n\n const entryPath = getNestedDictionaryPath(\n dictionariesDir,\n key,\n extension\n );\n assertPathWithin(entryPath, nestedDir);\n\n await writeFileIfChanged(entryPath, content).catch((error) => {\n console.error(\n `Error creating nested ${colorizePath(entryPath)}:`,\n error\n );\n });\n });\n }\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAa,6BAA6B;;;;;AAM1C,MAAM,mBAAmB,UACvB,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC,QAAQ,MAAM,KAAK;;;;;;;;;;;;AAalD,MAAa,2BACX,iBACA,KACA,YAA2B,iCAEnB,iBAAiB,4BAA4B,GAAG,IAAI,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;AAuB5E,MAAa,sCACX,KACA,YACA,SAAwB,UACb;CACX,MAAM,aAAa,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAIpE,MAAM,gBAAgB,cAAsB,IAAIA,sCAAY,SAAS;CAErE,MAAM,cAAc,WACjB,KAAK,cACJ,WAAW,QACP,UAAU,aAAa,SAAS,EAAE,YAAY,gBAAgB,SAAS,EAAE,iCACzE,SAAS,aAAa,SAAS,EAAE,iBAAiB,gBAAgB,SAAS,EAAE,SACnF,CAAC,CACA,KAAK,IAAI;CAEZ,MAAM,kBAAkB,WACrB,KACE,cACC,MAAM,gBAAgB,SAAS,EAAE,KAAK,aAAa,SAAS,GAChE,CAAC,CACA,KAAK,KAAK;CAEb,MAAM,UAAU,gBAAgB,GAAG;CAEnC,IAAI,WAAW,OACb,OACE,+BAA+B,QAAQ,iCACpC,YAAY,oCACkB,gBAAgB;CAKrD,OACE,mCAAmC,QAAQ,YACxC,YAAY,oCACkB,gBAAgB;AAGrD;;;;;;;;AASA,MAAa,0BAA0B,OACrC,uBACA,eACA,UAA6BC,iDACX;CAClB,IAAI,sBAAsB,SAAS,GAAG;CAEtC,MAAM,EAAE,oBAAoB,cAAc;CAC1C,MAAM,mCAAoB,iBAAiB,0BAA0B;CAErE,kCAAY,WAAW,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAMC,sCACJ,CAAC,GAAG,sBAAsB,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,GAC1E,OAAO,CAAC,KAAK,gBAAgB;EAC3B,MAAMA,sCAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,mCACd,KACA,CAAC,GAAG,UAAU,GACd,MACF;GAEA,MAAM,YAAY,wBAChB,iBACA,KACA,SACF;GACA,6CAAiB,WAAW,SAAS;GAErC,MAAMC,8CAAmB,WAAW,OAAO,CAAC,CAAC,OAAO,UAAU;IAC5D,QAAQ,MACN,mEAAsC,SAAS,EAAE,IACjD,KACF;GACF,CAAC;EACH,CAAC;CACH,CACF;AACF"}
|