@intlayer/cli 9.5.11 → 9.6.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 (90) hide show
  1. package/dist/cjs/_virtual/_utils_asset.cjs +1 -1
  2. package/dist/cjs/build.cjs +2 -2
  3. package/dist/cjs/build.cjs.map +1 -1
  4. package/dist/cjs/ci.cjs +1 -1
  5. package/dist/cjs/cli.cjs +51 -12
  6. package/dist/cjs/cli.cjs.map +1 -1
  7. package/dist/cjs/extract.cjs +1 -1
  8. package/dist/cjs/fill/fill.cjs +25 -9
  9. package/dist/cjs/fill/fill.cjs.map +1 -1
  10. package/dist/cjs/getTargetDictionary.cjs +1 -1
  11. package/dist/cjs/index.cjs +15 -1
  12. package/dist/cjs/init.cjs +98 -27
  13. package/dist/cjs/init.cjs.map +1 -1
  14. package/dist/cjs/initChromeExtension.cjs +26 -3
  15. package/dist/cjs/initChromeExtension.cjs.map +1 -1
  16. package/dist/cjs/initInfra.cjs +6 -0
  17. package/dist/cjs/initInfra.cjs.map +1 -1
  18. package/dist/cjs/initMCP.cjs +18 -7
  19. package/dist/cjs/initMCP.cjs.map +1 -1
  20. package/dist/cjs/initSkills.cjs +37 -34
  21. package/dist/cjs/initSkills.cjs.map +1 -1
  22. package/dist/cjs/listContentDeclaration.cjs +1 -1
  23. package/dist/cjs/listProjects.cjs +1 -1
  24. package/dist/cjs/pull.cjs +1 -1
  25. package/dist/cjs/push/push.cjs +1 -1
  26. package/dist/cjs/reviewDoc/reviewDoc.cjs +1 -1
  27. package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +1 -1
  28. package/dist/cjs/scan.cjs +1 -1
  29. package/dist/cjs/scan.cjs.map +1 -1
  30. package/dist/cjs/translateDoc/translateDoc.cjs +1 -1
  31. package/dist/cjs/upgrade.cjs +1 -1
  32. package/dist/cjs/utils/getParentPackageJSON.cjs +1 -1
  33. package/dist/cjs/utils/isInteractiveTerminal.cjs +12 -0
  34. package/dist/cjs/utils/isInteractiveTerminal.cjs.map +1 -0
  35. package/dist/cjs/utils/parseChoice.cjs +21 -0
  36. package/dist/cjs/utils/parseChoice.cjs.map +1 -0
  37. package/dist/esm/_virtual/_utils_asset.mjs +1 -1
  38. package/dist/esm/build.mjs +1 -1
  39. package/dist/esm/build.mjs.map +1 -1
  40. package/dist/esm/ci.mjs +1 -1
  41. package/dist/esm/cli.mjs +51 -12
  42. package/dist/esm/cli.mjs.map +1 -1
  43. package/dist/esm/extract.mjs +1 -1
  44. package/dist/esm/fill/fill.mjs +25 -9
  45. package/dist/esm/fill/fill.mjs.map +1 -1
  46. package/dist/esm/getTargetDictionary.mjs +1 -1
  47. package/dist/esm/index.mjs +5 -4
  48. package/dist/esm/init.mjs +93 -28
  49. package/dist/esm/init.mjs.map +1 -1
  50. package/dist/esm/initChromeExtension.mjs +24 -4
  51. package/dist/esm/initChromeExtension.mjs.map +1 -1
  52. package/dist/esm/initInfra.mjs +6 -0
  53. package/dist/esm/initInfra.mjs.map +1 -1
  54. package/dist/esm/initMCP.mjs +21 -11
  55. package/dist/esm/initMCP.mjs.map +1 -1
  56. package/dist/esm/initSkills.mjs +37 -36
  57. package/dist/esm/initSkills.mjs.map +1 -1
  58. package/dist/esm/listContentDeclaration.mjs +1 -1
  59. package/dist/esm/listProjects.mjs +1 -1
  60. package/dist/esm/pull.mjs +1 -1
  61. package/dist/esm/push/push.mjs +1 -1
  62. package/dist/esm/reviewDoc/reviewDoc.mjs +1 -1
  63. package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +1 -1
  64. package/dist/esm/scan.mjs +1 -1
  65. package/dist/esm/scan.mjs.map +1 -1
  66. package/dist/esm/translateDoc/translateDoc.mjs +1 -1
  67. package/dist/esm/upgrade.mjs +1 -1
  68. package/dist/esm/utils/getParentPackageJSON.mjs +1 -1
  69. package/dist/esm/utils/isInteractiveTerminal.mjs +11 -0
  70. package/dist/esm/utils/isInteractiveTerminal.mjs.map +1 -0
  71. package/dist/esm/utils/parseChoice.mjs +20 -0
  72. package/dist/esm/utils/parseChoice.mjs.map +1 -0
  73. package/dist/types/fill/fill.d.ts +22 -1
  74. package/dist/types/fill/fill.d.ts.map +1 -1
  75. package/dist/types/fill/index.d.ts +2 -2
  76. package/dist/types/index.d.ts +6 -5
  77. package/dist/types/init.d.ts +36 -0
  78. package/dist/types/init.d.ts.map +1 -1
  79. package/dist/types/initChromeExtension.d.ts +19 -1
  80. package/dist/types/initChromeExtension.d.ts.map +1 -1
  81. package/dist/types/initInfra.d.ts.map +1 -1
  82. package/dist/types/initMCP.d.ts +16 -2
  83. package/dist/types/initMCP.d.ts.map +1 -1
  84. package/dist/types/initSkills.d.ts +23 -6
  85. package/dist/types/initSkills.d.ts.map +1 -1
  86. package/dist/types/utils/isInteractiveTerminal.d.ts +9 -0
  87. package/dist/types/utils/isInteractiveTerminal.d.ts.map +1 -0
  88. package/dist/types/utils/parseChoice.d.ts +13 -0
  89. package/dist/types/utils/parseChoice.d.ts.map +1 -0
  90. package/package.json +18 -13
@@ -1 +1 @@
1
- {"version":3,"file":"initSkills.mjs","names":[],"sources":["../../src/initSkills.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport {\n getInitialSkills,\n installSkills,\n PLATFORMS,\n PLATFORMS_METADATA,\n type Platform,\n SKILLS,\n SKILLS_METADATA,\n} from '@intlayer/engine/cli';\nimport enquirer from 'enquirer';\nimport { findProjectRoot } from './init';\nimport { loadPrompts } from './loadPrompts';\n\nconst PLATFORM_CHECKS: Array<{ check: () => boolean; platform: Platform }> =\n PLATFORMS.filter((platform) => PLATFORMS_METADATA[platform]?.check).map(\n (platform) => ({\n check: PLATFORMS_METADATA[platform]?.check ?? (() => false),\n platform,\n })\n );\n\nexport const PLATFORM_OPTIONS: Array<{\n value: Platform;\n label: string;\n hint: string;\n}> = PLATFORMS.map((platform) => ({\n value: platform,\n label: PLATFORMS_METADATA[platform]?.label ?? '',\n hint: `(${PLATFORMS_METADATA[platform]?.dir})`,\n}));\n\nexport const getDetectedPlatform = (): Platform | undefined =>\n PLATFORM_CHECKS.find(({ check }) => check())?.platform;\n\nconst getDependencies = (root: string): Record<string, string> => {\n try {\n const packageJsonPath = join(root, 'package.json');\n if (!existsSync(packageJsonPath)) return {};\n\n const { dependencies = {}, devDependencies = {} } = JSON.parse(\n readFileSync(packageJsonPath, 'utf-8')\n );\n return { ...dependencies, ...devDependencies };\n } catch {\n return {};\n }\n};\n\n/**\n * Asks which AI platform the user is using, preselecting the detected one.\n * Resolves to `undefined` when the prompt is cancelled.\n */\nexport const promptPlatform = async (): Promise<Platform | undefined> => {\n const detectedPlatform = getDetectedPlatform();\n\n try {\n const response = await enquirer.prompt<{ platform: Platform }>({\n type: 'autocomplete',\n name: 'platform',\n message: 'Which platform are you using? (Type to search)',\n multiple: false,\n initial: detectedPlatform\n ? PLATFORMS.indexOf(detectedPlatform)\n : undefined,\n choices: PLATFORM_OPTIONS.map((option) => ({\n name: option.value,\n message: option.label,\n hint: option.hint,\n })),\n });\n\n return response.platform;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Installs the Intlayer documentation skills. The skills are picked first, then\n * the platform (unless preselected). Resolves to the platform used, so a\n * following step (e.g. MCP) can reuse it without asking again.\n */\nexport const initSkills = async (\n projectRoot?: string,\n preselectedPlatform?: Platform\n): Promise<Platform | undefined> => {\n const p = await loadPrompts();\n\n const root = findProjectRoot(\n projectRoot ? resolve(projectRoot) : process.cwd()\n );\n\n p.intro('Initializing Intlayer skills');\n\n const dependencies = getDependencies(root);\n const initialValues = getInitialSkills(dependencies);\n\n const selectedSkills = await p.multiselect({\n message: 'Select the documentation skills to provide to your AI:',\n initialValues,\n options: SKILLS.map((skill) => ({\n value: skill,\n label: skill,\n hint: SKILLS_METADATA[skill],\n })),\n required: false,\n });\n\n if (\n p.isCancel(selectedSkills) ||\n !selectedSkills ||\n (selectedSkills as string[]).length === 0\n ) {\n p.cancel('Operation cancelled. No skills selected.');\n return;\n }\n\n const platform = preselectedPlatform ?? (await promptPlatform());\n\n if (!platform) {\n p.cancel('Operation cancelled. No platform selected.');\n return;\n }\n\n const s = p.spinner();\n s.start('Installing skills...');\n\n try {\n const result = await installSkills(root, platform, selectedSkills);\n\n s.stop('Skills installed successfully');\n\n p.note(result, 'Success');\n } catch (error) {\n s.stop('Failed to install skills');\n p.log.error(error instanceof Error ? error.message : String(error));\n }\n\n p.outro('Intlayer skills initialization complete');\n\n return platform;\n};\n"],"mappings":";;;;;;;;AAeA,MAAM,kBACJ,UAAU,QAAQ,aAAa,mBAAmB,SAAS,EAAE,KAAK,CAAC,CAAC,KACjE,cAAc;CACb,OAAO,mBAAmB,SAAS,EAAE,gBAAgB;CACrD;AACF,EACF;AAEF,MAAa,mBAIR,UAAU,KAAK,cAAc;CAChC,OAAO;CACP,OAAO,mBAAmB,SAAS,EAAE,SAAS;CAC9C,MAAM,IAAI,mBAAmB,SAAS,EAAE,IAAI;AAC9C,EAAE;AAEF,MAAa,4BACX,gBAAgB,MAAM,EAAE,YAAY,MAAM,CAAC,CAAC,EAAE;AAEhD,MAAM,mBAAmB,SAAyC;CAChE,IAAI;EACF,MAAM,kBAAkB,KAAK,MAAM,cAAc;EACjD,IAAI,CAAC,WAAW,eAAe,GAAG,OAAO,CAAC;EAE1C,MAAM,EAAE,eAAe,CAAC,GAAG,kBAAkB,CAAC,MAAM,KAAK,MACvD,aAAa,iBAAiB,OAAO,CACvC;EACA,OAAO;GAAE,GAAG;GAAc,GAAG;EAAgB;CAC/C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;;;;AAMA,MAAa,iBAAiB,YAA2C;CACvE,MAAM,mBAAmB,oBAAoB;CAE7C,IAAI;EAgBF,QAAO,MAfgB,SAAS,OAA+B;GAC7D,MAAM;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS,mBACL,UAAU,QAAQ,gBAAgB,IAClC;GACJ,SAAS,iBAAiB,KAAK,YAAY;IACzC,MAAM,OAAO;IACb,SAAS,OAAO;IAChB,MAAM,OAAO;GACf,EAAE;EACJ,CAAC,EAEc,CAAC;CAClB,QAAQ;EACN;CACF;AACF;;;;;;AAOA,MAAa,aAAa,OACxB,aACA,wBACkC;CAClC,MAAM,IAAI,MAAM,YAAY;CAE5B,MAAM,OAAO,gBACX,cAAc,QAAQ,WAAW,IAAI,QAAQ,IAAI,CACnD;CAEA,EAAE,MAAM,8BAA8B;CAEtC,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,gBAAgB,iBAAiB,YAAY;CAEnD,MAAM,iBAAiB,MAAM,EAAE,YAAY;EACzC,SAAS;EACT;EACA,SAAS,OAAO,KAAK,WAAW;GAC9B,OAAO;GACP,OAAO;GACP,MAAM,gBAAgB;EACxB,EAAE;EACF,UAAU;CACZ,CAAC;CAED,IACE,EAAE,SAAS,cAAc,KACzB,CAAC,kBACA,eAA4B,WAAW,GACxC;EACA,EAAE,OAAO,0CAA0C;EACnD;CACF;CAEA,MAAM,WAAW,uBAAwB,MAAM,eAAe;CAE9D,IAAI,CAAC,UAAU;EACb,EAAE,OAAO,4CAA4C;EACrD;CACF;CAEA,MAAM,IAAI,EAAE,QAAQ;CACpB,EAAE,MAAM,sBAAsB;CAE9B,IAAI;EACF,MAAM,SAAS,MAAM,cAAc,MAAM,UAAU,cAAc;EAEjE,EAAE,KAAK,+BAA+B;EAEtC,EAAE,KAAK,QAAQ,SAAS;CAC1B,SAAS,OAAO;EACd,EAAE,KAAK,0BAA0B;EACjC,EAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CACpE;CAEA,EAAE,MAAM,yCAAyC;CAEjD,OAAO;AACT"}
1
+ {"version":3,"file":"initSkills.mjs","names":[],"sources":["../../src/initSkills.ts"],"sourcesContent":["import {\n detectPlatform,\n getInitialSkills,\n installSkills,\n PLATFORMS,\n PLATFORMS_METADATA,\n type Platform,\n SKILLS,\n SKILLS_METADATA,\n type Skill,\n} from '@intlayer/engine/cli';\nimport enquirer from 'enquirer';\nimport { getProjectDependencies, resolveProjectRoot } from './init';\nimport { loadPrompts } from './loadPrompts';\nimport { isInteractiveTerminal } from './utils/isInteractiveTerminal';\nimport { parseChoice } from './utils/parseChoice';\n\nexport const PLATFORM_OPTIONS: Array<{\n value: Platform;\n label: string;\n hint: string;\n}> = PLATFORMS.map((platform) => ({\n value: platform,\n label: PLATFORMS_METADATA[platform]?.label ?? '',\n hint: `(${PLATFORMS_METADATA[platform]?.dir})`,\n}));\n\n/**\n * Asks which AI platform the user is using, preselecting the detected one.\n * Resolves to `undefined` when the prompt is cancelled.\n */\nexport const promptPlatform = async (\n projectRoot: string\n): Promise<Platform | undefined> => {\n const detectedPlatform = detectPlatform(projectRoot);\n\n try {\n const response = await enquirer.prompt<{ platform: Platform }>({\n type: 'autocomplete',\n name: 'platform',\n message: 'Which platform are you using? (Type to search)',\n multiple: false,\n initial: detectedPlatform\n ? PLATFORMS.indexOf(detectedPlatform)\n : undefined,\n choices: PLATFORM_OPTIONS.map((option) => ({\n name: option.value,\n message: option.label,\n hint: option.hint,\n })),\n });\n\n return response.platform;\n } catch {\n return undefined;\n }\n};\n\n/** Options of {@link initSkills}; anything omitted is prompted for. */\nexport type InitSkillsOptions = {\n /** AI platform to install the skills for. */\n platform?: Platform;\n /** Skills to install. Defaults to the ones matching the project stack. */\n skills?: Skill[];\n};\n\n/** Validates a `--platform` value, ignoring case. */\nexport const parsePlatform = (value: string): Platform =>\n parseChoice(value, PLATFORMS, '--platform');\n\n/** Validates the `--skills` values, ignoring case. */\nexport const parseSkills = (values: string[]): Skill[] =>\n values\n .flatMap((value) => value.split(','))\n .filter((value) => value.trim() !== '')\n .map((value) => parseChoice(value, SKILLS, '--skills'));\n\n/**\n * Resolves the platform without prompting: the given one, else the detected\n * one. Logs how to pass it and sets a failing exit code when neither exists.\n */\nexport const resolvePlatformWithoutPrompt = async (\n projectRoot: string,\n platform: Platform | undefined,\n command: string\n): Promise<Platform | undefined> => {\n const resolvedPlatform = platform ?? detectPlatform(projectRoot);\n\n if (!resolvedPlatform) {\n const p = await loadPrompts();\n\n p.log.error(\n `No AI platform detected. Pass it explicitly: ${command} --platform <platform>\\nPlatforms: ${PLATFORMS.join(', ')}`\n );\n process.exitCode = 1;\n }\n\n return resolvedPlatform;\n};\n\n/**\n * Installs the Intlayer documentation skills. The skills are picked first, then\n * the platform. Without a terminal (AI agents, CI), nothing is prompted: the\n * skills default to the project stack and the platform to the detected one.\n * Resolves to the platform used, so a following step (e.g. MCP) can reuse it\n * without asking again.\n */\nexport const initSkills = async (\n projectRoot?: string,\n options: InitSkillsOptions = {}\n): Promise<Platform | undefined> => {\n const p = await loadPrompts();\n\n const root = resolveProjectRoot(projectRoot);\n const isInteractive = isInteractiveTerminal();\n\n p.intro('Initializing Intlayer skills');\n\n const initialSkills = getInitialSkills(getProjectDependencies(root));\n\n const selectedSkills =\n options.skills ??\n (isInteractive\n ? await p.multiselect({\n message: 'Select the documentation skills to provide to your AI:',\n initialValues: initialSkills,\n options: SKILLS.map((skill) => ({\n value: skill,\n label: skill,\n hint: SKILLS_METADATA[skill],\n })),\n required: false,\n })\n : initialSkills);\n\n if (p.isCancel(selectedSkills) || selectedSkills.length === 0) {\n p.cancel('Operation cancelled. No skills selected.');\n return;\n }\n\n const platform = isInteractive\n ? (options.platform ?? (await promptPlatform(root)))\n : await resolvePlatformWithoutPrompt(\n root,\n options.platform,\n 'intlayer init skills'\n );\n\n if (!platform) {\n p.cancel('Operation cancelled. No platform selected.');\n return;\n }\n\n const s = p.spinner();\n s.start('Installing skills...');\n\n try {\n const result = await installSkills(root, platform, selectedSkills);\n\n s.stop('Skills installed successfully');\n\n p.note(result, 'Success');\n } catch (error) {\n s.stop('Failed to install skills');\n p.log.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n }\n\n p.outro('Intlayer skills initialization complete');\n\n return platform;\n};\n"],"mappings":";;;;;;;;AAiBA,MAAa,mBAIR,UAAU,KAAK,cAAc;CAChC,OAAO;CACP,OAAO,mBAAmB,SAAS,EAAE,SAAS;CAC9C,MAAM,IAAI,mBAAmB,SAAS,EAAE,IAAI;AAC9C,EAAE;;;;;AAMF,MAAa,iBAAiB,OAC5B,gBACkC;CAClC,MAAM,mBAAmB,eAAe,WAAW;CAEnD,IAAI;EAgBF,QAAO,MAfgB,SAAS,OAA+B;GAC7D,MAAM;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS,mBACL,UAAU,QAAQ,gBAAgB,IAClC;GACJ,SAAS,iBAAiB,KAAK,YAAY;IACzC,MAAM,OAAO;IACb,SAAS,OAAO;IAChB,MAAM,OAAO;GACf,EAAE;EACJ,CAAC,EAEc,CAAC;CAClB,QAAQ;EACN;CACF;AACF;;AAWA,MAAa,iBAAiB,UAC5B,YAAY,OAAO,WAAW,YAAY;;AAG5C,MAAa,eAAe,WAC1B,OACG,SAAS,UAAU,MAAM,MAAM,GAAG,CAAC,CAAC,CACpC,QAAQ,UAAU,MAAM,KAAK,MAAM,EAAE,CAAC,CACtC,KAAK,UAAU,YAAY,OAAO,QAAQ,UAAU,CAAC;;;;;AAM1D,MAAa,+BAA+B,OAC1C,aACA,UACA,YACkC;CAClC,MAAM,mBAAmB,YAAY,eAAe,WAAW;CAE/D,IAAI,CAAC,kBAAkB;EAGrB,OAFgB,YAAY,EAE3B,CAAC,IAAI,MACJ,gDAAgD,QAAQ,qCAAqC,UAAU,KAAK,IAAI,GAClH;EACA,QAAQ,WAAW;CACrB;CAEA,OAAO;AACT;;;;;;;;AASA,MAAa,aAAa,OACxB,aACA,UAA6B,CAAC,MACI;CAClC,MAAM,IAAI,MAAM,YAAY;CAE5B,MAAM,OAAO,mBAAmB,WAAW;CAC3C,MAAM,gBAAgB,sBAAsB;CAE5C,EAAE,MAAM,8BAA8B;CAEtC,MAAM,gBAAgB,iBAAiB,uBAAuB,IAAI,CAAC;CAEnE,MAAM,iBACJ,QAAQ,WACP,gBACG,MAAM,EAAE,YAAY;EAClB,SAAS;EACT,eAAe;EACf,SAAS,OAAO,KAAK,WAAW;GAC9B,OAAO;GACP,OAAO;GACP,MAAM,gBAAgB;EACxB,EAAE;EACF,UAAU;CACZ,CAAC,IACD;CAEN,IAAI,EAAE,SAAS,cAAc,KAAK,eAAe,WAAW,GAAG;EAC7D,EAAE,OAAO,0CAA0C;EACnD;CACF;CAEA,MAAM,WAAW,gBACZ,QAAQ,YAAa,MAAM,eAAe,IAAI,IAC/C,MAAM,6BACJ,MACA,QAAQ,UACR,sBACF;CAEJ,IAAI,CAAC,UAAU;EACb,EAAE,OAAO,4CAA4C;EACrD;CACF;CAEA,MAAM,IAAI,EAAE,QAAQ;CACpB,EAAE,MAAM,sBAAsB;CAE9B,IAAI;EACF,MAAM,SAAS,MAAM,cAAc,MAAM,UAAU,cAAc;EAEjE,EAAE,KAAK,+BAA+B;EAEtC,EAAE,KAAK,QAAQ,SAAS;CAC1B,SAAS,OAAO;EACd,EAAE,KAAK,0BAA0B;EACjC,EAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EAClE,QAAQ,WAAW;CACrB;CAEA,EAAE,MAAM,yCAAyC;CAEjD,OAAO;AACT"}
@@ -1,5 +1,5 @@
1
- import { relative } from "node:path";
2
1
  import { prepareIntlayer } from "@intlayer/engine/cli";
2
+ import { relative } from "node:path";
3
3
  import { colon, colorizeKey, colorizeNumber, getAppLogger } from "@intlayer/config/logger";
4
4
  import { getConfiguration } from "@intlayer/config/node";
5
5
  import { formatPath } from "@intlayer/engine/utils";
@@ -1,5 +1,5 @@
1
- import { relative } from "node:path";
2
1
  import { listProjects } from "@intlayer/engine/cli";
2
+ import { relative } from "node:path";
3
3
 
4
4
  //#region src/listProjects.ts
5
5
  const listProjectsCommand = async (options) => {
package/dist/esm/pull.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { checkCMSAuth, getAuthenticatedAPI } from "./utils/checkAccess.mjs";
2
2
  import { PullLogger } from "./push/pullLog.mjs";
3
3
  import { selectCmsEnvironment } from "./utils/selectCmsEnvironment.mjs";
4
- import { join } from "node:path";
5
4
  import { logConfigDetails } from "@intlayer/engine/cli";
6
5
  import { existsSync } from "node:fs";
6
+ import { join } from "node:path";
7
7
  import * as ANSIColors from "@intlayer/config/colors";
8
8
  import { getAppLogger } from "@intlayer/config/logger";
9
9
  import { getConfiguration } from "@intlayer/config/node";
@@ -2,8 +2,8 @@ import { loadPrompts } from "../loadPrompts.mjs";
2
2
  import { checkCMSAuth, getAuthenticatedAPI } from "../utils/checkAccess.mjs";
3
3
  import { selectCmsEnvironment } from "../utils/selectCmsEnvironment.mjs";
4
4
  import { PushLogger } from "../pushLog.mjs";
5
- import { join } from "node:path";
6
5
  import { listGitFiles, logConfigDetails } from "@intlayer/engine/cli";
6
+ import { join } from "node:path";
7
7
  import * as ANSIColors from "@intlayer/config/colors";
8
8
  import { colorize, colorizeKey, getAppLogger } from "@intlayer/config/logger";
9
9
  import { getConfiguration } from "@intlayer/config/node";
@@ -6,9 +6,9 @@ import { reviewFileBlockAware } from "./reviewDocBlockAware.mjs";
6
6
  import { buildFileReviewReport, logReviewFileBlocks } from "./reviewDocLog.mjs";
7
7
  import { createReviewProgressLogger } from "./reviewDocProgress.mjs";
8
8
  import { formatReviewSynthesis } from "./reviewDocSynthesis.mjs";
9
- import { join, relative } from "node:path";
10
9
  import { listGitFiles, listGitLines, logConfigDetails } from "@intlayer/engine/cli";
11
10
  import { existsSync } from "node:fs";
11
+ import { join, relative } from "node:path";
12
12
  import * as ANSIColors from "@intlayer/config/colors";
13
13
  import { colorize, colorizeNumber, getAppLogger, x } from "@intlayer/config/logger";
14
14
  import { getConfiguration } from "@intlayer/config/node";
@@ -2,8 +2,8 @@ import { readAsset } from "../_virtual/_utils_asset.mjs";
2
2
  import { sanitizeChunk, validateTranslation } from "../translateDoc/validation.mjs";
3
3
  import { chunkInference } from "../utils/chunkInference.mjs";
4
4
  import { fixChunkStartEndChars } from "../utils/fixChunkStartEndChars.mjs";
5
- import { dirname } from "node:path";
6
5
  import { mkdirSync, writeFileSync } from "node:fs";
6
+ import { dirname } from "node:path";
7
7
  import * as ANSIColors from "@intlayer/config/colors";
8
8
  import { colon, colorize, colorizeNumber, getAppLogger } from "@intlayer/config/logger";
9
9
  import { getConfiguration } from "@intlayer/config/node";
package/dist/esm/scan.mjs CHANGED
@@ -92,7 +92,7 @@ const scan = async (url, options = {}) => {
92
92
  appLogger(`Routing: ${colorize(routingLabels[routing.strategy], ANSIColors.BLUE)} ${colorize(`(${routing.evidence}${routing.defaultLocale ? `, default locale: ${routing.defaultLocale}` : ""})`, ANSIColors.GREY)}`);
93
93
  if (result.technologies.length > 0) {
94
94
  appLogger("\nStack:");
95
- for (const technology of result.technologies) appLogger(` ${colorize(categoryLabels[technology.category], ANSIColors.GREY)} ${technology.name}${technology.version ? ` ${technology.version}` : ""} ${colorize(`(${technology.evidence})`, ANSIColors.GREY)}`);
95
+ for (const technology of result.technologies) appLogger(` ${colorize(categoryLabels[technology.category], ANSIColors.GREY)} ${technology.name}${technology.version ? ` ${technology.version}` : ""}`);
96
96
  }
97
97
  appLogger("\nChecks:");
98
98
  for (const event of result.events) logCheck(appLogger, event);
@@ -1 +1 @@
1
- {"version":3,"file":"scan.mjs","names":[],"sources":["../../src/scan.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport {\n type DetectedTechnology,\n formatSize,\n getCheckDetailLines,\n type ScanEvent,\n type ScanResult,\n scanWebsite,\n} from '@intlayer/engine/scan';\nimport type { ConfigurationOptions } from './cli';\n\n/** Options accepted by the {@link scan} command. */\nexport type ScanCommandOptions = {\n /** Disable the deeper puppeteer-based render scan. */\n deep?: boolean;\n /** Output the raw {@link ScanResult} as JSON instead of formatted text. */\n json?: boolean;\n configOptions?: ConfigurationOptions;\n};\n\n/** Human-readable labels for each scorable check type. */\nconst checkLabels: Record<string, string> = {\n robots_robotsPresent: 'robots.txt present',\n robots_noLocalizedUrlsForgotten: 'robots.txt keeps localized URLs crawlable',\n sitemap_sitemapPresent: 'sitemap present',\n sitemap_noLocalizedUrlsForgotten: 'sitemap lists every locale',\n sitemap_hasAlternates: 'sitemap has alternate links',\n sitemap_hasXDefault: 'sitemap has x-default',\n url_htmlLang: 'html lang attribute',\n url_htmlDir: 'html dir attribute',\n url_currentLocale: 'locale signals consistent (lang, URL, hreflang)',\n url_ogLocale: 'og:locale meta tag',\n url_hasCanonical: 'canonical link',\n url_hreflang: 'hreflang tags',\n url_hreflangReciprocal: 'hreflang alternates link back',\n url_hasXDefault: 'x-default hreflang',\n url_hasLocalizedLinks: 'localized internal links',\n url_allAnchorsLocalized: 'all internal links keep the locale',\n url_hasLangSelector: 'crawlable language switcher',\n url_unusedBundleContent: 'unused bundle locale content',\n};\n\n/** Human-readable labels of the routing strategies. */\nconst routingLabels: Record<ScanResult['routing']['strategy'], string> = {\n 'prefix-all': 'locale prefix on every URL (/en/…, /fr/…)',\n 'prefix-no-default': 'locale prefix except for the default locale',\n 'search-params': 'locale in a query parameter',\n subdomain: 'locale subdomain (fr.example.com)',\n domain: 'one domain per locale',\n 'no-prefix': 'no locale in the URL (cookie / header based)',\n unknown: 'unknown',\n};\n\n/** Human-readable labels of the technology categories. */\nconst categoryLabels: Record<DetectedTechnology['category'], string> = {\n framework: 'Framework',\n 'i18n-library': 'i18n library',\n tms: 'TMS',\n 'translation-proxy': 'Translation proxy',\n cms: 'CMS',\n};\n\n/** Maximum number of detail lines printed under a failing check. */\nconst MAX_DETAIL_LINES = 3;\n\nconst statusIcon = (status: ScanEvent['status']): string => {\n if (status === 'success') return colorize('✓', ANSIColors.GREEN);\n if (status === 'warning') return colorize('⚠', ANSIColors.YELLOW);\n return colorize('✗', ANSIColors.RED);\n};\n\nconst scoreColor = (score: number) => {\n if (score >= 80) return ANSIColors.GREEN;\n if (score >= 50) return ANSIColors.YELLOW;\n return ANSIColors.RED;\n};\n\n/** Print a check with, when it fails, a short explanation. */\nconst logCheck = (\n appLogger: ReturnType<typeof getAppLogger>,\n event: ScanEvent\n): void => {\n const type = event.type.split('\\\\')[0];\n if (!type) return;\n\n appLogger(` ${statusIcon(event.status)} ${checkLabels[type] ?? type}`);\n\n if (event.status === 'success') return;\n\n const detailLines = getCheckDetailLines(event.details?.[event.status]);\n detailLines.slice(0, MAX_DETAIL_LINES).forEach((line, index) => {\n appLogger(\n colorize(`${index === 0 ? ' ' : ' '}${line}`, ANSIColors.GREY)\n );\n });\n if (detailLines.length > MAX_DETAIL_LINES) {\n appLogger(\n colorize(\n ` … ${detailLines.length - MAX_DETAIL_LINES} more (use --json)`,\n ANSIColors.GREY\n )\n );\n }\n};\n\n/**\n * Scan a website for i18n/SEO health and bundle weight, printing a formatted\n * report (or JSON with `--json`).\n *\n * @example\n * ```sh\n * npx intlayer scan https://intlayer.org\n * ```\n */\nexport const scan = async (\n url: string,\n options: ScanCommandOptions = {}\n): Promise<void> => {\n const configuration = getConfiguration(options.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const result = await scanWebsite(url, { deep: options.deep });\n\n if (options.json) {\n appLogger(JSON.stringify(result, null, 2));\n return;\n }\n\n appLogger(\n `\\n🔍 Scanned ${colorize(result.url, ANSIColors.GREY_LIGHT)} ${colorize(\n `(${result.mode} mode)`,\n ANSIColors.GREY\n )}\\n`\n );\n\n appLogger(\n `Score: ${colorize(`${result.score}/100`, scoreColor(result.score))}`\n );\n appLogger(\n `Page size: ${colorize(formatSize(result.totalPageSize), ANSIColors.BLUE)} ${colorize(\n `(HTML ${formatSize(result.htmlSize)})`,\n ANSIColors.GREY\n )}`\n );\n if (result.locales.length > 0) {\n appLogger(\n `Locales: ${colorize(result.locales.join(', '), ANSIColors.GREEN)}`\n );\n }\n\n const { routing } = result;\n appLogger(\n `Routing: ${colorize(routingLabels[routing.strategy], ANSIColors.BLUE)} ${colorize(\n `(${routing.evidence}${routing.defaultLocale ? `, default locale: ${routing.defaultLocale}` : ''})`,\n ANSIColors.GREY\n )}`\n );\n\n if (result.technologies.length > 0) {\n appLogger('\\nStack:');\n for (const technology of result.technologies) {\n appLogger(\n ` ${colorize(categoryLabels[technology.category], ANSIColors.GREY)} ${technology.name}${\n technology.version ? ` ${technology.version}` : ''\n } ${colorize(`(${technology.evidence})`, ANSIColors.GREY)}`\n );\n }\n }\n\n appLogger('\\nChecks:');\n for (const event of result.events) {\n logCheck(appLogger, event);\n }\n\n if (result.bundle && result.bundle.totalLocaleSize > 0) {\n const { bundle } = result;\n appLogger('\\nBundle locale weight:');\n appLogger(\n ` Translations shipped: ${colorize(formatSize(bundle.totalLocaleSize), ANSIColors.BLUE)}`\n );\n appLogger(\n ` Unused (other locales): ${colorize(\n `${formatSize(bundle.totalUnusedLocaleSize)} (${bundle.unusedPercentOfLocale}%)`,\n bundle.unusedPercentOfLocale > 30\n ? ANSIColors.RED\n : bundle.unusedPercentOfLocale > 0\n ? ANSIColors.YELLOW\n : ANSIColors.GREEN\n )}`\n );\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"scan.mjs","names":[],"sources":["../../src/scan.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport {\n type DetectedTechnology,\n formatSize,\n getCheckDetailLines,\n type ScanEvent,\n type ScanResult,\n scanWebsite,\n} from '@intlayer/engine/scan';\nimport type { ConfigurationOptions } from './cli';\n\n/** Options accepted by the {@link scan} command. */\nexport type ScanCommandOptions = {\n /** Disable the deeper puppeteer-based render scan. */\n deep?: boolean;\n /** Output the raw {@link ScanResult} as JSON instead of formatted text. */\n json?: boolean;\n configOptions?: ConfigurationOptions;\n};\n\n/** Human-readable labels for each scorable check type. */\nconst checkLabels: Record<string, string> = {\n robots_robotsPresent: 'robots.txt present',\n robots_noLocalizedUrlsForgotten: 'robots.txt keeps localized URLs crawlable',\n sitemap_sitemapPresent: 'sitemap present',\n sitemap_noLocalizedUrlsForgotten: 'sitemap lists every locale',\n sitemap_hasAlternates: 'sitemap has alternate links',\n sitemap_hasXDefault: 'sitemap has x-default',\n url_htmlLang: 'html lang attribute',\n url_htmlDir: 'html dir attribute',\n url_currentLocale: 'locale signals consistent (lang, URL, hreflang)',\n url_ogLocale: 'og:locale meta tag',\n url_hasCanonical: 'canonical link',\n url_hreflang: 'hreflang tags',\n url_hreflangReciprocal: 'hreflang alternates link back',\n url_hasXDefault: 'x-default hreflang',\n url_hasLocalizedLinks: 'localized internal links',\n url_allAnchorsLocalized: 'all internal links keep the locale',\n url_hasLangSelector: 'crawlable language switcher',\n url_unusedBundleContent: 'unused bundle locale content',\n};\n\n/** Human-readable labels of the routing strategies. */\nconst routingLabels: Record<ScanResult['routing']['strategy'], string> = {\n 'prefix-all': 'locale prefix on every URL (/en/…, /fr/…)',\n 'prefix-no-default': 'locale prefix except for the default locale',\n 'search-params': 'locale in a query parameter',\n subdomain: 'locale subdomain (fr.example.com)',\n domain: 'one domain per locale',\n 'no-prefix': 'no locale in the URL (cookie / header based)',\n unknown: 'unknown',\n};\n\n/** Human-readable labels of the technology categories. */\nconst categoryLabels: Record<DetectedTechnology['category'], string> = {\n framework: 'Framework',\n 'i18n-library': 'i18n library',\n tms: 'TMS',\n 'translation-proxy': 'Translation proxy',\n cms: 'CMS',\n};\n\n/** Maximum number of detail lines printed under a failing check. */\nconst MAX_DETAIL_LINES = 3;\n\nconst statusIcon = (status: ScanEvent['status']): string => {\n if (status === 'success') return colorize('✓', ANSIColors.GREEN);\n if (status === 'warning') return colorize('⚠', ANSIColors.YELLOW);\n return colorize('✗', ANSIColors.RED);\n};\n\nconst scoreColor = (score: number) => {\n if (score >= 80) return ANSIColors.GREEN;\n if (score >= 50) return ANSIColors.YELLOW;\n return ANSIColors.RED;\n};\n\n/** Print a check with, when it fails, a short explanation. */\nconst logCheck = (\n appLogger: ReturnType<typeof getAppLogger>,\n event: ScanEvent\n): void => {\n const type = event.type.split('\\\\')[0];\n if (!type) return;\n\n appLogger(` ${statusIcon(event.status)} ${checkLabels[type] ?? type}`);\n\n if (event.status === 'success') return;\n\n const detailLines = getCheckDetailLines(event.details?.[event.status]);\n detailLines.slice(0, MAX_DETAIL_LINES).forEach((line, index) => {\n appLogger(\n colorize(`${index === 0 ? ' ' : ' '}${line}`, ANSIColors.GREY)\n );\n });\n if (detailLines.length > MAX_DETAIL_LINES) {\n appLogger(\n colorize(\n ` … ${detailLines.length - MAX_DETAIL_LINES} more (use --json)`,\n ANSIColors.GREY\n )\n );\n }\n};\n\n/**\n * Scan a website for i18n/SEO health and bundle weight, printing a formatted\n * report (or JSON with `--json`).\n *\n * @example\n * ```sh\n * npx intlayer scan https://intlayer.org\n * ```\n */\nexport const scan = async (\n url: string,\n options: ScanCommandOptions = {}\n): Promise<void> => {\n const configuration = getConfiguration(options.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const result = await scanWebsite(url, { deep: options.deep });\n\n if (options.json) {\n appLogger(JSON.stringify(result, null, 2));\n return;\n }\n\n appLogger(\n `\\n🔍 Scanned ${colorize(result.url, ANSIColors.GREY_LIGHT)} ${colorize(\n `(${result.mode} mode)`,\n ANSIColors.GREY\n )}\\n`\n );\n\n appLogger(\n `Score: ${colorize(`${result.score}/100`, scoreColor(result.score))}`\n );\n appLogger(\n `Page size: ${colorize(formatSize(result.totalPageSize), ANSIColors.BLUE)} ${colorize(\n `(HTML ${formatSize(result.htmlSize)})`,\n ANSIColors.GREY\n )}`\n );\n if (result.locales.length > 0) {\n appLogger(\n `Locales: ${colorize(result.locales.join(', '), ANSIColors.GREEN)}`\n );\n }\n\n const { routing } = result;\n appLogger(\n `Routing: ${colorize(routingLabels[routing.strategy], ANSIColors.BLUE)} ${colorize(\n `(${routing.evidence}${routing.defaultLocale ? `, default locale: ${routing.defaultLocale}` : ''})`,\n ANSIColors.GREY\n )}`\n );\n\n if (result.technologies.length > 0) {\n appLogger('\\nStack:');\n for (const technology of result.technologies) {\n appLogger(\n ` ${colorize(categoryLabels[technology.category], ANSIColors.GREY)} ${technology.name}${\n technology.version ? ` ${technology.version}` : ''\n }`\n );\n }\n }\n\n appLogger('\\nChecks:');\n for (const event of result.events) {\n logCheck(appLogger, event);\n }\n\n if (result.bundle && result.bundle.totalLocaleSize > 0) {\n const { bundle } = result;\n appLogger('\\nBundle locale weight:');\n appLogger(\n ` Translations shipped: ${colorize(formatSize(bundle.totalLocaleSize), ANSIColors.BLUE)}`\n );\n appLogger(\n ` Unused (other locales): ${colorize(\n `${formatSize(bundle.totalUnusedLocaleSize)} (${bundle.unusedPercentOfLocale}%)`,\n bundle.unusedPercentOfLocale > 30\n ? ANSIColors.RED\n : bundle.unusedPercentOfLocale > 0\n ? ANSIColors.YELLOW\n : ANSIColors.GREEN\n )}`\n );\n }\n};\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import { setupAI } from "../utils/setupAI.mjs";
2
2
  import { getOutputFilePath } from "../utils/getOutputFilePath.mjs";
3
3
  import { checkFileModifiedRange } from "../utils/checkFileModifiedRange.mjs";
4
4
  import { translateFile } from "./translateFile.mjs";
5
- import { dirname, join } from "node:path";
6
5
  import { listGitFiles, logConfigDetails } from "@intlayer/engine/cli";
7
6
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
7
+ import { dirname, join } from "node:path";
8
8
  import * as ANSIColors from "@intlayer/config/colors";
9
9
  import { colorize, colorizeNumber, getAppLogger, x } from "@intlayer/config/logger";
10
10
  import { getConfiguration } from "@intlayer/config/node";
@@ -1,6 +1,6 @@
1
1
  import { findProjectRoot } from "./init.mjs";
2
- import { resolve } from "node:path";
3
2
  import { upgradeIntlayerPackages } from "@intlayer/engine/cli";
3
+ import { resolve } from "node:path";
4
4
 
5
5
  //#region src/upgrade.ts
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { dirname, resolve } from "node:path";
2
1
  import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
3
 
4
4
  //#region src/utils/getParentPackageJSON.ts
5
5
  const getParentPackageJSON = (startDir) => {
@@ -0,0 +1,11 @@
1
+ //#region src/utils/isInteractiveTerminal.ts
2
+ /**
3
+ * Whether the process can prompt: both stdin and stdout are attached to a
4
+ * terminal. False for AI agents, CI and piped runs, where a prompt would print
5
+ * and exit without an answer.
6
+ */
7
+ const isInteractiveTerminal = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
8
+
9
+ //#endregion
10
+ export { isInteractiveTerminal };
11
+ //# sourceMappingURL=isInteractiveTerminal.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInteractiveTerminal.mjs","names":[],"sources":["../../../src/utils/isInteractiveTerminal.ts"],"sourcesContent":["/**\n * Whether the process can prompt: both stdin and stdout are attached to a\n * terminal. False for AI agents, CI and piped runs, where a prompt would print\n * and exit without an answer.\n */\nexport const isInteractiveTerminal = (): boolean =>\n Boolean(process.stdin.isTTY && process.stdout.isTTY);\n"],"mappings":";;;;;;AAKA,MAAa,8BACX,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK"}
@@ -0,0 +1,20 @@
1
+ //#region src/utils/parseChoice.ts
2
+ /**
3
+ * Resolves a command-line value against its allowed choices, ignoring case.
4
+ *
5
+ * @param value - Raw value passed on the command line.
6
+ * @param choices - Accepted values, in their canonical spelling.
7
+ * @param optionName - Option name used in the error message (e.g. `--platform`).
8
+ * @returns The matching choice, in its canonical spelling.
9
+ * @throws When the value matches none of the choices.
10
+ */
11
+ const parseChoice = (value, choices, optionName) => {
12
+ const normalizedValue = value.trim().toLowerCase();
13
+ const choice = choices.find((candidate) => candidate.toLowerCase() === normalizedValue);
14
+ if (!choice) throw new Error(`Invalid ${optionName} value "${value}". Expected one of: ${choices.join(", ")}.`);
15
+ return choice;
16
+ };
17
+
18
+ //#endregion
19
+ export { parseChoice };
20
+ //# sourceMappingURL=parseChoice.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseChoice.mjs","names":[],"sources":["../../../src/utils/parseChoice.ts"],"sourcesContent":["/**\n * Resolves a command-line value against its allowed choices, ignoring case.\n *\n * @param value - Raw value passed on the command line.\n * @param choices - Accepted values, in their canonical spelling.\n * @param optionName - Option name used in the error message (e.g. `--platform`).\n * @returns The matching choice, in its canonical spelling.\n * @throws When the value matches none of the choices.\n */\nexport const parseChoice = <Choice extends string>(\n value: string,\n choices: readonly Choice[],\n optionName: string\n): Choice => {\n const normalizedValue = value.trim().toLowerCase();\n const choice = choices.find(\n (candidate) => candidate.toLowerCase() === normalizedValue\n );\n\n if (!choice) {\n throw new Error(\n `Invalid ${optionName} value \"${value}\". Expected one of: ${choices.join(', ')}.`\n );\n }\n\n return choice;\n};\n"],"mappings":";;;;;;;;;;AASA,MAAa,eACX,OACA,SACA,eACW;CACX,MAAM,kBAAkB,MAAM,KAAK,CAAC,CAAC,YAAY;CACjD,MAAM,SAAS,QAAQ,MACpB,cAAc,UAAU,YAAY,MAAM,eAC7C;CAEA,IAAI,CAAC,QACH,MAAM,IAAI,MACR,WAAW,WAAW,UAAU,MAAM,sBAAsB,QAAQ,KAAK,IAAI,EAAE,EACjF;CAGF,OAAO;AACT"}
@@ -15,9 +15,30 @@ export type FillOptions = {
15
15
  build?: boolean;
16
16
  skipMetadata?: boolean;
17
17
  } & GetTargetDictionaryOptions;
18
+ /** Outcome of a {@link fill} run. */
19
+ export type FillResult = {
20
+ /** No AI provider is reachable: nothing was translated. */
21
+ status: 'no-ai-access';
22
+ /** Why the AI provider could not be used, when known. */
23
+ error?: string;
24
+ } | {
25
+ /** No dictionary matched the filters: nothing was translated. */
26
+ status: 'no-dictionaries';
27
+ } | {
28
+ status: 'completed';
29
+ /** Keys of the dictionaries processed. */
30
+ dictionaryKeys: string[];
31
+ /** Translation tasks (one per dictionary and locale set) run. */
32
+ taskCount: number;
33
+ /** Tasks whose translation was written. */
34
+ writtenCount: number;
35
+ };
18
36
  /**
19
37
  * Fill translations based on the provided options.
38
+ *
39
+ * @returns What was done, so callers without a terminal (editor extension,
40
+ * MCP) can tell a completed run from one that translated nothing.
20
41
  */
21
- export declare const fill: (options?: FillOptions) => Promise<void>;
42
+ export declare const fill: (options?: FillOptions) => Promise<FillResult>;
22
43
  //#endregion
23
44
  //# sourceMappingURL=fill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fill.d.ts","names":[],"sources":["../../../src/fill/fill.ts"],"mappings":";;;;;YA2CY;EACV,eAAe;EACf,gBAAgB,SAAS;EACzB;EACA,aAAa;EACb,YAAY;EACZ;EACA;EACA;EACA;EACA;IACE;;;;qBAKS,OAAI,UAAoB,gBAAc"}
1
+ {"version":3,"file":"fill.d.ts","names":[],"sources":["../../../src/fill/fill.ts"],"mappings":";;;;;YA2CY;EACV,eAAe;EACf,gBAAgB,SAAS;EACzB;EACA,aAAa;EACb,YAAY;EACZ;EACA;EACA;EACA;EACA;IACE;;YAGQ;;EAGN;;EAEA;;;EAIA;;EAGA;;EAEA;;EAEA;;EAEA;;;;;;;;qBASO,OAAI,UAAoB,gBAAc,QAAQ"}
@@ -1,3 +1,3 @@
1
- import { FillOptions, fill } from "./fill.js";
1
+ import { FillOptions, FillResult, fill } from "./fill.js";
2
2
  import { writeFill } from "./writeFill.js";
3
- export { FillOptions, fill, writeFill };
3
+ export { FillOptions, FillResult, fill, writeFill };
@@ -3,11 +3,11 @@ import { bundle } from "./bundle.js";
3
3
  import { ConfigurationOptions, dirname, setAPI } from "./cli.js";
4
4
  import { startEditor } from "./editor.js";
5
5
  import { extract } from "./extract.js";
6
- import { FillOptions, fill } from "./fill/fill.js";
7
- import { ESLINT_CONFIG_FILES, INIT_STEP_GROUPS, InitStep, InitStepOption, LOCALE_ROUTING_CHOICES, LocaleRoutingChoice, OPT_IN_INIT_STEPS, findProjectRoot, getInitialInitSteps, getProjectDependencies, getRoutingInitOptions, init, isEslintInstalled, parseLocaleRoutingChoice } from "./init.js";
8
- import { BROWSER_EXTENSION_OPTIONS, CHROME_EXTENSION_URL, MOZILLA_EXTENSION_URL, initChromeExtension } from "./initChromeExtension.js";
6
+ import { FillOptions, FillResult, fill } from "./fill/fill.js";
7
+ import { DEFAULT_INIT_STEPS, ESLINT_CONFIG_FILES, INIT_STEP_COMMANDS, INIT_STEP_GROUPS, InitStep, InitStepOption, LOCALE_ROUTING_CHOICES, LocaleRoutingChoice, OPT_IN_INIT_STEPS, findProjectRoot, getInitOptionsForSteps, getInitialInitSteps, getProjectDependencies, getRoutingInitOptions, init, initCms, initSteps, isEslintInstalled, parseLocaleRoutingChoice, resolveProjectRoot } from "./init.js";
8
+ import { BROWSER_EXTENSION_OPTIONS, CHROME_EXTENSION_URL, EXTENSION_BROWSERS, EXTENSION_URL_BY_BROWSER, ExtensionBrowser, InitChromeExtensionOptions, MOZILLA_EXTENSION_URL, initChromeExtension, parseExtensionBrowsers } from "./initChromeExtension.js";
9
9
  import { INFRA_MODES, INSTALL_SCRIPT_URL, INSTALL_SCRIPT_URL_WINDOWS, InfraMode, InitInfraOptions, initInfra, parseInfraMode } from "./initInfra.js";
10
- import { PLATFORM_OPTIONS, getDetectedPlatform, initSkills, promptPlatform } from "./initSkills.js";
10
+ import { InitSkillsOptions, PLATFORM_OPTIONS, initSkills, parsePlatform, parseSkills, promptPlatform, resolvePlatformWithoutPrompt } from "./initSkills.js";
11
11
  import { listContentDeclaration, listContentDeclarationRows } from "./listContentDeclaration.js";
12
12
  import { ListProjectsCommandOptions, listProjectsCommand } from "./listProjects.js";
13
13
  import { liveSync } from "./liveSync.js";
@@ -21,8 +21,9 @@ import { listMissingTranslations, listMissingTranslationsWithConfig } from "./te
21
21
  import { testMissingTranslations } from "./test/test.js";
22
22
  import "./test/index.js";
23
23
  import { translateDoc } from "./translateDoc/translateDoc.js";
24
+ import { checkCMSAuth, getAuthenticatedAPI } from "./utils/checkAccess.js";
24
25
  export type * from "@intlayer/engine/cli";
25
26
  export type * from "@intlayer/engine/build";
26
27
  export type * from "@intlayer/engine/utils";
27
28
  export type * from "@intlayer/engine/watcher";
28
- export { BROWSER_EXTENSION_OPTIONS, CHROME_EXTENSION_URL, ConfigurationOptions, ESLINT_CONFIG_FILES, FillOptions, INFRA_MODES, INIT_STEP_GROUPS, INSTALL_SCRIPT_URL, INSTALL_SCRIPT_URL_WINDOWS, InfraMode, InitInfraOptions, InitStep, InitStepOption, LOCALE_ROUTING_CHOICES, ListProjectsCommandOptions, LocaleRoutingChoice, MOZILLA_EXTENSION_URL, OPT_IN_INIT_STEPS, PLATFORM_OPTIONS, ReviewDocMode, ScanCommandOptions, build, bundle, dirname, extract, fill, findProjectRoot, getDetectedPlatform, getInitialInitSteps, getProjectDependencies, getRoutingInitOptions, init, initChromeExtension, initInfra, initSkills, isEslintInstalled, listContentDeclaration, listContentDeclarationRows, listMissingTranslations, listMissingTranslationsWithConfig, listProjectsCommand, liveSync, parseInfraMode, parseLocaleRoutingChoice, promptPlatform, pull, push, pushConfig, reviewDoc, scan, searchDoc, setAPI, startEditor, testMissingTranslations, translateDoc };
29
+ export { BROWSER_EXTENSION_OPTIONS, CHROME_EXTENSION_URL, ConfigurationOptions, DEFAULT_INIT_STEPS, ESLINT_CONFIG_FILES, EXTENSION_BROWSERS, EXTENSION_URL_BY_BROWSER, ExtensionBrowser, FillOptions, FillResult, INFRA_MODES, INIT_STEP_COMMANDS, INIT_STEP_GROUPS, INSTALL_SCRIPT_URL, INSTALL_SCRIPT_URL_WINDOWS, InfraMode, InitChromeExtensionOptions, InitInfraOptions, InitSkillsOptions, InitStep, InitStepOption, LOCALE_ROUTING_CHOICES, ListProjectsCommandOptions, LocaleRoutingChoice, MOZILLA_EXTENSION_URL, OPT_IN_INIT_STEPS, PLATFORM_OPTIONS, ReviewDocMode, ScanCommandOptions, build, bundle, checkCMSAuth, dirname, extract, fill, findProjectRoot, getAuthenticatedAPI, getInitOptionsForSteps, getInitialInitSteps, getProjectDependencies, getRoutingInitOptions, init, initChromeExtension, initCms, initInfra, initSkills, initSteps, isEslintInstalled, listContentDeclaration, listContentDeclarationRows, listMissingTranslations, listMissingTranslationsWithConfig, listProjectsCommand, liveSync, parseExtensionBrowsers, parseInfraMode, parseLocaleRoutingChoice, parsePlatform, parseSkills, promptPlatform, pull, push, pushConfig, resolvePlatformWithoutPrompt, resolveProjectRoot, reviewDoc, scan, searchDoc, setAPI, startEditor, testMissingTranslations, translateDoc };
@@ -1,6 +1,8 @@
1
1
  import { InitOptions, RoutingMode } from "@intlayer/engine/cli";
2
2
  //#region src/init.d.ts
3
3
  export declare const findProjectRoot: (startDir: string) => string;
4
+ /** Resolves the project root from `--project-root`, else the working directory. */
5
+ export declare const resolveProjectRoot: (projectRoot?: string) => string;
4
6
  /** Individually selectable setup steps exposed by the interactive init flow. */
5
7
  export type InitStep = 'packages' | 'githubActions' | 'projectSetup' | 'vscodeExtension' | 'lsp' | 'eslint' | 'skills' | 'mcp' | 'infra' | 'cms' | 'chromeExtension';
6
8
  /** A checkbox entry of the interactive init flow. */
@@ -15,6 +17,35 @@ export type InitStepOption = {
15
17
  * rather than modifying the project, so they must be an explicit choice.
16
18
  */
17
19
  export declare const OPT_IN_INIT_STEPS: InitStep[];
20
+ /**
21
+ * Steps run by `intlayer init` without `--interactive`: install the packages
22
+ * and set up the framework. Every other step has its own command
23
+ * ({@link INIT_STEP_COMMANDS}), so nothing outside the app code is touched
24
+ * unless asked for.
25
+ */
26
+ export declare const DEFAULT_INIT_STEPS: InitStep[];
27
+ /**
28
+ * Command running each interactive step on its own, without prompts when every
29
+ * value is passed as a flag. Printed when `--interactive` has no terminal.
30
+ */
31
+ export declare const INIT_STEP_COMMANDS: Record<InitStep, string>;
32
+ /**
33
+ * Maps setup steps to the {@link initIntlayer} options: every step handled by
34
+ * `initIntlayer` that is not listed is skipped. Explicit `--no-*` flags in
35
+ * `baseOptions` still win over a listed step.
36
+ */
37
+ export declare const getInitOptionsForSteps: (steps: InitStep[], baseOptions?: InitOptions) => InitOptions;
38
+ /**
39
+ * Runs the given {@link initIntlayer} steps only (packages, project setup, CI,
40
+ * VS Code extension, LSP, lint rules). Backs `intlayer init` and its
41
+ * single-step subcommands.
42
+ */
43
+ export declare const initSteps: (projectRoot: string | undefined, steps: InitStep[], options?: InitOptions) => Promise<void>;
44
+ /**
45
+ * Logs in to the Intlayer CMS through the browser, then stores the access-key
46
+ * credentials in `.env` and enables the editor in the config file.
47
+ */
48
+ export declare const initCms: (projectRoot?: string) => Promise<void>;
18
49
  /** Grouped checkbox entries of the interactive init flow, in display order. */
19
50
  export declare const INIT_STEP_GROUPS: Record<string, InitStepOption[]>;
20
51
  /**
@@ -43,6 +74,11 @@ export declare const isEslintInstalled: (dependencies: Record<string, string>, r
43
74
  export declare const getInitialInitSteps: (dependencies: Record<string, string>, root?: string) => InitStep[];
44
75
  /** Reads the merged dependencies of the project at `root`. */
45
76
  export declare const getProjectDependencies: (root: string) => Record<string, string>;
77
+ /**
78
+ * `intlayer init`: installs the packages and sets up the framework, or, with
79
+ * `interactive`, lets the user pick every setup step. `--interactive` needs a
80
+ * terminal; without one it fails and lists the single-step commands instead.
81
+ */
46
82
  export declare const init: (projectRoot?: string, options?: InitOptions, interactive?: boolean) => Promise<void>;
47
83
  //#endregion
48
84
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","names":[],"sources":["../../src/init.ts"],"mappings":";;qBAmBa,kBAAe;;YAgBhB;;YAcA;EACV,OAAO;EACP;EACA;;;;;;;qBAQW,mBAAmB;;qBAGnB,kBAAkB,eAAe;;;;;YAsElC,sBAAsB;;qBAoCrB,wBAAsB;;qBAKtB,2BAAwB,kBAElC;;qBAaU,wBAAqB,QACxB,wBACP,KAAK;;qBAMK;;;;;qBAoBA,oBAAiB,cACd,wBAAsB;;;;;;qBAkBzB,sBAAmB,cAChB,wBAAsB,kBAEnC;;qBAcU,yBAAsB,iBAEhC;qBAgJU,OAAI,sBACK,UACV,aAAW,0BACA"}
1
+ {"version":3,"file":"init.d.ts","names":[],"sources":["../../src/init.ts"],"mappings":";;qBAqBa,kBAAe;;qBAgBf,qBAAkB;;YAInB;;YAcA;EACV,OAAO;EACP;EACA;;;;;;;qBAQW,mBAAmB;;;;;;;qBAQnB,oBAAoB;;;;;qBAMpB,oBAAoB,OAAO;;;;;;qBAmB3B,yBAAsB,OAC1B,YAAU,cACH,gBACb;;;;;;qBAwBU,YAAS,iCACW,OACxB,YAAU,UACP,gBACT;;;;;qBAWU,UAAO,yBAAiC;;qBAuBxC,kBAAkB,eAAe;;;;;YAsElC,sBAAsB;;qBAoCrB,wBAAsB;;qBAKtB,2BAAwB,kBAAoB;;qBAI5C,wBAAqB,QACxB,wBACP,KAAK;;qBAMK;;;;;qBAoBA,oBAAiB,cACd,wBAAsB;;;;;;qBAkBzB,sBAAmB,cAChB,wBAAsB,kBAEnC;;qBAcU,yBAAsB,iBAEhC;;;;;;qBAkIU,OAAI,sBACK,UACV,aAAW,0BACA"}
@@ -6,6 +6,24 @@ export declare const BROWSER_EXTENSION_OPTIONS: {
6
6
  label: string;
7
7
  hint: string;
8
8
  }[];
9
- export declare const initChromeExtension: () => Promise<void>;
9
+ /** Browsers the Intlayer extension is published for. */
10
+ export type ExtensionBrowser = 'chrome' | 'firefox';
11
+ /** Browsers accepted by `intlayer init extension --browser`. */
12
+ export declare const EXTENSION_BROWSERS: ExtensionBrowser[];
13
+ /** Store page of the Intlayer extension, per browser. */
14
+ export declare const EXTENSION_URL_BY_BROWSER: Record<ExtensionBrowser, string>;
15
+ /** Validates the `--browser` values, ignoring case. */
16
+ export declare const parseExtensionBrowsers: (values: string[]) => ExtensionBrowser[];
17
+ /** Options of {@link initChromeExtension}. */
18
+ export type InitChromeExtensionOptions = {
19
+ /** Browsers to open the store page for, skipping the prompt. */
20
+ browsers?: ExtensionBrowser[];
21
+ };
22
+ /**
23
+ * Opens the store page of the Intlayer browser extension. The browsers are
24
+ * prompted for unless given; without a terminal (AI agents, CI) the store
25
+ * links are only printed, since the install needs a person anyway.
26
+ */
27
+ export declare const initChromeExtension: (options?: InitChromeExtensionOptions) => Promise<void>;
10
28
  //#endregion
11
29
  //# sourceMappingURL=initChromeExtension.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initChromeExtension.d.ts","names":[],"sources":["../../src/initChromeExtension.ts"],"mappings":";qBAGa;qBAGA;qBAGA;;;;;qBAaA,2BAAmB"}
1
+ {"version":3,"file":"initChromeExtension.d.ts","names":[],"sources":["../../src/initChromeExtension.ts"],"mappings":";qBAKa;qBAGA;qBAGA;;;;;;YAcD;;qBAGC,oBAAoB;;qBAGpB,0BAA0B,OAAO;;qBAMjC,yBAAsB,qBAAuB;;YAO9C;;EAEV,WAAW;;;;;;;qBAQA,sBAAmB,UACrB,+BAA0B"}
@@ -1 +1 @@
1
- {"version":3,"file":"initInfra.d.ts","names":[],"sources":["../../src/initInfra.ts"],"mappings":";;qBAOa;YAED,oBAAoB;;;;;;qBAOnB;qBACA;YAED;;EAEV,OAAO;;EAEP;;;;;;;qBA4CW,iBAAc,kBAAoB;;;;;;;qBA8BlC,YAAS,UACX,qBACR"}
1
+ {"version":3,"file":"initInfra.d.ts","names":[],"sources":["../../src/initInfra.ts"],"mappings":";;qBAQa;YAED,oBAAoB;;;;;;qBAOnB;qBACA;YAED;;EAEV,OAAO;;EAEP;;;;;;;qBA4CW,iBAAc,kBAAoB;;;;;;;qBA8BlC,YAAS,UACX,qBACR"}
@@ -1,5 +1,19 @@
1
- import { Platform } from "@intlayer/engine/cli";
1
+ import { MCPTransport, Platform } from "@intlayer/engine/cli";
2
2
  //#region src/initMCP.d.ts
3
- export declare const initMCP: (projectRoot?: string, preselectedPlatform?: Platform) => Promise<void>;
3
+ /** Options of {@link initMCP}; anything omitted is prompted for. */
4
+ export type InitMCPOptions = {
5
+ /** AI platform to configure the MCP server for. */
6
+ platform?: Platform;
7
+ /** MCP transport. Defaults to `stdio` without a terminal. */
8
+ transport?: MCPTransport;
9
+ };
10
+ /** Validates a `--transport` value, ignoring case. */
11
+ export declare const parseMCPTransport: (value: string) => MCPTransport;
12
+ /**
13
+ * Configures the Intlayer MCP server for an AI platform. Without a terminal
14
+ * (AI agents, CI), nothing is prompted: the platform defaults to the detected
15
+ * one and the transport to `stdio`.
16
+ */
17
+ export declare const initMCP: (projectRoot?: string, options?: InitMCPOptions) => Promise<void>;
4
18
  //#endregion
5
19
  //# sourceMappingURL=initMCP.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initMCP.d.ts","names":[],"sources":["../../src/initMCP.ts"],"mappings":";;qBAUa,UAAO,sBACE,sBACE,aAAQ"}
1
+ {"version":3,"file":"initMCP.d.ts","names":[],"sources":["../../src/initMCP.ts"],"mappings":";;;YAaY;;EAEV,WAAW;;EAEX,YAAY;;;qBAID,oBAAiB,kBAAoB;;;;;;qBAQrC,UAAO,sBACE,UACX,mBAAc"}
@@ -1,21 +1,38 @@
1
- import { Platform } from "@intlayer/engine/cli";
1
+ import { Platform, Skill } from "@intlayer/engine/cli";
2
2
  //#region src/initSkills.d.ts
3
3
  export declare const PLATFORM_OPTIONS: Array<{
4
4
  value: Platform;
5
5
  label: string;
6
6
  hint: string;
7
7
  }>;
8
- export declare const getDetectedPlatform: () => Platform | undefined;
9
8
  /**
10
9
  * Asks which AI platform the user is using, preselecting the detected one.
11
10
  * Resolves to `undefined` when the prompt is cancelled.
12
11
  */
13
- export declare const promptPlatform: () => Promise<Platform | undefined>;
12
+ export declare const promptPlatform: (projectRoot: string) => Promise<Platform | undefined>;
13
+ /** Options of {@link initSkills}; anything omitted is prompted for. */
14
+ export type InitSkillsOptions = {
15
+ /** AI platform to install the skills for. */
16
+ platform?: Platform;
17
+ /** Skills to install. Defaults to the ones matching the project stack. */
18
+ skills?: Skill[];
19
+ };
20
+ /** Validates a `--platform` value, ignoring case. */
21
+ export declare const parsePlatform: (value: string) => Platform;
22
+ /** Validates the `--skills` values, ignoring case. */
23
+ export declare const parseSkills: (values: string[]) => Skill[];
24
+ /**
25
+ * Resolves the platform without prompting: the given one, else the detected
26
+ * one. Logs how to pass it and sets a failing exit code when neither exists.
27
+ */
28
+ export declare const resolvePlatformWithoutPrompt: (projectRoot: string, platform: Platform | undefined, command: string) => Promise<Platform | undefined>;
14
29
  /**
15
30
  * Installs the Intlayer documentation skills. The skills are picked first, then
16
- * the platform (unless preselected). Resolves to the platform used, so a
17
- * following step (e.g. MCP) can reuse it without asking again.
31
+ * the platform. Without a terminal (AI agents, CI), nothing is prompted: the
32
+ * skills default to the project stack and the platform to the detected one.
33
+ * Resolves to the platform used, so a following step (e.g. MCP) can reuse it
34
+ * without asking again.
18
35
  */
19
- export declare const initSkills: (projectRoot?: string, preselectedPlatform?: Platform) => Promise<Platform | undefined>;
36
+ export declare const initSkills: (projectRoot?: string, options?: InitSkillsOptions) => Promise<Platform | undefined>;
20
37
  //#endregion
21
38
  //# sourceMappingURL=initSkills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initSkills.d.ts","names":[],"sources":["../../src/initSkills.ts"],"mappings":";;qBAuBa,kBAAkB;EAC7B,OAAO;EACP;EACA;;qBAOW,2BAA0B;;;;;qBAqB1B,sBAA2B,QAAQ;;;;;;qBA8BnC,aAAU,sBACD,sBACE,aACrB,QAAQ"}
1
+ {"version":3,"file":"initSkills.d.ts","names":[],"sources":["../../src/initSkills.ts"],"mappings":";;qBAiBa,kBAAkB;EAC7B,OAAO;EACP;EACA;;;;;;qBAWW,iBAAc,wBAExB,QAAQ;;YA0BC;;EAEV,WAAW;;EAEX,SAAS;;;qBAIE,gBAAa,kBAAoB;;qBAIjC,cAAW,qBAAuB;;;;;qBAUlC,+BAA4B,qBACpB,UACT,sBAAoB,oBAE7B,QAAQ;;;;;;;;qBAsBE,aAAU,sBACD,UACX,sBACR,QAAQ"}
@@ -0,0 +1,9 @@
1
+ //#region src/utils/isInteractiveTerminal.d.ts
2
+ /**
3
+ * Whether the process can prompt: both stdin and stdout are attached to a
4
+ * terminal. False for AI agents, CI and piped runs, where a prompt would print
5
+ * and exit without an answer.
6
+ */
7
+ export declare const isInteractiveTerminal: () => boolean;
8
+ //#endregion
9
+ //# sourceMappingURL=isInteractiveTerminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInteractiveTerminal.d.ts","names":[],"sources":["../../../src/utils/isInteractiveTerminal.ts"],"mappings":";;;;;;qBAKa"}
@@ -0,0 +1,13 @@
1
+ //#region src/utils/parseChoice.d.ts
2
+ /**
3
+ * Resolves a command-line value against its allowed choices, ignoring case.
4
+ *
5
+ * @param value - Raw value passed on the command line.
6
+ * @param choices - Accepted values, in their canonical spelling.
7
+ * @param optionName - Option name used in the error message (e.g. `--platform`).
8
+ * @returns The matching choice, in its canonical spelling.
9
+ * @throws When the value matches none of the choices.
10
+ */
11
+ export declare const parseChoice: <Choice extends string>(value: string, choices: readonly Choice[], optionName: string) => Choice;
12
+ //#endregion
13
+ //# sourceMappingURL=parseChoice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseChoice.d.ts","names":[],"sources":["../../../src/utils/parseChoice.ts"],"mappings":";;;;;;;;;;qBASa,cAAe,uBAAqB,eAClC,kBACK,UAAQ,uBAEzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/cli",
3
- "version": "9.5.11",
3
+ "version": "9.6.0",
4
4
  "private": false,
5
5
  "description": "Provides uniform command-line interface scripts for Intlayer, used in packages like intlayer-cli and intlayer.",
6
6
  "keywords": [
@@ -38,6 +38,11 @@
38
38
  "require": "./dist/cjs/index.cjs",
39
39
  "import": "./dist/esm/index.mjs"
40
40
  },
41
+ "./cli": {
42
+ "types": "./dist/types/cli.d.ts",
43
+ "require": "./dist/cjs/cli.cjs",
44
+ "import": "./dist/esm/cli.mjs"
45
+ },
41
46
  "./package.json": "./package.json"
42
47
  },
43
48
  "main": "dist/cjs/index.cjs",
@@ -67,21 +72,21 @@
67
72
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
68
73
  },
69
74
  "dependencies": {
70
- "@clack/prompts": "1.7.0",
71
- "@intlayer/api": "9.5.11",
72
- "@intlayer/babel": "9.5.11",
73
- "@intlayer/config": "9.5.11",
74
- "@intlayer/core": "9.5.11",
75
- "@intlayer/dictionaries-entry": "9.5.11",
76
- "@intlayer/engine": "9.5.11",
77
- "@intlayer/types": "9.5.11",
75
+ "@clack/prompts": "1.8.1",
76
+ "@intlayer/api": "9.6.0",
77
+ "@intlayer/babel": "9.6.0",
78
+ "@intlayer/config": "9.6.0",
79
+ "@intlayer/core": "9.6.0",
80
+ "@intlayer/dictionaries-entry": "9.6.0",
81
+ "@intlayer/engine": "9.6.0",
82
+ "@intlayer/types": "9.6.0",
78
83
  "commander": "15.0.0",
79
84
  "enquirer": "2.4.1",
80
- "eventsource": "5.1.1",
85
+ "eventsource": "5.1.2",
81
86
  "fast-glob": "3.3.3"
82
87
  },
83
88
  "devDependencies": {
84
- "@intlayer/ai": "9.5.11",
89
+ "@intlayer/ai": "9.6.0",
85
90
  "@types/node": "^22",
86
91
  "@utils/ts-config": "1.0.4",
87
92
  "@utils/ts-config-types": "1.0.4",
@@ -89,10 +94,10 @@
89
94
  "rimraf": "6.1.3",
90
95
  "tsdown": "0.23.0",
91
96
  "typescript": "7.0.2",
92
- "vitest": "5.0.2"
97
+ "vitest": "5.0.3"
93
98
  },
94
99
  "peerDependencies": {
95
- "@intlayer/ai": "9.5.11"
100
+ "@intlayer/ai": "9.6.0"
96
101
  },
97
102
  "peerDependenciesMeta": {
98
103
  "@intlayer/ai": {