@intlayer/engine 9.5.12 → 9.7.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 (169) hide show
  1. package/dist/assets/installSkills/skills/cli.md +28 -1
  2. package/dist/assets/installSkills/skills/compat.md +1 -1
  3. package/dist/assets/installSkills/skills/dev-tools.md +8 -6
  4. package/dist/cjs/build.cjs +12 -2
  5. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs +12 -11
  6. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
  7. package/dist/cjs/buildIntlayerDictionary/index.cjs +4 -1
  8. package/dist/cjs/buildIntlayerDictionary/rebuildUnmergedDictionaries.cjs +23 -0
  9. package/dist/cjs/buildIntlayerDictionary/rebuildUnmergedDictionaries.cjs.map +1 -0
  10. package/dist/cjs/cli.cjs +12 -0
  11. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  12. package/dist/cjs/handleAdditionalContentDeclarationFile.cjs +1 -1
  13. package/dist/cjs/handleContentDeclarationFileChange.cjs +1 -1
  14. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +1 -1
  15. package/dist/cjs/init/cms.cjs +18 -0
  16. package/dist/cjs/init/cms.cjs.map +1 -1
  17. package/dist/cjs/init/index.cjs +23 -10
  18. package/dist/cjs/init/index.cjs.map +1 -1
  19. package/dist/cjs/init/utils/configManipulation.cjs +28 -0
  20. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  21. package/dist/cjs/init/utils/contentLayout.cjs +61 -0
  22. package/dist/cjs/init/utils/contentLayout.cjs.map +1 -0
  23. package/dist/cjs/init/utils/index.cjs +1 -0
  24. package/dist/cjs/init/utils/packageManager.cjs +1 -1
  25. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  26. package/dist/cjs/installMCP/installMCP.cjs +35 -25
  27. package/dist/cjs/installMCP/installMCP.cjs.map +1 -1
  28. package/dist/cjs/installSkills/index.cjs +26 -1
  29. package/dist/cjs/installSkills/index.cjs.map +1 -1
  30. package/dist/cjs/listDictionariesPath.cjs +2 -5
  31. package/dist/cjs/listDictionariesPath.cjs.map +1 -1
  32. package/dist/cjs/listGitFiles.cjs +3 -5
  33. package/dist/cjs/listGitFiles.cjs.map +1 -1
  34. package/dist/cjs/listProjects.cjs +1 -2
  35. package/dist/cjs/listProjects.cjs.map +1 -1
  36. package/dist/cjs/loadDictionaries/index.cjs +1 -1
  37. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +1 -1
  38. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  39. package/dist/cjs/utils/buildComponentFilesList.cjs +18 -30
  40. package/dist/cjs/utils/buildComponentFilesList.cjs.map +1 -1
  41. package/dist/cjs/utils/chunkJSON.cjs +1 -1
  42. package/dist/cjs/utils/chunkJSON.cjs.map +1 -1
  43. package/dist/cjs/utils/index.cjs +2 -0
  44. package/dist/cjs/utils/isDirectoryExcluded.cjs +36 -0
  45. package/dist/cjs/utils/isDirectoryExcluded.cjs.map +1 -0
  46. package/dist/cjs/watcher.cjs +5 -2
  47. package/dist/cjs/watcher.cjs.map +1 -1
  48. package/dist/cjs/writeConfiguration/index.cjs +23 -0
  49. package/dist/cjs/writeConfiguration/index.cjs.map +1 -1
  50. package/dist/cjs/writeContentDeclaration/index.cjs +6 -0
  51. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs +20 -13
  52. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs.map +1 -1
  53. package/dist/cjs/writeContentDeclaration/renderContentDeclaration.cjs +213 -0
  54. package/dist/cjs/writeContentDeclaration/renderContentDeclaration.cjs.map +1 -0
  55. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +5 -51
  56. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs.map +1 -1
  57. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +2 -31
  58. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs.map +1 -1
  59. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +2 -8
  60. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs.map +1 -1
  61. package/dist/esm/build.mjs +7 -5
  62. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs +12 -12
  63. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs.map +1 -1
  64. package/dist/esm/buildIntlayerDictionary/index.mjs +3 -2
  65. package/dist/esm/buildIntlayerDictionary/rebuildUnmergedDictionaries.mjs +22 -0
  66. package/dist/esm/buildIntlayerDictionary/rebuildUnmergedDictionaries.mjs.map +1 -0
  67. package/dist/esm/cli.mjs +5 -3
  68. package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
  69. package/dist/esm/handleAdditionalContentDeclarationFile.mjs +1 -1
  70. package/dist/esm/handleContentDeclarationFileChange.mjs +1 -1
  71. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +1 -1
  72. package/dist/esm/init/cms.mjs +19 -2
  73. package/dist/esm/init/cms.mjs.map +1 -1
  74. package/dist/esm/init/index.mjs +24 -11
  75. package/dist/esm/init/index.mjs.map +1 -1
  76. package/dist/esm/init/utils/configManipulation.mjs +28 -1
  77. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  78. package/dist/esm/init/utils/contentLayout.mjs +58 -0
  79. package/dist/esm/init/utils/contentLayout.mjs.map +1 -0
  80. package/dist/esm/init/utils/index.mjs +2 -2
  81. package/dist/esm/init/utils/packageManager.mjs +1 -1
  82. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  83. package/dist/esm/installMCP/installMCP.mjs +35 -25
  84. package/dist/esm/installMCP/installMCP.mjs.map +1 -1
  85. package/dist/esm/installSkills/index.mjs +27 -3
  86. package/dist/esm/installSkills/index.mjs.map +1 -1
  87. package/dist/esm/listDictionariesPath.mjs +2 -5
  88. package/dist/esm/listDictionariesPath.mjs.map +1 -1
  89. package/dist/esm/listGitFiles.mjs +1 -1
  90. package/dist/esm/listGitFiles.mjs.map +1 -1
  91. package/dist/esm/listProjects.mjs +1 -1
  92. package/dist/esm/listProjects.mjs.map +1 -1
  93. package/dist/esm/loadDictionaries/index.mjs +1 -1
  94. package/dist/esm/loadDictionaries/loadDictionaries.mjs +1 -1
  95. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  96. package/dist/esm/utils/buildComponentFilesList.mjs +19 -31
  97. package/dist/esm/utils/buildComponentFilesList.mjs.map +1 -1
  98. package/dist/esm/utils/chunkJSON.mjs +1 -1
  99. package/dist/esm/utils/chunkJSON.mjs.map +1 -1
  100. package/dist/esm/utils/index.mjs +2 -1
  101. package/dist/esm/utils/isDirectoryExcluded.mjs +35 -0
  102. package/dist/esm/utils/isDirectoryExcluded.mjs.map +1 -0
  103. package/dist/esm/utils/runParallel/pidTree.mjs +3 -3
  104. package/dist/esm/utils/runParallel/pidTree.mjs.map +1 -1
  105. package/dist/esm/utils/runParallel/ps.mjs +2 -2
  106. package/dist/esm/utils/runParallel/ps.mjs.map +1 -1
  107. package/dist/esm/utils/runParallel/wmic.mjs +2 -2
  108. package/dist/esm/utils/runParallel/wmic.mjs.map +1 -1
  109. package/dist/esm/watcher.mjs +5 -2
  110. package/dist/esm/watcher.mjs.map +1 -1
  111. package/dist/esm/writeConfiguration/index.mjs +23 -1
  112. package/dist/esm/writeConfiguration/index.mjs.map +1 -1
  113. package/dist/esm/writeContentDeclaration/index.mjs +2 -1
  114. package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs +20 -13
  115. package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs.map +1 -1
  116. package/dist/esm/writeContentDeclaration/renderContentDeclaration.mjs +208 -0
  117. package/dist/esm/writeContentDeclaration/renderContentDeclaration.mjs.map +1 -0
  118. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +5 -51
  119. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs.map +1 -1
  120. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +2 -31
  121. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs.map +1 -1
  122. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +2 -8
  123. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs.map +1 -1
  124. package/dist/types/build.d.ts +5 -3
  125. package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts +6 -0
  126. package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts.map +1 -1
  127. package/dist/types/buildIntlayerDictionary/index.d.ts +3 -2
  128. package/dist/types/buildIntlayerDictionary/rebuildUnmergedDictionaries.d.ts +14 -0
  129. package/dist/types/buildIntlayerDictionary/rebuildUnmergedDictionaries.d.ts.map +1 -0
  130. package/dist/types/cli.d.ts +6 -4
  131. package/dist/types/fetchDistantDictionaries.d.ts +1 -1
  132. package/dist/types/fetchDistantDictionaries.d.ts.map +1 -1
  133. package/dist/types/init/cms.d.ts +6 -0
  134. package/dist/types/init/cms.d.ts.map +1 -1
  135. package/dist/types/init/index.d.ts +15 -14
  136. package/dist/types/init/index.d.ts.map +1 -1
  137. package/dist/types/init/utils/configManipulation.d.ts +8 -0
  138. package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
  139. package/dist/types/init/utils/contentLayout.d.ts +42 -0
  140. package/dist/types/init/utils/contentLayout.d.ts.map +1 -0
  141. package/dist/types/init/utils/index.d.ts +2 -2
  142. package/dist/types/init/utils/packageManager.d.ts +9 -3
  143. package/dist/types/init/utils/packageManager.d.ts.map +1 -1
  144. package/dist/types/installMCP/installMCP.d.ts +4 -0
  145. package/dist/types/installMCP/installMCP.d.ts.map +1 -1
  146. package/dist/types/installSkills/index.d.ts +6 -0
  147. package/dist/types/installSkills/index.d.ts.map +1 -1
  148. package/dist/types/listDictionariesPath.d.ts +1 -1
  149. package/dist/types/listDictionariesPath.d.ts.map +1 -1
  150. package/dist/types/loadDictionaries/loadRemoteDictionaries.d.ts +1 -1
  151. package/dist/types/loadDictionaries/loadRemoteDictionaries.d.ts.map +1 -1
  152. package/dist/types/utils/buildComponentFilesList.d.ts +6 -6
  153. package/dist/types/utils/buildComponentFilesList.d.ts.map +1 -1
  154. package/dist/types/utils/chunkJSON.d.ts.map +1 -1
  155. package/dist/types/utils/index.d.ts +2 -1
  156. package/dist/types/utils/isDirectoryExcluded.d.ts +15 -0
  157. package/dist/types/utils/isDirectoryExcluded.d.ts.map +1 -0
  158. package/dist/types/watcher.d.ts.map +1 -1
  159. package/dist/types/writeConfiguration/index.d.ts +13 -0
  160. package/dist/types/writeConfiguration/index.d.ts.map +1 -1
  161. package/dist/types/writeContentDeclaration/index.d.ts +2 -1
  162. package/dist/types/writeContentDeclaration/processContentDeclarationContent.d.ts +8 -2
  163. package/dist/types/writeContentDeclaration/processContentDeclarationContent.d.ts.map +1 -1
  164. package/dist/types/writeContentDeclaration/renderContentDeclaration.d.ts +61 -0
  165. package/dist/types/writeContentDeclaration/renderContentDeclaration.d.ts.map +1 -0
  166. package/dist/types/writeContentDeclaration/writeContentDeclaration.d.ts.map +1 -1
  167. package/dist/types/writeContentDeclaration/writeMarkdownFile.d.ts.map +1 -1
  168. package/dist/types/writeContentDeclaration/writeYamlFile.d.ts.map +1 -1
  169. package/package.json +18 -10
@@ -1 +1 @@
1
- {"version":3,"file":"listGitFiles.cjs","names":["simpleGit","getAppLogger","join","readFileSync"],"sources":["../../src/listGitFiles.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport simpleGit from 'simple-git';\n\nexport type DiffMode = 'gitDiff' | 'uncommitted' | 'unpushed' | 'untracked';\n\nconst getGitRootDir = async (): Promise<string | null> => {\n try {\n const git = simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (error) {\n const appLogger = getAppLogger({ log });\n appLogger(`Error getting git root directory: ${error}`, {\n level: 'error',\n });\n return null;\n }\n};\n\nexport type ListGitFilesOptions = {\n mode: DiffMode[];\n baseRef?: string;\n currentRef?: string;\n absolute?: boolean;\n};\n\nexport const listGitFiles = async ({\n mode,\n baseRef = 'origin/main',\n currentRef = 'HEAD', // HEAD points to the current branch's latest commit\n absolute = true,\n}: ListGitFilesOptions) => {\n try {\n const git = simpleGit();\n const diff: Set<string> = new Set();\n\n if (mode.includes('untracked')) {\n const status = await git.status();\n status.not_added.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('uncommitted')) {\n // Get uncommitted changes\n const uncommittedDiff = await git.diff(['--name-only', 'HEAD']);\n\n const uncommittedFiles = uncommittedDiff.split('\\n').filter(Boolean);\n\n uncommittedFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('unpushed')) {\n // Get unpushed commits\n const unpushedDiff = await git.diff(['--name-only', '@{push}...HEAD']);\n\n const unpushedFiles = unpushedDiff.split('\\n').filter(Boolean);\n\n unpushedFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('gitDiff')) {\n // Get the base branch (usually main/master) from CI environment\n\n await git.fetch(baseRef);\n\n const diffBranch = await git.diff([\n '--name-only',\n `${baseRef}...${currentRef}`,\n ]);\n\n const gitDiffFiles = diffBranch.split('\\n').filter(Boolean);\n\n gitDiffFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (absolute) {\n const gitRootDir = await getGitRootDir();\n if (!gitRootDir) {\n return [];\n }\n return Array.from(diff).map((file) => join(gitRootDir, file));\n }\n\n return Array.from(diff);\n } catch (error) {\n console.warn('Failed to get changes list:', error);\n }\n};\n\nexport type ListGitLinesOptions = {\n mode: DiffMode[];\n baseRef?: string;\n currentRef?: string;\n};\n\nexport const listGitLines = async (\n filePath: string,\n {\n mode,\n baseRef = 'origin/main',\n currentRef = 'HEAD', // HEAD points to the current branch's latest commit\n }: ListGitLinesOptions\n): Promise<number[]> => {\n const git = simpleGit();\n // We collect **line numbers** (1-based) that were modified/added by the diff.\n // Using a Set ensures uniqueness when the same line is reported by several modes.\n const changedLines: Set<number> = new Set();\n\n /**\n * Extracts line numbers from a diff generated with `--unified=0`.\n * Each hunk header looks like: @@ -<oldStart>,<oldCount> +<newStart>,<newCount> @@\n * We consider both the \"+\" (new) side for additions and the \"-\" (old) side for deletions.\n * For deletions, we add the line before and after the deletion point in the current file.\n */\n const collectLinesFromDiff = (diffOutput: string) => {\n const hunkRegex = /@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/g;\n let match: RegExpExecArray | null;\n\n // biome-ignore lint/suspicious/noAssignInExpressions: Used in while loop condition\n while ((match = hunkRegex.exec(diffOutput)) !== null) {\n const oldCount = match[2] ? Number(match[2]) : 1;\n const newStart = Number(match[3]);\n const newCount = match[4] ? Number(match[4]) : 1;\n\n // Handle additions/modifications (+ side)\n if (newCount > 0) {\n for (let i = 0; i < newCount; i++) {\n changedLines.add(newStart + i);\n }\n }\n\n // Handle deletions (- side)\n if (oldCount > 0 && newCount === 0) {\n // For deletions, add the line before and after the deletion point\n // The deletion point in the new file is at newStart\n if (newStart > 1) {\n changedLines.add(newStart - 1); // Line before deletion\n }\n changedLines.add(newStart); // Line after deletion (if it exists)\n }\n }\n };\n\n // 1. Handle untracked files – when a file is untracked its entire content is new.\n if (mode.includes('untracked')) {\n const status = await git.status();\n const isUntracked = status.not_added.includes(filePath);\n if (isUntracked) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n content.split('\\n').forEach((_, idx) => {\n changedLines.add(idx + 1);\n });\n } catch {\n // ignore read errors – file may have been deleted, etc.\n }\n }\n }\n\n // 2. Uncommitted changes (working tree vs HEAD)\n if (mode.includes('uncommitted')) {\n const diffOutput = await git.diff(['--unified=0', 'HEAD', '--', filePath]);\n collectLinesFromDiff(diffOutput);\n }\n\n // 3. Unpushed commits – compare local branch to its upstream\n if (mode.includes('unpushed')) {\n const diffOutput = await git.diff([\n '--unified=0',\n '@{push}...HEAD',\n '--',\n filePath,\n ]);\n collectLinesFromDiff(diffOutput);\n }\n\n // 4. Regular git diff between baseRef and currentRef (e.g., CI pull-request diff)\n if (mode.includes('gitDiff')) {\n await git.fetch(baseRef);\n const diffOutput = await git.diff([\n '--unified=0',\n `${baseRef}...${currentRef}`,\n '--',\n filePath,\n ]);\n collectLinesFromDiff(diffOutput);\n }\n\n // Return the list sorted for convenience\n return Array.from(changedLines).sort((a, b) => a - b);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"listGitFiles.cjs","names":["simpleGit","getAppLogger","join","readFileSync"],"sources":["../../src/listGitFiles.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport { simpleGit } from 'simple-git';\n\nexport type DiffMode = 'gitDiff' | 'uncommitted' | 'unpushed' | 'untracked';\n\nconst getGitRootDir = async (): Promise<string | null> => {\n try {\n const git = simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (error) {\n const appLogger = getAppLogger({ log });\n appLogger(`Error getting git root directory: ${error}`, {\n level: 'error',\n });\n return null;\n }\n};\n\nexport type ListGitFilesOptions = {\n mode: DiffMode[];\n baseRef?: string;\n currentRef?: string;\n absolute?: boolean;\n};\n\nexport const listGitFiles = async ({\n mode,\n baseRef = 'origin/main',\n currentRef = 'HEAD', // HEAD points to the current branch's latest commit\n absolute = true,\n}: ListGitFilesOptions) => {\n try {\n const git = simpleGit();\n const diff: Set<string> = new Set();\n\n if (mode.includes('untracked')) {\n const status = await git.status();\n status.not_added.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('uncommitted')) {\n // Get uncommitted changes\n const uncommittedDiff = await git.diff(['--name-only', 'HEAD']);\n\n const uncommittedFiles = uncommittedDiff.split('\\n').filter(Boolean);\n\n uncommittedFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('unpushed')) {\n // Get unpushed commits\n const unpushedDiff = await git.diff(['--name-only', '@{push}...HEAD']);\n\n const unpushedFiles = unpushedDiff.split('\\n').filter(Boolean);\n\n unpushedFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (mode.includes('gitDiff')) {\n // Get the base branch (usually main/master) from CI environment\n\n await git.fetch(baseRef);\n\n const diffBranch = await git.diff([\n '--name-only',\n `${baseRef}...${currentRef}`,\n ]);\n\n const gitDiffFiles = diffBranch.split('\\n').filter(Boolean);\n\n gitDiffFiles.forEach((file) => {\n diff.add(file);\n });\n }\n\n if (absolute) {\n const gitRootDir = await getGitRootDir();\n if (!gitRootDir) {\n return [];\n }\n return Array.from(diff).map((file) => join(gitRootDir, file));\n }\n\n return Array.from(diff);\n } catch (error) {\n console.warn('Failed to get changes list:', error);\n }\n};\n\nexport type ListGitLinesOptions = {\n mode: DiffMode[];\n baseRef?: string;\n currentRef?: string;\n};\n\nexport const listGitLines = async (\n filePath: string,\n {\n mode,\n baseRef = 'origin/main',\n currentRef = 'HEAD', // HEAD points to the current branch's latest commit\n }: ListGitLinesOptions\n): Promise<number[]> => {\n const git = simpleGit();\n // We collect **line numbers** (1-based) that were modified/added by the diff.\n // Using a Set ensures uniqueness when the same line is reported by several modes.\n const changedLines: Set<number> = new Set();\n\n /**\n * Extracts line numbers from a diff generated with `--unified=0`.\n * Each hunk header looks like: @@ -<oldStart>,<oldCount> +<newStart>,<newCount> @@\n * We consider both the \"+\" (new) side for additions and the \"-\" (old) side for deletions.\n * For deletions, we add the line before and after the deletion point in the current file.\n */\n const collectLinesFromDiff = (diffOutput: string) => {\n const hunkRegex = /@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/g;\n let match: RegExpExecArray | null;\n\n // biome-ignore lint/suspicious/noAssignInExpressions: Used in while loop condition\n while ((match = hunkRegex.exec(diffOutput)) !== null) {\n const oldCount = match[2] ? Number(match[2]) : 1;\n const newStart = Number(match[3]);\n const newCount = match[4] ? Number(match[4]) : 1;\n\n // Handle additions/modifications (+ side)\n if (newCount > 0) {\n for (let i = 0; i < newCount; i++) {\n changedLines.add(newStart + i);\n }\n }\n\n // Handle deletions (- side)\n if (oldCount > 0 && newCount === 0) {\n // For deletions, add the line before and after the deletion point\n // The deletion point in the new file is at newStart\n if (newStart > 1) {\n changedLines.add(newStart - 1); // Line before deletion\n }\n changedLines.add(newStart); // Line after deletion (if it exists)\n }\n }\n };\n\n // 1. Handle untracked files – when a file is untracked its entire content is new.\n if (mode.includes('untracked')) {\n const status = await git.status();\n const isUntracked = status.not_added.includes(filePath);\n if (isUntracked) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n content.split('\\n').forEach((_, idx) => {\n changedLines.add(idx + 1);\n });\n } catch {\n // ignore read errors – file may have been deleted, etc.\n }\n }\n }\n\n // 2. Uncommitted changes (working tree vs HEAD)\n if (mode.includes('uncommitted')) {\n const diffOutput = await git.diff(['--unified=0', 'HEAD', '--', filePath]);\n collectLinesFromDiff(diffOutput);\n }\n\n // 3. Unpushed commits – compare local branch to its upstream\n if (mode.includes('unpushed')) {\n const diffOutput = await git.diff([\n '--unified=0',\n '@{push}...HEAD',\n '--',\n filePath,\n ]);\n collectLinesFromDiff(diffOutput);\n }\n\n // 4. Regular git diff between baseRef and currentRef (e.g., CI pull-request diff)\n if (mode.includes('gitDiff')) {\n await git.fetch(baseRef);\n const diffOutput = await git.diff([\n '--unified=0',\n `${baseRef}...${currentRef}`,\n '--',\n filePath,\n ]);\n collectLinesFromDiff(diffOutput);\n }\n\n // Return the list sorted for convenience\n return Array.from(changedLines).sort((a, b) => a - b);\n};\n"],"mappings":"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"}
@@ -5,7 +5,6 @@ let _intlayer_config_node = require("@intlayer/config/node");
5
5
  let fast_glob = require("fast-glob");
6
6
  fast_glob = require_runtime.__toESM(fast_glob);
7
7
  let simple_git = require("simple-git");
8
- simple_git = require_runtime.__toESM(simple_git);
9
8
 
10
9
  //#region src/listProjects.ts
11
10
  /**
@@ -14,7 +13,7 @@ simple_git = require_runtime.__toESM(simple_git);
14
13
  */
15
14
  const getGitRootDir = async (cwd) => {
16
15
  try {
17
- return (await (cwd ? (0, simple_git.default)(cwd) : (0, simple_git.default)()).revparse(["--show-toplevel"])).trim();
16
+ return (await (cwd ? (0, simple_git.simpleGit)(cwd) : (0, simple_git.simpleGit)()).revparse(["--show-toplevel"])).trim();
18
17
  } catch (_error) {
19
18
  return null;
20
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"listProjects.cjs","names":["simpleGit","configurationFilesCandidates","fg","dirname"],"sources":["../../src/listProjects.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { configurationFilesCandidates } from '@intlayer/config/node';\nimport fg from 'fast-glob';\nimport simpleGit from 'simple-git';\n\nexport type ListProjectsOptions = {\n /**\n * Base directory to search from\n * @default process.cwd()\n */\n baseDir?: string;\n /**\n * If true, search from the git root directory instead of baseDir\n * @default false\n */\n gitRoot?: boolean;\n};\n\n/**\n * Returns the git repository root directory, or `null` when the given\n * directory is not inside a git repository.\n */\nexport const getGitRootDir = async (cwd?: string): Promise<string | null> => {\n try {\n const git = cwd ? simpleGit(cwd) : simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (_error) {\n return null;\n }\n};\n\n/**\n * List all Intlayer projects by searching for configuration files\n *\n * @param options - Options for listing projects\n * @returns Array of absolute paths to project directories containing Intlayer config\n */\nexport const listProjects = async (\n options?: ListProjectsOptions\n): Promise<{ searchDir: string; projectsPath: string[] }> => {\n let searchDir = options?.baseDir ?? process.cwd();\n\n // If gitRoot option is enabled, try to get the git root directory\n if (options?.gitRoot) {\n const gitRootDir = await getGitRootDir(searchDir);\n if (gitRootDir) {\n searchDir = gitRootDir;\n }\n }\n\n // Build glob patterns for all config file candidates\n const configPatterns = configurationFilesCandidates.map(\n (fileName) => `**/${fileName}`\n );\n\n // Search for all config files\n const configFiles = await fg(configPatterns, {\n cwd: searchDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.git/**'],\n dot: true, // Include dot files like .intlayerrc\n });\n\n // Extract unique directory paths from config files\n const projectDirs = [...new Set(configFiles.map((file) => dirname(file)))];\n\n // Sort alphabetically for consistent output\n return { searchDir, projectsPath: projectDirs.sort() };\n};\n"],"mappings":";;;;;;;;;;;;;;AAsBA,MAAa,gBAAgB,OAAO,QAAyC;CAC3E,IAAI;EAGF,QAAO,OAFK,UAAMA,oBAAU,GAAG,QAAIA,oBAAU,EACpB,CAAC,SAAS,CAAC,iBAAiB,CAAC,EACxC,CAAC,KAAK;CACtB,SAAS,QAAQ;EACf,OAAO;CACT;AACF;;;;;;;AAQA,MAAa,eAAe,OAC1B,YAC2D;CAC3D,IAAI,YAAY,SAAS,WAAW,QAAQ,IAAI;CAGhD,IAAI,SAAS,SAAS;EACpB,MAAM,aAAa,MAAM,cAAc,SAAS;EAChD,IAAI,YACF,YAAY;CAEhB;CAGA,MAAM,iBAAiBC,mDAA6B,KACjD,aAAa,MAAM,UACtB;CAGA,MAAM,cAAc,UAAMC,mBAAG,gBAAgB;EAC3C,KAAK;EACL,UAAU;EACV,QAAQ,CAAC,sBAAsB,YAAY;EAC3C,KAAK;CACP,CAAC;CAGD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,KAAK,aAASC,mBAAQ,IAAI,CAAC,CAAC,CAAC;CAGzE,OAAO;EAAE;EAAW,cAAc,YAAY,KAAK;CAAE;AACvD"}
1
+ {"version":3,"file":"listProjects.cjs","names":["simpleGit","configurationFilesCandidates","fg","dirname"],"sources":["../../src/listProjects.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { configurationFilesCandidates } from '@intlayer/config/node';\nimport fg from 'fast-glob';\nimport { simpleGit } from 'simple-git';\n\nexport type ListProjectsOptions = {\n /**\n * Base directory to search from\n * @default process.cwd()\n */\n baseDir?: string;\n /**\n * If true, search from the git root directory instead of baseDir\n * @default false\n */\n gitRoot?: boolean;\n};\n\n/**\n * Returns the git repository root directory, or `null` when the given\n * directory is not inside a git repository.\n */\nexport const getGitRootDir = async (cwd?: string): Promise<string | null> => {\n try {\n const git = cwd ? simpleGit(cwd) : simpleGit();\n const rootDir = await git.revparse(['--show-toplevel']);\n return rootDir.trim();\n } catch (_error) {\n return null;\n }\n};\n\n/**\n * List all Intlayer projects by searching for configuration files\n *\n * @param options - Options for listing projects\n * @returns Array of absolute paths to project directories containing Intlayer config\n */\nexport const listProjects = async (\n options?: ListProjectsOptions\n): Promise<{ searchDir: string; projectsPath: string[] }> => {\n let searchDir = options?.baseDir ?? process.cwd();\n\n // If gitRoot option is enabled, try to get the git root directory\n if (options?.gitRoot) {\n const gitRootDir = await getGitRootDir(searchDir);\n if (gitRootDir) {\n searchDir = gitRootDir;\n }\n }\n\n // Build glob patterns for all config file candidates\n const configPatterns = configurationFilesCandidates.map(\n (fileName) => `**/${fileName}`\n );\n\n // Search for all config files\n const configFiles = await fg(configPatterns, {\n cwd: searchDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.git/**'],\n dot: true, // Include dot files like .intlayerrc\n });\n\n // Extract unique directory paths from config files\n const projectDirs = [...new Set(configFiles.map((file) => dirname(file)))];\n\n // Sort alphabetically for consistent output\n return { searchDir, projectsPath: projectDirs.sort() };\n};\n"],"mappings":";;;;;;;;;;;;;AAsBA,MAAa,gBAAgB,OAAO,QAAyC;CAC3E,IAAI;EAGF,QAAO,OAFK,UAAMA,sBAAU,GAAG,QAAIA,sBAAU,EACpB,CAAC,SAAS,CAAC,iBAAiB,CAAC,EACxC,CAAC,KAAK;CACtB,SAAS,QAAQ;EACf,OAAO;CACT;AACF;;;;;;;AAQA,MAAa,eAAe,OAC1B,YAC2D;CAC3D,IAAI,YAAY,SAAS,WAAW,QAAQ,IAAI;CAGhD,IAAI,SAAS,SAAS;EACpB,MAAM,aAAa,MAAM,cAAc,SAAS;EAChD,IAAI,YACF,YAAY;CAEhB;CAGA,MAAM,iBAAiBC,mDAA6B,KACjD,aAAa,MAAM,UACtB;CAGA,MAAM,cAAc,UAAMC,mBAAG,gBAAgB;EAC3C,KAAK;EACL,UAAU;EACV,QAAQ,CAAC,sBAAsB,YAAY;EAC3C,KAAK;CACP,CAAC;CAGD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,YAAY,KAAK,aAASC,mBAAQ,IAAI,CAAC,CAAC,CAAC;CAGzE,OAAO;EAAE;EAAW,cAAc,YAAY,KAAK;CAAE;AACvD"}
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_loadDictionaries_loadContentDeclaration = require('./loadContentDeclaration.cjs');
3
+ const require_loadDictionaries_loadLocalDictionaries = require('./loadLocalDictionaries.cjs');
3
4
  const require_loadDictionaries_loadRemoteDictionaries = require('./loadRemoteDictionaries.cjs');
4
5
  const require_loadDictionaries_loadDictionaries = require('./loadDictionaries.cjs');
5
- const require_loadDictionaries_loadLocalDictionaries = require('./loadLocalDictionaries.cjs');
6
6
 
7
7
  exports.ensureIntlayerBundle = require_loadDictionaries_loadContentDeclaration.ensureIntlayerBundle;
8
8
  exports.formatDistantDictionaries = require_loadDictionaries_loadRemoteDictionaries.formatDistantDictionaries;
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_filterInvalidDictionaries = require('../filterInvalidDictionaries.cjs');
4
- const require_formatDictionary = require('../formatDictionary.cjs');
5
4
  const require_loadDictionaries_loadContentDeclaration = require('./loadContentDeclaration.cjs');
5
+ const require_formatDictionary = require('../formatDictionary.cjs');
6
6
  const require_loadDictionaries_loadRemoteDictionaries = require('./loadRemoteDictionaries.cjs');
7
7
  const require_loadDictionaries_log = require('./log.cjs');
8
8
  let _intlayer_config_colors = require("@intlayer/config/colors");
@@ -1 +1 @@
1
- {"version":3,"file":"loadRemoteDictionaries.cjs","names":["getConfiguration","getRemoteDictionaries","sortAlphabetically"],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend is not build yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getRemoteDictionaries } from '@intlayer/dictionaries-entry/remote';\nimport type {\n Dictionary,\n DictionaryId,\n DictionaryKey,\n} from '@intlayer/types/dictionary';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\nimport type { DictionariesStatus } from './loadDictionaries';\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 // Lazy: the CMS client is only needed when remote credentials are set\n const { createRemoteDictionaryClient, fetchDistantDictionaries } =\n await import('./remoteDictionaryClient');\n\n const dictionary = createRemoteDictionaryClient(configuration);\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await 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 = dictionary.id\n ? distantDictionaryUpdateTimeStamp[dictionary.id]?.updatedAt\n : undefined;\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 // Several qualified dictionaries can share a key, so keys are deduplicated:\n // one request per key already returns all of its siblings.\n const orderedDistantDictionaryKeys = [\n ...new Set(dictionariesIdToFetch.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 // Fetching by key also returns the up-to-date siblings of a stale\n // dictionary, so drop the cached copies the remote just sent back.\n const fetchedDictionaryIds = new Set(\n distantDictionaries.map((dictionary) => dictionary.id)\n );\n\n const notRefetchedCachedDictionaries = cachedDictionaries.filter(\n (dictionary) => !fetchedDictionaryIds.has(dictionary.id)\n );\n\n return [...notRefetchedCachedDictionaries, ...distantDictionaries];\n } catch (error) {\n options?.onError?.(error as Error);\n return [];\n } finally {\n options?.onStopRemoteCheck?.();\n }\n};\n"],"mappings":";;;;;;AAYA,MAAa,6BACX,iBAEA,aAAa,KAAK,UAAU;CAC1B,GAAG;CACH,SAAS,GAAG,KAAK,IAAI,YAAY,KAAK;CACtC,UAAU;AACZ,EAAE;AAEJ,MAAa,yBAAyB,OACpC,oBAAgBA,wCAAiB,GACjC,gBACA,YAK0B;CAC1B,MAAM,EAAE,WAAW;CACnB,MAAM,+BAA2BC,2DAAsB,aAAa;CAIpE,IAAI,CAF0B,QAAQ,OAAO,YAAY,OAAO,YAEvC,GAAG,OAAO,CAAC;CAEpC,IAAI;EACF,SAAS,qBAAqB;EAG9B,MAAM,EAAE,8BAA8B,6BACpC,2CAAM;EAQR,MAAM,oCAGK,MATQ,6BAA6B,aAI/B,CAAC,CAAC,+BAA+B,EAKd,CAAC;EAErC,IAAI,CAAC,kCACH,MAAM,IAAI,MAAM,+BAA+B;EAGjD,MAAM,wBAAwB,OAAO,QACnC,gCACF,CAAC,CAAC,QAAQ,CAAC,cAAc,UAAU;GAEjC,IAAI,CAAC,KAAK,WAAW,OAAO;GAG5B,MAAM,QAAgC,yBACpC,KAAK,IACN,EAAE,MAAM,eAAe,WAAW,OAAO,YAAY;GACtD,IAAI,CAAC,OAAO,OAAO;GAEnB,MAAM,oBAAqB,OAAe;GAK1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GAGR,IAAI,OAAO,mBAAmB,UAAU,OAAO;GAE/C,OAAO,KAAK,YAAY;EAC1B,CAAC;EAMD,MAAM,qBAJgD,OAAO,OAC3D,wBACF,CAAC,CAAC,KAG2B,CAAC,CAAC,QAAQ,eAAe;GAClD,MAAM,kBAAkB,WAAW,KAC/B,iCAAiC,WAAW,GAAG,EAAE,YACjD;GAEJ,MAAM,oBAAoB,WAAW;GAErC,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GAGR,OACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;EAEtB,CAAC;EAGH,IAAI,mBAAmB,SAAS,GAC9B,iBACE,mBAAmB,KAAK,gBAAgB;GACtC,eAAe,WAAW;GAC1B,MAAM;GACN,QAAQ;EACV,EAAE,CACJ;EAKF,MAAM,+BAA+B,CACnC,GAAG,IAAI,IAAI,sBAAsB,KAAK,GAAG,UAAU,KAAK,GAAG,CAAC,CAC9D,CAAC,CAAC,KAAKC,mDAAkB;EAGzB,IAAI,6BAA6B,SAAS,GACxC,iBACE,6BAA6B,KAAK,SAAS;GACzC,eAAe;GACf,MAAM;GACN,QAAQ;EACV,EAAE,CACJ;EAGF,MAAM,0BAA0B,MAAM,yBACpC,EACE,gBAAgB,6BAClB,GACA,cACF;EAEA,MAAM,sBAAoC,0BACxC,uBACF;EAIA,MAAM,uBAAuB,IAAI,IAC/B,oBAAoB,KAAK,eAAe,WAAW,EAAE,CACvD;EAMA,OAAO,CAAC,GAJ+B,mBAAmB,QACvD,eAAe,CAAC,qBAAqB,IAAI,WAAW,EAAE,CAGjB,GAAG,GAAG,mBAAmB;CACnE,SAAS,OAAO;EACd,SAAS,UAAU,KAAc;EACjC,OAAO,CAAC;CACV,UAAU;EACR,SAAS,oBAAoB;CAC/B;AACF"}
1
+ {"version":3,"file":"loadRemoteDictionaries.cjs","names":["getConfiguration","getRemoteDictionaries","sortAlphabetically"],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"sourcesContent":["import type { DictionaryAPI } from '@intlayer/api';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getRemoteDictionaries } from '@intlayer/dictionaries-entry/remote';\nimport type {\n Dictionary,\n DictionaryId,\n DictionaryKey,\n} from '@intlayer/types/dictionary';\nimport { sortAlphabetically } from '../utils/sortAlphabetically';\nimport type { DictionariesStatus } from './loadDictionaries';\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 // Lazy: the CMS client is only needed when remote credentials are set\n const { createRemoteDictionaryClient, fetchDistantDictionaries } =\n await import('./remoteDictionaryClient');\n\n const dictionary = createRemoteDictionaryClient(configuration);\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await 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 = dictionary.id\n ? distantDictionaryUpdateTimeStamp[dictionary.id]?.updatedAt\n : undefined;\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 // Several qualified dictionaries can share a key, so keys are deduplicated:\n // one request per key already returns all of its siblings.\n const orderedDistantDictionaryKeys = [\n ...new Set(dictionariesIdToFetch.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 // Fetching by key also returns the up-to-date siblings of a stale\n // dictionary, so drop the cached copies the remote just sent back.\n const fetchedDictionaryIds = new Set(\n distantDictionaries.map((dictionary) => dictionary.id)\n );\n\n const notRefetchedCachedDictionaries = cachedDictionaries.filter(\n (dictionary) => !fetchedDictionaryIds.has(dictionary.id)\n );\n\n return [...notRefetchedCachedDictionaries, ...distantDictionaries];\n } catch (error) {\n options?.onError?.(error as Error);\n return [];\n } finally {\n options?.onStopRemoteCheck?.();\n }\n};\n"],"mappings":";;;;;;AAWA,MAAa,6BACX,iBAEA,aAAa,KAAK,UAAU;CAC1B,GAAG;CACH,SAAS,GAAG,KAAK,IAAI,YAAY,KAAK;CACtC,UAAU;AACZ,EAAE;AAEJ,MAAa,yBAAyB,OACpC,oBAAgBA,wCAAiB,GACjC,gBACA,YAK0B;CAC1B,MAAM,EAAE,WAAW;CACnB,MAAM,+BAA2BC,2DAAsB,aAAa;CAIpE,IAAI,CAF0B,QAAQ,OAAO,YAAY,OAAO,YAEvC,GAAG,OAAO,CAAC;CAEpC,IAAI;EACF,SAAS,qBAAqB;EAG9B,MAAM,EAAE,8BAA8B,6BACpC,2CAAM;EAQR,MAAM,oCAGK,MATQ,6BAA6B,aAI/B,CAAC,CAAC,+BAA+B,EAKd,CAAC;EAErC,IAAI,CAAC,kCACH,MAAM,IAAI,MAAM,+BAA+B;EAGjD,MAAM,wBAAwB,OAAO,QACnC,gCACF,CAAC,CAAC,QAAQ,CAAC,cAAc,UAAU;GAEjC,IAAI,CAAC,KAAK,WAAW,OAAO;GAG5B,MAAM,QAAgC,yBACpC,KAAK,IACN,EAAE,MAAM,eAAe,WAAW,OAAO,YAAY;GACtD,IAAI,CAAC,OAAO,OAAO;GAEnB,MAAM,oBAAqB,OAAe;GAK1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GAGR,IAAI,OAAO,mBAAmB,UAAU,OAAO;GAE/C,OAAO,KAAK,YAAY;EAC1B,CAAC;EAMD,MAAM,qBAJgD,OAAO,OAC3D,wBACF,CAAC,CAAC,KAG2B,CAAC,CAAC,QAAQ,eAAe;GAClD,MAAM,kBAAkB,WAAW,KAC/B,iCAAiC,WAAW,GAAG,EAAE,YACjD;GAEJ,MAAM,oBAAoB,WAAW;GAErC,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GAGR,OACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;EAEtB,CAAC;EAGH,IAAI,mBAAmB,SAAS,GAC9B,iBACE,mBAAmB,KAAK,gBAAgB;GACtC,eAAe,WAAW;GAC1B,MAAM;GACN,QAAQ;EACV,EAAE,CACJ;EAKF,MAAM,+BAA+B,CACnC,GAAG,IAAI,IAAI,sBAAsB,KAAK,GAAG,UAAU,KAAK,GAAG,CAAC,CAC9D,CAAC,CAAC,KAAKC,mDAAkB;EAGzB,IAAI,6BAA6B,SAAS,GACxC,iBACE,6BAA6B,KAAK,SAAS;GACzC,eAAe;GACf,MAAM;GACN,QAAQ;EACV,EAAE,CACJ;EAGF,MAAM,0BAA0B,MAAM,yBACpC,EACE,gBAAgB,6BAClB,GACA,cACF;EAEA,MAAM,sBAAoC,0BACxC,uBACF;EAIA,MAAM,uBAAuB,IAAI,IAC/B,oBAAoB,KAAK,eAAe,WAAW,EAAE,CACvD;EAMA,OAAO,CAAC,GAJ+B,mBAAmB,QACvD,eAAe,CAAC,qBAAqB,IAAI,WAAW,EAAE,CAGjB,GAAG,GAAG,mBAAmB;CACnE,SAAS,OAAO;EACd,SAAS,UAAU,KAAc;EACjC,OAAO,CAAC;CACV,UAAU;EACR,SAAS,oBAAoB;CAC/B;AACF"}
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ const require_utils_isDirectoryExcluded = require('./isDirectoryExcluded.cjs');
3
4
  let node_path = require("node:path");
4
5
  let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
5
6
  let _intlayer_config_utils = require("@intlayer/config/utils");
@@ -12,27 +13,24 @@ fast_glob = require_runtime.__toESM(fast_glob);
12
13
  */
13
14
  const normalizeToArray = (value) => Array.isArray(value) ? value : [value];
14
15
  /**
15
- * Remove directories that are subdirectories of others in the list so files
16
- * are never scanned twice.
17
- * Example: ['/root', '/root/src'] → ['/root']
16
+ * Remove directories nested in others so files are never scanned twice.
17
+ * A nested directory is kept as its own root when the exclude patterns would
18
+ * drop it from its parent's scan (e.g. `<root>/dist` under `**\/dist/**`).
19
+ *
20
+ * Example: ['/root', '/root/src', '/root/dist'] → ['/root', '/root/dist']
18
21
  */
19
- const getDistinctRootDirs = (dirs) => {
22
+ const getDistinctRootDirs = (dirs, excludePatterns) => {
20
23
  const uniqueDirs = Array.from(new Set(dirs.map((dir) => (0, node_path.resolve)(dir))));
21
24
  uniqueDirs.sort((a, b) => a.length - b.length);
22
25
  return uniqueDirs.reduce((acc, dir) => {
23
26
  if (!acc.some((parent) => {
24
- const rel = (0, node_path.relative)(parent, dir);
25
- return !rel.startsWith("..") && !(0, node_path.isAbsolute)(rel) && rel !== "";
27
+ const relativePath = (0, node_path.relative)(parent, dir);
28
+ return relativePath !== "" && !relativePath.startsWith("..") && !(0, node_path.isAbsolute)(relativePath) && !require_utils_isDirectoryExcluded.isDirectoryExcluded(relativePath, excludePatterns);
26
29
  })) acc.push(dir);
27
30
  return acc;
28
31
  }, []);
29
32
  };
30
33
  /**
31
- * Returns true when the resolved path passes through a `node_modules` segment.
32
- * Works on both POSIX and Windows paths.
33
- */
34
- const isInsideNodeModules = (dir) => (0, node_path.resolve)(dir).split(node_path.sep).includes("node_modules");
35
- /**
36
34
  * Default exclude patterns derived from TRAVERSE_PATTERN.
37
35
  * Extracted once so the function body can reference them without re-computing.
38
36
  */
@@ -44,18 +42,18 @@ const DEFAULT_EXCLUDE_PATTERNS = _intlayer_config_defaultValues.TRAVERSE_PATTERN
44
42
  * patterns, negation patterns embedded in `traversePattern`, and optional
45
43
  * dot-file inclusion.
46
44
  *
47
- * Special case: `codeDir` entries that live inside `node_modules` (e.g. a
48
- * design-system package installed as a workspace dependency) are scanned as
49
- * their own explicit roots. They are NOT collapsed into the project root so
50
- * the `*\/node_modules\/**` exclusion does not silently drop them.
45
+ * `codeDir` entries are more precise than the exclude patterns: a `codeDir`
46
+ * inside an excluded directory (e.g. a design-system `dist` or a package in
47
+ * `node_modules`) is scanned as its own root, so the exclusion only applies
48
+ * below it.
51
49
  *
52
50
  * @example
53
51
  * // Single root with excludes
54
52
  * const files = buildComponentFilesList(config);
55
53
  *
56
54
  * @example
57
- * // Design-system package inside node_modules is still scanned
58
- * // intlayer.config.ts: { content: { codeDir: ['node_modules/my-ds/src'] } }
55
+ * // Design-system build output is still scanned
56
+ * // intlayer.config.ts: { content: { codeDir: ['node_modules/my-ds/dist'] } }
59
57
  * const files = buildComponentFilesList(config);
60
58
  */
61
59
  const buildComponentFilesList = (config, excludePattern) => {
@@ -70,23 +68,13 @@ const buildComponentFilesList = (config, excludePattern) => {
70
68
  ...excludePattern ?? [],
71
69
  ...contentDeclarationPattern
72
70
  ])).filter((pattern) => typeof pattern === "string").map(_intlayer_config_utils.normalizePath);
73
- const resolvedCodeDirs = (config.content.codeDir ?? []).map((dir) => (0, node_path.resolve)(dir));
74
- const inNodeModulesCodeDirs = resolvedCodeDirs.filter(isInsideNodeModules);
75
- const normalCodeDirs = resolvedCodeDirs.filter((dir) => !isInsideNodeModules(dir));
76
- const normalFiles = getDistinctRootDirs([config.system.baseDir, ...normalCodeDirs]).flatMap((root) => fast_glob.default.sync(patterns, {
71
+ const roots = getDistinctRootDirs([config.system.baseDir, ...config.content.codeDir ?? []], baseExcludePatterns);
72
+ return Array.from(new Set(roots.flatMap((root) => fast_glob.default.sync(patterns, {
77
73
  cwd: root,
78
74
  ignore: baseExcludePatterns,
79
75
  absolute: true,
80
76
  dot: true
81
- }));
82
- const nodeModulesExcludePatterns = baseExcludePatterns.filter((pattern) => !pattern.includes("node_modules"));
83
- const nodeModulesFiles = inNodeModulesCodeDirs.flatMap((dir) => fast_glob.default.sync(patterns, {
84
- cwd: dir,
85
- ignore: nodeModulesExcludePatterns,
86
- absolute: true,
87
- dot: false
88
- }));
89
- return Array.from(/* @__PURE__ */ new Set([...normalFiles, ...nodeModulesFiles]));
77
+ }))));
90
78
  };
91
79
 
92
80
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"buildComponentFilesList.cjs","names":["resolve","relative","isAbsolute","sep","TRAVERSE_PATTERN","normalizePath","fg"],"sources":["../../../src/utils/buildComponentFilesList.ts"],"sourcesContent":["import { isAbsolute, relative, resolve, sep } from 'node:path';\nimport { TRAVERSE_PATTERN } from '@intlayer/config/defaultValues';\nimport { normalizePath } from '@intlayer/config/utils';\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 * Returns true when the resolved path passes through a `node_modules` segment.\n * Works on both POSIX and Windows paths.\n */\nconst isInsideNodeModules = (dir: string): boolean =>\n resolve(dir).split(sep).includes('node_modules');\n\n/**\n * Default exclude patterns derived from TRAVERSE_PATTERN.\n * Extracted once so the function body can reference them without re-computing.\n */\nconst DEFAULT_EXCLUDE_PATTERNS: string[] = TRAVERSE_PATTERN.filter(\n (p): p is string => typeof p === 'string' && p.startsWith('!')\n).map((p) => p.slice(1));\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 `traversePattern`, and optional\n * dot-file inclusion.\n *\n * Special case: `codeDir` entries that live inside `node_modules` (e.g. a\n * design-system package installed as a workspace dependency) are scanned as\n * their own explicit roots. They are NOT collapsed into the project root so\n * the `*\\/node_modules\\/**` exclusion does not silently drop them.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList(config);\n *\n * @example\n * // Design-system package inside node_modules is still scanned\n * // intlayer.config.ts: { content: { codeDir: ['node_modules/my-ds/src'] } }\n * const files = buildComponentFilesList(config);\n */\nexport const buildComponentFilesList = (\n config: IntlayerConfig,\n excludePattern?: string[]\n): string[] => {\n const traversePattern = 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 ...traversePattern,\n ...normalizeToArray(compilerTransformPattern),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .filter((pattern) => !pattern.startsWith('!'))\n .map(normalizePath);\n\n // User-supplied negations from traversePattern\n const userExcludes = traversePattern\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1));\n\n // Full exclude list: defaults (from TRAVERSE_PATTERN) + user overrides + caller extras + content files.\n // DEFAULT_EXCLUDE_PATTERNS acts as a safety floor — if the user provides a\n // partial traversePattern that omits some defaults, they are still applied.\n const baseExcludePatterns = Array.from(\n new Set([\n ...DEFAULT_EXCLUDE_PATTERNS,\n ...userExcludes,\n ...(excludePattern ?? []),\n ...contentDeclarationPattern,\n ])\n )\n .filter((pattern): pattern is string => typeof pattern === 'string')\n .map(normalizePath);\n\n // Separate codeDir entries that live inside node_modules.\n // getDistinctRootDirs would collapse them into the project root, after which\n // the **/node_modules/** ignore would silently exclude them.\n const resolvedCodeDirs = (config.content.codeDir ?? []).map((dir) =>\n resolve(dir)\n );\n const inNodeModulesCodeDirs = resolvedCodeDirs.filter(isInsideNodeModules);\n const normalCodeDirs = resolvedCodeDirs.filter(\n (dir) => !isInsideNodeModules(dir)\n );\n\n // Normal roots: project base + regular codeDir entries, deduplicated.\n const normalRoots = getDistinctRootDirs([\n config.system.baseDir,\n ...normalCodeDirs,\n ]);\n\n const normalFiles = normalRoots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: baseExcludePatterns,\n absolute: true,\n dot: true, // needed for .intlayer and similar\n })\n );\n\n // node_modules codeDir roots: scanned directly from the package root.\n // **/node_modules/** is removed from the ignore list so it doesn't block\n // the scan (it is still applied inside the package for nested node_modules).\n const nodeModulesExcludePatterns = baseExcludePatterns.filter(\n (pattern) => !pattern.includes('node_modules')\n );\n\n const nodeModulesFiles = inNodeModulesCodeDirs.flatMap((dir) =>\n fg.sync(patterns, {\n cwd: dir,\n ignore: nodeModulesExcludePatterns,\n absolute: true,\n dot: false,\n })\n );\n\n return Array.from(new Set([...normalFiles, ...nodeModulesFiles]));\n};\n"],"mappings":";;;;;;;;;;;;AASA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;;;;;;AAOvC,MAAM,uBAAuB,SAA6B;CACxD,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,YAAQA,mBAAQ,GAAG,CAAC,CAAC,CAAC;CACtE,WAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;CAE7C,OAAO,WAAW,QAAQ,KAAe,QAAQ;EAM/C,IAAI,CALa,IAAI,MAAM,WAAW;GACpC,MAAM,UAAMC,oBAAS,QAAQ,GAAG;GAEhC,OAAO,CAAC,IAAI,WAAW,IAAI,KAAK,KAACC,sBAAW,GAAG,KAAK,QAAQ;EAC9D,CACY,GAAG,IAAI,KAAK,GAAG;EAE3B,OAAO;CACT,GAAG,CAAC,CAAC;AACP;;;;;AAMA,MAAM,uBAAuB,YAC3BF,mBAAQ,GAAG,CAAC,CAAC,MAAMG,aAAG,CAAC,CAAC,SAAS,cAAc;;;;;AAMjD,MAAM,2BAAqCC,gDAAiB,QACzD,MAAmB,OAAO,MAAM,YAAY,EAAE,WAAW,GAAG,CAC/D,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;AAuBvB,MAAa,2BACX,QACA,mBACa;CACb,MAAM,kBAAkB,OAAO,MAAM;CACrC,MAAM,2BAA2B,OAAO,SAAS;CACjD,MAAM,4BAA4B,OAAO,QAAQ,eAAe,KAC7D,QAAQ,QAAQ,KACnB;CAEA,MAAM,WAAW,CACf,GAAG,iBACH,GAAG,iBAAiB,wBAAwB,CAC9C,CAAC,CACE,QAAQ,YAAY,OAAO,YAAY,QAAQ,CAAC,CAChD,QAAQ,YAAY,CAAC,QAAQ,WAAW,GAAG,CAAC,CAAC,CAC7C,IAAIC,oCAAa;CAGpB,MAAM,eAAe,gBAClB,QACE,YACC,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG,CACzD,CAAC,CACA,KAAK,YAAY,QAAQ,MAAM,CAAC,CAAC;CAKpC,MAAM,sBAAsB,MAAM,qBAChC,IAAI,IAAI;EACN,GAAG;EACH,GAAG;EACH,GAAI,kBAAkB,CAAC;EACvB,GAAG;CACL,CAAC,CACH,CAAC,CACE,QAAQ,YAA+B,OAAO,YAAY,QAAQ,CAAC,CACnE,IAAIA,oCAAa;CAKpB,MAAM,oBAAoB,OAAO,QAAQ,WAAW,CAAC,EAAC,CAAE,KAAK,YAC3DL,mBAAQ,GAAG,CACb;CACA,MAAM,wBAAwB,iBAAiB,OAAO,mBAAmB;CACzE,MAAM,iBAAiB,iBAAiB,QACrC,QAAQ,CAAC,oBAAoB,GAAG,CACnC;CAQA,MAAM,cALc,oBAAoB,CACtC,OAAO,OAAO,SACd,GAAG,cACL,CAE8B,CAAC,CAAC,SAAS,SACvCM,kBAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV,KAAK;CACP,CAAC,CACH;CAKA,MAAM,6BAA6B,oBAAoB,QACpD,YAAY,CAAC,QAAQ,SAAS,cAAc,CAC/C;CAEA,MAAM,mBAAmB,sBAAsB,SAAS,QACtDA,kBAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV,KAAK;CACP,CAAC,CACH;CAEA,OAAO,MAAM,qBAAK,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,gBAAgB,CAAC,CAAC;AAClE"}
1
+ {"version":3,"file":"buildComponentFilesList.cjs","names":["resolve","relative","isAbsolute","isDirectoryExcluded","TRAVERSE_PATTERN","normalizePath","fg"],"sources":["../../../src/utils/buildComponentFilesList.ts"],"sourcesContent":["import { isAbsolute, relative, resolve } from 'node:path';\nimport { TRAVERSE_PATTERN } from '@intlayer/config/defaultValues';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\nimport { isDirectoryExcluded } from './isDirectoryExcluded';\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 nested in others so files are never scanned twice.\n * A nested directory is kept as its own root when the exclude patterns would\n * drop it from its parent's scan (e.g. `<root>/dist` under `**\\/dist/**`).\n *\n * Example: ['/root', '/root/src', '/root/dist'] → ['/root', '/root/dist']\n */\nconst getDistinctRootDirs = (\n dirs: string[],\n excludePatterns: string[]\n): 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 isCoveredByParent = acc.some((parent) => {\n const relativePath = relative(parent, dir);\n const isNested =\n relativePath !== '' &&\n !relativePath.startsWith('..') &&\n !isAbsolute(relativePath);\n\n return isNested && !isDirectoryExcluded(relativePath, excludePatterns);\n });\n if (!isCoveredByParent) acc.push(dir);\n\n return acc;\n }, []);\n};\n\n/**\n * Default exclude patterns derived from TRAVERSE_PATTERN.\n * Extracted once so the function body can reference them without re-computing.\n */\nconst DEFAULT_EXCLUDE_PATTERNS: string[] = TRAVERSE_PATTERN.filter(\n (p): p is string => typeof p === 'string' && p.startsWith('!')\n).map((p) => p.slice(1));\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 `traversePattern`, and optional\n * dot-file inclusion.\n *\n * `codeDir` entries are more precise than the exclude patterns: a `codeDir`\n * inside an excluded directory (e.g. a design-system `dist` or a package in\n * `node_modules`) is scanned as its own root, so the exclusion only applies\n * below it.\n *\n * @example\n * // Single root with excludes\n * const files = buildComponentFilesList(config);\n *\n * @example\n * // Design-system build output is still scanned\n * // intlayer.config.ts: { content: { codeDir: ['node_modules/my-ds/dist'] } }\n * const files = buildComponentFilesList(config);\n */\nexport const buildComponentFilesList = (\n config: IntlayerConfig,\n excludePattern?: string[]\n): string[] => {\n const traversePattern = 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 ...traversePattern,\n ...normalizeToArray(compilerTransformPattern),\n ]\n .filter((pattern) => typeof pattern === 'string')\n .filter((pattern) => !pattern.startsWith('!'))\n .map(normalizePath);\n\n // User-supplied negations from traversePattern\n const userExcludes = traversePattern\n .filter(\n (pattern): pattern is string =>\n typeof pattern === 'string' && pattern.startsWith('!')\n )\n .map((pattern) => pattern.slice(1));\n\n // Full exclude list: defaults (from TRAVERSE_PATTERN) + user overrides + caller extras + content files.\n // DEFAULT_EXCLUDE_PATTERNS acts as a safety floor — if the user provides a\n // partial traversePattern that omits some defaults, they are still applied.\n const baseExcludePatterns = Array.from(\n new Set([\n ...DEFAULT_EXCLUDE_PATTERNS,\n ...userExcludes,\n ...(excludePattern ?? []),\n ...contentDeclarationPattern,\n ])\n )\n .filter((pattern): pattern is string => typeof pattern === 'string')\n .map(normalizePath);\n\n const roots = getDistinctRootDirs(\n [config.system.baseDir, ...(config.content.codeDir ?? [])],\n baseExcludePatterns\n );\n\n return Array.from(\n new Set(\n roots.flatMap((root) =>\n fg.sync(patterns, {\n cwd: root,\n ignore: baseExcludePatterns,\n absolute: true,\n dot: true, // needed for .intlayer and similar\n })\n )\n )\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAUA,MAAM,oBAAuB,UAC3B,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;;;;;;;;AASvC,MAAM,uBACJ,MACA,oBACa;CACb,MAAM,aAAa,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,YAAQA,mBAAQ,GAAG,CAAC,CAAC,CAAC;CACtE,WAAW,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;CAE7C,OAAO,WAAW,QAAQ,KAAe,QAAQ;EAU/C,IAAI,CATsB,IAAI,MAAM,WAAW;GAC7C,MAAM,mBAAeC,oBAAS,QAAQ,GAAG;GAMzC,OAJE,iBAAiB,MACjB,CAAC,aAAa,WAAW,IAAI,KAC7B,KAACC,sBAAW,YAAY,KAEP,CAACC,sDAAoB,cAAc,eAAe;EACvE,CACqB,GAAG,IAAI,KAAK,GAAG;EAEpC,OAAO;CACT,GAAG,CAAC,CAAC;AACP;;;;;AAMA,MAAM,2BAAqCC,gDAAiB,QACzD,MAAmB,OAAO,MAAM,YAAY,EAAE,WAAW,GAAG,CAC/D,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;AAuBvB,MAAa,2BACX,QACA,mBACa;CACb,MAAM,kBAAkB,OAAO,MAAM;CACrC,MAAM,2BAA2B,OAAO,SAAS;CACjD,MAAM,4BAA4B,OAAO,QAAQ,eAAe,KAC7D,QAAQ,QAAQ,KACnB;CAEA,MAAM,WAAW,CACf,GAAG,iBACH,GAAG,iBAAiB,wBAAwB,CAC9C,CAAC,CACE,QAAQ,YAAY,OAAO,YAAY,QAAQ,CAAC,CAChD,QAAQ,YAAY,CAAC,QAAQ,WAAW,GAAG,CAAC,CAAC,CAC7C,IAAIC,oCAAa;CAGpB,MAAM,eAAe,gBAClB,QACE,YACC,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG,CACzD,CAAC,CACA,KAAK,YAAY,QAAQ,MAAM,CAAC,CAAC;CAKpC,MAAM,sBAAsB,MAAM,qBAChC,IAAI,IAAI;EACN,GAAG;EACH,GAAG;EACH,GAAI,kBAAkB,CAAC;EACvB,GAAG;CACL,CAAC,CACH,CAAC,CACE,QAAQ,YAA+B,OAAO,YAAY,QAAQ,CAAC,CACnE,IAAIA,oCAAa;CAEpB,MAAM,QAAQ,oBACZ,CAAC,OAAO,OAAO,SAAS,GAAI,OAAO,QAAQ,WAAW,CAAC,CAAE,GACzD,mBACF;CAEA,OAAO,MAAM,KACX,IAAI,IACF,MAAM,SAAS,SACbC,kBAAG,KAAK,UAAU;EAChB,KAAK;EACL,QAAQ;EACR,UAAU;EACV,KAAK;CACP,CAAC,CACH,CACF,CACF;AACF"}
@@ -22,7 +22,7 @@ const setAtPath = (root, path, value) => {
22
22
  for (let i = 0; i < path.length - 1; i++) {
23
23
  const key = path[i];
24
24
  if (key === void 0) continue;
25
- const isNextIndex = typeof nextKey === "number";
25
+ const isNextIndex = typeof path[i + 1] === "number";
26
26
  if (typeof key === "number") {
27
27
  if (!Array.isArray(current)) throw new Error(`Expected array at path segment ${i}`);
28
28
  if (current[key] === void 0) current[key] = isNextIndex ? [] : {};
@@ -1 +1 @@
1
- {"version":3,"file":"chunkJSON.cjs","names":["getChunk"],"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 if (key === undefined) continue;\n\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 Record<string, any>)[key] = isNextIndex ? [] : {};\n }\n\n current = (current as Record<string, any>)[key];\n }\n }\n\n const last = path[path.length - 1];\n\n if (last === undefined) return;\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 Record<string, 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 const part = parts[i];\n\n if (part !== undefined) {\n patches.push({\n op: 'set',\n path: [...currentPath, String(i + 1)],\n value: part,\n });\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 const item = currentValue[i];\n if (item !== undefined) {\n walk(item as JSONValue, [...currentPath, i]);\n }\n }\n } else {\n for (const key of Object.keys(currentValue)) {\n const childVal = (currentValue as JSONObject)[key];\n\n if (childVal !== undefined) {\n walk(childVal, [...currentPath, key]);\n }\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 firstChunk = sorted[0];\n\n if (!firstChunk) {\n throw new Error('No chunks provided.');\n }\n\n const { checksum, rootType } = firstChunk;\n const schemaVersion = 1;\n\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (!chunk) continue;\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) continue;\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.cjs","names":["getChunk"],"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 if (key === undefined) continue;\n\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 Record<string, any>)[key] = isNextIndex ? [] : {};\n }\n\n current = (current as Record<string, any>)[key];\n }\n }\n\n const last = path[path.length - 1];\n\n if (last === undefined) return;\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 Record<string, 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 const part = parts[i];\n\n if (part !== undefined) {\n patches.push({\n op: 'set',\n path: [...currentPath, String(i + 1)],\n value: part,\n });\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 const item = currentValue[i];\n if (item !== undefined) {\n walk(item as JSONValue, [...currentPath, i]);\n }\n }\n } else {\n for (const key of Object.keys(currentValue)) {\n const childVal = (currentValue as JSONObject)[key];\n\n if (childVal !== undefined) {\n walk(childVal, [...currentPath, key]);\n }\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 firstChunk = sorted[0];\n\n if (!firstChunk) {\n throw new Error('No chunks provided.');\n }\n\n const { checksum, rootType } = firstChunk;\n const schemaVersion = 1;\n\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n\n if (!chunk) continue;\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) continue;\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,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_utils_autoDecorateContent = require('./autoDecorateContent.cjs');
3
+ const require_utils_isDirectoryExcluded = require('./isDirectoryExcluded.cjs');
3
4
  const require_utils_buildComponentFilesList = require('./buildComponentFilesList.cjs');
4
5
  const require_utils_chunkArray = require('./chunkArray.cjs');
5
6
  const require_utils_splitTextByLine = require('./splitTextByLine.cjs');
@@ -47,6 +48,7 @@ exports.getFormatFromExtension = require_utils_getFormatFromExtension.getFormatF
47
48
  exports.getGlobalLimiter = require_utils_parallelizeGlobal.getGlobalLimiter;
48
49
  exports.getPathHash = require_utils_getPathHash.getPathHash;
49
50
  exports.getTaskLimiter = require_utils_parallelizeGlobal.getTaskLimiter;
51
+ exports.isDirectoryExcluded = require_utils_isDirectoryExcluded.isDirectoryExcluded;
50
52
  exports.mergeChunks = require_utils_mergeChunks.mergeChunks;
51
53
  exports.pLimit = require_utils_pLimit.pLimit;
52
54
  exports.parallelize = require_utils_parallelize.parallelize;
@@ -0,0 +1,36 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _intlayer_config_utils = require("@intlayer/config/utils");
3
+
4
+ //#region src/utils/isDirectoryExcluded.ts
5
+ /**
6
+ * Extracts the literal directory segments of a directory-shaped exclude
7
+ * pattern (`**\/dist/**` → `dist`, `!**\/.next/**` → `.next`).
8
+ * Returns `undefined` for file-shaped or wildcard patterns (`**\/*.config.*`),
9
+ * which can never exclude a whole directory.
10
+ */
11
+ const getExcludedDirectorySegments = (excludePattern) => {
12
+ const segments = (0, _intlayer_config_utils.normalizePath)(excludePattern).replace(/^!/, "").replace(/^(\*\*\/)+/, "").replace(/(\/\*\*)+\/?$/, "");
13
+ return segments !== "" && !/[*?[\]{}()!]/.test(segments) ? segments : void 0;
14
+ };
15
+ /**
16
+ * Whether a directory path lies inside a directory matched by one of the
17
+ * exclude patterns (e.g. `packages/ds/dist/esm` against `**\/dist/**`).
18
+ *
19
+ * Used to keep explicitly configured directories (`codeDir`, `contentDir`)
20
+ * from being dropped by an exclusion that only matches their ancestors.
21
+ *
22
+ * @example
23
+ * isDirectoryExcluded('ds/dist/esm', ['**\/dist/**']); // true
24
+ * isDirectoryExcluded('src/distance', ['**\/dist/**']); // false
25
+ */
26
+ const isDirectoryExcluded = (directoryPath, excludePatterns) => {
27
+ const wrappedPath = `/${(0, _intlayer_config_utils.normalizePath)(directoryPath).replace(/^\/+|\/+$/g, "")}/`;
28
+ return excludePatterns.some((excludePattern) => {
29
+ const excludedSegments = getExcludedDirectorySegments(excludePattern);
30
+ return excludedSegments !== void 0 && wrappedPath.includes(`/${excludedSegments}/`);
31
+ });
32
+ };
33
+
34
+ //#endregion
35
+ exports.isDirectoryExcluded = isDirectoryExcluded;
36
+ //# sourceMappingURL=isDirectoryExcluded.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isDirectoryExcluded.cjs","names":["normalizePath"],"sources":["../../../src/utils/isDirectoryExcluded.ts"],"sourcesContent":["import { normalizePath } from '@intlayer/config/utils';\n\n/**\n * Extracts the literal directory segments of a directory-shaped exclude\n * pattern (`**\\/dist/**` → `dist`, `!**\\/.next/**` → `.next`).\n * Returns `undefined` for file-shaped or wildcard patterns (`**\\/*.config.*`),\n * which can never exclude a whole directory.\n */\nconst getExcludedDirectorySegments = (\n excludePattern: string\n): string | undefined => {\n const segments = normalizePath(excludePattern)\n .replace(/^!/, '')\n .replace(/^(\\*\\*\\/)+/, '')\n .replace(/(\\/\\*\\*)+\\/?$/, '');\n\n const isLiteral = segments !== '' && !/[*?[\\]{}()!]/.test(segments);\n\n return isLiteral ? segments : undefined;\n};\n\n/**\n * Whether a directory path lies inside a directory matched by one of the\n * exclude patterns (e.g. `packages/ds/dist/esm` against `**\\/dist/**`).\n *\n * Used to keep explicitly configured directories (`codeDir`, `contentDir`)\n * from being dropped by an exclusion that only matches their ancestors.\n *\n * @example\n * isDirectoryExcluded('ds/dist/esm', ['**\\/dist/**']); // true\n * isDirectoryExcluded('src/distance', ['**\\/dist/**']); // false\n */\nexport const isDirectoryExcluded = (\n directoryPath: string,\n excludePatterns: string[]\n): boolean => {\n const wrappedPath = `/${normalizePath(directoryPath).replace(/^\\/+|\\/+$/g, '')}/`;\n\n return excludePatterns.some((excludePattern) => {\n const excludedSegments = getExcludedDirectorySegments(excludePattern);\n\n return (\n excludedSegments !== undefined &&\n wrappedPath.includes(`/${excludedSegments}/`)\n );\n });\n};\n"],"mappings":";;;;;;;;;;AAQA,MAAM,gCACJ,mBACuB;CACvB,MAAM,eAAWA,sCAAc,cAAc,CAAC,CAC3C,QAAQ,MAAM,EAAE,CAAC,CACjB,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,iBAAiB,EAAE;CAI9B,OAFkB,aAAa,MAAM,CAAC,eAAe,KAAK,QAAQ,IAE/C,WAAW;AAChC;;;;;;;;;;;;AAaA,MAAa,uBACX,eACA,oBACY;CACZ,MAAM,cAAc,QAAIA,sCAAc,aAAa,CAAC,CAAC,QAAQ,cAAc,EAAE,EAAE;CAE/E,OAAO,gBAAgB,MAAM,mBAAmB;EAC9C,MAAM,mBAAmB,6BAA6B,cAAc;EAEpE,OACE,qBAAqB,UACrB,YAAY,SAAS,IAAI,iBAAiB,EAAE;CAEhD,CAAC;AACH"}
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
+ const require_utils_isDirectoryExcluded = require('./utils/isDirectoryExcluded.cjs');
3
4
  const require_utils_formatter = require('./utils/formatter.cjs');
4
5
  const require_utils_getFormatFromExtension = require('./utils/getFormatFromExtension.cjs');
5
6
  const require_utils_parseContentDeclarationFileName = require('./utils/parseContentDeclarationFileName.cjs');
@@ -142,8 +143,10 @@ const watch = async (options) => {
142
143
  const path = (0, _intlayer_config_utils.normalizePath)(filePath);
143
144
  const isConfigFile = normalizedConfigPath && path === normalizedConfigPath;
144
145
  if (!isConfigFile) {
145
- if (!contentDirs.some((d) => path.startsWith(`${d}/`) || path === d)) continue;
146
- if (excludedSegments.some((segment) => path.includes(`/${segment}`))) continue;
146
+ const matchingContentDir = contentDirs.filter((dictionary) => path.startsWith(`${dictionary}/`) || path === dictionary).reduce((longest, dictionary) => longest === void 0 || dictionary.length > longest.length ? dictionary : longest, void 0);
147
+ if (matchingContentDir === void 0) continue;
148
+ const relativeDirectory = (0, node_path.dirname)(path.slice(matchingContentDir.length));
149
+ if (require_utils_isDirectoryExcluded.isDirectoryExcluded(relativeDirectory, excludedPath)) continue;
147
150
  if (!fileExtensions.some((extension) => path.endsWith(extension))) continue;
148
151
  }
149
152
  if (event.type === "create") {