@intlayer/core 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/cjs/deepTransformPlugins/getEditedContent.cjs +10 -6
- package/dist/cjs/deepTransformPlugins/getEditedContent.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getNestedDictionaryReferences.cjs +153 -0
- package/dist/cjs/dictionaryManipulator/getNestedDictionaryReferences.cjs.map +1 -0
- package/dist/cjs/dictionaryManipulator/index.cjs +16 -9
- package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs +4 -3
- package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs +1 -170
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionaryDeclaration.cjs +69 -0
- package/dist/cjs/dictionaryManipulator/qualifiedDictionaryDeclaration.cjs.map +1 -0
- package/dist/cjs/dictionaryManipulator/qualifiedDynamicLoader.cjs +115 -0
- package/dist/cjs/dictionaryManipulator/qualifiedDynamicLoader.cjs.map +1 -0
- package/dist/cjs/index.cjs +20 -9
- package/dist/cjs/interpreter/getContent/plugins.cjs +12 -1
- package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
- package/dist/cjs/interpreter/getDictionary.cjs +2 -1
- package/dist/cjs/interpreter/getDictionary.cjs.map +1 -1
- package/dist/cjs/interpreter/getNesting.optimized.cjs +59 -0
- package/dist/cjs/interpreter/getNesting.optimized.cjs.map +1 -0
- package/dist/cjs/localization/index.cjs +4 -0
- package/dist/cjs/localization/proxyMode.cjs +92 -0
- package/dist/cjs/localization/proxyMode.cjs.map +1 -0
- package/dist/esm/deepTransformPlugins/getEditedContent.mjs +10 -6
- package/dist/esm/deepTransformPlugins/getEditedContent.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getNestedDictionaryReferences.mjs +150 -0
- package/dist/esm/dictionaryManipulator/getNestedDictionaryReferences.mjs.map +1 -0
- package/dist/esm/dictionaryManipulator/index.mjs +5 -2
- package/dist/esm/dictionaryManipulator/mergeQualifiedDictionaries.mjs +2 -1
- package/dist/esm/dictionaryManipulator/mergeQualifiedDictionaries.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs +1 -162
- package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/qualifiedDictionaryDeclaration.mjs +64 -0
- package/dist/esm/dictionaryManipulator/qualifiedDictionaryDeclaration.mjs.map +1 -0
- package/dist/esm/dictionaryManipulator/qualifiedDynamicLoader.mjs +111 -0
- package/dist/esm/dictionaryManipulator/qualifiedDynamicLoader.mjs.map +1 -0
- package/dist/esm/index.mjs +6 -2
- package/dist/esm/interpreter/getContent/plugins.mjs +12 -1
- package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
- package/dist/esm/interpreter/getDictionary.mjs +2 -1
- package/dist/esm/interpreter/getDictionary.mjs.map +1 -1
- package/dist/esm/interpreter/getNesting.optimized.mjs +58 -0
- package/dist/esm/interpreter/getNesting.optimized.mjs.map +1 -0
- package/dist/esm/localization/index.mjs +2 -1
- package/dist/esm/localization/proxyMode.mjs +87 -0
- package/dist/esm/localization/proxyMode.mjs.map +1 -0
- package/dist/types/deepTransformPlugins/getEditedContent.d.ts.map +1 -1
- package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts +1 -0
- package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts +1 -0
- package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts +1 -0
- package/dist/types/dictionaryManipulator/getNestedDictionaryReferences.d.ts +62 -0
- package/dist/types/dictionaryManipulator/getNestedDictionaryReferences.d.ts.map +1 -0
- package/dist/types/dictionaryManipulator/index.d.ts +5 -2
- package/dist/types/dictionaryManipulator/mergeQualifiedDictionaries.d.ts.map +1 -1
- package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts +18 -126
- package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts.map +1 -1
- package/dist/types/dictionaryManipulator/qualifiedDictionaryDeclaration.d.ts +41 -0
- package/dist/types/dictionaryManipulator/qualifiedDictionaryDeclaration.d.ts.map +1 -0
- package/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +93 -0
- package/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts.map +1 -0
- package/dist/types/index.d.ts +6 -2
- package/dist/types/interpreter/getContent/plugins.d.ts +10 -0
- package/dist/types/interpreter/getContent/plugins.d.ts.map +1 -1
- package/dist/types/interpreter/getNesting.optimized.d.ts +33 -0
- package/dist/types/interpreter/getNesting.optimized.d.ts.map +1 -0
- package/dist/types/localization/index.d.ts +2 -1
- package/dist/types/localization/proxyMode.d.ts +92 -0
- package/dist/types/localization/proxyMode.d.ts.map +1 -0
- package/package.json +7 -7
|
@@ -4,8 +4,12 @@ let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
|
|
|
4
4
|
_intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
|
|
5
5
|
|
|
6
6
|
//#region src/deepTransformPlugins/getEditedContent.ts
|
|
7
|
-
|
|
8
|
-
const
|
|
7
|
+
/** Whether `node` is a plain (non-array) object, i.e. a content branch. */
|
|
8
|
+
const isRecordNode = (node) => typeof node === "object" && node !== null && !Array.isArray(node);
|
|
9
|
+
/** Whether `node` is a typed node, whatever its `nodeType`. */
|
|
10
|
+
const isTypedNode = (node) => isRecordNode(node) && typeof node.nodeType === "string";
|
|
11
|
+
/** Whether `node` is a `translation` node holding a locale map. */
|
|
12
|
+
const isTranslationNode = (node) => isTypedNode(node) && node.nodeType === _intlayer_types_nodeType.TRANSLATION && isRecordNode(node[_intlayer_types_nodeType.TRANSLATION]);
|
|
9
13
|
/** Structural equality for leaf source values (string / number / nested objects). */
|
|
10
14
|
const isSameValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
11
15
|
/**
|
|
@@ -15,8 +19,8 @@ const isSameValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
|
15
19
|
*/
|
|
16
20
|
const getEditedNode = (previous, next, defaultLocale) => {
|
|
17
21
|
if (isTranslationNode(next)) {
|
|
18
|
-
const nextValue = next[_intlayer_types_nodeType.TRANSLATION]
|
|
19
|
-
const previousValue = isTranslationNode(previous) ? previous[_intlayer_types_nodeType.TRANSLATION]
|
|
22
|
+
const nextValue = next[_intlayer_types_nodeType.TRANSLATION][defaultLocale];
|
|
23
|
+
const previousValue = isTranslationNode(previous) ? previous[_intlayer_types_nodeType.TRANSLATION][defaultLocale] : void 0;
|
|
20
24
|
if (typeof nextValue === "undefined") return;
|
|
21
25
|
if (isSameValue(previousValue, nextValue)) return;
|
|
22
26
|
return {
|
|
@@ -47,8 +51,8 @@ const getEditedNode = (previous, next, defaultLocale) => {
|
|
|
47
51
|
});
|
|
48
52
|
return hasChange ? result : void 0;
|
|
49
53
|
}
|
|
50
|
-
if (
|
|
51
|
-
const previousObject =
|
|
54
|
+
if (isRecordNode(next)) {
|
|
55
|
+
const previousObject = isRecordNode(previous) ? previous : void 0;
|
|
52
56
|
const result = {};
|
|
53
57
|
let hasChange = false;
|
|
54
58
|
for (const key of Object.keys(next)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEditedContent.cjs","names":["NodeTypes"],"sources":["../../../src/deepTransformPlugins/getEditedContent.ts"],"sourcesContent":["import type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/** A `translation` node, e.g. `{ nodeType: 'translation', translation: { en, fr } }`. */\ntype TranslationNode =
|
|
1
|
+
{"version":3,"file":"getEditedContent.cjs","names":["NodeTypes"],"sources":["../../../src/deepTransformPlugins/getEditedContent.ts"],"sourcesContent":["import type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport type { TypedNodeModel } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/**\n * Structural view of a dictionary content tree.\n *\n * `ContentNode` describes leaves and typed nodes only — the plain objects and\n * arrays that hold them are typed as `any` by the public `Dictionary['content']`.\n * Declaring those containers explicitly lets the diff walk a whole content tree\n * without casting at every step.\n */\ntype ContentTree = ContentNode | ContentTree[] | { [key: string]: ContentTree };\n\n/** A `translation` node, e.g. `{ nodeType: 'translation', translation: { en, fr } }`. */\ntype TranslationNode = TypedNodeModel<\n typeof NodeTypes.TRANSLATION,\n Record<string, ContentTree>\n>;\n\n/**\n * Any typed node — a wrapper holding its value under the key named by its own\n * `nodeType` (e.g. `{ nodeType: 'plural', plural: … }`).\n */\ntype TypedContentNode = {\n nodeType: string;\n [wrappedValueKey: string]: ContentTree;\n};\n\n/** Whether `node` is a plain (non-array) object, i.e. a content branch. */\nconst isRecordNode = (node: ContentTree): node is Record<string, ContentTree> =>\n typeof node === 'object' && node !== null && !Array.isArray(node);\n\n/** Whether `node` is a typed node, whatever its `nodeType`. */\nconst isTypedNode = (node: ContentTree): node is TypedContentNode =>\n isRecordNode(node) && typeof node.nodeType === 'string';\n\n/** Whether `node` is a `translation` node holding a locale map. */\nconst isTranslationNode = (node: ContentTree): node is TranslationNode =>\n isTypedNode(node) &&\n node.nodeType === NodeTypes.TRANSLATION &&\n isRecordNode(node[NodeTypes.TRANSLATION]);\n\n/** Structural equality for leaf source values (string / number / nested objects). */\nconst isSameValue = (a: ContentTree, b: ContentTree): boolean =>\n JSON.stringify(a) === JSON.stringify(b);\n\n/**\n * Recursively compares `next` against `previous` and returns the sub-tree of\n * `next` that holds only the nodes whose source-locale value was added or\n * changed. Returns `undefined` when nothing changed at this node.\n */\nconst getEditedNode = (\n previous: ContentTree,\n next: ContentTree,\n defaultLocale: LocalesValues\n): ContentTree | undefined => {\n // Translation node: compare the default-locale leaf only.\n if (isTranslationNode(next)) {\n const nextValue = next[NodeTypes.TRANSLATION][defaultLocale];\n const previousValue = isTranslationNode(previous)\n ? previous[NodeTypes.TRANSLATION][defaultLocale]\n : undefined;\n\n // Nothing to (re)translate if the source locale is absent.\n if (typeof nextValue === 'undefined') {\n return undefined;\n }\n\n // Include only when the source value was added or changed.\n if (isSameValue(previousValue, nextValue)) {\n return undefined;\n }\n\n // Reduce to the source locale only, so every target locale is regenerated.\n return {\n nodeType: NodeTypes.TRANSLATION,\n [NodeTypes.TRANSLATION]: { [defaultLocale]: nextValue },\n } satisfies TranslationNode;\n }\n\n // Other typed nodes (enumeration, condition, nested, …): recurse into the\n // wrapped value while preserving the wrapper so the partial stays valid.\n if (isTypedNode(next)) {\n const { nodeType } = next;\n const previousInner = isTypedNode(previous)\n ? previous[nodeType]\n : undefined;\n const editedInner = getEditedNode(\n previousInner,\n next[nodeType],\n defaultLocale\n );\n\n if (typeof editedInner === 'undefined') {\n return undefined;\n }\n\n return {\n nodeType,\n [nodeType]: editedInner,\n } satisfies TypedContentNode;\n }\n\n // Arrays: keep changed items reduced to source-only, unchanged items as-is to\n // preserve index alignment for `mergeDictionaries` (which merges by index).\n if (Array.isArray(next)) {\n const previousArray = Array.isArray(previous) ? previous : [];\n let hasChange = false;\n\n const result = next.map((child, index) => {\n const editedChild = getEditedNode(\n previousArray[index],\n child,\n defaultLocale\n );\n if (typeof editedChild !== 'undefined') {\n hasChange = true;\n return editedChild;\n }\n // Unchanged item: keep the full node. It already has every locale, so the\n // complete-mode translation pass skips it and the merge leaves it intact.\n return child;\n });\n\n return hasChange ? result : undefined;\n }\n\n // Plain objects: recurse into each key, keeping only changed branches.\n if (isRecordNode(next)) {\n const previousObject = isRecordNode(previous) ? previous : undefined;\n\n const result: Record<string, ContentTree> = {};\n let hasChange = false;\n\n for (const key of Object.keys(next)) {\n const editedChild = getEditedNode(\n previousObject?.[key],\n next[key],\n defaultLocale\n );\n if (typeof editedChild !== 'undefined') {\n result[key] = editedChild;\n hasChange = true;\n }\n }\n\n return hasChange ? result : undefined;\n }\n\n // Primitive leaves are not locale-aware on their own — nothing to translate.\n return undefined;\n};\n\n/**\n * Returns the partial content holding only the `translation` nodes whose\n * source (`defaultLocale`) value was added or changed between `previousContent`\n * and `newContent`. Each changed node is reduced to its source locale so that\n * every target locale is regenerated when the partial is translated.\n *\n * Returns `{}` (empty content) when no source value changed.\n *\n * @example\n * // default value of `title` changed → only `title` is returned, source-only\n * getEditedContent(\n * { title: t({ en: 'Old', fr: 'Vieux' }), body: t({ en: 'B', fr: 'B' }) },\n * { title: t({ en: 'New', fr: 'Vieux' }), body: t({ en: 'B', fr: 'B' }) },\n * 'en'\n * ); // → { title: { nodeType: 'translation', translation: { en: 'New' } } }\n */\nexport const getEditedContent = (\n previousContent: ContentNode | undefined,\n newContent: ContentNode,\n defaultLocale: LocalesValues\n): ContentNode =>\n // The result is a sub-tree of `newContent`, so narrowing the structural\n // `ContentTree` back to the public `ContentNode` is sound: only the plain\n // containers `ContentNode` leaves untyped are dropped from the type.\n (getEditedNode(previousContent, newContent, defaultLocale) ??\n {}) as ContentNode;\n\n/**\n * Dictionary-level wrapper around {@link getEditedContent}. Returns a partial\n * dictionary (same `key`) whose `content` holds only the changed source nodes.\n *\n * @param previousDictionary - Dictionary state before the edit.\n * @param newDictionary - Dictionary state after the edit.\n * @param defaultLocale - The source locale to diff against.\n */\nexport const getEditedDictionary = (\n previousDictionary: Dictionary | undefined,\n newDictionary: Dictionary,\n defaultLocale: LocalesValues\n): Dictionary => ({\n ...newDictionary,\n content: getEditedContent(\n previousDictionary?.content,\n newDictionary.content,\n defaultLocale\n ),\n});\n"],"mappings":";;;;;;;AA+BA,MAAM,gBAAgB,SACpB,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI;;AAGlE,MAAM,eAAe,SACnB,aAAa,IAAI,KAAK,OAAO,KAAK,aAAa;;AAGjD,MAAM,qBAAqB,SACzB,YAAY,IAAI,KAChB,KAAK,aAAaA,yBAAU,eAC5B,aAAa,KAAKA,yBAAU,YAAY;;AAG1C,MAAM,eAAe,GAAgB,MACnC,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;;;;;;AAOxC,MAAM,iBACJ,UACA,MACA,kBAC4B;CAE5B,IAAI,kBAAkB,IAAI,GAAG;EAC3B,MAAM,YAAY,KAAKA,yBAAU,YAAY,CAAC;EAC9C,MAAM,gBAAgB,kBAAkB,QAAQ,IAC5C,SAASA,yBAAU,YAAY,CAAC,iBAChC;EAGJ,IAAI,OAAO,cAAc,aACvB;EAIF,IAAI,YAAY,eAAe,SAAS,GACtC;EAIF,OAAO;GACL,UAAUA,yBAAU;IACnBA,yBAAU,cAAc,GAAG,gBAAgB,UAAU;EACxD;CACF;CAIA,IAAI,YAAY,IAAI,GAAG;EACrB,MAAM,EAAE,aAAa;EACrB,MAAM,gBAAgB,YAAY,QAAQ,IACtC,SAAS,YACT;EACJ,MAAM,cAAc,cAClB,eACA,KAAK,WACL,aACF;EAEA,IAAI,OAAO,gBAAgB,aACzB;EAGF,OAAO;GACL;IACC,WAAW;EACd;CACF;CAIA,IAAI,MAAM,QAAQ,IAAI,GAAG;EACvB,MAAM,gBAAgB,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;EAC5D,IAAI,YAAY;EAEhB,MAAM,SAAS,KAAK,KAAK,OAAO,UAAU;GACxC,MAAM,cAAc,cAClB,cAAc,QACd,OACA,aACF;GACA,IAAI,OAAO,gBAAgB,aAAa;IACtC,YAAY;IACZ,OAAO;GACT;GAGA,OAAO;EACT,CAAC;EAED,OAAO,YAAY,SAAS;CAC9B;CAGA,IAAI,aAAa,IAAI,GAAG;EACtB,MAAM,iBAAiB,aAAa,QAAQ,IAAI,WAAW;EAE3D,MAAM,SAAsC,CAAC;EAC7C,IAAI,YAAY;EAEhB,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,GAAG;GACnC,MAAM,cAAc,cAClB,iBAAiB,MACjB,KAAK,MACL,aACF;GACA,IAAI,OAAO,gBAAgB,aAAa;IACtC,OAAO,OAAO;IACd,YAAY;GACd;EACF;EAEA,OAAO,YAAY,SAAS;CAC9B;AAIF;;;;;;;;;;;;;;;;;AAkBA,MAAa,oBACX,iBACA,YACA,kBAKC,cAAc,iBAAiB,YAAY,aAAa,KACvD,CAAC;;;;;;;;;AAUL,MAAa,uBACX,oBACA,eACA,mBACgB;CAChB,GAAG;CACH,SAAS,iBACP,oBAAoB,SACpB,cAAc,SACd,aACF;AACF"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
|
|
3
|
+
|
|
4
|
+
//#region src/dictionaryManipulator/getNestedDictionaryReferences.ts
|
|
5
|
+
/**
|
|
6
|
+
* Compact alias some minified pipelines emit in place of `nodeType: 'nested'`.
|
|
7
|
+
* Matched defensively so the scan keeps working on already-minified content.
|
|
8
|
+
*/
|
|
9
|
+
const MINIFIED_NESTED_NODE_TYPE = "n";
|
|
10
|
+
/**
|
|
11
|
+
* Narrows a value to a traversable object (plain object or array). `null` is
|
|
12
|
+
* excluded even though `typeof null === 'object'`.
|
|
13
|
+
*/
|
|
14
|
+
const isTraversable = (value) => typeof value === "object" && value !== null;
|
|
15
|
+
/**
|
|
16
|
+
* Records one `nest()` reference, widening the entry to `'all'` as soon as a
|
|
17
|
+
* reference targets the whole dictionary.
|
|
18
|
+
*/
|
|
19
|
+
const addNestedReference = (references, dictionaryKey, path) => {
|
|
20
|
+
const existingReference = references.get(dictionaryKey);
|
|
21
|
+
if (existingReference === "all") return;
|
|
22
|
+
const rootField = path?.split(".")[0];
|
|
23
|
+
if (!rootField) {
|
|
24
|
+
references.set(dictionaryKey, "all");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (existingReference) {
|
|
28
|
+
existingReference.add(rootField);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
references.set(dictionaryKey, /* @__PURE__ */ new Set([rootField]));
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Walks a dictionary tree and collects every dictionary referenced through a
|
|
35
|
+
* `nest()` node, together with the top-level fields those references read.
|
|
36
|
+
*
|
|
37
|
+
* The walk is iterative (no recursion depth limit) and guards against shared
|
|
38
|
+
* or circular references, so it is safe on both compiled JSON and in-memory
|
|
39
|
+
* dictionaries.
|
|
40
|
+
*
|
|
41
|
+
* @param dictionaries - Dictionary objects (or any content subtree) to scan.
|
|
42
|
+
* @returns Map of nest-target dictionary key → referenced top-level fields.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // dashboard.content.ts → { period: nest('common', 'period') }
|
|
47
|
+
* getNestedDictionaryReferences([dashboardDictionary]);
|
|
48
|
+
* // Map { 'common' => Set { 'period' } }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
const getNestedDictionaryReferences = (dictionaries) => {
|
|
52
|
+
const references = /* @__PURE__ */ new Map();
|
|
53
|
+
const stack = [...dictionaries];
|
|
54
|
+
const visitedNodes = /* @__PURE__ */ new Set();
|
|
55
|
+
while (stack.length > 0) {
|
|
56
|
+
const node = stack.pop();
|
|
57
|
+
if (!isTraversable(node)) continue;
|
|
58
|
+
if (visitedNodes.has(node)) continue;
|
|
59
|
+
visitedNodes.add(node);
|
|
60
|
+
if (Array.isArray(node)) {
|
|
61
|
+
stack.push(...node);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const { nodeType } = node;
|
|
65
|
+
if (nodeType === _intlayer_types_nodeType.NESTED || nodeType === MINIFIED_NESTED_NODE_TYPE) {
|
|
66
|
+
const nestedState = node[nodeType];
|
|
67
|
+
if (isTraversable(nestedState)) {
|
|
68
|
+
const { dictionaryKey, path } = nestedState;
|
|
69
|
+
if (typeof dictionaryKey === "string") addNestedReference(references, dictionaryKey, typeof path === "string" ? path : void 0);
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
stack.push(...Object.values(node));
|
|
74
|
+
}
|
|
75
|
+
return references;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Keys of every dictionary referenced through a `nest()` node.
|
|
79
|
+
*
|
|
80
|
+
* @param dictionaries - Dictionary objects (or any content subtree) to scan.
|
|
81
|
+
* @returns Set of nest-target dictionary keys.
|
|
82
|
+
*/
|
|
83
|
+
const getNestedDictionaryKeys = (dictionaries) => new Set(getNestedDictionaryReferences(dictionaries).keys());
|
|
84
|
+
/**
|
|
85
|
+
* Expands direct nest edges into their transitive closure, so a consumer that
|
|
86
|
+
* nests a dictionary which itself nests another ends up depending on both.
|
|
87
|
+
*
|
|
88
|
+
* Self-references and cycles are absorbed: a key never appears in its own
|
|
89
|
+
* dependency set, and the walk terminates on cyclic graphs.
|
|
90
|
+
*/
|
|
91
|
+
const closeOverNestedEdges = (directEdges) => {
|
|
92
|
+
const closedEdges = /* @__PURE__ */ new Map();
|
|
93
|
+
for (const [consumerKey, directTargets] of directEdges) {
|
|
94
|
+
const allTargets = /* @__PURE__ */ new Set();
|
|
95
|
+
const pending = [...directTargets];
|
|
96
|
+
while (pending.length > 0) {
|
|
97
|
+
const targetKey = pending.pop();
|
|
98
|
+
if (targetKey === consumerKey) continue;
|
|
99
|
+
if (allTargets.has(targetKey)) continue;
|
|
100
|
+
allTargets.add(targetKey);
|
|
101
|
+
const transitiveTargets = directEdges.get(targetKey);
|
|
102
|
+
if (transitiveTargets) pending.push(...transitiveTargets);
|
|
103
|
+
}
|
|
104
|
+
closedEdges.set(consumerKey, allTargets);
|
|
105
|
+
}
|
|
106
|
+
return closedEdges;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Builds the `nest()` dependency graph of a set of dictionaries: for each
|
|
110
|
+
* dictionary key, the keys of every dictionary it needs in order to resolve its
|
|
111
|
+
* nested nodes, transitively.
|
|
112
|
+
*
|
|
113
|
+
* The build optimization uses this to attach the nest targets to the dictionary
|
|
114
|
+
* artifact itself, so `nest()` resolves from a local reference and the target
|
|
115
|
+
* lands in the same chunk (or the same lazy per-locale loader) as the
|
|
116
|
+
* dictionary referencing it.
|
|
117
|
+
*
|
|
118
|
+
* Dictionaries without nested nodes are absent from the result.
|
|
119
|
+
*
|
|
120
|
+
* @param dictionaries - Compiled dictionaries to scan; each must carry its `key`.
|
|
121
|
+
* @returns Map of dictionary key → keys it depends on through `nest()`.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* // dashboard nests common, common nests labels
|
|
126
|
+
* getNestedDictionaryGraph([dashboard, common]);
|
|
127
|
+
* // Map { 'dashboard' => Set { 'common', 'labels' }, 'common' => Set { 'labels' } }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
const getNestedDictionaryGraph = (dictionaries) => {
|
|
131
|
+
const directEdges = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const dictionary of dictionaries) {
|
|
133
|
+
if (!isTraversable(dictionary)) continue;
|
|
134
|
+
const { key } = dictionary;
|
|
135
|
+
if (typeof key !== "string") continue;
|
|
136
|
+
const targets = getNestedDictionaryKeys([dictionary]);
|
|
137
|
+
targets.delete(key);
|
|
138
|
+
if (targets.size === 0) continue;
|
|
139
|
+
const existingTargets = directEdges.get(key);
|
|
140
|
+
if (existingTargets) {
|
|
141
|
+
for (const target of targets) existingTargets.add(target);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
directEdges.set(key, targets);
|
|
145
|
+
}
|
|
146
|
+
return closeOverNestedEdges(directEdges);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
exports.getNestedDictionaryGraph = getNestedDictionaryGraph;
|
|
151
|
+
exports.getNestedDictionaryKeys = getNestedDictionaryKeys;
|
|
152
|
+
exports.getNestedDictionaryReferences = getNestedDictionaryReferences;
|
|
153
|
+
//# sourceMappingURL=getNestedDictionaryReferences.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getNestedDictionaryReferences.cjs","names":["NESTED"],"sources":["../../../src/dictionaryManipulator/getNestedDictionaryReferences.ts"],"sourcesContent":["import { NESTED } from '@intlayer/types/nodeType';\n\n/**\n * Top-level content fields of a nest target that are referenced through\n * `nest()` nodes.\n *\n * `'all'` means at least one reference targets the whole dictionary\n * (`nest('common')` without a path), so no field of that dictionary may be\n * dropped.\n */\nexport type NestedFieldReferences = Set<string> | 'all';\n\n/**\n * Compact alias some minified pipelines emit in place of `nodeType: 'nested'`.\n * Matched defensively so the scan keeps working on already-minified content.\n */\nconst MINIFIED_NESTED_NODE_TYPE = 'n';\n\ntype UnknownRecord = Record<string, unknown>;\n\n/**\n * Narrows a value to a traversable object (plain object or array). `null` is\n * excluded even though `typeof null === 'object'`.\n */\nconst isTraversable = (value: unknown): value is UnknownRecord =>\n typeof value === 'object' && value !== null;\n\n/**\n * Records one `nest()` reference, widening the entry to `'all'` as soon as a\n * reference targets the whole dictionary.\n */\nconst addNestedReference = (\n references: Map<string, NestedFieldReferences>,\n dictionaryKey: string,\n path: string | undefined\n): void => {\n const existingReference = references.get(dictionaryKey);\n\n if (existingReference === 'all') return;\n\n // `getNesting` returns the whole dictionary when no path is given, and also\n // falls back to it when the path cannot be resolved — both cases require\n // every field to stay available.\n const rootField = path?.split('.')[0];\n\n if (!rootField) {\n references.set(dictionaryKey, 'all');\n return;\n }\n\n if (existingReference) {\n existingReference.add(rootField);\n return;\n }\n\n references.set(dictionaryKey, new Set([rootField]));\n};\n\n/**\n * Walks a dictionary tree and collects every dictionary referenced through a\n * `nest()` node, together with the top-level fields those references read.\n *\n * The walk is iterative (no recursion depth limit) and guards against shared\n * or circular references, so it is safe on both compiled JSON and in-memory\n * dictionaries.\n *\n * @param dictionaries - Dictionary objects (or any content subtree) to scan.\n * @returns Map of nest-target dictionary key → referenced top-level fields.\n *\n * @example\n * ```ts\n * // dashboard.content.ts → { period: nest('common', 'period') }\n * getNestedDictionaryReferences([dashboardDictionary]);\n * // Map { 'common' => Set { 'period' } }\n * ```\n */\nexport const getNestedDictionaryReferences = (\n dictionaries: Iterable<unknown>\n): Map<string, NestedFieldReferences> => {\n const references = new Map<string, NestedFieldReferences>();\n const stack: unknown[] = [...dictionaries];\n const visitedNodes = new Set<object>();\n\n while (stack.length > 0) {\n const node = stack.pop();\n\n if (!isTraversable(node)) continue;\n if (visitedNodes.has(node)) continue;\n visitedNodes.add(node);\n\n if (Array.isArray(node)) {\n stack.push(...node);\n continue;\n }\n\n const { nodeType } = node;\n\n if (nodeType === NESTED || nodeType === MINIFIED_NESTED_NODE_TYPE) {\n const nestedState = node[nodeType];\n\n if (isTraversable(nestedState)) {\n const { dictionaryKey, path } = nestedState;\n\n if (typeof dictionaryKey === 'string') {\n addNestedReference(\n references,\n dictionaryKey,\n typeof path === 'string' ? path : undefined\n );\n }\n }\n\n // A nested node only carries the reference descriptor — no sub-content.\n continue;\n }\n\n stack.push(...Object.values(node));\n }\n\n return references;\n};\n\n/**\n * Keys of every dictionary referenced through a `nest()` node.\n *\n * @param dictionaries - Dictionary objects (or any content subtree) to scan.\n * @returns Set of nest-target dictionary keys.\n */\nexport const getNestedDictionaryKeys = (\n dictionaries: Iterable<unknown>\n): Set<string> => new Set(getNestedDictionaryReferences(dictionaries).keys());\n\n/**\n * Expands direct nest edges into their transitive closure, so a consumer that\n * nests a dictionary which itself nests another ends up depending on both.\n *\n * Self-references and cycles are absorbed: a key never appears in its own\n * dependency set, and the walk terminates on cyclic graphs.\n */\nconst closeOverNestedEdges = (\n directEdges: Map<string, Set<string>>\n): Map<string, Set<string>> => {\n const closedEdges = new Map<string, Set<string>>();\n\n for (const [consumerKey, directTargets] of directEdges) {\n const allTargets = new Set<string>();\n const pending = [...directTargets];\n\n while (pending.length > 0) {\n const targetKey = pending.pop()!;\n\n if (targetKey === consumerKey) continue;\n if (allTargets.has(targetKey)) continue;\n allTargets.add(targetKey);\n\n const transitiveTargets = directEdges.get(targetKey);\n if (transitiveTargets) pending.push(...transitiveTargets);\n }\n\n closedEdges.set(consumerKey, allTargets);\n }\n\n return closedEdges;\n};\n\n/**\n * Builds the `nest()` dependency graph of a set of dictionaries: for each\n * dictionary key, the keys of every dictionary it needs in order to resolve its\n * nested nodes, transitively.\n *\n * The build optimization uses this to attach the nest targets to the dictionary\n * artifact itself, so `nest()` resolves from a local reference and the target\n * lands in the same chunk (or the same lazy per-locale loader) as the\n * dictionary referencing it.\n *\n * Dictionaries without nested nodes are absent from the result.\n *\n * @param dictionaries - Compiled dictionaries to scan; each must carry its `key`.\n * @returns Map of dictionary key → keys it depends on through `nest()`.\n *\n * @example\n * ```ts\n * // dashboard nests common, common nests labels\n * getNestedDictionaryGraph([dashboard, common]);\n * // Map { 'dashboard' => Set { 'common', 'labels' }, 'common' => Set { 'labels' } }\n * ```\n */\nexport const getNestedDictionaryGraph = (\n dictionaries: Iterable<unknown>\n): Map<string, Set<string>> => {\n const directEdges = new Map<string, Set<string>>();\n\n for (const dictionary of dictionaries) {\n if (!isTraversable(dictionary)) continue;\n\n const { key } = dictionary;\n if (typeof key !== 'string') continue;\n\n const targets = getNestedDictionaryKeys([dictionary]);\n targets.delete(key);\n\n if (targets.size === 0) continue;\n\n // Several compiled entries can share a key (qualified groups); merge them.\n const existingTargets = directEdges.get(key);\n if (existingTargets) {\n for (const target of targets) existingTargets.add(target);\n continue;\n }\n\n directEdges.set(key, targets);\n }\n\n return closeOverNestedEdges(directEdges);\n};\n"],"mappings":";;;;;;;;AAgBA,MAAM,4BAA4B;;;;;AAQlC,MAAM,iBAAiB,UACrB,OAAO,UAAU,YAAY,UAAU;;;;;AAMzC,MAAM,sBACJ,YACA,eACA,SACS;CACT,MAAM,oBAAoB,WAAW,IAAI,aAAa;CAEtD,IAAI,sBAAsB,OAAO;CAKjC,MAAM,YAAY,MAAM,MAAM,GAAG,CAAC,CAAC;CAEnC,IAAI,CAAC,WAAW;EACd,WAAW,IAAI,eAAe,KAAK;EACnC;CACF;CAEA,IAAI,mBAAmB;EACrB,kBAAkB,IAAI,SAAS;EAC/B;CACF;CAEA,WAAW,IAAI,+BAAe,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;AACpD;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,iCACX,iBACuC;CACvC,MAAM,6BAAa,IAAI,IAAmC;CAC1D,MAAM,QAAmB,CAAC,GAAG,YAAY;CACzC,MAAM,+BAAe,IAAI,IAAY;CAErC,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,OAAO,MAAM,IAAI;EAEvB,IAAI,CAAC,cAAc,IAAI,GAAG;EAC1B,IAAI,aAAa,IAAI,IAAI,GAAG;EAC5B,aAAa,IAAI,IAAI;EAErB,IAAI,MAAM,QAAQ,IAAI,GAAG;GACvB,MAAM,KAAK,GAAG,IAAI;GAClB;EACF;EAEA,MAAM,EAAE,aAAa;EAErB,IAAI,aAAaA,mCAAU,aAAa,2BAA2B;GACjE,MAAM,cAAc,KAAK;GAEzB,IAAI,cAAc,WAAW,GAAG;IAC9B,MAAM,EAAE,eAAe,SAAS;IAEhC,IAAI,OAAO,kBAAkB,UAC3B,mBACE,YACA,eACA,OAAO,SAAS,WAAW,OAAO,MACpC;GAEJ;GAGA;EACF;EAEA,MAAM,KAAK,GAAG,OAAO,OAAO,IAAI,CAAC;CACnC;CAEA,OAAO;AACT;;;;;;;AAQA,MAAa,2BACX,iBACgB,IAAI,IAAI,8BAA8B,YAAY,CAAC,CAAC,KAAK,CAAC;;;;;;;;AAS5E,MAAM,wBACJ,gBAC6B;CAC7B,MAAM,8BAAc,IAAI,IAAyB;CAEjD,KAAK,MAAM,CAAC,aAAa,kBAAkB,aAAa;EACtD,MAAM,6BAAa,IAAI,IAAY;EACnC,MAAM,UAAU,CAAC,GAAG,aAAa;EAEjC,OAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,YAAY,QAAQ,IAAI;GAE9B,IAAI,cAAc,aAAa;GAC/B,IAAI,WAAW,IAAI,SAAS,GAAG;GAC/B,WAAW,IAAI,SAAS;GAExB,MAAM,oBAAoB,YAAY,IAAI,SAAS;GACnD,IAAI,mBAAmB,QAAQ,KAAK,GAAG,iBAAiB;EAC1D;EAEA,YAAY,IAAI,aAAa,UAAU;CACzC;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,4BACX,iBAC6B;CAC7B,MAAM,8BAAc,IAAI,IAAyB;CAEjD,KAAK,MAAM,cAAc,cAAc;EACrC,IAAI,CAAC,cAAc,UAAU,GAAG;EAEhC,MAAM,EAAE,QAAQ;EAChB,IAAI,OAAO,QAAQ,UAAU;EAE7B,MAAM,UAAU,wBAAwB,CAAC,UAAU,CAAC;EACpD,QAAQ,OAAO,GAAG;EAElB,IAAI,QAAQ,SAAS,GAAG;EAGxB,MAAM,kBAAkB,YAAY,IAAI,GAAG;EAC3C,IAAI,iBAAiB;GACnB,KAAK,MAAM,UAAU,SAAS,gBAAgB,IAAI,MAAM;GACxD;EACF;EAEA,YAAY,IAAI,KAAK,OAAO;CAC9B;CAEA,OAAO,qBAAqB,WAAW;AACzC"}
|
|
@@ -4,33 +4,39 @@ const require_dictionaryManipulator_editDictionaryByKeyPath = require('./editDic
|
|
|
4
4
|
const require_dictionaryManipulator_getContentNodeByKeyPath = require('./getContentNodeByKeyPath.cjs');
|
|
5
5
|
const require_dictionaryManipulator_getDefaultNode = require('./getDefaultNode.cjs');
|
|
6
6
|
const require_dictionaryManipulator_getEmptyNode = require('./getEmptyNode.cjs');
|
|
7
|
+
const require_dictionaryManipulator_getNestedDictionaryReferences = require('./getNestedDictionaryReferences.cjs');
|
|
7
8
|
const require_dictionaryManipulator_getNodeChildren = require('./getNodeChildren.cjs');
|
|
8
9
|
const require_dictionaryManipulator_getNodeType = require('./getNodeType.cjs');
|
|
9
10
|
const require_dictionaryManipulator_mergeDictionaries = require('./mergeDictionaries.cjs');
|
|
11
|
+
const require_dictionaryManipulator_qualifiedDictionaryDeclaration = require('./qualifiedDictionaryDeclaration.cjs');
|
|
10
12
|
const require_dictionaryManipulator_mergeQualifiedDictionaries = require('./mergeQualifiedDictionaries.cjs');
|
|
11
13
|
const require_dictionaryManipulator_orderDictionaries = require('./orderDictionaries.cjs');
|
|
12
14
|
const require_dictionaryManipulator_normalizeDictionary = require('./normalizeDictionary.cjs');
|
|
15
|
+
const require_dictionaryManipulator_qualifiedDynamicLoader = require('./qualifiedDynamicLoader.cjs');
|
|
13
16
|
const require_dictionaryManipulator_removeContentNodeByKeyPath = require('./removeContentNodeByKeyPath.cjs');
|
|
14
17
|
const require_dictionaryManipulator_renameContentNodeByKeyPath = require('./renameContentNodeByKeyPath.cjs');
|
|
15
18
|
const require_dictionaryManipulator_updateNodeChildren = require('./updateNodeChildren.cjs');
|
|
16
19
|
|
|
17
20
|
exports.COMPOSITE_ID_SEPARATOR = require_dictionaryManipulator_qualifiedDictionary.COMPOSITE_ID_SEPARATOR;
|
|
18
21
|
exports.DEFAULT_VARIANT_ID = require_dictionaryManipulator_qualifiedDictionary.DEFAULT_VARIANT_ID;
|
|
19
|
-
exports.QUALIFIER_DYNAMIC_TYPES_KEY =
|
|
20
|
-
exports.QUALIFIER_ORDER =
|
|
22
|
+
exports.QUALIFIER_DYNAMIC_TYPES_KEY = require_dictionaryManipulator_qualifiedDynamicLoader.QUALIFIER_DYNAMIC_TYPES_KEY;
|
|
23
|
+
exports.QUALIFIER_ORDER = require_dictionaryManipulator_qualifiedDictionaryDeclaration.QUALIFIER_ORDER;
|
|
21
24
|
exports.editDictionaryByKeyPath = require_dictionaryManipulator_editDictionaryByKeyPath.editDictionaryByKeyPath;
|
|
22
25
|
exports.getContentNodeByKeyPath = require_dictionaryManipulator_getContentNodeByKeyPath.getContentNodeByKeyPath;
|
|
23
26
|
exports.getDefaultNode = require_dictionaryManipulator_getDefaultNode.getDefaultNode;
|
|
24
|
-
exports.getDictionaryCompositeIds =
|
|
25
|
-
exports.getDictionaryQualifierIds =
|
|
26
|
-
exports.getDictionaryQualifierTypes =
|
|
27
|
+
exports.getDictionaryCompositeIds = require_dictionaryManipulator_qualifiedDictionaryDeclaration.getDictionaryCompositeIds;
|
|
28
|
+
exports.getDictionaryQualifierIds = require_dictionaryManipulator_qualifiedDictionaryDeclaration.getDictionaryQualifierIds;
|
|
29
|
+
exports.getDictionaryQualifierTypes = require_dictionaryManipulator_qualifiedDictionaryDeclaration.getDictionaryQualifierTypes;
|
|
27
30
|
exports.getDictionarySelectorCacheKey = require_dictionaryManipulator_qualifiedDictionary.getDictionarySelectorCacheKey;
|
|
28
31
|
exports.getEmptyNode = require_dictionaryManipulator_getEmptyNode.getEmptyNode;
|
|
32
|
+
exports.getNestedDictionaryGraph = require_dictionaryManipulator_getNestedDictionaryReferences.getNestedDictionaryGraph;
|
|
33
|
+
exports.getNestedDictionaryKeys = require_dictionaryManipulator_getNestedDictionaryReferences.getNestedDictionaryKeys;
|
|
34
|
+
exports.getNestedDictionaryReferences = require_dictionaryManipulator_getNestedDictionaryReferences.getNestedDictionaryReferences;
|
|
29
35
|
exports.getNodeChildren = require_dictionaryManipulator_getNodeChildren.getNodeChildren;
|
|
30
36
|
exports.getNodeType = require_dictionaryManipulator_getNodeType.getNodeType;
|
|
31
|
-
exports.getVariantIds =
|
|
37
|
+
exports.getVariantIds = require_dictionaryManipulator_qualifiedDictionaryDeclaration.getVariantIds;
|
|
32
38
|
exports.isQualifiedDictionaryGroup = require_dictionaryManipulator_qualifiedDictionary.isQualifiedDictionaryGroup;
|
|
33
|
-
exports.isQualifiedDynamicLoaderMap =
|
|
39
|
+
exports.isQualifiedDynamicLoaderMap = require_dictionaryManipulator_qualifiedDynamicLoader.isQualifiedDynamicLoaderMap;
|
|
34
40
|
exports.mergeDictionaries = require_dictionaryManipulator_mergeDictionaries.mergeDictionaries;
|
|
35
41
|
exports.mergeQualifiedDictionaries = require_dictionaryManipulator_mergeQualifiedDictionaries.mergeQualifiedDictionaries;
|
|
36
42
|
exports.normalizeDictionaries = require_dictionaryManipulator_normalizeDictionary.normalizeDictionaries;
|
|
@@ -41,10 +47,11 @@ exports.reconstructQualifiedEntry = require_dictionaryManipulator_qualifiedDicti
|
|
|
41
47
|
exports.removeContentNodeByKeyPath = require_dictionaryManipulator_removeContentNodeByKeyPath.removeContentNodeByKeyPath;
|
|
42
48
|
exports.renameContentNodeByKeyPath = require_dictionaryManipulator_renameContentNodeByKeyPath.renameContentNodeByKeyPath;
|
|
43
49
|
exports.resolveDictionaryArgument = require_dictionaryManipulator_qualifiedDictionary.resolveDictionaryArgument;
|
|
50
|
+
exports.resolveEffectiveVariantId = require_dictionaryManipulator_qualifiedDictionary.resolveEffectiveVariantId;
|
|
44
51
|
exports.resolveProviderVariant = require_dictionaryManipulator_qualifiedDictionary.resolveProviderVariant;
|
|
45
52
|
exports.resolveQualifiedDictionary = require_dictionaryManipulator_qualifiedDictionary.resolveQualifiedDictionary;
|
|
46
|
-
exports.resolveQualifiedDynamicContent =
|
|
47
|
-
exports.resolveQualifiedDynamicContentAsync =
|
|
53
|
+
exports.resolveQualifiedDynamicContent = require_dictionaryManipulator_qualifiedDynamicLoader.resolveQualifiedDynamicContent;
|
|
54
|
+
exports.resolveQualifiedDynamicContentAsync = require_dictionaryManipulator_qualifiedDynamicLoader.resolveQualifiedDynamicContentAsync;
|
|
48
55
|
exports.serializeVariant = require_dictionaryManipulator_qualifiedDictionary.serializeVariant;
|
|
49
56
|
exports.serializeVariantChain = require_dictionaryManipulator_qualifiedDictionary.serializeVariantChain;
|
|
50
57
|
exports.updateNodeChildren = require_dictionaryManipulator_updateNodeChildren.updateNodeChildren;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_dictionaryManipulator_qualifiedDictionary = require('./qualifiedDictionary.cjs');
|
|
3
3
|
const require_dictionaryManipulator_mergeDictionaries = require('./mergeDictionaries.cjs');
|
|
4
|
+
const require_dictionaryManipulator_qualifiedDictionaryDeclaration = require('./qualifiedDictionaryDeclaration.cjs');
|
|
4
5
|
let _intlayer_config_built = require("@intlayer/config/built");
|
|
5
6
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
6
7
|
|
|
@@ -24,10 +25,10 @@ let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
|
24
25
|
* declares only a subset is ambiguous and is rejected with an error log.
|
|
25
26
|
*/
|
|
26
27
|
const mergeQualifiedDictionaries = (dictionaries) => {
|
|
27
|
-
const perDictionaryTypes = dictionaries.map(
|
|
28
|
+
const perDictionaryTypes = dictionaries.map(require_dictionaryManipulator_qualifiedDictionaryDeclaration.getDictionaryQualifierTypes);
|
|
28
29
|
const declaredDimensions = /* @__PURE__ */ new Set();
|
|
29
30
|
for (const types of perDictionaryTypes) for (const type of types) declaredDimensions.add(type);
|
|
30
|
-
const groupQualifierTypes =
|
|
31
|
+
const groupQualifierTypes = require_dictionaryManipulator_qualifiedDictionaryDeclaration.QUALIFIER_ORDER.filter((qualifierType) => declaredDimensions.has(qualifierType));
|
|
31
32
|
if (groupQualifierTypes.length === 0) return require_dictionaryManipulator_mergeDictionaries.mergeDictionaries(dictionaries);
|
|
32
33
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)({ log: _intlayer_config_built.log });
|
|
33
34
|
const baseDictionaries = [];
|
|
@@ -37,7 +38,7 @@ const mergeQualifiedDictionaries = (dictionaries) => {
|
|
|
37
38
|
baseDictionaries.push(dictionary);
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
|
-
const compositeIds =
|
|
41
|
+
const compositeIds = require_dictionaryManipulator_qualifiedDictionaryDeclaration.getDictionaryCompositeIds(dictionary, groupQualifierTypes);
|
|
41
42
|
if (compositeIds === void 0) {
|
|
42
43
|
appLogger(`Dictionary ${(0, _intlayer_config_logger.colorizeKey)(dictionary.key)} declares (${perDictionaryTypes[index].join(", ")}) but the key's dimensions are (${groupQualifierTypes.join(", ")}); every entry must declare all of them. Entry ignored${dictionary.filePath ? ` - ${dictionary.filePath}` : ""}.`, { level: "error" });
|
|
43
44
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeQualifiedDictionaries.cjs","names":["getDictionaryQualifierTypes","QUALIFIER_ORDER","mergeDictionaries","getDictionaryCompositeIds","DEFAULT_VARIANT_ID"],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { mergeDictionaries } from './mergeDictionaries';\nimport {\n COMPOSITE_ID_SEPARATOR,\n DEFAULT_VARIANT_ID,\n getDictionaryCompositeIds,\n getDictionaryQualifierTypes,\n QUALIFIER_ORDER,\n} from './
|
|
1
|
+
{"version":3,"file":"mergeQualifiedDictionaries.cjs","names":["getDictionaryQualifierTypes","QUALIFIER_ORDER","mergeDictionaries","getDictionaryCompositeIds","DEFAULT_VARIANT_ID"],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { mergeDictionaries } from './mergeDictionaries';\nimport {\n COMPOSITE_ID_SEPARATOR,\n DEFAULT_VARIANT_ID,\n} from './qualifiedDictionary';\nimport {\n getDictionaryCompositeIds,\n getDictionaryQualifierTypes,\n QUALIFIER_ORDER,\n} from './qualifiedDictionaryDeclaration';\n\n/**\n * Merges sibling dictionaries sharing the same key, honouring qualifiers.\n *\n * - No dictionary declares a qualifier → behaves exactly like\n * `mergeDictionaries` (single merged dictionary).\n * - At least one dictionary declares a qualifier → the group's dimension set is\n * the union of every declared dimension (in canonical order\n * `variant → item`). Dictionaries are grouped by their composite id\n * (one segment per dimension), merged within each group (locale completion /\n * priority overrides preserved), and a `QualifiedDictionaryGroup` is returned.\n * Unqualified siblings act as shared base content merged into every entry —\n * and, on a variant-only key, also materialize the `default` entry when no\n * declaration claims it. Every other variant entry then inherits from that\n * `default` entry, so a variant only declares the fields it overrides.\n *\n * Every qualified entry must declare ALL dimensions of the group; an entry that\n * declares only a subset is ambiguous and is rejected with an error log.\n */\nexport const mergeQualifiedDictionaries = (\n dictionaries: Dictionary[]\n): Dictionary | QualifiedDictionaryGroup => {\n const perDictionaryTypes = dictionaries.map(getDictionaryQualifierTypes);\n\n const declaredDimensions = new Set<DictionaryQualifierType>();\n for (const types of perDictionaryTypes) {\n for (const type of types) declaredDimensions.add(type);\n }\n\n // Canonical order, restricted to the dimensions actually declared.\n const groupQualifierTypes = QUALIFIER_ORDER.filter((qualifierType) =>\n declaredDimensions.has(qualifierType)\n );\n\n if (groupQualifierTypes.length === 0) {\n return mergeDictionaries(dictionaries);\n }\n\n const appLogger = getAppLogger({ log });\n\n const baseDictionaries: Dictionary[] = [];\n const entriesDictionaries = new Map<string, Dictionary[]>();\n\n dictionaries.forEach((dictionary, index) => {\n if (perDictionaryTypes[index]?.length === 0) {\n baseDictionaries.push(dictionary);\n return;\n }\n\n // A dictionary may map to several composite ids (array variant fan-out):\n // its content is registered under every id it lists.\n const compositeIds = getDictionaryCompositeIds(\n dictionary,\n groupQualifierTypes\n );\n\n if (compositeIds === undefined) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} declares (${perDictionaryTypes[index].join(', ')}) but the key's dimensions are (${groupQualifierTypes.join(', ')}); every entry must declare all of them. Entry ignored${dictionary.filePath ? ` - ${dictionary.filePath}` : ''}.`,\n { level: 'error' }\n );\n return;\n }\n\n for (const compositeId of compositeIds) {\n const existingEntries = entriesDictionaries.get(compositeId) ?? [];\n existingEntries.push(dictionary);\n entriesDictionaries.set(compositeId, existingEntries);\n }\n });\n\n // Unqualified siblings are the key's base content. On a variant key they also\n // materialize the `default` entry when no declaration claims it, so the key\n // still resolves when no variant is selected — and so variants that declare\n // no entry of their own can fall back to it. Registering an empty entry list\n // is enough: the merge loop below appends the base dictionaries to it.\n //\n // Composite (variant × item) keys are excluded: base content carries no item\n // index, so it cannot be placed on the collection axis.\n const isVariantOnlyGroup =\n groupQualifierTypes.length === 1 && groupQualifierTypes[0] === 'variant';\n\n if (\n isVariantOnlyGroup &&\n baseDictionaries.length > 0 &&\n !entriesDictionaries.has(DEFAULT_VARIANT_ID)\n ) {\n entriesDictionaries.set(DEFAULT_VARIANT_ID, []);\n }\n\n // `content` maps each composite id to its resolved content node directly; the\n // qualifier coordinates live in the key, not in a per-entry wrapper. For an\n // object variant the variant segment is the canonical serialization of the\n // object, so it fully identifies the entry — no side-map is needed.\n const content: Record<string, unknown> = {};\n\n let importMode: Dictionary['importMode'];\n\n const variantIndex = groupQualifierTypes.indexOf('variant');\n\n /**\n * The id of the entry a composite id inherits from — itself with its variant\n * segment swapped for `default` (`'promo/2'` → `'default/2'`). `undefined`\n * for the default entries themselves and for keys with no variant dimension.\n */\n const getInheritedEntryId = (compositeId: string): string | undefined => {\n if (variantIndex === -1) return undefined;\n\n const segments = compositeId.split(COMPOSITE_ID_SEPARATOR);\n if (segments[variantIndex] === DEFAULT_VARIANT_ID) return undefined;\n\n segments[variantIndex] = DEFAULT_VARIANT_ID;\n return segments.join(COMPOSITE_ID_SEPARATOR);\n };\n\n for (const [compositeId, qualifiedDictionaries] of entriesDictionaries) {\n // Precedence, highest first: the entry's own declarations, then the\n // `default` variant it inherits from, then the unqualified siblings shared\n // by the whole key (mergeDictionaries prefers the first occurrence).\n //\n // Inheriting from `default` is what makes a variant declaration partial: it\n // only has to declare the fields whose wording actually differs, and every\n // other field is completed from the default entry.\n const inheritedEntryId = getInheritedEntryId(compositeId);\n const inheritedDictionaries = inheritedEntryId\n ? (entriesDictionaries.get(inheritedEntryId) ?? [])\n : [];\n\n const mergedEntry = mergeDictionaries([\n ...qualifiedDictionaries,\n ...inheritedDictionaries,\n ...baseDictionaries,\n ]);\n\n content[compositeId] = mergedEntry.content;\n\n const [firstQualified] = qualifiedDictionaries;\n\n importMode ??= firstQualified?.importMode;\n }\n\n const localIds = Array.from(\n new Set(\n dictionaries\n .filter((dictionary) => dictionary.localId)\n .map((dictionary) => dictionary.localId!)\n )\n );\n\n return {\n key: dictionaries[0]!.key,\n qualifierTypes: groupQualifierTypes,\n content,\n ...(importMode !== undefined && { importMode }),\n localIds,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,8BACX,iBAC0C;CAC1C,MAAM,qBAAqB,aAAa,IAAIA,wFAA2B;CAEvE,MAAM,qCAAqB,IAAI,IAA6B;CAC5D,KAAK,MAAM,SAAS,oBAClB,KAAK,MAAM,QAAQ,OAAO,mBAAmB,IAAI,IAAI;CAIvD,MAAM,sBAAsBC,6EAAgB,QAAQ,kBAClD,mBAAmB,IAAI,aAAa,CACtC;CAEA,IAAI,oBAAoB,WAAW,GACjC,OAAOC,kEAAkB,YAAY;CAGvC,MAAM,sDAAyB,EAAE,gCAAI,CAAC;CAEtC,MAAM,mBAAiC,CAAC;CACxC,MAAM,sCAAsB,IAAI,IAA0B;CAE1D,aAAa,SAAS,YAAY,UAAU;EAC1C,IAAI,mBAAmB,MAAM,EAAE,WAAW,GAAG;GAC3C,iBAAiB,KAAK,UAAU;GAChC;EACF;EAIA,MAAM,eAAeC,uFACnB,YACA,mBACF;EAEA,IAAI,iBAAiB,QAAW;GAC9B,UACE,uDAA0B,WAAW,GAAG,EAAE,aAAa,mBAAmB,MAAM,CAAC,KAAK,IAAI,EAAE,kCAAkC,oBAAoB,KAAK,IAAI,EAAE,wDAAwD,WAAW,WAAW,MAAM,WAAW,aAAa,GAAG,IAC5Q,EAAE,OAAO,QAAQ,CACnB;GACA;EACF;EAEA,KAAK,MAAM,eAAe,cAAc;GACtC,MAAM,kBAAkB,oBAAoB,IAAI,WAAW,KAAK,CAAC;GACjE,gBAAgB,KAAK,UAAU;GAC/B,oBAAoB,IAAI,aAAa,eAAe;EACtD;CACF,CAAC;CAaD,IAFE,oBAAoB,WAAW,KAAK,oBAAoB,OAAO,aAI/D,iBAAiB,SAAS,KAC1B,CAAC,oBAAoB,aAAsB,GAE3C,oBAAoB,IAAIC,sEAAoB,CAAC,CAAC;CAOhD,MAAM,UAAmC,CAAC;CAE1C,IAAI;CAEJ,MAAM,eAAe,oBAAoB,QAAQ,SAAS;;;;;;CAO1D,MAAM,uBAAuB,gBAA4C;EACvE,IAAI,iBAAiB,IAAI,OAAO;EAEhC,MAAM,WAAW,YAAY,SAA4B;EACzD,IAAI,SAAS,6BAAsC,OAAO;EAE1D,SAAS,gBAAgBA;EACzB,OAAO,SAAS,QAA2B;CAC7C;CAEA,KAAK,MAAM,CAAC,aAAa,0BAA0B,qBAAqB;EAQtE,MAAM,mBAAmB,oBAAoB,WAAW;EACxD,MAAM,wBAAwB,mBACzB,oBAAoB,IAAI,gBAAgB,KAAK,CAAC,IAC/C,CAAC;EAQL,QAAQ,eANYF,kEAAkB;GACpC,GAAG;GACH,GAAG;GACH,GAAG;EACL,CAEiC,CAAC,CAAC;EAEnC,MAAM,CAAC,kBAAkB;EAEzB,eAAe,gBAAgB;CACjC;CAEA,MAAM,WAAW,MAAM,KACrB,IAAI,IACF,aACG,QAAQ,eAAe,WAAW,OAAO,CAAC,CAC1C,KAAK,eAAe,WAAW,OAAQ,CAC5C,CACF;CAEA,OAAO;EACL,KAAK,aAAa,EAAE,CAAE;EACtB,gBAAgB;EAChB;EACA,GAAI,eAAe,UAAa,EAAE,WAAW;EAC7C;CACF;AACF"}
|
|
@@ -2,12 +2,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
//#region src/dictionaryManipulator/qualifiedDictionary.ts
|
|
4
4
|
/**
|
|
5
|
-
* Canonical order of qualifier dimensions. A key that declares both dimensions
|
|
6
|
-
* always nests them in this order, with `item` innermost so it can act as the
|
|
7
|
-
* collection (array) axis.
|
|
8
|
-
*/
|
|
9
|
-
const QUALIFIER_ORDER = ["variant", "item"];
|
|
10
|
-
/**
|
|
11
5
|
* Separator joining per-dimension ids into a composite entry id. Also used as
|
|
12
6
|
* the chunk path separator in dynamic mode.
|
|
13
7
|
*/
|
|
@@ -62,57 +56,6 @@ const serializeVariant = (variant) => {
|
|
|
62
56
|
return Object.keys(variant).sort().map((field) => `${encodeSegmentText(field, COMPONENT_UNSAFE_CHARS)}=${encodeSegmentText(String(variant[field]), COMPONENT_UNSAFE_CHARS)}`).join("&");
|
|
63
57
|
};
|
|
64
58
|
/**
|
|
65
|
-
* Normalizes the `variant` field of a dictionary into the list of variant ids
|
|
66
|
-
* the declaration registers under. A single value yields one id; an **array**
|
|
67
|
-
* fans out into one id per element (duplicates collapsed). Returns `undefined`
|
|
68
|
-
* when the dictionary does not declare the variant dimension (no `variant`
|
|
69
|
-
* field, or an empty array).
|
|
70
|
-
*/
|
|
71
|
-
const getVariantIds = (variant) => {
|
|
72
|
-
if (variant === void 0) return void 0;
|
|
73
|
-
const values = Array.isArray(variant) ? variant : [variant];
|
|
74
|
-
if (values.length === 0) return void 0;
|
|
75
|
-
return [...new Set(values.map(serializeVariant))];
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Returns the qualifier dimensions declared on a dictionary, in canonical
|
|
79
|
-
* order (`variant → item`). Empty when the dictionary is unqualified
|
|
80
|
-
* (plain dictionary or shared base content of a qualified group).
|
|
81
|
-
*/
|
|
82
|
-
const getDictionaryQualifierTypes = (dictionary) => {
|
|
83
|
-
const declaredQualifiers = [];
|
|
84
|
-
if (getVariantIds(dictionary.variant) !== void 0) declaredQualifiers.push("variant");
|
|
85
|
-
if (typeof dictionary.item === "number") declaredQualifiers.push("item");
|
|
86
|
-
return declaredQualifiers;
|
|
87
|
-
};
|
|
88
|
-
/**
|
|
89
|
-
* Returns the qualifier identifiers of a dictionary for the given qualifier
|
|
90
|
-
* dimension — the candidate segments of the composite entry ids.
|
|
91
|
-
*
|
|
92
|
-
* - 'variant' → the serialized variant id(s); an array variant yields one id
|
|
93
|
-
* per element (declaration-side fan-out)
|
|
94
|
-
* - 'item' → the item index as a single-element list
|
|
95
|
-
*/
|
|
96
|
-
const getDictionaryQualifierIds = (dictionary, qualifierType) => {
|
|
97
|
-
if (qualifierType === "variant") return getVariantIds(dictionary.variant);
|
|
98
|
-
return dictionary.item === void 0 ? void 0 : [String(dictionary.item)];
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Builds every composite entry id of a dictionary — the cartesian product of
|
|
102
|
-
* its per-dimension id lists, joined in canonical order. A dictionary with a
|
|
103
|
-
* plain (non-array) variant yields exactly one id; an array variant fans out
|
|
104
|
-
* into one id per element. `undefined` when a dimension of the set is missing.
|
|
105
|
-
*/
|
|
106
|
-
const getDictionaryCompositeIds = (dictionary, qualifierTypes) => {
|
|
107
|
-
let compositeIds = [""];
|
|
108
|
-
for (const qualifierType of qualifierTypes) {
|
|
109
|
-
const ids = getDictionaryQualifierIds(dictionary, qualifierType);
|
|
110
|
-
if (ids === void 0) return void 0;
|
|
111
|
-
compositeIds = compositeIds.flatMap((prefix) => ids.map((id) => prefix === "" ? id : `${prefix}${"/"}${id}`));
|
|
112
|
-
}
|
|
113
|
-
return compositeIds;
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
59
|
* Serializes the variant coordinate of a selector into the ordered list of
|
|
117
60
|
* candidate ids to try, so a single value and a preference chain share one code
|
|
118
61
|
* path downstream.
|
|
@@ -290,130 +233,18 @@ const getDictionarySelectorCacheKey = (selector) => {
|
|
|
290
233
|
return `${selectorKey}:${selectorKey === "variant" ? serializeVariantChain(value).join(",") : String(value)}`;
|
|
291
234
|
}).join("|");
|
|
292
235
|
};
|
|
293
|
-
/**
|
|
294
|
-
* Marker property carrying the ordered qualifier dimensions on a dynamic loader
|
|
295
|
-
* map. Its presence distinguishes a qualified group loader map (a nested tree
|
|
296
|
-
* of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed
|
|
297
|
-
* and unlikely to collide with a real locale code.
|
|
298
|
-
*/
|
|
299
|
-
const QUALIFIER_DYNAMIC_TYPES_KEY = "__intlayerQualifierTypes";
|
|
300
|
-
/**
|
|
301
|
-
* Type guard discriminating a qualified dynamic loader map (collections /
|
|
302
|
-
* variants, possibly combined) from a plain dynamic loader map.
|
|
303
|
-
*/
|
|
304
|
-
const isQualifiedDynamicLoaderMap = (value) => typeof value === "object" && value !== null && "__intlayerQualifierTypes" in value;
|
|
305
|
-
/**
|
|
306
|
-
* Walks the loader tree following the selector and collects the chunk loaders
|
|
307
|
-
* it targets — shared by the sync ({@link resolveQualifiedDynamicContent}) and
|
|
308
|
-
* async ({@link resolveQualifiedDynamicContentAsync}) resolvers.
|
|
309
|
-
*/
|
|
310
|
-
const collectQualifiedChunks = (loaderMap, key, locale, selector) => {
|
|
311
|
-
const qualifierTypes = loaderMap[QUALIFIER_DYNAMIC_TYPES_KEY];
|
|
312
|
-
const localeTree = loaderMap[locale];
|
|
313
|
-
const itemAxisOpen = qualifierTypes.includes("item") && selector?.item === void 0;
|
|
314
|
-
if (!localeTree) return {
|
|
315
|
-
itemAxisOpen,
|
|
316
|
-
missed: true,
|
|
317
|
-
chunks: []
|
|
318
|
-
};
|
|
319
|
-
const chunks = [];
|
|
320
|
-
const walk = (node, dimensions, segments) => {
|
|
321
|
-
if (dimensions.length === 0) {
|
|
322
|
-
chunks.push({
|
|
323
|
-
cacheKey: `${key}.${locale}.${segments.join("/")}`,
|
|
324
|
-
loader: node
|
|
325
|
-
});
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
const [dimension, ...rest] = dimensions;
|
|
329
|
-
const tree = node;
|
|
330
|
-
if (dimension === "item" && selector?.item === void 0) {
|
|
331
|
-
for (const segment of Object.keys(tree).sort((left, right) => Number(left) - Number(right))) walk(tree[segment], rest, [...segments, segment]);
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
const segment = dimension === "variant" ? resolveEffectiveVariantId(serializeVariantChain(selector?.variant), (variantId) => tree[variantId] !== void 0) : String(selector?.item);
|
|
335
|
-
const child = tree[segment];
|
|
336
|
-
if (!child) return false;
|
|
337
|
-
return walk(child, rest, [...segments, segment]);
|
|
338
|
-
};
|
|
339
|
-
return {
|
|
340
|
-
itemAxisOpen,
|
|
341
|
-
missed: !walk(localeTree, qualifierTypes, []),
|
|
342
|
-
chunks
|
|
343
|
-
};
|
|
344
|
-
};
|
|
345
|
-
/**
|
|
346
|
-
* Resolves the content of a qualified dynamic loader map against a selector,
|
|
347
|
-
* loading only the chunk(s) the selector actually targets.
|
|
348
|
-
*
|
|
349
|
-
* Walks the nested loader tree one dimension at a time (canonical order
|
|
350
|
-
* `variant → item`): `variant` descends by the serialized id, falling back to
|
|
351
|
-
* `default` when the selected variant has no chunk of its own, and `item`
|
|
352
|
-
* either narrows to the selected index or — when no item is given — expands
|
|
353
|
-
* into every sibling chunk (the collection axis). Semantics mirror
|
|
354
|
-
* {@link resolveQualifiedDictionary} so dynamic and static modes behave alike.
|
|
355
|
-
*
|
|
356
|
-
* The Suspense mechanism is injected through `loadChunk` so the same logic
|
|
357
|
-
* serves both the client (suspender cache) and the server (`react.use`). Every
|
|
358
|
-
* targeted loader is started before the first chunk is read, so sibling chunks
|
|
359
|
-
* load in parallel rather than waterfalling.
|
|
360
|
-
*
|
|
361
|
-
* @param loaderMap - The qualified dynamic loader map (entry point default export).
|
|
362
|
-
* @param key - The dictionary key (used to build stable chunk cache keys).
|
|
363
|
-
* @param locale - The resolved locale to load chunks for.
|
|
364
|
-
* @param selector - The selector splitting the qualifier dimensions.
|
|
365
|
-
* @param loadChunk - Reads a started chunk promise, suspending until it resolves.
|
|
366
|
-
* @param transform - Turns a resolved chunk dictionary into final content.
|
|
367
|
-
*/
|
|
368
|
-
const resolveQualifiedDynamicContent = (params) => {
|
|
369
|
-
const { loaderMap, key, locale, selector, loadChunk, transform } = params;
|
|
370
|
-
const { itemAxisOpen, missed, chunks } = collectQualifiedChunks(loaderMap, key, locale, selector);
|
|
371
|
-
if (missed) return itemAxisOpen ? [] : null;
|
|
372
|
-
const dictionaries = chunks.map(({ cacheKey, loader }) => loadChunk(cacheKey, loader()));
|
|
373
|
-
if (itemAxisOpen) return dictionaries.map(transform);
|
|
374
|
-
const [dictionary] = dictionaries;
|
|
375
|
-
return dictionary ? transform(dictionary) : null;
|
|
376
|
-
};
|
|
377
|
-
/**
|
|
378
|
-
* Async counterpart of {@link resolveQualifiedDynamicContent} for frameworks
|
|
379
|
-
* that load dictionaries with `await` instead of Suspense (Vue, Svelte, Lit,
|
|
380
|
-
* vanilla). Awaits every targeted chunk in parallel, then resolves identically.
|
|
381
|
-
*
|
|
382
|
-
* @param loaderMap - The qualified dynamic loader map.
|
|
383
|
-
* @param key - The dictionary key (used to build stable chunk cache keys).
|
|
384
|
-
* @param locale - The resolved locale to load chunks for.
|
|
385
|
-
* @param selector - The selector splitting the qualifier dimensions.
|
|
386
|
-
* @param transform - Turns a resolved chunk dictionary into final content.
|
|
387
|
-
*/
|
|
388
|
-
const resolveQualifiedDynamicContentAsync = async (params) => {
|
|
389
|
-
const { loaderMap, key, locale, selector, transform } = params;
|
|
390
|
-
const { itemAxisOpen, missed, chunks } = collectQualifiedChunks(loaderMap, key, locale, selector);
|
|
391
|
-
if (missed) return itemAxisOpen ? [] : null;
|
|
392
|
-
const dictionaries = await Promise.all(chunks.map(({ loader }) => loader()));
|
|
393
|
-
if (itemAxisOpen) return dictionaries.map(transform);
|
|
394
|
-
const [dictionary] = dictionaries;
|
|
395
|
-
return dictionary ? transform(dictionary) : null;
|
|
396
|
-
};
|
|
397
236
|
|
|
398
237
|
//#endregion
|
|
399
238
|
exports.COMPOSITE_ID_SEPARATOR = COMPOSITE_ID_SEPARATOR;
|
|
400
239
|
exports.DEFAULT_VARIANT_ID = DEFAULT_VARIANT_ID;
|
|
401
|
-
exports.QUALIFIER_DYNAMIC_TYPES_KEY = QUALIFIER_DYNAMIC_TYPES_KEY;
|
|
402
|
-
exports.QUALIFIER_ORDER = QUALIFIER_ORDER;
|
|
403
|
-
exports.getDictionaryCompositeIds = getDictionaryCompositeIds;
|
|
404
|
-
exports.getDictionaryQualifierIds = getDictionaryQualifierIds;
|
|
405
|
-
exports.getDictionaryQualifierTypes = getDictionaryQualifierTypes;
|
|
406
240
|
exports.getDictionarySelectorCacheKey = getDictionarySelectorCacheKey;
|
|
407
|
-
exports.getVariantIds = getVariantIds;
|
|
408
241
|
exports.isQualifiedDictionaryGroup = isQualifiedDictionaryGroup;
|
|
409
|
-
exports.isQualifiedDynamicLoaderMap = isQualifiedDynamicLoaderMap;
|
|
410
242
|
exports.parseDictionarySelector = parseDictionarySelector;
|
|
411
243
|
exports.reconstructQualifiedEntry = reconstructQualifiedEntry;
|
|
412
244
|
exports.resolveDictionaryArgument = resolveDictionaryArgument;
|
|
245
|
+
exports.resolveEffectiveVariantId = resolveEffectiveVariantId;
|
|
413
246
|
exports.resolveProviderVariant = resolveProviderVariant;
|
|
414
247
|
exports.resolveQualifiedDictionary = resolveQualifiedDictionary;
|
|
415
|
-
exports.resolveQualifiedDynamicContent = resolveQualifiedDynamicContent;
|
|
416
|
-
exports.resolveQualifiedDynamicContentAsync = resolveQualifiedDynamicContentAsync;
|
|
417
248
|
exports.serializeVariant = serializeVariant;
|
|
418
249
|
exports.serializeVariantChain = serializeVariantChain;
|
|
419
250
|
//# sourceMappingURL=qualifiedDictionary.cjs.map
|