@intlayer/chokidar 8.9.4 → 8.9.6-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +6 -2
  2. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  3. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +4 -2
  4. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
  5. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +2 -0
  6. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs.map +1 -1
  7. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs +2 -0
  8. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs.map +1 -1
  9. package/dist/cjs/createType/createModuleAugmentation.cjs +17 -6
  10. package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
  11. package/dist/cjs/installSkills/index.cjs +5 -2
  12. package/dist/cjs/installSkills/index.cjs.map +1 -1
  13. package/dist/cjs/watcher.cjs +54 -0
  14. package/dist/cjs/watcher.cjs.map +1 -1
  15. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +6 -2
  16. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  17. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +5 -3
  18. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs.map +1 -1
  19. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +2 -0
  20. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs.map +1 -1
  21. package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs +2 -0
  22. package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs.map +1 -1
  23. package/dist/esm/createType/createModuleAugmentation.mjs +17 -6
  24. package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
  25. package/dist/esm/installSkills/index.mjs +5 -2
  26. package/dist/esm/installSkills/index.mjs.map +1 -1
  27. package/dist/esm/watcher.mjs +55 -1
  28. package/dist/esm/watcher.mjs.map +1 -1
  29. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts.map +1 -1
  30. package/dist/types/buildIntlayerDictionary/writeMergedDictionary.d.ts.map +1 -1
  31. package/dist/types/buildIntlayerDictionary/writeUnmergedDictionary.d.ts.map +1 -1
  32. package/dist/types/createType/createModuleAugmentation.d.ts.map +1 -1
  33. package/dist/types/installSkills/index.d.ts.map +1 -1
  34. package/dist/types/watcher.d.ts.map +1 -1
  35. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"writeDynamicDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { MergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Generates the content of a dictionary entry point file.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) =>\n format === 'esm'\n ? ` '${locale}': () => import('./${DICTIONARIES_SUBDIR}/${key}/${locale}.json').then(m => m.default)`\n : ` '${locale}': () => Promise.resolve(require('./${DICTIONARIES_SUBDIR}/${key}/${locale}.json'))`\n )\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: MergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format);\n\n await writeFileIfChanged(\n resolve(dynamicDictionariesDir, `${key}.${extension}`),\n content\n ).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(resolve(dynamicDictionariesDir, `${key}.${extension}`))}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,sBAAsB;;;;AAK5B,MAAa,gCACX,KACA,SACA,SAAwB,UACb;CAKX,MAAM,gBAJgB,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,MAC1C,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CAGD,CAChC,KAAK,WACJ,WAAW,QACP,MAAM,OAAO,qBAAqB,oBAAoB,GAAG,IAAI,GAAG,OAAO,gCACvE,MAAM,OAAO,sCAAsC,oBAAoB,GAAG,IAAI,GAAG,OAAO,UAC7F,CACA,KAAK,MAAM;CAEd,IAAI,WAAW,OACb,OACE,sBAAsB,cAAc;CAIxC,OAAO,uBAAuB,cAAc;;;;;;;;;;;;;;;;;;AAmB9C,MAAa,yBAAyB,OACpC,oBACA,eACA,UAA6B,kBACU;CACvC,MAAM,EAAE,SAAS,kBAAkB,cAAc;CACjD,MAAM,EAAE,2BAA2B,cAAc;CAEjD,MAAM,UAAU,QAAQ,wBAAwB,oBAAoB;CACpE,MAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;CAEzC,MAAM,0BAAqD,EAAE;CAG7D,MAAM,YACJ,OAAO,QAAQ,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,OAC7C,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CACnC,EACD,OAAO,CAAC,KAAK,qBAAqB;EAChC,IAAI,QAAQ,aAAa;EAEzB,MAAM,mCAA8D,EAAE;EAEtE,MAAM,SAAS,QAAQ,SAAS,IAAI;EACpC,MAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;EAExC,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,sBAAsB,uBAC1B,gBAAgB,YAChB,QACA,cACD;GAGD,MAAM,iBAAiB,QAAQ,QAAQ,GAAG,OAAO,OAAO;GAExD,MAAM,mBAAmB,gBAAgB,oBAAoB,CAAC,OAC3D,QAAQ;IACP,QAAQ,MACN,4BAA4B,IAAI,GAAG,OAAO,SAC1C,IACD;KAEJ;GAED,iCAAiC,UAAU;IACzC,gBAAgB;IAChB,YAAY;IACb;IACD;EAEF,wBAAwB,OAAO;EAE/B,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BAA6B,KAAK,SAAS,OAAO;GAElE,MAAM,mBACJ,QAAQ,wBAAwB,GAAG,IAAI,GAAG,YAAY,EACtD,QACD,CAAC,OAAO,QAAQ;IACf,QAAQ,MACN,0BAA0B,aAAa,QAAQ,wBAAwB,GAAG,IAAI,GAAG,YAAY,CAAC,CAAC,IAC/F,IACD;KACD;IACF;GAEL;CAED,OAAO"}
1
+ {"version":3,"file":"writeDynamicDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport { getPerLocaleDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { MergedDictionaryOutput } from './writeMergedDictionary';\n\nexport type DictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type LocalizedDictionaryResult = Partial<\n Record<Locale, DictionaryResult>\n>;\n\nexport type LocalizedDictionaryOutput = Record<\n string,\n LocalizedDictionaryResult\n>;\n\nconst DICTIONARIES_SUBDIR = 'json'; // Necessary to add a static first dir for Turbopack\n\n/**\n * Generates the content of a dictionary entry point file.\n */\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const sortedLocales = [...locales].sort((a, b) =>\n String(a).localeCompare(String(b))\n );\n\n const localeEntries = sortedLocales\n .map((locale) =>\n format === 'esm'\n ? ` '${locale}': () => import('./${DICTIONARIES_SUBDIR}/${key}/${locale}.json').then(m => m.default)`\n : ` '${locale}': () => Promise.resolve(require('./${DICTIONARIES_SUBDIR}/${key}/${locale}.json'))`\n )\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return `module.exports = {\\n${localeEntries}\\n};\\n`;\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dynamic_dictionary/dictionaries/en_home.json\n * // .intlayer/dynamic_dictionary/dictionaries/fr_home.json\n * ```\n */\nexport const writeDynamicDictionary = async (\n mergedDictionaries: MergedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { locales, defaultLocale } = configuration.internationalization;\n const { dynamicDictionariesDir } = configuration.system;\n\n const dictDir = resolve(dynamicDictionariesDir, DICTIONARIES_SUBDIR);\n await mkdir(dictDir, { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Merge dictionaries with the same key and write to dictionariesDir\n await parallelize(\n Object.entries(mergedDictionaries).sort(([a], [b]) =>\n String(a).localeCompare(String(b))\n ),\n async ([key, dictionaryEntry]) => {\n if (key === 'undefined') return;\n\n const localizedDictionariesPathsRecord: LocalizedDictionaryResult = {};\n\n const keyDir = resolve(dictDir, key);\n assertPathWithin(keyDir, dictDir);\n await mkdir(keyDir, { recursive: true });\n\n await parallelize(locales, async (locale) => {\n const localizedDictionary = getPerLocaleDictionary(\n dictionaryEntry.dictionary,\n locale,\n defaultLocale\n );\n\n // Directory structure: json/key/locale.json\n const resultFilePath = resolve(keyDir, `${locale}.json`);\n\n await writeJsonIfChanged(resultFilePath, localizedDictionary).catch(\n (err) => {\n console.error(\n `Error creating localized ${key}/${locale}.json:`,\n err\n );\n }\n );\n\n localizedDictionariesPathsRecord[locale] = {\n dictionaryPath: resultFilePath,\n dictionary: localizedDictionary,\n };\n });\n\n resultDictionariesPaths[key] = localizedDictionariesPathsRecord;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(key, locales, format);\n\n const dynEntryPath = resolve(\n dynamicDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(dynEntryPath, dynamicDictionariesDir);\n\n await writeFileIfChanged(dynEntryPath, content).catch((err) => {\n console.error(\n `Error creating dynamic ${colorizePath(dynEntryPath)}:`,\n err\n );\n });\n });\n }\n );\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;;;AA4BA,MAAM,sBAAsB;;;;AAK5B,MAAa,gCACX,KACA,SACA,SAAwB,UACb;CAKX,MAAM,gBAJgB,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,MAC1C,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CAGD,CAChC,KAAK,WACJ,WAAW,QACP,MAAM,OAAO,qBAAqB,oBAAoB,GAAG,IAAI,GAAG,OAAO,gCACvE,MAAM,OAAO,sCAAsC,oBAAoB,GAAG,IAAI,GAAG,OAAO,UAC7F,CACA,KAAK,MAAM;CAEd,IAAI,WAAW,OACb,OACE,sBAAsB,cAAc;CAIxC,OAAO,uBAAuB,cAAc;;;;;;;;;;;;;;;;;;AAmB9C,MAAa,yBAAyB,OACpC,oBACA,eACA,UAA6B,kBACU;CACvC,MAAM,EAAE,SAAS,kBAAkB,cAAc;CACjD,MAAM,EAAE,2BAA2B,cAAc;CAEjD,MAAM,UAAU,QAAQ,wBAAwB,oBAAoB;CACpE,MAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;CAEzC,MAAM,0BAAqD,EAAE;CAG7D,MAAM,YACJ,OAAO,QAAQ,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,OAC7C,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CACnC,EACD,OAAO,CAAC,KAAK,qBAAqB;EAChC,IAAI,QAAQ,aAAa;EAEzB,MAAM,mCAA8D,EAAE;EAEtE,MAAM,SAAS,QAAQ,SAAS,IAAI;EACpC,iBAAiB,QAAQ,QAAQ;EACjC,MAAM,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;EAExC,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,sBAAsB,uBAC1B,gBAAgB,YAChB,QACA,cACD;GAGD,MAAM,iBAAiB,QAAQ,QAAQ,GAAG,OAAO,OAAO;GAExD,MAAM,mBAAmB,gBAAgB,oBAAoB,CAAC,OAC3D,QAAQ;IACP,QAAQ,MACN,4BAA4B,IAAI,GAAG,OAAO,SAC1C,IACD;KAEJ;GAED,iCAAiC,UAAU;IACzC,gBAAgB;IAChB,YAAY;IACb;IACD;EAEF,wBAAwB,OAAO;EAE/B,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BAA6B,KAAK,SAAS,OAAO;GAElE,MAAM,eAAe,QACnB,wBACA,GAAG,IAAI,GAAG,YACX;GACD,iBAAiB,cAAc,uBAAuB;GAEtD,MAAM,mBAAmB,cAAc,QAAQ,CAAC,OAAO,QAAQ;IAC7D,QAAQ,MACN,0BAA0B,aAAa,aAAa,CAAC,IACrD,IACD;KACD;IACF;GAEL;CAED,OAAO"}
@@ -3,7 +3,7 @@ import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
3
3
  import { mkdir } from "node:fs/promises";
4
4
  import { relative, resolve } from "node:path";
5
5
  import { colorizePath } from "@intlayer/config/logger";
6
- import { normalizePath } from "@intlayer/config/utils";
6
+ import { assertPathWithin, normalizePath } from "@intlayer/config/utils";
7
7
  import { OUTPUT_FORMAT } from "@intlayer/config/defaultValues";
8
8
 
9
9
  //#region src/buildIntlayerDictionary/writeFetchDictionary.ts
@@ -41,8 +41,10 @@ const writeFetchDictionary = async (dynamicDictionaries, configuration, formats
41
41
  await parallelize(formats, async (format) => {
42
42
  const extension = format === "cjs" ? "cjs" : "mjs";
43
43
  const content = generateDictionaryEntryPoint(key, locales, relativePrefix, format);
44
- await writeFileIfChanged(resolve(fetchDictionariesDir, `${key}.${extension}`), content).catch((err) => {
45
- console.error(`Error creating fetch ${colorizePath(resolve(fetchDictionariesDir, `${key}.${extension}`))}:`, err);
44
+ const fetchEntryPath = resolve(fetchDictionariesDir, `${key}.${extension}`);
45
+ assertPathWithin(fetchEntryPath, fetchDictionariesDir);
46
+ await writeFileIfChanged(fetchEntryPath, content).catch((err) => {
47
+ console.error(`Error creating fetch ${colorizePath(fetchEntryPath)}:`, err);
46
48
  });
47
49
  });
48
50
  });
@@ -1 +1 @@
1
- {"version":3,"file":"writeFetchDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map(\n (locale) =>\n ` '${locale}': async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return dynContent['${locale}']();\\n` +\n ` }\\n` +\n ` }`\n )\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `import { editor } from 'intlayer';\\n` +\n `import dynContent from '${relativePrefix}/${key}.${extension}';\\n\\n` +\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return (\n `const { editor } = require('intlayer');\\n` +\n `const dynContent = require('${relativePrefix}/${key}.${extension}');\\n\\n` +\n `module.exports = {\\n${localeEntries}\\n};\\n`\n );\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionary/home.mjs\n * // .intlayer/fetch_dictionary/home.cjs\n * ```\n */\nexport const writeFetchDictionary = async (\n dynamicDictionaries: LocalizedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;\n const { locales } = configuration.internationalization;\n\n // Compute relative path from fetch dir to dynamic dir\n let relativePrefix = normalizePath(\n relative(fetchDictionariesDir, dynamicDictionariesDir)\n );\n if (!relativePrefix.startsWith('.')) {\n relativePrefix = `./${relativePrefix}`;\n }\n\n await mkdir(resolve(fetchDictionariesDir), { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Write entry points for each dictionary in parallel\n await parallelize(Object.entries(dynamicDictionaries), async ([key]) => {\n if (key === 'undefined') return;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(\n key,\n locales,\n relativePrefix,\n format\n );\n\n await writeFileIfChanged(\n resolve(fetchDictionariesDir, `${key}.${extension}`),\n content\n ).catch((err) => {\n console.error(\n `Error creating fetch ${colorizePath(resolve(fetchDictionariesDir, `${key}.${extension}`))}:`,\n err\n );\n });\n });\n });\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,gCACX,KACA,SACA,gBACA,SAAwB,UACb;CACX,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAE7C,MAAM,gBAAgB,QACnB,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC,CAClD,KACE,WACC,MAAM,OAAO,mGAE0D,IAAI,GAAG,OAAO,gFAGzD,OAAO,mBAGtC,CACA,KAAK,MAAM;CAEd,IAAI,WAAW,OACb,OACE,+DAC2B,eAAe,GAAG,IAAI,GAAG,UAAU,2BACxC,cAAc;CAIxC,OACE,wEAC+B,eAAe,GAAG,IAAI,GAAG,UAAU,6BAC3C,cAAc;;;;;;;;;;;;;;;;;;AAoBzC,MAAa,uBAAuB,OAClC,qBACA,eACA,UAA6B,kBACU;CACvC,MAAM,EAAE,sBAAsB,2BAA2B,cAAc;CACvE,MAAM,EAAE,YAAY,cAAc;CAGlC,IAAI,iBAAiB,cACnB,SAAS,sBAAsB,uBAAuB,CACvD;CACD,IAAI,CAAC,eAAe,WAAW,IAAI,EACjC,iBAAiB,KAAK;CAGxB,MAAM,MAAM,QAAQ,qBAAqB,EAAE,EAAE,WAAW,MAAM,CAAC;CAE/D,MAAM,0BAAqD,EAAE;CAG7D,MAAM,YAAY,OAAO,QAAQ,oBAAoB,EAAE,OAAO,CAAC,SAAS;EACtE,IAAI,QAAQ,aAAa;EAEzB,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BACd,KACA,SACA,gBACA,OACD;GAED,MAAM,mBACJ,QAAQ,sBAAsB,GAAG,IAAI,GAAG,YAAY,EACpD,QACD,CAAC,OAAO,QAAQ;IACf,QAAQ,MACN,wBAAwB,aAAa,QAAQ,sBAAsB,GAAG,IAAI,GAAG,YAAY,CAAC,CAAC,IAC3F,IACD;KACD;IACF;GACF;CAEF,OAAO"}
1
+ {"version":3,"file":"writeFetchDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeFetchDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin, normalizePath } from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { parallelize } from '../utils/parallelize';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\nimport type { LocalizedDictionaryOutput } from './writeDynamicDictionary';\n\nexport const generateDictionaryEntryPoint = (\n key: string,\n locales: string[],\n relativePrefix: string,\n format: 'cjs' | 'esm' = 'esm'\n): string => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n\n const localeEntries = locales\n .sort((a, b) => String(a).localeCompare(String(b)))\n .map(\n (locale) =>\n ` '${locale}': async () => {\\n` +\n ` try {\\n` +\n ` const res = await fetch(\\`\\${editor.liveSyncURL}/dictionaries/${key}/${locale}\\`);\\n` +\n ` return await res.json();\\n` +\n ` } catch {\\n` +\n ` return dynContent['${locale}']();\\n` +\n ` }\\n` +\n ` }`\n )\n .join(',\\n');\n\n if (format === 'esm') {\n return (\n `import { editor } from 'intlayer';\\n` +\n `import dynContent from '${relativePrefix}/${key}.${extension}';\\n\\n` +\n `const content = {\\n${localeEntries}\\n};\\n\\n` +\n `export default content;\\n`\n );\n }\n return (\n `const { editor } = require('intlayer');\\n` +\n `const dynContent = require('${relativePrefix}/${key}.${extension}');\\n\\n` +\n `module.exports = {\\n${localeEntries}\\n};\\n`\n );\n};\n\n/**\n * Write the localized dictionaries to the dictionariesDir\n * @param mergedDictionaries - The merged dictionaries\n * @param configuration - The configuration\n * @returns The final dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/fetch_dictionary/home.mjs\n * // .intlayer/fetch_dictionary/home.cjs\n * ```\n */\nexport const writeFetchDictionary = async (\n dynamicDictionaries: LocalizedDictionaryOutput,\n configuration: IntlayerConfig,\n formats: ('cjs' | 'esm')[] = OUTPUT_FORMAT\n): Promise<LocalizedDictionaryOutput> => {\n const { fetchDictionariesDir, dynamicDictionariesDir } = configuration.system;\n const { locales } = configuration.internationalization;\n\n // Compute relative path from fetch dir to dynamic dir\n let relativePrefix = normalizePath(\n relative(fetchDictionariesDir, dynamicDictionariesDir)\n );\n if (!relativePrefix.startsWith('.')) {\n relativePrefix = `./${relativePrefix}`;\n }\n\n await mkdir(resolve(fetchDictionariesDir), { recursive: true });\n\n const resultDictionariesPaths: LocalizedDictionaryOutput = {};\n\n // Write entry points for each dictionary in parallel\n await parallelize(Object.entries(dynamicDictionaries), async ([key]) => {\n if (key === 'undefined') return;\n\n await parallelize(formats, async (format) => {\n const extension = format === 'cjs' ? 'cjs' : 'mjs';\n const content = generateDictionaryEntryPoint(\n key,\n locales,\n relativePrefix,\n format\n );\n\n const fetchEntryPath = resolve(\n fetchDictionariesDir,\n `${key}.${extension}`\n );\n assertPathWithin(fetchEntryPath, fetchDictionariesDir);\n\n await writeFileIfChanged(fetchEntryPath, content).catch((err) => {\n console.error(\n `Error creating fetch ${colorizePath(fetchEntryPath)}:`,\n err\n );\n });\n });\n });\n\n return resultDictionariesPaths;\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,gCACX,KACA,SACA,gBACA,SAAwB,UACb;CACX,MAAM,YAAY,WAAW,QAAQ,QAAQ;CAE7C,MAAM,gBAAgB,QACnB,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC,CAClD,KACE,WACC,MAAM,OAAO,mGAE0D,IAAI,GAAG,OAAO,gFAGzD,OAAO,mBAGtC,CACA,KAAK,MAAM;CAEd,IAAI,WAAW,OACb,OACE,+DAC2B,eAAe,GAAG,IAAI,GAAG,UAAU,2BACxC,cAAc;CAIxC,OACE,wEAC+B,eAAe,GAAG,IAAI,GAAG,UAAU,6BAC3C,cAAc;;;;;;;;;;;;;;;;;;AAoBzC,MAAa,uBAAuB,OAClC,qBACA,eACA,UAA6B,kBACU;CACvC,MAAM,EAAE,sBAAsB,2BAA2B,cAAc;CACvE,MAAM,EAAE,YAAY,cAAc;CAGlC,IAAI,iBAAiB,cACnB,SAAS,sBAAsB,uBAAuB,CACvD;CACD,IAAI,CAAC,eAAe,WAAW,IAAI,EACjC,iBAAiB,KAAK;CAGxB,MAAM,MAAM,QAAQ,qBAAqB,EAAE,EAAE,WAAW,MAAM,CAAC;CAE/D,MAAM,0BAAqD,EAAE;CAG7D,MAAM,YAAY,OAAO,QAAQ,oBAAoB,EAAE,OAAO,CAAC,SAAS;EACtE,IAAI,QAAQ,aAAa;EAEzB,MAAM,YAAY,SAAS,OAAO,WAAW;GAC3C,MAAM,YAAY,WAAW,QAAQ,QAAQ;GAC7C,MAAM,UAAU,6BACd,KACA,SACA,gBACA,OACD;GAED,MAAM,iBAAiB,QACrB,sBACA,GAAG,IAAI,GAAG,YACX;GACD,iBAAiB,gBAAgB,qBAAqB;GAEtD,MAAM,mBAAmB,gBAAgB,QAAQ,CAAC,OAAO,QAAQ;IAC/D,QAAQ,MACN,wBAAwB,aAAa,eAAe,CAAC,IACrD,IACD;KACD;IACF;GACF;CAEF,OAAO"}
@@ -3,6 +3,7 @@ import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
3
3
  import { mkdir } from "node:fs/promises";
4
4
  import { resolve } from "node:path";
5
5
  import { colorizePath } from "@intlayer/config/logger";
6
+ import { assertPathWithin } from "@intlayer/config/utils";
6
7
  import { mergeDictionaries, normalizeDictionaries } from "@intlayer/core/dictionaryManipulator";
7
8
 
8
9
  //#region src/buildIntlayerDictionary/writeMergedDictionary.ts
@@ -29,6 +30,7 @@ const writeMergedDictionaries = async (groupedDictionaries, configuration) => {
29
30
  if (key === "undefined") return;
30
31
  const mergedDictionary = mergeDictionaries(normalizeDictionaries(dictionariesEntry.dictionaries, configuration));
31
32
  const resultFilePath = resolve(dictionariesDir, `${key}.json`);
33
+ assertPathWithin(resultFilePath, dictionariesDir);
32
34
  await writeJsonIfChanged(resultFilePath, mergedDictionary).catch((err) => {
33
35
  console.error(`Error creating merged ${colorizePath(resultFilePath)}:`, err);
34
36
  });
@@ -1 +1 @@
1
- {"version":3,"file":"writeMergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath } from '@intlayer/config/logger';\nimport {\n mergeDictionaries,\n normalizeDictionaries,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { UnmergedDictionaryOutput } from './writeUnmergedDictionary';\n\nexport type MergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type MergedDictionaryOutput = Record<string, MergedDictionaryResult>;\n\n/**\n * Write the merged dictionaries to the dictionariesDir\n * @param groupedDictionaries - The grouped dictionaries\n * @param configuration - The configuration\n * @returns The merged dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dictionary/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeMergedDictionaries = async (\n groupedDictionaries: UnmergedDictionaryOutput,\n configuration: IntlayerConfig\n): Promise<MergedDictionaryOutput> => {\n const { dictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(dictionariesDir), { recursive: true });\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionariesEntry]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n MergedDictionaryResult,\n ];\n }\n\n const normalizedDictionaries = normalizeDictionaries(\n dictionariesEntry.dictionaries,\n configuration\n );\n\n const mergedDictionary = mergeDictionaries(normalizedDictionaries);\n\n const outputFileName = `${key}.json`;\n const resultFilePath = resolve(dictionariesDir, outputFileName);\n\n // Write the merged dictionary\n await writeJsonIfChanged(resultFilePath, mergedDictionary).catch(\n (err) => {\n console.error(\n `Error creating merged ${colorizePath(resultFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: resultFilePath,\n dictionary: mergedDictionary,\n } as MergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<readonly [string, MergedDictionaryResult]>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,0BAA0B,OACrC,qBACA,kBACoC;CACpC,MAAM,EAAE,oBAAoB,cAAc;CAG1C,MAAM,MAAM,QAAQ,gBAAgB,EAAE,EAAE,WAAW,MAAM,CAAC;CAE1D,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,oBAAoB,EACnC,OAAO,CAAC,KAAK,uBAAuB;EAClC,IAAI,QAAQ,aACV;EAWF,MAAM,mBAAmB,kBALM,sBAC7B,kBAAkB,cAClB,cAG+D,CAAC;EAGlE,MAAM,iBAAiB,QAAQ,iBAAiB,GADtB,IAAI,OACiC;EAG/D,MAAM,mBAAmB,gBAAgB,iBAAiB,CAAC,OACxD,QAAQ;GACP,QAAQ,MACN,yBAAyB,aAAa,eAAe,CAAC,IACtD,IACD;IAEJ;EAED,OAAO,CACL,KACA;GACE,gBAAgB;GAChB,YAAY;GACb,CACF;GAEJ;CAED,OAAO,OAAO,YACZ,QAAQ,OAAO,QAAQ,CACxB"}
1
+ {"version":3,"file":"writeMergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport {\n mergeDictionaries,\n normalizeDictionaries,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\nimport type { UnmergedDictionaryOutput } from './writeUnmergedDictionary';\n\nexport type MergedDictionaryResult = {\n dictionaryPath: string;\n dictionary: Dictionary;\n};\n\nexport type MergedDictionaryOutput = Record<string, MergedDictionaryResult>;\n\n/**\n * Write the merged dictionaries to the dictionariesDir\n * @param groupedDictionaries - The grouped dictionaries\n * @param configuration - The configuration\n * @returns The merged dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * const finalDictionaries = await writeFinalDictionaries(unmergedDictionaries);\n * console.log(finalDictionaries);\n *\n * // .intlayer/dictionary/home.json\n * // { key: 'home', content: { ... } },\n * ```\n */\nexport const writeMergedDictionaries = async (\n groupedDictionaries: UnmergedDictionaryOutput,\n configuration: IntlayerConfig\n): Promise<MergedDictionaryOutput> => {\n const { dictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(dictionariesDir), { recursive: true });\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionariesEntry]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n MergedDictionaryResult,\n ];\n }\n\n const normalizedDictionaries = normalizeDictionaries(\n dictionariesEntry.dictionaries,\n configuration\n );\n\n const mergedDictionary = mergeDictionaries(normalizedDictionaries);\n\n const outputFileName = `${key}.json`;\n const resultFilePath = resolve(dictionariesDir, outputFileName);\n\n assertPathWithin(resultFilePath, dictionariesDir);\n\n // Write the merged dictionary\n await writeJsonIfChanged(resultFilePath, mergedDictionary).catch(\n (err) => {\n console.error(\n `Error creating merged ${colorizePath(resultFilePath)}:`,\n err\n );\n }\n );\n\n return [\n key,\n {\n dictionaryPath: resultFilePath,\n dictionary: mergedDictionary,\n } as MergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<readonly [string, MergedDictionaryResult]>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,0BAA0B,OACrC,qBACA,kBACoC;CACpC,MAAM,EAAE,oBAAoB,cAAc;CAG1C,MAAM,MAAM,QAAQ,gBAAgB,EAAE,EAAE,WAAW,MAAM,CAAC;CAE1D,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,oBAAoB,EACnC,OAAO,CAAC,KAAK,uBAAuB;EAClC,IAAI,QAAQ,aACV;EAWF,MAAM,mBAAmB,kBALM,sBAC7B,kBAAkB,cAClB,cAG+D,CAAC;EAGlE,MAAM,iBAAiB,QAAQ,iBAAiB,GADtB,IAAI,OACiC;EAE/D,iBAAiB,gBAAgB,gBAAgB;EAGjD,MAAM,mBAAmB,gBAAgB,iBAAiB,CAAC,OACxD,QAAQ;GACP,QAAQ,MACN,yBAAyB,aAAa,eAAe,CAAC,IACtD,IACD;IAEJ;EAED,OAAO,CACL,KACA;GACE,gBAAgB;GAChB,YAAY;GACb,CACF;GAEJ;CAED,OAAO,OAAO,YACZ,QAAQ,OAAO,QAAQ,CACxB"}
@@ -4,6 +4,7 @@ import { filterInvalidDictionaries } from "../filterInvalidDictionaries.mjs";
4
4
  import { mkdir } from "node:fs/promises";
5
5
  import { resolve } from "node:path";
6
6
  import { colorizePath, x } from "@intlayer/config/logger";
7
+ import { assertPathWithin } from "@intlayer/config/utils";
7
8
  import { orderDictionaries } from "@intlayer/core/dictionaryManipulator";
8
9
 
9
10
  //#region src/buildIntlayerDictionary/writeUnmergedDictionary.ts
@@ -41,6 +42,7 @@ const writeUnmergedDictionaries = async (dictionaries, configuration, env) => {
41
42
  if (key === "undefined") return;
42
43
  const orderedDictionaries = orderDictionaries(dictionaries);
43
44
  const unmergedFilePath = resolve(unmergedDictionariesDir, `${key}.json`);
45
+ assertPathWithin(unmergedFilePath, unmergedDictionariesDir);
44
46
  if (configuration.editor.enabled || env === "dev") await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch((err) => {
45
47
  console.error(`${x} Error creating unmerged ${colorizePath(unmergedFilePath)}:`, err);
46
48
  });
@@ -1 +1 @@
1
- {"version":3,"file":"writeUnmergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeUnmergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { orderDictionaries } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, DictionaryKey } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\n\nexport const groupDictionariesByKey = (\n dictionaries: Dictionary[]\n): Record<string, Dictionary[]> =>\n dictionaries.reduce(\n (acc, dictionary) => {\n const key = dictionary.key;\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(dictionary);\n return acc;\n },\n {} as Record<string, Dictionary[]>\n );\n\nexport type UnmergedDictionaryResult = {\n dictionaryPath: string;\n dictionaries: Dictionary[];\n};\n\nexport type UnmergedDictionaryOutput = Record<\n DictionaryKey,\n UnmergedDictionaryResult\n>;\n\n/**\n * Write the unmerged dictionaries to the unmergedDictionariesDir\n * @param dictionaries - The dictionaries to write\n * @param configuration - The configuration\n * @returns The grouped dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * console.log(unmergedDictionaries);\n *\n * // .intlayer/unmerged_dictionaries/home.json\n * // {\n * // [\n * // { key: 'home', content: { ... } },\n * // { key: 'home', content: { ... } },\n * // ],\n * // }\n * ```\n */\nexport const writeUnmergedDictionaries = async (\n dictionaries: Dictionary[],\n configuration: IntlayerConfig,\n env: 'prod' | 'dev'\n): Promise<UnmergedDictionaryOutput> => {\n const { unmergedDictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(unmergedDictionariesDir), { recursive: true });\n\n const filteredDictionaries = filterInvalidDictionaries(\n dictionaries,\n configuration,\n { checkSchema: true }\n );\n\n // Group dictionaries by key and write to unmergedDictionariesDir\n const groupedDictionaries = groupDictionariesByKey(filteredDictionaries);\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionaries]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n UnmergedDictionaryResult,\n ];\n }\n\n const orderedDictionaries = orderDictionaries(dictionaries);\n\n const outputFileName = `${key}.json`;\n const unmergedFilePath = resolve(unmergedDictionariesDir, outputFileName);\n\n // Write the grouped dictionaries in disk if the editor is enabled\n // To make work the visual editor on the server\n // No need them if the editor is disabled\n // But in local env (env: 'dev') we write them for the vscode extension\n if (configuration.editor.enabled || env === 'dev') {\n await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch(\n (err) => {\n console.error(\n `${x} Error creating unmerged ${colorizePath(unmergedFilePath)}:`,\n err\n );\n }\n );\n }\n\n return [\n key,\n {\n dictionaryPath: unmergedFilePath,\n dictionaries: dictionaries,\n } as UnmergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<\n readonly [string, UnmergedDictionaryResult]\n >\n );\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,0BACX,iBAEA,aAAa,QACV,KAAK,eAAe;CACnB,MAAM,MAAM,WAAW;CACvB,IAAI,CAAC,IAAI,MACP,IAAI,OAAO,EAAE;CAEf,IAAI,KAAK,KAAK,WAAW;CACzB,OAAO;GAET,EAAE,CACH;;;;;;;;;;;;;;;;;;;;;AAgCH,MAAa,4BAA4B,OACvC,cACA,eACA,QACsC;CACtC,MAAM,EAAE,4BAA4B,cAAc;CAGlD,MAAM,MAAM,QAAQ,wBAAwB,EAAE,EAAE,WAAW,MAAM,CAAC;CASlE,MAAM,sBAAsB,uBAPC,0BAC3B,cACA,eACA,EAAE,aAAa,MAAM,CAIgD,CAAC;CAExE,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,oBAAoB,EACnC,OAAO,CAAC,KAAK,kBAAkB;EAC7B,IAAI,QAAQ,aACV;EAMF,MAAM,sBAAsB,kBAAkB,aAAa;EAG3D,MAAM,mBAAmB,QAAQ,yBAAyB,GADhC,IAAI,OAC2C;EAMzE,IAAI,cAAc,OAAO,WAAW,QAAQ,OAC1C,MAAM,mBAAmB,kBAAkB,oBAAoB,CAAC,OAC7D,QAAQ;GACP,QAAQ,MACN,GAAG,EAAE,2BAA2B,aAAa,iBAAiB,CAAC,IAC/D,IACD;IAEJ;EAGH,OAAO,CACL,KACA;GACE,gBAAgB;GACF;GACf,CACF;GAEJ;CAED,OAAO,OAAO,YACZ,QAAQ,OAAO,QAAQ,CAGxB"}
1
+ {"version":3,"file":"writeUnmergedDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/writeUnmergedDictionary.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { colorizePath, x } from '@intlayer/config/logger';\nimport { assertPathWithin } from '@intlayer/config/utils';\nimport { orderDictionaries } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, DictionaryKey } from '@intlayer/types/dictionary';\nimport { filterInvalidDictionaries } from '../filterInvalidDictionaries';\nimport { parallelize } from '../utils/parallelize';\nimport { writeJsonIfChanged } from '../writeJsonIfChanged';\n\nexport const groupDictionariesByKey = (\n dictionaries: Dictionary[]\n): Record<string, Dictionary[]> =>\n dictionaries.reduce(\n (acc, dictionary) => {\n const key = dictionary.key;\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(dictionary);\n return acc;\n },\n {} as Record<string, Dictionary[]>\n );\n\nexport type UnmergedDictionaryResult = {\n dictionaryPath: string;\n dictionaries: Dictionary[];\n};\n\nexport type UnmergedDictionaryOutput = Record<\n DictionaryKey,\n UnmergedDictionaryResult\n>;\n\n/**\n * Write the unmerged dictionaries to the unmergedDictionariesDir\n * @param dictionaries - The dictionaries to write\n * @param configuration - The configuration\n * @returns The grouped dictionaries\n *\n * @example\n * ```ts\n * const unmergedDictionaries = await writeUnmergedDictionaries(dictionaries);\n * console.log(unmergedDictionaries);\n *\n * // .intlayer/unmerged_dictionaries/home.json\n * // {\n * // [\n * // { key: 'home', content: { ... } },\n * // { key: 'home', content: { ... } },\n * // ],\n * // }\n * ```\n */\nexport const writeUnmergedDictionaries = async (\n dictionaries: Dictionary[],\n configuration: IntlayerConfig,\n env: 'prod' | 'dev'\n): Promise<UnmergedDictionaryOutput> => {\n const { unmergedDictionariesDir } = configuration.system;\n\n // Create the dictionaries folder if it doesn't exist\n await mkdir(resolve(unmergedDictionariesDir), { recursive: true });\n\n const filteredDictionaries = filterInvalidDictionaries(\n dictionaries,\n configuration,\n { checkSchema: true }\n );\n\n // Group dictionaries by key and write to unmergedDictionariesDir\n const groupedDictionaries = groupDictionariesByKey(filteredDictionaries);\n\n const results = await parallelize(\n Object.entries(groupedDictionaries),\n async ([key, dictionaries]) => {\n if (key === 'undefined') {\n return undefined as unknown as readonly [\n string,\n UnmergedDictionaryResult,\n ];\n }\n\n const orderedDictionaries = orderDictionaries(dictionaries);\n\n const outputFileName = `${key}.json`;\n const unmergedFilePath = resolve(unmergedDictionariesDir, outputFileName);\n\n assertPathWithin(unmergedFilePath, unmergedDictionariesDir);\n\n // Write the grouped dictionaries in disk if the editor is enabled\n // To make work the visual editor on the server\n // No need them if the editor is disabled\n // But in local env (env: 'dev') we write them for the vscode extension\n if (configuration.editor.enabled || env === 'dev') {\n await writeJsonIfChanged(unmergedFilePath, orderedDictionaries).catch(\n (err) => {\n console.error(\n `${x} Error creating unmerged ${colorizePath(unmergedFilePath)}:`,\n err\n );\n }\n );\n }\n\n return [\n key,\n {\n dictionaryPath: unmergedFilePath,\n dictionaries: dictionaries,\n } as UnmergedDictionaryResult,\n ] as const;\n }\n );\n\n return Object.fromEntries(\n results.filter(Boolean) as Array<\n readonly [string, UnmergedDictionaryResult]\n >\n );\n};\n"],"mappings":";;;;;;;;;;AAWA,MAAa,0BACX,iBAEA,aAAa,QACV,KAAK,eAAe;CACnB,MAAM,MAAM,WAAW;CACvB,IAAI,CAAC,IAAI,MACP,IAAI,OAAO,EAAE;CAEf,IAAI,KAAK,KAAK,WAAW;CACzB,OAAO;GAET,EAAE,CACH;;;;;;;;;;;;;;;;;;;;;AAgCH,MAAa,4BAA4B,OACvC,cACA,eACA,QACsC;CACtC,MAAM,EAAE,4BAA4B,cAAc;CAGlD,MAAM,MAAM,QAAQ,wBAAwB,EAAE,EAAE,WAAW,MAAM,CAAC;CASlE,MAAM,sBAAsB,uBAPC,0BAC3B,cACA,eACA,EAAE,aAAa,MAAM,CAIgD,CAAC;CAExE,MAAM,UAAU,MAAM,YACpB,OAAO,QAAQ,oBAAoB,EACnC,OAAO,CAAC,KAAK,kBAAkB;EAC7B,IAAI,QAAQ,aACV;EAMF,MAAM,sBAAsB,kBAAkB,aAAa;EAG3D,MAAM,mBAAmB,QAAQ,yBAAyB,GADhC,IAAI,OAC2C;EAEzE,iBAAiB,kBAAkB,wBAAwB;EAM3D,IAAI,cAAc,OAAO,WAAW,QAAQ,OAC1C,MAAM,mBAAmB,kBAAkB,oBAAoB,CAAC,OAC7D,QAAQ;GACP,QAAQ,MACN,GAAG,EAAE,2BAA2B,aAAa,iBAAiB,CAAC,IAC/D,IACD;IAEJ;EAGH,OAAO,CACL,KACA;GACE,gBAAgB;GACF;GACf,CACF;GAEJ;CAED,OAAO,OAAO,YACZ,QAAQ,OAAO,QAAQ,CAGxB"}
@@ -4,7 +4,6 @@ import { mkdir } from "node:fs/promises";
4
4
  import { basename, extname, join, relative } from "node:path";
5
5
  import fg from "fast-glob";
6
6
  import { kebabCaseToCamelCase, normalizePath } from "@intlayer/config/utils";
7
- import { createAuxiliaryTypeStore, printNode, zodToTs } from "zod-to-ts";
8
7
 
9
8
  //#region src/createType/createModuleAugmentation.ts
10
9
  const getTypeName = (key) => `${kebabCaseToCamelCase(key)}Content`;
@@ -51,7 +50,7 @@ const zodToTsString = (schema) => {
51
50
  }
52
51
  };
53
52
  /** Generate the content of the module augmentation file */
54
- const generateTypeIndexContent = (typeFiles, configuration) => {
53
+ const generateTypeIndexContent = (typeFiles, configuration, zodToTsFns) => {
55
54
  const { internationalization, system, editor } = configuration;
56
55
  const { moduleAugmentationDir } = system;
57
56
  const { enabled } = editor;
@@ -73,9 +72,11 @@ const generateTypeIndexContent = (typeFiles, configuration) => {
73
72
  const formattedSchemas = Object.entries(schemas).map(([key, schema]) => {
74
73
  let typeStr = "any";
75
74
  if (schema) try {
76
- const { node } = zodToTs(schema, { auxiliaryTypeStore: createAuxiliaryTypeStore() });
77
- if (node.kind !== 133) typeStr = printNode(node);
78
- else typeStr = zodToTsString(schema);
75
+ if (zodToTsFns) {
76
+ const { node } = zodToTsFns.zodToTs(schema, { auxiliaryTypeStore: zodToTsFns.createAuxiliaryTypeStore() });
77
+ if (node.kind !== 133) typeStr = zodToTsFns.printNode(node);
78
+ else typeStr = zodToTsString(schema);
79
+ } else typeStr = zodToTsString(schema);
79
80
  } catch (_e) {
80
81
  typeStr = zodToTsString(schema);
81
82
  }
@@ -100,7 +101,17 @@ const generateTypeIndexContent = (typeFiles, configuration) => {
100
101
  const createModuleAugmentation = async (configuration) => {
101
102
  const { moduleAugmentationDir, typesDir } = configuration.system;
102
103
  await mkdir(moduleAugmentationDir, { recursive: true });
103
- const tsContent = generateTypeIndexContent(await fg(normalizePath(`${typesDir}/*.ts`), { ignore: ["**/*.d.ts"] }), configuration);
104
+ const dictionariesTypesDefinitions = await fg(normalizePath(`${typesDir}/*.ts`), { ignore: ["**/*.d.ts"] });
105
+ let zodToTsFns = null;
106
+ try {
107
+ const mod = await import("zod-to-ts");
108
+ zodToTsFns = {
109
+ zodToTs: mod.zodToTs,
110
+ printNode: mod.printNode,
111
+ createAuxiliaryTypeStore: mod.createAuxiliaryTypeStore
112
+ };
113
+ } catch {}
114
+ const tsContent = generateTypeIndexContent(dictionariesTypesDefinitions, configuration, zodToTsFns);
104
115
  await writeFileIfChanged(join(moduleAugmentationDir, "intlayer.d.ts"), tsContent);
105
116
  };
106
117
 
@@ -1 +1 @@
1
- {"version":3,"file":"createModuleAugmentation.mjs","names":[],"sources":["../../../src/createType/createModuleAugmentation.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { basename, extname, join, relative } from 'node:path';\nimport { kebabCaseToCamelCase, normalizePath } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\nimport { createAuxiliaryTypeStore, printNode, zodToTs } from 'zod-to-ts';\nimport { getPathHash } from '../utils';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\n\nexport const getTypeName = (key: string): string =>\n `${kebabCaseToCamelCase(key)}Content`;\n\n/** Returns lines like: [Locales.FRENCH]: 1; */\nconst formatLocales = (locales: Locale[]) =>\n locales.map((locale) => ` \"${locale}\": 1;`).join('\\n');\n\nconst zodToTsString = (schema: any): string => {\n if (!schema) return 'any';\n\n // Support both real Zod objects (_def) and serialized versions (def or nested)\n const def = schema._def ?? schema.def ?? schema;\n\n // Handle serialized type names (sometimes 'type' instead of 'typeName')\n const typeName = def.typeName ?? def.type;\n\n switch (typeName) {\n case 'ZodString':\n case 'string':\n return 'string';\n case 'ZodNumber':\n case 'number':\n return 'number';\n case 'ZodBoolean':\n case 'boolean':\n return 'boolean';\n case 'ZodNull':\n case 'null':\n return 'null';\n case 'ZodUndefined':\n case 'undefined':\n return 'undefined';\n case 'ZodArray':\n case 'array':\n return `${zodToTsString(def.type ?? def.element)}[]`;\n case 'ZodObject':\n case 'object': {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n if (!shape) return 'Record<string, any>';\n\n const entries = Object.entries(shape)\n .map(([k, v]) => ` \"${k}\": ${zodToTsString(v)};`)\n .join('\\n');\n return `{\\n${entries}\\n }`;\n }\n case 'ZodOptional':\n case 'optional':\n return `${zodToTsString(def.innerType ?? def.wrapped)} | undefined`;\n case 'ZodNullable':\n case 'nullable':\n return `${zodToTsString(def.innerType ?? def.wrapped)} | null`;\n case 'ZodUnion':\n case 'union': {\n const options = def.options ?? [];\n return options.map(zodToTsString).join(' | ');\n }\n case 'ZodIntersection':\n case 'intersection':\n return `${zodToTsString(def.left)} & ${zodToTsString(def.right)}`;\n case 'ZodEnum':\n case 'enum': {\n const values = def.values ?? [];\n return values.map((v: string) => `\"${v}\"`).join(' | ');\n }\n case 'ZodLiteral':\n case 'literal': {\n const value = def.value;\n return typeof value === 'string' ? `\"${value}\"` : String(value);\n }\n default:\n return 'any';\n }\n};\n\n/** Generate the content of the module augmentation file */\nconst generateTypeIndexContent = (\n typeFiles: string[],\n configuration: IntlayerConfig\n): string => {\n const { internationalization, system, editor } = configuration;\n const { moduleAugmentationDir } = system;\n const { enabled } = editor;\n const { locales, requiredLocales, strictMode } = internationalization;\n\n let fileContent = 'import \"intlayer\";\\n';\n\n // Build dictionary refs\n const dictionariesRef = typeFiles.map((dictionaryPath) => ({\n relativePath: `./${relative(moduleAugmentationDir, dictionaryPath)}`,\n id: basename(dictionaryPath, extname(dictionaryPath)),\n hash: `_${getPathHash(dictionaryPath)}`,\n }));\n\n // Import all dictionaries\n for (const dictionary of dictionariesRef) {\n fileContent += `import ${dictionary.hash} from '${dictionary.relativePath}';\\n`;\n }\n fileContent += '\\n';\n\n // Dictionary map entries (id: typeof <hash>)\n const formattedDictionaryMap: string = dictionariesRef\n .map((dictionary) => ` \"${dictionary.id}\": typeof ${dictionary.hash};`)\n .join('\\n');\n\n // Ensure required ⊆ declared; if empty, default required = declared\n const declared = locales;\n const requiredSanitized = requiredLocales?.length\n ? requiredLocales.filter((requiredLocales) =>\n declared.includes(requiredLocales)\n )\n : declared;\n\n const formattedDeclaredLocales = formatLocales(declared);\n const formattedRequiredLocales = formatLocales(requiredSanitized);\n\n // Build schema registry\n const schemas = configuration.schemas ?? {};\n const formattedSchemas = Object.entries(schemas)\n .map(([key, schema]) => {\n let typeStr = 'any';\n\n if (schema) {\n try {\n const { node } = zodToTs(schema, {\n auxiliaryTypeStore: createAuxiliaryTypeStore(),\n });\n // 133 is the kind for AnyKeyword in TypeScript\n if ((node as any).kind !== 133) {\n typeStr = printNode(node);\n } else {\n // Fallback to custom string generator if zodToTs returns any\n typeStr = zodToTsString(schema);\n }\n } catch (_e) {\n // Fallback to custom string generator\n typeStr = zodToTsString(schema);\n }\n }\n return ` \"${key}\": ${typeStr};`;\n })\n .join('\\n');\n\n // Choose strict mode registry key\n const strictKey =\n strictMode === 'strict'\n ? 'strict'\n : strictMode === 'inclusive'\n ? 'inclusive'\n : 'loose';\n\n /**\n * Module augmentation that ONLY adds keys to registries.\n * No types/aliases redefined here—avoids merge conflicts.\n */\n fileContent += `declare module 'intlayer' {\\n`;\n // Dictionaries registry\n fileContent += ` interface __DictionaryRegistry {\\n${formattedDictionaryMap}\\n }\\n\\n`;\n // Locales registries\n fileContent += ` interface __DeclaredLocalesRegistry {\\n${formattedDeclaredLocales}\\n }\\n\\n`;\n fileContent += ` interface __RequiredLocalesRegistry {\\n${formattedRequiredLocales}\\n }\\n\\n`;\n // Schema registry\n fileContent += ` interface __SchemaRegistry {\\n${formattedSchemas}\\n }\\n\\n`;\n // Resolved strict mode (narrow the literal at build time)\n fileContent += ` interface __StrictModeRegistry { mode: '${strictKey}' }\\n\\n`;\n // Editor registry\n fileContent += ` interface __EditorRegistry { enabled : ${enabled} } \\n`;\n fileContent += `}\\n`;\n\n return fileContent;\n};\n\n/** Generate the index file merging all the types */\nexport const createModuleAugmentation = async (\n configuration: IntlayerConfig\n) => {\n const { moduleAugmentationDir, typesDir } = configuration.system;\n\n await mkdir(moduleAugmentationDir, { recursive: true });\n\n const dictionariesTypesDefinitions: string[] = await fg(\n normalizePath(`${typesDir}/*.ts`),\n { ignore: ['**/*.d.ts'] }\n );\n\n const tsContent = generateTypeIndexContent(\n dictionariesTypesDefinitions,\n configuration\n );\n\n const tsFilePath = join(moduleAugmentationDir, 'intlayer.d.ts');\n await writeFileIfChanged(tsFilePath, tsContent);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"createModuleAugmentation.mjs","names":[],"sources":["../../../src/createType/createModuleAugmentation.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { basename, extname, join, relative } from 'node:path';\nimport { kebabCaseToCamelCase, normalizePath } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\nimport { getPathHash } from '../utils';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\n\nexport const getTypeName = (key: string): string =>\n `${kebabCaseToCamelCase(key)}Content`;\n\n/** Returns lines like: [Locales.FRENCH]: 1; */\nconst formatLocales = (locales: Locale[]) =>\n locales.map((locale) => ` \"${locale}\": 1;`).join('\\n');\n\nconst zodToTsString = (schema: any): string => {\n if (!schema) return 'any';\n\n // Support both real Zod objects (_def) and serialized versions (def or nested)\n const def = schema._def ?? schema.def ?? schema;\n\n // Handle serialized type names (sometimes 'type' instead of 'typeName')\n const typeName = def.typeName ?? def.type;\n\n switch (typeName) {\n case 'ZodString':\n case 'string':\n return 'string';\n case 'ZodNumber':\n case 'number':\n return 'number';\n case 'ZodBoolean':\n case 'boolean':\n return 'boolean';\n case 'ZodNull':\n case 'null':\n return 'null';\n case 'ZodUndefined':\n case 'undefined':\n return 'undefined';\n case 'ZodArray':\n case 'array':\n return `${zodToTsString(def.type ?? def.element)}[]`;\n case 'ZodObject':\n case 'object': {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n if (!shape) return 'Record<string, any>';\n\n const entries = Object.entries(shape)\n .map(([k, v]) => ` \"${k}\": ${zodToTsString(v)};`)\n .join('\\n');\n return `{\\n${entries}\\n }`;\n }\n case 'ZodOptional':\n case 'optional':\n return `${zodToTsString(def.innerType ?? def.wrapped)} | undefined`;\n case 'ZodNullable':\n case 'nullable':\n return `${zodToTsString(def.innerType ?? def.wrapped)} | null`;\n case 'ZodUnion':\n case 'union': {\n const options = def.options ?? [];\n return options.map(zodToTsString).join(' | ');\n }\n case 'ZodIntersection':\n case 'intersection':\n return `${zodToTsString(def.left)} & ${zodToTsString(def.right)}`;\n case 'ZodEnum':\n case 'enum': {\n const values = def.values ?? [];\n return values.map((v: string) => `\"${v}\"`).join(' | ');\n }\n case 'ZodLiteral':\n case 'literal': {\n const value = def.value;\n return typeof value === 'string' ? `\"${value}\"` : String(value);\n }\n default:\n return 'any';\n }\n};\n\ntype ZodToTsFns = {\n zodToTs: (schema: any, opts?: any) => { node: any };\n printNode: (node: any) => string;\n createAuxiliaryTypeStore: () => any;\n};\n\n/** Generate the content of the module augmentation file */\nconst generateTypeIndexContent = (\n typeFiles: string[],\n configuration: IntlayerConfig,\n zodToTsFns: ZodToTsFns | null\n): string => {\n const { internationalization, system, editor } = configuration;\n const { moduleAugmentationDir } = system;\n const { enabled } = editor;\n const { locales, requiredLocales, strictMode } = internationalization;\n\n let fileContent = 'import \"intlayer\";\\n';\n\n // Build dictionary refs\n const dictionariesRef = typeFiles.map((dictionaryPath) => ({\n relativePath: `./${relative(moduleAugmentationDir, dictionaryPath)}`,\n id: basename(dictionaryPath, extname(dictionaryPath)),\n hash: `_${getPathHash(dictionaryPath)}`,\n }));\n\n // Import all dictionaries\n for (const dictionary of dictionariesRef) {\n fileContent += `import ${dictionary.hash} from '${dictionary.relativePath}';\\n`;\n }\n fileContent += '\\n';\n\n // Dictionary map entries (id: typeof <hash>)\n const formattedDictionaryMap: string = dictionariesRef\n .map((dictionary) => ` \"${dictionary.id}\": typeof ${dictionary.hash};`)\n .join('\\n');\n\n // Ensure required ⊆ declared; if empty, default required = declared\n const declared = locales;\n const requiredSanitized = requiredLocales?.length\n ? requiredLocales.filter((requiredLocales) =>\n declared.includes(requiredLocales)\n )\n : declared;\n\n const formattedDeclaredLocales = formatLocales(declared);\n const formattedRequiredLocales = formatLocales(requiredSanitized);\n\n // Build schema registry\n const schemas = configuration.schemas ?? {};\n const formattedSchemas = Object.entries(schemas)\n .map(([key, schema]) => {\n let typeStr = 'any';\n\n if (schema) {\n try {\n if (zodToTsFns) {\n const { node } = zodToTsFns.zodToTs(schema, {\n auxiliaryTypeStore: zodToTsFns.createAuxiliaryTypeStore(),\n });\n // 133 is the kind for AnyKeyword in TypeScript\n if ((node as any).kind !== 133) {\n typeStr = zodToTsFns.printNode(node);\n } else {\n typeStr = zodToTsString(schema);\n }\n } else {\n typeStr = zodToTsString(schema);\n }\n } catch (_e) {\n // Fallback to custom string generator\n typeStr = zodToTsString(schema);\n }\n }\n return ` \"${key}\": ${typeStr};`;\n })\n .join('\\n');\n\n // Choose strict mode registry key\n const strictKey =\n strictMode === 'strict'\n ? 'strict'\n : strictMode === 'inclusive'\n ? 'inclusive'\n : 'loose';\n\n /**\n * Module augmentation that ONLY adds keys to registries.\n * No types/aliases redefined here—avoids merge conflicts.\n */\n fileContent += `declare module 'intlayer' {\\n`;\n // Dictionaries registry\n fileContent += ` interface __DictionaryRegistry {\\n${formattedDictionaryMap}\\n }\\n\\n`;\n // Locales registries\n fileContent += ` interface __DeclaredLocalesRegistry {\\n${formattedDeclaredLocales}\\n }\\n\\n`;\n fileContent += ` interface __RequiredLocalesRegistry {\\n${formattedRequiredLocales}\\n }\\n\\n`;\n // Schema registry\n fileContent += ` interface __SchemaRegistry {\\n${formattedSchemas}\\n }\\n\\n`;\n // Resolved strict mode (narrow the literal at build time)\n fileContent += ` interface __StrictModeRegistry { mode: '${strictKey}' }\\n\\n`;\n // Editor registry\n fileContent += ` interface __EditorRegistry { enabled : ${enabled} } \\n`;\n fileContent += `}\\n`;\n\n return fileContent;\n};\n\n/** Generate the index file merging all the types */\nexport const createModuleAugmentation = async (\n configuration: IntlayerConfig\n) => {\n const { moduleAugmentationDir, typesDir } = configuration.system;\n\n await mkdir(moduleAugmentationDir, { recursive: true });\n\n const dictionariesTypesDefinitions: string[] = await fg(\n normalizePath(`${typesDir}/*.ts`),\n { ignore: ['**/*.d.ts'] }\n );\n\n let zodToTsFns: ZodToTsFns | null = null;\n try {\n const mod = await import('zod-to-ts');\n zodToTsFns = {\n zodToTs: mod.zodToTs,\n printNode: mod.printNode,\n createAuxiliaryTypeStore: mod.createAuxiliaryTypeStore,\n };\n } catch {\n // typescript peer dep not installed (plain JS project), use fallback\n }\n\n const tsContent = generateTypeIndexContent(\n dictionariesTypesDefinitions,\n configuration,\n zodToTsFns\n );\n\n const tsFilePath = join(moduleAugmentationDir, 'intlayer.d.ts');\n await writeFileIfChanged(tsFilePath, tsContent);\n};\n"],"mappings":"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"}
@@ -227,11 +227,14 @@ const getLicenceContent = () => {
227
227
  return "";
228
228
  }
229
229
  };
230
+ const ALLOWED_FETCH_HOSTS = new Set(["intlayer.org"]);
230
231
  /**
231
232
  * Fetches the content of a URL using native fetch.
232
233
  */
233
234
  const fetchUrlContent = async (url) => {
234
- const response = await fetch(url);
235
+ const parsed = new URL(url);
236
+ if (parsed.protocol !== "https:" || !ALLOWED_FETCH_HOSTS.has(parsed.hostname)) throw new Error(`Blocked fetch to disallowed host: ${parsed.hostname}`);
237
+ const response = await fetch(url, { redirect: "error" });
235
238
  if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
236
239
  return response.text();
237
240
  };
@@ -249,7 +252,7 @@ const installSkills = async (projectRoot, platform, skills) => {
249
252
  const skillName = `intlayer-${SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill)}`;
250
253
  const skillContent = getSkillContent(skill);
251
254
  if (!skillContent) continue;
252
- const urls = Array.from(new Set(skillContent.match(/https:\/\/intlayer\.org\/doc\/[^\s)]+\.md/g) || []));
255
+ const urls = Array.from(new Set(skillContent.match(/https:\/\/intlayer\.org\/[^\s)]+\.md/g) || []));
253
256
  const skillDir = path.join(skillsBaseDir, skillName);
254
257
  const referenceDir = path.join(skillDir, "references");
255
258
  await promises.mkdir(referenceDir, { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { v } from '@intlayer/config/logger';\nimport { getMarkdownMetadata } from '@intlayer/core/markdown';\n\n/**\n * Metadata for each available documentation skill.\n */\nexport const SKILLS_METADATA = {\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n Usage: 'How to use Intlayer in your project',\n CLI: 'Intlayer CLI commands and usage',\n Compiler:\n 'Intlayer Compiler setup and usage for automatic content extraction without .content files',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n React: 'React-specific syntax and hooks usage',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid:\n 'Integrates Intlayer internationalization with SolidJS components. Use when the user asks to \"setup SolidJS i18n\", use the \"useIntlayer\" hook in Solid, or manage locales in a SolidJS application.',\n Astro: 'Astro-specific usage and getIntlayer',\n} as const;\n\nexport type Skill = keyof typeof SKILLS_METADATA;\n\nexport const SKILLS = Object.keys(SKILLS_METADATA) as Skill[];\n\nexport const getInitialSkills = (\n deps: Record<string, string>\n): (keyof typeof SKILLS_METADATA)[] => {\n const skills: (keyof typeof SKILLS_METADATA)[] = [\n 'Usage',\n 'Content',\n 'Config',\n 'CLI',\n 'Compiler',\n ];\n\n if (deps.next) skills.push('NextJS');\n if (deps.react || !deps.next) skills.push('React');\n if (deps.preact) skills.push('Preact');\n if (deps['solid-js']) skills.push('Solid');\n if (deps.vue || deps.nuxt) skills.push('Vue');\n if (deps.svelte || deps['@sveltejs/kit']) skills.push('Svelte');\n if (deps.astro) skills.push('Astro');\n\n return skills;\n};\n\nexport interface PlatformMetadata {\n label: string;\n dir: string;\n check?: () => boolean;\n}\n\n/**\n * Metadata and configuration for each supported platform.\n */\nexport const PLATFORMS_METADATA: Record<string, PlatformMetadata> = {\n Cursor: {\n label: 'Cursor',\n dir: '.cursor/skills',\n check: () =>\n process.env.CURSOR === 'true' || process.env.TERM_PROGRAM === 'cursor',\n },\n Windsurf: {\n label: 'Windsurf',\n dir: '.windsurf/skills',\n check: () =>\n process.env.WINDSURF === 'true' ||\n process.env.TERM_PROGRAM === 'windsurf',\n },\n Trae: {\n label: 'Trae',\n dir: '.trae/skills',\n check: () =>\n process.env.TRAE === 'true' || process.env.TERM_PROGRAM === 'trae',\n },\n TraeCN: {\n label: 'Trae CN',\n dir: '.trae/skills',\n check: () => process.env.TRAE_CN === 'true',\n },\n VSCode: {\n label: 'VS Code',\n dir: '.vscode/skills',\n check: () =>\n process.env.VSCODE === 'true' || process.env.TERM_PROGRAM === 'vscode',\n },\n OpenCode: {\n label: 'OpenCode',\n dir: '.opencode/skills',\n check: () => process.env.OPENCODE === 'true',\n },\n Claude: {\n label: 'Claude Code',\n dir: '.claude/skills',\n check: () => process.env.CLAUDE === 'true',\n },\n GitHub: {\n label: 'GitHub Copilot Workspace',\n dir: '.github/skills',\n check: () =>\n process.env.GITHUB_ACTIONS === 'true' || !!process.env.GITHUB_WORKSPACE,\n },\n Antigravity: {\n label: 'Antigravity',\n dir: '.agent/skills',\n },\n Augment: {\n label: 'Augment',\n dir: '.augment/skills',\n },\n OpenClaw: {\n label: 'OpenClaw',\n dir: 'skills',\n },\n Cline: {\n label: 'Cline',\n dir: '.cline/skills',\n },\n CodeBuddy: {\n label: 'CodeBuddy',\n dir: '.codebuddy/skills',\n },\n CommandCode: {\n label: 'Command Code',\n dir: '.commandcode/skills',\n },\n Continue: {\n label: 'Continue',\n dir: '.continue/skills',\n },\n Crush: {\n label: 'Crush',\n dir: '.crush/skills',\n },\n Droid: {\n label: 'Droid',\n dir: '.factory/skills',\n },\n Goose: {\n label: 'Goose',\n dir: '.goose/skills',\n },\n IFlow: {\n label: 'iFlow CLI',\n dir: '.iflow/skills',\n },\n Junie: {\n label: 'Junie',\n dir: '.junie/skills',\n },\n KiloCode: {\n label: 'Kilo Code',\n dir: '.kilocode/skills',\n },\n Kiro: {\n label: 'Kiro CLI',\n dir: '.kiro/skills',\n },\n Kode: {\n label: 'Kode',\n dir: '.kode/skills',\n },\n MCPJam: {\n label: 'MCPJam',\n dir: '.mcpjam/skills',\n },\n MistralVibe: {\n label: 'Mistral Vibe',\n dir: '.vibe/skills',\n },\n Mux: {\n label: 'Mux',\n dir: '.mux/skills',\n },\n OpenHands: {\n label: 'OpenHands',\n dir: '.openhands/skills',\n },\n Pi: {\n label: 'Pi',\n dir: '.pi/skills',\n },\n Qoder: {\n label: 'Qoder',\n dir: '.qoder/skills',\n },\n Qwen: {\n label: 'Qwen Code',\n dir: '.qwen/skills',\n },\n RooCode: {\n label: 'Roo Code',\n dir: '.roo/skills',\n },\n Zencoder: {\n label: 'Zencoder',\n dir: '.zencoder/skills',\n },\n Neovate: {\n label: 'Neovate',\n dir: '.neovate/skills',\n },\n Pochi: {\n label: 'Pochi',\n dir: '.pochi/skills',\n },\n Other: {\n label: 'Other',\n dir: 'skills',\n },\n} as const;\n\nexport type Platform = keyof typeof PLATFORMS_METADATA;\n\nexport const PLATFORMS = Object.keys(PLATFORMS_METADATA) as Platform[];\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to kebab-case for directory naming\n */\nconst camelToKebabCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL using native fetch.\n */\nconst fetchUrlContent = async (url: string): Promise<string> => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n return response.text();\n};\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n // Determine destination directory\n const relativeDir = PLATFORMS_METADATA[platform].dir ?? 'skills';\n const skillsBaseDir = path.join(projectRoot, relativeDir);\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const skillName = `intlayer-${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n // Extract unique URLs\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n const referenceDir = path.join(skillDir, 'references');\n\n // Ensure directories exist\n await fs.mkdir(referenceDir, { recursive: true });\n\n // Write License\n if (licenceContent) {\n await fs.writeFile(\n path.join(skillDir, 'LICENCE.md'),\n licenceContent,\n 'utf-8'\n );\n }\n\n let updatedSkillContent = skillContent;\n\n // Parallel download of references\n const downloadPromises = urls.map(async (url) => {\n try {\n const content = await fetchUrlContent(url);\n const metadata = getMarkdownMetadata<{ slugs?: string[] }>(content);\n\n let fileName = '';\n\n // Determine filename from slugs or URL path\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs.filter((slug) => slug !== 'doc').join('_');\n } else {\n const urlPath = new URL(url).pathname;\n fileName = urlPath\n .split('/')\n .filter((part) => part && part !== 'doc')\n .map((part) => part.replace('.md', '')) // Clean extension for joining\n .join('_');\n }\n\n // Ensure it ends with .md\n fileName = fileName ? `${fileName}.md` : 'index.md';\n const localRefPath = `references/${fileName}`;\n\n return {\n url,\n localRefPath,\n fileName,\n content,\n success: true,\n };\n } catch (error) {\n console.warn(\n `Warning: Failed to download ref ${url} for skill ${skill}`,\n error\n );\n return { url, success: false };\n }\n });\n\n const results = await Promise.all(downloadPromises);\n\n // Process results: Write files and update content string\n for (const res of results) {\n if (res.success && res.fileName && res.content && res.localRefPath) {\n // Write the reference file\n await fs.writeFile(\n path.join(referenceDir, res.fileName),\n res.content,\n 'utf-8'\n );\n\n // Update the main content to point to local file\n updatedSkillContent = updatedSkillContent.replaceAll(\n res.url,\n res.localRefPath\n );\n }\n }\n\n // Write the main SKILL.md\n const filePath = path.join(skillDir, 'SKILL.md');\n await fs.writeFile(filePath, updatedSkillContent, 'utf-8');\n createdSkills.push(`${skillName}/SKILL.md`);\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `${v} Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { v } from '@intlayer/config/logger';\nimport { getMarkdownMetadata } from '@intlayer/core/markdown';\n\n/**\n * Metadata for each available documentation skill.\n */\nexport const SKILLS_METADATA = {\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n Usage: 'How to use Intlayer in your project',\n CLI: 'Intlayer CLI commands and usage',\n Compiler:\n 'Intlayer Compiler setup and usage for automatic content extraction without .content files',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n React: 'React-specific syntax and hooks usage',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid:\n 'Integrates Intlayer internationalization with SolidJS components. Use when the user asks to \"setup SolidJS i18n\", use the \"useIntlayer\" hook in Solid, or manage locales in a SolidJS application.',\n Astro: 'Astro-specific usage and getIntlayer',\n} as const;\n\nexport type Skill = keyof typeof SKILLS_METADATA;\n\nexport const SKILLS = Object.keys(SKILLS_METADATA) as Skill[];\n\nexport const getInitialSkills = (\n deps: Record<string, string>\n): (keyof typeof SKILLS_METADATA)[] => {\n const skills: (keyof typeof SKILLS_METADATA)[] = [\n 'Usage',\n 'Content',\n 'Config',\n 'CLI',\n 'Compiler',\n ];\n\n if (deps.next) skills.push('NextJS');\n if (deps.react || !deps.next) skills.push('React');\n if (deps.preact) skills.push('Preact');\n if (deps['solid-js']) skills.push('Solid');\n if (deps.vue || deps.nuxt) skills.push('Vue');\n if (deps.svelte || deps['@sveltejs/kit']) skills.push('Svelte');\n if (deps.astro) skills.push('Astro');\n\n return skills;\n};\n\nexport interface PlatformMetadata {\n label: string;\n dir: string;\n check?: () => boolean;\n}\n\n/**\n * Metadata and configuration for each supported platform.\n */\nexport const PLATFORMS_METADATA: Record<string, PlatformMetadata> = {\n Cursor: {\n label: 'Cursor',\n dir: '.cursor/skills',\n check: () =>\n process.env.CURSOR === 'true' || process.env.TERM_PROGRAM === 'cursor',\n },\n Windsurf: {\n label: 'Windsurf',\n dir: '.windsurf/skills',\n check: () =>\n process.env.WINDSURF === 'true' ||\n process.env.TERM_PROGRAM === 'windsurf',\n },\n Trae: {\n label: 'Trae',\n dir: '.trae/skills',\n check: () =>\n process.env.TRAE === 'true' || process.env.TERM_PROGRAM === 'trae',\n },\n TraeCN: {\n label: 'Trae CN',\n dir: '.trae/skills',\n check: () => process.env.TRAE_CN === 'true',\n },\n VSCode: {\n label: 'VS Code',\n dir: '.vscode/skills',\n check: () =>\n process.env.VSCODE === 'true' || process.env.TERM_PROGRAM === 'vscode',\n },\n OpenCode: {\n label: 'OpenCode',\n dir: '.opencode/skills',\n check: () => process.env.OPENCODE === 'true',\n },\n Claude: {\n label: 'Claude Code',\n dir: '.claude/skills',\n check: () => process.env.CLAUDE === 'true',\n },\n GitHub: {\n label: 'GitHub Copilot Workspace',\n dir: '.github/skills',\n check: () =>\n process.env.GITHUB_ACTIONS === 'true' || !!process.env.GITHUB_WORKSPACE,\n },\n Antigravity: {\n label: 'Antigravity',\n dir: '.agent/skills',\n },\n Augment: {\n label: 'Augment',\n dir: '.augment/skills',\n },\n OpenClaw: {\n label: 'OpenClaw',\n dir: 'skills',\n },\n Cline: {\n label: 'Cline',\n dir: '.cline/skills',\n },\n CodeBuddy: {\n label: 'CodeBuddy',\n dir: '.codebuddy/skills',\n },\n CommandCode: {\n label: 'Command Code',\n dir: '.commandcode/skills',\n },\n Continue: {\n label: 'Continue',\n dir: '.continue/skills',\n },\n Crush: {\n label: 'Crush',\n dir: '.crush/skills',\n },\n Droid: {\n label: 'Droid',\n dir: '.factory/skills',\n },\n Goose: {\n label: 'Goose',\n dir: '.goose/skills',\n },\n IFlow: {\n label: 'iFlow CLI',\n dir: '.iflow/skills',\n },\n Junie: {\n label: 'Junie',\n dir: '.junie/skills',\n },\n KiloCode: {\n label: 'Kilo Code',\n dir: '.kilocode/skills',\n },\n Kiro: {\n label: 'Kiro CLI',\n dir: '.kiro/skills',\n },\n Kode: {\n label: 'Kode',\n dir: '.kode/skills',\n },\n MCPJam: {\n label: 'MCPJam',\n dir: '.mcpjam/skills',\n },\n MistralVibe: {\n label: 'Mistral Vibe',\n dir: '.vibe/skills',\n },\n Mux: {\n label: 'Mux',\n dir: '.mux/skills',\n },\n OpenHands: {\n label: 'OpenHands',\n dir: '.openhands/skills',\n },\n Pi: {\n label: 'Pi',\n dir: '.pi/skills',\n },\n Qoder: {\n label: 'Qoder',\n dir: '.qoder/skills',\n },\n Qwen: {\n label: 'Qwen Code',\n dir: '.qwen/skills',\n },\n RooCode: {\n label: 'Roo Code',\n dir: '.roo/skills',\n },\n Zencoder: {\n label: 'Zencoder',\n dir: '.zencoder/skills',\n },\n Neovate: {\n label: 'Neovate',\n dir: '.neovate/skills',\n },\n Pochi: {\n label: 'Pochi',\n dir: '.pochi/skills',\n },\n Other: {\n label: 'Other',\n dir: 'skills',\n },\n} as const;\n\nexport type Platform = keyof typeof PLATFORMS_METADATA;\n\nexport const PLATFORMS = Object.keys(PLATFORMS_METADATA) as Platform[];\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to kebab-case for directory naming\n */\nconst camelToKebabCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\nconst ALLOWED_FETCH_HOSTS = new Set(['intlayer.org']);\n\n/**\n * Fetches the content of a URL using native fetch.\n */\nconst fetchUrlContent = async (url: string): Promise<string> => {\n const parsed = new URL(url);\n if (\n parsed.protocol !== 'https:' ||\n !ALLOWED_FETCH_HOSTS.has(parsed.hostname)\n ) {\n throw new Error(`Blocked fetch to disallowed host: ${parsed.hostname}`);\n }\n const response = await fetch(url, { redirect: 'error' });\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n return response.text();\n};\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n // Determine destination directory\n const relativeDir = PLATFORMS_METADATA[platform].dir ?? 'skills';\n const skillsBaseDir = path.join(projectRoot, relativeDir);\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const skillName = `intlayer-${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n // Extract unique URLs\n const urls = Array.from(\n new Set(skillContent.match(/https:\\/\\/intlayer\\.org\\/[^\\s)]+\\.md/g) || [])\n );\n\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n const referenceDir = path.join(skillDir, 'references');\n\n // Ensure directories exist\n await fs.mkdir(referenceDir, { recursive: true });\n\n // Write License\n if (licenceContent) {\n await fs.writeFile(\n path.join(skillDir, 'LICENCE.md'),\n licenceContent,\n 'utf-8'\n );\n }\n\n let updatedSkillContent = skillContent;\n\n // Parallel download of references\n const downloadPromises = urls.map(async (url) => {\n try {\n const content = await fetchUrlContent(url);\n const metadata = getMarkdownMetadata<{ slugs?: string[] }>(content);\n\n let fileName = '';\n\n // Determine filename from slugs or URL path\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs.filter((slug) => slug !== 'doc').join('_');\n } else {\n const urlPath = new URL(url).pathname;\n fileName = urlPath\n .split('/')\n .filter((part) => part && part !== 'doc')\n .map((part) => part.replace('.md', '')) // Clean extension for joining\n .join('_');\n }\n\n // Ensure it ends with .md\n fileName = fileName ? `${fileName}.md` : 'index.md';\n const localRefPath = `references/${fileName}`;\n\n return {\n url,\n localRefPath,\n fileName,\n content,\n success: true,\n };\n } catch (error) {\n console.warn(\n `Warning: Failed to download ref ${url} for skill ${skill}`,\n error\n );\n return { url, success: false };\n }\n });\n\n const results = await Promise.all(downloadPromises);\n\n // Process results: Write files and update content string\n for (const res of results) {\n if (res.success && res.fileName && res.content && res.localRefPath) {\n // Write the reference file\n await fs.writeFile(\n path.join(referenceDir, res.fileName),\n res.content,\n 'utf-8'\n );\n\n // Update the main content to point to local file\n updatedSkillContent = updatedSkillContent.replaceAll(\n res.url,\n res.localRefPath\n );\n }\n }\n\n // Write the main SKILL.md\n const filePath = path.join(skillDir, 'SKILL.md');\n await fs.writeFile(filePath, updatedSkillContent, 'utf-8');\n createdSkills.push(`${skillName}/SKILL.md`);\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `${v} Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { formatPath } from "./utils/formatter.mjs";
1
2
  import { handleContentDeclarationFileChange } from "./handleContentDeclarationFileChange.mjs";
2
3
  import { handleContentDeclarationFileMoved } from "./handleContentDeclarationFileMoved.mjs";
3
4
  import { handleAdditionalContentDeclarationFile } from "./handleAdditionalContentDeclarationFile.mjs";
@@ -5,12 +6,13 @@ import { handleUnlinkedContentDeclarationFile } from "./handleUnlinkedContentDec
5
6
  import { prepareIntlayer } from "./prepareIntlayer.mjs";
6
7
  import { writeContentDeclaration } from "./writeContentDeclaration/writeContentDeclaration.mjs";
7
8
  import { readFile } from "node:fs/promises";
8
- import { basename } from "node:path";
9
+ import { basename, dirname } from "node:path";
9
10
  import { colorize, getAppLogger } from "@intlayer/config/logger";
10
11
  import { getConfiguration, getConfigurationAndFilePath } from "@intlayer/config/node";
11
12
  import { existsSync } from "node:fs";
12
13
  import { clearAllCache, clearDiskCacheMemory, clearModuleCache, normalizePath } from "@intlayer/config/utils";
13
14
  import * as ANSIColor from "@intlayer/config/colors";
15
+ import { pathToFileURL } from "node:url";
14
16
 
15
17
  //#region src/watcher.ts
16
18
  const pendingUnlinks = /* @__PURE__ */ new Map();
@@ -54,6 +56,58 @@ const watch = async (options) => {
54
56
  ], { level: "warn" });
55
57
  const excludedSegments = excludedPath.map((segment) => segment.replace(/^\*\*\//, "").replace(/\/\*\*$/, ""));
56
58
  const normalizedConfigPath = configurationFilePath ? normalizePath(configurationFilePath) : null;
59
+ const { mainDir, baseDir } = configuration.system;
60
+ const normalizedIntlayerDir = normalizePath(dirname(mainDir));
61
+ if (existsSync(mainDir)) chokidarWatch(mainDir, {
62
+ persistent: isWatchMode,
63
+ ignoreInitial: true,
64
+ depth: 0
65
+ }).on("change", async (filePath) => {
66
+ if (isProcessing) return;
67
+ processEvent(async () => {
68
+ clearModuleCache(filePath);
69
+ try {
70
+ await import(`${pathToFileURL(filePath).href}?update=${Date.now()}`);
71
+ } catch {
72
+ appLogger(`Entry point ${basename(filePath)} failed to load, running clean rebuild...`, { level: "warn" });
73
+ await prepareIntlayer(configuration, {
74
+ clean: true,
75
+ forceRun: true
76
+ });
77
+ }
78
+ });
79
+ }).on("unlink", async (filePath) => {
80
+ if (isProcessing) return;
81
+ processEvent(async () => {
82
+ appLogger([
83
+ "Entry point",
84
+ formatPath(basename(filePath)),
85
+ "was removed, running clean rebuild..."
86
+ ], { level: "warn" });
87
+ await prepareIntlayer(configuration, {
88
+ clean: true,
89
+ forceRun: true
90
+ });
91
+ });
92
+ });
93
+ chokidarWatch(baseDir, {
94
+ persistent: isWatchMode,
95
+ ignoreInitial: true,
96
+ depth: 0,
97
+ ignored: (filePath) => {
98
+ const path = normalizePath(filePath);
99
+ return path !== normalizePath(baseDir) && path !== normalizedIntlayerDir;
100
+ }
101
+ }).on("unlinkDir", async (dirPath) => {
102
+ if (isProcessing) return;
103
+ if (normalizePath(dirPath) === normalizedIntlayerDir) {
104
+ appLogger([formatPath(".intlayer"), "directory removed, running clean rebuild..."]);
105
+ processEvent(() => prepareIntlayer(configuration, {
106
+ clean: true,
107
+ forceRun: true
108
+ }));
109
+ }
110
+ });
57
111
  return chokidarWatch(pathsToWatch, {
58
112
  persistent: isWatchMode,
59
113
  ignoreInitial: true,
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.mjs","names":[],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { ChokidarOptions } from 'chokidar';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = ChokidarOptions & {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n};\n\n// Initialize chokidar watcher (non-persistent)\nexport const watch = async (options?: WatchOptions) => {\n const { watch: chokidarWatch } = await import('chokidar');\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n // chokidar v5 dropped glob support — use fs to resolve dirs, filter extensions via ignored\n const pathsToWatch = [\n ...contentDir.map((dir) => normalizePath(dir)).filter(existsSync),\n ...(configurationFilePath ? [configurationFilePath] : []),\n ];\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n return chokidarWatch(pathsToWatch, {\n persistent: isWatchMode, // Make the watcher persistent\n ignoreInitial: true, // Process existing files\n awaitWriteFinish: {\n stabilityThreshold: 1000,\n pollInterval: 100,\n },\n ignored: (filePath: string, stats?: import('node:fs').Stats) => {\n const path = normalizePath(filePath);\n\n if (normalizedConfigPath && path === normalizedConfigPath) return false;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n return true;\n\n if (stats?.isFile()) {\n return !fileExtensions.some((extension) => path.endsWith(extension));\n }\n\n return false;\n },\n ...options,\n })\n .on('add', async (filePath) => {\n const fileName = basename(filePath);\n let isMove = false;\n\n // Check if this Add corresponds to a pending Unlink (Move/Rename detection)\n // Heuristic:\n // - Priority A: Exact basename match (Moved to different folder)\n // - Priority B: Single entry in pendingUnlinks (Renamed file)\n let matchedOldPath: string | undefined;\n\n // Search for basename match\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n // If no basename match, but exactly one file was recently unlinked, assume it's a rename\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n // It is a move! Cancel the unlink handler\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n processEvent(async () => {\n if (isMove && matchedOldPath) {\n await handleContentDeclarationFileMoved(\n matchedOldPath,\n filePath,\n configuration\n );\n } else {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n // Fill template content declaration file if it is empty\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n {\n key: name,\n content: {},\n filePath,\n },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(filePath, configuration);\n }\n });\n })\n .on('change', async (filePath) =>\n processEvent(async () => {\n if (configurationFilePath && filePath === configurationFilePath) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(configurationFilePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n })\n )\n .on('unlink', async (filePath) => {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'add' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n })\n .on('error', async (error) => {\n appLogger(`Watcher error: ${error}`, {\n level: 'error',\n });\n\n appLogger('Restarting watcher');\n\n await prepareIntlayer(configuration);\n });\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n if (configuration.content.watch || options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"watcher.mjs","names":[],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { ChokidarOptions } from 'chokidar';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { formatPath } from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = ChokidarOptions & {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n};\n\n// Initialize chokidar watcher (non-persistent)\nexport const watch = async (options?: WatchOptions) => {\n const { watch: chokidarWatch } = await import('chokidar');\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n // chokidar v5 dropped glob support — use fs to resolve dirs, filter extensions via ignored\n const pathsToWatch = [\n ...contentDir.map((dir) => normalizePath(dir)).filter(existsSync),\n ...(configurationFilePath ? [configurationFilePath] : []),\n ];\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n // Watch mainDir to detect broken or missing entry point files\n if (existsSync(mainDir)) {\n chokidarWatch(mainDir, {\n persistent: isWatchMode,\n ignoreInitial: true,\n depth: 0,\n })\n .on('change', async (filePath) => {\n if (isProcessing) return;\n\n processEvent(async () => {\n clearModuleCache(filePath);\n try {\n // Convert absolute path to a valid file:// URL\n const fileUrl = pathToFileURL(filePath).href;\n\n // Append a timestamp to bypass the ESM cache\n await import(`${fileUrl}?update=${Date.now()}`);\n } catch {\n appLogger(\n `Entry point ${basename(filePath)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n })\n .on('unlink', async (filePath) => {\n if (isProcessing) return;\n\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(filePath)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, { clean: true, forceRun: true });\n });\n });\n }\n\n // Watch baseDir at depth 0 to detect the entire .intlayer folder being removed\n chokidarWatch(baseDir, {\n persistent: isWatchMode,\n ignoreInitial: true,\n depth: 0,\n ignored: (filePath: string) => {\n const path = normalizePath(filePath);\n return path !== normalizePath(baseDir) && path !== normalizedIntlayerDir;\n },\n }).on('unlinkDir', async (dirPath) => {\n if (isProcessing) return;\n\n if (normalizePath(dirPath) === normalizedIntlayerDir) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n });\n\n return chokidarWatch(pathsToWatch, {\n persistent: isWatchMode, // Make the watcher persistent\n ignoreInitial: true, // Process existing files\n awaitWriteFinish: {\n stabilityThreshold: 1000,\n pollInterval: 100,\n },\n ignored: (filePath: string, stats?: import('node:fs').Stats) => {\n const path = normalizePath(filePath);\n\n if (normalizedConfigPath && path === normalizedConfigPath) return false;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n return true;\n\n if (stats?.isFile()) {\n return !fileExtensions.some((extension) => path.endsWith(extension));\n }\n\n return false;\n },\n ...options,\n })\n .on('add', async (filePath) => {\n const fileName = basename(filePath);\n let isMove = false;\n\n // Check if this Add corresponds to a pending Unlink (Move/Rename detection)\n // Heuristic:\n // - Priority A: Exact basename match (Moved to different folder)\n // - Priority B: Single entry in pendingUnlinks (Renamed file)\n let matchedOldPath: string | undefined;\n\n // Search for basename match\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n // If no basename match, but exactly one file was recently unlinked, assume it's a rename\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n // It is a move! Cancel the unlink handler\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n processEvent(async () => {\n if (isMove && matchedOldPath) {\n await handleContentDeclarationFileMoved(\n matchedOldPath,\n filePath,\n configuration\n );\n } else {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n // Fill template content declaration file if it is empty\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n {\n key: name,\n content: {},\n filePath,\n },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(filePath, configuration);\n }\n });\n })\n .on('change', async (filePath) =>\n processEvent(async () => {\n if (configurationFilePath && filePath === configurationFilePath) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(configurationFilePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n })\n )\n .on('unlink', async (filePath) => {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'add' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n })\n .on('error', async (error) => {\n appLogger(`Watcher error: ${error}`, {\n level: 'error',\n });\n\n appLogger('Restarting watcher');\n\n await prepareIntlayer(configuration);\n });\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n if (configuration.content.watch || options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"writeDynamicDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"mappings":";;;;;;KAaY,gBAAA;EACV,cAAA;EACA,UAAA,EAAY,UAAA;AAAA;AAAA,KAGF,yBAAA,GAA4B,OAAA,CACtC,MAAA,CAAO,MAAA,EAAQ,gBAAA;AAAA,KAGL,yBAAA,GAA4B,MAAA,SAEtC,yBAAA;;;;cAQW,4BAAA,GACX,GAAA,UACA,OAAA,YACA,MAAA;;AAjBF;;;;;;;;;;;;;;;cAwDa,sBAAA,GACX,kBAAA,EAAoB,sBAAA,EACpB,aAAA,EAAe,cAAA,EACf,OAAA,yBACC,OAAA,CAAQ,yBAAA"}
1
+ {"version":3,"file":"writeDynamicDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeDynamicDictionary.ts"],"mappings":";;;;;;KAcY,gBAAA;EACV,cAAA;EACA,UAAA,EAAY,UAAA;AAAA;AAAA,KAGF,yBAAA,GAA4B,OAAA,CACtC,MAAA,CAAO,MAAA,EAAQ,gBAAA;AAAA,KAGL,yBAAA,GAA4B,MAAA,SAEtC,yBAAA;;;;cAQW,4BAAA,GACX,GAAA,UACA,OAAA,YACA,MAAA;;AAjBF;;;;;;;;;;;;;;;cAwDa,sBAAA,GACX,kBAAA,EAAoB,sBAAA,EACpB,aAAA,EAAe,cAAA,EACf,OAAA,yBACC,OAAA,CAAQ,yBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"writeMergedDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"mappings":";;;;;KAaY,sBAAA;EACV,cAAA;EACA,UAAA,EAAY,UAAA;AAAA;AAAA,KAGF,sBAAA,GAAyB,MAAA,SAAe,sBAAA;;;;;;;AAApD;;;;;AAkBA;;;;;cAAa,uBAAA,GACX,mBAAA,EAAqB,wBAAA,EACrB,aAAA,EAAe,cAAA,KACd,OAAA,CAAQ,sBAAA"}
1
+ {"version":3,"file":"writeMergedDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeMergedDictionary.ts"],"mappings":";;;;;KAcY,sBAAA;EACV,cAAA;EACA,UAAA,EAAY,UAAA;AAAA;AAAA,KAGF,sBAAA,GAAyB,MAAA,SAAe,sBAAA;;;;;;;AAApD;;;;;AAkBA;;;;;cAAa,uBAAA,GACX,mBAAA,EAAqB,wBAAA,EACrB,aAAA,EAAe,cAAA,KACd,OAAA,CAAQ,sBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"writeUnmergedDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeUnmergedDictionary.ts"],"mappings":";;;;cAUa,sBAAA,GACX,YAAA,EAAc,UAAA,OACb,MAAA,SAAe,UAAA;AAAA,KAaN,wBAAA;EACV,cAAA;EACA,YAAA,EAAc,UAAA;AAAA;AAAA,KAGJ,wBAAA,GAA2B,MAAA,CACrC,aAAA,EACA,wBAAA;;;;;;;;;;;AAPF;;;;;;;;;AAKA;cAyBa,yBAAA,GACX,YAAA,EAAc,UAAA,IACd,aAAA,EAAe,cAAA,EACf,GAAA,qBACC,OAAA,CAAQ,wBAAA"}
1
+ {"version":3,"file":"writeUnmergedDictionary.d.ts","names":[],"sources":["../../../src/buildIntlayerDictionary/writeUnmergedDictionary.ts"],"mappings":";;;;cAWa,sBAAA,GACX,YAAA,EAAc,UAAA,OACb,MAAA,SAAe,UAAA;AAAA,KAaN,wBAAA;EACV,cAAA;EACA,YAAA,EAAc,UAAA;AAAA;AAAA,KAGJ,wBAAA,GAA2B,MAAA,CACrC,aAAA,EACA,wBAAA;;;;;;;;;;;AAPF;;;;;;;;;AAKA;cAyBa,yBAAA,GACX,YAAA,EAAc,UAAA,IACd,aAAA,EAAe,cAAA,EACf,GAAA,qBACC,OAAA,CAAQ,wBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"createModuleAugmentation.d.ts","names":[],"sources":["../../../src/createType/createModuleAugmentation.ts"],"mappings":";;;cAUa,WAAA,GAAe,GAAA;;cA4Kf,wBAAA,GACX,aAAA,EAAe,cAAA,KAAc,OAAA"}
1
+ {"version":3,"file":"createModuleAugmentation.d.ts","names":[],"sources":["../../../src/createType/createModuleAugmentation.ts"],"mappings":";;;cASa,WAAA,GAAe,GAAA;;cAsLf,wBAAA,GACX,aAAA,EAAe,cAAA,KAAc,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";;AASA;;cAAa,eAAA;EAAA;;;;;;;;;;;;;;;KAmBD,KAAA,gBAAqB,eAAA;AAAA,cAEpB,MAAA,EAAyC,KAAA;AAAA,cAEzC,gBAAA,GACX,IAAA,EAAM,MAAA,mCACS,eAAA;AAAA,UAoBA,gBAAA;EACf,KAAA;EACA,GAAA;EACA,KAAA;AAAA;;;;cAMW,kBAAA,EAAoB,MAAA,SAAe,gBAAA;AAAA,KA6JpC,QAAA,gBAAwB,kBAAA;AAAA,cAEvB,SAAA,EAA+C,QAAA;;;;;cAyD/C,aAAA,GACX,WAAA,UACA,QAAA,EAAU,QAAA,EACV,MAAA,EAAQ,KAAA,OACP,OAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";;AASA;;cAAa,eAAA;EAAA;;;;;;;;;;;;;;;KAmBD,KAAA,gBAAqB,eAAA;AAAA,cAEpB,MAAA,EAAyC,KAAA;AAAA,cAEzC,gBAAA,GACX,IAAA,EAAM,MAAA,mCACS,eAAA;AAAA,UAoBA,gBAAA;EACf,KAAA;EACA,GAAA;EACA,KAAA;AAAA;;;;cAMW,kBAAA,EAAoB,MAAA,SAAe,gBAAA;AAAA,KA6JpC,QAAA,gBAAwB,kBAAA;AAAA,cAEvB,SAAA,EAA+C,QAAA;;;;;cAkE/C,aAAA,GACX,WAAA,UACA,QAAA,EAAU,QAAA,EACV,MAAA,EAAQ,KAAA,OACP,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","names":[],"sources":["../../src/watcher.ts"],"mappings":";;;;;;KAsDK,YAAA,GAAe,eAAA;EAClB,aAAA,GAAgB,cAAA;EAChB,aAAA,GAAgB,uBAAA;EAChB,WAAA;AAAA;AAAA,cAIW,KAAA,GAAe,OAAA,GAAU,YAAA,KAAY,OAAA,CAAA,UAAA,CAAA,SAAA;AAAA,cA+LrC,qBAAA,GAA+B,OAAA,GAAU,YAAA,KAAY,OAAA"}
1
+ {"version":3,"file":"watcher.d.ts","names":[],"sources":["../../src/watcher.ts"],"mappings":";;;;;;KAwDK,YAAA,GAAe,eAAA;EAClB,aAAA,GAAgB,cAAA;EAChB,aAAA,GAAgB,uBAAA;EAChB,WAAA;AAAA;AAAA,cAIW,KAAA,GAAe,OAAA,GAAU,YAAA,KAAY,OAAA,CAAA,UAAA,CAAA,SAAA;AAAA,cAyQrC,qBAAA,GAA+B,OAAA,GAAU,YAAA,KAAY,OAAA"}