@intlayer/chokidar 5.7.7 → 5.8.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +2 -1
  2. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  3. package/dist/cjs/mergeDictionaries.cjs +67 -3
  4. package/dist/cjs/mergeDictionaries.cjs.map +1 -1
  5. package/dist/cjs/reduceDictionaryContent/applyMask.cjs +16 -2
  6. package/dist/cjs/reduceDictionaryContent/applyMask.cjs.map +1 -1
  7. package/dist/cjs/writeContentDeclaration/formatCode.cjs +3 -1
  8. package/dist/cjs/writeContentDeclaration/formatCode.cjs.map +1 -1
  9. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +101 -148
  10. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
  11. package/dist/esm/loadDictionaries/loadDictionaries.mjs +2 -1
  12. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  13. package/dist/esm/mergeDictionaries.mjs +67 -3
  14. package/dist/esm/mergeDictionaries.mjs.map +1 -1
  15. package/dist/esm/reduceDictionaryContent/applyMask.mjs +16 -2
  16. package/dist/esm/reduceDictionaryContent/applyMask.mjs.map +1 -1
  17. package/dist/esm/writeContentDeclaration/formatCode.mjs +3 -1
  18. package/dist/esm/writeContentDeclaration/formatCode.mjs.map +1 -1
  19. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +101 -148
  20. package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
  21. package/dist/types/loadDictionaries/loadDictionaries.d.ts.map +1 -1
  22. package/dist/types/mergeDictionaries.d.ts.map +1 -1
  23. package/dist/types/reduceDictionaryContent/applyMask.d.ts.map +1 -1
  24. package/dist/types/writeContentDeclaration/formatCode.d.ts.map +1 -1
  25. package/dist/types/writeContentDeclaration/writeJSFile.d.ts.map +1 -1
  26. package/package.json +17 -17
  27. package/dist/cjs/utils/resolveObjectPromises.test.cjs +0 -107
  28. package/dist/cjs/utils/resolveObjectPromises.test.cjs.map +0 -1
  29. package/dist/esm/utils/resolveObjectPromises.test.mjs +0 -106
  30. package/dist/esm/utils/resolveObjectPromises.test.mjs.map +0 -1
  31. package/dist/types/utils/resolveObjectPromises.test.d.ts +0 -2
  32. package/dist/types/utils/resolveObjectPromises.test.d.ts.map +0 -1
@@ -22,6 +22,7 @@ __export(loadDictionaries_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(loadDictionaries_exports);
24
24
  var import_config = require("@intlayer/config");
25
+ var import_node_path = require("node:path");
25
26
  var import_fetchDistantDictionaryKeys = require('../fetchDistantDictionaryKeys.cjs');
26
27
  var import_log = require('../log.cjs');
27
28
  var import_sortAlphabetically = require('../utils/sortAlphabetically.cjs');
@@ -43,7 +44,7 @@ const loadDictionaries = async (contentDeclarationsPaths, configuration = (0, im
43
44
  if (!hasContent) {
44
45
  console.error(
45
46
  "Content declaration has no exported content",
46
- dict.filePath
47
+ dict.filePath ? (0, import_node_path.relative)(configuration.content.baseDir, dict.filePath) : ""
47
48
  );
48
49
  } else if (!hasKey) {
49
50
  console.error("Content declaration has no key", dict.filePath);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend is not build yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport {\n ESMxCJSRequire,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string,\n configuration = getConfiguration(),\n projectRequire = ESMxCJSRequire\n): Promise<Dictionary[]> => {\n try {\n const appLogger = getAppLogger(configuration);\n const { editor } = configuration;\n\n appLogger('Dictionaries:', { isVerbose: true });\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] = await loadContentDeclarations(\n files,\n projectRequire\n );\n\n const filteredLocalDictionaries = localDictionaries.filter((dict) => {\n const hasKey = Boolean(dict.key);\n const hasContent = Boolean(dict.content);\n\n if (!hasContent) {\n console.error(\n 'Content declaration has no exported content',\n dict.filePath\n );\n } else if (!hasKey) {\n console.error('Content declaration has no key', dict.filePath);\n }\n\n return hasKey && hasContent;\n });\n\n const localDictionaryKeys = filteredLocalDictionaries\n .map((dict) => dict.key)\n .filter(Boolean); // Remove empty or undefined keys\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n logger.updateStatus(\n filteredLocalDictionaries.map((dict) => ({\n dictionaryKey: dict.key,\n type: 'local',\n status: { status: 'built' },\n }))\n );\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n } catch (_error) {\n appLogger('Error during fetching distant dictionaries', {\n level: 'error',\n });\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return [...filteredLocalDictionaries, ...distantDictionaries];\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAIO;AAEP,wCAA2C;AAC3C,iBAAuB;AACvB,gCAAmC;AACnC,oCAAwC;AACxC,qCAAwC;AAEjC,MAAM,mBAAmB,OAC9B,0BACA,oBAAgB,gCAAiB,GACjC,iBAAiB,iCACS;AAC1B,MAAI;AACF,UAAM,gBAAY,4BAAa,aAAa;AAC5C,UAAM,EAAE,OAAO,IAAI;AAEnB,cAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAE9C,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBAAkC,UAAM;AAAA,MAC5C;AAAA,MACA;AAAA,IACF;AAEA,UAAM,4BAA4B,kBAAkB,OAAO,CAAC,SAAS;AACnE,YAAM,SAAS,QAAQ,KAAK,GAAG;AAC/B,YAAM,aAAa,QAAQ,KAAK,OAAO;AAEvC,UAAI,CAAC,YAAY;AACf,gBAAQ;AAAA,UACN;AAAA,UACA,KAAK;AAAA,QACP;AAAA,MACF,WAAW,CAAC,QAAQ;AAClB,gBAAQ,MAAM,kCAAkC,KAAK,QAAQ;AAAA,MAC/D;AAEA,aAAO,UAAU;AAAA,IACnB,CAAC;AAED,UAAM,sBAAsB,0BACzB,IAAI,CAAC,SAAS,KAAK,GAAG,EACtB,OAAO,OAAO;AAGjB,sBAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,sBAAO;AAAA,MACL,0BAA0B,IAAI,CAAC,UAAU;AAAA,QACvC,eAAe,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,EAAE,QAAQ,QAAQ;AAAA,MAC5B,EAAE;AAAA,IACJ;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AAEvC,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,UAAM,8DAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,4CAAkB;AAG/C,0BAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,UAAM,wDAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,QAAQ;AACf,kBAAU,8CAA8C;AAAA,UACtD,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAGA,sBAAO,KAAK;AAEZ,WAAO,CAAC,GAAG,2BAA2B,GAAG,mBAAmB;AAAA,EAC9D,SAAS,OAAO;AAEd,sBAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend is not build yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport {\n ESMxCJSRequire,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport { relative } from 'node:path';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string,\n configuration = getConfiguration(),\n projectRequire = ESMxCJSRequire\n): Promise<Dictionary[]> => {\n try {\n const appLogger = getAppLogger(configuration);\n const { editor } = configuration;\n\n appLogger('Dictionaries:', { isVerbose: true });\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] = await loadContentDeclarations(\n files,\n projectRequire\n );\n\n const filteredLocalDictionaries = localDictionaries.filter((dict) => {\n const hasKey = Boolean(dict.key);\n const hasContent = Boolean(dict.content);\n\n if (!hasContent) {\n console.error(\n 'Content declaration has no exported content',\n dict.filePath\n ? relative(configuration.content.baseDir, dict.filePath)\n : ''\n );\n } else if (!hasKey) {\n console.error('Content declaration has no key', dict.filePath);\n }\n\n return hasKey && hasContent;\n });\n\n const localDictionaryKeys = filteredLocalDictionaries\n .map((dict) => dict.key)\n .filter(Boolean); // Remove empty or undefined keys\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n logger.updateStatus(\n filteredLocalDictionaries.map((dict) => ({\n dictionaryKey: dict.key,\n type: 'local',\n status: { status: 'built' },\n }))\n );\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n } catch (_error) {\n appLogger('Error during fetching distant dictionaries', {\n level: 'error',\n });\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return [...filteredLocalDictionaries, ...distantDictionaries];\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAIO;AAEP,uBAAyB;AACzB,wCAA2C;AAC3C,iBAAuB;AACvB,gCAAmC;AACnC,oCAAwC;AACxC,qCAAwC;AAEjC,MAAM,mBAAmB,OAC9B,0BACA,oBAAgB,gCAAiB,GACjC,iBAAiB,iCACS;AAC1B,MAAI;AACF,UAAM,gBAAY,4BAAa,aAAa;AAC5C,UAAM,EAAE,OAAO,IAAI;AAEnB,cAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAE9C,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBAAkC,UAAM;AAAA,MAC5C;AAAA,MACA;AAAA,IACF;AAEA,UAAM,4BAA4B,kBAAkB,OAAO,CAAC,SAAS;AACnE,YAAM,SAAS,QAAQ,KAAK,GAAG;AAC/B,YAAM,aAAa,QAAQ,KAAK,OAAO;AAEvC,UAAI,CAAC,YAAY;AACf,gBAAQ;AAAA,UACN;AAAA,UACA,KAAK,eACD,2BAAS,cAAc,QAAQ,SAAS,KAAK,QAAQ,IACrD;AAAA,QACN;AAAA,MACF,WAAW,CAAC,QAAQ;AAClB,gBAAQ,MAAM,kCAAkC,KAAK,QAAQ;AAAA,MAC/D;AAEA,aAAO,UAAU;AAAA,IACnB,CAAC;AAED,UAAM,sBAAsB,0BACzB,IAAI,CAAC,SAAS,KAAK,GAAG,EACtB,OAAO,OAAO;AAGjB,sBAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,sBAAO;AAAA,MACL,0BAA0B,IAAI,CAAC,UAAU;AAAA,QACvC,eAAe,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,EAAE,QAAQ,QAAQ;AAAA,MAC5B,EAAE;AAAA,IACJ;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AAEvC,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,UAAM,8DAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,4CAAkB;AAG/C,0BAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,UAAM,wDAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,QAAQ;AACf,kBAAU,8CAA8C;AAAA,UACtD,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAGA,sBAAO,KAAK;AAEZ,WAAO,CAAC,GAAG,2BAA2B,GAAG,mBAAmB;AAAA,EAC9D,SAAS,OAAO;AAEd,sBAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -41,7 +41,7 @@ const checkTypesMatch = (obj1, obj2, dictionaryKey, path = []) => {
41
41
  const type2 = (0, import_core.getNodeType)(obj2);
42
42
  if (type1 !== type2) {
43
43
  appLogger(
44
- `Error: Dictionary ${dictionaryKey} has a multiple content files with type mismatch at path "${path.join(".")}": Cannot merge ${type1} with ${type2}`,
44
+ `Error: Dictionary "${dictionaryKey}" has a multiple content files with type mismatch at path "${path.join(".")}": Cannot merge ${type1} with ${type2}`,
45
45
  {
46
46
  level: "error"
47
47
  }
@@ -56,9 +56,65 @@ const checkTypesMatch = (obj1, obj2, dictionaryKey, path = []) => {
56
56
  }
57
57
  }
58
58
  };
59
+ const arrayMerge = (destinationArray, sourceArray) => {
60
+ const isObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
61
+ const getKey = (item) => {
62
+ if (!isObject(item)) return void 0;
63
+ const key = item.key;
64
+ if (typeof key === "string" || typeof key === "number") return key;
65
+ return void 0;
66
+ };
67
+ const result = [];
68
+ const destKeyToIndex = /* @__PURE__ */ new Map();
69
+ const destUsed = new Array(destinationArray.length).fill(false);
70
+ for (let i = 0; i < destinationArray.length; i++) {
71
+ const k = getKey(destinationArray[i]);
72
+ if (k !== void 0 && !destKeyToIndex.has(k)) {
73
+ destKeyToIndex.set(k, i);
74
+ }
75
+ }
76
+ for (let i = 0; i < sourceArray.length; i++) {
77
+ const sourceItem = sourceArray[i];
78
+ const sourceKey = getKey(sourceItem);
79
+ if (sourceKey !== void 0 && destKeyToIndex.has(sourceKey)) {
80
+ const destIndex = destKeyToIndex.get(sourceKey);
81
+ const destItem2 = destinationArray[destIndex];
82
+ destUsed[destIndex] = true;
83
+ if (isObject(destItem2) && isObject(sourceItem)) {
84
+ result.push((0, import_deepmerge.default)(sourceItem, destItem2, { arrayMerge }));
85
+ } else {
86
+ result.push(destItem2 !== void 0 ? destItem2 : sourceItem);
87
+ }
88
+ continue;
89
+ }
90
+ const destItem = destinationArray[i];
91
+ if (destItem !== void 0 && !destUsed[i]) {
92
+ destUsed[i] = true;
93
+ if (isObject(destItem) && isObject(sourceItem)) {
94
+ result.push((0, import_deepmerge.default)(sourceItem, destItem, { arrayMerge }));
95
+ } else if (destItem !== void 0) {
96
+ result.push(destItem);
97
+ } else {
98
+ result.push(sourceItem);
99
+ }
100
+ } else {
101
+ result.push(sourceItem);
102
+ }
103
+ }
104
+ for (let i = 0; i < destinationArray.length; i++) {
105
+ if (!destUsed[i]) {
106
+ result.push(destinationArray[i]);
107
+ destUsed[i] = true;
108
+ }
109
+ }
110
+ return result;
111
+ };
59
112
  const mergeDictionaries = (dictionaries) => {
60
113
  const { editor } = import_built.default;
61
114
  let mergedDictionaries = dictionaries[0];
115
+ const mergeOptions = {
116
+ arrayMerge
117
+ };
62
118
  for (let i = 1; i < dictionaries.length; i++) {
63
119
  const currentDictionary = dictionaries[i];
64
120
  checkTypesMatch(
@@ -69,9 +125,17 @@ const mergeDictionaries = (dictionaries) => {
69
125
  );
70
126
  const isDistant = currentDictionary.location === "distant";
71
127
  if (editor.dictionaryPriorityStrategy === "distant_first" && isDistant) {
72
- mergedDictionaries = (0, import_deepmerge.default)(mergedDictionaries, currentDictionary);
128
+ mergedDictionaries = (0, import_deepmerge.default)(
129
+ mergedDictionaries,
130
+ currentDictionary,
131
+ mergeOptions
132
+ );
73
133
  } else {
74
- mergedDictionaries = (0, import_deepmerge.default)(currentDictionary, mergedDictionaries);
134
+ mergedDictionaries = (0, import_deepmerge.default)(
135
+ currentDictionary,
136
+ mergedDictionaries,
137
+ mergeOptions
138
+ );
75
139
  }
76
140
  }
77
141
  return { ...mergedDictionaries, filePath: void 0 };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/mergeDictionaries.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/core';\nimport { getNodeType } from '@intlayer/core';\nimport merge from 'deepmerge';\n\nconst checkTypesMatch = (\n obj1: any,\n obj2: any,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger(configuration);\n const type1 = getNodeType(obj1);\n const type2 = getNodeType(obj2);\n\n if (type1 !== type2) {\n appLogger(\n `Error: Dictionary ${dictionaryKey} has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2}`,\n {\n level: 'error',\n }\n );\n }\n\n if (type1 === 'object' && obj1 && obj2) {\n const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);\n for (const key of allKeys) {\n if (key in obj1 && key in obj2) {\n checkTypesMatch(obj1[key], obj2[key], dictionaryKey, [...path, key]);\n }\n }\n }\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const { editor } = configuration;\n\n let mergedDictionaries: Dictionary = dictionaries[0];\n\n for (let i = 1; i < dictionaries.length; i++) {\n const currentDictionary = dictionaries[i];\n\n // Check types before merging\n checkTypesMatch(\n mergedDictionaries,\n currentDictionary,\n currentDictionary.key,\n []\n );\n\n const isDistant = currentDictionary.location === 'distant';\n\n if (editor.dictionaryPriorityStrategy === 'distant_first' && isDistant) {\n mergedDictionaries = merge(mergedDictionaries, currentDictionary);\n } else {\n mergedDictionaries = merge(currentDictionary, mergedDictionaries);\n }\n }\n\n return { ...mergedDictionaries, filePath: undefined };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAC7B,mBAA0B;AAE1B,kBAA4B;AAC5B,uBAAkB;AAElB,MAAM,kBAAkB,CACtB,MACA,MACA,eACA,OAAiB,CAAC,MACT;AACT,QAAM,gBAAY,4BAAa,aAAAA,OAAa;AAC5C,QAAM,YAAQ,yBAAY,IAAI;AAC9B,QAAM,YAAQ,yBAAY,IAAI;AAE9B,MAAI,UAAU,OAAO;AACnB;AAAA,MACE,qBAAqB,aAAa,6DAA6D,KAAK,KAAK,GAAG,CAAC,mBAAmB,KAAK,SAAS,KAAK;AAAA,MACnJ;AAAA,QACE,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,YAAY,QAAQ,MAAM;AACtC,UAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,IAAI,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC;AACpE,eAAW,OAAO,SAAS;AACzB,UAAI,OAAO,QAAQ,OAAO,MAAM;AAC9B,wBAAgB,KAAK,GAAG,GAAG,KAAK,GAAG,GAAG,eAAe,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB,CAAC,iBAA2C;AAC3E,QAAM,EAAE,OAAO,IAAI,aAAAA;AAEnB,MAAI,qBAAiC,aAAa,CAAC;AAEnD,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UAAM,oBAAoB,aAAa,CAAC;AAGxC;AAAA,MACE;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,CAAC;AAAA,IACH;AAEA,UAAM,YAAY,kBAAkB,aAAa;AAEjD,QAAI,OAAO,+BAA+B,mBAAmB,WAAW;AACtE,+BAAqB,iBAAAC,SAAM,oBAAoB,iBAAiB;AAAA,IAClE,OAAO;AACL,+BAAqB,iBAAAA,SAAM,mBAAmB,kBAAkB;AAAA,IAClE;AAAA,EACF;AAEA,SAAO,EAAE,GAAG,oBAAoB,UAAU,OAAU;AACtD;","names":["configuration","merge"]}
1
+ {"version":3,"sources":["../../src/mergeDictionaries.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/core';\nimport { getNodeType } from '@intlayer/core';\nimport merge, { Options } from 'deepmerge';\n\nconst checkTypesMatch = (\n obj1: any,\n obj2: any,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger(configuration);\n const type1 = getNodeType(obj1);\n const type2 = getNodeType(obj2);\n\n if (type1 !== type2) {\n appLogger(\n `Error: Dictionary \"${dictionaryKey}\" has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2}`,\n {\n level: 'error',\n }\n );\n }\n\n if (type1 === 'object' && obj1 && obj2) {\n const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);\n for (const key of allKeys) {\n if (key in obj1 && key in obj2) {\n checkTypesMatch(obj1[key], obj2[key], dictionaryKey, [...path, key]);\n }\n }\n }\n};\n\n// Custom array merge strategy that merges arrays by key when present, otherwise by index\nconst arrayMerge = (destinationArray: any[], sourceArray: any[]): any[] => {\n const isObject = (value: unknown): value is Record<string, any> =>\n !!value && typeof value === 'object' && !Array.isArray(value);\n\n const getKey = (item: any): string | number | undefined => {\n if (!isObject(item)) return undefined;\n const key = (item as any).key;\n if (typeof key === 'string' || typeof key === 'number') return key;\n return undefined;\n };\n\n const result: any[] = [];\n\n // Build a lookup for destination keyed items and track usage of all destination indices\n const destKeyToIndex = new Map<string | number, number>();\n const destUsed: boolean[] = new Array(destinationArray.length).fill(false);\n for (let i = 0; i < destinationArray.length; i++) {\n const k = getKey(destinationArray[i]);\n if (k !== undefined && !destKeyToIndex.has(k)) {\n destKeyToIndex.set(k, i);\n }\n }\n\n // First pass: respect source (already merged) order\n for (let i = 0; i < sourceArray.length; i++) {\n const sourceItem = sourceArray[i];\n const sourceKey = getKey(sourceItem);\n\n if (sourceKey !== undefined && destKeyToIndex.has(sourceKey)) {\n const destIndex = destKeyToIndex.get(sourceKey)!;\n const destItem = destinationArray[destIndex];\n destUsed[destIndex] = true;\n\n if (isObject(destItem) && isObject(sourceItem)) {\n result.push(merge(sourceItem, destItem, { arrayMerge }));\n } else {\n // Prefer destination item (later dictionary) when primitive\n result.push(destItem !== undefined ? destItem : sourceItem);\n }\n continue;\n }\n\n // Fallback to index-based merge when no key match\n const destItem = destinationArray[i];\n if (destItem !== undefined && !destUsed[i]) {\n destUsed[i] = true;\n if (isObject(destItem) && isObject(sourceItem)) {\n result.push(merge(sourceItem, destItem, { arrayMerge }));\n } else if (destItem !== undefined) {\n result.push(destItem);\n } else {\n result.push(sourceItem);\n }\n } else {\n result.push(sourceItem);\n }\n }\n\n // Second pass: append remaining unused destination items (including keyed-only in destination or extra by index)\n for (let i = 0; i < destinationArray.length; i++) {\n if (!destUsed[i]) {\n result.push(destinationArray[i]);\n destUsed[i] = true;\n }\n }\n\n return result;\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const { editor } = configuration;\n\n let mergedDictionaries: Dictionary = dictionaries[0];\n\n // Configure deepmerge options with custom array merge strategy\n const mergeOptions: Options = {\n arrayMerge,\n };\n\n for (let i = 1; i < dictionaries.length; i++) {\n const currentDictionary = dictionaries[i];\n\n // Check types before merging\n checkTypesMatch(\n mergedDictionaries,\n currentDictionary,\n currentDictionary.key,\n []\n );\n\n const isDistant = currentDictionary.location === 'distant';\n\n if (editor.dictionaryPriorityStrategy === 'distant_first' && isDistant) {\n mergedDictionaries = merge(\n mergedDictionaries,\n currentDictionary,\n mergeOptions\n );\n } else {\n mergedDictionaries = merge(\n currentDictionary,\n mergedDictionaries,\n mergeOptions\n );\n }\n }\n\n return { ...mergedDictionaries, filePath: undefined };\n};\n"],"mappings":"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","names":["configuration","destItem","merge"]}
@@ -36,8 +36,22 @@ const applyMask = (full, mask) => {
36
36
  }
37
37
  if (mask && typeof mask === "object" && full && typeof full === "object") {
38
38
  const out = {};
39
- for (const [k, m] of Object.entries(mask)) {
40
- out[k] = applyMask(full[k], m);
39
+ const maskEntries = Object.entries(mask);
40
+ const allChildrenAreArrays = maskEntries.every(
41
+ ([, value]) => Array.isArray(value)
42
+ );
43
+ for (const [k, m] of maskEntries) {
44
+ const fullValue = full[k];
45
+ if (Array.isArray(m) && Array.isArray(fullValue)) {
46
+ const isTranslationNode = (val) => !!val && typeof val === "object" && "nodeType" in val;
47
+ const isArrayOfTranslationNodes = fullValue.every(
48
+ (item) => isTranslationNode(item)
49
+ );
50
+ if (!allChildrenAreArrays && !isArrayOfTranslationNodes) {
51
+ continue;
52
+ }
53
+ }
54
+ out[k] = applyMask(fullValue, m);
41
55
  }
42
56
  return out;
43
57
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/reduceDictionaryContent/applyMask.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/core';\n\nexport const applyMask = (full: Dictionary, mask: any): Dictionary => {\n // the mask \"true\" → we don't filter\n if (mask === true) {\n return full;\n }\n\n // arrays\n if (Array.isArray(mask) && Array.isArray(full)) {\n return mask.map((m, i) => applyMask(full[i], m)) as any;\n }\n\n // handle node with nodeType property\n if (full && typeof full === 'object' && 'nodeType' in full) {\n if (mask && typeof mask === 'object') {\n return full; // Keep the full object with nodeType intact\n }\n return full;\n }\n\n // generic object\n if (mask && typeof mask === 'object' && full && typeof full === 'object') {\n const out: any = {};\n for (const [k, m] of Object.entries(mask)) {\n out[k] = applyMask((full as any)[k], m);\n }\n return out;\n }\n\n // unexpected case: we return the original value\n return full;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,YAAY,CAAC,MAAkB,SAA0B;AAEpE,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,IAAI,GAAG;AAC9C,WAAO,KAAK,IAAI,CAAC,GAAG,MAAM,UAAU,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,EACjD;AAGA,MAAI,QAAQ,OAAO,SAAS,YAAY,cAAc,MAAM;AAC1D,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,OAAO,SAAS,YAAY,QAAQ,OAAO,SAAS,UAAU;AACxE,UAAM,MAAW,CAAC;AAClB,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,GAAG;AACzC,UAAI,CAAC,IAAI,UAAW,KAAa,CAAC,GAAG,CAAC;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AAGA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/reduceDictionaryContent/applyMask.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/core';\n\nexport const applyMask = (full: Dictionary, mask: any): Dictionary => {\n // the mask \"true\" → we don't filter\n if (mask === true) {\n return full;\n }\n\n // arrays\n if (Array.isArray(mask) && Array.isArray(full)) {\n return mask.map((m, i) => applyMask(full[i], m)) as any;\n }\n\n // handle node with nodeType property\n if (full && typeof full === 'object' && 'nodeType' in full) {\n if (mask && typeof mask === 'object') {\n return full; // Keep the full object with nodeType intact\n }\n return full;\n }\n\n // generic object\n if (mask && typeof mask === 'object' && full && typeof full === 'object') {\n const out: any = {};\n const maskEntries = Object.entries(mask);\n const allChildrenAreArrays = maskEntries.every(([, value]) =>\n Array.isArray(value)\n );\n\n for (const [k, m] of maskEntries) {\n const fullValue = (full as any)[k];\n\n // If this child is an array, decide preservation rules.\n // - Preserve when all children at this level are arrays in the mask\n // - Also preserve when the array is an array of translation nodes\n if (Array.isArray(m) && Array.isArray(fullValue)) {\n const isTranslationNode = (val: unknown): boolean =>\n !!val && typeof val === 'object' && 'nodeType' in (val as any);\n const isArrayOfTranslationNodes = fullValue.every((item: any) =>\n isTranslationNode(item)\n );\n\n if (!allChildrenAreArrays && !isArrayOfTranslationNodes) {\n continue; // skip incidental arrays when mixed with non-arrays\n }\n }\n\n out[k] = applyMask(fullValue, m);\n }\n return out;\n }\n\n // unexpected case: we return the original value\n return full;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,YAAY,CAAC,MAAkB,SAA0B;AAEpE,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ,IAAI,GAAG;AAC9C,WAAO,KAAK,IAAI,CAAC,GAAG,MAAM,UAAU,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,EACjD;AAGA,MAAI,QAAQ,OAAO,SAAS,YAAY,cAAc,MAAM;AAC1D,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,OAAO,SAAS,YAAY,QAAQ,OAAO,SAAS,UAAU;AACxE,UAAM,MAAW,CAAC;AAClB,UAAM,cAAc,OAAO,QAAQ,IAAI;AACvC,UAAM,uBAAuB,YAAY;AAAA,MAAM,CAAC,CAAC,EAAE,KAAK,MACtD,MAAM,QAAQ,KAAK;AAAA,IACrB;AAEA,eAAW,CAAC,GAAG,CAAC,KAAK,aAAa;AAChC,YAAM,YAAa,KAAa,CAAC;AAKjC,UAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,SAAS,GAAG;AAChD,cAAM,oBAAoB,CAAC,QACzB,CAAC,CAAC,OAAO,OAAO,QAAQ,YAAY,cAAe;AACrD,cAAM,4BAA4B,UAAU;AAAA,UAAM,CAAC,SACjD,kBAAkB,IAAI;AAAA,QACxB;AAEA,YAAI,CAAC,wBAAwB,CAAC,2BAA2B;AACvD;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,UAAU,WAAW,CAAC;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAGA,SAAO;AACT;","names":[]}
@@ -33,6 +33,7 @@ __export(formatCode_exports, {
33
33
  module.exports = __toCommonJS(formatCode_exports);
34
34
  var import_config = require("@intlayer/config");
35
35
  var import_built = __toESM(require("@intlayer/config/built"));
36
+ var import_path = require("path");
36
37
  const formatCode = async (filePath, code) => {
37
38
  const appLogger = (0, import_config.getAppLogger)(import_built.default);
38
39
  let prettier;
@@ -48,7 +49,8 @@ const formatCode = async (filePath, code) => {
48
49
  filepath: filePath
49
50
  // Explicitly provide the filepath so Prettier can infer the parser
50
51
  });
51
- appLogger(`Applied Prettier formatting to ${filePath}`, {
52
+ const relativePath = (0, import_path.relative)(import_built.default.content.baseDir, filePath);
53
+ appLogger(`Applied Prettier formatting to ${relativePath}`, {
52
54
  level: "info",
53
55
  isVerbose: true
54
56
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/writeContentDeclaration/formatCode.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\n\nexport const formatCode = async (filePath: string, code: string) => {\n const appLogger = getAppLogger(configuration);\n // Try to import prettier if it exists\n let prettier: any;\n try {\n prettier = require('prettier');\n } catch (error) {\n // Prettier is not installed, continue without it\n }\n\n // Apply Prettier formatting if it's available\n if (prettier) {\n try {\n // Try to find a prettier config file\n const prettierConfig = await prettier.resolveConfig(filePath ?? '');\n\n // Format the code with Prettier\n const formattedCode = await prettier.format(code, {\n ...prettierConfig,\n filepath: filePath, // Explicitly provide the filepath so Prettier can infer the parser\n });\n\n appLogger(`Applied Prettier formatting to ${filePath}`, {\n level: 'info',\n isVerbose: true,\n });\n\n return formattedCode;\n } catch (error) {\n const err = error as Error;\n appLogger(\n `Failed to apply Prettier formatting to ${filePath}: ${err.message}`,\n {\n level: 'warn',\n isVerbose: true,\n }\n );\n // Continue with unformatted code on prettier error\n }\n }\n\n return code;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAC7B,mBAA0B;AAEnB,MAAM,aAAa,OAAO,UAAkB,SAAiB;AAClE,QAAM,gBAAY,4BAAa,aAAAA,OAAa;AAE5C,MAAI;AACJ,MAAI;AACF,eAAW,QAAQ,UAAU;AAAA,EAC/B,SAAS,OAAO;AAAA,EAEhB;AAGA,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,iBAAiB,MAAM,SAAS,cAAc,YAAY,EAAE;AAGlE,YAAM,gBAAgB,MAAM,SAAS,OAAO,MAAM;AAAA,QAChD,GAAG;AAAA,QACH,UAAU;AAAA;AAAA,MACZ,CAAC;AAED,gBAAU,kCAAkC,QAAQ,IAAI;AAAA,QACtD,OAAO;AAAA,QACP,WAAW;AAAA,MACb,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,MAAM;AACZ;AAAA,QACE,0CAA0C,QAAQ,KAAK,IAAI,OAAO;AAAA,QAClE;AAAA,UACE,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;","names":["configuration"]}
1
+ {"version":3,"sources":["../../../src/writeContentDeclaration/formatCode.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { relative } from 'path';\n\nexport const formatCode = async (filePath: string, code: string) => {\n const appLogger = getAppLogger(configuration);\n // Try to import prettier if it exists\n let prettier: any;\n try {\n prettier = require('prettier');\n } catch (error) {\n // Prettier is not installed, continue without it\n }\n\n // Apply Prettier formatting if it's available\n if (prettier) {\n try {\n // Try to find a prettier config file\n const prettierConfig = await prettier.resolveConfig(filePath ?? '');\n\n // Format the code with Prettier\n const formattedCode = await prettier.format(code, {\n ...prettierConfig,\n filepath: filePath, // Explicitly provide the filepath so Prettier can infer the parser\n });\n\n const relativePath = relative(configuration.content.baseDir, filePath);\n\n appLogger(`Applied Prettier formatting to ${relativePath}`, {\n level: 'info',\n isVerbose: true,\n });\n\n return formattedCode;\n } catch (error) {\n const err = error as Error;\n appLogger(\n `Failed to apply Prettier formatting to ${filePath}: ${err.message}`,\n {\n level: 'warn',\n isVerbose: true,\n }\n );\n // Continue with unformatted code on prettier error\n }\n }\n\n return code;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAC7B,mBAA0B;AAC1B,kBAAyB;AAElB,MAAM,aAAa,OAAO,UAAkB,SAAiB;AAClE,QAAM,gBAAY,4BAAa,aAAAA,OAAa;AAE5C,MAAI;AACJ,MAAI;AACF,eAAW,QAAQ,UAAU;AAAA,EAC/B,SAAS,OAAO;AAAA,EAEhB;AAGA,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,iBAAiB,MAAM,SAAS,cAAc,YAAY,EAAE;AAGlE,YAAM,gBAAgB,MAAM,SAAS,OAAO,MAAM;AAAA,QAChD,GAAG;AAAA,QACH,UAAU;AAAA;AAAA,MACZ,CAAC;AAED,YAAM,mBAAe,sBAAS,aAAAA,QAAc,QAAQ,SAAS,QAAQ;AAErE,gBAAU,kCAAkC,YAAY,IAAI;AAAA,QAC1D,OAAO;AAAA,QACP,WAAW;AAAA,MACb,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,MAAM;AACZ;AAAA,QACE,0CAA0C,QAAQ,KAAK,IAAI,OAAO;AAAA,QAClE;AAAA,UACE,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;","names":["configuration"]}
@@ -186,167 +186,120 @@ const writeJSFile = async (filePath, dictionary) => {
186
186
  const contentObjectPath = contentPropertyPath.get(
187
187
  "value"
188
188
  );
189
- for (const [entryKeyToUpdate, newEntryData] of Object.entries(
190
- updatesToApply
191
- )) {
192
- const targetPropertyPath = contentObjectPath.get("properties").find((propPath) => {
189
+ const buildValueNodeFromData = (data) => {
190
+ if (data?.nodeType === import_core.NodeType.Translation) {
191
+ const translationContent = data;
192
+ if (isPerLocaleDeclarationFile && typeof locale === "string" && translationContent?.[import_core.NodeType.Translation]?.[locale] !== void 0) {
193
+ return buildValueNodeFromData(
194
+ translationContent[import_core.NodeType.Translation][locale]
195
+ );
196
+ }
197
+ const translationsObj = t.objectExpression(
198
+ Object.entries(translationContent?.[import_core.NodeType.Translation] ?? {}).map(
199
+ ([langKey, langValue]) => {
200
+ const keyNode = t.isValidIdentifier(langKey) ? t.identifier(langKey) : t.stringLiteral(langKey);
201
+ return t.objectProperty(keyNode, buildValueNodeFromData(langValue));
202
+ }
203
+ )
204
+ );
205
+ return t.callExpression(t.identifier("t"), [translationsObj]);
206
+ }
207
+ if (Array.isArray(data)) {
208
+ return t.arrayExpression(data.map((el) => buildValueNodeFromData(el)));
209
+ }
210
+ if (data && typeof data === "object") {
211
+ const props = Object.entries(data).map(([k, v]) => {
212
+ const key = t.isValidIdentifier(k) ? t.identifier(k) : t.stringLiteral(k);
213
+ return t.objectProperty(key, buildValueNodeFromData(v));
214
+ });
215
+ return t.objectExpression(props);
216
+ }
217
+ switch (typeof data) {
218
+ case "string":
219
+ return t.stringLiteral(data);
220
+ case "number":
221
+ return t.numericLiteral(data);
222
+ case "boolean":
223
+ return t.booleanLiteral(data);
224
+ default:
225
+ return t.nullLiteral();
226
+ }
227
+ };
228
+ const ensureObjectProperty = (objPath, key) => {
229
+ const existing = objPath.get("properties").find((propPath) => {
193
230
  if (!propPath.isObjectProperty()) return false;
194
231
  const propNode = propPath.node;
195
232
  const keyName = t.isIdentifier(propNode.key) ? propNode.key.name : t.isStringLiteral(propNode.key) ? propNode.key.value : null;
196
- return keyName === entryKeyToUpdate;
233
+ return keyName === key;
197
234
  });
198
- if (!targetPropertyPath || !targetPropertyPath.isObjectProperty()) {
199
- appLogger(
200
- `Key '${entryKeyToUpdate}' not found in content object of ${filePath}. Adding the missing key.`,
201
- {
202
- level: "info",
203
- isVerbose: true
204
- }
205
- );
206
- let valueNode;
207
- if (newEntryData?.nodeType === import_core.NodeType.Translation) {
208
- const translationContent = newEntryData;
209
- if (isPerLocaleDeclarationFile && typeof locale === "string" && translationContent?.[import_core.NodeType.Translation]?.[locale]) {
210
- valueNode = t.stringLiteral(
211
- String(translationContent[import_core.NodeType.Translation][locale])
212
- );
213
- } else {
214
- const translationsObj = t.objectExpression(
215
- Object.entries(translationContent?.[import_core.NodeType.Translation]).map(
216
- ([langKey, langValue]) => {
217
- const keyNode2 = t.isValidIdentifier(langKey) ? t.identifier(langKey) : t.stringLiteral(langKey);
218
- return t.objectProperty(
219
- keyNode2,
220
- t.stringLiteral(String(langValue))
221
- );
222
- }
235
+ if (existing) return existing;
236
+ const keyNode = t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
237
+ const newProp = t.objectProperty(keyNode, t.objectExpression([]));
238
+ objPath.node.properties.push(newProp);
239
+ const props = objPath.get("properties");
240
+ return props[props.length - 1];
241
+ };
242
+ const mergeValueIntoProperty = (propPath, value, propKeyForLogs) => {
243
+ const valuePath = propPath.get("value");
244
+ if (value?.nodeType === import_core.NodeType.Translation) {
245
+ const translationContent = value;
246
+ if (valuePath.isCallExpression() && t.isIdentifier(valuePath.node.callee) && valuePath.node.callee.name === "t") {
247
+ const translationsObj = t.objectExpression(
248
+ Object.entries(translationContent?.[import_core.NodeType.Translation] ?? {}).map(
249
+ ([langKey, langValue]) => t.objectProperty(
250
+ t.isValidIdentifier(langKey) ? t.identifier(langKey) : t.stringLiteral(langKey),
251
+ buildValueNodeFromData(langValue)
223
252
  )
224
- );
225
- valueNode = t.callExpression(t.identifier("t"), [translationsObj]);
226
- }
227
- } else if (typeof newEntryData === "string") {
228
- valueNode = t.stringLiteral(newEntryData);
229
- } else {
230
- appLogger(
231
- `Unsupported data type for new key '${entryKeyToUpdate}'. Using empty string.`,
232
- { level: "warn", isVerbose: true }
253
+ )
233
254
  );
234
- valueNode = t.stringLiteral("");
235
- }
236
- const keyNode = t.isValidIdentifier(entryKeyToUpdate) ? t.identifier(entryKeyToUpdate) : t.stringLiteral(entryKeyToUpdate);
237
- const newProperty = t.objectProperty(keyNode, valueNode);
238
- contentObjectPath.node.properties.push(newProperty);
239
- continue;
240
- }
241
- const callExpressionPath = targetPropertyPath.get("value");
242
- if (callExpressionPath.isCallExpression()) {
243
- const calleeNode = callExpressionPath.node.callee;
244
- const calleeName = t.isIdentifier(calleeNode) ? calleeNode.name : null;
245
- if (newEntryData?.nodeType === "translation" && calleeName === "t") {
246
- const args = callExpressionPath.node.arguments;
247
- if (args.length === 0 || !t.isObjectExpression(args[0])) {
248
- appLogger(
249
- `'t' call for '${entryKeyToUpdate}' in ${filePath} does not have an object literal as its first argument. Skipping.`,
250
- {
251
- level: "warn",
252
- isVerbose: true
253
- }
254
- );
255
- continue;
256
- }
257
255
  if (isPerLocaleDeclarationFile && typeof locale === "string") {
258
- const translations = newEntryData?.[import_core.NodeType.Translation];
259
- if (translations[locale]) {
260
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(String(translations[locale])));
261
- } else {
262
- appLogger(
263
- `Missing translation for locale '${locale}' in '${entryKeyToUpdate}'. Using first available translation.`,
264
- { level: "warn", isVerbose: true }
265
- );
266
- const firstValue = Object.values(translations)[0];
267
- if (firstValue) {
268
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(String(firstValue)));
269
- }
270
- }
271
- continue;
272
- }
273
- const translationsObjectAstNode = args[0];
274
- const processedLangKeysInJsonUpdate = /* @__PURE__ */ new Set();
275
- translationsObjectAstNode.properties.forEach((prop) => {
276
- if (t.isObjectProperty(prop)) {
277
- const langKeyNode = prop.key;
278
- const astLangKeyName = t.isIdentifier(langKeyNode) ? langKeyNode.name : t.isStringLiteral(langKeyNode) ? langKeyNode.value : null;
279
- if (astLangKeyName && newEntryData?.[import_core.NodeType.Translation].hasOwnProperty(astLangKeyName)) {
280
- prop.value = t.stringLiteral(
281
- String(
282
- newEntryData?.[import_core.NodeType.Translation]?.[astLangKeyName]
283
- )
284
- );
285
- processedLangKeysInJsonUpdate.add(astLangKeyName);
286
- }
287
- }
288
- });
289
- for (const [jsonLangKey, jsonLangValue] of Object.entries(
290
- newEntryData?.[import_core.NodeType.Translation]
291
- )) {
292
- if (!processedLangKeysInJsonUpdate.has(jsonLangKey)) {
293
- const newKeyNode = t.isValidIdentifier(jsonLangKey) ? t.identifier(jsonLangKey) : t.stringLiteral(jsonLangKey);
294
- translationsObjectAstNode.properties.push(
295
- t.objectProperty(
296
- newKeyNode,
297
- t.stringLiteral(String(jsonLangValue))
298
- )
299
- );
256
+ const localized = translationContent?.[import_core.NodeType.Translation]?.[locale];
257
+ if (localized !== void 0) {
258
+ valuePath.replaceWith(buildValueNodeFromData(localized));
259
+ return;
300
260
  }
301
261
  }
302
- } else {
303
- appLogger(
304
- `Unhandled callee '${calleeName || "unknown"}' for key '${entryKeyToUpdate}' in ${filePath}.`,
305
- { level: "warn", isVerbose: true }
306
- );
262
+ valuePath.node.arguments = [translationsObj];
263
+ return;
307
264
  }
308
- } else if (callExpressionPath.isStringLiteral()) {
309
- if (typeof newEntryData === "string") {
310
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(newEntryData));
311
- } else if (newEntryData?.[import_core.NodeType.Translation]) {
312
- const translations = newEntryData[import_core.NodeType.Translation];
313
- const firstValue = Object.values(translations)[0];
314
- if (firstValue) {
315
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(String(firstValue)));
316
- }
317
- } else {
318
- appLogger(
319
- `Unhandled data structure for string replacement at '${entryKeyToUpdate}' in ${filePath}.`,
320
- { level: "warn", isVerbose: true }
321
- );
265
+ valuePath.replaceWith(buildValueNodeFromData(value));
266
+ return;
267
+ }
268
+ if (Array.isArray(value)) {
269
+ valuePath.replaceWith(buildValueNodeFromData(value));
270
+ return;
271
+ }
272
+ if (value && typeof value === "object") {
273
+ if (!valuePath.isObjectExpression()) {
274
+ valuePath.replaceWith(t.objectExpression([]));
322
275
  }
323
- } else {
324
- const valueType = callExpressionPath.node.type;
325
- appLogger(
326
- `Updating value of type ${valueType} for '${entryKeyToUpdate}' in ${filePath}`,
327
- { level: "info", isVerbose: true }
328
- );
329
- if (typeof newEntryData === "string") {
330
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(newEntryData));
331
- } else if (newEntryData?.[import_core.NodeType.Translation]) {
332
- const translations = newEntryData[import_core.NodeType.Translation];
333
- const localeMatch = filePath.match(/\.([a-z]{2})\.content\.(ts|js)$/i);
334
- const locale2 = localeMatch ? localeMatch[1] : Object.keys(translations)[0];
335
- if (translations[locale2]) {
336
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(String(translations[locale2])));
337
- } else {
338
- const firstValue = Object.values(translations)[0];
339
- if (firstValue) {
340
- targetPropertyPath.get("value").replaceWith(t.stringLiteral(String(firstValue)));
341
- }
342
- }
343
- } else {
344
- appLogger(
345
- `Cannot update value of type ${valueType} for '${entryKeyToUpdate}' in ${filePath}. Unsupported data structure.`,
346
- { level: "warn", isVerbose: true }
347
- );
276
+ const objPath = valuePath;
277
+ for (const [k, v] of Object.entries(value)) {
278
+ const childProp = ensureObjectProperty(objPath, k);
279
+ mergeValueIntoProperty(childProp, v, `${propKeyForLogs}.${k}`);
348
280
  }
281
+ return;
282
+ }
283
+ valuePath.replaceWith(buildValueNodeFromData(value));
284
+ return;
285
+ };
286
+ for (const [entryKeyToUpdate, newEntryData] of Object.entries(
287
+ updatesToApply
288
+ )) {
289
+ let targetPropertyPath = contentObjectPath.get("properties").find((propPath) => {
290
+ if (!propPath.isObjectProperty()) return false;
291
+ const propNode = propPath.node;
292
+ const keyName = t.isIdentifier(propNode.key) ? propNode.key.name : t.isStringLiteral(propNode.key) ? propNode.key.value : null;
293
+ return keyName === entryKeyToUpdate;
294
+ });
295
+ if (!targetPropertyPath) {
296
+ const keyNode = t.isValidIdentifier(entryKeyToUpdate) ? t.identifier(entryKeyToUpdate) : t.stringLiteral(entryKeyToUpdate);
297
+ const newProperty = t.objectProperty(keyNode, t.objectExpression([]));
298
+ contentObjectPath.node.properties.push(newProperty);
299
+ const props = contentObjectPath.get("properties");
300
+ targetPropertyPath = props[props.length - 1];
349
301
  }
302
+ mergeValueIntoProperty(targetPropertyPath, newEntryData, entryKeyToUpdate);
350
303
  }
351
304
  const generatedCode = (0, import_generator.default)(ast, {
352
305
  retainLines: true,