@intlayer/chokidar 8.7.6 → 8.7.8-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  2. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
  3. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs.map +1 -1
  4. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
  5. package/dist/cjs/cleanRemovedContentDeclaration.cjs.map +1 -1
  6. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs.map +1 -1
  7. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs.map +1 -1
  8. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs.map +1 -1
  9. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs.map +1 -1
  10. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs.map +1 -1
  11. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs.map +1 -1
  12. package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
  13. package/dist/cjs/createType/createType.cjs.map +1 -1
  14. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  15. package/dist/cjs/filterInvalidDictionaries.cjs.map +1 -1
  16. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs.map +1 -1
  17. package/dist/cjs/handleContentDeclarationFileChange.cjs.map +1 -1
  18. package/dist/cjs/handleContentDeclarationFileMoved.cjs.map +1 -1
  19. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs.map +1 -1
  20. package/dist/cjs/init/index.cjs +34 -0
  21. package/dist/cjs/init/index.cjs.map +1 -1
  22. package/dist/cjs/init/utils/configManipulation.cjs +82 -54
  23. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  24. package/dist/cjs/init/utils/index.cjs +3 -0
  25. package/dist/cjs/init/utils/jsonParser.cjs.map +1 -1
  26. package/dist/cjs/init/utils/tsConfig.cjs.map +1 -1
  27. package/dist/cjs/initConfig/index.cjs.map +1 -1
  28. package/dist/cjs/installSkills/index.cjs.map +1 -1
  29. package/dist/cjs/listDictionariesPath.cjs.map +1 -1
  30. package/dist/cjs/listGitFiles.cjs.map +1 -1
  31. package/dist/cjs/listProjects.cjs.map +1 -1
  32. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs.map +1 -1
  33. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
  34. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  35. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  36. package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
  37. package/dist/cjs/logConfigDetails.cjs.map +1 -1
  38. package/dist/cjs/prepareIntlayer.cjs.map +1 -1
  39. package/dist/cjs/reduceDictionaryContent/reduceDictionaryContent.cjs.map +1 -1
  40. package/dist/cjs/utils/autoDecorateContent.cjs.map +1 -1
  41. package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
  42. package/dist/cjs/utils/buildFilesList.cjs.map +1 -1
  43. package/dist/cjs/utils/chunkJSON.cjs.map +1 -1
  44. package/dist/cjs/utils/getContentExtension.cjs.map +1 -1
  45. package/dist/cjs/utils/pLimit.cjs +6 -1
  46. package/dist/cjs/utils/pLimit.cjs.map +1 -1
  47. package/dist/cjs/utils/resolveObjectPromises.cjs.map +1 -1
  48. package/dist/cjs/utils/resolveRelativePath.cjs.map +1 -1
  49. package/dist/cjs/utils/runOnce.cjs.map +1 -1
  50. package/dist/cjs/utils/runParallel/bin.cjs.map +1 -1
  51. package/dist/cjs/utils/runParallel/bootstrap.cjs.map +1 -1
  52. package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
  53. package/dist/cjs/utils/runParallel/ps.cjs.map +1 -1
  54. package/dist/cjs/utils/runParallel/wmic.cjs.map +1 -1
  55. package/dist/cjs/watcher.cjs.map +1 -1
  56. package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
  57. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
  58. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  59. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
  60. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs.map +1 -1
  61. package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
  62. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  63. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
  64. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs.map +1 -1
  65. package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs.map +1 -1
  66. package/dist/esm/cleanRemovedContentDeclaration.mjs.map +1 -1
  67. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs.map +1 -1
  68. package/dist/esm/createDictionaryEntryPoint/getBuiltDictionariesPath.mjs.map +1 -1
  69. package/dist/esm/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.mjs.map +1 -1
  70. package/dist/esm/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.mjs.map +1 -1
  71. package/dist/esm/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.mjs.map +1 -1
  72. package/dist/esm/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.mjs.map +1 -1
  73. package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
  74. package/dist/esm/createType/createType.mjs.map +1 -1
  75. package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
  76. package/dist/esm/filterInvalidDictionaries.mjs.map +1 -1
  77. package/dist/esm/handleAdditionalContentDeclarationFile.mjs.map +1 -1
  78. package/dist/esm/handleContentDeclarationFileChange.mjs.map +1 -1
  79. package/dist/esm/handleContentDeclarationFileMoved.mjs.map +1 -1
  80. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs.map +1 -1
  81. package/dist/esm/init/index.mjs +35 -1
  82. package/dist/esm/init/index.mjs.map +1 -1
  83. package/dist/esm/init/utils/configManipulation.mjs +80 -55
  84. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  85. package/dist/esm/init/utils/index.mjs +2 -2
  86. package/dist/esm/init/utils/jsonParser.mjs.map +1 -1
  87. package/dist/esm/init/utils/tsConfig.mjs.map +1 -1
  88. package/dist/esm/initConfig/index.mjs.map +1 -1
  89. package/dist/esm/installSkills/index.mjs.map +1 -1
  90. package/dist/esm/listDictionariesPath.mjs.map +1 -1
  91. package/dist/esm/listGitFiles.mjs.map +1 -1
  92. package/dist/esm/listProjects.mjs.map +1 -1
  93. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs.map +1 -1
  94. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
  95. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  96. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  97. package/dist/esm/loadDictionaries/logTypeScriptErrors.mjs.map +1 -1
  98. package/dist/esm/logConfigDetails.mjs.map +1 -1
  99. package/dist/esm/prepareIntlayer.mjs.map +1 -1
  100. package/dist/esm/reduceDictionaryContent/reduceDictionaryContent.mjs.map +1 -1
  101. package/dist/esm/utils/autoDecorateContent.mjs.map +1 -1
  102. package/dist/esm/utils/buildComponentFilesList.mjs.map +1 -1
  103. package/dist/esm/utils/buildFilesList.mjs.map +1 -1
  104. package/dist/esm/utils/chunkJSON.mjs.map +1 -1
  105. package/dist/esm/utils/getContentExtension.mjs.map +1 -1
  106. package/dist/esm/utils/pLimit.mjs +6 -1
  107. package/dist/esm/utils/pLimit.mjs.map +1 -1
  108. package/dist/esm/utils/resolveObjectPromises.mjs.map +1 -1
  109. package/dist/esm/utils/resolveRelativePath.mjs.map +1 -1
  110. package/dist/esm/utils/runOnce.mjs.map +1 -1
  111. package/dist/esm/utils/runParallel/bin.mjs.map +1 -1
  112. package/dist/esm/utils/runParallel/bootstrap.mjs.map +1 -1
  113. package/dist/esm/utils/runParallel/index.mjs.map +1 -1
  114. package/dist/esm/utils/runParallel/ps.mjs.map +1 -1
  115. package/dist/esm/utils/runParallel/wmic.mjs.map +1 -1
  116. package/dist/esm/watcher.mjs.map +1 -1
  117. package/dist/esm/writeConfiguration/index.mjs.map +1 -1
  118. package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs.map +1 -1
  119. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  120. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
  121. package/dist/esm/writeContentDeclaration/writeJSFile.mjs.map +1 -1
  122. package/dist/esm/writeFileIfChanged.mjs.map +1 -1
  123. package/dist/types/init/index.d.ts.map +1 -1
  124. package/dist/types/init/utils/configManipulation.d.ts +4 -1
  125. package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
  126. package/dist/types/init/utils/index.d.ts +2 -2
  127. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"getIntlayerBundle.mjs","names":[],"sources":["../../../src/loadDictionaries/getIntlayerBundle.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { builtinModules } from 'node:module';\nimport { join } from 'node:path';\nimport { bundleFile, type ESBuildPlugin } from '@intlayer/config/file';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Rewrites bare specifiers to absolute paths on the user's disk and externalizes them\n * to preserve directory context (__dirname/import.meta.url).\n */\nconst localResolvePlugin = (\n aliases: Record<string, string>,\n rootRequire: NodeJS.Require\n): ESBuildPlugin => {\n return {\n name: 'local-resolve',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n // 1. Direct alias match\n if (aliases[args.path]) {\n return {\n path: aliases[args.path],\n external: true, // Prevents inlining and context loss\n };\n }\n\n // 2. Dynamic resolution via user workspace\n if (args.path === 'defu' || args.path.startsWith('@intlayer/')) {\n try {\n const absolutePath = rootRequire.resolve(args.path);\n return {\n path: absolutePath,\n external: true, // Injects `require('/absolute/path')`\n };\n } catch {\n return null;\n }\n }\n\n return null;\n });\n },\n };\n};\n\nexport const getIntlayerBundle = async (configuration: IntlayerConfig) => {\n const rootRequire = getProjectRequire(configuration.system.baseDir);\n\n const configurationPath = join(\n configuration.system.configDir,\n `configuration.cjs`\n );\n\n const aliases = {\n '@intlayer/config/built': configurationPath,\n };\n\n const filePath = rootRequire.resolve('intlayer');\n const code = await readFile(filePath, 'utf-8');\n\n const output = await bundleFile(code, filePath, {\n bundle: true,\n platform: 'node',\n external: [\n ...builtinModules,\n ...builtinModules.map((mod) => `node:${mod}`),\n 'vscode',\n 'esbuild',\n ],\n minify: true,\n plugins: [localResolvePlugin(aliases, rootRequire)],\n });\n\n return output ?? '';\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,sBACJ,SACA,gBACkB;AAClB,QAAO;EACL,MAAM;EACN,MAAM,OAAO;AACX,SAAM,UAAU,EAAE,QAAQ,MAAM,GAAG,SAAS;AAE1C,QAAI,QAAQ,KAAK,MACf,QAAO;KACL,MAAM,QAAQ,KAAK;KACnB,UAAU;KACX;AAIH,QAAI,KAAK,SAAS,UAAU,KAAK,KAAK,WAAW,aAAa,CAC5D,KAAI;AAEF,YAAO;MACL,MAFmB,YAAY,QAAQ,KAAK,KAAK;MAGjD,UAAU;MACX;YACK;AACN,YAAO;;AAIX,WAAO;KACP;;EAEL;;AAGH,MAAa,oBAAoB,OAAO,kBAAkC;CACxE,MAAM,cAAc,kBAAkB,cAAc,OAAO,QAAQ;CAOnE,MAAM,UAAU,EACd,0BANwB,KACxB,cAAc,OAAO,WACrB,oBACD,EAIA;CAED,MAAM,WAAW,YAAY,QAAQ,WAAW;AAgBhD,QAbe,MAAM,WAFR,MAAM,SAAS,UAAU,QAAQ,EAER,UAAU;EAC9C,QAAQ;EACR,UAAU;EACV,UAAU;GACR,GAAG;GACH,GAAG,eAAe,KAAK,QAAQ,QAAQ,MAAM;GAC7C;GACA;GACD;EACD,QAAQ;EACR,SAAS,CAAC,mBAAmB,SAAS,YAAY,CAAC;EACpD,CAAC,IAEe"}
1
+ {"version":3,"file":"getIntlayerBundle.mjs","names":[],"sources":["../../../src/loadDictionaries/getIntlayerBundle.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { builtinModules } from 'node:module';\nimport { join } from 'node:path';\nimport { bundleFile, type ESBuildPlugin } from '@intlayer/config/file';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Rewrites bare specifiers to absolute paths on the user's disk and externalizes them\n * to preserve directory context (__dirname/import.meta.url).\n */\nconst localResolvePlugin = (\n aliases: Record<string, string>,\n rootRequire: NodeJS.Require\n): ESBuildPlugin => {\n return {\n name: 'local-resolve',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n // 1. Direct alias match\n if (aliases[args.path]) {\n return {\n path: aliases[args.path],\n external: true, // Prevents inlining and context loss\n };\n }\n\n // 2. Dynamic resolution via user workspace\n if (args.path === 'defu' || args.path.startsWith('@intlayer/')) {\n try {\n const absolutePath = rootRequire.resolve(args.path);\n return {\n path: absolutePath,\n external: true, // Injects `require('/absolute/path')`\n };\n } catch {\n return null;\n }\n }\n\n return null;\n });\n },\n };\n};\n\nexport const getIntlayerBundle = async (configuration: IntlayerConfig) => {\n const rootRequire = getProjectRequire(configuration.system.baseDir);\n\n const configurationPath = join(\n configuration.system.configDir,\n `configuration.cjs`\n );\n\n const aliases = {\n '@intlayer/config/built': configurationPath,\n };\n\n const filePath = rootRequire.resolve('intlayer');\n const code = await readFile(filePath, 'utf-8');\n\n const output = await bundleFile(code, filePath, {\n bundle: true,\n platform: 'node',\n external: [\n ...builtinModules,\n ...builtinModules.map((mod) => `node:${mod}`),\n 'vscode',\n 'esbuild',\n ],\n minify: true,\n plugins: [localResolvePlugin(aliases, rootRequire)],\n });\n\n return output ?? '';\n};\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,sBACJ,SACA,gBACkB;AAClB,QAAO;EACL,MAAM;EACN,MAAM,OAAO;AACX,SAAM,UAAU,EAAE,QAAQ,MAAM,GAAG,SAAS;AAE1C,QAAI,QAAQ,KAAK,MACf,QAAO;KACL,MAAM,QAAQ,KAAK;KACnB,UAAU;KACX;AAIH,QAAI,KAAK,SAAS,UAAU,KAAK,KAAK,WAAW,aAAa,CAC5D,KAAI;AAEF,YAAO;MACL,MAFmB,YAAY,QAAQ,KAAK,KAE1B;MAClB,UAAU;MACX;YACK;AACN,YAAO;;AAIX,WAAO;KACP;;EAEL;;AAGH,MAAa,oBAAoB,OAAO,kBAAkC;CACxE,MAAM,cAAc,kBAAkB,cAAc,OAAO,QAAQ;CAOnE,MAAM,UAAU,EACd,0BANwB,KACxB,cAAc,OAAO,WACrB,oBAI2C,EAC5C;CAED,MAAM,WAAW,YAAY,QAAQ,WAAW;AAgBhD,QAAO,MAbc,WAAW,MAFb,SAAS,UAAU,QAAQ,EAER,UAAU;EAC9C,QAAQ;EACR,UAAU;EACV,UAAU;GACR,GAAG;GACH,GAAG,eAAe,KAAK,QAAQ,QAAQ,MAAM;GAC7C;GACA;GACD;EACD,QAAQ;EACR,SAAS,CAAC,mBAAmB,SAAS,YAAY,CAAC;EACpD,CAAC,IAEe"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadContentDeclaration.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { loadExternalFile } from '@intlayer/config/file';\nimport {\n cacheDisk,\n getPackageJsonPath,\n getProjectRequire,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { processContentDeclaration } from '../buildIntlayerDictionary/processContentDeclaration';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { getIntlayerBundle } from './getIntlayerBundle';\nimport type { DictionariesStatus } from './loadDictionaries';\nimport { logTypeScriptErrors } from './logTypeScriptErrors';\n\nexport const formatLocalDictionaries = (\n dictionariesRecord: Record<string, Dictionary>,\n configuration: IntlayerConfig\n): Dictionary[] =>\n Object.entries(dictionariesRecord).map(([relativePath, dict]) => ({\n ...dict,\n location: dict.location ?? configuration.dictionary?.location ?? 'local',\n localId: `${dict.key}::local::${relativePath}`,\n filePath: relativePath,\n }));\n\nexport const ensureIntlayerBundle = async (\n configuration: IntlayerConfig\n): Promise<string> => {\n const { system } = configuration;\n\n const { set, isValid } = cacheDisk(configuration, ['intlayer-bundle'], {\n ttlMs: 1000 * 60 * 60 * 24 * 5, // 5 days\n });\n\n const filePath = join(system.cacheDir, 'intlayer-bundle.cjs');\n const hasIntlayerBundle = await isValid();\n\n if (!hasIntlayerBundle) {\n const intlayerBundle = await getIntlayerBundle(configuration);\n await writeFile(filePath, intlayerBundle);\n await set('ok');\n }\n\n return filePath;\n};\n\ntype LoadContentDeclarationOptions = {\n logError?: boolean;\n};\n\n// Initialize a module-level cache\nlet cachedExternalDeps: string[] | null = null;\n\n// Helper to fetch and cache the dependencies\nconst getExternalDeps = async (baseDir: string): Promise<string[]> => {\n if (cachedExternalDeps) {\n return cachedExternalDeps; // Return instantly on subsequent calls\n }\n\n try {\n const packageJsonPath = getPackageJsonPath(baseDir);\n\n const packageJSON = await readFile(\n packageJsonPath.packageJsonPath,\n 'utf-8'\n );\n const parsedPackages = JSON.parse(packageJSON);\n const allDependencies = Object.keys({\n ...parsedPackages.dependencies,\n ...parsedPackages.devDependencies,\n });\n\n // Specify the ESM packages to bundle\n const esmPackagesToBundle = ['your-esm-package-name'];\n\n const externalDeps = allDependencies.filter(\n (dep) => !esmPackagesToBundle.includes(dep)\n );\n\n externalDeps.push('esbuild');\n\n // Save to cache\n cachedExternalDeps = externalDeps;\n } catch (error) {\n console.warn(\n 'Could not read package.json for externalizing dependencies, fallback to empty array',\n error\n );\n cachedExternalDeps = ['esbuild'];\n }\n\n return cachedExternalDeps;\n};\n\nexport const loadContentDeclaration = async (\n path: string,\n configuration: IntlayerConfig,\n bundleFilePath?: string,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary | undefined> => {\n const { build, system } = configuration;\n\n // Call the cached helper\n const externalDeps = await getExternalDeps(system.baseDir);\n\n const resolvedBundleFilePath =\n bundleFilePath ?? (await ensureIntlayerBundle(configuration));\n\n try {\n const dictionary = await loadExternalFile(path, {\n logError: options?.logError,\n projectRequire: build.require ?? getProjectRequire(),\n buildOptions: {\n packages: undefined, // It fixes the import of ESM packages in the content declaration\n external: externalDeps,\n banner: {\n js: [\n `var __filename = ${JSON.stringify(path)};`,\n `var __dirname = ${JSON.stringify(dirname(path))};`,\n `globalThis.INTLAYER_FILE_PATH = '${path}';`,\n `globalThis.INTLAYER_BASE_DIR = '${configuration.system.baseDir}';`,\n ].join('\\n'),\n },\n },\n aliases: {\n intlayer: resolvedBundleFilePath,\n },\n });\n\n return dictionary;\n } catch (error) {\n console.error(`Error loading content declaration at ${path}:`, error);\n return undefined;\n }\n};\n\nexport const loadContentDeclarations = async (\n contentDeclarationFilePath: string[],\n configuration: IntlayerConfig,\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary[]> => {\n const { build, system } = configuration;\n\n // Check for TypeScript warnings before we build\n if (build.checkTypes) {\n logTypeScriptErrors(contentDeclarationFilePath, configuration).catch(\n (e) => {\n console.error('Error during TypeScript validation:', e);\n }\n );\n }\n\n const bundleFilePath = await ensureIntlayerBundle(configuration);\n\n try {\n const dictionariesPromises = contentDeclarationFilePath.map(\n async (path) => {\n const relativePath = relative(system.baseDir, path);\n\n const dictionary = await loadContentDeclaration(\n path,\n configuration,\n bundleFilePath,\n options\n );\n\n return { relativePath, dictionary };\n }\n );\n\n const dictionariesArray = await Promise.all(dictionariesPromises);\n const dictionariesRecord = dictionariesArray.reduce(\n (acc, { relativePath, dictionary }) => {\n if (dictionary) {\n acc[relativePath] = dictionary;\n }\n return acc;\n },\n {} as Record<string, Dictionary>\n );\n\n const contentDeclarations: Dictionary[] = formatLocalDictionaries(\n dictionariesRecord,\n configuration\n ).filter((dictionary) => dictionary.location !== 'remote');\n\n const listFoundDictionaries = contentDeclarations.map((declaration) => ({\n dictionaryKey: declaration.key,\n type: 'local' as const,\n status: 'found' as const,\n }));\n\n onStatusUpdate?.(listFoundDictionaries);\n\n const processedDictionaries = await parallelize(\n contentDeclarations,\n async (contentDeclaration): Promise<Dictionary | undefined> => {\n if (!contentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: contentDeclaration.key,\n type: 'local',\n status: 'building',\n },\n ]);\n\n const processedContentDeclaration = await processContentDeclaration(\n contentDeclaration as Dictionary,\n configuration\n );\n\n if (!processedContentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: processedContentDeclaration.key,\n type: 'local',\n status: 'built',\n },\n ]);\n\n return processedContentDeclaration;\n }\n );\n\n return filterInvalidDictionaries(processedDictionaries, configuration, {\n checkSchema: false,\n });\n } catch {\n console.error('Error loading content declarations');\n }\n\n return [];\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"loadContentDeclaration.mjs","names":[],"sources":["../../../src/loadDictionaries/loadContentDeclaration.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { loadExternalFile } from '@intlayer/config/file';\nimport {\n cacheDisk,\n getPackageJsonPath,\n getProjectRequire,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { processContentDeclaration } from '../buildIntlayerDictionary/processContentDeclaration';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { getIntlayerBundle } from './getIntlayerBundle';\nimport type { DictionariesStatus } from './loadDictionaries';\nimport { logTypeScriptErrors } from './logTypeScriptErrors';\n\nexport const formatLocalDictionaries = (\n dictionariesRecord: Record<string, Dictionary>,\n configuration: IntlayerConfig\n): Dictionary[] =>\n Object.entries(dictionariesRecord).map(([relativePath, dict]) => ({\n ...dict,\n location: dict.location ?? configuration.dictionary?.location ?? 'local',\n localId: `${dict.key}::local::${relativePath}`,\n filePath: relativePath,\n }));\n\nexport const ensureIntlayerBundle = async (\n configuration: IntlayerConfig\n): Promise<string> => {\n const { system } = configuration;\n\n const { set, isValid } = cacheDisk(configuration, ['intlayer-bundle'], {\n ttlMs: 1000 * 60 * 60 * 24 * 5, // 5 days\n });\n\n const filePath = join(system.cacheDir, 'intlayer-bundle.cjs');\n const hasIntlayerBundle = await isValid();\n\n if (!hasIntlayerBundle) {\n const intlayerBundle = await getIntlayerBundle(configuration);\n await writeFile(filePath, intlayerBundle);\n await set('ok');\n }\n\n return filePath;\n};\n\ntype LoadContentDeclarationOptions = {\n logError?: boolean;\n};\n\n// Initialize a module-level cache\nlet cachedExternalDeps: string[] | null = null;\n\n// Helper to fetch and cache the dependencies\nconst getExternalDeps = async (baseDir: string): Promise<string[]> => {\n if (cachedExternalDeps) {\n return cachedExternalDeps; // Return instantly on subsequent calls\n }\n\n try {\n const packageJsonPath = getPackageJsonPath(baseDir);\n\n const packageJSON = await readFile(\n packageJsonPath.packageJsonPath,\n 'utf-8'\n );\n const parsedPackages = JSON.parse(packageJSON);\n const allDependencies = Object.keys({\n ...parsedPackages.dependencies,\n ...parsedPackages.devDependencies,\n });\n\n // Specify the ESM packages to bundle\n const esmPackagesToBundle = ['your-esm-package-name'];\n\n const externalDeps = allDependencies.filter(\n (dep) => !esmPackagesToBundle.includes(dep)\n );\n\n externalDeps.push('esbuild');\n\n // Save to cache\n cachedExternalDeps = externalDeps;\n } catch (error) {\n console.warn(\n 'Could not read package.json for externalizing dependencies, fallback to empty array',\n error\n );\n cachedExternalDeps = ['esbuild'];\n }\n\n return cachedExternalDeps;\n};\n\nexport const loadContentDeclaration = async (\n path: string,\n configuration: IntlayerConfig,\n bundleFilePath?: string,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary | undefined> => {\n const { build, system } = configuration;\n\n // Call the cached helper\n const externalDeps = await getExternalDeps(system.baseDir);\n\n const resolvedBundleFilePath =\n bundleFilePath ?? (await ensureIntlayerBundle(configuration));\n\n try {\n const dictionary = await loadExternalFile(path, {\n logError: options?.logError,\n projectRequire: build.require ?? getProjectRequire(),\n buildOptions: {\n packages: undefined, // It fixes the import of ESM packages in the content declaration\n external: externalDeps,\n banner: {\n js: [\n `var __filename = ${JSON.stringify(path)};`,\n `var __dirname = ${JSON.stringify(dirname(path))};`,\n `globalThis.INTLAYER_FILE_PATH = '${path}';`,\n `globalThis.INTLAYER_BASE_DIR = '${configuration.system.baseDir}';`,\n ].join('\\n'),\n },\n },\n aliases: {\n intlayer: resolvedBundleFilePath,\n },\n });\n\n return dictionary;\n } catch (error) {\n console.error(`Error loading content declaration at ${path}:`, error);\n return undefined;\n }\n};\n\nexport const loadContentDeclarations = async (\n contentDeclarationFilePath: string[],\n configuration: IntlayerConfig,\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: LoadContentDeclarationOptions\n): Promise<Dictionary[]> => {\n const { build, system } = configuration;\n\n // Check for TypeScript warnings before we build\n if (build.checkTypes) {\n logTypeScriptErrors(contentDeclarationFilePath, configuration).catch(\n (e) => {\n console.error('Error during TypeScript validation:', e);\n }\n );\n }\n\n const bundleFilePath = await ensureIntlayerBundle(configuration);\n\n try {\n const dictionariesPromises = contentDeclarationFilePath.map(\n async (path) => {\n const relativePath = relative(system.baseDir, path);\n\n const dictionary = await loadContentDeclaration(\n path,\n configuration,\n bundleFilePath,\n options\n );\n\n return { relativePath, dictionary };\n }\n );\n\n const dictionariesArray = await Promise.all(dictionariesPromises);\n const dictionariesRecord = dictionariesArray.reduce(\n (acc, { relativePath, dictionary }) => {\n if (dictionary) {\n acc[relativePath] = dictionary;\n }\n return acc;\n },\n {} as Record<string, Dictionary>\n );\n\n const contentDeclarations: Dictionary[] = formatLocalDictionaries(\n dictionariesRecord,\n configuration\n ).filter((dictionary) => dictionary.location !== 'remote');\n\n const listFoundDictionaries = contentDeclarations.map((declaration) => ({\n dictionaryKey: declaration.key,\n type: 'local' as const,\n status: 'found' as const,\n }));\n\n onStatusUpdate?.(listFoundDictionaries);\n\n const processedDictionaries = await parallelize(\n contentDeclarations,\n async (contentDeclaration): Promise<Dictionary | undefined> => {\n if (!contentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: contentDeclaration.key,\n type: 'local',\n status: 'building',\n },\n ]);\n\n const processedContentDeclaration = await processContentDeclaration(\n contentDeclaration as Dictionary,\n configuration\n );\n\n if (!processedContentDeclaration) {\n return undefined;\n }\n\n onStatusUpdate?.([\n {\n dictionaryKey: processedContentDeclaration.key,\n type: 'local',\n status: 'built',\n },\n ]);\n\n return processedContentDeclaration;\n }\n );\n\n return filterInvalidDictionaries(processedDictionaries, configuration, {\n checkSchema: false,\n });\n } catch {\n console.error('Error loading content declarations');\n }\n\n return [];\n};\n"],"mappings":";;;;;;;;;;;AAiBA,MAAa,2BACX,oBACA,kBAEA,OAAO,QAAQ,mBAAmB,CAAC,KAAK,CAAC,cAAc,WAAW;CAChE,GAAG;CACH,UAAU,KAAK,YAAY,cAAc,YAAY,YAAY;CACjE,SAAS,GAAG,KAAK,IAAI,WAAW;CAChC,UAAU;CACX,EAAE;AAEL,MAAa,uBAAuB,OAClC,kBACoB;CACpB,MAAM,EAAE,WAAW;CAEnB,MAAM,EAAE,KAAK,YAAY,UAAU,eAAe,CAAC,kBAAkB,EAAE,EACrE,OAAO,MAAO,KAAK,KAAK,KAAK,GAC9B,CAAC;CAEF,MAAM,WAAW,KAAK,OAAO,UAAU,sBAAsB;AAG7D,KAAI,CAAC,MAF2B,SAAS,EAEjB;AAEtB,QAAM,UAAU,UAAU,MADG,kBAAkB,cAAc,CACpB;AACzC,QAAM,IAAI,KAAK;;AAGjB,QAAO;;AAQT,IAAI,qBAAsC;AAG1C,MAAM,kBAAkB,OAAO,YAAuC;AACpE,KAAI,mBACF,QAAO;AAGT,KAAI;EAGF,MAAM,cAAc,MAAM,SAFF,mBAAmB,QAG1B,CAAC,iBAChB,QACD;EACD,MAAM,iBAAiB,KAAK,MAAM,YAAY;EAC9C,MAAM,kBAAkB,OAAO,KAAK;GAClC,GAAG,eAAe;GAClB,GAAG,eAAe;GACnB,CAAC;EAGF,MAAM,sBAAsB,CAAC,wBAAwB;EAErD,MAAM,eAAe,gBAAgB,QAClC,QAAQ,CAAC,oBAAoB,SAAS,IAAI,CAC5C;AAED,eAAa,KAAK,UAAU;AAG5B,uBAAqB;UACd,OAAO;AACd,UAAQ,KACN,uFACA,MACD;AACD,uBAAqB,CAAC,UAAU;;AAGlC,QAAO;;AAGT,MAAa,yBAAyB,OACpC,MACA,eACA,gBACA,YACoC;CACpC,MAAM,EAAE,OAAO,WAAW;CAG1B,MAAM,eAAe,MAAM,gBAAgB,OAAO,QAAQ;CAE1D,MAAM,yBACJ,kBAAmB,MAAM,qBAAqB,cAAc;AAE9D,KAAI;AAqBF,SAAO,MApBkB,iBAAiB,MAAM;GAC9C,UAAU,SAAS;GACnB,gBAAgB,MAAM,WAAW,mBAAmB;GACpD,cAAc;IACZ,UAAU;IACV,UAAU;IACV,QAAQ,EACN,IAAI;KACF,oBAAoB,KAAK,UAAU,KAAK,CAAC;KACzC,mBAAmB,KAAK,UAAU,QAAQ,KAAK,CAAC,CAAC;KACjD,oCAAoC,KAAK;KACzC,mCAAmC,cAAc,OAAO,QAAQ;KACjE,CAAC,KAAK,KAAK,EACb;IACF;GACD,SAAS,EACP,UAAU,wBACX;GACF,CAAC;UAGK,OAAO;AACd,UAAQ,MAAM,wCAAwC,KAAK,IAAI,MAAM;AACrE;;;AAIJ,MAAa,0BAA0B,OACrC,4BACA,eACA,gBACA,YAC0B;CAC1B,MAAM,EAAE,OAAO,WAAW;AAG1B,KAAI,MAAM,WACR,qBAAoB,4BAA4B,cAAc,CAAC,OAC5D,MAAM;AACL,UAAQ,MAAM,uCAAuC,EAAE;GAE1D;CAGH,MAAM,iBAAiB,MAAM,qBAAqB,cAAc;AAEhE,KAAI;EACF,MAAM,uBAAuB,2BAA2B,IACtD,OAAO,SAAS;AAUd,UAAO;IAAE,cATY,SAAS,OAAO,SAAS,KASzB;IAAE,kBAPE,uBACvB,MACA,eACA,gBACA,QACD;IAEkC;IAEtC;EAaD,MAAM,sBAAoC,yBAVf,MADK,QAAQ,IAAI,qBAAqB,EACpB,QAC1C,KAAK,EAAE,cAAc,iBAAiB;AACrC,OAAI,WACF,KAAI,gBAAgB;AAEtB,UAAO;KAET,EAAE,CAIgB,EAClB,cACD,CAAC,QAAQ,eAAe,WAAW,aAAa,SAAS;EAE1D,MAAM,wBAAwB,oBAAoB,KAAK,iBAAiB;GACtE,eAAe,YAAY;GAC3B,MAAM;GACN,QAAQ;GACT,EAAE;AAEH,mBAAiB,sBAAsB;AAsCvC,SAAO,0BAA0B,MApCG,YAClC,qBACA,OAAO,uBAAwD;AAC7D,OAAI,CAAC,mBACH;AAGF,oBAAiB,CACf;IACE,eAAe,mBAAmB;IAClC,MAAM;IACN,QAAQ;IACT,CACF,CAAC;GAEF,MAAM,8BAA8B,MAAM,0BACxC,oBACA,cACD;AAED,OAAI,CAAC,4BACH;AAGF,oBAAiB,CACf;IACE,eAAe,4BAA4B;IAC3C,MAAM;IACN,QAAQ;IACT,CACF,CAAC;AAEF,UAAO;IAEV,EAEuD,eAAe,EACrE,aAAa,OACd,CAAC;SACI;AACN,UAAQ,MAAM,qCAAqC;;AAGrD,QAAO,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadDictionaries.mjs","names":["logger"],"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { formatDictionaries } from '../formatDictionary';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadRemoteDictionaries } from './loadRemoteDictionaries';\nimport { DictionariesLogger } from './log';\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n type: 'local' | 'remote';\n status:\n | 'pending' // Key found but not fetched yet\n | 'fetching' // If dictionary fetch is in progress\n | 'fetched' // If dictionary fetch succeeded\n | 'error' // If dictionary fetch failed\n | 'imported' // If dictionary already fetched and still up to date\n | 'found' // If dictionary key is found but promise is not resolved yet (ex: fetching distant content)\n | 'building' // If dictionary is being built\n | 'built'; // If dictionary is built;\n error?: string;\n};\n\nlet loadDictionariesStatus: DictionariesStatus[] = [];\nconst logger = new DictionariesLogger();\n\nconst setLoadDictionariesStatus = (statuses: DictionariesStatus[]) => {\n const updated: DictionariesStatus[] = [...loadDictionariesStatus];\n\n for (const incoming of statuses) {\n const index = updated.findIndex(\n (s) =>\n s.dictionaryKey === incoming.dictionaryKey && s.type === incoming.type\n );\n if (index >= 0) {\n updated[index] = incoming;\n } else {\n updated.push(incoming);\n }\n }\n\n loadDictionariesStatus = updated;\n logger.update(statuses);\n\n return updated;\n};\n\ntype StatusRecord = {\n local?: DictionariesStatus['status'];\n remote?: DictionariesStatus['status'];\n};\n\nconst iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'built':\n case 'imported':\n case 'fetched':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n};\n\nconst colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'built':\n case 'imported':\n case 'fetched':\n return ANSIColors.GREEN;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n};\n\nconst printSummary = (configuration: IntlayerConfig) => {\n if (configuration.log.mode !== 'verbose') return;\n\n const appLogger = getAppLogger(configuration);\n\n // Aggregate by dictionary key\n const byKey = new Map<string, StatusRecord>();\n for (const status of loadDictionariesStatus) {\n const rec = byKey.get(status.dictionaryKey) ?? {};\n if (status.type === 'local') rec.local = status.status;\n if (status.type === 'remote') rec.remote = status.status;\n byKey.set(status.dictionaryKey, rec);\n }\n\n const keys = Array.from(byKey.keys()).sort((a, b) => a.localeCompare(b));\n\n // Compute the max visible length of the local label to align distant labels\n let maxLocalLabelLen = 0;\n for (const key of keys) {\n const rec = byKey.get(key)!;\n if (rec.local) {\n const visibleLocal = `[local: ${iconFor(rec.local)} ${rec.local}]`;\n if (visibleLocal.length > maxLocalLabelLen) {\n maxLocalLabelLen = visibleLocal.length;\n }\n }\n }\n\n for (const key of keys) {\n const rec = byKey.get(key)!;\n const labels: string[] = [];\n\n if (rec.local) {\n const inner = colorize(\n `${iconFor(rec.local)} ${rec.local}`,\n colorFor(rec.local)\n );\n const coloredLocal =\n `${ANSIColors.GREY}[` +\n colorize('local: ', ANSIColors.GREY) +\n inner +\n `${ANSIColors.GREY}]${ANSIColors.RESET}`;\n\n // Pad to align distant label across rows\n const visibleLocal = `[local: ${iconFor(rec.local)} ${rec.local}]`;\n const pad = Math.max(0, maxLocalLabelLen - visibleLocal.length);\n labels.push(coloredLocal + ' '.repeat(pad));\n } else {\n // If no local label, insert spaces to keep distant aligned\n labels.push(' '.repeat(maxLocalLabelLen));\n }\n\n if (rec.remote) {\n const inner = colorize(\n `${iconFor(rec.remote)} ${rec.remote}`,\n colorFor(rec.remote)\n );\n labels.push(\n `${ANSIColors.GREY}[` +\n colorize('distant: ', ANSIColors.GREY) +\n inner +\n `${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n appLogger(\n ` - ${colon(colorizeKey(key), { colSize: keys })} ${labels.join(' ')}`\n );\n }\n};\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string,\n configuration: IntlayerConfig\n): Promise<{\n localDictionaries: Dictionary[];\n remoteDictionaries: Dictionary[];\n pluginDictionaries: Dictionary[];\n time: {\n localDictionaries: number;\n remoteDictionaries: number;\n pluginDictionaries: number;\n };\n}> => {\n const { plugins } = configuration;\n const loadDictionariesStartTime = Date.now();\n const appLogger = getAppLogger(configuration);\n\n appLogger('Dictionaries:', { isVerbose: true });\n\n // Load additional dictionaries via plugins (e.g., ICU JSON ingestion)\n const resolvedPlugins = await Promise.all(plugins ?? []);\n\n const pluginsWithLoadDictionaries = resolvedPlugins.filter(\n (plugin) => plugin.loadDictionaries\n );\n\n const loadPluginDictionariesPromise = pluginsWithLoadDictionaries.map(\n async (plugin) => {\n try {\n const res = await plugin.loadDictionaries?.({\n configuration,\n });\n\n return (res as Dictionary[] | undefined) ?? [];\n } catch (error) {\n logger.setPluginError(error as Error);\n\n return [];\n }\n }\n );\n\n const pluginDictionaries: Dictionary[] = await Promise.all(\n loadPluginDictionariesPromise as Promise<Dictionary[]>[]\n )\n .then((dictionaries) => dictionaries.flat())\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n\n logger.setPluginTotal(pluginDictionaries.length);\n logger.setPluginDone(pluginDictionaries.length);\n\n const pluginDictionariesTime = Date.now();\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] = await loadContentDeclarations(\n files,\n configuration,\n setLoadDictionariesStatus\n )\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n\n const localDictionariesTime = Date.now();\n\n const localDictionariesStatus = localDictionaries.map(\n (dictionary) =>\n ({\n dictionaryKey: dictionary.key,\n type: 'local',\n status: 'built',\n }) as const\n );\n\n setLoadDictionariesStatus(localDictionariesStatus);\n\n const hasRemoteDictionaries = Boolean(\n configuration.editor.clientId && configuration.editor.clientSecret\n );\n\n if (hasRemoteDictionaries) {\n // We expect to fetch remote dictionaries soon; suppress a transient local-only render\n logger.setExpectRemote(true);\n }\n\n let remoteDictionaries: Dictionary[] = [];\n\n if (hasRemoteDictionaries) {\n remoteDictionaries = await loadRemoteDictionaries(\n configuration,\n setLoadDictionariesStatus,\n {\n onStartRemoteCheck: () => logger.startRemoteCheck(),\n onStopRemoteCheck: () => logger.stopRemoteCheck(),\n onError: (e) => logger.setRemoteError(e),\n }\n )\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n }\n\n const remoteDictionariesTime = Date.now();\n\n // Stop spinner and show final progress line(s)\n logger.finish();\n\n printSummary(configuration);\n\n return {\n localDictionaries,\n remoteDictionaries,\n pluginDictionaries,\n time: {\n localDictionaries: localDictionariesTime - pluginDictionariesTime,\n remoteDictionaries: remoteDictionariesTime - localDictionariesTime,\n pluginDictionaries: pluginDictionariesTime - loadDictionariesStartTime,\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"loadDictionaries.mjs","names":["logger"],"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { formatDictionaries } from '../formatDictionary';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadRemoteDictionaries } from './loadRemoteDictionaries';\nimport { DictionariesLogger } from './log';\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n type: 'local' | 'remote';\n status:\n | 'pending' // Key found but not fetched yet\n | 'fetching' // If dictionary fetch is in progress\n | 'fetched' // If dictionary fetch succeeded\n | 'error' // If dictionary fetch failed\n | 'imported' // If dictionary already fetched and still up to date\n | 'found' // If dictionary key is found but promise is not resolved yet (ex: fetching distant content)\n | 'building' // If dictionary is being built\n | 'built'; // If dictionary is built;\n error?: string;\n};\n\nlet loadDictionariesStatus: DictionariesStatus[] = [];\nconst logger = new DictionariesLogger();\n\nconst setLoadDictionariesStatus = (statuses: DictionariesStatus[]) => {\n const updated: DictionariesStatus[] = [...loadDictionariesStatus];\n\n for (const incoming of statuses) {\n const index = updated.findIndex(\n (s) =>\n s.dictionaryKey === incoming.dictionaryKey && s.type === incoming.type\n );\n if (index >= 0) {\n updated[index] = incoming;\n } else {\n updated.push(incoming);\n }\n }\n\n loadDictionariesStatus = updated;\n logger.update(statuses);\n\n return updated;\n};\n\ntype StatusRecord = {\n local?: DictionariesStatus['status'];\n remote?: DictionariesStatus['status'];\n};\n\nconst iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'built':\n case 'imported':\n case 'fetched':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n};\n\nconst colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'built':\n case 'imported':\n case 'fetched':\n return ANSIColors.GREEN;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n};\n\nconst printSummary = (configuration: IntlayerConfig) => {\n if (configuration.log.mode !== 'verbose') return;\n\n const appLogger = getAppLogger(configuration);\n\n // Aggregate by dictionary key\n const byKey = new Map<string, StatusRecord>();\n for (const status of loadDictionariesStatus) {\n const rec = byKey.get(status.dictionaryKey) ?? {};\n if (status.type === 'local') rec.local = status.status;\n if (status.type === 'remote') rec.remote = status.status;\n byKey.set(status.dictionaryKey, rec);\n }\n\n const keys = Array.from(byKey.keys()).sort((a, b) => a.localeCompare(b));\n\n // Compute the max visible length of the local label to align distant labels\n let maxLocalLabelLen = 0;\n for (const key of keys) {\n const rec = byKey.get(key)!;\n if (rec.local) {\n const visibleLocal = `[local: ${iconFor(rec.local)} ${rec.local}]`;\n if (visibleLocal.length > maxLocalLabelLen) {\n maxLocalLabelLen = visibleLocal.length;\n }\n }\n }\n\n for (const key of keys) {\n const rec = byKey.get(key)!;\n const labels: string[] = [];\n\n if (rec.local) {\n const inner = colorize(\n `${iconFor(rec.local)} ${rec.local}`,\n colorFor(rec.local)\n );\n const coloredLocal =\n `${ANSIColors.GREY}[` +\n colorize('local: ', ANSIColors.GREY) +\n inner +\n `${ANSIColors.GREY}]${ANSIColors.RESET}`;\n\n // Pad to align distant label across rows\n const visibleLocal = `[local: ${iconFor(rec.local)} ${rec.local}]`;\n const pad = Math.max(0, maxLocalLabelLen - visibleLocal.length);\n labels.push(coloredLocal + ' '.repeat(pad));\n } else {\n // If no local label, insert spaces to keep distant aligned\n labels.push(' '.repeat(maxLocalLabelLen));\n }\n\n if (rec.remote) {\n const inner = colorize(\n `${iconFor(rec.remote)} ${rec.remote}`,\n colorFor(rec.remote)\n );\n labels.push(\n `${ANSIColors.GREY}[` +\n colorize('distant: ', ANSIColors.GREY) +\n inner +\n `${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n appLogger(\n ` - ${colon(colorizeKey(key), { colSize: keys })} ${labels.join(' ')}`\n );\n }\n};\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string,\n configuration: IntlayerConfig\n): Promise<{\n localDictionaries: Dictionary[];\n remoteDictionaries: Dictionary[];\n pluginDictionaries: Dictionary[];\n time: {\n localDictionaries: number;\n remoteDictionaries: number;\n pluginDictionaries: number;\n };\n}> => {\n const { plugins } = configuration;\n const loadDictionariesStartTime = Date.now();\n const appLogger = getAppLogger(configuration);\n\n appLogger('Dictionaries:', { isVerbose: true });\n\n // Load additional dictionaries via plugins (e.g., ICU JSON ingestion)\n const resolvedPlugins = await Promise.all(plugins ?? []);\n\n const pluginsWithLoadDictionaries = resolvedPlugins.filter(\n (plugin) => plugin.loadDictionaries\n );\n\n const loadPluginDictionariesPromise = pluginsWithLoadDictionaries.map(\n async (plugin) => {\n try {\n const res = await plugin.loadDictionaries?.({\n configuration,\n });\n\n return (res as Dictionary[] | undefined) ?? [];\n } catch (error) {\n logger.setPluginError(error as Error);\n\n return [];\n }\n }\n );\n\n const pluginDictionaries: Dictionary[] = await Promise.all(\n loadPluginDictionariesPromise as Promise<Dictionary[]>[]\n )\n .then((dictionaries) => dictionaries.flat())\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n\n logger.setPluginTotal(pluginDictionaries.length);\n logger.setPluginDone(pluginDictionaries.length);\n\n const pluginDictionariesTime = Date.now();\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] = await loadContentDeclarations(\n files,\n configuration,\n setLoadDictionariesStatus\n )\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n\n const localDictionariesTime = Date.now();\n\n const localDictionariesStatus = localDictionaries.map(\n (dictionary) =>\n ({\n dictionaryKey: dictionary.key,\n type: 'local',\n status: 'built',\n }) as const\n );\n\n setLoadDictionariesStatus(localDictionariesStatus);\n\n const hasRemoteDictionaries = Boolean(\n configuration.editor.clientId && configuration.editor.clientSecret\n );\n\n if (hasRemoteDictionaries) {\n // We expect to fetch remote dictionaries soon; suppress a transient local-only render\n logger.setExpectRemote(true);\n }\n\n let remoteDictionaries: Dictionary[] = [];\n\n if (hasRemoteDictionaries) {\n remoteDictionaries = await loadRemoteDictionaries(\n configuration,\n setLoadDictionariesStatus,\n {\n onStartRemoteCheck: () => logger.startRemoteCheck(),\n onStopRemoteCheck: () => logger.stopRemoteCheck(),\n onError: (e) => logger.setRemoteError(e),\n }\n )\n .then((dictionaries) =>\n filterInvalidDictionaries(dictionaries, configuration)\n )\n .then((dictionaries) => formatDictionaries(dictionaries));\n }\n\n const remoteDictionariesTime = Date.now();\n\n // Stop spinner and show final progress line(s)\n logger.finish();\n\n printSummary(configuration);\n\n return {\n localDictionaries,\n remoteDictionaries,\n pluginDictionaries,\n time: {\n localDictionaries: localDictionariesTime - pluginDictionariesTime,\n remoteDictionaries: remoteDictionariesTime - localDictionariesTime,\n pluginDictionaries: pluginDictionariesTime - loadDictionariesStartTime,\n },\n };\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadRemoteDictionaries.mjs","names":[],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\n// @ts-ignore @intlayer/backend is not build yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getRemoteDictionaries } from '@intlayer/remote-dictionaries-entry';\nimport type { Dictionary, DictionaryId, DictionaryKey } from '@intlayer/types/dictionary';\nimport { fetchDistantDictionaries } from '../fetchDistantDictionaries';\nimport type { DictionariesStatus } from '../loadDictionaries/loadDictionaries';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\n\nexport const formatDistantDictionaries = (\n dictionaries: (DictionaryAPI | Dictionary)[]\n): Dictionary[] =>\n dictionaries.map((dict) => ({\n ...dict,\n localId: `${dict.key}::remote::${dict.id}`,\n location: 'remote' as const,\n }));\n\nexport const loadRemoteDictionaries = async (\n configuration = getConfiguration(),\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: {\n onStartRemoteCheck?: () => void;\n onStopRemoteCheck?: () => void;\n onError?: (error: Error) => void;\n }\n): Promise<Dictionary[]> => {\n const { editor } = configuration;\n const remoteDictionariesRecord = getRemoteDictionaries(configuration);\n\n const hasRemoteDictionaries = Boolean(editor.clientId && editor.clientSecret);\n\n if (!hasRemoteDictionaries) return [];\n\n try {\n options?.onStartRemoteCheck?.();\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n const distantDictionaryUpdateTimeStamp: Record<\n DictionaryId,\n { key: DictionaryKey; updatedAt: number }\n > | null = getDictionariesKeysResult.data;\n\n if (!distantDictionaryUpdateTimeStamp) {\n throw new Error('No distant dictionaries found');\n }\n\n const dictionariesIdToFetch = Object.entries(\n distantDictionaryUpdateTimeStamp\n ).filter(([dictionaryId, data]) => {\n // If remote doesn't provide updatedAt, fetch to be safe\n if (!data.updatedAt) return true;\n\n // If no local cache exists, fetch\n const local: Dictionary | undefined = remoteDictionariesRecord[\n data.key\n ]?.find((dictionary) => dictionary.id === dictionaryId);\n if (!local) return true;\n\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n\n // If local timestamp missing or older than remote, fetch\n if (typeof localUpdatedAt !== 'number') return true;\n\n return data.updatedAt > localUpdatedAt;\n });\n\n const flatRemoteDictionariesRecord: DictionaryAPI[] = Object.values(\n remoteDictionariesRecord\n ).flat();\n\n const cachedDictionaries: Dictionary[] =\n flatRemoteDictionariesRecord.filter((dictionary) => {\n const remoteUpdatedAt =\n distantDictionaryUpdateTimeStamp[dictionary.id!].updatedAt;\n\n const localUpdatedAtRaw = dictionary.updatedAt;\n\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n\n // Consider as cached/imported when local exists and is up-to-date or newer\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n });\n\n // Report cached as already imported\n if (cachedDictionaries.length > 0) {\n onStatusUpdate?.(\n cachedDictionaries.map((dictionary) => ({\n dictionaryKey: dictionary.key,\n type: 'remote',\n status: 'imported',\n }))\n );\n }\n\n const orderedDistantDictionaryKeys = dictionariesIdToFetch\n .map(([, data]) => data.key)\n .sort(sortAlphabetically);\n\n // Report pending for keys to be fetched so totals are visible immediately\n if (orderedDistantDictionaryKeys.length > 0) {\n onStatusUpdate?.(\n orderedDistantDictionaryKeys.map((key) => ({\n dictionaryKey: key,\n type: 'remote',\n status: 'pending',\n }))\n );\n }\n\n const distantDictionariesData = await fetchDistantDictionaries(\n {\n dictionaryKeys: orderedDistantDictionaryKeys,\n },\n onStatusUpdate\n );\n\n const distantDictionaries: Dictionary[] = formatDistantDictionaries(\n distantDictionariesData\n );\n\n return [...cachedDictionaries, ...distantDictionaries];\n } catch (error) {\n options?.onError?.(error as Error);\n return [];\n } finally {\n options?.onStopRemoteCheck?.();\n }\n};\n"],"mappings":";;;;;;;AAUA,MAAa,6BACX,iBAEA,aAAa,KAAK,UAAU;CAC1B,GAAG;CACH,SAAS,GAAG,KAAK,IAAI,YAAY,KAAK;CACtC,UAAU;CACX,EAAE;AAEL,MAAa,yBAAyB,OACpC,gBAAgB,kBAAkB,EAClC,gBACA,YAK0B;CAC1B,MAAM,EAAE,WAAW;CACnB,MAAM,2BAA2B,sBAAsB,cAAc;AAIrE,KAAI,CAF0B,QAAQ,OAAO,YAAY,OAAO,aAAa,CAEjD,QAAO,EAAE;AAErC,KAAI;AACF,WAAS,sBAAsB;EAQ/B,MAAM,oCAFJ,MAJkB,oBAAoB,QAAW,cAAc,CAI7C,WAAW,gCAAgC,EAK1B;AAErC,MAAI,CAAC,iCACH,OAAM,IAAI,MAAM,gCAAgC;EAGlD,MAAM,wBAAwB,OAAO,QACnC,iCACD,CAAC,QAAQ,CAAC,cAAc,UAAU;AAEjC,OAAI,CAAC,KAAK,UAAW,QAAO;GAG5B,MAAM,QAAgC,yBACpC,KAAK,MACJ,MAAM,eAAe,WAAW,OAAO,aAAa;AACvD,OAAI,CAAC,MAAO,QAAO;GAEnB,MAAM,oBAAqB,OAAe;GAK1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,kBAAkB,CAAC,SAAS,GACrC;AAGR,OAAI,OAAO,mBAAmB,SAAU,QAAO;AAE/C,UAAO,KAAK,YAAY;IACxB;EAMF,MAAM,qBAJgD,OAAO,OAC3D,yBACD,CAAC,MAAM,CAGuB,QAAQ,eAAe;GAClD,MAAM,kBACJ,iCAAiC,WAAW,IAAK;GAEnD,MAAM,oBAAoB,WAAW;GAErC,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,kBAAkB,CAAC,SAAS,GACrC;AAGR,UACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;IAEpB;AAGJ,MAAI,mBAAmB,SAAS,EAC9B,kBACE,mBAAmB,KAAK,gBAAgB;GACtC,eAAe,WAAW;GAC1B,MAAM;GACN,QAAQ;GACT,EAAE,CACJ;EAGH,MAAM,+BAA+B,sBAClC,KAAK,GAAG,UAAU,KAAK,IAAI,CAC3B,KAAK,mBAAmB;AAG3B,MAAI,6BAA6B,SAAS,EACxC,kBACE,6BAA6B,KAAK,SAAS;GACzC,eAAe;GACf,MAAM;GACN,QAAQ;GACT,EAAE,CACJ;EAUH,MAAM,sBAAoC,0BAPV,MAAM,yBACpC,EACE,gBAAgB,8BACjB,EACD,eACD,CAIA;AAED,SAAO,CAAC,GAAG,oBAAoB,GAAG,oBAAoB;UAC/C,OAAO;AACd,WAAS,UAAU,MAAe;AAClC,SAAO,EAAE;WACD;AACR,WAAS,qBAAqB"}
1
+ {"version":3,"file":"loadRemoteDictionaries.mjs","names":[],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\n// @ts-ignore @intlayer/backend is not build yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getRemoteDictionaries } from '@intlayer/remote-dictionaries-entry';\nimport type { Dictionary, DictionaryId, DictionaryKey } from '@intlayer/types/dictionary';\nimport { fetchDistantDictionaries } from '../fetchDistantDictionaries';\nimport type { DictionariesStatus } from '../loadDictionaries/loadDictionaries';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\n\nexport const formatDistantDictionaries = (\n dictionaries: (DictionaryAPI | Dictionary)[]\n): Dictionary[] =>\n dictionaries.map((dict) => ({\n ...dict,\n localId: `${dict.key}::remote::${dict.id}`,\n location: 'remote' as const,\n }));\n\nexport const loadRemoteDictionaries = async (\n configuration = getConfiguration(),\n onStatusUpdate?: (status: DictionariesStatus[]) => void,\n options?: {\n onStartRemoteCheck?: () => void;\n onStopRemoteCheck?: () => void;\n onError?: (error: Error) => void;\n }\n): Promise<Dictionary[]> => {\n const { editor } = configuration;\n const remoteDictionariesRecord = getRemoteDictionaries(configuration);\n\n const hasRemoteDictionaries = Boolean(editor.clientId && editor.clientSecret);\n\n if (!hasRemoteDictionaries) return [];\n\n try {\n options?.onStartRemoteCheck?.();\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n const distantDictionaryUpdateTimeStamp: Record<\n DictionaryId,\n { key: DictionaryKey; updatedAt: number }\n > | null = getDictionariesKeysResult.data;\n\n if (!distantDictionaryUpdateTimeStamp) {\n throw new Error('No distant dictionaries found');\n }\n\n const dictionariesIdToFetch = Object.entries(\n distantDictionaryUpdateTimeStamp\n ).filter(([dictionaryId, data]) => {\n // If remote doesn't provide updatedAt, fetch to be safe\n if (!data.updatedAt) return true;\n\n // If no local cache exists, fetch\n const local: Dictionary | undefined = remoteDictionariesRecord[\n data.key\n ]?.find((dictionary) => dictionary.id === dictionaryId);\n if (!local) return true;\n\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n\n // If local timestamp missing or older than remote, fetch\n if (typeof localUpdatedAt !== 'number') return true;\n\n return data.updatedAt > localUpdatedAt;\n });\n\n const flatRemoteDictionariesRecord: DictionaryAPI[] = Object.values(\n remoteDictionariesRecord\n ).flat();\n\n const cachedDictionaries: Dictionary[] =\n flatRemoteDictionariesRecord.filter((dictionary) => {\n const remoteUpdatedAt =\n distantDictionaryUpdateTimeStamp[dictionary.id!].updatedAt;\n\n const localUpdatedAtRaw = dictionary.updatedAt;\n\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n\n // Consider as cached/imported when local exists and is up-to-date or newer\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n });\n\n // Report cached as already imported\n if (cachedDictionaries.length > 0) {\n onStatusUpdate?.(\n cachedDictionaries.map((dictionary) => ({\n dictionaryKey: dictionary.key,\n type: 'remote',\n status: 'imported',\n }))\n );\n }\n\n const orderedDistantDictionaryKeys = dictionariesIdToFetch\n .map(([, data]) => data.key)\n .sort(sortAlphabetically);\n\n // Report pending for keys to be fetched so totals are visible immediately\n if (orderedDistantDictionaryKeys.length > 0) {\n onStatusUpdate?.(\n orderedDistantDictionaryKeys.map((key) => ({\n dictionaryKey: key,\n type: 'remote',\n status: 'pending',\n }))\n );\n }\n\n const distantDictionariesData = await fetchDistantDictionaries(\n {\n dictionaryKeys: orderedDistantDictionaryKeys,\n },\n onStatusUpdate\n );\n\n const distantDictionaries: Dictionary[] = formatDistantDictionaries(\n distantDictionariesData\n );\n\n return [...cachedDictionaries, ...distantDictionaries];\n } catch (error) {\n options?.onError?.(error as Error);\n return [];\n } finally {\n options?.onStopRemoteCheck?.();\n }\n};\n"],"mappings":";;;;;;;AAUA,MAAa,6BACX,iBAEA,aAAa,KAAK,UAAU;CAC1B,GAAG;CACH,SAAS,GAAG,KAAK,IAAI,YAAY,KAAK;CACtC,UAAU;CACX,EAAE;AAEL,MAAa,yBAAyB,OACpC,gBAAgB,kBAAkB,EAClC,gBACA,YAK0B;CAC1B,MAAM,EAAE,WAAW;CACnB,MAAM,2BAA2B,sBAAsB,cAAc;AAIrE,KAAI,CAF0B,QAAQ,OAAO,YAAY,OAAO,aAEtC,CAAE,QAAO,EAAE;AAErC,KAAI;AACF,WAAS,sBAAsB;EAQ/B,MAAM,oCAGK,MATS,oBAAoB,QAAW,cAIhC,CAAC,WAAW,gCAAgC,EAK1B;AAErC,MAAI,CAAC,iCACH,OAAM,IAAI,MAAM,gCAAgC;EAGlD,MAAM,wBAAwB,OAAO,QACnC,iCACD,CAAC,QAAQ,CAAC,cAAc,UAAU;AAEjC,OAAI,CAAC,KAAK,UAAW,QAAO;GAG5B,MAAM,QAAgC,yBACpC,KAAK,MACJ,MAAM,eAAe,WAAW,OAAO,aAAa;AACvD,OAAI,CAAC,MAAO,QAAO;GAEnB,MAAM,oBAAqB,OAAe;GAK1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,kBAAkB,CAAC,SAAS,GACrC;AAGR,OAAI,OAAO,mBAAmB,SAAU,QAAO;AAE/C,UAAO,KAAK,YAAY;IACxB;EAMF,MAAM,qBAJgD,OAAO,OAC3D,yBACD,CAAC,MAG4B,CAAC,QAAQ,eAAe;GAClD,MAAM,kBACJ,iCAAiC,WAAW,IAAK;GAEnD,MAAM,oBAAoB,WAAW;GAErC,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,kBAAkB,CAAC,SAAS,GACrC;AAGR,UACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;IAEpB;AAGJ,MAAI,mBAAmB,SAAS,EAC9B,kBACE,mBAAmB,KAAK,gBAAgB;GACtC,eAAe,WAAW;GAC1B,MAAM;GACN,QAAQ;GACT,EAAE,CACJ;EAGH,MAAM,+BAA+B,sBAClC,KAAK,GAAG,UAAU,KAAK,IAAI,CAC3B,KAAK,mBAAmB;AAG3B,MAAI,6BAA6B,SAAS,EACxC,kBACE,6BAA6B,KAAK,SAAS;GACzC,eAAe;GACf,MAAM;GACN,QAAQ;GACT,EAAE,CACJ;EAUH,MAAM,sBAAoC,0BACxC,MARoC,yBACpC,EACE,gBAAgB,8BACjB,EACD,eACD,CAIA;AAED,SAAO,CAAC,GAAG,oBAAoB,GAAG,oBAAoB;UAC/C,OAAO;AACd,WAAS,UAAU,MAAe;AAClC,SAAO,EAAE;WACD;AACR,WAAS,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"logTypeScriptErrors.mjs","names":[],"sources":["../../../src/loadDictionaries/logTypeScriptErrors.ts"],"sourcesContent":["import { dirname, extname } from 'node:path';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\nexport const logTypeScriptErrors = async (\n filePaths: string[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n\n const filesToCheck = filePaths.filter((path) => {\n const ext = extname(path);\n\n return ['.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs', '.json'].includes(\n ext\n );\n });\n\n if (filesToCheck.length === 0) return;\n\n let ts: typeof import('typescript');\n\n try {\n ts = (await import('typescript')).default || (await import('typescript'));\n } catch {\n // TypeScript not installed, skip type checking\n\n return;\n }\n\n const configFileName = ts.findConfigFile(\n configuration.system?.baseDir ?? process.cwd(),\n ts.sys.fileExists,\n 'tsconfig.json'\n );\n\n let compilerOptions: any = {\n noEmit: true,\n\n allowJs: true,\n\n resolveJsonModule: true,\n };\n\n if (configFileName) {\n const configFileText = ts.sys.readFile(configFileName);\n\n if (configFileText) {\n const configJson = ts.parseConfigFileTextToJson(\n configFileName,\n\n configFileText\n );\n\n if (!configJson.error) {\n const parsedConfig = ts.parseJsonConfigFileContent(\n configJson.config,\n\n ts.sys,\n\n dirname(configFileName)\n );\n\n const { incremental, tsBuildInfoFile, ...restOptions } =\n parsedConfig.options;\n\n compilerOptions = { ...compilerOptions, ...restOptions, noEmit: true };\n }\n }\n }\n\n const program = ts.createProgram(filesToCheck, compilerOptions);\n\n filesToCheck.forEach((filePath) => {\n const sourceFile = program.getSourceFile(filePath);\n\n if (!sourceFile) return;\n\n const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);\n\n diagnostics.forEach((diagnostic) => {\n const message = ts.flattenDiagnosticMessageText(\n diagnostic.messageText,\n\n '\\n'\n );\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const { line, character } =\n diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n\n appLogger(\n `TS Error in ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`,\n\n { level: 'warn' }\n );\n }\n });\n });\n};\n"],"mappings":";;;;AAIA,MAAa,sBAAsB,OACjC,WACA,kBACG;CACH,MAAM,YAAY,aAAa,cAAc;CAE7C,MAAM,eAAe,UAAU,QAAQ,SAAS;EAC9C,MAAM,MAAM,QAAQ,KAAK;AAEzB,SAAO;GAAC;GAAO;GAAQ;GAAO;GAAQ;GAAQ;GAAQ;GAAQ,CAAC,SAC7D,IACD;GACD;AAEF,KAAI,aAAa,WAAW,EAAG;CAE/B,IAAI;AAEJ,KAAI;AACF,QAAM,MAAM,OAAO,eAAe,WAAY,MAAM,OAAO;SACrD;AAGN;;CAGF,MAAM,iBAAiB,GAAG,eACxB,cAAc,QAAQ,WAAW,QAAQ,KAAK,EAC9C,GAAG,IAAI,YACP,gBACD;CAED,IAAI,kBAAuB;EACzB,QAAQ;EAER,SAAS;EAET,mBAAmB;EACpB;AAED,KAAI,gBAAgB;EAClB,MAAM,iBAAiB,GAAG,IAAI,SAAS,eAAe;AAEtD,MAAI,gBAAgB;GAClB,MAAM,aAAa,GAAG,0BACpB,gBAEA,eACD;AAED,OAAI,CAAC,WAAW,OAAO;IASrB,MAAM,EAAE,aAAa,iBAAiB,GAAG,gBARpB,GAAG,2BACtB,WAAW,QAEX,GAAG,KAEH,QAAQ,eAAe,CACxB,CAGc;AAEf,sBAAkB;KAAE,GAAG;KAAiB,GAAG;KAAa,QAAQ;KAAM;;;;CAK5E,MAAM,UAAU,GAAG,cAAc,cAAc,gBAAgB;AAE/D,cAAa,SAAS,aAAa;EACjC,MAAM,aAAa,QAAQ,cAAc,SAAS;AAElD,MAAI,CAAC,WAAY;AAIjB,EAFoB,GAAG,sBAAsB,SAAS,WAAW,CAErD,SAAS,eAAe;GAClC,MAAM,UAAU,GAAG,6BACjB,WAAW,aAEX,KACD;AAED,OAAI,WAAW,QAAQ,WAAW,UAAU,QAAW;IACrD,MAAM,EAAE,MAAM,cACZ,WAAW,KAAK,8BAA8B,WAAW,MAAM;AAEjE,cACE,eAAe,WAAW,KAAK,SAAS,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,KAAK,WAE3E,EAAE,OAAO,QAAQ,CAClB;;IAEH;GACF"}
1
+ {"version":3,"file":"logTypeScriptErrors.mjs","names":[],"sources":["../../../src/loadDictionaries/logTypeScriptErrors.ts"],"sourcesContent":["import { dirname, extname } from 'node:path';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\nexport const logTypeScriptErrors = async (\n filePaths: string[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n\n const filesToCheck = filePaths.filter((path) => {\n const ext = extname(path);\n\n return ['.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs', '.json'].includes(\n ext\n );\n });\n\n if (filesToCheck.length === 0) return;\n\n let ts: typeof import('typescript');\n\n try {\n ts = (await import('typescript')).default || (await import('typescript'));\n } catch {\n // TypeScript not installed, skip type checking\n\n return;\n }\n\n const configFileName = ts.findConfigFile(\n configuration.system?.baseDir ?? process.cwd(),\n ts.sys.fileExists,\n 'tsconfig.json'\n );\n\n let compilerOptions: any = {\n noEmit: true,\n\n allowJs: true,\n\n resolveJsonModule: true,\n };\n\n if (configFileName) {\n const configFileText = ts.sys.readFile(configFileName);\n\n if (configFileText) {\n const configJson = ts.parseConfigFileTextToJson(\n configFileName,\n\n configFileText\n );\n\n if (!configJson.error) {\n const parsedConfig = ts.parseJsonConfigFileContent(\n configJson.config,\n\n ts.sys,\n\n dirname(configFileName)\n );\n\n const { incremental, tsBuildInfoFile, ...restOptions } =\n parsedConfig.options;\n\n compilerOptions = { ...compilerOptions, ...restOptions, noEmit: true };\n }\n }\n }\n\n const program = ts.createProgram(filesToCheck, compilerOptions);\n\n filesToCheck.forEach((filePath) => {\n const sourceFile = program.getSourceFile(filePath);\n\n if (!sourceFile) return;\n\n const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);\n\n diagnostics.forEach((diagnostic) => {\n const message = ts.flattenDiagnosticMessageText(\n diagnostic.messageText,\n\n '\\n'\n );\n\n if (diagnostic.file && diagnostic.start !== undefined) {\n const { line, character } =\n diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);\n\n appLogger(\n `TS Error in ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`,\n\n { level: 'warn' }\n );\n }\n });\n });\n};\n"],"mappings":";;;;AAIA,MAAa,sBAAsB,OACjC,WACA,kBACG;CACH,MAAM,YAAY,aAAa,cAAc;CAE7C,MAAM,eAAe,UAAU,QAAQ,SAAS;EAC9C,MAAM,MAAM,QAAQ,KAAK;AAEzB,SAAO;GAAC;GAAO;GAAQ;GAAO;GAAQ;GAAQ;GAAQ;GAAQ,CAAC,SAC7D,IACD;GACD;AAEF,KAAI,aAAa,WAAW,EAAG;CAE/B,IAAI;AAEJ,KAAI;AACF,QAAM,MAAM,OAAO,eAAe,WAAY,MAAM,OAAO;SACrD;AAGN;;CAGF,MAAM,iBAAiB,GAAG,eACxB,cAAc,QAAQ,WAAW,QAAQ,KAAK,EAC9C,GAAG,IAAI,YACP,gBACD;CAED,IAAI,kBAAuB;EACzB,QAAQ;EAER,SAAS;EAET,mBAAmB;EACpB;AAED,KAAI,gBAAgB;EAClB,MAAM,iBAAiB,GAAG,IAAI,SAAS,eAAe;AAEtD,MAAI,gBAAgB;GAClB,MAAM,aAAa,GAAG,0BACpB,gBAEA,eACD;AAED,OAAI,CAAC,WAAW,OAAO;IASrB,MAAM,EAAE,aAAa,iBAAiB,GAAG,gBARpB,GAAG,2BACtB,WAAW,QAEX,GAAG,KAEH,QAAQ,eAAe,CAIX,CAAC;AAEf,sBAAkB;KAAE,GAAG;KAAiB,GAAG;KAAa,QAAQ;KAAM;;;;CAK5E,MAAM,UAAU,GAAG,cAAc,cAAc,gBAAgB;AAE/D,cAAa,SAAS,aAAa;EACjC,MAAM,aAAa,QAAQ,cAAc,SAAS;AAElD,MAAI,CAAC,WAAY;AAIjB,EAFoB,GAAG,sBAAsB,SAAS,WAE3C,CAAC,SAAS,eAAe;GAClC,MAAM,UAAU,GAAG,6BACjB,WAAW,aAEX,KACD;AAED,OAAI,WAAW,QAAQ,WAAW,UAAU,QAAW;IACrD,MAAM,EAAE,MAAM,cACZ,WAAW,KAAK,8BAA8B,WAAW,MAAM;AAEjE,cACE,eAAe,WAAW,KAAK,SAAS,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,KAAK,WAE3E,EAAE,OAAO,QAAQ,CAClB;;IAEH;GACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"logConfigDetails.mjs","names":[],"sources":["../../src/logConfigDetails.ts"],"sourcesContent":["import { join, relative } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { getEnvFilePath } from '@intlayer/config/env';\nimport {\n colorize,\n colorizePath,\n getAppLogger,\n x,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfigurationAndFilePath,\n intlayerConfigSchema,\n} from '@intlayer/config/node';\nimport { formatPath, runOnce } from './utils';\n\nexport const logConfigDetails = (options?: GetConfigurationOptions) => {\n const {\n configuration,\n customConfiguration,\n numCustomConfiguration,\n configurationFilePath,\n } = getConfigurationAndFilePath(options);\n const appLogger = getAppLogger(configuration);\n\n runOnce(\n join(\n configuration.system.baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-config-locaded.lock'\n ),\n () => {\n if (numCustomConfiguration === 0) {\n appLogger(\n 'Configuration file not found, using default configuration.',\n {\n isVerbose: true,\n }\n );\n } else {\n const baseDir = configuration.system.baseDir;\n const relativeOutputPath = relative(baseDir, configurationFilePath!);\n\n if (numCustomConfiguration === 1) {\n const dotEnvFilePath = getEnvFilePath(options?.env, options?.envFile);\n\n appLogger(\n `Configuration loaded ${formatPath(relativeOutputPath)}${dotEnvFilePath ? ` - Env: ${formatPath(dotEnvFilePath)}` : ''}`,\n {\n isVerbose: true,\n }\n );\n } else {\n appLogger(\n `Multiple configuration files found, using ${formatPath(relativeOutputPath)}.`,\n {\n isVerbose: true,\n }\n );\n }\n }\n\n if (customConfiguration) {\n const validation = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!validation.success) {\n const errorMessages = validation.error.issues\n .map((error) => {\n const path = colorizePath(` - ${error.path.join('.')}:`);\n const message = colorize(error.message, ANSIColors.GREY_DARK);\n return `${path} ${message}`;\n })\n .join('\\n');\n const errorMessage = `${x} Invalid configuration:\\n${errorMessages}`;\n\n appLogger(errorMessage);\n }\n\n if (customConfiguration.build?.importMode) {\n appLogger(\n `${colorize('build.importMode', ANSIColors.BLUE)} is deprecated, use ${colorize('dictionary.importMode', ANSIColors.BLUE)} instead`\n );\n }\n if (customConfiguration.compiler?.transformPattern) {\n appLogger(\n `${colorize('compiler.transformPattern', ANSIColors.BLUE)} is deprecated, use ${colorize('build.traversePattern', ANSIColors.BLUE)} instead`\n );\n }\n if (customConfiguration.compiler?.excludePattern) {\n appLogger(\n `${colorize('compiler.excludePattern', ANSIColors.BLUE)} is deprecated, use ${colorize('build.traversePattern', ANSIColors.BLUE)} instead`\n );\n }\n }\n },\n {\n cacheTimeoutMs: 1000 * 60, // 1 minute\n }\n );\n};\n"],"mappings":";;;;;;;;;AAgBA,MAAa,oBAAoB,YAAsC;CACrE,MAAM,EACJ,eACA,qBACA,wBACA,0BACE,4BAA4B,QAAQ;CACxC,MAAM,YAAY,aAAa,cAAc;AAE7C,SACE,KACE,cAAc,OAAO,SACrB,aACA,SACA,+BACD,QACK;AACJ,MAAI,2BAA2B,EAC7B,WACE,8DACA,EACE,WAAW,MACZ,CACF;OACI;GACL,MAAM,UAAU,cAAc,OAAO;GACrC,MAAM,qBAAqB,SAAS,SAAS,sBAAuB;AAEpE,OAAI,2BAA2B,GAAG;IAChC,MAAM,iBAAiB,eAAe,SAAS,KAAK,SAAS,QAAQ;AAErE,cACE,wBAAwB,WAAW,mBAAmB,GAAG,iBAAiB,WAAW,WAAW,eAAe,KAAK,MACpH,EACE,WAAW,MACZ,CACF;SAED,WACE,6CAA6C,WAAW,mBAAmB,CAAC,IAC5E,EACE,WAAW,MACZ,CACF;;AAIL,MAAI,qBAAqB;GACvB,MAAM,aAAa,qBAAqB,UAAU,oBAAoB;AAEtE,OAAI,CAAC,WAAW,QAUd,WAFqB,GAAG,EAAE,2BAPJ,WAAW,MAAM,OACpC,KAAK,UAAU;AAGd,WAAO,GAFM,aAAa,MAAM,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG,CAEzC,GADC,SAAS,MAAM,SAAS,WAAW,UAAU;KAE7D,CACD,KAAK,KAAK,GAGU;AAGzB,OAAI,oBAAoB,OAAO,WAC7B,WACE,GAAG,SAAS,oBAAoB,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UAC3H;AAEH,OAAI,oBAAoB,UAAU,iBAChC,WACE,GAAG,SAAS,6BAA6B,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UACpI;AAEH,OAAI,oBAAoB,UAAU,eAChC,WACE,GAAG,SAAS,2BAA2B,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UAClI;;IAIP,EACE,gBAAgB,MAAO,IACxB,CACF"}
1
+ {"version":3,"file":"logConfigDetails.mjs","names":[],"sources":["../../src/logConfigDetails.ts"],"sourcesContent":["import { join, relative } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { getEnvFilePath } from '@intlayer/config/env';\nimport {\n colorize,\n colorizePath,\n getAppLogger,\n x,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfigurationAndFilePath,\n intlayerConfigSchema,\n} from '@intlayer/config/node';\nimport { formatPath, runOnce } from './utils';\n\nexport const logConfigDetails = (options?: GetConfigurationOptions) => {\n const {\n configuration,\n customConfiguration,\n numCustomConfiguration,\n configurationFilePath,\n } = getConfigurationAndFilePath(options);\n const appLogger = getAppLogger(configuration);\n\n runOnce(\n join(\n configuration.system.baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-config-locaded.lock'\n ),\n () => {\n if (numCustomConfiguration === 0) {\n appLogger(\n 'Configuration file not found, using default configuration.',\n {\n isVerbose: true,\n }\n );\n } else {\n const baseDir = configuration.system.baseDir;\n const relativeOutputPath = relative(baseDir, configurationFilePath!);\n\n if (numCustomConfiguration === 1) {\n const dotEnvFilePath = getEnvFilePath(options?.env, options?.envFile);\n\n appLogger(\n `Configuration loaded ${formatPath(relativeOutputPath)}${dotEnvFilePath ? ` - Env: ${formatPath(dotEnvFilePath)}` : ''}`,\n {\n isVerbose: true,\n }\n );\n } else {\n appLogger(\n `Multiple configuration files found, using ${formatPath(relativeOutputPath)}.`,\n {\n isVerbose: true,\n }\n );\n }\n }\n\n if (customConfiguration) {\n const validation = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!validation.success) {\n const errorMessages = validation.error.issues\n .map((error) => {\n const path = colorizePath(` - ${error.path.join('.')}:`);\n const message = colorize(error.message, ANSIColors.GREY_DARK);\n return `${path} ${message}`;\n })\n .join('\\n');\n const errorMessage = `${x} Invalid configuration:\\n${errorMessages}`;\n\n appLogger(errorMessage);\n }\n\n if (customConfiguration.build?.importMode) {\n appLogger(\n `${colorize('build.importMode', ANSIColors.BLUE)} is deprecated, use ${colorize('dictionary.importMode', ANSIColors.BLUE)} instead`\n );\n }\n if (customConfiguration.compiler?.transformPattern) {\n appLogger(\n `${colorize('compiler.transformPattern', ANSIColors.BLUE)} is deprecated, use ${colorize('build.traversePattern', ANSIColors.BLUE)} instead`\n );\n }\n if (customConfiguration.compiler?.excludePattern) {\n appLogger(\n `${colorize('compiler.excludePattern', ANSIColors.BLUE)} is deprecated, use ${colorize('build.traversePattern', ANSIColors.BLUE)} instead`\n );\n }\n }\n },\n {\n cacheTimeoutMs: 1000 * 60, // 1 minute\n }\n );\n};\n"],"mappings":";;;;;;;;;AAgBA,MAAa,oBAAoB,YAAsC;CACrE,MAAM,EACJ,eACA,qBACA,wBACA,0BACE,4BAA4B,QAAQ;CACxC,MAAM,YAAY,aAAa,cAAc;AAE7C,SACE,KACE,cAAc,OAAO,SACrB,aACA,SACA,+BACD,QACK;AACJ,MAAI,2BAA2B,EAC7B,WACE,8DACA,EACE,WAAW,MACZ,CACF;OACI;GACL,MAAM,UAAU,cAAc,OAAO;GACrC,MAAM,qBAAqB,SAAS,SAAS,sBAAuB;AAEpE,OAAI,2BAA2B,GAAG;IAChC,MAAM,iBAAiB,eAAe,SAAS,KAAK,SAAS,QAAQ;AAErE,cACE,wBAAwB,WAAW,mBAAmB,GAAG,iBAAiB,WAAW,WAAW,eAAe,KAAK,MACpH,EACE,WAAW,MACZ,CACF;SAED,WACE,6CAA6C,WAAW,mBAAmB,CAAC,IAC5E,EACE,WAAW,MACZ,CACF;;AAIL,MAAI,qBAAqB;GACvB,MAAM,aAAa,qBAAqB,UAAU,oBAAoB;AAEtE,OAAI,CAAC,WAAW,QAUd,WAAU,GAFc,EAAE,2BAPJ,WAAW,MAAM,OACpC,KAAK,UAAU;AAGd,WAAO,GAFM,aAAa,MAAM,MAAM,KAAK,KAAK,IAAI,CAAC,GAEvC,CAAC,GADC,SAAS,MAAM,SAAS,WAAW,UAC1B;KACzB,CACD,KAAK,KAC0D,GAE3C;AAGzB,OAAI,oBAAoB,OAAO,WAC7B,WACE,GAAG,SAAS,oBAAoB,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UAC3H;AAEH,OAAI,oBAAoB,UAAU,iBAChC,WACE,GAAG,SAAS,6BAA6B,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UACpI;AAEH,OAAI,oBAAoB,UAAU,eAChC,WACE,GAAG,SAAS,2BAA2B,WAAW,KAAK,CAAC,sBAAsB,SAAS,yBAAyB,WAAW,KAAK,CAAC,UAClI;;IAIP,EACE,gBAAgB,MAAO,IACxB,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"prepareIntlayer.mjs","names":[],"sources":["../../src/prepareIntlayer.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport packageJson from '@intlayer/config/package.json' with { type: 'json' };\nimport { cacheDisk } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { buildDictionary } from './buildIntlayerDictionary/buildIntlayerDictionary';\nimport { writeRemoteDictionary } from './buildIntlayerDictionary/writeRemoteDictionary';\nimport { cleanOutputDir } from './cleanOutputDir';\nimport { createDictionaryEntryPoint } from './createDictionaryEntryPoint/createDictionaryEntryPoint';\nimport { createModuleAugmentation, createTypes } from './createType/index';\nimport { listDictionariesWithStats } from './listDictionariesPath';\nimport { loadDictionaries } from './loadDictionaries/loadDictionaries';\nimport { runOnce } from './utils/runOnce';\nimport {\n isCachedConfigurationUpToDate,\n writeConfiguration,\n} from './writeConfiguration';\n\ntype PrepareIntlayerOptions = {\n clean?: boolean;\n env?: 'prod' | 'dev';\n format?: ('cjs' | 'esm')[];\n forceRun?: boolean;\n cacheTimeoutMs?: number;\n onIsCached?: () => void | Promise<void>;\n};\n\nconst DEFAULT_PREPARE_INTLAYER_OPTIONS = {\n clean: false,\n env: 'dev',\n format: ['cjs', 'esm'],\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n} satisfies PrepareIntlayerOptions;\n\nexport const prepareIntlayer = async (\n configuration: IntlayerConfig,\n options?: PrepareIntlayerOptions\n) => {\n const appLogger = getAppLogger(configuration);\n\n const sentinelPath = join(\n configuration.system.cacheDir,\n 'intlayer-prepared.lock'\n );\n // Clean output dir if the intlayer version has changed\n const versionCache = cacheDisk(configuration, ['intlayer-version']);\n const intlayerCacheVersion = await versionCache.get();\n const isCorrectVersion = Boolean(\n intlayerCacheVersion && intlayerCacheVersion === packageJson.version\n );\n\n const isConfigSimilar = await isCachedConfigurationUpToDate(configuration);\n\n // Check if any dictionary has been changed to force a new rebuild\n const dictionariesWithStats = await listDictionariesWithStats(configuration);\n let isDictionaryChanged = false;\n try {\n // Try catch as sentinel file may not exist yet\n const sentinelStats = await stat(sentinelPath);\n isDictionaryChanged = dictionariesWithStats.some(\n (dictionary) =>\n dictionary.stats.mtime.getTime() > sentinelStats.mtime.getTime()\n );\n } catch {}\n\n const resolvedPlugins = await Promise.all(configuration.plugins ?? []);\n const hasPluginLoadDictionaries = resolvedPlugins.some((plugin) =>\n Boolean(plugin.loadDictionaries)\n ); // Disable cache if any plugin because it can have custom behavior\n\n const { clean, format, forceRun, onIsCached, cacheTimeoutMs, env } = {\n ...DEFAULT_PREPARE_INTLAYER_OPTIONS,\n forceRun:\n !isCorrectVersion ||\n !isConfigSimilar ||\n isDictionaryChanged ||\n hasPluginLoadDictionaries,\n ...(options ?? {}),\n };\n\n // Skip preparation if it has already been done recently\n await runOnce(\n sentinelPath,\n async () => {\n // comment because of issue with next and webpack\n // await checkVersionsConsistency(configuration);\n\n if (clean || !isCorrectVersion) {\n await cleanOutputDir(configuration);\n }\n\n await versionCache.set(packageJson.version);\n\n const preparationStartMs = Date.now();\n\n appLogger([\n 'Preparing Intlayer',\n colorize(`(v${packageJson.version})`, ANSIColors.GREY_DARK),\n ]);\n\n await writeConfiguration(configuration);\n\n const configurationWrittenTime = Date.now();\n\n appLogger(\n [\n 'Configuration written',\n colorize(\n `(${configurationWrittenTime - preparationStartMs}ms)`,\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n const contentDeclarationPaths = dictionariesWithStats.map(\n (dictionary) => dictionary.path\n );\n\n const dictionaries = await loadDictionaries(\n contentDeclarationPaths,\n configuration\n );\n\n const dictionariesLoadedTime = Date.now();\n\n appLogger(\n [\n 'Content loaded',\n colorize(\n [\n dictionaries.remoteDictionaries.length +\n dictionaries.pluginDictionaries.length >\n 0\n ? [\n `(Total: ${dictionariesLoadedTime - configurationWrittenTime}ms`,\n dictionaries.localDictionaries.length > 0\n ? ` - Local: ${dictionaries.time.localDictionaries}ms`\n : '',\n dictionaries.remoteDictionaries.length > 0\n ? ` - Remote: ${dictionaries.time.remoteDictionaries}ms`\n : '',\n dictionaries.pluginDictionaries.length > 0\n ? ` - Plugin: ${dictionaries.time.pluginDictionaries}ms`\n : '',\n `)`,\n ].join('')\n : `(${dictionariesLoadedTime - configurationWrittenTime}ms)`,\n ].join(''),\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n // Build local dictionaries\n const dictionariesOutput = await buildDictionary(\n [\n ...dictionaries.localDictionaries,\n ...dictionaries.remoteDictionaries,\n ...dictionaries.pluginDictionaries,\n ],\n configuration,\n { formats: format, importOtherDictionaries: false, env }\n );\n\n // Write remote dictionaries\n // Used as cache for next fetch\n await writeRemoteDictionary(\n dictionaries.remoteDictionaries,\n configuration\n );\n\n const dictionariesToBuild = Object.values(\n dictionariesOutput?.mergedDictionaries ?? {}\n ).map((dictionary) => dictionary.dictionary);\n\n await createTypes(dictionariesToBuild, configuration);\n\n await createDictionaryEntryPoint(configuration);\n\n const dictionariesBuiltTime = Date.now();\n\n appLogger([\n 'Dictionaries built',\n colorize(\n `(${dictionariesBuiltTime - preparationStartMs}ms)`,\n ANSIColors.GREY_DARK\n ),\n ]);\n\n await createModuleAugmentation(configuration);\n\n const moduleAugmentationBuiltTime = Date.now();\n\n appLogger(\n [\n 'Module augmentation built',\n colorize(\n `(${moduleAugmentationBuiltTime - dictionariesBuiltTime}ms)`,\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n // Plugin transformation\n // Allow plugins to post-process the final build output (e.g., write back ICU JSON)\n for await (const plugin of configuration.plugins ?? []) {\n const { unmergedDictionaries, mergedDictionaries } = dictionariesOutput;\n\n await plugin.afterBuild?.({\n dictionaries: {\n unmergedDictionaries,\n mergedDictionaries,\n },\n configuration,\n });\n }\n\n const preparationElapsedMs = Date.now() - preparationStartMs;\n appLogger(\n [`Done`, colorize(`${preparationElapsedMs}ms`, ANSIColors.GREEN)],\n {\n level: 'info',\n isVerbose: true,\n }\n );\n },\n {\n forceRun,\n onIsCached,\n cacheTimeoutMs,\n }\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"prepareIntlayer.mjs","names":[],"sources":["../../src/prepareIntlayer.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport packageJson from '@intlayer/config/package.json' with { type: 'json' };\nimport { cacheDisk } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { buildDictionary } from './buildIntlayerDictionary/buildIntlayerDictionary';\nimport { writeRemoteDictionary } from './buildIntlayerDictionary/writeRemoteDictionary';\nimport { cleanOutputDir } from './cleanOutputDir';\nimport { createDictionaryEntryPoint } from './createDictionaryEntryPoint/createDictionaryEntryPoint';\nimport { createModuleAugmentation, createTypes } from './createType/index';\nimport { listDictionariesWithStats } from './listDictionariesPath';\nimport { loadDictionaries } from './loadDictionaries/loadDictionaries';\nimport { runOnce } from './utils/runOnce';\nimport {\n isCachedConfigurationUpToDate,\n writeConfiguration,\n} from './writeConfiguration';\n\ntype PrepareIntlayerOptions = {\n clean?: boolean;\n env?: 'prod' | 'dev';\n format?: ('cjs' | 'esm')[];\n forceRun?: boolean;\n cacheTimeoutMs?: number;\n onIsCached?: () => void | Promise<void>;\n};\n\nconst DEFAULT_PREPARE_INTLAYER_OPTIONS = {\n clean: false,\n env: 'dev',\n format: ['cjs', 'esm'],\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n} satisfies PrepareIntlayerOptions;\n\nexport const prepareIntlayer = async (\n configuration: IntlayerConfig,\n options?: PrepareIntlayerOptions\n) => {\n const appLogger = getAppLogger(configuration);\n\n const sentinelPath = join(\n configuration.system.cacheDir,\n 'intlayer-prepared.lock'\n );\n // Clean output dir if the intlayer version has changed\n const versionCache = cacheDisk(configuration, ['intlayer-version']);\n const intlayerCacheVersion = await versionCache.get();\n const isCorrectVersion = Boolean(\n intlayerCacheVersion && intlayerCacheVersion === packageJson.version\n );\n\n const isConfigSimilar = await isCachedConfigurationUpToDate(configuration);\n\n // Check if any dictionary has been changed to force a new rebuild\n const dictionariesWithStats = await listDictionariesWithStats(configuration);\n let isDictionaryChanged = false;\n try {\n // Try catch as sentinel file may not exist yet\n const sentinelStats = await stat(sentinelPath);\n isDictionaryChanged = dictionariesWithStats.some(\n (dictionary) =>\n dictionary.stats.mtime.getTime() > sentinelStats.mtime.getTime()\n );\n } catch {}\n\n const resolvedPlugins = await Promise.all(configuration.plugins ?? []);\n const hasPluginLoadDictionaries = resolvedPlugins.some((plugin) =>\n Boolean(plugin.loadDictionaries)\n ); // Disable cache if any plugin because it can have custom behavior\n\n const { clean, format, forceRun, onIsCached, cacheTimeoutMs, env } = {\n ...DEFAULT_PREPARE_INTLAYER_OPTIONS,\n forceRun:\n !isCorrectVersion ||\n !isConfigSimilar ||\n isDictionaryChanged ||\n hasPluginLoadDictionaries,\n ...(options ?? {}),\n };\n\n // Skip preparation if it has already been done recently\n await runOnce(\n sentinelPath,\n async () => {\n // comment because of issue with next and webpack\n // await checkVersionsConsistency(configuration);\n\n if (clean || !isCorrectVersion) {\n await cleanOutputDir(configuration);\n }\n\n await versionCache.set(packageJson.version);\n\n const preparationStartMs = Date.now();\n\n appLogger([\n 'Preparing Intlayer',\n colorize(`(v${packageJson.version})`, ANSIColors.GREY_DARK),\n ]);\n\n await writeConfiguration(configuration);\n\n const configurationWrittenTime = Date.now();\n\n appLogger(\n [\n 'Configuration written',\n colorize(\n `(${configurationWrittenTime - preparationStartMs}ms)`,\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n const contentDeclarationPaths = dictionariesWithStats.map(\n (dictionary) => dictionary.path\n );\n\n const dictionaries = await loadDictionaries(\n contentDeclarationPaths,\n configuration\n );\n\n const dictionariesLoadedTime = Date.now();\n\n appLogger(\n [\n 'Content loaded',\n colorize(\n [\n dictionaries.remoteDictionaries.length +\n dictionaries.pluginDictionaries.length >\n 0\n ? [\n `(Total: ${dictionariesLoadedTime - configurationWrittenTime}ms`,\n dictionaries.localDictionaries.length > 0\n ? ` - Local: ${dictionaries.time.localDictionaries}ms`\n : '',\n dictionaries.remoteDictionaries.length > 0\n ? ` - Remote: ${dictionaries.time.remoteDictionaries}ms`\n : '',\n dictionaries.pluginDictionaries.length > 0\n ? ` - Plugin: ${dictionaries.time.pluginDictionaries}ms`\n : '',\n `)`,\n ].join('')\n : `(${dictionariesLoadedTime - configurationWrittenTime}ms)`,\n ].join(''),\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n // Build local dictionaries\n const dictionariesOutput = await buildDictionary(\n [\n ...dictionaries.localDictionaries,\n ...dictionaries.remoteDictionaries,\n ...dictionaries.pluginDictionaries,\n ],\n configuration,\n { formats: format, importOtherDictionaries: false, env }\n );\n\n // Write remote dictionaries\n // Used as cache for next fetch\n await writeRemoteDictionary(\n dictionaries.remoteDictionaries,\n configuration\n );\n\n const dictionariesToBuild = Object.values(\n dictionariesOutput?.mergedDictionaries ?? {}\n ).map((dictionary) => dictionary.dictionary);\n\n await createTypes(dictionariesToBuild, configuration);\n\n await createDictionaryEntryPoint(configuration);\n\n const dictionariesBuiltTime = Date.now();\n\n appLogger([\n 'Dictionaries built',\n colorize(\n `(${dictionariesBuiltTime - preparationStartMs}ms)`,\n ANSIColors.GREY_DARK\n ),\n ]);\n\n await createModuleAugmentation(configuration);\n\n const moduleAugmentationBuiltTime = Date.now();\n\n appLogger(\n [\n 'Module augmentation built',\n colorize(\n `(${moduleAugmentationBuiltTime - dictionariesBuiltTime}ms)`,\n ANSIColors.GREY_DARK\n ),\n ],\n {\n isVerbose: true,\n }\n );\n\n // Plugin transformation\n // Allow plugins to post-process the final build output (e.g., write back ICU JSON)\n for await (const plugin of configuration.plugins ?? []) {\n const { unmergedDictionaries, mergedDictionaries } = dictionariesOutput;\n\n await plugin.afterBuild?.({\n dictionaries: {\n unmergedDictionaries,\n mergedDictionaries,\n },\n configuration,\n });\n }\n\n const preparationElapsedMs = Date.now() - preparationStartMs;\n appLogger(\n [`Done`, colorize(`${preparationElapsedMs}ms`, ANSIColors.GREEN)],\n {\n level: 'info',\n isVerbose: true,\n }\n );\n },\n {\n forceRun,\n onIsCached,\n cacheTimeoutMs,\n }\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reduceDictionaryContent.mjs","names":[],"sources":["../../../src/reduceDictionaryContent/reduceDictionaryContent.ts"],"sourcesContent":["import { getMaskContent } from '@intlayer/core/plugins';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { applyMask } from './applyMask';\n\nexport const reduceDictionaryContent = (\n fullDictionary: Dictionary,\n partialDictionary: Dictionary\n) => {\n const mask = getMaskContent(partialDictionary);\n const result = applyMask(fullDictionary, mask);\n\n return result;\n};\n"],"mappings":";;;;AAIA,MAAa,2BACX,gBACA,sBACG;AAIH,QAFe,UAAU,gBADZ,eAAe,kBAAkB,CACA"}
1
+ {"version":3,"file":"reduceDictionaryContent.mjs","names":[],"sources":["../../../src/reduceDictionaryContent/reduceDictionaryContent.ts"],"sourcesContent":["import { getMaskContent } from '@intlayer/core/plugins';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { applyMask } from './applyMask';\n\nexport const reduceDictionaryContent = (\n fullDictionary: Dictionary,\n partialDictionary: Dictionary\n) => {\n const mask = getMaskContent(partialDictionary);\n const result = applyMask(fullDictionary, mask);\n\n return result;\n};\n"],"mappings":";;;;AAIA,MAAa,2BACX,gBACA,sBACG;AAIH,QAFe,UAAU,gBADZ,eAAe,kBACiB,CAEhC"}
@@ -1 +1 @@
1
- {"version":3,"file":"autoDecorateContent.mjs","names":[],"sources":["../../../src/utils/autoDecorateContent.ts"],"sourcesContent":["import { getMarkdownMetadata } from '@intlayer/core/markdown';\nimport {\n getInsertionValues,\n html,\n insert,\n md,\n} from '@intlayer/core/transpiler';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/**\n * Check if a string is a markdown string\n */\nconst isMarkdown = (str: string): boolean => {\n // Check for common markdown indicators\n const patterns = [\n /^\\s*---/m, // Front Matter\n /^\\s*#+\\s/m, // Headers: # Title\n /^\\s*[-*+]\\s/m, // Unordered lists: - Item or * Item\n /^\\s*\\d+\\.\\s/m, // Ordered lists: 1. Item\n /^\\s*>\\s/m, // Blockquotes: > Quote\n /\\[.+\\]\\(.+\\)/, // Links: [text](url)\n /!\\[.+\\]\\(.+\\)/, // Images: ![alt](url)\n /`{1,3}.+`{1,3}/, // Code blocks or inline code: `code` or ```code```\n /\\*\\*.+\\*\\*/, // Bold: **text**\n /__.+__/, // Bold: __text__\n /<(https?:\\/\\/[^\\s>]+)>/, // Autolinks: <http://...>\n ];\n\n return patterns.some((pattern) => pattern.test(str));\n};\n\n/**\n * Check if a string is an insertion string\n */\nconst isInsertion = (str: string): boolean =>\n getInsertionValues(str).length > 0;\n\n/**\n * Check if a string is an HTML/JSX string\n * Matches:\n * - <Tag>\n * - </Tag>\n * - <Tag />\n * - <Tag attribute=\"value\">\n * - <Component.SubComponent>\n */\nconst isHTML = (str: string): boolean => {\n // 1. Matches opening or self-closing tags: <Tag ... > or <Tag ... />\n // - Must start with < followed by a letter (to avoid math comparisons like a < b)\n // - Allows alphanumeric, hyphens, and dots (for Namespaced components) in tag name\n // - Allows attributes until the closing >\n const openTagRegex = /<[a-zA-Z][a-zA-Z0-9\\-.]*(\\s+[^>]*)?\\/?>/;\n\n // 2. Matches closing tags: </Tag>\n const closeTagRegex = /<\\/[a-zA-Z][a-zA-Z0-9\\-.]*\\s*>/;\n\n return openTagRegex.test(str) || closeTagRegex.test(str);\n};\n\nconst leafNodeTypes: string[] = [\n NodeTypes.HTML,\n NodeTypes.MARKDOWN,\n NodeTypes.INSERTION,\n NodeTypes.FILE,\n NodeTypes.REACT_NODE,\n NodeTypes.TEXT,\n NodeTypes.NUMBER,\n NodeTypes.BOOLEAN,\n NodeTypes.NULL,\n NodeTypes.UNKNOWN,\n];\n\ntype AutoTransformationOptions = {\n markdown?: boolean;\n html?: boolean;\n insertion?: boolean;\n};\n\n/**\n * Automatically decorate content strings with md() or insert() if they match\n */\nexport const autoDecorateContent = (\n content: any,\n options: boolean | AutoTransformationOptions = true\n): any => {\n if (options === false) {\n return content;\n }\n\n const {\n markdown = true,\n html: htmlOption = true,\n insertion = true,\n } = typeof options === 'object' ? options : {};\n\n if (typeof content === 'string') {\n if (markdown && isMarkdown(content)) {\n const markdownNode = md(content);\n\n return {\n ...markdownNode,\n metadata: getMarkdownMetadata(content),\n };\n }\n\n if (htmlOption && isHTML(content)) {\n return html(content);\n }\n\n if (insertion && isInsertion(content)) {\n return insert(content);\n }\n\n return content;\n }\n\n if (Array.isArray(content)) {\n return content.map((item) => autoDecorateContent(item, options));\n }\n\n if (content && typeof content === 'object') {\n // If it's already a decorated node (has nodeType)\n if ('nodeType' in content) {\n const nodeType = content.nodeType;\n\n // If it's a leaf node type, don't re-decorate its content\n if (leafNodeTypes.includes(nodeType)) {\n return content;\n }\n\n // If it's a container node type (like translation, enumeration, etc.), recurse into its content field\n if (nodeType in content) {\n return {\n ...content,\n [nodeType]: autoDecorateContent(content[nodeType], options),\n };\n }\n\n return content;\n }\n\n // Plain object, recurse into all keys\n const result: Record<string, any> = {};\n for (const key of Object.keys(content)) {\n result[key] = autoDecorateContent(content[key], options);\n }\n return result;\n }\n\n return content;\n};\n"],"mappings":";;;;;;;;AAYA,MAAM,cAAc,QAAyB;AAgB3C,QAdiB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAEe,MAAM,YAAY,QAAQ,KAAK,IAAI,CAAC;;;;;AAMtD,MAAM,eAAe,QACnB,mBAAmB,IAAI,CAAC,SAAS;;;;;;;;;;AAWnC,MAAM,UAAU,QAAyB;AAUvC,QALqB,0CAKD,KAAK,IAAI,IAFP,iCAEyB,KAAK,IAAI;;AAG1D,MAAM,gBAA0B;CAC9B,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACX;;;;AAWD,MAAa,uBACX,SACA,UAA+C,SACvC;AACR,KAAI,YAAY,MACd,QAAO;CAGT,MAAM,EACJ,WAAW,MACX,MAAM,aAAa,MACnB,YAAY,SACV,OAAO,YAAY,WAAW,UAAU,EAAE;AAE9C,KAAI,OAAO,YAAY,UAAU;AAC/B,MAAI,YAAY,WAAW,QAAQ,CAGjC,QAAO;GACL,GAHmB,GAAG,QAAQ;GAI9B,UAAU,oBAAoB,QAAQ;GACvC;AAGH,MAAI,cAAc,OAAO,QAAQ,CAC/B,QAAO,KAAK,QAAQ;AAGtB,MAAI,aAAa,YAAY,QAAQ,CACnC,QAAO,OAAO,QAAQ;AAGxB,SAAO;;AAGT,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO,QAAQ,KAAK,SAAS,oBAAoB,MAAM,QAAQ,CAAC;AAGlE,KAAI,WAAW,OAAO,YAAY,UAAU;AAE1C,MAAI,cAAc,SAAS;GACzB,MAAM,WAAW,QAAQ;AAGzB,OAAI,cAAc,SAAS,SAAS,CAClC,QAAO;AAIT,OAAI,YAAY,QACd,QAAO;IACL,GAAG;KACF,WAAW,oBAAoB,QAAQ,WAAW,QAAQ;IAC5D;AAGH,UAAO;;EAIT,MAAM,SAA8B,EAAE;AACtC,OAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,CACpC,QAAO,OAAO,oBAAoB,QAAQ,MAAM,QAAQ;AAE1D,SAAO;;AAGT,QAAO"}
1
+ {"version":3,"file":"autoDecorateContent.mjs","names":[],"sources":["../../../src/utils/autoDecorateContent.ts"],"sourcesContent":["import { getMarkdownMetadata } from '@intlayer/core/markdown';\nimport {\n getInsertionValues,\n html,\n insert,\n md,\n} from '@intlayer/core/transpiler';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n/**\n * Check if a string is a markdown string\n */\nconst isMarkdown = (str: string): boolean => {\n // Check for common markdown indicators\n const patterns = [\n /^\\s*---/m, // Front Matter\n /^\\s*#+\\s/m, // Headers: # Title\n /^\\s*[-*+]\\s/m, // Unordered lists: - Item or * Item\n /^\\s*\\d+\\.\\s/m, // Ordered lists: 1. Item\n /^\\s*>\\s/m, // Blockquotes: > Quote\n /\\[.+\\]\\(.+\\)/, // Links: [text](url)\n /!\\[.+\\]\\(.+\\)/, // Images: ![alt](url)\n /`{1,3}.+`{1,3}/, // Code blocks or inline code: `code` or ```code```\n /\\*\\*.+\\*\\*/, // Bold: **text**\n /__.+__/, // Bold: __text__\n /<(https?:\\/\\/[^\\s>]+)>/, // Autolinks: <http://...>\n ];\n\n return patterns.some((pattern) => pattern.test(str));\n};\n\n/**\n * Check if a string is an insertion string\n */\nconst isInsertion = (str: string): boolean =>\n getInsertionValues(str).length > 0;\n\n/**\n * Check if a string is an HTML/JSX string\n * Matches:\n * - <Tag>\n * - </Tag>\n * - <Tag />\n * - <Tag attribute=\"value\">\n * - <Component.SubComponent>\n */\nconst isHTML = (str: string): boolean => {\n // 1. Matches opening or self-closing tags: <Tag ... > or <Tag ... />\n // - Must start with < followed by a letter (to avoid math comparisons like a < b)\n // - Allows alphanumeric, hyphens, and dots (for Namespaced components) in tag name\n // - Allows attributes until the closing >\n const openTagRegex = /<[a-zA-Z][a-zA-Z0-9\\-.]*(\\s+[^>]*)?\\/?>/;\n\n // 2. Matches closing tags: </Tag>\n const closeTagRegex = /<\\/[a-zA-Z][a-zA-Z0-9\\-.]*\\s*>/;\n\n return openTagRegex.test(str) || closeTagRegex.test(str);\n};\n\nconst leafNodeTypes: string[] = [\n NodeTypes.HTML,\n NodeTypes.MARKDOWN,\n NodeTypes.INSERTION,\n NodeTypes.FILE,\n NodeTypes.REACT_NODE,\n NodeTypes.TEXT,\n NodeTypes.NUMBER,\n NodeTypes.BOOLEAN,\n NodeTypes.NULL,\n NodeTypes.UNKNOWN,\n];\n\ntype AutoTransformationOptions = {\n markdown?: boolean;\n html?: boolean;\n insertion?: boolean;\n};\n\n/**\n * Automatically decorate content strings with md() or insert() if they match\n */\nexport const autoDecorateContent = (\n content: any,\n options: boolean | AutoTransformationOptions = true\n): any => {\n if (options === false) {\n return content;\n }\n\n const {\n markdown = true,\n html: htmlOption = true,\n insertion = true,\n } = typeof options === 'object' ? options : {};\n\n if (typeof content === 'string') {\n if (markdown && isMarkdown(content)) {\n const markdownNode = md(content);\n\n return {\n ...markdownNode,\n metadata: getMarkdownMetadata(content),\n };\n }\n\n if (htmlOption && isHTML(content)) {\n return html(content);\n }\n\n if (insertion && isInsertion(content)) {\n return insert(content);\n }\n\n return content;\n }\n\n if (Array.isArray(content)) {\n return content.map((item) => autoDecorateContent(item, options));\n }\n\n if (content && typeof content === 'object') {\n // If it's already a decorated node (has nodeType)\n if ('nodeType' in content) {\n const nodeType = content.nodeType;\n\n // If it's a leaf node type, don't re-decorate its content\n if (leafNodeTypes.includes(nodeType)) {\n return content;\n }\n\n // If it's a container node type (like translation, enumeration, etc.), recurse into its content field\n if (nodeType in content) {\n return {\n ...content,\n [nodeType]: autoDecorateContent(content[nodeType], options),\n };\n }\n\n return content;\n }\n\n // Plain object, recurse into all keys\n const result: Record<string, any> = {};\n for (const key of Object.keys(content)) {\n result[key] = autoDecorateContent(content[key], options);\n }\n return result;\n }\n\n return content;\n};\n"],"mappings":";;;;;;;;AAYA,MAAM,cAAc,QAAyB;AAgB3C,QAAO;EAbL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGa,CAAC,MAAM,YAAY,QAAQ,KAAK,IAAI,CAAC;;;;;AAMtD,MAAM,eAAe,QACnB,mBAAmB,IAAI,CAAC,SAAS;;;;;;;;;;AAWnC,MAAM,UAAU,QAAyB;AAUvC,QAAO,0CAAa,KAAK,IAAI,IAAI,iCAAc,KAAK,IAAI;;AAG1D,MAAM,gBAA0B;CAC9B,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACX;;;;AAWD,MAAa,uBACX,SACA,UAA+C,SACvC;AACR,KAAI,YAAY,MACd,QAAO;CAGT,MAAM,EACJ,WAAW,MACX,MAAM,aAAa,MACnB,YAAY,SACV,OAAO,YAAY,WAAW,UAAU,EAAE;AAE9C,KAAI,OAAO,YAAY,UAAU;AAC/B,MAAI,YAAY,WAAW,QAAQ,CAGjC,QAAO;GACL,GAHmB,GAAG,QAGP;GACf,UAAU,oBAAoB,QAAQ;GACvC;AAGH,MAAI,cAAc,OAAO,QAAQ,CAC/B,QAAO,KAAK,QAAQ;AAGtB,MAAI,aAAa,YAAY,QAAQ,CACnC,QAAO,OAAO,QAAQ;AAGxB,SAAO;;AAGT,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO,QAAQ,KAAK,SAAS,oBAAoB,MAAM,QAAQ,CAAC;AAGlE,KAAI,WAAW,OAAO,YAAY,UAAU;AAE1C,MAAI,cAAc,SAAS;GACzB,MAAM,WAAW,QAAQ;AAGzB,OAAI,cAAc,SAAS,SAAS,CAClC,QAAO;AAIT,OAAI,YAAY,QACd,QAAO;IACL,GAAG;KACF,WAAW,oBAAoB,QAAQ,WAAW,QAAQ;IAC5D;AAGH,UAAO;;EAIT,MAAM,SAA8B,EAAE;AACtC,OAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,CACpC,QAAO,OAAO,oBAAoB,QAAQ,MAAM,QAAQ;AAE1D,SAAO;;AAGT,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildComponentFilesList.mjs","names":[],"sources":["../../../src/utils/buildComponentFilesList.ts"],"sourcesContent":["import { isAbsolute, normalize, relative, resolve } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * Normalizes a pattern value to an array\n */\nconst normalizeToArray = <T>(value: T | T[]): T[] =>\n Array.isArray(value) ? value : [value];\n\n/**\n * Remove directories that are subdirectories of others in the list so files\n * are never scanned twice.\n * Example: ['/root', '/root/src'] → ['/root']\n */\nconst getDistinctRootDirs = (dirs: string[]): string[] => {\n const uniqueDirs = Array.from(new Set(dirs.map((dir) => resolve(dir))));\n uniqueDirs.sort((a, b) => a.length - b.length);\n\n return uniqueDirs.reduce((acc: string[], dir) => {\n const isNested = acc.some((parent) => {\n const rel = relative(parent, dir);\n\n return !rel.startsWith('..') && !isAbsolute(rel) && rel !== '';\n });\n if (!isNested) acc.push(dir);\n\n return acc;\n }, []);\n};\n\n/**\n * Builds a deduplicated list of absolute file paths matching the given patterns.\n *\n * Handles multiple root directories (deduplicates overlapping roots), exclude\n * patterns, negation patterns embedded in `transformPattern`, and optional\n * dot-file inclusion.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList({\n * transformPattern: 'src/**\\/*.{ts,tsx}',\n * excludePattern: ['**\\/node_modules\\/**'],\n * baseDir: '/path/to/project',\n * });\n *\n * @example\n * // Multiple roots (e.g. baseDir + codeDir), dot files included\n * const files = buildComponentFilesList(config, ['**\\/node_modules\\/**']);\n */\nexport const buildComponentFilesList = (\n config: IntlayerConfig,\n excludePattern?: string[]\n): string[] => {\n const transformPattern = config.build.traversePattern;\n const compilerTransformPattern = config.compiler.transformPattern;\n const contentDeclarationPattern = config.content.fileExtensions.map(\n (ext) => `/**/*${ext}`\n );\n\n const patterns = [\n ...transformPattern,\n ...normalizeToArray(compilerTransformPattern),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .filter((pattern) => !pattern.startsWith('!'))\n .map((pattern) => normalize(pattern)); // Ensure it works with Windows\n\n const excludePatterns = [\n ...(excludePattern ?? []),\n ...contentDeclarationPattern,\n // Treat negation entries in transformPattern as additional excludes\n ...transformPattern\n .filter(\n (pattern) => typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1)),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .map((pattern) => normalize(pattern)); // Ensure it works with Windows\n\n const roots = getDistinctRootDirs([\n config.system.baseDir,\n ...config.content.codeDir,\n ]);\n\n const fileList = roots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: excludePatterns,\n absolute: true,\n dot: true, // include dot files like .next / .intlayer\n })\n );\n\n return Array.from(new Set(fileList));\n};\n"],"mappings":";;;;;;;AAOA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;;;;;;AAOxC,MAAM,uBAAuB,SAA6B;CACxD,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC;AACvE,YAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;AAE9C,QAAO,WAAW,QAAQ,KAAe,QAAQ;AAM/C,MAAI,CALa,IAAI,MAAM,WAAW;GACpC,MAAM,MAAM,SAAS,QAAQ,IAAI;AAEjC,UAAO,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,WAAW,IAAI,IAAI,QAAQ;IAC5D,CACa,KAAI,KAAK,IAAI;AAE5B,SAAO;IACN,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBR,MAAa,2BACX,QACA,mBACa;CACb,MAAM,mBAAmB,OAAO,MAAM;CACtC,MAAM,2BAA2B,OAAO,SAAS;CACjD,MAAM,4BAA4B,OAAO,QAAQ,eAAe,KAC7D,QAAQ,QAAQ,MAClB;CAED,MAAM,WAAW,CACf,GAAG,kBACH,GAAG,iBAAiB,yBAAyB,CAC9C,CACE,QAAQ,YAAY,OAAO,YAAY,SAAS,CAChD,QAAQ,YAAY,CAAC,QAAQ,WAAW,IAAI,CAAC,CAC7C,KAAK,YAAY,UAAU,QAAQ,CAAC;CAEvC,MAAM,kBAAkB;EACtB,GAAI,kBAAkB,EAAE;EACxB,GAAG;EAEH,GAAG,iBACA,QACE,YAAY,OAAO,YAAY,YAAY,QAAQ,WAAW,IAAI,CACpE,CACA,KAAK,YAAY,QAAQ,MAAM,EAAE,CAAC;EACtC,CACE,QAAQ,YAAY,OAAO,YAAY,SAAS,CAChD,KAAK,YAAY,UAAU,QAAQ,CAAC;CAOvC,MAAM,WALQ,oBAAoB,CAChC,OAAO,OAAO,SACd,GAAG,OAAO,QAAQ,QACnB,CAAC,CAEqB,SAAS,SAC9B,GAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV,KAAK;EACN,CAAC,CACH;AAED,QAAO,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC"}
1
+ {"version":3,"file":"buildComponentFilesList.mjs","names":[],"sources":["../../../src/utils/buildComponentFilesList.ts"],"sourcesContent":["import { isAbsolute, normalize, relative, resolve } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * Normalizes a pattern value to an array\n */\nconst normalizeToArray = <T>(value: T | T[]): T[] =>\n Array.isArray(value) ? value : [value];\n\n/**\n * Remove directories that are subdirectories of others in the list so files\n * are never scanned twice.\n * Example: ['/root', '/root/src'] → ['/root']\n */\nconst getDistinctRootDirs = (dirs: string[]): string[] => {\n const uniqueDirs = Array.from(new Set(dirs.map((dir) => resolve(dir))));\n uniqueDirs.sort((a, b) => a.length - b.length);\n\n return uniqueDirs.reduce((acc: string[], dir) => {\n const isNested = acc.some((parent) => {\n const rel = relative(parent, dir);\n\n return !rel.startsWith('..') && !isAbsolute(rel) && rel !== '';\n });\n if (!isNested) acc.push(dir);\n\n return acc;\n }, []);\n};\n\n/**\n * Builds a deduplicated list of absolute file paths matching the given patterns.\n *\n * Handles multiple root directories (deduplicates overlapping roots), exclude\n * patterns, negation patterns embedded in `transformPattern`, and optional\n * dot-file inclusion.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList({\n * transformPattern: 'src/**\\/*.{ts,tsx}',\n * excludePattern: ['**\\/node_modules\\/**'],\n * baseDir: '/path/to/project',\n * });\n *\n * @example\n * // Multiple roots (e.g. baseDir + codeDir), dot files included\n * const files = buildComponentFilesList(config, ['**\\/node_modules\\/**']);\n */\nexport const buildComponentFilesList = (\n config: IntlayerConfig,\n excludePattern?: string[]\n): string[] => {\n const transformPattern = config.build.traversePattern;\n const compilerTransformPattern = config.compiler.transformPattern;\n const contentDeclarationPattern = config.content.fileExtensions.map(\n (ext) => `/**/*${ext}`\n );\n\n const patterns = [\n ...transformPattern,\n ...normalizeToArray(compilerTransformPattern),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .filter((pattern) => !pattern.startsWith('!'))\n .map((pattern) => normalize(pattern)); // Ensure it works with Windows\n\n const excludePatterns = [\n ...(excludePattern ?? []),\n ...contentDeclarationPattern,\n // Treat negation entries in transformPattern as additional excludes\n ...transformPattern\n .filter(\n (pattern) => typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1)),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .map((pattern) => normalize(pattern)); // Ensure it works with Windows\n\n const roots = getDistinctRootDirs([\n config.system.baseDir,\n ...config.content.codeDir,\n ]);\n\n const fileList = roots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: excludePatterns,\n absolute: true,\n dot: true, // include dot files like .next / .intlayer\n })\n );\n\n return Array.from(new Set(fileList));\n};\n"],"mappings":";;;;;;;AAOA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;;;;;;AAOxC,MAAM,uBAAuB,SAA6B;CACxD,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC;AACvE,YAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;AAE9C,QAAO,WAAW,QAAQ,KAAe,QAAQ;AAM/C,MAAI,CALa,IAAI,MAAM,WAAW;GACpC,MAAM,MAAM,SAAS,QAAQ,IAAI;AAEjC,UAAO,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,WAAW,IAAI,IAAI,QAAQ;IAEjD,CAAE,KAAI,KAAK,IAAI;AAE5B,SAAO;IACN,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBR,MAAa,2BACX,QACA,mBACa;CACb,MAAM,mBAAmB,OAAO,MAAM;CACtC,MAAM,2BAA2B,OAAO,SAAS;CACjD,MAAM,4BAA4B,OAAO,QAAQ,eAAe,KAC7D,QAAQ,QAAQ,MAClB;CAED,MAAM,WAAW,CACf,GAAG,kBACH,GAAG,iBAAiB,yBAAyB,CAC9C,CACE,QAAQ,YAAY,OAAO,YAAY,SAAS,CAChD,QAAQ,YAAY,CAAC,QAAQ,WAAW,IAAI,CAAC,CAC7C,KAAK,YAAY,UAAU,QAAQ,CAAC;CAEvC,MAAM,kBAAkB;EACtB,GAAI,kBAAkB,EAAE;EACxB,GAAG;EAEH,GAAG,iBACA,QACE,YAAY,OAAO,YAAY,YAAY,QAAQ,WAAW,IAAI,CACpE,CACA,KAAK,YAAY,QAAQ,MAAM,EAAE,CAAC;EACtC,CACE,QAAQ,YAAY,OAAO,YAAY,SAAS,CAChD,KAAK,YAAY,UAAU,QAAQ,CAAC;CAOvC,MAAM,WALQ,oBAAoB,CAChC,OAAO,OAAO,SACd,GAAG,OAAO,QAAQ,QACnB,CAEqB,CAAC,SAAS,SAC9B,GAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV,KAAK;EACN,CAAC,CACH;AAED,QAAO,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildFilesList.mjs","names":[],"sources":["../../../src/utils/buildFilesList.ts"],"sourcesContent":["import { isAbsolute, normalize, relative, resolve } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * Options for building the files list\n */\nexport type BuildComponentFilesListOptions = {\n /**\n * Glob patterns to match files\n */\n transformPattern: string | string[];\n /**\n * Glob patterns to exclude files\n */\n excludePattern?: string | string[];\n /**\n * Base directory (or directories) for file resolution.\n * When multiple directories are provided, subdirectories of others are\n * automatically deduplicated so files are never scanned twice.\n */\n baseDir: string | string[];\n /**\n * Whether to include dot-prefixed files and directories (default: false)\n */\n dot?: boolean;\n};\n\n/**\n * Normalizes a pattern value to an array\n */\nconst normalizeToArray = <T>(value: T | T[]): T[] =>\n Array.isArray(value) ? value : [value];\n\n/**\n * Remove directories that are subdirectories of others in the list so files\n * are never scanned twice.\n * Example: ['/root', '/root/src'] → ['/root']\n */\nconst getDistinctRootDirs = (dirs: string[]): string[] => {\n const uniqueDirs = Array.from(new Set(dirs.map((dir) => resolve(dir))));\n uniqueDirs.sort((a, b) => a.length - b.length);\n\n return uniqueDirs.reduce((acc: string[], dir) => {\n const isNested = acc.some((parent) => {\n const rel = relative(parent, dir);\n return !rel.startsWith('..') && !isAbsolute(rel) && rel !== '';\n });\n if (!isNested) acc.push(dir);\n return acc;\n }, []);\n};\n\n/**\n * Builds a deduplicated list of absolute file paths matching the given patterns.\n *\n * Handles multiple root directories (deduplicates overlapping roots), exclude\n * patterns, negation patterns embedded in `transformPattern`, and optional\n * dot-file inclusion.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList({\n * transformPattern: 'src/**\\/*.{ts,tsx}',\n * excludePattern: ['**\\/node_modules\\/**'],\n * baseDir: '/path/to/project',\n * });\n *\n * @example\n * // Multiple roots (e.g. baseDir + codeDir), dot files included\n * const files = buildComponentFilesList({\n * transformPattern: config.build.traversePattern,\n * baseDir: [config.system.baseDir, ...config.content.codeDir],\n * dot: true,\n * });\n */\nexport const buildComponentFilesList = (\n config: BuildComponentFilesListOptions\n): string[] => {\n const {\n transformPattern,\n excludePattern = [],\n baseDir,\n dot = false,\n } = config;\n\n const patterns = normalizeToArray(transformPattern)\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && !pattern.startsWith('!')\n )\n .map(normalize); // Ensure it works with Windows\n\n const excludePatterns = [\n ...normalizeToArray(excludePattern),\n // Treat negation entries in transformPattern as additional excludes\n ...normalizeToArray(transformPattern)\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1)),\n ]\n .filter((pattern): pattern is string => typeof pattern === 'string')\n .map(normalize); // Ensure it works with Windows\n\n const roots = getDistinctRootDirs(normalizeToArray(baseDir));\n\n return Array.from(\n new Set(\n roots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: excludePatterns,\n absolute: true,\n dot,\n })\n )\n )\n );\n};\n\n/**\n * Convenience wrapper that derives all file-list options directly from an\n * `IntlayerConfig` object.\n *\n * Scans `[baseDir, ...codeDir]` using `build.traversePattern`, excludes\n * content declaration file extensions and any `compiler.excludePattern`\n * entries defined in the configuration, and includes dot files.\n */\nexport const buildComponentFilesListFromConfig = (\n intlayerConfig: IntlayerConfig\n): string[] => {\n const {\n build: { traversePattern },\n system: { baseDir },\n content: { codeDir, fileExtensions },\n compiler: { excludePattern },\n } = intlayerConfig;\n\n const excludePatterns = [\n // Exclude content declaration files (e.g. **/*.content.ts)\n ...fileExtensions.map((ext) => `**/*${ext}`),\n ...(Array.isArray(excludePattern) ? excludePattern : [excludePattern]),\n ].filter((p): p is string => typeof p === 'string');\n\n return buildComponentFilesList({\n transformPattern: traversePattern,\n excludePattern: excludePatterns,\n baseDir: [baseDir, ...codeDir],\n dot: true,\n });\n};\n"],"mappings":";;;;;;;AA+BA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;;;;;;AAOxC,MAAM,uBAAuB,SAA6B;CACxD,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC;AACvE,YAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;AAE9C,QAAO,WAAW,QAAQ,KAAe,QAAQ;AAK/C,MAAI,CAJa,IAAI,MAAM,WAAW;GACpC,MAAM,MAAM,SAAS,QAAQ,IAAI;AACjC,UAAO,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,WAAW,IAAI,IAAI,QAAQ;IAC5D,CACa,KAAI,KAAK,IAAI;AAC5B,SAAO;IACN,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BR,MAAa,2BACX,WACa;CACb,MAAM,EACJ,kBACA,iBAAiB,EAAE,EACnB,SACA,MAAM,UACJ;CAEJ,MAAM,WAAW,iBAAiB,iBAAiB,CAChD,QACE,YACC,OAAO,YAAY,YAAY,CAAC,QAAQ,WAAW,IAAI,CAC1D,CACA,IAAI,UAAU;CAEjB,MAAM,kBAAkB,CACtB,GAAG,iBAAiB,eAAe,EAEnC,GAAG,iBAAiB,iBAAiB,CAClC,QACE,YACC,OAAO,YAAY,YAAY,QAAQ,WAAW,IAAI,CACzD,CACA,KAAK,YAAY,QAAQ,MAAM,EAAE,CAAC,CACtC,CACE,QAAQ,YAA+B,OAAO,YAAY,SAAS,CACnE,IAAI,UAAU;CAEjB,MAAM,QAAQ,oBAAoB,iBAAiB,QAAQ,CAAC;AAE5D,QAAO,MAAM,KACX,IAAI,IACF,MAAM,SAAS,SACb,GAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV;EACD,CAAC,CACH,CACF,CACF;;;;;;;;;;AAWH,MAAa,qCACX,mBACa;CACb,MAAM,EACJ,OAAO,EAAE,mBACT,QAAQ,EAAE,WACV,SAAS,EAAE,SAAS,kBACpB,UAAU,EAAE,qBACV;AAQJ,QAAO,wBAAwB;EAC7B,kBAAkB;EAClB,gBARsB,CAEtB,GAAG,eAAe,KAAK,QAAQ,OAAO,MAAM,EAC5C,GAAI,MAAM,QAAQ,eAAe,GAAG,iBAAiB,CAAC,eAAe,CACtE,CAAC,QAAQ,MAAmB,OAAO,MAAM,SAAS;EAKjD,SAAS,CAAC,SAAS,GAAG,QAAQ;EAC9B,KAAK;EACN,CAAC"}
1
+ {"version":3,"file":"buildFilesList.mjs","names":[],"sources":["../../../src/utils/buildFilesList.ts"],"sourcesContent":["import { isAbsolute, normalize, relative, resolve } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\n\n/**\n * Options for building the files list\n */\nexport type BuildComponentFilesListOptions = {\n /**\n * Glob patterns to match files\n */\n transformPattern: string | string[];\n /**\n * Glob patterns to exclude files\n */\n excludePattern?: string | string[];\n /**\n * Base directory (or directories) for file resolution.\n * When multiple directories are provided, subdirectories of others are\n * automatically deduplicated so files are never scanned twice.\n */\n baseDir: string | string[];\n /**\n * Whether to include dot-prefixed files and directories (default: false)\n */\n dot?: boolean;\n};\n\n/**\n * Normalizes a pattern value to an array\n */\nconst normalizeToArray = <T>(value: T | T[]): T[] =>\n Array.isArray(value) ? value : [value];\n\n/**\n * Remove directories that are subdirectories of others in the list so files\n * are never scanned twice.\n * Example: ['/root', '/root/src'] → ['/root']\n */\nconst getDistinctRootDirs = (dirs: string[]): string[] => {\n const uniqueDirs = Array.from(new Set(dirs.map((dir) => resolve(dir))));\n uniqueDirs.sort((a, b) => a.length - b.length);\n\n return uniqueDirs.reduce((acc: string[], dir) => {\n const isNested = acc.some((parent) => {\n const rel = relative(parent, dir);\n return !rel.startsWith('..') && !isAbsolute(rel) && rel !== '';\n });\n if (!isNested) acc.push(dir);\n return acc;\n }, []);\n};\n\n/**\n * Builds a deduplicated list of absolute file paths matching the given patterns.\n *\n * Handles multiple root directories (deduplicates overlapping roots), exclude\n * patterns, negation patterns embedded in `transformPattern`, and optional\n * dot-file inclusion.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList({\n * transformPattern: 'src/**\\/*.{ts,tsx}',\n * excludePattern: ['**\\/node_modules\\/**'],\n * baseDir: '/path/to/project',\n * });\n *\n * @example\n * // Multiple roots (e.g. baseDir + codeDir), dot files included\n * const files = buildComponentFilesList({\n * transformPattern: config.build.traversePattern,\n * baseDir: [config.system.baseDir, ...config.content.codeDir],\n * dot: true,\n * });\n */\nexport const buildComponentFilesList = (\n config: BuildComponentFilesListOptions\n): string[] => {\n const {\n transformPattern,\n excludePattern = [],\n baseDir,\n dot = false,\n } = config;\n\n const patterns = normalizeToArray(transformPattern)\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && !pattern.startsWith('!')\n )\n .map(normalize); // Ensure it works with Windows\n\n const excludePatterns = [\n ...normalizeToArray(excludePattern),\n // Treat negation entries in transformPattern as additional excludes\n ...normalizeToArray(transformPattern)\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1)),\n ]\n .filter((pattern): pattern is string => typeof pattern === 'string')\n .map(normalize); // Ensure it works with Windows\n\n const roots = getDistinctRootDirs(normalizeToArray(baseDir));\n\n return Array.from(\n new Set(\n roots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: excludePatterns,\n absolute: true,\n dot,\n })\n )\n )\n );\n};\n\n/**\n * Convenience wrapper that derives all file-list options directly from an\n * `IntlayerConfig` object.\n *\n * Scans `[baseDir, ...codeDir]` using `build.traversePattern`, excludes\n * content declaration file extensions and any `compiler.excludePattern`\n * entries defined in the configuration, and includes dot files.\n */\nexport const buildComponentFilesListFromConfig = (\n intlayerConfig: IntlayerConfig\n): string[] => {\n const {\n build: { traversePattern },\n system: { baseDir },\n content: { codeDir, fileExtensions },\n compiler: { excludePattern },\n } = intlayerConfig;\n\n const excludePatterns = [\n // Exclude content declaration files (e.g. **/*.content.ts)\n ...fileExtensions.map((ext) => `**/*${ext}`),\n ...(Array.isArray(excludePattern) ? excludePattern : [excludePattern]),\n ].filter((p): p is string => typeof p === 'string');\n\n return buildComponentFilesList({\n transformPattern: traversePattern,\n excludePattern: excludePatterns,\n baseDir: [baseDir, ...codeDir],\n dot: true,\n });\n};\n"],"mappings":";;;;;;;AA+BA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;;;;;;AAOxC,MAAM,uBAAuB,SAA6B;CACxD,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC;AACvE,YAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;AAE9C,QAAO,WAAW,QAAQ,KAAe,QAAQ;AAK/C,MAAI,CAJa,IAAI,MAAM,WAAW;GACpC,MAAM,MAAM,SAAS,QAAQ,IAAI;AACjC,UAAO,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,WAAW,IAAI,IAAI,QAAQ;IAEjD,CAAE,KAAI,KAAK,IAAI;AAC5B,SAAO;IACN,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BR,MAAa,2BACX,WACa;CACb,MAAM,EACJ,kBACA,iBAAiB,EAAE,EACnB,SACA,MAAM,UACJ;CAEJ,MAAM,WAAW,iBAAiB,iBAAiB,CAChD,QACE,YACC,OAAO,YAAY,YAAY,CAAC,QAAQ,WAAW,IAAI,CAC1D,CACA,IAAI,UAAU;CAEjB,MAAM,kBAAkB,CACtB,GAAG,iBAAiB,eAAe,EAEnC,GAAG,iBAAiB,iBAAiB,CAClC,QACE,YACC,OAAO,YAAY,YAAY,QAAQ,WAAW,IAAI,CACzD,CACA,KAAK,YAAY,QAAQ,MAAM,EAAE,CAAC,CACtC,CACE,QAAQ,YAA+B,OAAO,YAAY,SAAS,CACnE,IAAI,UAAU;CAEjB,MAAM,QAAQ,oBAAoB,iBAAiB,QAAQ,CAAC;AAE5D,QAAO,MAAM,KACX,IAAI,IACF,MAAM,SAAS,SACb,GAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV;EACD,CAAC,CACH,CACF,CACF;;;;;;;;;;AAWH,MAAa,qCACX,mBACa;CACb,MAAM,EACJ,OAAO,EAAE,mBACT,QAAQ,EAAE,WACV,SAAS,EAAE,SAAS,kBACpB,UAAU,EAAE,qBACV;AAQJ,QAAO,wBAAwB;EAC7B,kBAAkB;EAClB,gBARsB,CAEtB,GAAG,eAAe,KAAK,QAAQ,OAAO,MAAM,EAC5C,GAAI,MAAM,QAAQ,eAAe,GAAG,iBAAiB,CAAC,eAAe,CACtE,CAAC,QAAQ,MAAmB,OAAO,MAAM,SAIT;EAC/B,SAAS,CAAC,SAAS,GAAG,QAAQ;EAC9B,KAAK;EACN,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chunkJSON.mjs","names":[],"sources":["../../../src/utils/chunkJSON.ts"],"sourcesContent":["/**\n * Split & reassemble JSON by character budget.\n * - Measures serialized size using JSON.stringify(..).length (characters).\n * - Ensures each chunk is itself valid JSON.\n * - Very large strings are split into safe pieces using getChunk and re-concatenated on assemble.\n * - Protects against circular structures (JSON can't serialize those anyway).\n */\n\nimport { getChunk } from './getChunk';\n\ntype JSONPrimitive = string | number | boolean | null;\ntype JSONValue = JSONPrimitive | JSONObject | JSONArray;\n\nexport type JSONObject = {\n [k: string]: JSONValue;\n};\n\ntype JSONArray = JSONValue[];\n\ntype Path = Array<string | number>;\n\ntype SetPatch = { op: 'set'; path: Path; value: JSONValue };\ntype StrAppendPatch = {\n op: 'str-append';\n path: Path;\n value: string; // part of a longer string\n index: number;\n total: number;\n};\ntype Patch = SetPatch | StrAppendPatch;\n\ntype RootType = 'object' | 'array';\n\nexport type JsonChunk = {\n schemaVersion: 1;\n index: number;\n total: number;\n rootType: RootType;\n checksum: string; // hash of the full original JSON string\n entries: Patch[];\n};\n\nconst isObject = (val: unknown): val is Record<string, unknown> => {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n};\n\nconst computeDjb2 = (str: string): string => {\n // Simple 32-bit hash; deterministic & fast\n let hash = 5381;\n\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash) ^ str.charCodeAt(i);\n }\n\n // convert to unsigned hex\n return (hash >>> 0).toString(16).padStart(8, '0');\n};\n\nconst setAtPath = (root: any, path: Path, value: JSONValue) => {\n let current = root;\n\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n const nextKey = path[i + 1];\n const isNextIndex = typeof nextKey === 'number';\n\n if (typeof key === 'number') {\n if (!Array.isArray(current)) {\n throw new Error(`Expected array at path segment ${i}`);\n }\n\n if (current[key] === undefined) {\n current[key] = isNextIndex ? [] : {};\n }\n\n current = current[key];\n } else {\n if (!isObject(current)) {\n throw new Error(`Expected object at path segment ${i}`);\n }\n\n if (!(key in current)) {\n (current as any)[key] = isNextIndex ? [] : {};\n }\n\n current = (current as any)[key];\n }\n }\n\n const last = path[path.length - 1];\n\n if (typeof last === 'number') {\n if (!Array.isArray(current)) {\n throw new Error(`Expected array at final segment`);\n }\n\n current[last] = value as any;\n } else {\n if (!isObject(current)) {\n throw new Error(`Expected object at final segment`);\n }\n\n (current as any)[last] = value as any;\n }\n};\n\nconst pathKey = (path: Path): string => {\n // stable key for grouping string parts\n return JSON.stringify(path);\n};\n\n/**\n * Split a string into parts using getChunk with a charLength budget per part.\n */\nconst splitStringByBudget = (\n str: string,\n maxCharsPerPart: number\n): string[] => {\n if (maxCharsPerPart <= 0) {\n throw new Error('maxChars must be > 0');\n }\n\n const output: string[] = [];\n let offset = 0;\n\n while (offset < str.length) {\n const part = getChunk(str, {\n charStart: offset,\n charLength: maxCharsPerPart,\n });\n\n if (!part) break;\n\n output.push(part);\n offset += part.length;\n }\n\n return output;\n};\n\n/**\n * Flatten JSON into patches (leaf writes). Strings too large to fit in a single\n * chunk are yielded as multiple str-append patches.\n */\nconst flattenToPatches = (\n value: JSONValue,\n maxCharsPerChunk: number,\n path: Path = [],\n seen = new WeakSet<object>()\n): Patch[] => {\n // Conservative per-entry cap so a single entry fits into an empty chunk with envelope overhead.\n // (Envelope ~ a few hundred chars; we keep a comfortable margin.)\n const maxStringPiece = Math.max(\n 1,\n Math.floor((maxCharsPerChunk - 400) * 0.8)\n );\n\n const patches: Patch[] = [];\n\n const walk = (currentValue: JSONValue, currentPath: Path) => {\n if (typeof currentValue === 'string') {\n // If the serialized patch wouldn't fit, split the string into multiple parts\n // and encode as a split-node sentinel with numbered keys.\n const testPatch: SetPatch = {\n op: 'set',\n path: currentPath,\n value: currentValue,\n };\n const testLen = JSON.stringify(testPatch).length + 150; // margin\n\n if (testLen <= maxCharsPerChunk) {\n patches.push(testPatch);\n return;\n }\n\n // Use getChunk-based splitting to produce stable parts\n const parts = splitStringByBudget(currentValue, maxStringPiece);\n\n // Emit split-node metadata and parts as individual leaf writes\n patches.push({\n op: 'set',\n path: [...currentPath, '__splittedType'],\n value: 'string',\n });\n patches.push({\n op: 'set',\n path: [...currentPath, '__total'],\n value: parts.length,\n });\n\n for (let i = 0; i < parts.length; i++) {\n patches.push({\n op: 'set',\n path: [...currentPath, String(i + 1)],\n value: parts[i],\n });\n }\n\n return;\n }\n\n if (currentValue === null || typeof currentValue !== 'object') {\n patches.push({ op: 'set', path: currentPath, value: currentValue });\n return;\n }\n\n if (seen.has(currentValue as object)) {\n throw new Error('Cannot serialize circular structures to JSON.');\n }\n\n seen.add(currentValue as object);\n\n if (Array.isArray(currentValue)) {\n for (let i = 0; i < currentValue.length; i++) {\n walk(currentValue[i] as JSONValue, [...currentPath, i]);\n }\n } else {\n for (const key of Object.keys(currentValue)) {\n walk((currentValue as JSONObject)[key], [...currentPath, key]);\n }\n }\n\n seen.delete(currentValue as object);\n };\n\n walk(value, path);\n return patches;\n};\n\n/**\n * Split JSON into chunks constrained by character count of serialized chunk.\n */\nexport const chunkJSON = (\n value: JSONObject | JSONArray,\n maxChars: number\n): JsonChunk[] => {\n if (!isObject(value) && !Array.isArray(value)) {\n throw new Error('Root must be an object or array.');\n }\n\n if (maxChars < 500) {\n // You can lower this if you truly need; recommended to keep some envelope headroom.\n throw new Error('maxChars is too small. Use at least 500 characters.');\n }\n\n const rootType: RootType = Array.isArray(value) ? 'array' : 'object';\n let sourceString: string;\n\n try {\n sourceString = JSON.stringify(value);\n } catch {\n // Provide a deterministic error message for circular refs\n throw new Error('Cannot serialize circular structures to JSON.');\n }\n\n const checksum = computeDjb2(sourceString);\n const allPatches = flattenToPatches(value as JSONValue, maxChars);\n\n const chunks: JsonChunk[] = [];\n let currentChunk: JsonChunk = {\n schemaVersion: 1,\n index: 0, // provisional\n total: 0, // provisional\n rootType,\n checksum,\n entries: [],\n };\n\n const emptyEnvelopeSize = JSON.stringify({\n ...currentChunk,\n entries: [],\n }).length;\n\n const tryFlush = () => {\n if (currentChunk.entries.length > 0) {\n chunks.push(currentChunk);\n currentChunk = {\n schemaVersion: 1,\n index: 0,\n total: 0,\n rootType,\n checksum,\n entries: [],\n };\n }\n };\n\n for (const patch of allPatches) {\n // Would adding this patch exceed maxChars?\n const withPatchSize =\n emptyEnvelopeSize +\n JSON.stringify(currentChunk.entries).length + // current entries array\n (currentChunk.entries.length ? 1 : 0) + // possible comma\n JSON.stringify(patch).length;\n\n if (withPatchSize <= maxChars) {\n currentChunk.entries.push(patch);\n } else {\n // Start a new chunk if current has items\n if (currentChunk.entries.length > 0) {\n tryFlush();\n }\n\n // Ensure single patch fits into an empty chunk\n const singleSize = emptyEnvelopeSize + JSON.stringify([patch]).length;\n\n if (singleSize > maxChars) {\n // This should only happen for massive strings, which we pre-split;\n // if it happens for a non-string, we cannot split further.\n throw new Error(\n 'A single entry exceeds maxChars and cannot be split. Reduce entry size or increase maxChars.'\n );\n }\n\n currentChunk.entries.push(patch);\n }\n }\n\n tryFlush();\n\n // Ensure at least one chunk exists (even for empty root)\n if (chunks.length === 0) {\n chunks.push({\n schemaVersion: 1,\n index: 0,\n total: 0, // provisional\n rootType,\n checksum,\n entries: [],\n });\n }\n\n // Finalize indices & totals\n const totalChunks = chunks.length;\n\n chunks.forEach((chunk, index) => {\n chunk.index = index;\n chunk.total = totalChunks;\n });\n\n return chunks;\n};\n\n/**\n * Reassemble JSON from chunks.\n * - Validates checksums and indices.\n * - Applies 'set' patches and merges string pieces from 'str-append'.\n */\n/**\n * Reconstruct content from a single chunk without validation.\n * Useful for processing individual chunks in a pipeline where you don't have all chunks yet.\n * Note: This will only reconstruct the partial content contained in this chunk.\n */\nexport const reconstructFromSingleChunk = (\n chunk: JsonChunk\n): JSONObject | JSONArray => {\n const root: any = chunk.rootType === 'array' ? [] : {};\n\n // Apply all 'set' patches from this chunk\n for (const entry of chunk.entries) {\n if (entry.op === 'set') {\n setAtPath(root, entry.path, entry.value);\n }\n }\n\n // Reconcile split-node sentinels for strings/arrays\n // When reconstructing from a single chunk, we may have incomplete split nodes\n const reconcileSplitNodes = (node: any): any => {\n if (node === null || typeof node !== 'object') return node;\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n node[i] = reconcileSplitNodes(node[i]);\n }\n return node;\n }\n\n // string split-node\n if ((node as any)['__splittedType'] === 'string') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total <= 0) {\n // Invalid split node, return as-is\n return node;\n }\n\n const parts: string[] = [];\n let hasAllParts = true;\n\n for (let i = 1; i <= total; i++) {\n const piece = (node as any)[String(i)];\n\n if (typeof piece !== 'string') {\n hasAllParts = false;\n break;\n }\n\n parts.push(piece);\n }\n\n // Only reconstruct if we have all parts, otherwise return the node as-is\n if (hasAllParts) {\n return parts.join('');\n }\n\n return node;\n }\n\n // array split-node (optional support)\n if ((node as any)['__splittedType'] === 'array') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total < 0) {\n // Invalid split node, return as-is\n return node;\n }\n\n const output: any[] = [];\n let hasAllParts = true;\n\n for (let i = 1; i <= total; i++) {\n const slice = (node as any)[String(i)];\n\n if (!Array.isArray(slice)) {\n hasAllParts = false;\n break;\n }\n\n for (let j = 0; j < slice.length; j++) {\n output.push(reconcileSplitNodes(slice[j]));\n }\n }\n\n // Only reconstruct if we have all parts\n if (hasAllParts) {\n return output;\n }\n\n return node;\n }\n\n // walk normal object\n for (const key of Object.keys(node)) {\n node[key] = reconcileSplitNodes(node[key]);\n }\n\n return node;\n };\n\n return reconcileSplitNodes(root);\n};\n\nexport const assembleJSON = (chunks: JsonChunk[]): JSONObject | JSONArray => {\n if (!chunks || chunks.length === 0) {\n throw new Error('No chunks provided.');\n }\n\n // Basic validation & sort\n const sorted = [...chunks].sort((a, b) => a.index - b.index);\n const { checksum, rootType } = sorted[0];\n const schemaVersion = 1;\n\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (chunk.schemaVersion !== schemaVersion) {\n console.error('Unsupported schemaVersion.', {\n cause: chunk,\n schemaVersion,\n });\n throw new Error('Unsupported schemaVersion.');\n }\n\n if (chunk.rootType !== rootType) {\n console.error('Chunks rootType mismatch.', {\n cause: chunk,\n rootType,\n });\n throw new Error('Chunks rootType mismatch.');\n }\n\n if (chunk.checksum !== checksum) {\n console.error('Chunks checksum mismatch (different source objects?).', {\n cause: chunk,\n checksum,\n });\n throw new Error('Chunks checksum mismatch (different source objects?).');\n }\n\n if (chunk.index !== i) {\n console.error('Chunk indices are not contiguous or sorted.', {\n cause: chunk,\n index: chunk.index,\n i,\n });\n throw new Error('Chunk indices are not contiguous or sorted.');\n }\n\n // Defer total check until after reconstruction to prefer more specific errors\n }\n\n const root: any = rootType === 'array' ? [] : {};\n\n // Collect string parts by path\n const stringParts = new Map<\n string,\n { path: Path; total: number; received: StrAppendPatch[] }\n >();\n\n const applySet = (patch: SetPatch) =>\n setAtPath(root, patch.path, patch.value);\n\n for (const chunk of sorted) {\n for (const entry of chunk.entries) {\n if (entry.op === 'set') {\n applySet(entry);\n } else {\n const key = pathKey(entry.path);\n const record = stringParts.get(key) ?? {\n path: entry.path,\n total: entry.total,\n received: [],\n };\n\n if (record.total !== entry.total) {\n throw new Error('Inconsistent string part totals for a path.');\n }\n\n record.received.push(entry);\n stringParts.set(key, record);\n }\n }\n }\n\n // Stitch strings\n for (const { path, total, received } of stringParts.values()) {\n if (received.length !== total) {\n throw new Error('Missing string parts for a path; incomplete chunk set.');\n }\n\n received.sort((a, b) => a.index - b.index);\n const fullString = received.map((part) => part.value).join('');\n setAtPath(root, path, fullString);\n }\n\n // Reconcile split-node sentinels for strings/arrays after all patches applied\n const reconcileSplitNodes = (node: any): any => {\n if (node === null || typeof node !== 'object') return node;\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n node[i] = reconcileSplitNodes(node[i]);\n }\n return node;\n }\n\n // string split-node\n if ((node as any)['__splittedType'] === 'string') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total <= 0) {\n throw new Error('Invalid split-node total for a path.');\n }\n\n const parts: string[] = [];\n\n for (let i = 1; i <= total; i++) {\n const piece = (node as any)[String(i)];\n\n if (typeof piece !== 'string') {\n throw new Error(\n 'Missing string parts for a path; incomplete chunk set.'\n );\n }\n\n parts.push(piece);\n }\n\n return parts.join('');\n }\n\n // array split-node (optional support)\n if ((node as any)['__splittedType'] === 'array') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total < 0) {\n throw new Error('Invalid split-node total for a path.');\n }\n\n const output: any[] = [];\n\n for (let i = 1; i <= total; i++) {\n const slice = (node as any)[String(i)];\n\n if (!Array.isArray(slice)) {\n throw new Error(\n 'Missing string parts for a path; incomplete chunk set.'\n );\n }\n\n for (let j = 0; j < slice.length; j++) {\n output.push(reconcileSplitNodes(slice[j]));\n }\n }\n\n return output;\n }\n\n // walk normal object\n for (const key of Object.keys(node)) {\n node[key] = reconcileSplitNodes(node[key]);\n }\n\n return node;\n };\n\n const reconciled = reconcileSplitNodes(root);\n\n // Now validate totals match provided count\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (chunk.total !== sorted.length) {\n throw new Error(\n `Chunk total does not match provided count. Expected ${sorted.length}, but chunk ${i} has total=${chunk.total}`\n );\n }\n }\n\n return reconciled;\n};\n\n/* -------------------------------------------\n * Example usage\n * -------------------------------------------\nconst big: JSONObject = {\n title: \"Document\",\n content: \"…a very very long text…\",\n items: Array.from({ length: 2000 }, (_, i) => ({ id: i, label: `Item ${i}` }))\n};\n\n// Split to ~16k-char chunks\nconst chunks = chunkJSON(big, 16_000);\n\n// Send each `chunks[i]` as JSON to your backend.\n// Later, reassemble:\nconst restored = assembleJSON(chunks);\nconsole.log(JSON.stringify(restored) === JSON.stringify(big)); // true\n*/\n"],"mappings":"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"}
1
+ {"version":3,"file":"chunkJSON.mjs","names":[],"sources":["../../../src/utils/chunkJSON.ts"],"sourcesContent":["/**\n * Split & reassemble JSON by character budget.\n * - Measures serialized size using JSON.stringify(..).length (characters).\n * - Ensures each chunk is itself valid JSON.\n * - Very large strings are split into safe pieces using getChunk and re-concatenated on assemble.\n * - Protects against circular structures (JSON can't serialize those anyway).\n */\n\nimport { getChunk } from './getChunk';\n\ntype JSONPrimitive = string | number | boolean | null;\ntype JSONValue = JSONPrimitive | JSONObject | JSONArray;\n\nexport type JSONObject = {\n [k: string]: JSONValue;\n};\n\ntype JSONArray = JSONValue[];\n\ntype Path = Array<string | number>;\n\ntype SetPatch = { op: 'set'; path: Path; value: JSONValue };\ntype StrAppendPatch = {\n op: 'str-append';\n path: Path;\n value: string; // part of a longer string\n index: number;\n total: number;\n};\ntype Patch = SetPatch | StrAppendPatch;\n\ntype RootType = 'object' | 'array';\n\nexport type JsonChunk = {\n schemaVersion: 1;\n index: number;\n total: number;\n rootType: RootType;\n checksum: string; // hash of the full original JSON string\n entries: Patch[];\n};\n\nconst isObject = (val: unknown): val is Record<string, unknown> => {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n};\n\nconst computeDjb2 = (str: string): string => {\n // Simple 32-bit hash; deterministic & fast\n let hash = 5381;\n\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash) ^ str.charCodeAt(i);\n }\n\n // convert to unsigned hex\n return (hash >>> 0).toString(16).padStart(8, '0');\n};\n\nconst setAtPath = (root: any, path: Path, value: JSONValue) => {\n let current = root;\n\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n const nextKey = path[i + 1];\n const isNextIndex = typeof nextKey === 'number';\n\n if (typeof key === 'number') {\n if (!Array.isArray(current)) {\n throw new Error(`Expected array at path segment ${i}`);\n }\n\n if (current[key] === undefined) {\n current[key] = isNextIndex ? [] : {};\n }\n\n current = current[key];\n } else {\n if (!isObject(current)) {\n throw new Error(`Expected object at path segment ${i}`);\n }\n\n if (!(key in current)) {\n (current as any)[key] = isNextIndex ? [] : {};\n }\n\n current = (current as any)[key];\n }\n }\n\n const last = path[path.length - 1];\n\n if (typeof last === 'number') {\n if (!Array.isArray(current)) {\n throw new Error(`Expected array at final segment`);\n }\n\n current[last] = value as any;\n } else {\n if (!isObject(current)) {\n throw new Error(`Expected object at final segment`);\n }\n\n (current as any)[last] = value as any;\n }\n};\n\nconst pathKey = (path: Path): string => {\n // stable key for grouping string parts\n return JSON.stringify(path);\n};\n\n/**\n * Split a string into parts using getChunk with a charLength budget per part.\n */\nconst splitStringByBudget = (\n str: string,\n maxCharsPerPart: number\n): string[] => {\n if (maxCharsPerPart <= 0) {\n throw new Error('maxChars must be > 0');\n }\n\n const output: string[] = [];\n let offset = 0;\n\n while (offset < str.length) {\n const part = getChunk(str, {\n charStart: offset,\n charLength: maxCharsPerPart,\n });\n\n if (!part) break;\n\n output.push(part);\n offset += part.length;\n }\n\n return output;\n};\n\n/**\n * Flatten JSON into patches (leaf writes). Strings too large to fit in a single\n * chunk are yielded as multiple str-append patches.\n */\nconst flattenToPatches = (\n value: JSONValue,\n maxCharsPerChunk: number,\n path: Path = [],\n seen = new WeakSet<object>()\n): Patch[] => {\n // Conservative per-entry cap so a single entry fits into an empty chunk with envelope overhead.\n // (Envelope ~ a few hundred chars; we keep a comfortable margin.)\n const maxStringPiece = Math.max(\n 1,\n Math.floor((maxCharsPerChunk - 400) * 0.8)\n );\n\n const patches: Patch[] = [];\n\n const walk = (currentValue: JSONValue, currentPath: Path) => {\n if (typeof currentValue === 'string') {\n // If the serialized patch wouldn't fit, split the string into multiple parts\n // and encode as a split-node sentinel with numbered keys.\n const testPatch: SetPatch = {\n op: 'set',\n path: currentPath,\n value: currentValue,\n };\n const testLen = JSON.stringify(testPatch).length + 150; // margin\n\n if (testLen <= maxCharsPerChunk) {\n patches.push(testPatch);\n return;\n }\n\n // Use getChunk-based splitting to produce stable parts\n const parts = splitStringByBudget(currentValue, maxStringPiece);\n\n // Emit split-node metadata and parts as individual leaf writes\n patches.push({\n op: 'set',\n path: [...currentPath, '__splittedType'],\n value: 'string',\n });\n patches.push({\n op: 'set',\n path: [...currentPath, '__total'],\n value: parts.length,\n });\n\n for (let i = 0; i < parts.length; i++) {\n patches.push({\n op: 'set',\n path: [...currentPath, String(i + 1)],\n value: parts[i],\n });\n }\n\n return;\n }\n\n if (currentValue === null || typeof currentValue !== 'object') {\n patches.push({ op: 'set', path: currentPath, value: currentValue });\n return;\n }\n\n if (seen.has(currentValue as object)) {\n throw new Error('Cannot serialize circular structures to JSON.');\n }\n\n seen.add(currentValue as object);\n\n if (Array.isArray(currentValue)) {\n for (let i = 0; i < currentValue.length; i++) {\n walk(currentValue[i] as JSONValue, [...currentPath, i]);\n }\n } else {\n for (const key of Object.keys(currentValue)) {\n walk((currentValue as JSONObject)[key], [...currentPath, key]);\n }\n }\n\n seen.delete(currentValue as object);\n };\n\n walk(value, path);\n return patches;\n};\n\n/**\n * Split JSON into chunks constrained by character count of serialized chunk.\n */\nexport const chunkJSON = (\n value: JSONObject | JSONArray,\n maxChars: number\n): JsonChunk[] => {\n if (!isObject(value) && !Array.isArray(value)) {\n throw new Error('Root must be an object or array.');\n }\n\n if (maxChars < 500) {\n // You can lower this if you truly need; recommended to keep some envelope headroom.\n throw new Error('maxChars is too small. Use at least 500 characters.');\n }\n\n const rootType: RootType = Array.isArray(value) ? 'array' : 'object';\n let sourceString: string;\n\n try {\n sourceString = JSON.stringify(value);\n } catch {\n // Provide a deterministic error message for circular refs\n throw new Error('Cannot serialize circular structures to JSON.');\n }\n\n const checksum = computeDjb2(sourceString);\n const allPatches = flattenToPatches(value as JSONValue, maxChars);\n\n const chunks: JsonChunk[] = [];\n let currentChunk: JsonChunk = {\n schemaVersion: 1,\n index: 0, // provisional\n total: 0, // provisional\n rootType,\n checksum,\n entries: [],\n };\n\n const emptyEnvelopeSize = JSON.stringify({\n ...currentChunk,\n entries: [],\n }).length;\n\n const tryFlush = () => {\n if (currentChunk.entries.length > 0) {\n chunks.push(currentChunk);\n currentChunk = {\n schemaVersion: 1,\n index: 0,\n total: 0,\n rootType,\n checksum,\n entries: [],\n };\n }\n };\n\n for (const patch of allPatches) {\n // Would adding this patch exceed maxChars?\n const withPatchSize =\n emptyEnvelopeSize +\n JSON.stringify(currentChunk.entries).length + // current entries array\n (currentChunk.entries.length ? 1 : 0) + // possible comma\n JSON.stringify(patch).length;\n\n if (withPatchSize <= maxChars) {\n currentChunk.entries.push(patch);\n } else {\n // Start a new chunk if current has items\n if (currentChunk.entries.length > 0) {\n tryFlush();\n }\n\n // Ensure single patch fits into an empty chunk\n const singleSize = emptyEnvelopeSize + JSON.stringify([patch]).length;\n\n if (singleSize > maxChars) {\n // This should only happen for massive strings, which we pre-split;\n // if it happens for a non-string, we cannot split further.\n throw new Error(\n 'A single entry exceeds maxChars and cannot be split. Reduce entry size or increase maxChars.'\n );\n }\n\n currentChunk.entries.push(patch);\n }\n }\n\n tryFlush();\n\n // Ensure at least one chunk exists (even for empty root)\n if (chunks.length === 0) {\n chunks.push({\n schemaVersion: 1,\n index: 0,\n total: 0, // provisional\n rootType,\n checksum,\n entries: [],\n });\n }\n\n // Finalize indices & totals\n const totalChunks = chunks.length;\n\n chunks.forEach((chunk, index) => {\n chunk.index = index;\n chunk.total = totalChunks;\n });\n\n return chunks;\n};\n\n/**\n * Reassemble JSON from chunks.\n * - Validates checksums and indices.\n * - Applies 'set' patches and merges string pieces from 'str-append'.\n */\n/**\n * Reconstruct content from a single chunk without validation.\n * Useful for processing individual chunks in a pipeline where you don't have all chunks yet.\n * Note: This will only reconstruct the partial content contained in this chunk.\n */\nexport const reconstructFromSingleChunk = (\n chunk: JsonChunk\n): JSONObject | JSONArray => {\n const root: any = chunk.rootType === 'array' ? [] : {};\n\n // Apply all 'set' patches from this chunk\n for (const entry of chunk.entries) {\n if (entry.op === 'set') {\n setAtPath(root, entry.path, entry.value);\n }\n }\n\n // Reconcile split-node sentinels for strings/arrays\n // When reconstructing from a single chunk, we may have incomplete split nodes\n const reconcileSplitNodes = (node: any): any => {\n if (node === null || typeof node !== 'object') return node;\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n node[i] = reconcileSplitNodes(node[i]);\n }\n return node;\n }\n\n // string split-node\n if ((node as any)['__splittedType'] === 'string') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total <= 0) {\n // Invalid split node, return as-is\n return node;\n }\n\n const parts: string[] = [];\n let hasAllParts = true;\n\n for (let i = 1; i <= total; i++) {\n const piece = (node as any)[String(i)];\n\n if (typeof piece !== 'string') {\n hasAllParts = false;\n break;\n }\n\n parts.push(piece);\n }\n\n // Only reconstruct if we have all parts, otherwise return the node as-is\n if (hasAllParts) {\n return parts.join('');\n }\n\n return node;\n }\n\n // array split-node (optional support)\n if ((node as any)['__splittedType'] === 'array') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total < 0) {\n // Invalid split node, return as-is\n return node;\n }\n\n const output: any[] = [];\n let hasAllParts = true;\n\n for (let i = 1; i <= total; i++) {\n const slice = (node as any)[String(i)];\n\n if (!Array.isArray(slice)) {\n hasAllParts = false;\n break;\n }\n\n for (let j = 0; j < slice.length; j++) {\n output.push(reconcileSplitNodes(slice[j]));\n }\n }\n\n // Only reconstruct if we have all parts\n if (hasAllParts) {\n return output;\n }\n\n return node;\n }\n\n // walk normal object\n for (const key of Object.keys(node)) {\n node[key] = reconcileSplitNodes(node[key]);\n }\n\n return node;\n };\n\n return reconcileSplitNodes(root);\n};\n\nexport const assembleJSON = (chunks: JsonChunk[]): JSONObject | JSONArray => {\n if (!chunks || chunks.length === 0) {\n throw new Error('No chunks provided.');\n }\n\n // Basic validation & sort\n const sorted = [...chunks].sort((a, b) => a.index - b.index);\n const { checksum, rootType } = sorted[0];\n const schemaVersion = 1;\n\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (chunk.schemaVersion !== schemaVersion) {\n console.error('Unsupported schemaVersion.', {\n cause: chunk,\n schemaVersion,\n });\n throw new Error('Unsupported schemaVersion.');\n }\n\n if (chunk.rootType !== rootType) {\n console.error('Chunks rootType mismatch.', {\n cause: chunk,\n rootType,\n });\n throw new Error('Chunks rootType mismatch.');\n }\n\n if (chunk.checksum !== checksum) {\n console.error('Chunks checksum mismatch (different source objects?).', {\n cause: chunk,\n checksum,\n });\n throw new Error('Chunks checksum mismatch (different source objects?).');\n }\n\n if (chunk.index !== i) {\n console.error('Chunk indices are not contiguous or sorted.', {\n cause: chunk,\n index: chunk.index,\n i,\n });\n throw new Error('Chunk indices are not contiguous or sorted.');\n }\n\n // Defer total check until after reconstruction to prefer more specific errors\n }\n\n const root: any = rootType === 'array' ? [] : {};\n\n // Collect string parts by path\n const stringParts = new Map<\n string,\n { path: Path; total: number; received: StrAppendPatch[] }\n >();\n\n const applySet = (patch: SetPatch) =>\n setAtPath(root, patch.path, patch.value);\n\n for (const chunk of sorted) {\n for (const entry of chunk.entries) {\n if (entry.op === 'set') {\n applySet(entry);\n } else {\n const key = pathKey(entry.path);\n const record = stringParts.get(key) ?? {\n path: entry.path,\n total: entry.total,\n received: [],\n };\n\n if (record.total !== entry.total) {\n throw new Error('Inconsistent string part totals for a path.');\n }\n\n record.received.push(entry);\n stringParts.set(key, record);\n }\n }\n }\n\n // Stitch strings\n for (const { path, total, received } of stringParts.values()) {\n if (received.length !== total) {\n throw new Error('Missing string parts for a path; incomplete chunk set.');\n }\n\n received.sort((a, b) => a.index - b.index);\n const fullString = received.map((part) => part.value).join('');\n setAtPath(root, path, fullString);\n }\n\n // Reconcile split-node sentinels for strings/arrays after all patches applied\n const reconcileSplitNodes = (node: any): any => {\n if (node === null || typeof node !== 'object') return node;\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n node[i] = reconcileSplitNodes(node[i]);\n }\n return node;\n }\n\n // string split-node\n if ((node as any)['__splittedType'] === 'string') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total <= 0) {\n throw new Error('Invalid split-node total for a path.');\n }\n\n const parts: string[] = [];\n\n for (let i = 1; i <= total; i++) {\n const piece = (node as any)[String(i)];\n\n if (typeof piece !== 'string') {\n throw new Error(\n 'Missing string parts for a path; incomplete chunk set.'\n );\n }\n\n parts.push(piece);\n }\n\n return parts.join('');\n }\n\n // array split-node (optional support)\n if ((node as any)['__splittedType'] === 'array') {\n const total = (node as any)['__total'];\n\n if (typeof total !== 'number' || total < 0) {\n throw new Error('Invalid split-node total for a path.');\n }\n\n const output: any[] = [];\n\n for (let i = 1; i <= total; i++) {\n const slice = (node as any)[String(i)];\n\n if (!Array.isArray(slice)) {\n throw new Error(\n 'Missing string parts for a path; incomplete chunk set.'\n );\n }\n\n for (let j = 0; j < slice.length; j++) {\n output.push(reconcileSplitNodes(slice[j]));\n }\n }\n\n return output;\n }\n\n // walk normal object\n for (const key of Object.keys(node)) {\n node[key] = reconcileSplitNodes(node[key]);\n }\n\n return node;\n };\n\n const reconciled = reconcileSplitNodes(root);\n\n // Now validate totals match provided count\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (chunk.total !== sorted.length) {\n throw new Error(\n `Chunk total does not match provided count. Expected ${sorted.length}, but chunk ${i} has total=${chunk.total}`\n );\n }\n }\n\n return reconciled;\n};\n\n/* -------------------------------------------\n * Example usage\n * -------------------------------------------\nconst big: JSONObject = {\n title: \"Document\",\n content: \"…a very very long text…\",\n items: Array.from({ length: 2000 }, (_, i) => ({ id: i, label: `Item ${i}` }))\n};\n\n// Split to ~16k-char chunks\nconst chunks = chunkJSON(big, 16_000);\n\n// Send each `chunks[i]` as JSON to your backend.\n// Later, reassemble:\nconst restored = assembleJSON(chunks);\nconsole.log(JSON.stringify(restored) === JSON.stringify(big)); // true\n*/\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getContentExtension.mjs","names":[],"sources":["../../../src/utils/getContentExtension.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Generates the .content file extension based on the desired format\n * and the project's fileExtensions configuration.\n *\n * Example:\n * format 'ts' -> '.content.ts'\n * format 'esm' -> '.content.js' (if matching .content.js is found in config)\n */\nexport const getContentExtension = (\n format: 'ts' | 'esm' | 'cjs' | 'json' | 'jsonc' | 'json5' | (string & {}),\n configuration: IntlayerConfig\n): string => {\n let contentFileExtension = '.ts';\n switch (format) {\n case 'json':\n contentFileExtension = '.json';\n break;\n case 'cjs':\n contentFileExtension = '.cjs';\n break;\n case 'esm':\n contentFileExtension = '.js';\n break;\n }\n\n // Find the configured extension that matches the format's extension\n const pickedFileExtension = configuration.content.fileExtensions.find(\n (extension) => extension.endsWith(contentFileExtension)\n );\n\n return (\n pickedFileExtension ??\n configuration.content.fileExtensions[0] ??\n `.content${contentFileExtension}`\n );\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,uBACX,QACA,kBACW;CACX,IAAI,uBAAuB;AAC3B,SAAQ,QAAR;EACE,KAAK;AACH,0BAAuB;AACvB;EACF,KAAK;AACH,0BAAuB;AACvB;EACF,KAAK;AACH,0BAAuB;AACvB;;AAQJ,QAJ4B,cAAc,QAAQ,eAAe,MAC9D,cAAc,UAAU,SAAS,qBAAqB,CACxD,IAIC,cAAc,QAAQ,eAAe,MACrC,WAAW"}
1
+ {"version":3,"file":"getContentExtension.mjs","names":[],"sources":["../../../src/utils/getContentExtension.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Generates the .content file extension based on the desired format\n * and the project's fileExtensions configuration.\n *\n * Example:\n * format 'ts' -> '.content.ts'\n * format 'esm' -> '.content.js' (if matching .content.js is found in config)\n */\nexport const getContentExtension = (\n format: 'ts' | 'esm' | 'cjs' | 'json' | 'jsonc' | 'json5' | (string & {}),\n configuration: IntlayerConfig\n): string => {\n let contentFileExtension = '.ts';\n switch (format) {\n case 'json':\n contentFileExtension = '.json';\n break;\n case 'cjs':\n contentFileExtension = '.cjs';\n break;\n case 'esm':\n contentFileExtension = '.js';\n break;\n }\n\n // Find the configured extension that matches the format's extension\n const pickedFileExtension = configuration.content.fileExtensions.find(\n (extension) => extension.endsWith(contentFileExtension)\n );\n\n return (\n pickedFileExtension ??\n configuration.content.fileExtensions[0] ??\n `.content${contentFileExtension}`\n );\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,uBACX,QACA,kBACW;CACX,IAAI,uBAAuB;AAC3B,SAAQ,QAAR;EACE,KAAK;AACH,0BAAuB;AACvB;EACF,KAAK;AACH,0BAAuB;AACvB;EACF,KAAK;AACH,0BAAuB;AACvB;;AAQJ,QAJ4B,cAAc,QAAQ,eAAe,MAC9D,cAAc,UAAU,SAAS,qBAAqB,CAIpC,IACnB,cAAc,QAAQ,eAAe,MACrC,WAAW"}
@@ -110,7 +110,12 @@ const pLimit = (concurrency) => {
110
110
  const promises = array.map((value, index) => this(fn, value, index));
111
111
  return Promise.all(promises);
112
112
  } },
113
- onIdle: { value() {
113
+ onIdle: {
114
+ /**
115
+ * Resolves when `activeCount === 0` and the queue is empty.
116
+ * Use this to wait for completion without holding a list of Promises.
117
+ */
118
+ value() {
114
119
  if (activeCount === 0 && queue.size === 0) return Promise.resolve();
115
120
  return new Promise((resolve) => idleWaiters.push(resolve));
116
121
  } }
@@ -1 +1 @@
1
- {"version":3,"file":"pLimit.mjs","names":["#head","#tail","#size"],"sources":["../../../src/utils/pLimit.ts"],"sourcesContent":["/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node<T> {\n value: T;\n next: Node<T> | undefined;\n\n constructor(value: T) {\n this.value = value;\n }\n}\n\nexport class Queue<T> {\n #head: Node<T> | undefined;\n #tail: Node<T> | undefined;\n #size!: number;\n\n constructor() {\n this.clear();\n }\n\n enqueue(value: T): void {\n const node = new Node(value);\n\n if (this.#head) {\n this.#tail!.next = node;\n this.#tail = node;\n } else {\n this.#head = node;\n this.#tail = node;\n }\n\n this.#size++;\n }\n\n dequeue(): T | undefined {\n const current = this.#head;\n if (!current) {\n return;\n }\n\n this.#head = current.next;\n this.#size--;\n return current.value;\n }\n\n peek(): T | undefined {\n if (!this.#head) {\n return;\n }\n\n return this.#head.value;\n\n // TODO: Node.js 18.\n // return this.#head?.value;\n }\n\n clear(): void {\n this.#head = undefined;\n this.#tail = undefined;\n this.#size = 0;\n }\n\n get size(): number {\n return this.#size;\n }\n\n *[Symbol.iterator](): Generator<T, void, unknown> {\n let current = this.#head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n *drain(): Generator<T | undefined, void, unknown> {\n while (this.#head) {\n yield this.dequeue();\n }\n }\n}\n\nexport const pLimit = (concurrency: number) => {\n validateConcurrency(concurrency);\n\n const queue = new Queue<() => void>();\n let activeCount = 0;\n\n const idleWaiters: Array<() => void> = [];\n const notifyIdleIfNeeded = (): void => {\n if (activeCount === 0 && queue.size === 0) {\n while (idleWaiters.length) idleWaiters.pop()?.();\n }\n };\n\n const resumeNext = (): void => {\n // Process the next queued function if we're under the concurrency limit\n if (activeCount < concurrency && queue.size > 0) {\n activeCount++;\n queue.dequeue()?.();\n }\n };\n\n const next = (): void => {\n activeCount--;\n resumeNext();\n };\n\n const run = async (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): Promise<void> => {\n // Execute the function and capture the result promise\n const result = (async () => fn(...arguments_))();\n\n // Resolve immediately with the promise (don't wait for completion)\n resolve(result);\n\n // Wait for the function to complete (success or failure)\n // We catch errors here to prevent unhandled rejections,\n // but the original promise rejection is preserved for the caller\n try {\n await result;\n } catch {}\n\n // Decrement active count and process next queued function\n next();\n };\n\n const enqueue = (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): void => {\n // Queue the internal resolve function instead of the run function\n // to preserve the asynchronous execution context.\n new Promise<void>((internalResolve) => {\n queue.enqueue(internalResolve);\n }).then(run.bind(undefined, fn, resolve, arguments_));\n\n // Start processing immediately if we haven't reached the concurrency limit\n if (activeCount < concurrency) {\n resumeNext();\n }\n };\n\n const generator = (\n fn: (...args: any[]) => Promise<any>,\n ...arguments_: any[]\n ): Promise<any> =>\n new Promise<any>((resolve) => {\n enqueue(fn, resolve, arguments_);\n });\n\n Object.defineProperties(generator, {\n activeCount: {\n get: () => activeCount,\n },\n pendingCount: {\n get: () => queue.size,\n },\n clearQueue: {\n value() {\n queue.clear();\n notifyIdleIfNeeded();\n },\n },\n concurrency: {\n get: () => concurrency,\n\n set(newConcurrency: number) {\n validateConcurrency(newConcurrency);\n concurrency = newConcurrency;\n\n queueMicrotask(() => {\n while (activeCount < concurrency && queue.size > 0) {\n resumeNext();\n }\n });\n },\n },\n map: {\n async value<T, R>(\n array: T[],\n fn: (value: T, index: number) => Promise<R>\n ): Promise<R[]> {\n const promises = array.map((value, index) => this(fn, value, index));\n return Promise.all(promises);\n },\n },\n onIdle: {\n /**\n * Resolves when `activeCount === 0` and the queue is empty.\n * Use this to wait for completion without holding a list of Promises.\n */\n value(): Promise<void> {\n if (activeCount === 0 && queue.size === 0) return Promise.resolve();\n return new Promise<void>((resolve) => idleWaiters.push(resolve));\n },\n },\n });\n\n return generator;\n};\n\nconst validateConcurrency = (concurrency: number): void => {\n if (\n !(\n (Number.isInteger(concurrency) ||\n concurrency === Number.POSITIVE_INFINITY) &&\n concurrency > 0\n )\n ) {\n throw new TypeError('Expected `concurrency` to be a number from 1 and up');\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"pLimit.mjs","names":["#head","#tail","#size"],"sources":["../../../src/utils/pLimit.ts"],"sourcesContent":["/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node<T> {\n value: T;\n next: Node<T> | undefined;\n\n constructor(value: T) {\n this.value = value;\n }\n}\n\nexport class Queue<T> {\n #head: Node<T> | undefined;\n #tail: Node<T> | undefined;\n #size!: number;\n\n constructor() {\n this.clear();\n }\n\n enqueue(value: T): void {\n const node = new Node(value);\n\n if (this.#head) {\n this.#tail!.next = node;\n this.#tail = node;\n } else {\n this.#head = node;\n this.#tail = node;\n }\n\n this.#size++;\n }\n\n dequeue(): T | undefined {\n const current = this.#head;\n if (!current) {\n return;\n }\n\n this.#head = current.next;\n this.#size--;\n return current.value;\n }\n\n peek(): T | undefined {\n if (!this.#head) {\n return;\n }\n\n return this.#head.value;\n\n // TODO: Node.js 18.\n // return this.#head?.value;\n }\n\n clear(): void {\n this.#head = undefined;\n this.#tail = undefined;\n this.#size = 0;\n }\n\n get size(): number {\n return this.#size;\n }\n\n *[Symbol.iterator](): Generator<T, void, unknown> {\n let current = this.#head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n *drain(): Generator<T | undefined, void, unknown> {\n while (this.#head) {\n yield this.dequeue();\n }\n }\n}\n\nexport const pLimit = (concurrency: number) => {\n validateConcurrency(concurrency);\n\n const queue = new Queue<() => void>();\n let activeCount = 0;\n\n const idleWaiters: Array<() => void> = [];\n const notifyIdleIfNeeded = (): void => {\n if (activeCount === 0 && queue.size === 0) {\n while (idleWaiters.length) idleWaiters.pop()?.();\n }\n };\n\n const resumeNext = (): void => {\n // Process the next queued function if we're under the concurrency limit\n if (activeCount < concurrency && queue.size > 0) {\n activeCount++;\n queue.dequeue()?.();\n }\n };\n\n const next = (): void => {\n activeCount--;\n resumeNext();\n };\n\n const run = async (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): Promise<void> => {\n // Execute the function and capture the result promise\n const result = (async () => fn(...arguments_))();\n\n // Resolve immediately with the promise (don't wait for completion)\n resolve(result);\n\n // Wait for the function to complete (success or failure)\n // We catch errors here to prevent unhandled rejections,\n // but the original promise rejection is preserved for the caller\n try {\n await result;\n } catch {}\n\n // Decrement active count and process next queued function\n next();\n };\n\n const enqueue = (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): void => {\n // Queue the internal resolve function instead of the run function\n // to preserve the asynchronous execution context.\n new Promise<void>((internalResolve) => {\n queue.enqueue(internalResolve);\n }).then(run.bind(undefined, fn, resolve, arguments_));\n\n // Start processing immediately if we haven't reached the concurrency limit\n if (activeCount < concurrency) {\n resumeNext();\n }\n };\n\n const generator = (\n fn: (...args: any[]) => Promise<any>,\n ...arguments_: any[]\n ): Promise<any> =>\n new Promise<any>((resolve) => {\n enqueue(fn, resolve, arguments_);\n });\n\n Object.defineProperties(generator, {\n activeCount: {\n get: () => activeCount,\n },\n pendingCount: {\n get: () => queue.size,\n },\n clearQueue: {\n value() {\n queue.clear();\n notifyIdleIfNeeded();\n },\n },\n concurrency: {\n get: () => concurrency,\n\n set(newConcurrency: number) {\n validateConcurrency(newConcurrency);\n concurrency = newConcurrency;\n\n queueMicrotask(() => {\n while (activeCount < concurrency && queue.size > 0) {\n resumeNext();\n }\n });\n },\n },\n map: {\n async value<T, R>(\n array: T[],\n fn: (value: T, index: number) => Promise<R>\n ): Promise<R[]> {\n const promises = array.map((value, index) => this(fn, value, index));\n return Promise.all(promises);\n },\n },\n onIdle: {\n /**\n * Resolves when `activeCount === 0` and the queue is empty.\n * Use this to wait for completion without holding a list of Promises.\n */\n value(): Promise<void> {\n if (activeCount === 0 && queue.size === 0) return Promise.resolve();\n return new Promise<void>((resolve) => idleWaiters.push(resolve));\n },\n },\n });\n\n return generator;\n};\n\nconst validateConcurrency = (concurrency: number): void => {\n if (\n !(\n (Number.isInteger(concurrency) ||\n concurrency === Number.POSITIVE_INFINITY) &&\n concurrency > 0\n )\n ) {\n throw new TypeError('Expected `concurrency` to be a number from 1 and up');\n }\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveObjectPromises.mjs","names":[],"sources":["../../../src/utils/resolveObjectPromises.ts"],"sourcesContent":["/**\n * A more \"unified\" approach where each type (function, array, object, primitive)\n * is handled inside the main recursive body.\n */\nexport const resolveObjectPromises = async <T = unknown>(\n entry: any\n): Promise<T> => {\n // Check if entry is a Promise (Thenable)\n if (entry && typeof entry.then === 'function') {\n const awaited = await entry;\n return resolveObjectPromises(awaited);\n }\n\n // If entry is a function, invoke it and process the result\n if (typeof entry === 'function') {\n const result = entry();\n return resolveObjectPromises(result);\n }\n\n if (Array.isArray(entry)) {\n return Promise.all(\n entry.map(async (item) => resolveObjectPromises(item))\n ) as unknown as T;\n }\n\n // Handle plain objects (but not arrays)\n if (entry && typeof entry === 'object') {\n // Arrays are handled in the `Array.isArray` branch above, so we know `entry` is a plain object here.\n\n const result: Record<string, any> = {};\n\n // Iterate over keys **sequentially** to make sure the insertion order of the\n // resulting object matches the original key order. Using `Promise.all` here\n // could lead to out-of-order insertions when asynchronous resolutions\n // finish at different times.\n for (const key of Object.keys(entry)) {\n result[key] = await resolveObjectPromises(entry[key]);\n }\n\n return result as T;\n }\n\n return entry as T;\n};\n"],"mappings":";;;;;AAIA,MAAa,wBAAwB,OACnC,UACe;AAEf,KAAI,SAAS,OAAO,MAAM,SAAS,WAEjC,QAAO,sBADS,MAAM,MACe;AAIvC,KAAI,OAAO,UAAU,WAEnB,QAAO,sBADQ,OAAO,CACc;AAGtC,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,QAAQ,IACb,MAAM,IAAI,OAAO,SAAS,sBAAsB,KAAK,CAAC,CACvD;AAIH,KAAI,SAAS,OAAO,UAAU,UAAU;EAGtC,MAAM,SAA8B,EAAE;AAMtC,OAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,QAAO,OAAO,MAAM,sBAAsB,MAAM,KAAK;AAGvD,SAAO;;AAGT,QAAO"}
1
+ {"version":3,"file":"resolveObjectPromises.mjs","names":[],"sources":["../../../src/utils/resolveObjectPromises.ts"],"sourcesContent":["/**\n * A more \"unified\" approach where each type (function, array, object, primitive)\n * is handled inside the main recursive body.\n */\nexport const resolveObjectPromises = async <T = unknown>(\n entry: any\n): Promise<T> => {\n // Check if entry is a Promise (Thenable)\n if (entry && typeof entry.then === 'function') {\n const awaited = await entry;\n return resolveObjectPromises(awaited);\n }\n\n // If entry is a function, invoke it and process the result\n if (typeof entry === 'function') {\n const result = entry();\n return resolveObjectPromises(result);\n }\n\n if (Array.isArray(entry)) {\n return Promise.all(\n entry.map(async (item) => resolveObjectPromises(item))\n ) as unknown as T;\n }\n\n // Handle plain objects (but not arrays)\n if (entry && typeof entry === 'object') {\n // Arrays are handled in the `Array.isArray` branch above, so we know `entry` is a plain object here.\n\n const result: Record<string, any> = {};\n\n // Iterate over keys **sequentially** to make sure the insertion order of the\n // resulting object matches the original key order. Using `Promise.all` here\n // could lead to out-of-order insertions when asynchronous resolutions\n // finish at different times.\n for (const key of Object.keys(entry)) {\n result[key] = await resolveObjectPromises(entry[key]);\n }\n\n return result as T;\n }\n\n return entry as T;\n};\n"],"mappings":";;;;;AAIA,MAAa,wBAAwB,OACnC,UACe;AAEf,KAAI,SAAS,OAAO,MAAM,SAAS,WAEjC,QAAO,sBAAsB,MADP,MACe;AAIvC,KAAI,OAAO,UAAU,WAEnB,QAAO,sBADQ,OACoB,CAAC;AAGtC,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,QAAQ,IACb,MAAM,IAAI,OAAO,SAAS,sBAAsB,KAAK,CAAC,CACvD;AAIH,KAAI,SAAS,OAAO,UAAU,UAAU;EAGtC,MAAM,SAA8B,EAAE;AAMtC,OAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,QAAO,OAAO,MAAM,sBAAsB,MAAM,KAAK;AAGvD,SAAO;;AAGT,QAAO"}