@intlayer/chokidar
Version:
Scans and builds Intlayer declaration files into dictionaries based on Intlayer configuration.
1 lines • 5.92 kB
Source Map (JSON)
{"version":3,"file":"handleContentDeclarationFileChange.mjs","names":[],"sources":["../../src/handleContentDeclarationFileChange.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { buildDictionary } from './buildIntlayerDictionary/buildIntlayerDictionary';\nimport { cleanRemovedContentDeclaration } from './cleanRemovedContentDeclaration';\nimport { createDictionaryEntryPoint } from './createDictionaryEntryPoint/createDictionaryEntryPoint';\nimport { getBuiltDictionariesPath } from './createDictionaryEntryPoint/getBuiltDictionariesPath';\nimport { createTypes } from './createType';\nimport { createModuleAugmentation } from './createType/createModuleAugmentation';\nimport { loadLocalDictionaries } from './loadDictionaries/loadLocalDictionaries';\nimport { formatPath } from './utils/formatter';\n\nexport const handleContentDeclarationFileChange = async (\n filePath: string,\n config: IntlayerConfig\n) => {\n const appLogger = getAppLogger(config);\n\n // Process the file with the functionToRun\n appLogger(`Change detected: ${formatPath(filePath)}`, {\n isVerbose: true,\n });\n\n const allDictionariesPaths: string[] = await getBuiltDictionariesPath(config);\n\n const localeDictionaries = await loadLocalDictionaries(filePath, config);\n\n const dictionariesOutput = await buildDictionary(localeDictionaries, config);\n const updatedDictionaries = Object.values(\n dictionariesOutput?.mergedDictionaries ?? {}\n );\n const updatedDictionariesPaths = updatedDictionaries.map(\n (dictionary) => dictionary.dictionaryPath\n );\n\n const { excludeKeys, hasRebuilt } = await cleanRemovedContentDeclaration(\n filePath,\n localeDictionaries.map((dictionary) => dictionary.key),\n config\n );\n\n const hasNewDictionaries = updatedDictionariesPaths.some(\n (updatedDictionaryPath) =>\n !allDictionariesPaths.includes(updatedDictionaryPath)\n );\n\n // Rebuild Types first — types must be ready before anything triggers a bundler rebuild.\n // esbuild (used by Angular, Vite, etc.) only watches files in its JS bundle graph; it does\n // NOT watch .intlayer/types/*.ts (TypeScript-only files). Generating types here, before\n // updating the entry point, guarantees that when the entry point write below fires esbuild's\n // file watcher the types are already up-to-date.\n const dictionariesToBuild = updatedDictionaries.map(\n (dictionary) => dictionary.dictionary\n );\n\n await createTypes(dictionariesToBuild, config);\n appLogger('TypeScript types built', {\n isVerbose: true,\n });\n\n // Always regenerate the module augmentation so that structural changes to existing\n // dictionaries (new content keys, type changes) are reflected in intlayer.d.ts.\n await createModuleAugmentation(config);\n appLogger('Module augmentation built', {\n isVerbose: true,\n });\n\n // Rebuild Entry Point\n // Only needed when the *list* of dictionaries changed (Add/Remove/Rename).\n if (hasRebuilt || hasNewDictionaries) {\n // If hasRebuilt is true, cleanRemovedContentDeclaration has already updated the entry point\n // to remove the old keys (and it likely included the new ones if they were already on disk).\n // If NOT hasRebuilt, we explicitly need to update the entry point to include the new dictionaries.\n if (!hasRebuilt) {\n await createDictionaryEntryPoint(config, { excludeKeys });\n appLogger('Dictionary list built', {\n isVerbose: true,\n });\n }\n }\n\n // Force-write the entry point files so esbuild detects a change and triggers a fresh rebuild\n // now that all types are ready. Without this, the only rebuild esbuild sees is the one\n // triggered by buildDictionary's JSON writes above — which races against type generation\n // and often runs before the new .intlayer/types/*.ts files are on disk.\n const { mainDir } = config.system;\n\n for (const extension of config.build.outputFormat) {\n const entryPointPath = join(mainDir, `dictionaries.${extension}`);\n\n if (existsSync(entryPointPath)) {\n const content = await readFile(entryPointPath, 'utf-8');\n await writeFile(entryPointPath, content);\n }\n }\n\n // Plugin transformation\n // Allow plugins to post-process the final build output (e.g., write back ICU JSON)\n for await (const plugin of config.plugins ?? []) {\n const { unmergedDictionaries, mergedDictionaries } = dictionariesOutput;\n\n await plugin.afterBuild?.({\n dictionaries: {\n unmergedDictionaries,\n mergedDictionaries,\n },\n configuration: config,\n });\n }\n};\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAa,qCAAqC,OAChD,UACA,WACG;CACH,MAAM,YAAY,aAAa,OAAO;AAGtC,WAAU,oBAAoB,WAAW,SAAS,IAAI,EACpD,WAAW,MACZ,CAAC;CAEF,MAAM,uBAAiC,MAAM,yBAAyB,OAAO;CAE7E,MAAM,qBAAqB,MAAM,sBAAsB,UAAU,OAAO;CAExE,MAAM,qBAAqB,MAAM,gBAAgB,oBAAoB,OAAO;CAC5E,MAAM,sBAAsB,OAAO,OACjC,oBAAoB,sBAAsB,EAAE,CAC7C;CACD,MAAM,2BAA2B,oBAAoB,KAClD,eAAe,WAAW,eAC5B;CAED,MAAM,EAAE,aAAa,eAAe,MAAM,+BACxC,UACA,mBAAmB,KAAK,eAAe,WAAW,IAAI,EACtD,OACD;CAED,MAAM,qBAAqB,yBAAyB,MACjD,0BACC,CAAC,qBAAqB,SAAS,sBAAsB,CACxD;AAWD,OAAM,YAJsB,oBAAoB,KAC7C,eAAe,WAAW,WAGQ,EAAE,OAAO;AAC9C,WAAU,0BAA0B,EAClC,WAAW,MACZ,CAAC;AAIF,OAAM,yBAAyB,OAAO;AACtC,WAAU,6BAA6B,EACrC,WAAW,MACZ,CAAC;AAIF,KAAI,cAAc,oBAIhB;MAAI,CAAC,YAAY;AACf,SAAM,2BAA2B,QAAQ,EAAE,aAAa,CAAC;AACzD,aAAU,yBAAyB,EACjC,WAAW,MACZ,CAAC;;;CAQN,MAAM,EAAE,YAAY,OAAO;AAE3B,MAAK,MAAM,aAAa,OAAO,MAAM,cAAc;EACjD,MAAM,iBAAiB,KAAK,SAAS,gBAAgB,YAAY;AAEjE,MAAI,WAAW,eAAe,CAE5B,OAAM,UAAU,gBAAgB,MADV,SAAS,gBAAgB,QAAQ,CACf;;AAM5C,YAAW,MAAM,UAAU,OAAO,WAAW,EAAE,EAAE;EAC/C,MAAM,EAAE,sBAAsB,uBAAuB;AAErD,QAAM,OAAO,aAAa;GACxB,cAAc;IACZ;IACA;IACD;GACD,eAAe;GAChB,CAAC"}