@intlayer/engine 9.3.0 → 9.3.1
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/README.md +24 -24
- package/dist/assets/initConfig/templates/cjs.txt +1 -1
- package/dist/assets/initConfig/templates/mjs.txt +1 -1
- package/dist/assets/initConfig/templates/ts.txt +1 -1
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
- package/dist/cjs/_virtual/_utils_asset.cjs +2 -1
- package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +2 -1
- package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +2 -1
- package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +4 -2
- package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs.map +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
- package/dist/cjs/cleanOutputDir.cjs.map +1 -1
- package/dist/cjs/cleanRemovedContentDeclaration.cjs +7 -4
- package/dist/cjs/cleanRemovedContentDeclaration.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +5 -3
- package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/generateDictionaryListContent.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs.map +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs.map +1 -1
- package/dist/cjs/createType/createModuleAugmentation.cjs +2 -1
- package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
- package/dist/cjs/createType/createType.cjs.map +1 -1
- package/dist/cjs/detectFormatCommand.cjs.map +1 -1
- package/dist/cjs/docReview/alignBlocks.cjs +1 -1
- package/dist/cjs/docReview/alignBlocks.cjs.map +1 -1
- package/dist/cjs/docReview/computeSimilarity.cjs +0 -1
- package/dist/cjs/docReview/computeSimilarity.cjs.map +1 -1
- package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs +0 -1
- package/dist/cjs/docReview/mapChangedLinesToBlocks.cjs.map +1 -1
- package/dist/cjs/docReview/normalizeBlock.cjs +0 -1
- package/dist/cjs/docReview/normalizeBlock.cjs.map +1 -1
- package/dist/cjs/docReview/planActions.cjs +0 -1
- package/dist/cjs/docReview/planActions.cjs.map +1 -1
- package/dist/cjs/docReview/rebuildDocument.cjs +0 -1
- package/dist/cjs/docReview/rebuildDocument.cjs.map +1 -1
- package/dist/cjs/docReview/reviewReport.cjs +2 -1
- package/dist/cjs/docReview/reviewReport.cjs.map +1 -1
- package/dist/cjs/docReview/segmentDocument.cjs +0 -1
- package/dist/cjs/docReview/segmentDocument.cjs.map +1 -1
- package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
- package/dist/cjs/filterInvalidDictionaries.cjs.map +1 -1
- package/dist/cjs/formatDictionary.cjs.map +1 -1
- package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs.map +1 -1
- package/dist/cjs/handleAdditionalContentDeclarationFile.cjs +4 -2
- package/dist/cjs/handleAdditionalContentDeclarationFile.cjs.map +1 -1
- package/dist/cjs/handleContentDeclarationFileChange.cjs +6 -2
- package/dist/cjs/handleContentDeclarationFileChange.cjs.map +1 -1
- package/dist/cjs/handleContentDeclarationFileMoved.cjs.map +1 -1
- package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +4 -2
- package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs.map +1 -1
- package/dist/cjs/init/cms.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +1 -3
- package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +2 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs +0 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/detect.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +3 -5
- package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +2 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +18 -12
- package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +57 -14
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
- package/dist/cjs/init/index.cjs +66 -38
- package/dist/cjs/init/index.cjs.map +1 -1
- package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
- package/dist/cjs/init/utils/fileSystem.cjs +3 -1
- package/dist/cjs/init/utils/fileSystem.cjs.map +1 -1
- package/dist/cjs/init/utils/githubActions.cjs.map +1 -1
- package/dist/cjs/init/utils/jsonParser.cjs +0 -1
- package/dist/cjs/init/utils/jsonParser.cjs.map +1 -1
- package/dist/cjs/init/utils/nextCompilerBabel.cjs.map +1 -1
- package/dist/cjs/init/utils/packageManager.cjs +4 -2
- package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
- package/dist/cjs/init/utils/tsConfig.cjs.map +1 -1
- package/dist/cjs/init/utils/version.cjs +0 -1
- package/dist/cjs/init/utils/version.cjs.map +1 -1
- package/dist/cjs/initConfig/index.cjs +12 -8
- package/dist/cjs/initConfig/index.cjs.map +1 -1
- package/dist/cjs/installSkills/index.cjs.map +1 -1
- package/dist/cjs/listDictionariesPath.cjs +6 -5
- package/dist/cjs/listDictionariesPath.cjs.map +1 -1
- package/dist/cjs/listGitFiles.cjs.map +1 -1
- package/dist/cjs/listProjects.cjs +2 -1
- package/dist/cjs/listProjects.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -1
- package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +8 -5
- package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs +2 -1
- package/dist/cjs/loadDictionaries/loadYamlContentDeclaration.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/log.cjs +10 -6
- package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
- package/dist/cjs/logConfigDetails.cjs +4 -3
- package/dist/cjs/logConfigDetails.cjs.map +1 -1
- package/dist/cjs/prepareIntlayer.cjs +5 -3
- package/dist/cjs/prepareIntlayer.cjs.map +1 -1
- package/dist/cjs/reduceDictionaryContent/applyMask.cjs +0 -1
- package/dist/cjs/reduceDictionaryContent/applyMask.cjs.map +1 -1
- package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs +2 -1
- package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs.map +1 -1
- package/dist/cjs/scan/calculateScore.cjs +0 -1
- package/dist/cjs/scan/calculateScore.cjs.map +1 -1
- package/dist/cjs/scan/checks.cjs +1 -1
- package/dist/cjs/scan/checks.cjs.map +1 -1
- package/dist/cjs/scan/parseHtml.cjs +0 -1
- package/dist/cjs/scan/parseHtml.cjs.map +1 -1
- package/dist/cjs/scan/scanWebsite.cjs.map +1 -1
- package/dist/cjs/syncPluginKit/createFileAdapter.cjs +2 -1
- package/dist/cjs/syncPluginKit/createFileAdapter.cjs.map +1 -1
- package/dist/cjs/syncPluginKit/createSyncPlugin.cjs +4 -1
- package/dist/cjs/syncPluginKit/createSyncPlugin.cjs.map +1 -1
- package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs +0 -1
- package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs.map +1 -1
- package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs +0 -1
- package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs.map +1 -1
- package/dist/cjs/utils/autoDecorateContent.cjs.map +1 -1
- package/dist/cjs/utils/babelParser.cjs.map +1 -1
- package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
- package/dist/cjs/utils/buildFilesList.cjs.map +1 -1
- package/dist/cjs/utils/chunkArray.cjs +0 -1
- package/dist/cjs/utils/chunkArray.cjs.map +1 -1
- package/dist/cjs/utils/formatter.cjs.map +1 -1
- package/dist/cjs/utils/getContentExtension.cjs +1 -4
- package/dist/cjs/utils/getContentExtension.cjs.map +1 -1
- package/dist/cjs/utils/getFormatFromExtension.cjs +0 -1
- package/dist/cjs/utils/getFormatFromExtension.cjs.map +1 -1
- package/dist/cjs/utils/getPathHash.cjs +0 -1
- package/dist/cjs/utils/getPathHash.cjs.map +1 -1
- package/dist/cjs/utils/mergeChunks.cjs +0 -1
- package/dist/cjs/utils/mergeChunks.cjs.map +1 -1
- package/dist/cjs/utils/pLimit.cjs +0 -1
- package/dist/cjs/utils/pLimit.cjs.map +1 -1
- package/dist/cjs/utils/readDictionariesFromDisk.cjs.map +1 -1
- package/dist/cjs/utils/reduceObjectFormat.cjs +0 -1
- package/dist/cjs/utils/reduceObjectFormat.cjs.map +1 -1
- package/dist/cjs/utils/resolveObjectPromises.cjs +0 -1
- package/dist/cjs/utils/resolveObjectPromises.cjs.map +1 -1
- package/dist/cjs/utils/resolveRelativePath.cjs +4 -1
- package/dist/cjs/utils/resolveRelativePath.cjs.map +1 -1
- package/dist/cjs/utils/runOnce.cjs +2 -2
- package/dist/cjs/utils/runOnce.cjs.map +1 -1
- package/dist/cjs/utils/runParallel/bin.cjs.map +1 -1
- package/dist/cjs/utils/runParallel/bootstrap.cjs +0 -1
- package/dist/cjs/utils/runParallel/bootstrap.cjs.map +1 -1
- package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
- package/dist/cjs/utils/runParallel/spawnPosix.cjs.map +1 -1
- package/dist/cjs/utils/runParallel/spawnWin32.cjs.map +1 -1
- package/dist/cjs/utils/sortAlphabetically.cjs +0 -1
- package/dist/cjs/utils/sortAlphabetically.cjs.map +1 -1
- package/dist/cjs/utils/splitTextByLine.cjs +0 -1
- package/dist/cjs/utils/splitTextByLine.cjs.map +1 -1
- package/dist/cjs/utils/verifyIdenticObjectFormat.cjs +0 -1
- package/dist/cjs/utils/verifyIdenticObjectFormat.cjs.map +1 -1
- package/dist/cjs/watcher.cjs +4 -2
- package/dist/cjs/watcher.cjs.map +1 -1
- package/dist/cjs/writeConfiguration/index.cjs +2 -1
- package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs +0 -1
- package/dist/cjs/writeContentDeclaration/detectExportedComponentName.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +26 -23
- package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs +6 -5
- package/dist/cjs/writeContentDeclaration/transformJSONFile.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +9 -3
- package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +2 -1
- package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -1
- package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
- package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +4 -2
- package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs.map +1 -1
- package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +2 -1
- package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +2 -1
- package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +2 -1
- package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
- package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +4 -2
- package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs.map +1 -1
- package/dist/esm/cleanRemovedContentDeclaration.mjs +7 -4
- package/dist/esm/cleanRemovedContentDeclaration.mjs.map +1 -1
- package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +5 -3
- package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs.map +1 -1
- package/dist/esm/createType/createModuleAugmentation.mjs +2 -1
- package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
- package/dist/esm/docReview/alignBlocks.mjs +1 -1
- package/dist/esm/docReview/alignBlocks.mjs.map +1 -1
- package/dist/esm/docReview/reviewReport.mjs +2 -1
- package/dist/esm/docReview/reviewReport.mjs.map +1 -1
- package/dist/esm/handleAdditionalContentDeclarationFile.mjs +4 -2
- package/dist/esm/handleAdditionalContentDeclarationFile.mjs.map +1 -1
- package/dist/esm/handleContentDeclarationFileChange.mjs +6 -2
- package/dist/esm/handleContentDeclarationFileChange.mjs.map +1 -1
- package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +4 -2
- package/dist/esm/handleUnlinkedContentDeclarationFile.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +1 -3
- package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +2 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +4 -6
- package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +2 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +17 -10
- package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +58 -15
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
- package/dist/esm/init/index.mjs +66 -38
- package/dist/esm/init/index.mjs.map +1 -1
- package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
- package/dist/esm/init/utils/fileSystem.mjs +3 -1
- package/dist/esm/init/utils/fileSystem.mjs.map +1 -1
- package/dist/esm/init/utils/packageManager.mjs +4 -2
- package/dist/esm/init/utils/packageManager.mjs.map +1 -1
- package/dist/esm/initConfig/index.mjs +12 -8
- package/dist/esm/initConfig/index.mjs.map +1 -1
- package/dist/esm/listDictionariesPath.mjs +6 -5
- package/dist/esm/listDictionariesPath.mjs.map +1 -1
- package/dist/esm/listProjects.mjs +2 -1
- package/dist/esm/listProjects.mjs.map +1 -1
- package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -1
- package/dist/esm/loadDictionaries/getIntlayerBundle.mjs.map +1 -1
- package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +8 -5
- package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
- package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs +2 -1
- package/dist/esm/loadDictionaries/loadYamlContentDeclaration.mjs.map +1 -1
- package/dist/esm/loadDictionaries/log.mjs +10 -6
- package/dist/esm/loadDictionaries/log.mjs.map +1 -1
- package/dist/esm/logConfigDetails.mjs +4 -3
- package/dist/esm/logConfigDetails.mjs.map +1 -1
- package/dist/esm/prepareIntlayer.mjs +5 -3
- package/dist/esm/prepareIntlayer.mjs.map +1 -1
- package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs +2 -1
- package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs.map +1 -1
- package/dist/esm/scan/checks.mjs +1 -1
- package/dist/esm/scan/checks.mjs.map +1 -1
- package/dist/esm/syncPluginKit/createFileAdapter.mjs +2 -1
- package/dist/esm/syncPluginKit/createFileAdapter.mjs.map +1 -1
- package/dist/esm/syncPluginKit/createSyncPlugin.mjs +4 -1
- package/dist/esm/syncPluginKit/createSyncPlugin.mjs.map +1 -1
- package/dist/esm/utils/babelParser.mjs.map +1 -1
- package/dist/esm/utils/getContentExtension.mjs +1 -3
- package/dist/esm/utils/getContentExtension.mjs.map +1 -1
- package/dist/esm/utils/resolveRelativePath.mjs +4 -1
- package/dist/esm/utils/resolveRelativePath.mjs.map +1 -1
- package/dist/esm/utils/runOnce.mjs +2 -2
- package/dist/esm/utils/runOnce.mjs.map +1 -1
- package/dist/esm/watcher.mjs +4 -2
- package/dist/esm/watcher.mjs.map +1 -1
- package/dist/esm/writeConfiguration/index.mjs +2 -1
- package/dist/esm/writeConfiguration/index.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/transformJSFile.mjs +26 -23
- package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/transformJSONFile.mjs +6 -5
- package/dist/esm/writeContentDeclaration/transformJSONFile.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +9 -3
- package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/writeJSFile.mjs +2 -1
- package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -1
- package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
- package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +4 -2
- package/dist/esm/writeContentDeclaration/writeYamlFile.mjs.map +1 -1
- package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +9 -4
- package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts +6 -2
- package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeContentDeclaration.cjs","names":["processContentDeclarationContent","getFormatFromExtension","COMPILER_NO_METADATA","readDictionariesFromDisk","writeMarkdownFile","writeYamlFile","transformJSONFile","detectFormatCommand","writeJSFile"],"sources":["../../../src/writeContentDeclaration/writeContentDeclaration.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, extname, join, resolve } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport { COMPILER_NO_METADATA } from '@intlayer/config/defaultValues';\nimport {\n getFilteredLocalesDictionary,\n getPerLocaleDictionary,\n} from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { detectFormatCommand } from '../detectFormatCommand';\nimport {\n type Extension,\n getFormatFromExtension,\n} from '../utils/getFormatFromExtension';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport type { DictionaryStatus } from './dictionaryStatus';\nimport { processContentDeclarationContent } from './processContentDeclarationContent';\nimport { transformJSONFile } from './transformJSONFile';\nimport { writeJSFile } from './writeJSFile';\nimport { writeMarkdownFile } from './writeMarkdownFile';\nimport { writeYamlFile } from './writeYamlFile';\n\nconst formatContentDeclaration = async (\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n localeList?: LocalesValues[]\n) => {\n /**\n * Clean Markdown, Insertion, File, etc. node metadata\n */\n const processedDictionary =\n await processContentDeclarationContent(dictionary);\n\n let content = processedDictionary.content;\n\n /**\n * Filter locales content\n */\n\n if (dictionary.locale) {\n content = getPerLocaleDictionary(\n processedDictionary,\n dictionary.locale\n ).content;\n } else if (localeList) {\n content = getFilteredLocalesDictionary(\n processedDictionary,\n localeList\n ).content;\n }\n\n let pluginFormatResult: any = {\n ...dictionary,\n content,\n } satisfies Dictionary;\n\n /**\n * Format the dictionary with the plugins\n */\n\n for await (const plugin of configuration.plugins ?? []) {\n if (plugin.formatOutput) {\n const formattedResult = await plugin.formatOutput?.({\n dictionary: pluginFormatResult,\n configuration,\n });\n\n if (formattedResult) {\n pluginFormatResult = formattedResult;\n }\n }\n }\n\n const isDictionaryFormat =\n pluginFormatResult.content && pluginFormatResult.key;\n\n if (!isDictionaryFormat) return pluginFormatResult;\n\n // Build result from the original dictionary so that extra user-defined fields\n // (e.g. custom frontmatter in markdown files) are preserved.\n // Strip internal-only fields that must never appear in persisted output.\n const INTERNAL_FIELDS = new Set([\n '$schema',\n 'filePath',\n 'localId',\n 'localIds',\n 'projectIds',\n ]);\n\n const preservedFields = Object.fromEntries(\n Object.entries(dictionary as Record<string, unknown>).filter(\n ([k]) => !INTERNAL_FIELDS.has(k)\n )\n );\n\n let result: Dictionary = {\n ...preservedFields,\n content,\n } as Dictionary;\n\n /**\n * Add $schema to JSON dictionaries\n */\n const extension = (\n dictionary.filePath ? extname(dictionary.filePath) : '.json'\n ) as Extension;\n const format = getFormatFromExtension(extension);\n\n if (\n format === 'json' &&\n pluginFormatResult.content &&\n pluginFormatResult.key\n ) {\n result = {\n $schema: 'https://intlayer.org/schema.json',\n ...result,\n };\n }\n\n return result;\n};\n\ntype WriteContentDeclarationOptions = {\n newDictionariesPath?: string;\n localeList?: LocalesValues[];\n fallbackLocale?: Locale;\n};\n\nconst defaultOptions = {\n newDictionariesPath: 'intlayer-dictionaries',\n} satisfies WriteContentDeclarationOptions;\n\nexport const writeContentDeclaration = async (\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n options?: WriteContentDeclarationOptions\n): Promise<{ status: DictionaryStatus; path: string }> => {\n const { system, compiler } = configuration;\n const { baseDir } = system;\n\n const noMetadata = compiler?.noMetadata ?? COMPILER_NO_METADATA;\n const { newDictionariesPath, localeList } = {\n ...defaultOptions,\n ...options,\n };\n\n const newDictionaryLocationPath = join(baseDir, newDictionariesPath);\n\n const unmergedDictionariesRecord = readDictionariesFromDisk<\n Record<string, Dictionary[]>\n >(configuration.system.unmergedDictionariesDir);\n const unmergedDictionaries = unmergedDictionariesRecord[\n dictionary.key\n ] as Dictionary[];\n\n const existingDictionary = unmergedDictionaries?.find(\n (el) => el.localId === dictionary.localId\n );\n\n const formattedContentDeclaration = await formatContentDeclaration(\n dictionary,\n configuration,\n localeList\n );\n\n if (existingDictionary?.filePath) {\n // Compare existing dictionary content with new dictionary content\n const isSameContent = isDeepStrictEqual(existingDictionary, dictionary);\n\n const filePath = resolve(\n configuration.system.baseDir,\n existingDictionary.filePath\n );\n\n // Up to date, nothing to do\n if (isSameContent) {\n return {\n status: 'up-to-date',\n path: filePath,\n };\n }\n\n await writeFileWithDirectories(\n filePath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return { status: 'updated', path: filePath };\n }\n\n if (dictionary.filePath) {\n const filePath = resolve(configuration.system.baseDir, dictionary.filePath);\n\n await writeFileWithDirectories(\n filePath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return { status: 'created', path: filePath };\n }\n\n // No existing dictionary, write to new location\n const contentDeclarationPath = join(\n newDictionaryLocationPath,\n `${dictionary.key}.content.json`\n );\n\n await writeFileWithDirectories(\n contentDeclarationPath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return {\n status: 'imported',\n path: contentDeclarationPath,\n };\n};\n\nconst writeFileWithDirectories = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n noMetadata?: boolean\n): Promise<void> => {\n // Extract the directory from the file path\n const dir = dirname(absoluteFilePath);\n\n // Create the directory recursively\n await mkdir(dir, { recursive: true });\n\n const extension = extname(absoluteFilePath);\n\n if (extension === '.md' || extension === '.mdx') {\n await writeMarkdownFile(absoluteFilePath, dictionary, configuration);\n return;\n }\n\n if (extension === '.yaml' || extension === '.yml') {\n await writeYamlFile(absoluteFilePath, dictionary, configuration);\n return;\n }\n\n // Handle JSON, JSONC, and JSON5 via the AST transformer\n if (['.json', '.jsonc', '.json5'].includes(extension)) {\n let fileContent = '{}';\n\n if (existsSync(absoluteFilePath)) {\n try {\n fileContent = await readFile(absoluteFilePath, 'utf-8');\n } catch {\n // ignore read errors, start with empty object\n }\n }\n\n const transformedContent = transformJSONFile(\n fileContent,\n dictionary,\n noMetadata\n );\n\n // We use standard writeFile because transformedContent is already a string\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, transformedContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n return;\n }\n\n const knownJsExtensions = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n ]);\n\n if (!knownJsExtensions.has(extension)) {\n // Unknown extension (e.g. .po managed by a plugin) — skip; the plugin\n // owns this file format and writeJSFile / prettier would corrupt it.\n return;\n }\n\n await writeJSFile(absoluteFilePath, dictionary, configuration, noMetadata);\n\n // remove the cache as content has changed\n // Will force a new preparation of the intlayer on next build\n try {\n const sentinelPath = join(\n configuration.system.cacheDir,\n 'intlayer-prepared.lock'\n );\n await rm(sentinelPath, { recursive: true });\n } catch {}\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"writeContentDeclaration.cjs","names":["processContentDeclarationContent","getPerLocaleDictionary","getFilteredLocalesDictionary","extname","getFormatFromExtension","COMPILER_NO_METADATA","join","readDictionariesFromDisk","isDeepStrictEqual","resolve","dirname","mkdir","writeMarkdownFile","writeYamlFile","existsSync","readFile","transformJSONFile","basename","writeFile","rename","rm","detectFormatCommand","writeJSFile"],"sources":["../../../src/writeContentDeclaration/writeContentDeclaration.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, extname, join, resolve } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport { COMPILER_NO_METADATA } from '@intlayer/config/defaultValues';\nimport {\n getFilteredLocalesDictionary,\n getPerLocaleDictionary,\n} from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { detectFormatCommand } from '../detectFormatCommand';\nimport {\n type Extension,\n getFormatFromExtension,\n} from '../utils/getFormatFromExtension';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport type { DictionaryStatus } from './dictionaryStatus';\nimport { processContentDeclarationContent } from './processContentDeclarationContent';\nimport { transformJSONFile } from './transformJSONFile';\nimport { writeJSFile } from './writeJSFile';\nimport { writeMarkdownFile } from './writeMarkdownFile';\nimport { writeYamlFile } from './writeYamlFile';\n\nconst formatContentDeclaration = async (\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n localeList?: LocalesValues[]\n) => {\n /**\n * Clean Markdown, Insertion, File, etc. node metadata\n */\n const processedDictionary =\n await processContentDeclarationContent(dictionary);\n\n let content = processedDictionary.content;\n\n /**\n * Filter locales content\n */\n\n if (dictionary.locale) {\n content = getPerLocaleDictionary(\n processedDictionary,\n dictionary.locale\n ).content;\n } else if (localeList) {\n content = getFilteredLocalesDictionary(\n processedDictionary,\n localeList\n ).content;\n }\n\n let pluginFormatResult: any = {\n ...dictionary,\n content,\n } satisfies Dictionary;\n\n /**\n * Format the dictionary with the plugins\n */\n\n for await (const plugin of configuration.plugins ?? []) {\n if (plugin.formatOutput) {\n const formattedResult = await plugin.formatOutput?.({\n dictionary: pluginFormatResult,\n configuration,\n });\n\n if (formattedResult) {\n pluginFormatResult = formattedResult;\n }\n }\n }\n\n const isDictionaryFormat =\n pluginFormatResult.content && pluginFormatResult.key;\n\n if (!isDictionaryFormat) return pluginFormatResult;\n\n // Build result from the original dictionary so that extra user-defined fields\n // (e.g. custom frontmatter in markdown files) are preserved.\n // Strip internal-only fields that must never appear in persisted output.\n const INTERNAL_FIELDS = new Set([\n '$schema',\n 'filePath',\n 'localId',\n 'localIds',\n 'projectIds',\n ]);\n\n const preservedFields = Object.fromEntries(\n Object.entries(dictionary as Record<string, unknown>).filter(\n ([k]) => !INTERNAL_FIELDS.has(k)\n )\n );\n\n let result: Dictionary = {\n ...preservedFields,\n content,\n } as Dictionary;\n\n /**\n * Add $schema to JSON dictionaries\n */\n const extension = (\n dictionary.filePath ? extname(dictionary.filePath) : '.json'\n ) as Extension;\n const format = getFormatFromExtension(extension);\n\n if (\n format === 'json' &&\n pluginFormatResult.content &&\n pluginFormatResult.key\n ) {\n result = {\n $schema: 'https://intlayer.org/schema.json',\n ...result,\n };\n }\n\n return result;\n};\n\ntype WriteContentDeclarationOptions = {\n newDictionariesPath?: string;\n localeList?: LocalesValues[];\n fallbackLocale?: Locale;\n};\n\nconst defaultOptions = {\n newDictionariesPath: 'intlayer-dictionaries',\n} satisfies WriteContentDeclarationOptions;\n\nexport const writeContentDeclaration = async (\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n options?: WriteContentDeclarationOptions\n): Promise<{ status: DictionaryStatus; path: string }> => {\n const { system, compiler } = configuration;\n const { baseDir } = system;\n\n const noMetadata = compiler?.noMetadata ?? COMPILER_NO_METADATA;\n const { newDictionariesPath, localeList } = {\n ...defaultOptions,\n ...options,\n };\n\n const newDictionaryLocationPath = join(baseDir, newDictionariesPath);\n\n const unmergedDictionariesRecord = readDictionariesFromDisk<\n Record<string, Dictionary[]>\n >(configuration.system.unmergedDictionariesDir);\n const unmergedDictionaries = unmergedDictionariesRecord[\n dictionary.key\n ] as Dictionary[];\n\n const existingDictionary = unmergedDictionaries?.find(\n (el) => el.localId === dictionary.localId\n );\n\n const formattedContentDeclaration = await formatContentDeclaration(\n dictionary,\n configuration,\n localeList\n );\n\n if (existingDictionary?.filePath) {\n // Compare existing dictionary content with new dictionary content\n const isSameContent = isDeepStrictEqual(existingDictionary, dictionary);\n\n const filePath = resolve(\n configuration.system.baseDir,\n existingDictionary.filePath\n );\n\n // Up to date, nothing to do\n if (isSameContent) {\n return {\n status: 'up-to-date',\n path: filePath,\n };\n }\n\n await writeFileWithDirectories(\n filePath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return { status: 'updated', path: filePath };\n }\n\n if (dictionary.filePath) {\n const filePath = resolve(configuration.system.baseDir, dictionary.filePath);\n\n await writeFileWithDirectories(\n filePath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return { status: 'created', path: filePath };\n }\n\n // No existing dictionary, write to new location\n const contentDeclarationPath = join(\n newDictionaryLocationPath,\n `${dictionary.key}.content.json`\n );\n\n await writeFileWithDirectories(\n contentDeclarationPath,\n formattedContentDeclaration,\n configuration,\n noMetadata\n );\n\n return {\n status: 'imported',\n path: contentDeclarationPath,\n };\n};\n\nconst writeFileWithDirectories = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n noMetadata?: boolean\n): Promise<void> => {\n // Extract the directory from the file path\n const dir = dirname(absoluteFilePath);\n\n // Create the directory recursively\n await mkdir(dir, { recursive: true });\n\n const extension = extname(absoluteFilePath);\n\n if (extension === '.md' || extension === '.mdx') {\n await writeMarkdownFile(absoluteFilePath, dictionary, configuration);\n return;\n }\n\n if (extension === '.yaml' || extension === '.yml') {\n await writeYamlFile(absoluteFilePath, dictionary, configuration);\n return;\n }\n\n // Handle JSON, JSONC, and JSON5 via the AST transformer\n if (['.json', '.jsonc', '.json5'].includes(extension)) {\n let fileContent = '{}';\n\n if (existsSync(absoluteFilePath)) {\n try {\n fileContent = await readFile(absoluteFilePath, 'utf-8');\n } catch {\n // ignore read errors, start with empty object\n }\n }\n\n const transformedContent = transformJSONFile(\n fileContent,\n dictionary,\n noMetadata\n );\n\n // We use standard writeFile because transformedContent is already a string\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, transformedContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n return;\n }\n\n const knownJsExtensions = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n ]);\n\n if (!knownJsExtensions.has(extension)) {\n // Unknown extension (e.g. .po managed by a plugin) — skip; the plugin\n // owns this file format and writeJSFile / prettier would corrupt it.\n return;\n }\n\n await writeJSFile(absoluteFilePath, dictionary, configuration, noMetadata);\n\n // remove the cache as content has changed\n // Will force a new preparation of the intlayer on next build\n try {\n const sentinelPath = join(\n configuration.system.cacheDir,\n 'intlayer-prepared.lock'\n );\n await rm(sentinelPath, { recursive: true });\n } catch {}\n};\n"],"mappings":"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"}
|
|
@@ -23,7 +23,8 @@ const writeJSFile = async (filePath, dictionary, configuration, noMetadata) => {
|
|
|
23
23
|
};
|
|
24
24
|
const appLogger = (0, _intlayer_config_logger.getAppLogger)(configuration);
|
|
25
25
|
if (!(0, node_fs.existsSync)(filePath)) {
|
|
26
|
-
const
|
|
26
|
+
const fileExtension = (0, node_path.extname)(filePath);
|
|
27
|
+
const format = require_utils_getFormatFromExtension.getFormatFromExtension(fileExtension);
|
|
27
28
|
appLogger("File does not exist, creating it", { isVerbose: true });
|
|
28
29
|
const template = await require_getContentDeclarationFileTemplate_getContentDeclarationFileTemplate.getContentDeclarationFileTemplate(mergedDictionary.key, format, Object.fromEntries(Object.entries({
|
|
29
30
|
id: noMetadata ? void 0 : mergedDictionary.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeJSFile.cjs","names":["getFormatFromExtension","getContentDeclarationFileTemplate","transformJSFile","detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeJSFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, extname, join } from 'node:path';\nimport { getAppLogger, logger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { detectFormatCommand } from '../detectFormatCommand';\nimport { getContentDeclarationFileTemplate } from '../getContentDeclarationFileTemplate/getContentDeclarationFileTemplate';\nimport {\n type Extension,\n getFormatFromExtension,\n} from '../utils/getFormatFromExtension';\nimport { transformJSFile } from './transformJSFile';\n\n/**\n * Updates a JavaScript/TypeScript file based on the provided JSON instructions.\n * It targets a specific dictionary object within the file (identified by its 'key' property)\n * and updates its 'content' entries. Currently, it focuses on modifying arguments\n * of 't' (translation) function calls.\n */\nexport const writeJSFile = async (\n filePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n noMetadata?: boolean\n): Promise<void> => {\n const mergedDictionary = {\n ...configuration.dictionary,\n ...dictionary,\n };\n\n const appLogger = getAppLogger(configuration);\n\n // Check if the file exist\n if (!existsSync(filePath)) {\n const fileExtension = extname(filePath) as Extension;\n\n const format = getFormatFromExtension(fileExtension);\n\n appLogger('File does not exist, creating it', {\n isVerbose: true,\n });\n const template = await getContentDeclarationFileTemplate(\n mergedDictionary.key,\n format,\n // Filter out undefined values\n Object.fromEntries(\n Object.entries({\n id: noMetadata ? undefined : mergedDictionary.id,\n locale: noMetadata ? undefined : mergedDictionary.locale,\n filled: noMetadata ? undefined : mergedDictionary.filled,\n fill: noMetadata ? undefined : mergedDictionary.fill,\n description: noMetadata ? undefined : mergedDictionary.description,\n title: noMetadata ? undefined : mergedDictionary.title,\n tags: noMetadata ? undefined : mergedDictionary.tags,\n version: noMetadata ? undefined : mergedDictionary.version,\n priority: noMetadata ? undefined : mergedDictionary.priority,\n importMode: noMetadata ? undefined : mergedDictionary.importMode,\n }).filter(([, value]) => value !== undefined)\n ),\n noMetadata\n );\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(filePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${filePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, template, 'utf-8');\n await rename(tempPath, filePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n throw error;\n }\n }\n\n let fileContent = await readFile(filePath, 'utf-8');\n\n if (fileContent === '') {\n const format = getFormatFromExtension(extname(filePath) as Extension);\n\n fileContent = await getContentDeclarationFileTemplate(\n mergedDictionary.key,\n format,\n {},\n noMetadata\n );\n }\n\n const finalCode = await transformJSFile(\n fileContent,\n dictionary,\n dictionary.locale as any,\n noMetadata\n );\n\n // Write the modified code back to the file\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(filePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${filePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, finalCode, 'utf-8');\n await rename(tempPath, filePath);\n logger(`Successfully updated ${filePath}`, {\n level: 'info',\n isVerbose: true,\n });\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n const err = error as Error;\n logger(`Failed to write updated file: ${filePath}`, {\n level: 'error',\n });\n throw new Error(`Failed to write updated file ${filePath}: ${err.message}`);\n }\n\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,MAAa,cAAc,OACzB,UACA,YACA,eACA,eACkB;CAClB,MAAM,mBAAmB;EACvB,GAAG,cAAc;EACjB,GAAG;CACL;CAEA,MAAM,
|
|
1
|
+
{"version":3,"file":"writeJSFile.cjs","names":["getAppLogger","existsSync","extname","getFormatFromExtension","getContentDeclarationFileTemplate","mkdir","basename","join","writeFile","rename","rm","readFile","transformJSFile","detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeJSFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, extname, join } from 'node:path';\nimport { getAppLogger, logger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { detectFormatCommand } from '../detectFormatCommand';\nimport { getContentDeclarationFileTemplate } from '../getContentDeclarationFileTemplate/getContentDeclarationFileTemplate';\nimport {\n type Extension,\n getFormatFromExtension,\n} from '../utils/getFormatFromExtension';\nimport { transformJSFile } from './transformJSFile';\n\n/**\n * Updates a JavaScript/TypeScript file based on the provided JSON instructions.\n * It targets a specific dictionary object within the file (identified by its 'key' property)\n * and updates its 'content' entries. Currently, it focuses on modifying arguments\n * of 't' (translation) function calls.\n */\nexport const writeJSFile = async (\n filePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig,\n noMetadata?: boolean\n): Promise<void> => {\n const mergedDictionary = {\n ...configuration.dictionary,\n ...dictionary,\n };\n\n const appLogger = getAppLogger(configuration);\n\n // Check if the file exist\n if (!existsSync(filePath)) {\n const fileExtension = extname(filePath) as Extension;\n\n const format = getFormatFromExtension(fileExtension);\n\n appLogger('File does not exist, creating it', {\n isVerbose: true,\n });\n const template = await getContentDeclarationFileTemplate(\n mergedDictionary.key,\n format,\n // Filter out undefined values\n Object.fromEntries(\n Object.entries({\n id: noMetadata ? undefined : mergedDictionary.id,\n locale: noMetadata ? undefined : mergedDictionary.locale,\n filled: noMetadata ? undefined : mergedDictionary.filled,\n fill: noMetadata ? undefined : mergedDictionary.fill,\n description: noMetadata ? undefined : mergedDictionary.description,\n title: noMetadata ? undefined : mergedDictionary.title,\n tags: noMetadata ? undefined : mergedDictionary.tags,\n version: noMetadata ? undefined : mergedDictionary.version,\n priority: noMetadata ? undefined : mergedDictionary.priority,\n importMode: noMetadata ? undefined : mergedDictionary.importMode,\n }).filter(([, value]) => value !== undefined)\n ),\n noMetadata\n );\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(filePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${filePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, template, 'utf-8');\n await rename(tempPath, filePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n throw error;\n }\n }\n\n let fileContent = await readFile(filePath, 'utf-8');\n\n if (fileContent === '') {\n const format = getFormatFromExtension(extname(filePath) as Extension);\n\n fileContent = await getContentDeclarationFileTemplate(\n mergedDictionary.key,\n format,\n {},\n noMetadata\n );\n }\n\n const finalCode = await transformJSFile(\n fileContent,\n dictionary,\n dictionary.locale as any,\n noMetadata\n );\n\n // Write the modified code back to the file\n const tempDir = configuration.system?.tempDir;\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(filePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${filePath}.${tempFileName}`;\n try {\n await writeFile(tempPath, finalCode, 'utf-8');\n await rename(tempPath, filePath);\n logger(`Successfully updated ${filePath}`, {\n level: 'info',\n isVerbose: true,\n });\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // Ignore\n }\n const err = error as Error;\n logger(`Failed to write updated file: ${filePath}`, {\n level: 'error',\n });\n throw new Error(`Failed to write updated file ${filePath}: ${err.message}`);\n }\n\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":"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"}
|
|
@@ -37,7 +37,8 @@ const writeMarkdownFile = async (absoluteFilePath, dictionary, configuration) =>
|
|
|
37
37
|
const markdownBody = getMarkdownBody(markdownRaw);
|
|
38
38
|
const frontmatterFields = Object.fromEntries(Object.entries(dictionary).filter(([k, v]) => !EXCLUDED_FRONTMATTER_KEYS.has(k) && v !== void 0));
|
|
39
39
|
const fileContent = `---\n${stringifyYamlFrontmatter(frontmatterFields)}\n---\n\n${markdownBody}`;
|
|
40
|
-
|
|
40
|
+
const dir = (0, node_path.dirname)(absoluteFilePath);
|
|
41
|
+
await (0, node_fs_promises.mkdir)(dir, { recursive: true });
|
|
41
42
|
const tempDir = configuration.system?.tempDir;
|
|
42
43
|
if (tempDir) await (0, node_fs_promises.mkdir)(tempDir, { recursive: true });
|
|
43
44
|
const tempFileName = `${(0, node_path.basename)(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeMarkdownFile.cjs","names":["MARKDOWN","detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeMarkdownFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { MARKDOWN } from '@intlayer/types/nodeType';\nimport { detectFormatCommand } from '../detectFormatCommand';\n\nconst stringifyYamlFrontmatter = (fields: Record<string, any>): string =>\n Object.entries(fields)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => {\n if (Array.isArray(value)) {\n return `${key}:\\n${value.map((item) => ` - ${JSON.stringify(item)}`).join('\\n')}`;\n }\n if (\n typeof value === 'string' &&\n (value.includes(':') || value.includes('\\n') || value.includes('#'))\n ) {\n return `${key}: ${JSON.stringify(value)}`;\n }\n return `${key}: ${value}`;\n })\n .join('\\n');\n\n// Strips YAML frontmatter from a markdown string, returning only the body\nconst getMarkdownBody = (content: string): string => {\n const lines = content.split(/\\r?\\n/);\n const firstNonEmptyIndex = lines.findIndex((line) => line.trim() !== '');\n\n if (firstNonEmptyIndex === -1 || lines[firstNonEmptyIndex].trim() !== '---') {\n return content;\n }\n\n let endIndex = -1;\n for (let i = firstNonEmptyIndex + 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n endIndex = i;\n break;\n }\n }\n\n if (endIndex === -1) return content;\n\n return lines\n .slice(endIndex + 1)\n .join('\\n')\n .trimStart();\n};\n\n// Fields that are auto-generated / internal and must not appear in frontmatter\nconst EXCLUDED_FRONTMATTER_KEYS = new Set<string>([\n 'content',\n '$schema',\n 'filePath',\n 'localId',\n 'localIds',\n 'projectIds',\n]);\n\nexport const writeMarkdownFile = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig\n): Promise<void> => {\n const content = dictionary.content as any;\n const markdownRaw =\n typeof content === 'object' && content?.nodeType === MARKDOWN\n ? (content[MARKDOWN] ?? '')\n : '';\n // content.markdown now stores the full file (frontmatter + body); extract only the body\n const markdownBody = getMarkdownBody(markdownRaw);\n\n const frontmatterFields = Object.fromEntries(\n Object.entries(dictionary).filter(\n ([k, v]) => !EXCLUDED_FRONTMATTER_KEYS.has(k) && v !== undefined\n )\n );\n\n const frontmatterStr = stringifyYamlFrontmatter(frontmatterFields);\n const fileContent = `---\\n${frontmatterStr}\\n---\\n\\n${markdownBody}`;\n\n const dir = dirname(absoluteFilePath);\n await mkdir(dir, { recursive: true });\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) await mkdir(tempDir, { recursive: true });\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n\n try {\n await writeFile(tempPath, fileContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":";;;;;;;;AAQA,MAAM,4BAA4B,WAChC,OAAO,QAAQ,MAAM,CAAC,CACnB,QAAQ,GAAG,WAAW,UAAU,UAAa,UAAU,IAAI,CAAC,CAC5D,KAAK,CAAC,KAAK,WAAW;CACrB,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,GAAG,IAAI,KAAK,MAAM,KAAK,SAAS,OAAO,KAAK,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI;CAEjF,IACE,OAAO,UAAU,aAChB,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,GAAG,IAElE,OAAO,GAAG,IAAI,IAAI,KAAK,UAAU,KAAK;CAExC,OAAO,GAAG,IAAI,IAAI;AACpB,CAAC,CAAC,CACD,KAAK,IAAI;AAGd,MAAM,mBAAmB,YAA4B;CACnD,MAAM,QAAQ,QAAQ,MAAM,OAAO;CACnC,MAAM,qBAAqB,MAAM,WAAW,SAAS,KAAK,KAAK,MAAM,EAAE;CAEvE,IAAI,uBAAuB,MAAM,MAAM,mBAAmB,CAAC,KAAK,MAAM,OACpE,OAAO;CAGT,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,qBAAqB,GAAG,IAAI,MAAM,QAAQ,KACrD,IAAI,MAAM,EAAE,CAAC,KAAK,MAAM,OAAO;EAC7B,WAAW;EACX;CACF;CAGF,IAAI,aAAa,IAAI,OAAO;CAE5B,OAAO,MACJ,MAAM,WAAW,CAAC,CAAC,CACnB,KAAK,IAAI,CAAC,CACV,UAAU;AACf;AAGA,MAAM,4CAA4B,IAAI,IAAY;CAChD;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAa,oBAAoB,OAC/B,kBACA,YACA,kBACkB;CAClB,MAAM,UAAU,WAAW;CAC3B,MAAM,cACJ,OAAO,YAAY,YAAY,SAAS,aAAaA,oCAChD,QAAQA,sCAAa,KACtB;CAEN,MAAM,eAAe,gBAAgB,WAAW;CAEhD,MAAM,oBAAoB,OAAO,YAC/B,OAAO,QAAQ,UAAU,CAAC,CAAC,QACxB,CAAC,GAAG,OAAO,CAAC,0BAA0B,IAAI,CAAC,KAAK,MAAM,MACzD,CACF;CAGA,MAAM,cAAc,QADG,yBAAyB,iBACP,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"writeMarkdownFile.cjs","names":["MARKDOWN","dirname","mkdir","basename","join","writeFile","rename","rm","detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeMarkdownFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { MARKDOWN } from '@intlayer/types/nodeType';\nimport { detectFormatCommand } from '../detectFormatCommand';\n\nconst stringifyYamlFrontmatter = (fields: Record<string, any>): string =>\n Object.entries(fields)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => {\n if (Array.isArray(value)) {\n return `${key}:\\n${value.map((item) => ` - ${JSON.stringify(item)}`).join('\\n')}`;\n }\n if (\n typeof value === 'string' &&\n (value.includes(':') || value.includes('\\n') || value.includes('#'))\n ) {\n return `${key}: ${JSON.stringify(value)}`;\n }\n return `${key}: ${value}`;\n })\n .join('\\n');\n\n// Strips YAML frontmatter from a markdown string, returning only the body\nconst getMarkdownBody = (content: string): string => {\n const lines = content.split(/\\r?\\n/);\n const firstNonEmptyIndex = lines.findIndex((line) => line.trim() !== '');\n\n if (firstNonEmptyIndex === -1 || lines[firstNonEmptyIndex].trim() !== '---') {\n return content;\n }\n\n let endIndex = -1;\n for (let i = firstNonEmptyIndex + 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n endIndex = i;\n break;\n }\n }\n\n if (endIndex === -1) return content;\n\n return lines\n .slice(endIndex + 1)\n .join('\\n')\n .trimStart();\n};\n\n// Fields that are auto-generated / internal and must not appear in frontmatter\nconst EXCLUDED_FRONTMATTER_KEYS = new Set<string>([\n 'content',\n '$schema',\n 'filePath',\n 'localId',\n 'localIds',\n 'projectIds',\n]);\n\nexport const writeMarkdownFile = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig\n): Promise<void> => {\n const content = dictionary.content as any;\n const markdownRaw =\n typeof content === 'object' && content?.nodeType === MARKDOWN\n ? (content[MARKDOWN] ?? '')\n : '';\n // content.markdown now stores the full file (frontmatter + body); extract only the body\n const markdownBody = getMarkdownBody(markdownRaw);\n\n const frontmatterFields = Object.fromEntries(\n Object.entries(dictionary).filter(\n ([k, v]) => !EXCLUDED_FRONTMATTER_KEYS.has(k) && v !== undefined\n )\n );\n\n const frontmatterStr = stringifyYamlFrontmatter(frontmatterFields);\n const fileContent = `---\\n${frontmatterStr}\\n---\\n\\n${markdownBody}`;\n\n const dir = dirname(absoluteFilePath);\n await mkdir(dir, { recursive: true });\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) await mkdir(tempDir, { recursive: true });\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n\n try {\n await writeFile(tempPath, fileContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":";;;;;;;;AAQA,MAAM,4BAA4B,WAChC,OAAO,QAAQ,MAAM,CAAC,CACnB,QAAQ,GAAG,WAAW,UAAU,UAAa,UAAU,IAAI,CAAC,CAC5D,KAAK,CAAC,KAAK,WAAW;CACrB,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,GAAG,IAAI,KAAK,MAAM,KAAK,SAAS,OAAO,KAAK,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI;CAEjF,IACE,OAAO,UAAU,aAChB,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,GAAG,IAElE,OAAO,GAAG,IAAI,IAAI,KAAK,UAAU,KAAK;CAExC,OAAO,GAAG,IAAI,IAAI;AACpB,CAAC,CAAC,CACD,KAAK,IAAI;AAGd,MAAM,mBAAmB,YAA4B;CACnD,MAAM,QAAQ,QAAQ,MAAM,OAAO;CACnC,MAAM,qBAAqB,MAAM,WAAW,SAAS,KAAK,KAAK,MAAM,EAAE;CAEvE,IAAI,uBAAuB,MAAM,MAAM,mBAAmB,CAAC,KAAK,MAAM,OACpE,OAAO;CAGT,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,qBAAqB,GAAG,IAAI,MAAM,QAAQ,KACrD,IAAI,MAAM,EAAE,CAAC,KAAK,MAAM,OAAO;EAC7B,WAAW;EACX;CACF;CAGF,IAAI,aAAa,IAAI,OAAO;CAE5B,OAAO,MACJ,MAAM,WAAW,CAAC,CAAC,CACnB,KAAK,IAAI,CAAC,CACV,UAAU;AACf;AAGA,MAAM,4CAA4B,IAAI,IAAY;CAChD;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAa,oBAAoB,OAC/B,kBACA,YACA,kBACkB;CAClB,MAAM,UAAU,WAAW;CAC3B,MAAM,cACJ,OAAO,YAAY,YAAY,SAAS,aAAaA,oCAChD,QAAQA,sCAAa,KACtB;CAEN,MAAM,eAAe,gBAAgB,WAAW;CAEhD,MAAM,oBAAoB,OAAO,YAC/B,OAAO,QAAQ,UAAU,CAAC,CAAC,QACxB,CAAC,GAAG,OAAO,CAAC,0BAA0B,IAAI,CAAC,KAAK,MAAM,MACzD,CACF;CAGA,MAAM,cAAc,QADG,yBAAyB,iBACP,EAAE,WAAW;CAEtD,MAAM,UAAMC,mBAAQ,gBAAgB;CACpC,UAAMC,wBAAM,KAAK,EAAE,WAAW,KAAK,CAAC;CAEpC,MAAM,UAAU,cAAc,QAAQ;CACtC,IAAI,SAAS,UAAMA,wBAAM,SAAS,EAAE,WAAW,KAAK,CAAC;CAErD,MAAM,eAAe,OAAGC,oBAAS,gBAAgB,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;CACxG,MAAM,WAAW,cACbC,gBAAK,SAAS,YAAY,IAC1B,GAAG,iBAAiB,GAAG;CAE3B,IAAI;EACF,UAAMC,4BAAU,UAAU,aAAa,OAAO;EAC9C,UAAMC,yBAAO,UAAU,gBAAgB;CACzC,SAAS,OAAO;EACd,IAAI;GACF,UAAMC,qBAAG,UAAU,EAAE,OAAO,KAAK,CAAC;EACpC,QAAQ,CAER;EACA,MAAM;CACR;CAEA,MAAM,gBAAgBC,gDAAoB,aAAa;CACvD,IAAI,eACF,IAAI;EACF,iCAAS,cAAc,QAAQ,YAAY,gBAAgB,GAAG;GAC5D,OAAO;GACP,KAAK,cAAc,OAAO;EAC5B,CAAC;CACH,SAAS,OAAO;EACd,QAAQ,MAAM,KAAK;CACrB;AAEJ"}
|
|
@@ -12,8 +12,10 @@ const EXCLUDED_YAML_KEYS = /* @__PURE__ */ new Set([
|
|
|
12
12
|
"filePath"
|
|
13
13
|
]);
|
|
14
14
|
const writeYamlFile = async (absoluteFilePath, dictionary, configuration) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const filtered = Object.fromEntries(Object.entries(dictionary).filter(([k, v]) => !EXCLUDED_YAML_KEYS.has(k) && v !== void 0));
|
|
16
|
+
const fileContent = (0, _intlayer_core_utils.stringifyYaml)(filtered);
|
|
17
|
+
const dir = (0, node_path.dirname)(absoluteFilePath);
|
|
18
|
+
await (0, node_fs_promises.mkdir)(dir, { recursive: true });
|
|
17
19
|
const tempDir = configuration.system?.tempDir;
|
|
18
20
|
if (tempDir) await (0, node_fs_promises.mkdir)(tempDir, { recursive: true });
|
|
19
21
|
const tempFileName = `${(0, node_path.basename)(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeYamlFile.cjs","names":["detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeYamlFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport { stringifyYaml } from '@intlayer/core/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { detectFormatCommand } from '../detectFormatCommand';\n\n// Fields that are auto-generated or runtime-only, not persisted in the file\nconst EXCLUDED_YAML_KEYS = new Set<string>(['$schema', 'id', 'filePath']);\n\nexport const writeYamlFile = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig\n): Promise<void> => {\n const filtered = Object.fromEntries(\n Object.entries(dictionary).filter(\n ([k, v]) => !EXCLUDED_YAML_KEYS.has(k) && v !== undefined\n )\n );\n\n const fileContent = stringifyYaml(filtered);\n\n const dir = dirname(absoluteFilePath);\n await mkdir(dir, { recursive: true });\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) await mkdir(tempDir, { recursive: true });\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n\n try {\n await writeFile(tempPath, fileContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":";;;;;;;;AASA,MAAM,qCAAqB,IAAI,IAAY;CAAC;CAAW;CAAM;AAAU,CAAC;AAExE,MAAa,gBAAgB,OAC3B,kBACA,YACA,kBACkB;
|
|
1
|
+
{"version":3,"file":"writeYamlFile.cjs","names":["stringifyYaml","dirname","mkdir","basename","join","writeFile","rename","rm","detectFormatCommand"],"sources":["../../../src/writeContentDeclaration/writeYamlFile.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport { stringifyYaml } from '@intlayer/core/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { detectFormatCommand } from '../detectFormatCommand';\n\n// Fields that are auto-generated or runtime-only, not persisted in the file\nconst EXCLUDED_YAML_KEYS = new Set<string>(['$schema', 'id', 'filePath']);\n\nexport const writeYamlFile = async (\n absoluteFilePath: string,\n dictionary: Dictionary,\n configuration: IntlayerConfig\n): Promise<void> => {\n const filtered = Object.fromEntries(\n Object.entries(dictionary).filter(\n ([k, v]) => !EXCLUDED_YAML_KEYS.has(k) && v !== undefined\n )\n );\n\n const fileContent = stringifyYaml(filtered);\n\n const dir = dirname(absoluteFilePath);\n await mkdir(dir, { recursive: true });\n\n const tempDir = configuration.system?.tempDir;\n if (tempDir) await mkdir(tempDir, { recursive: true });\n\n const tempFileName = `${basename(absoluteFilePath)}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${absoluteFilePath}.${tempFileName}`;\n\n try {\n await writeFile(tempPath, fileContent, 'utf-8');\n await rename(tempPath, absoluteFilePath);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {\n // ignore\n }\n throw error;\n }\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', absoluteFilePath), {\n stdio: 'inherit',\n cwd: configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n};\n"],"mappings":";;;;;;;;AASA,MAAM,qCAAqB,IAAI,IAAY;CAAC;CAAW;CAAM;AAAU,CAAC;AAExE,MAAa,gBAAgB,OAC3B,kBACA,YACA,kBACkB;CAClB,MAAM,WAAW,OAAO,YACtB,OAAO,QAAQ,UAAU,CAAC,CAAC,QACxB,CAAC,GAAG,OAAO,CAAC,mBAAmB,IAAI,CAAC,KAAK,MAAM,MAClD,CACF;CAEA,MAAM,kBAAcA,oCAAc,QAAQ;CAE1C,MAAM,UAAMC,mBAAQ,gBAAgB;CACpC,UAAMC,wBAAM,KAAK,EAAE,WAAW,KAAK,CAAC;CAEpC,MAAM,UAAU,cAAc,QAAQ;CACtC,IAAI,SAAS,UAAMA,wBAAM,SAAS,EAAE,WAAW,KAAK,CAAC;CAErD,MAAM,eAAe,OAAGC,oBAAS,gBAAgB,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;CACxG,MAAM,WAAW,cACbC,gBAAK,SAAS,YAAY,IAC1B,GAAG,iBAAiB,GAAG;CAE3B,IAAI;EACF,UAAMC,4BAAU,UAAU,aAAa,OAAO;EAC9C,UAAMC,yBAAO,UAAU,gBAAgB;CACzC,SAAS,OAAO;EACd,IAAI;GACF,UAAMC,qBAAG,UAAU,EAAE,OAAO,KAAK,CAAC;EACpC,QAAQ,CAER;EACA,MAAM;CACR;CAEA,MAAM,gBAAgBC,gDAAoB,aAAa;CACvD,IAAI,eACF,IAAI;EACF,iCAAS,cAAc,QAAQ,YAAY,gBAAgB,GAAG;GAC5D,OAAO;GACP,KAAK,cAAc,OAAO;EAC5B,CAAC;CACH,SAAS,OAAO;EACd,QAAQ,MAAM,KAAK;CACrB;AAEJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeFileIfChanged.cjs","names":[],"sources":["../../src/writeFileIfChanged.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { rmSync } from 'node:fs';\nimport {\n chmod,\n mkdir,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\n\nconst activeTempFiles = new Set<string>();\n\n// Synchronous cleanup on process exit\nprocess.on('exit', () => {\n for (const file of activeTempFiles) {\n try {\n rmSync(file, { force: true });\n } catch {}\n }\n});\n\n/**\n * Permission bits a freshly created file receives on this system. Detected once\n * from the first temp file we actually write (`process.umask()` with no\n * argument is deprecated and thread-unsafe) and cached, so the atomic path can\n * skip restoring the mode whenever the source file already uses the default\n * mode — which is the case for essentially every generated file.\n */\nlet defaultFileMode: number | undefined;\n\n/**\n * Options for {@link writeFileIfChanged}.\n */\nexport type WriteFileIfChangedOptions = {\n /** Encoding used to turn `data` into bytes. Defaults to `'utf8'`. */\n encoding?: BufferEncoding;\n /** Directory to hold the temporary file used for the atomic swap. */\n tempDir?: string;\n /**\n * Write atomically via a temp file + `rename` so readers never observe a\n * half-written file. This creates a fresh inode on every write, which roughly\n * doubles the cost of a changed write compared to overwriting in place. Set to\n * `false` for callers whose consumers tolerate torn reads to write directly.\n * Defaults to `true`.\n */\n atomic?: boolean;\n};\n\n/**\n * Write `data` to `path` only when it differs from the file already on disk,\n * preserving the existing file's permission mode.\n *\n * The whole file is read back and byte-compared because the files written here\n * (dictionaries, entry points, types) are small, so reading beats streaming a\n * hash. When the content is unchanged the write is skipped entirely, which both\n * avoids inode churn and prevents downstream watchers from rebuilding.\n *\n * @returns `true` when the file was written, `false` when it was already up to date.\n */\nexport const writeFileIfChanged = async (\n path: string,\n data: string,\n { encoding = 'utf8', tempDir, atomic = true }: WriteFileIfChangedOptions = {}\n): Promise<boolean> => {\n const newData = Buffer.from(data, encoding);\n\n // Read the current content first: the common case is an unchanged file, and\n // this single read is the whole fast path (no stat/chmod needed to bail out).\n let existingData: Buffer | null = null;\n try {\n existingData = await readFile(path);\n } catch {}\n\n if (existingData?.equals(newData)) {\n return false;\n }\n\n // Fast path: overwrite in place. Truncating an existing file keeps its inode,\n // so its permission mode is preserved automatically (no chmod needed). This\n // skips the temp-file inode churn at the cost of exposing readers to a\n // partially written file.\n if (!atomic) {\n await writeFile(path, newData);\n return true;\n }\n\n // The atomic swap replaces the inode, so the existing mode is not preserved\n // and must be reapplied. Only a file that already exists has a mode to keep.\n let modeToRestore: number | undefined;\n if (existingData !== null) {\n try {\n modeToRestore = (await stat(path)).mode & 0o777;\n } catch {}\n }\n\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(path)}.${Date.now()}-${randomBytes(4).toString('hex')}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${path}.${tempFileName}`;\n activeTempFiles.add(tempPath);\n\n try {\n for (let attempt = 0; ; attempt++) {\n try {\n await writeFile(tempPath, newData);\n\n if (modeToRestore !== undefined) {\n // Learn the ambient default mode once from a real temp file, then only\n // chmod when the source file used a non-default mode.\n if (defaultFileMode === undefined) {\n try {\n defaultFileMode = (await stat(tempPath)).mode & 0o777;\n } catch {}\n }\n if (modeToRestore !== defaultFileMode) {\n await chmod(tempPath, modeToRestore);\n }\n }\n\n await rename(tempPath, path);\n break;\n } catch (error) {\n const isMissingDirectory =\n (error as NodeJS.ErrnoException).code === 'ENOENT';\n\n if (!isMissingDirectory || attempt > 0) throw error;\n\n await mkdir(dirname(path), { recursive: true });\n if (tempDir) await mkdir(tempDir, { recursive: true });\n }\n }\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {}\n throw error;\n } finally {\n activeTempFiles.delete(tempPath);\n }\n\n return true;\n};\n"],"mappings":";;;;;;;AAaA,MAAM,kCAAkB,IAAI,IAAY;AAGxC,QAAQ,GAAG,cAAc;CACvB,KAAK,MAAM,QAAQ,iBACjB,IAAI;EACF,oBAAO,MAAM,EAAE,OAAO,KAAK,CAAC;CAC9B,QAAQ,CAAC;AAEb,CAAC;;;;;;;;AASD,IAAI;;;;;;;;;;;;AA+BJ,MAAa,qBAAqB,OAChC,MACA,MACA,EAAE,WAAW,QAAQ,SAAS,SAAS,SAAoC,CAAC,MACvD;CACrB,MAAM,UAAU,OAAO,KAAK,MAAM,QAAQ;CAI1C,IAAI,eAA8B;CAClC,IAAI;EACF,eAAe,
|
|
1
|
+
{"version":3,"file":"writeFileIfChanged.cjs","names":["readFile","writeFile","stat","mkdir","basename","randomBytes","join","chmod","rename","dirname","rm"],"sources":["../../src/writeFileIfChanged.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { rmSync } from 'node:fs';\nimport {\n chmod,\n mkdir,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\n\nconst activeTempFiles = new Set<string>();\n\n// Synchronous cleanup on process exit\nprocess.on('exit', () => {\n for (const file of activeTempFiles) {\n try {\n rmSync(file, { force: true });\n } catch {}\n }\n});\n\n/**\n * Permission bits a freshly created file receives on this system. Detected once\n * from the first temp file we actually write (`process.umask()` with no\n * argument is deprecated and thread-unsafe) and cached, so the atomic path can\n * skip restoring the mode whenever the source file already uses the default\n * mode — which is the case for essentially every generated file.\n */\nlet defaultFileMode: number | undefined;\n\n/**\n * Options for {@link writeFileIfChanged}.\n */\nexport type WriteFileIfChangedOptions = {\n /** Encoding used to turn `data` into bytes. Defaults to `'utf8'`. */\n encoding?: BufferEncoding;\n /** Directory to hold the temporary file used for the atomic swap. */\n tempDir?: string;\n /**\n * Write atomically via a temp file + `rename` so readers never observe a\n * half-written file. This creates a fresh inode on every write, which roughly\n * doubles the cost of a changed write compared to overwriting in place. Set to\n * `false` for callers whose consumers tolerate torn reads to write directly.\n * Defaults to `true`.\n */\n atomic?: boolean;\n};\n\n/**\n * Write `data` to `path` only when it differs from the file already on disk,\n * preserving the existing file's permission mode.\n *\n * The whole file is read back and byte-compared because the files written here\n * (dictionaries, entry points, types) are small, so reading beats streaming a\n * hash. When the content is unchanged the write is skipped entirely, which both\n * avoids inode churn and prevents downstream watchers from rebuilding.\n *\n * @returns `true` when the file was written, `false` when it was already up to date.\n */\nexport const writeFileIfChanged = async (\n path: string,\n data: string,\n { encoding = 'utf8', tempDir, atomic = true }: WriteFileIfChangedOptions = {}\n): Promise<boolean> => {\n const newData = Buffer.from(data, encoding);\n\n // Read the current content first: the common case is an unchanged file, and\n // this single read is the whole fast path (no stat/chmod needed to bail out).\n let existingData: Buffer | null = null;\n try {\n existingData = await readFile(path);\n } catch {}\n\n if (existingData?.equals(newData)) {\n return false;\n }\n\n // Fast path: overwrite in place. Truncating an existing file keeps its inode,\n // so its permission mode is preserved automatically (no chmod needed). This\n // skips the temp-file inode churn at the cost of exposing readers to a\n // partially written file.\n if (!atomic) {\n await writeFile(path, newData);\n return true;\n }\n\n // The atomic swap replaces the inode, so the existing mode is not preserved\n // and must be reapplied. Only a file that already exists has a mode to keep.\n let modeToRestore: number | undefined;\n if (existingData !== null) {\n try {\n modeToRestore = (await stat(path)).mode & 0o777;\n } catch {}\n }\n\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(path)}.${Date.now()}-${randomBytes(4).toString('hex')}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${path}.${tempFileName}`;\n activeTempFiles.add(tempPath);\n\n try {\n for (let attempt = 0; ; attempt++) {\n try {\n await writeFile(tempPath, newData);\n\n if (modeToRestore !== undefined) {\n // Learn the ambient default mode once from a real temp file, then only\n // chmod when the source file used a non-default mode.\n if (defaultFileMode === undefined) {\n try {\n defaultFileMode = (await stat(tempPath)).mode & 0o777;\n } catch {}\n }\n if (modeToRestore !== defaultFileMode) {\n await chmod(tempPath, modeToRestore);\n }\n }\n\n await rename(tempPath, path);\n break;\n } catch (error) {\n const isMissingDirectory =\n (error as NodeJS.ErrnoException).code === 'ENOENT';\n\n if (!isMissingDirectory || attempt > 0) throw error;\n\n await mkdir(dirname(path), { recursive: true });\n if (tempDir) await mkdir(tempDir, { recursive: true });\n }\n }\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {}\n throw error;\n } finally {\n activeTempFiles.delete(tempPath);\n }\n\n return true;\n};\n"],"mappings":";;;;;;;AAaA,MAAM,kCAAkB,IAAI,IAAY;AAGxC,QAAQ,GAAG,cAAc;CACvB,KAAK,MAAM,QAAQ,iBACjB,IAAI;EACF,oBAAO,MAAM,EAAE,OAAO,KAAK,CAAC;CAC9B,QAAQ,CAAC;AAEb,CAAC;;;;;;;;AASD,IAAI;;;;;;;;;;;;AA+BJ,MAAa,qBAAqB,OAChC,MACA,MACA,EAAE,WAAW,QAAQ,SAAS,SAAS,SAAoC,CAAC,MACvD;CACrB,MAAM,UAAU,OAAO,KAAK,MAAM,QAAQ;CAI1C,IAAI,eAA8B;CAClC,IAAI;EACF,eAAe,UAAMA,2BAAS,IAAI;CACpC,QAAQ,CAAC;CAET,IAAI,cAAc,OAAO,OAAO,GAC9B,OAAO;CAOT,IAAI,CAAC,QAAQ;EACX,UAAMC,4BAAU,MAAM,OAAO;EAC7B,OAAO;CACT;CAIA,IAAI;CACJ,IAAI,iBAAiB,MACnB,IAAI;EACF,iBAAiB,UAAMC,uBAAK,IAAI,EAAC,CAAE,OAAO;CAC5C,QAAQ,CAAC;CAGX,IAAI,SACF,UAAMC,wBAAM,SAAS,EAAE,WAAW,KAAK,CAAC;CAG1C,MAAM,eAAe,OAAGC,oBAAS,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,OAAGC,yBAAY,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE;CACvF,MAAM,WAAW,cACbC,gBAAK,SAAS,YAAY,IAC1B,GAAG,KAAK,GAAG;CACf,gBAAgB,IAAI,QAAQ;CAE5B,IAAI;EACF,KAAK,IAAI,UAAU,IAAK,WACtB,IAAI;GACF,UAAML,4BAAU,UAAU,OAAO;GAEjC,IAAI,kBAAkB,QAAW;IAG/B,IAAI,oBAAoB,QACtB,IAAI;KACF,mBAAmB,UAAMC,uBAAK,QAAQ,EAAC,CAAE,OAAO;IAClD,QAAQ,CAAC;IAEX,IAAI,kBAAkB,iBACpB,UAAMK,wBAAM,UAAU,aAAa;GAEvC;GAEA,UAAMC,yBAAO,UAAU,IAAI;GAC3B;EACF,SAAS,OAAO;GAId,IAAI,EAFD,MAAgC,SAAS,aAEjB,UAAU,GAAG,MAAM;GAE9C,UAAML,4BAAMM,mBAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;GAC9C,IAAI,SAAS,UAAMN,wBAAM,SAAS,EAAE,WAAW,KAAK,CAAC;EACvD;CAEJ,SAAS,OAAO;EACd,IAAI;GACF,UAAMO,qBAAG,UAAU,EAAE,OAAO,KAAK,CAAC;EACpC,QAAQ,CAAC;EACT,MAAM;CACR,UAAU;EACR,gBAAgB,OAAO,QAAQ;CACjC;CAEA,OAAO;AACT"}
|
|
@@ -70,10 +70,11 @@ const readAsset = (relPath, encoding = "utf8") => {
|
|
|
70
70
|
const distRoot = findDistRoot(here) ?? resolve(here, "..", "..", "dist");
|
|
71
71
|
const assetsRoot = join(distRoot, "assets");
|
|
72
72
|
const tried = [];
|
|
73
|
+
const callerDirAbs = getCallerDir();
|
|
73
74
|
/**
|
|
74
75
|
* Transform dist/(esm|cjs)/... and _virtual/ prefix to clean subpath (Windows-safe)
|
|
75
76
|
*/
|
|
76
|
-
const callerSubpath = relative(distRoot,
|
|
77
|
+
const callerSubpath = relative(distRoot, callerDirAbs).split("\\").join("/").replace(/^(?:dist\/)?(?:esm|cjs)\//, "").replace(/^_virtual\//, "");
|
|
77
78
|
if (relPath.startsWith("./") || relPath.startsWith("../")) {
|
|
78
79
|
const fromCallerAbs = resolve(assetsRoot, callerSubpath, relPath);
|
|
79
80
|
tried.push(fromCallerAbs);
|
|
@@ -199,7 +199,8 @@ const writeDynamicQualifiedDictionaries = async (qualifiedDictionaries, configur
|
|
|
199
199
|
await mkdir(entryDir, { recursive: true });
|
|
200
200
|
await parallelize(locales, async (locale) => {
|
|
201
201
|
const localizedDictionary = getPerLocaleDictionary(entry, locale, defaultLocale);
|
|
202
|
-
|
|
202
|
+
const resultFilePath = resolve(entryDir, `${locale}.json`);
|
|
203
|
+
await writeJsonIfChanged(resultFilePath, localizedDictionary).catch((err) => {
|
|
203
204
|
console.error(`Error creating localized ${key}/${segments.join("/")}/${locale}.json:`, err);
|
|
204
205
|
});
|
|
205
206
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeDynamicDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Loader expression for one `(key, locale)` per-locale chunk. */\nconst buildPerLocaleLoader = (\n key: string,\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;\n\n return format === 'esm'\n ? `import('${path}').then(m => m.default)`\n : `Promise.resolve(require('${path}'))`;\n};\n\n/**\n * Generates the content of a dictionary entry point file.\n *\n * When the dictionary references other dictionaries through `nest()`, the\n * loader for a locale resolves the referenced dictionaries alongside it and\n * attaches them as `nestedDictionaries`. The nest targets then travel in the\n * same lazy chunk as their consumer, and `getNesting` resolves them from that\n * local reference instead of the global registry — which the build\n * optimization strips.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);\n\n if (sortedNestedKeys.length === 0) {\n return ` '${safeLocale}': () => ${ownLoader}`;\n }\n\n const nestedLoaders = sortedNestedKeys\n .map((nestedKey) =>\n buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map(\n (nestedKey, index) =>\n `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`\n )\n .join(', ');\n\n return (\n ` '${safeLocale}': () => Promise.all([\\n` +\n ` ${ownLoader},\\n` +\n ` ${nestedLoaders}\\n` +\n ` ]).then(([_dictionary, ..._nested]) => ({\\n` +\n ` ..._dictionary,\\n` +\n ` nestedDictionaries: { ${attachedEntries} }\\n` +\n ` }))`\n );\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format, [\n ...(nestedDictionaryGraph.get(key) ?? []),\n ]);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"writeDynamicDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n COMPOSITE_ID_SEPARATOR,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n reconstructQualifiedEntry,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { PlainMergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Escapes a value interpolated into a single-quoted literal of a generated\n * loader module, so keys or segments containing `'` or `\\` cannot break the\n * emitted JavaScript.\n */\nconst escapeJsLiteral = (value: string): string =>\n value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Loader expression for one `(key, locale)` per-locale chunk. */\nconst buildPerLocaleLoader = (\n key: string,\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = `./${DICTIONARIES_SUBDIR}/${key}/${locale}.json`;\n\n return format === 'esm'\n ? `import('${path}').then(m => m.default)`\n : `Promise.resolve(require('${path}'))`;\n};\n\n/**\n * Generates the content of a dictionary entry point file.\n *\n * When the dictionary references other dictionaries through `nest()`, the\n * loader for a locale resolves the referenced dictionaries alongside it and\n * attaches them as `nestedDictionaries`. The nest targets then travel in the\n * same lazy chunk as their consumer, and `getNesting` resolves them from that\n * local reference instead of the global registry — which the build\n * optimization strips.\n *\n * @param key - The dictionary key.\n * @param locales - Locales to emit a loader for.\n * @param format - Output module format.\n * @param nestedKeys - Keys referenced through `nest()`, transitively.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm',\n nestedKeys: string[] = []\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n const sortedNestedKeys = [...nestedKeys].sort((a, b) => a.localeCompare(b));\n\n const safeKey = escapeJsLiteral(key);\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const safeLocale = escapeJsLiteral(locale);\n const ownLoader = buildPerLocaleLoader(safeKey, safeLocale, format);\n\n if (sortedNestedKeys.length === 0) {\n return ` '${safeLocale}': () => ${ownLoader}`;\n }\n\n const nestedLoaders = sortedNestedKeys\n .map((nestedKey) =>\n buildPerLocaleLoader(escapeJsLiteral(nestedKey), safeLocale, format)\n )\n .join(',\\n ');\n\n const attachedEntries = sortedNestedKeys\n .map(\n (nestedKey, index) =>\n `'${escapeJsLiteral(nestedKey)}': _nested[${index}]`\n )\n .join(', ');\n\n return (\n ` '${safeLocale}': () => Promise.all([\\n` +\n ` ${ownLoader},\\n` +\n ` ${nestedLoaders}\\n` +\n ` ]).then(([_dictionary, ..._nested]) => ({\\n` +\n ` ..._dictionary,\\n` +\n ` nestedDictionaries: { ${attachedEntries} }\\n` +\n ` }))`\n );\n })\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * A nested loader tree: one level per declared dimension, leaves are loader\n * expression strings.\n */\ntype LoaderTree = { [segment: string]: LoaderTree | string };\n\n/**\n * One entry of a qualified loader map.\n *\n * `treeSegments` is where the entry lives in the loader tree (its composite id\n * segments); `chunkSegments` is the chunk path it loads. They differ when the\n * entry aliases another entry with identical content (e.g. array-variant\n * fan-out): the alias keeps its own tree position but points at the canonical\n * entry's chunk, so equal content is emitted — and downloaded — only once.\n */\nexport type QualifiedEntrySegments = {\n treeSegments: string[];\n chunkSegments: string[];\n};\n\nconst buildLoaderExpression = (\n key: string,\n chunkSegments: string[],\n locale: string,\n format: 'cjs' | 'esm'\n): string => {\n const path = escapeJsLiteral(\n `./${DICTIONARIES_SUBDIR}/${key}/${chunkSegments.join('/')}/${locale}.json`\n );\n\n return format === 'esm'\n ? `() => import('${path}').then(m => m.default)`\n : `() => Promise.resolve(require('${path}'))`;\n};\n\nconst buildLoaderTree = (\n key: string,\n entries: QualifiedEntrySegments[],\n locale: string,\n format: 'cjs' | 'esm'\n): LoaderTree => {\n const root: LoaderTree = {};\n\n for (const { treeSegments, chunkSegments } of entries) {\n let node = root;\n\n treeSegments.forEach((segment, index) => {\n if (index === treeSegments.length - 1) {\n node[segment] = buildLoaderExpression(\n key,\n chunkSegments,\n locale,\n format\n );\n return;\n }\n\n node[segment] = (node[segment] as LoaderTree | undefined) ?? {};\n node = node[segment] as LoaderTree;\n });\n }\n\n return root;\n};\n\nconst serializeLoaderTree = (tree: LoaderTree, indentLevel: number): string => {\n const pad = ' '.repeat(indentLevel);\n const innerPad = ' '.repeat(indentLevel + 1);\n\n const lines = Object.keys(tree)\n .sort((a, b) => a.localeCompare(b))\n .map((segment) => {\n const value = tree[segment]!;\n const serialized =\n typeof value === 'string'\n ? value\n : serializeLoaderTree(value, indentLevel + 1);\n\n return `${innerPad}'${escapeJsLiteral(segment)}': ${serialized}`;\n });\n\n return `{\\n${lines.join(',\\n')}\\n${pad}}`;\n};\n\n/**\n * Generates the entry point of a qualified dictionary (collection / variant,\n * possibly combined). Under each locale the loader map nests one\n * level per declared dimension (canonical order) and carries a marker listing\n * those dimensions so the runtime can walk the tree.\n *\n * One static `import()` is emitted per leaf `(locale, …segments)` chunk, which\n * keeps the output compatible with bundlers that reject template-literal\n * dynamic imports (Turbopack). Entries whose content is identical share one\n * chunk: their leaves point at the canonical entry's import path.\n */\nexport const generateQualifiedDictionaryEntryPoint = (\n key: string,\n qualifierTypes: DictionaryQualifierType[],\n entries: QualifiedEntrySegments[],\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) => {\n const tree = buildLoaderTree(key, entries, locale, format);\n return ` '${escapeJsLiteral(locale)}': ${serializeLoaderTree(tree, 1)}`;\n })\n .join(',\\n');\n\n const marker = ` '${QUALIFIER_DYNAMIC_TYPES_KEY}': ${JSON.stringify(qualifierTypes)}`;\n\n if (format === 'esm') {\n return (\n `const content = {\\n${marker},\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${marker},\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: PlainMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT,\n nestedDictionaryGraph: Map<string, Set<string>> = new Map()\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format, [\n ...(nestedDictionaryGraph.get(key) ?? []),\n ]);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n\nexport type QualifiedMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: QualifiedDictionaryGroup;\n};\n\nexport type QualifiedMergedDictionaryOutput = Record<\n string,\n QualifiedMergedDictionaryResult\n>;\n\n/**\n * Writes the dynamic chunks and entry points of qualified dictionaries\n * (collections, variants — possibly combined) in\n * `importMode: 'dynamic'`.\n *\n * Each entry is reduced to one per-locale chunk written to a path nested by\n * dimension — `json/{key}/{seg1}/{seg2}/{locale}.json` — and a single\n * `{key}.{ext}` entry point exposes the matching nested loader tree, so the\n * entry point is discovered and aggregated exactly like a plain dynamic one.\n */\nexport const writeDynamicQualifiedDictionaries = async (\n qualifiedDictionaries: QualifiedMergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<void> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n await parallelize(\n Object.entries(qualifiedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, { dictionary: group }]) => {\n if (key === 'undefined') return;\n\n const entryIds = Object.keys(group.content);\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n\n // Entries with identical content (e.g. array-variant fan-out) share one\n // chunk: only the first entry per content identity writes files; the\n // others become aliases whose loaders point at the canonical chunk path.\n const canonicalSegmentsByContent = new Map<string, string[]>();\n const entries: QualifiedEntrySegments[] = [];\n const canonicalEntryIds: string[] = [];\n\n for (const entryId of entryIds) {\n const treeSegments = entryId.split(COMPOSITE_ID_SEPARATOR);\n const contentIdentity = JSON.stringify(group.content[entryId]);\n const canonicalSegments =\n canonicalSegmentsByContent.get(contentIdentity);\n\n if (canonicalSegments) {\n entries.push({ treeSegments, chunkSegments: canonicalSegments });\n continue;\n }\n\n canonicalSegmentsByContent.set(contentIdentity, treeSegments);\n entries.push({ treeSegments, chunkSegments: treeSegments });\n canonicalEntryIds.push(entryId);\n }\n\n await parallelize(canonicalEntryIds, async (entryId) => {\n // Rebuild a resolvable dictionary from the content node + composite id\n // so per-locale extraction sees the same `{ key, content }` shape.\n const entry = reconstructQualifiedEntry(group, entryId);\n\n const segments = entryId.split(COMPOSITE_ID_SEPARATOR);\n\n const entryDir = resolve(keyDir, ...segments);\n assertPathWithin(entryDir, keyDir);\n await mkdir(entryDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n entry,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/<…segments>/locale.json\n const resultFilePath = resolve(entryDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${segments.join('/')}/${locale}.json:`,\n err\n );\n }\n );\n });\n });\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateQualifiedDictionaryEntryPoint(\n key,\n group.qualifierTypes,\n entries,\n locales,\n format\n );\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n};\n"],"mappings":"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"}
|
|
@@ -28,7 +28,8 @@ const writeMergedDictionaries = async (groupedDictionaries, configuration) => {
|
|
|
28
28
|
await mkdir(resolve(dictionariesDir), { recursive: true });
|
|
29
29
|
const results = await parallelize(Object.entries(groupedDictionaries), async ([key, dictionariesEntry]) => {
|
|
30
30
|
if (key === "undefined") return;
|
|
31
|
-
const
|
|
31
|
+
const normalizedDictionaries = normalizeDictionaries(dictionariesEntry.dictionaries, configuration);
|
|
32
|
+
const mergedDictionary = mergeQualifiedDictionaries(normalizedDictionaries);
|
|
32
33
|
const outputFileName = `${key}.json`;
|
|
33
34
|
const resultFilePath = resolve(dictionariesDir, outputFileName);
|
|
34
35
|
assertPathWithin(resultFilePath, dictionariesDir);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeMergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n mergeQualifiedDictionaries,\n normalizeDictionaries,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { UnmergedDictionaryOutput } from './writeUnmergedDictionary';\n\nexport type MergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary | QualifiedDictionaryGroup;\n};\n\nexport type MergedDictionaryOutput = Record<string, MergedDictionaryResult>;\n\n/**\n * Merged output restricted to plain (unqualified) dictionaries — qualified\n * groups (collections, variants) are static-only and filtered\n * out before the dynamic/fetch build steps.\n */\nexport type PlainMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type PlainMergedDictionaryOutput = Record<\n string,\n PlainMergedDictionaryResult\n>;\n\n/**\n * Write the merged dictionaries to the dictionariesDir\n * @param groupedDictionaries - The grouped dictionaries\n * @param configuration - The configuration\n * @returns The merged dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dictionary/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeMergedDictionaries = async (\n groupedDictionaries: UnmergedDictionaryOutput,\n configuration: IntlayerConfig\n): Promise<MergedDictionaryOutput> => {\n const { dictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(dictionariesDir), { recursive: true });\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionariesEntry]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n MergedDictionaryResult,\n ];\n }\n\n const normalizedDictionaries = normalizeDictionaries(\n dictionariesEntry.dictionaries,\n configuration\n );\n\n const mergedDictionary = mergeQualifiedDictionaries(\n normalizedDictionaries\n );\n\n const outputFileName = `${key}.json`;\n const resultFilePath = resolve(dictionariesDir, outputFileName);\n\n assertPathWithin(resultFilePath, dictionariesDir);\n\n // Write the merged dictionary\n await writeJsonIfChanged(resultFilePath, mergedDictionary).catch(\n (err) => {\n console.error(\n `Error creating merged ${colorizePath(resultFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: resultFilePath,\n dictionary: mergedDictionary,\n } as MergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<readonly [string, MergedDictionaryResult]>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,MAAa,0BAA0B,OACrC,qBACA,kBACoC;CACpC,MAAM,EAAE,oBAAoB,cAAc;CAG1C,MAAM,MAAM,QAAQ,eAAe,GAAG,EAAE,WAAW,KAAK,CAAC;CAEzD,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,mBAAmB,GAClC,OAAO,CAAC,KAAK,uBAAuB;EAClC,IAAI,QAAQ,aACV;
|
|
1
|
+
{"version":3,"file":"writeMergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n mergeQualifiedDictionaries,\n normalizeDictionaries,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type {\n Dictionary,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { UnmergedDictionaryOutput } from './writeUnmergedDictionary';\n\nexport type MergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary | QualifiedDictionaryGroup;\n};\n\nexport type MergedDictionaryOutput = Record<string, MergedDictionaryResult>;\n\n/**\n * Merged output restricted to plain (unqualified) dictionaries — qualified\n * groups (collections, variants) are static-only and filtered\n * out before the dynamic/fetch build steps.\n */\nexport type PlainMergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type PlainMergedDictionaryOutput = Record<\n string,\n PlainMergedDictionaryResult\n>;\n\n/**\n * Write the merged dictionaries to the dictionariesDir\n * @param groupedDictionaries - The grouped dictionaries\n * @param configuration - The configuration\n * @returns The merged dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dictionary/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeMergedDictionaries = async (\n groupedDictionaries: UnmergedDictionaryOutput,\n configuration: IntlayerConfig\n): Promise<MergedDictionaryOutput> => {\n const { dictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(dictionariesDir), { recursive: true });\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionariesEntry]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n MergedDictionaryResult,\n ];\n }\n\n const normalizedDictionaries = normalizeDictionaries(\n dictionariesEntry.dictionaries,\n configuration\n );\n\n const mergedDictionary = mergeQualifiedDictionaries(\n normalizedDictionaries\n );\n\n const outputFileName = `${key}.json`;\n const resultFilePath = resolve(dictionariesDir, outputFileName);\n\n assertPathWithin(resultFilePath, dictionariesDir);\n\n // Write the merged dictionary\n await writeJsonIfChanged(resultFilePath, mergedDictionary).catch(\n (err) => {\n console.error(\n `Error creating merged ${colorizePath(resultFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: resultFilePath,\n dictionary: mergedDictionary,\n } as MergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<readonly [string, MergedDictionaryResult]>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,MAAa,0BAA0B,OACrC,qBACA,kBACoC;CACpC,MAAM,EAAE,oBAAoB,cAAc;CAG1C,MAAM,MAAM,QAAQ,eAAe,GAAG,EAAE,WAAW,KAAK,CAAC;CAEzD,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,mBAAmB,GAClC,OAAO,CAAC,KAAK,uBAAuB;EAClC,IAAI,QAAQ,aACV;EAMF,MAAM,yBAAyB,sBAC7B,kBAAkB,cAClB,aACF;EAEA,MAAM,mBAAmB,2BACvB,sBACF;EAEA,MAAM,iBAAiB,GAAG,IAAI;EAC9B,MAAM,iBAAiB,QAAQ,iBAAiB,cAAc;EAE9D,iBAAiB,gBAAgB,eAAe;EAGhD,MAAM,mBAAmB,gBAAgB,gBAAgB,CAAC,CAAC,OACxD,QAAQ;GACP,QAAQ,MACN,yBAAyB,aAAa,cAAc,EAAE,IACtD,GACF;EACF,CACF;EAEA,OAAO,CACL,KACA;GACE,gBAAgB;GAChB,YAAY;EACd,CACF;CACF,CACF;CAEA,OAAO,OAAO,YACZ,QAAQ,OAAO,OAAO,CACxB;AACF"}
|
|
@@ -28,10 +28,12 @@ import { orderDictionaries } from "@intlayer/core/dictionaryManipulator";
|
|
|
28
28
|
const writeRemoteDictionary = async (remoteDictionaries, configuration) => {
|
|
29
29
|
const { remoteDictionariesDir } = configuration.system;
|
|
30
30
|
await mkdir(resolve(remoteDictionariesDir), { recursive: true });
|
|
31
|
-
const
|
|
31
|
+
const filteredDictionaries = filterInvalidDictionaries(remoteDictionaries, configuration);
|
|
32
|
+
const groupedDictionaries = groupDictionariesByKey(filteredDictionaries);
|
|
32
33
|
const results = await parallelize(Object.entries(groupedDictionaries), async ([key, dictionaries]) => {
|
|
33
34
|
if (key === "undefined") return;
|
|
34
|
-
const
|
|
35
|
+
const formattedDictionaries = formatDistantDictionaries(dictionaries);
|
|
36
|
+
const orderedDictionaries = orderDictionaries(formattedDictionaries);
|
|
35
37
|
const outputFileName = `${key}.json`;
|
|
36
38
|
const unmergedFilePath = resolve(remoteDictionariesDir, outputFileName);
|
|
37
39
|
await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch((err) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeRemoteDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeRemoteDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { orderDictionaries } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { formatDistantDictionaries } from '../loadDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport {\n groupDictionariesByKey,\n type UnmergedDictionaryResult,\n} from './writeUnmergedDictionary';\n\nexport type RemoteDictionaryResult = {\n dictionaryPath: string;\n dictionaries: Dictionary[];\n};\n\nexport type RemoteDictionaryOutput = Record<string, RemoteDictionaryResult>;\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionaries/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeRemoteDictionary = async (\n remoteDictionaries: Dictionary[],\n configuration: IntlayerConfig\n): Promise<RemoteDictionaryOutput> => {\n const { remoteDictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(remoteDictionariesDir), { recursive: true });\n\n const filteredDictionaries = filterInvalidDictionaries(\n remoteDictionaries,\n configuration\n );\n\n // Group dictionaries by key and write to unmergedDictionariesDir\n const groupedDictionaries = groupDictionariesByKey(filteredDictionaries);\n\n // Merge dictionaries with the same key and write to dictionariesDir\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionaries]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n UnmergedDictionaryResult,\n ];\n }\n\n const formattedDictionaries = formatDistantDictionaries(dictionaries);\n\n const orderedDictionaries = orderDictionaries(formattedDictionaries);\n\n const outputFileName = `${key}.json`;\n const unmergedFilePath = resolve(remoteDictionariesDir, outputFileName);\n\n // Write the grouped dictionaries\n await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch(\n (err) => {\n console.error(\n `${x} Error creating unmerged ${colorizePath(unmergedFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: unmergedFilePath,\n dictionaries,\n } as UnmergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<\n readonly [string, UnmergedDictionaryResult]\n >\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,wBAAwB,OACnC,oBACA,kBACoC;CACpC,MAAM,EAAE,0BAA0B,cAAc;CAGhD,MAAM,MAAM,QAAQ,qBAAqB,GAAG,EAAE,WAAW,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"writeRemoteDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeRemoteDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { orderDictionaries } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { formatDistantDictionaries } from '../loadDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport {\n groupDictionariesByKey,\n type UnmergedDictionaryResult,\n} from './writeUnmergedDictionary';\n\nexport type RemoteDictionaryResult = {\n dictionaryPath: string;\n dictionaries: Dictionary[];\n};\n\nexport type RemoteDictionaryOutput = Record<string, RemoteDictionaryResult>;\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionaries/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeRemoteDictionary = async (\n remoteDictionaries: Dictionary[],\n configuration: IntlayerConfig\n): Promise<RemoteDictionaryOutput> => {\n const { remoteDictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(remoteDictionariesDir), { recursive: true });\n\n const filteredDictionaries = filterInvalidDictionaries(\n remoteDictionaries,\n configuration\n );\n\n // Group dictionaries by key and write to unmergedDictionariesDir\n const groupedDictionaries = groupDictionariesByKey(filteredDictionaries);\n\n // Merge dictionaries with the same key and write to dictionariesDir\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionaries]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n UnmergedDictionaryResult,\n ];\n }\n\n const formattedDictionaries = formatDistantDictionaries(dictionaries);\n\n const orderedDictionaries = orderDictionaries(formattedDictionaries);\n\n const outputFileName = `${key}.json`;\n const unmergedFilePath = resolve(remoteDictionariesDir, outputFileName);\n\n // Write the grouped dictionaries\n await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch(\n (err) => {\n console.error(\n `${x} Error creating unmerged ${colorizePath(unmergedFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: unmergedFilePath,\n dictionaries,\n } as UnmergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<\n readonly [string, UnmergedDictionaryResult]\n >\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,wBAAwB,OACnC,oBACA,kBACoC;CACpC,MAAM,EAAE,0BAA0B,cAAc;CAGhD,MAAM,MAAM,QAAQ,qBAAqB,GAAG,EAAE,WAAW,KAAK,CAAC;CAE/D,MAAM,uBAAuB,0BAC3B,oBACA,aACF;CAGA,MAAM,sBAAsB,uBAAuB,oBAAoB;CAGvE,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,mBAAmB,GAClC,OAAO,CAAC,KAAK,kBAAkB;EAC7B,IAAI,QAAQ,aACV;EAMF,MAAM,wBAAwB,0BAA0B,YAAY;EAEpE,MAAM,sBAAsB,kBAAkB,qBAAqB;EAEnE,MAAM,iBAAiB,GAAG,IAAI;EAC9B,MAAM,mBAAmB,QAAQ,uBAAuB,cAAc;EAGtE,MAAM,mBAAmB,kBAAkB,mBAAmB,CAAC,CAAC,OAC7D,QAAQ;GACP,QAAQ,MACN,GAAG,EAAE,2BAA2B,aAAa,gBAAgB,EAAE,IAC/D,GACF;EACF,CACF;EAEA,OAAO,CACL,KACA;GACE,gBAAgB;GAChB;EACF,CACF;CACF,CACF;CAEA,OAAO,OAAO,YACZ,QAAQ,OAAO,OAAO,CAGxB;AACF"}
|
|
@@ -29,7 +29,8 @@ const cleanRemovedContentDeclaration = async (filePath, keysToKeep, configuratio
|
|
|
29
29
|
excludeKeys.push(dictionary.key);
|
|
30
30
|
}
|
|
31
31
|
} else {
|
|
32
|
-
|
|
32
|
+
const filteredContent = parsedContent.filter((content) => content.filePath !== relativeFilePath);
|
|
33
|
+
await writeJsonIfChanged(unmergedFilePath, filteredContent);
|
|
33
34
|
changedDictionariesLocalIds.push(dictionary.localId);
|
|
34
35
|
}
|
|
35
36
|
} catch (error) {
|
|
@@ -51,16 +52,18 @@ const cleanRemovedContentDeclaration = async (filePath, keysToKeep, configuratio
|
|
|
51
52
|
filesToRemove.push(mergedFilePath);
|
|
52
53
|
const typesFilePath = normalize(join(configuration.system.typesDir, `${dictionary.key}.ts`));
|
|
53
54
|
filesToRemove.push(typesFilePath);
|
|
54
|
-
const
|
|
55
|
+
const dynamicFilesGlob = join(configuration.system.dynamicDictionariesDir, `${dictionary.key}.*`);
|
|
56
|
+
const dynamicFiles = await fg(normalizePath(dynamicFilesGlob), { absolute: true });
|
|
55
57
|
filesToRemove.push(...dynamicFiles);
|
|
56
58
|
if (!excludeKeys.includes(dictionary.key)) excludeKeys.push(dictionary.key);
|
|
57
59
|
}
|
|
58
60
|
} else {
|
|
59
61
|
const localIds = parsedContent.localIds?.filter((localeId) => !localeId.endsWith(`::local::${relativeFilePath}`));
|
|
60
|
-
|
|
62
|
+
const newContent = {
|
|
61
63
|
...parsedContent,
|
|
62
64
|
localIds
|
|
63
|
-
}
|
|
65
|
+
};
|
|
66
|
+
await writeJsonIfChanged(mergedFilePath, newContent);
|
|
64
67
|
}
|
|
65
68
|
} catch (error) {
|
|
66
69
|
if (error.code === "ENOENT") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanRemovedContentDeclaration.mjs","names":[],"sources":["../../src/cleanRemovedContentDeclaration.ts"],"sourcesContent":["import { readFile, rm } from 'node:fs/promises';\nimport { join, normalize, relative } from 'node:path';\nimport { normalizePath } from '@intlayer/config/client';\nimport {\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport fg from 'fast-glob';\nimport { createDictionaryEntryPoint } from './createDictionaryEntryPoint';\nimport { readDictionariesFromDisk } from './utils/readDictionariesFromDisk';\nimport { writeJsonIfChanged } from './writeJsonIfChanged';\n\nexport const cleanRemovedContentDeclaration = async (\n filePath: string,\n keysToKeep: string[],\n configuration: IntlayerConfig\n): Promise<{\n changedDictionariesLocalIds: string[];\n excludeKeys: string[];\n hasRebuilt: boolean;\n}> => {\n const appLogger = getAppLogger(configuration);\n\n const unmergedDictionaries = readDictionariesFromDisk<\n Record<string, Dictionary[]>\n >(configuration.system.unmergedDictionariesDir);\n\n const baseDir = configuration.system.baseDir;\n\n const relativeFilePath = relative(baseDir, filePath);\n const flatUnmergedDictionaries = Object.values(unmergedDictionaries).flat();\n\n const filteredUnmergedDictionaries = flatUnmergedDictionaries.filter(\n (dictionary) =>\n dictionary.filePath === relativeFilePath &&\n !keysToKeep.includes(dictionary.key)\n );\n\n // Deduplicate dictionaries by key\n const uniqueUnmergedDictionaries = filteredUnmergedDictionaries.filter(\n (dictionary, index, self) =>\n index === self.findIndex((t) => t.key === dictionary.key)\n );\n\n const changedDictionariesLocalIds: string[] = [];\n const filesToRemove: string[] = [];\n const excludeKeys: string[] = [];\n\n // Identify Unmerged Dictionaries to remove or clean\n await Promise.all(\n uniqueUnmergedDictionaries.map(async (dictionary) => {\n const unmergedFilePath = normalize(\n join(\n configuration.system.unmergedDictionariesDir,\n `${dictionary.key}.json`\n )\n );\n\n try {\n const jsonContent = await readFile(unmergedFilePath, 'utf8');\n const parsedContent = JSON.parse(jsonContent);\n\n if (parsedContent.length === 1) {\n if (parsedContent[0].filePath === relativeFilePath) {\n appLogger(\n `Removing outdated dictionary ${colorizeKey(dictionary.key)}`,\n { isVerbose: true }\n );\n filesToRemove.push(unmergedFilePath);\n excludeKeys.push(dictionary.key);\n }\n } else {\n const filteredContent = parsedContent.filter(\n (content: any) => content.filePath !== relativeFilePath\n );\n await writeJsonIfChanged(unmergedFilePath, filteredContent);\n changedDictionariesLocalIds.push(dictionary.localId!);\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n }\n }\n })\n );\n\n const dictionaries = readDictionariesFromDisk<Record<string, Dictionary>>(\n configuration.system.dictionariesDir\n );\n const flatDictionaries = Object.values(dictionaries) as Dictionary[];\n\n const filteredMergedDictionaries = flatDictionaries?.filter(\n (dictionary) =>\n !keysToKeep.includes(dictionary.key) &&\n dictionary.localIds?.length === 1 &&\n (dictionary.localIds[0] as string).endsWith(\n `::local::${relativeFilePath}`\n )\n );\n\n const uniqueMergedDictionaries = filteredMergedDictionaries.filter(\n (dictionary, index, self) =>\n index === self.findIndex((t) => t.key === dictionary.key)\n );\n\n // Identify Merged Dictionaries, Types, and Dynamic Dictionaries to remove\n await Promise.all(\n uniqueMergedDictionaries.map(async (dictionary) => {\n const mergedFilePath = normalize(\n join(configuration.system.dictionariesDir, `${dictionary.key}.json`)\n );\n\n try {\n const fileContent = await readFile(mergedFilePath, 'utf8');\n const parsedContent = JSON.parse(fileContent) as Dictionary;\n\n if (parsedContent.localIds?.length === 1) {\n if (\n parsedContent.localIds[0].endsWith(`::local::${relativeFilePath}`)\n ) {\n appLogger(\n `Removing outdated unmerged dictionary ${colorizeKey(dictionary.key)}`,\n { isVerbose: true }\n );\n\n // Mark JSON for removal\n filesToRemove.push(mergedFilePath);\n\n // Mark TS Types for removal\n const typesFilePath = normalize(\n join(configuration.system.typesDir, `${dictionary.key}.ts`)\n );\n filesToRemove.push(typesFilePath);\n\n // Mark Dynamic Dictionaries for removal\n // We use glob to catch the loader files (.cjs, .mjs) AND the split locale files (.en.json, etc.)\n const dynamicFilesGlob = join(\n configuration.system.dynamicDictionariesDir,\n `${dictionary.key}.*`\n );\n const dynamicFiles = await fg(normalizePath(dynamicFilesGlob), {\n absolute: true,\n });\n filesToRemove.push(...dynamicFiles);\n\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n }\n } else {\n const localIds = parsedContent.localIds?.filter(\n (localeId) => !localeId.endsWith(`::local::${relativeFilePath}`)\n ) as string[];\n const newContent = { ...parsedContent, localIds };\n await writeJsonIfChanged(mergedFilePath, newContent);\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n const typesFilePath = normalize(\n join(configuration.system.typesDir, `${dictionary.key}.ts`)\n );\n filesToRemove.push(typesFilePath);\n }\n }\n })\n );\n\n // Execute Cleanup\n if (filesToRemove.length > 0 || excludeKeys.length > 0) {\n // Update entry points (indexes) first so the app doesn't import dead files\n await createDictionaryEntryPoint(configuration, { excludeKeys });\n\n // Remove the files synchronously (awaited) immediately after.\n if (filesToRemove.length > 0) {\n setTimeout(\n async () =>\n await Promise.all(\n filesToRemove.map(async (path) => {\n const relativePath = relative(baseDir, path);\n try {\n await rm(path, { force: true });\n\n appLogger(`Deleted artifact: ${colorizePath(relativePath)}`, {\n isVerbose: true,\n });\n } catch {\n appLogger(\n `Error while removing file ${colorizePath(relativePath)}`,\n {\n isVerbose: true,\n }\n );\n }\n })\n ),\n 3000\n );\n }\n }\n\n return {\n changedDictionariesLocalIds,\n excludeKeys,\n hasRebuilt: filesToRemove.length > 0 || excludeKeys.length > 0,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cleanRemovedContentDeclaration.mjs","names":[],"sources":["../../src/cleanRemovedContentDeclaration.ts"],"sourcesContent":["import { readFile, rm } from 'node:fs/promises';\nimport { join, normalize, relative } from 'node:path';\nimport { normalizePath } from '@intlayer/config/client';\nimport {\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport fg from 'fast-glob';\nimport { createDictionaryEntryPoint } from './createDictionaryEntryPoint';\nimport { readDictionariesFromDisk } from './utils/readDictionariesFromDisk';\nimport { writeJsonIfChanged } from './writeJsonIfChanged';\n\nexport const cleanRemovedContentDeclaration = async (\n filePath: string,\n keysToKeep: string[],\n configuration: IntlayerConfig\n): Promise<{\n changedDictionariesLocalIds: string[];\n excludeKeys: string[];\n hasRebuilt: boolean;\n}> => {\n const appLogger = getAppLogger(configuration);\n\n const unmergedDictionaries = readDictionariesFromDisk<\n Record<string, Dictionary[]>\n >(configuration.system.unmergedDictionariesDir);\n\n const baseDir = configuration.system.baseDir;\n\n const relativeFilePath = relative(baseDir, filePath);\n const flatUnmergedDictionaries = Object.values(unmergedDictionaries).flat();\n\n const filteredUnmergedDictionaries = flatUnmergedDictionaries.filter(\n (dictionary) =>\n dictionary.filePath === relativeFilePath &&\n !keysToKeep.includes(dictionary.key)\n );\n\n // Deduplicate dictionaries by key\n const uniqueUnmergedDictionaries = filteredUnmergedDictionaries.filter(\n (dictionary, index, self) =>\n index === self.findIndex((t) => t.key === dictionary.key)\n );\n\n const changedDictionariesLocalIds: string[] = [];\n const filesToRemove: string[] = [];\n const excludeKeys: string[] = [];\n\n // Identify Unmerged Dictionaries to remove or clean\n await Promise.all(\n uniqueUnmergedDictionaries.map(async (dictionary) => {\n const unmergedFilePath = normalize(\n join(\n configuration.system.unmergedDictionariesDir,\n `${dictionary.key}.json`\n )\n );\n\n try {\n const jsonContent = await readFile(unmergedFilePath, 'utf8');\n const parsedContent = JSON.parse(jsonContent);\n\n if (parsedContent.length === 1) {\n if (parsedContent[0].filePath === relativeFilePath) {\n appLogger(\n `Removing outdated dictionary ${colorizeKey(dictionary.key)}`,\n { isVerbose: true }\n );\n filesToRemove.push(unmergedFilePath);\n excludeKeys.push(dictionary.key);\n }\n } else {\n const filteredContent = parsedContent.filter(\n (content: any) => content.filePath !== relativeFilePath\n );\n await writeJsonIfChanged(unmergedFilePath, filteredContent);\n changedDictionariesLocalIds.push(dictionary.localId!);\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n }\n }\n })\n );\n\n const dictionaries = readDictionariesFromDisk<Record<string, Dictionary>>(\n configuration.system.dictionariesDir\n );\n const flatDictionaries = Object.values(dictionaries) as Dictionary[];\n\n const filteredMergedDictionaries = flatDictionaries?.filter(\n (dictionary) =>\n !keysToKeep.includes(dictionary.key) &&\n dictionary.localIds?.length === 1 &&\n (dictionary.localIds[0] as string).endsWith(\n `::local::${relativeFilePath}`\n )\n );\n\n const uniqueMergedDictionaries = filteredMergedDictionaries.filter(\n (dictionary, index, self) =>\n index === self.findIndex((t) => t.key === dictionary.key)\n );\n\n // Identify Merged Dictionaries, Types, and Dynamic Dictionaries to remove\n await Promise.all(\n uniqueMergedDictionaries.map(async (dictionary) => {\n const mergedFilePath = normalize(\n join(configuration.system.dictionariesDir, `${dictionary.key}.json`)\n );\n\n try {\n const fileContent = await readFile(mergedFilePath, 'utf8');\n const parsedContent = JSON.parse(fileContent) as Dictionary;\n\n if (parsedContent.localIds?.length === 1) {\n if (\n parsedContent.localIds[0].endsWith(`::local::${relativeFilePath}`)\n ) {\n appLogger(\n `Removing outdated unmerged dictionary ${colorizeKey(dictionary.key)}`,\n { isVerbose: true }\n );\n\n // Mark JSON for removal\n filesToRemove.push(mergedFilePath);\n\n // Mark TS Types for removal\n const typesFilePath = normalize(\n join(configuration.system.typesDir, `${dictionary.key}.ts`)\n );\n filesToRemove.push(typesFilePath);\n\n // Mark Dynamic Dictionaries for removal\n // We use glob to catch the loader files (.cjs, .mjs) AND the split locale files (.en.json, etc.)\n const dynamicFilesGlob = join(\n configuration.system.dynamicDictionariesDir,\n `${dictionary.key}.*`\n );\n const dynamicFiles = await fg(normalizePath(dynamicFilesGlob), {\n absolute: true,\n });\n filesToRemove.push(...dynamicFiles);\n\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n }\n } else {\n const localIds = parsedContent.localIds?.filter(\n (localeId) => !localeId.endsWith(`::local::${relativeFilePath}`)\n ) as string[];\n const newContent = { ...parsedContent, localIds };\n await writeJsonIfChanged(mergedFilePath, newContent);\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n if (!excludeKeys.includes(dictionary.key)) {\n excludeKeys.push(dictionary.key);\n }\n const typesFilePath = normalize(\n join(configuration.system.typesDir, `${dictionary.key}.ts`)\n );\n filesToRemove.push(typesFilePath);\n }\n }\n })\n );\n\n // Execute Cleanup\n if (filesToRemove.length > 0 || excludeKeys.length > 0) {\n // Update entry points (indexes) first so the app doesn't import dead files\n await createDictionaryEntryPoint(configuration, { excludeKeys });\n\n // Remove the files synchronously (awaited) immediately after.\n if (filesToRemove.length > 0) {\n setTimeout(\n async () =>\n await Promise.all(\n filesToRemove.map(async (path) => {\n const relativePath = relative(baseDir, path);\n try {\n await rm(path, { force: true });\n\n appLogger(`Deleted artifact: ${colorizePath(relativePath)}`, {\n isVerbose: true,\n });\n } catch {\n appLogger(\n `Error while removing file ${colorizePath(relativePath)}`,\n {\n isVerbose: true,\n }\n );\n }\n })\n ),\n 3000\n );\n }\n }\n\n return {\n changedDictionariesLocalIds,\n excludeKeys,\n hasRebuilt: filesToRemove.length > 0 || excludeKeys.length > 0,\n };\n};\n"],"mappings":"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"}
|
|
@@ -12,7 +12,8 @@ import { getConfiguration } from "@intlayer/config/node";
|
|
|
12
12
|
|
|
13
13
|
//#region src/createDictionaryEntryPoint/createDictionaryEntryPoint.ts
|
|
14
14
|
const writeDictionaryFiles = async (paths, fileName, importType, functionName, format, configuration = getConfiguration()) => {
|
|
15
|
-
const
|
|
15
|
+
const resolvedPath = await paths;
|
|
16
|
+
const content = generateDictionaryListContent(resolvedPath, functionName, importType, format, configuration);
|
|
16
17
|
const extension = format === "cjs" ? "cjs" : "mjs";
|
|
17
18
|
const { mainDir } = configuration.system;
|
|
18
19
|
await writeFileIfChanged(resolve(mainDir, `${fileName}.${extension}`), content);
|
|
@@ -25,7 +26,7 @@ const createDictionaryEntryPoint = async (configuration = getConfiguration(), op
|
|
|
25
26
|
const outputFormats = formats ?? configuration.build.outputFormat;
|
|
26
27
|
const { mainDir } = configuration.system;
|
|
27
28
|
await mkdir(mainDir, { recursive: true });
|
|
28
|
-
|
|
29
|
+
const writeOperations = [
|
|
29
30
|
...outputFormats.map((format) => ({
|
|
30
31
|
paths: getBuiltDictionariesPath(configuration, excludeKeys),
|
|
31
32
|
importType: "json",
|
|
@@ -61,7 +62,8 @@ const createDictionaryEntryPoint = async (configuration = getConfiguration(), op
|
|
|
61
62
|
fileName: "remote_dictionaries",
|
|
62
63
|
format
|
|
63
64
|
}))
|
|
64
|
-
]
|
|
65
|
+
];
|
|
66
|
+
await parallelize(writeOperations, async ({ paths, fileName, format, functionName, importType }) => await writeDictionaryFiles(paths, fileName, importType, functionName, format, configuration));
|
|
65
67
|
};
|
|
66
68
|
|
|
67
69
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDictionaryEntryPoint.mjs","names":[],"sources":["../../../src/createDictionaryEntryPoint/createDictionaryEntryPoint.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { generateDictionaryListContent } from './generateDictionaryListContent';\nimport { getBuiltDictionariesPath } from './getBuiltDictionariesPath';\nimport { getBuiltDynamicDictionariesPath } from './getBuiltDynamicDictionariesPath';\nimport { getBuiltFetchDictionariesPath } from './getBuiltFetchDictionariesPath';\nimport { getBuiltRemoteDictionariesPath } from './getBuiltRemoteDictionariesPath';\nimport { getBuiltUnmergedDictionariesPath } from './getBuiltUnmergedDictionariesPath';\n\nconst writeDictionaryFiles = async (\n paths: Promise<string[]>,\n fileName: string,\n importType: 'json' | 'javascript',\n functionName: string,\n format: 'cjs' | 'esm',\n configuration = getConfiguration()\n) => {\n const resolvedPath = await paths;\n\n const content = generateDictionaryListContent(\n resolvedPath,\n functionName,\n importType,\n format,\n configuration\n );\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const { mainDir } = configuration.system;\n\n await writeFileIfChanged(\n resolve(mainDir, `${fileName}.${extension}`),\n content\n );\n};\n\nexport type CreateDictionaryEntryPointOptions = {\n formats?: ('cjs' | 'esm')[];\n excludeKeys?: string[];\n};\n\n/**\n * This function generates a list of dictionaries in the main directory\n */\nexport const createDictionaryEntryPoint = async (\n configuration = getConfiguration(),\n options: CreateDictionaryEntryPointOptions = {}\n) => {\n const { formats, excludeKeys = [] } = options;\n const outputFormats = formats ?? configuration.build.outputFormat;\n const { mainDir } = configuration.system;\n\n await mkdir(mainDir, { recursive: true });\n\n const writeOperations = [\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getDictionaries',\n fileName: 'dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltUnmergedDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getUnmergedDictionaries',\n fileName: 'unmerged_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltDynamicDictionariesPath(\n configuration,\n format,\n excludeKeys\n ),\n importType: 'javascript',\n functionName: 'getDynamicDictionaries',\n fileName: 'dynamic_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltFetchDictionariesPath(\n configuration,\n format,\n excludeKeys\n ),\n importType: 'javascript',\n functionName: 'getFetchDictionaries',\n fileName: 'fetch_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltRemoteDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getRemoteDictionaries',\n fileName: 'remote_dictionaries' as const,\n format,\n }) as const\n ),\n ];\n\n await parallelize(\n writeOperations,\n async ({ paths, fileName, format, functionName, importType }) =>\n await writeDictionaryFiles(\n paths,\n fileName,\n importType,\n functionName,\n format,\n configuration\n )\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,uBAAuB,OAC3B,OACA,UACA,YACA,cACA,QACA,gBAAgB,iBAAiB,MAC9B;
|
|
1
|
+
{"version":3,"file":"createDictionaryEntryPoint.mjs","names":[],"sources":["../../../src/createDictionaryEntryPoint/createDictionaryEntryPoint.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { generateDictionaryListContent } from './generateDictionaryListContent';\nimport { getBuiltDictionariesPath } from './getBuiltDictionariesPath';\nimport { getBuiltDynamicDictionariesPath } from './getBuiltDynamicDictionariesPath';\nimport { getBuiltFetchDictionariesPath } from './getBuiltFetchDictionariesPath';\nimport { getBuiltRemoteDictionariesPath } from './getBuiltRemoteDictionariesPath';\nimport { getBuiltUnmergedDictionariesPath } from './getBuiltUnmergedDictionariesPath';\n\nconst writeDictionaryFiles = async (\n paths: Promise<string[]>,\n fileName: string,\n importType: 'json' | 'javascript',\n functionName: string,\n format: 'cjs' | 'esm',\n configuration = getConfiguration()\n) => {\n const resolvedPath = await paths;\n\n const content = generateDictionaryListContent(\n resolvedPath,\n functionName,\n importType,\n format,\n configuration\n );\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const { mainDir } = configuration.system;\n\n await writeFileIfChanged(\n resolve(mainDir, `${fileName}.${extension}`),\n content\n );\n};\n\nexport type CreateDictionaryEntryPointOptions = {\n formats?: ('cjs' | 'esm')[];\n excludeKeys?: string[];\n};\n\n/**\n * This function generates a list of dictionaries in the main directory\n */\nexport const createDictionaryEntryPoint = async (\n configuration = getConfiguration(),\n options: CreateDictionaryEntryPointOptions = {}\n) => {\n const { formats, excludeKeys = [] } = options;\n const outputFormats = formats ?? configuration.build.outputFormat;\n const { mainDir } = configuration.system;\n\n await mkdir(mainDir, { recursive: true });\n\n const writeOperations = [\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getDictionaries',\n fileName: 'dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltUnmergedDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getUnmergedDictionaries',\n fileName: 'unmerged_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltDynamicDictionariesPath(\n configuration,\n format,\n excludeKeys\n ),\n importType: 'javascript',\n functionName: 'getDynamicDictionaries',\n fileName: 'dynamic_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltFetchDictionariesPath(\n configuration,\n format,\n excludeKeys\n ),\n importType: 'javascript',\n functionName: 'getFetchDictionaries',\n fileName: 'fetch_dictionaries' as const,\n format,\n }) as const\n ),\n ...outputFormats.map(\n (format) =>\n ({\n paths: getBuiltRemoteDictionariesPath(configuration, excludeKeys),\n importType: 'json',\n functionName: 'getRemoteDictionaries',\n fileName: 'remote_dictionaries' as const,\n format,\n }) as const\n ),\n ];\n\n await parallelize(\n writeOperations,\n async ({ paths, fileName, format, functionName, importType }) =>\n await writeDictionaryFiles(\n paths,\n fileName,\n importType,\n functionName,\n format,\n configuration\n )\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,uBAAuB,OAC3B,OACA,UACA,YACA,cACA,QACA,gBAAgB,iBAAiB,MAC9B;CACH,MAAM,eAAe,MAAM;CAE3B,MAAM,UAAU,8BACd,cACA,cACA,YACA,QACA,aACF;CACA,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAE7C,MAAM,EAAE,YAAY,cAAc;CAElC,MAAM,mBACJ,QAAQ,SAAS,GAAG,SAAS,GAAG,WAAW,GAC3C,OACF;AACF;;;;AAUA,MAAa,6BAA6B,OACxC,gBAAgB,iBAAiB,GACjC,UAA6C,CAAC,MAC3C;CACH,MAAM,EAAE,SAAS,cAAc,CAAC,MAAM;CACtC,MAAM,gBAAgB,WAAW,cAAc,MAAM;CACrD,MAAM,EAAE,YAAY,cAAc;CAElC,MAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;CAExC,MAAM,kBAAkB;EACtB,GAAG,cAAc,KACd,YACE;GACC,OAAO,yBAAyB,eAAe,WAAW;GAC1D,YAAY;GACZ,cAAc;GACd,UAAU;GACV;EACF,EACJ;EACA,GAAG,cAAc,KACd,YACE;GACC,OAAO,iCAAiC,eAAe,WAAW;GAClE,YAAY;GACZ,cAAc;GACd,UAAU;GACV;EACF,EACJ;EACA,GAAG,cAAc,KACd,YACE;GACC,OAAO,gCACL,eACA,QACA,WACF;GACA,YAAY;GACZ,cAAc;GACd,UAAU;GACV;EACF,EACJ;EACA,GAAG,cAAc,KACd,YACE;GACC,OAAO,8BACL,eACA,QACA,WACF;GACA,YAAY;GACZ,cAAc;GACd,UAAU;GACV;EACF,EACJ;EACA,GAAG,cAAc,KACd,YACE;GACC,OAAO,+BAA+B,eAAe,WAAW;GAChE,YAAY;GACZ,cAAc;GACd,UAAU;GACV;EACF,EACJ;CACF;CAEA,MAAM,YACJ,iBACA,OAAO,EAAE,OAAO,UAAU,QAAQ,cAAc,iBAC9C,MAAM,qBACJ,OACA,UACA,YACA,cACA,QACA,aACF,CACJ;AACF"}
|