{"version":3,"file":"writeNestedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeNestedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getPathHash } from '../utils/getPathHash';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\n\n/**\n * Subdirectory of `dictionariesDir` holding the companion modules. Nested under\n * the compiled dictionaries so both stay together and are cleaned as one, and\n * because the `**\\/*.json` globs listing compiled dictionaries never match the\n * `.mjs` / `.cjs` files written here.\n */\nexport const NESTED_DICTIONARIES_SUBDIR = 'nested';\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * module, so keys containing `'` or `\\` cannot break the emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n  value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/**\n * Path of the companion module carrying the `nest()` targets of a dictionary.\n *\n * Shared with the bundler plugins, which re-point the static import they inject\n * at a `useIntlayer` call site to this module whenever the dictionary has nest\n * targets.\n *\n * @param dictionariesDir - The compiled dictionaries directory.\n * @param key - The dictionary key.\n * @param extension - Module extension, `'mjs'` (default) or `'cjs'`.\n */\nexport const getNestedDictionaryPath = (\n  dictionariesDir: string,\n  key: string,\n  extension: 'mjs' | 'cjs' = 'mjs'\n): string =>\n  resolve(dictionariesDir, NESTED_DICTIONARIES_SUBDIR, `${key}.${extension}`);\n\n/**\n * Generates a companion module that re-exports a compiled dictionary with its\n * `nest()` targets attached.\n *\n * The optimizer imports this instead of the raw JSON, so `getNesting` resolves\n * the reference from `nestedDictionaries` rather from the global registry\n * — which lets the registry be stripped, and puts each nest target in the same\n * chunk as the dictionary that references it.\n *\n * @param key - The dictionary key.\n * @param nestedKeys - Keys of the dictionaries it references, transitively.\n * @param format - Output module format.\n *\n * @example\n * ```js\n * import _dictionary from '../dashboard.json' with { type: 'json' };\n * import _1a2b3c from '../common.json' with { type: 'json' };\n *\n * export default { ..._dictionary, nestedDictionaries: { 'common': _1a2b3c } };\n * ```\n */\nexport const generateNestedDictionaryEntryPoint = (\n  key: string,\n  nestedKeys: string[],\n  format: 'cjs' | 'esm' = 'esm'\n): string => {\n  const sortedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n  // Hash the key so the generated identifier is a valid one whatever the\n  // dictionary key contains (dashes, dots, non-ASCII).\n  const identifierOf = (nestedKey: string) => `_${getPathHash(nestedKey)}`;\n\n  const importLines = sortedKeys\n    .map((nestedKey) =>\n      format === 'esm'\n        ? `import ${identifierOf(nestedKey)} from '../${escapeJsLiteral(nestedKey)}.json' with { type: 'json' };`\n        : `const ${identifierOf(nestedKey)} = require('../${escapeJsLiteral(nestedKey)}.json');`\n    )\n    .join('\\n');\n\n  const attachedEntries = sortedKeys\n    .map(\n      (nestedKey) =>\n        `  '${escapeJsLiteral(nestedKey)}': ${identifierOf(nestedKey)}`\n    )\n    .join(',\\n');\n\n  const safeKey = escapeJsLiteral(key);\n\n  if (format === 'esm') {\n    return (\n      `import _dictionary from '../${safeKey}.json' with { type: 'json' };\\n` +\n      `${importLines}\\n\\n` +\n      `const nestedDictionaries = {\\n${attachedEntries}\\n};\\n\\n` +\n      `export default { ..._dictionary, nestedDictionaries };\\n`\n    );\n  }\n\n  return (\n    `const _dictionary = require('../${safeKey}.json');\\n` +\n    `${importLines}\\n\\n` +\n    `const nestedDictionaries = {\\n${attachedEntries}\\n};\\n\\n` +\n    `module.exports = { ..._dictionary, nestedDictionaries };\\n`\n  );\n};\n\n/**\n * Writes one companion module per dictionary holding `nest()` references.\n *\n * @param nestedDictionaryGraph - Dictionary key → keys it nests, transitively.\n * @param configuration - The resolved intlayer configuration.\n * @param formats - Module formats to emit.\n */\nexport const writeNestedDictionaries = async (\n  nestedDictionaryGraph: Map<string, Set<string>>,\n  configuration: IntlayerConfig,\n  formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n  if (nestedDictionaryGraph.size === 0) return;\n\n  const { dictionariesDir } = configuration.system;\n  const nestedDir = resolve(dictionariesDir, NESTED_DICTIONARIES_SUBDIR);\n\n  await mkdir(nestedDir, { recursive: true });\n\n  await parallelize(\n    [...nestedDictionaryGraph.entries()].sort(([a], [b]) => a.localeCompare(b)),\n    async ([key, nestedKeys]) => {\n      await parallelize(formats, async (format) => {\n        const extension = format === 'cjs' ? 'cjs' : 'mjs';\n        const content = generateNestedDictionaryEntryPoint(\n          key,\n          [...nestedKeys],\n          format\n        );\n\n        const entryPath = getNestedDictionaryPath(\n          dictionariesDir,\n          key,\n          extension\n        );\n        assertPathWithin(entryPath, nestedDir);\n\n        await writeFileIfChanged(entryPath, content).catch((error) => {\n          console.error(\n            `Error creating nested ${colorizePath(entryPath)}:`,\n            error\n          );\n        });\n      });\n    }\n  );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAa,6BAA6B;;;;;AAM1C,MAAM,mBAAmB,UACvB,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC,QAAQ,MAAM,KAAK;;;;;;;;;;;;AAalD,MAAa,2BACX,iBACA,KACA,YAA2B,UAE3B,QAAQ,iBAAiB,4BAA4B,GAAG,IAAI,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;AAuB5E,MAAa,sCACX,KACA,YACA,SAAwB,UACb;CACX,MAAM,aAAa,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAIpE,MAAM,gBAAgB,cAAsB,IAAI,YAAY,SAAS;CAErE,MAAM,cAAc,WACjB,KAAK,cACJ,WAAW,QACP,UAAU,aAAa,SAAS,EAAE,YAAY,gBAAgB,SAAS,EAAE,iCACzE,SAAS,aAAa,SAAS,EAAE,iBAAiB,gBAAgB,SAAS,EAAE,SACnF,CAAC,CACA,KAAK,IAAI;CAEZ,MAAM,kBAAkB,WACrB,KACE,cACC,MAAM,gBAAgB,SAAS,EAAE,KAAK,aAAa,SAAS,GAChE,CAAC,CACA,KAAK,KAAK;CAEb,MAAM,UAAU,gBAAgB,GAAG;CAEnC,IAAI,WAAW,OACb,OACE,+BAA+B,QAAQ,iCACpC,YAAY,oCACkB,gBAAgB;CAKrD,OACE,mCAAmC,QAAQ,YACxC,YAAY,oCACkB,gBAAgB;AAGrD;;;;;;;;AASA,MAAa,0BAA0B,OACrC,uBACA,eACA,UAA6B,kBACX;CAClB,IAAI,sBAAsB,SAAS,GAAG;CAEtC,MAAM,EAAE,oBAAoB,cAAc;CAC1C,MAAM,YAAY,QAAQ,iBAAiB,0BAA0B;CAErE,MAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,YACJ,CAAC,GAAG,sBAAsB,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,GAC1E,OAAO,CAAC,KAAK,gBAAgB;EAC3B,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,mCACd,KACA,CAAC,GAAG,UAAU,GACd,MACF;GAEA,MAAM,YAAY,wBAChB,iBACA,KACA,SACF;GACA,iBAAiB,WAAW,SAAS;GAErC,MAAM,mBAAmB,WAAW,OAAO,CAAC,CAAC,OAAO,UAAU;IAC5D,QAAQ,MACN,yBAAyB,aAAa,SAAS,EAAE,IACjD,KACF;GACF,CAAC;EACH,CAAC;CACH,CACF;AACF"}