@intlayer/engine 9.0.0-canary.12 → 9.0.0-canary.13

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 (73) hide show
  1. package/dist/cjs/cli.cjs +1 -0
  2. package/dist/cjs/init/cms.cjs +18 -0
  3. package/dist/cjs/init/cms.cjs.map +1 -1
  4. package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs +2 -11
  5. package/dist/cjs/init/frameworkSetup/nextAppRouter/detect.cjs.map +1 -1
  6. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +2 -1
  7. package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
  8. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +2 -1
  9. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs.map +1 -1
  10. package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs +2 -1
  11. package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs.map +1 -1
  12. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +2 -1
  13. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
  14. package/dist/cjs/init/index.cjs +35 -11
  15. package/dist/cjs/init/index.cjs.map +1 -1
  16. package/dist/cjs/init/utils/configManipulation.cjs +43 -15
  17. package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
  18. package/dist/cjs/init/utils/index.cjs +3 -0
  19. package/dist/cjs/init/utils/version.cjs +17 -0
  20. package/dist/cjs/init/utils/version.cjs.map +1 -0
  21. package/dist/cjs/initConfig/index.cjs +6 -8
  22. package/dist/cjs/initConfig/index.cjs.map +1 -1
  23. package/dist/cjs/utils/recastBabelParser.cjs +67 -0
  24. package/dist/cjs/utils/recastBabelParser.cjs.map +1 -0
  25. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +2 -3
  26. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  27. package/dist/esm/cli.mjs +2 -2
  28. package/dist/esm/init/cms.mjs +19 -2
  29. package/dist/esm/init/cms.mjs.map +1 -1
  30. package/dist/esm/init/frameworkSetup/nextAppRouter/detect.mjs +1 -10
  31. package/dist/esm/init/frameworkSetup/nextAppRouter/detect.mjs.map +1 -1
  32. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +2 -1
  33. package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
  34. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +2 -2
  35. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs.map +1 -1
  36. package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs +2 -2
  37. package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs.map +1 -1
  38. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +2 -2
  39. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
  40. package/dist/esm/init/index.mjs +36 -13
  41. package/dist/esm/init/index.mjs.map +1 -1
  42. package/dist/esm/init/utils/configManipulation.mjs +43 -17
  43. package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
  44. package/dist/esm/init/utils/index.mjs +3 -2
  45. package/dist/esm/init/utils/version.mjs +15 -0
  46. package/dist/esm/init/utils/version.mjs.map +1 -0
  47. package/dist/esm/initConfig/index.mjs +6 -8
  48. package/dist/esm/initConfig/index.mjs.map +1 -1
  49. package/dist/esm/utils/recastBabelParser.mjs +64 -0
  50. package/dist/esm/utils/recastBabelParser.mjs.map +1 -0
  51. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +1 -1
  52. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  53. package/dist/types/cli.d.ts +2 -2
  54. package/dist/types/init/cms.d.ts +7 -1
  55. package/dist/types/init/cms.d.ts.map +1 -1
  56. package/dist/types/init/frameworkSetup/nextAppRouter/detect.d.ts +2 -5
  57. package/dist/types/init/frameworkSetup/nextAppRouter/detect.d.ts.map +1 -1
  58. package/dist/types/init/frameworkSetup/nextAppRouter/restructure.d.ts.map +1 -1
  59. package/dist/types/init/frameworkSetup/nextAppRouter/transforms.d.ts.map +1 -1
  60. package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
  61. package/dist/types/init/index.d.ts +25 -1
  62. package/dist/types/init/index.d.ts.map +1 -1
  63. package/dist/types/init/utils/configManipulation.d.ts +10 -1
  64. package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
  65. package/dist/types/init/utils/index.d.ts +3 -2
  66. package/dist/types/init/utils/version.d.ts +9 -0
  67. package/dist/types/init/utils/version.d.ts.map +1 -0
  68. package/dist/types/initConfig/index.d.ts +13 -3
  69. package/dist/types/initConfig/index.d.ts.map +1 -1
  70. package/dist/types/utils/recastBabelParser.d.ts +12 -0
  71. package/dist/types/utils/recastBabelParser.d.ts.map +1 -0
  72. package/package.json +11 -10
  73. package/dist/esm/_virtual/_rolldown/runtime.mjs +0 -8
@@ -1 +1 @@
1
- {"version":3,"file":"transforms.mjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/transforms.ts"],"sourcesContent":["import * as recast from 'recast';\nimport { ensureNamedImport } from '../../utils/astImports';\n\nconst { builders: b, namedTypes: n } = recast.types;\n\n/** babel-ts parser handles TypeScript *and* JSX. */\nconst parseTsx = (code: string): any =>\n recast.parse(code, { parser: require('recast/parsers/babel-ts') });\n\n/** Result of a source transform. `code` is unchanged for any non-`wrapped` status. */\nexport type TransformResult = {\n code: string;\n status: 'wrapped' | 'already' | 'skipped';\n};\n\n/**\n * Finds the single function that returns the `<html>` document element. Returns\n * `null` when there is no such function, or more than one (ambiguous).\n */\nconst findHtmlDocumentFunction = (ast: any): any => {\n const found = new Set<any>();\n\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type === 'JSXIdentifier' && node.name.name === 'html') {\n // Walk up to the nearest enclosing function node.\n let current = path.parentPath;\n while (current) {\n const value = current.value;\n if (\n value &&\n (n.FunctionDeclaration.check(value) ||\n n.FunctionExpression.check(value) ||\n n.ArrowFunctionExpression.check(value))\n ) {\n found.add(value);\n break;\n }\n current = current.parentPath;\n }\n }\n this.traverse(path);\n },\n });\n\n return found.size === 1 ? [...found][0] : null;\n};\n\n/**\n * Whether the binding pattern `node` introduces a variable named `name`.\n * Recurses through destructuring patterns so all of `const locale`,\n * `const { locale } = …`, `const { locale = fallback } = …`,\n * `const { foo: locale } = …`, `const [locale] = …` and `...locale` are\n * detected — not just a bare identifier.\n */\nconst patternBindsName = (node: any, name: string): boolean => {\n if (!node) return false;\n switch (node.type) {\n case 'Identifier':\n return node.name === name;\n case 'AssignmentPattern':\n // `locale = fallback`\n return patternBindsName(node.left, name);\n case 'RestElement':\n // `...locale`\n return patternBindsName(node.argument, name);\n case 'ArrayPattern':\n return node.elements.some((element: any) =>\n patternBindsName(element, name)\n );\n case 'ObjectPattern':\n return node.properties.some((property: any) =>\n property.type === 'RestElement'\n ? patternBindsName(property.argument, name)\n : // The *value* is the binding target (`{ foo: locale }` binds `locale`).\n patternBindsName(property.value, name)\n );\n default:\n return false;\n }\n};\n\n/**\n * Inserts `const locale = …` once, at the top of the function body. A single\n * self-contained statement is used (rather than an intermediate `params` const)\n * so it can never collide with a `params` variable the document already\n * declares. Expression-bodied arrow functions are first converted to a block so\n * the declaration has somewhere to live.\n *\n * No-ops when `locale` is already bound in the function — whether as a simple\n * identifier, through a destructuring pattern (e.g.\n * `const { locale = defaultLocale } = useLoaderData()`), or as a function\n * parameter — so the injected declaration never collides with one the document\n * already provides (which would produce an\n * `Identifier 'locale' has already been declared` parse error).\n */\nconst ensureLocaleFromParams = (funcNode: any): void => {\n if (funcNode.body?.type !== 'BlockStatement') {\n funcNode.body = b.blockStatement([b.returnStatement(funcNode.body)]);\n }\n\n const declaredInBody = funcNode.body.body.some(\n (stmt: any) =>\n stmt.type === 'VariableDeclaration' &&\n stmt.declarations.some((d: any) => patternBindsName(d.id, 'locale'))\n );\n const declaredInParams = (funcNode.params ?? []).some((param: any) =>\n patternBindsName(param, 'locale')\n );\n if (declaredInBody || declaredInParams) return;\n\n const statement = parseTsx(\n 'const locale = useParams({ strict: false }).locale ?? defaultLocale;'\n ).program.body[0];\n funcNode.body.body.unshift(statement);\n};\n\n/** Sets `lang={locale}` and `dir={getHTMLTextDir(locale)}` on the first `<html>` element. */\nconst setHtmlLangAndDir = (ast: any): void => {\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type !== 'JSXIdentifier' || node.name.name !== 'html') {\n this.traverse(path);\n return;\n }\n\n const upsertAttribute = (name: string, value: any): void => {\n const existing = node.attributes?.find(\n (attr: any) =>\n attr.type === 'JSXAttribute' && attr.name?.name === name\n ) as any;\n if (existing) {\n existing.value = value;\n } else {\n node.attributes.push(b.jsxAttribute(b.jsxIdentifier(name), value));\n }\n };\n\n upsertAttribute('lang', b.jsxExpressionContainer(b.identifier('locale')));\n upsertAttribute(\n 'dir',\n b.jsxExpressionContainer(\n b.callExpression(b.identifier('getHTMLTextDir'), [\n b.identifier('locale'),\n ])\n )\n );\n return false;\n },\n });\n};\n\n/**\n * Wraps the `{children}` of a TanStack Start root document with\n * `IntlayerProvider`, deriving the locale from the `{-$locale}` route param.\n * Safe and idempotent: bails (returns the original code) when the provider is\n * already present, when no `<html>` document function is found, or when there is\n * no `{children}` placeholder to wrap.\n */\nexport const wrapRootWithProvider = (code: string): TransformResult => {\n const ast = parseTsx(code);\n\n if (code.includes('IntlayerProvider')) return { code, status: 'already' };\n\n const funcNode = findHtmlDocumentFunction(ast);\n if (!funcNode) return { code, status: 'skipped' };\n\n let wrapped = false;\n recast.visit(funcNode, {\n visitJSXExpressionContainer(path) {\n if (wrapped) return false;\n const expression = path.node.expression;\n if (expression?.type === 'Identifier' && expression.name === 'children') {\n const template = parseTsx(\n 'const __wrap = <IntlayerProvider locale={locale}>{__child__}</IntlayerProvider>;'\n );\n const providerElement = template.program.body[0].declarations[0].init;\n providerElement.children = [path.node];\n path.replace(providerElement);\n wrapped = true;\n return false;\n }\n this.traverse(path);\n },\n });\n\n if (!wrapped) return { code, status: 'skipped' };\n\n ensureNamedImport(ast, 'IntlayerProvider', 'react-intlayer');\n ensureNamedImport(ast, 'useParams', '@tanstack/react-router');\n ensureNamedImport(ast, 'defaultLocale', 'intlayer');\n ensureNamedImport(ast, 'getHTMLTextDir', 'intlayer');\n ensureLocaleFromParams(funcNode);\n setHtmlLangAndDir(ast);\n\n return { code: recast.print(ast).code, status: 'wrapped' };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"transforms.mjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/transforms.ts"],"sourcesContent":["import * as recast from 'recast';\nimport { babelTsParser } from '../../../utils/recastBabelParser';\nimport { ensureNamedImport } from '../../utils/astImports';\n\nconst { builders: b, namedTypes: n } = recast.types;\n\n/** babel-ts parser handles TypeScript *and* JSX. */\nconst parseTsx = (code: string): any =>\n recast.parse(code, { parser: babelTsParser });\n\n/** Result of a source transform. `code` is unchanged for any non-`wrapped` status. */\nexport type TransformResult = {\n code: string;\n status: 'wrapped' | 'already' | 'skipped';\n};\n\n/**\n * Finds the single function that returns the `<html>` document element. Returns\n * `null` when there is no such function, or more than one (ambiguous).\n */\nconst findHtmlDocumentFunction = (ast: any): any => {\n const found = new Set<any>();\n\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type === 'JSXIdentifier' && node.name.name === 'html') {\n // Walk up to the nearest enclosing function node.\n let current = path.parentPath;\n while (current) {\n const value = current.value;\n if (\n value &&\n (n.FunctionDeclaration.check(value) ||\n n.FunctionExpression.check(value) ||\n n.ArrowFunctionExpression.check(value))\n ) {\n found.add(value);\n break;\n }\n current = current.parentPath;\n }\n }\n this.traverse(path);\n },\n });\n\n return found.size === 1 ? [...found][0] : null;\n};\n\n/**\n * Whether the binding pattern `node` introduces a variable named `name`.\n * Recurses through destructuring patterns so all of `const locale`,\n * `const { locale } = …`, `const { locale = fallback } = …`,\n * `const { foo: locale } = …`, `const [locale] = …` and `...locale` are\n * detected — not just a bare identifier.\n */\nconst patternBindsName = (node: any, name: string): boolean => {\n if (!node) return false;\n switch (node.type) {\n case 'Identifier':\n return node.name === name;\n case 'AssignmentPattern':\n // `locale = fallback`\n return patternBindsName(node.left, name);\n case 'RestElement':\n // `...locale`\n return patternBindsName(node.argument, name);\n case 'ArrayPattern':\n return node.elements.some((element: any) =>\n patternBindsName(element, name)\n );\n case 'ObjectPattern':\n return node.properties.some((property: any) =>\n property.type === 'RestElement'\n ? patternBindsName(property.argument, name)\n : // The *value* is the binding target (`{ foo: locale }` binds `locale`).\n patternBindsName(property.value, name)\n );\n default:\n return false;\n }\n};\n\n/**\n * Inserts `const locale = …` once, at the top of the function body. A single\n * self-contained statement is used (rather than an intermediate `params` const)\n * so it can never collide with a `params` variable the document already\n * declares. Expression-bodied arrow functions are first converted to a block so\n * the declaration has somewhere to live.\n *\n * No-ops when `locale` is already bound in the function — whether as a simple\n * identifier, through a destructuring pattern (e.g.\n * `const { locale = defaultLocale } = useLoaderData()`), or as a function\n * parameter — so the injected declaration never collides with one the document\n * already provides (which would produce an\n * `Identifier 'locale' has already been declared` parse error).\n */\nconst ensureLocaleFromParams = (funcNode: any): void => {\n if (funcNode.body?.type !== 'BlockStatement') {\n funcNode.body = b.blockStatement([b.returnStatement(funcNode.body)]);\n }\n\n const declaredInBody = funcNode.body.body.some(\n (stmt: any) =>\n stmt.type === 'VariableDeclaration' &&\n stmt.declarations.some((d: any) => patternBindsName(d.id, 'locale'))\n );\n const declaredInParams = (funcNode.params ?? []).some((param: any) =>\n patternBindsName(param, 'locale')\n );\n if (declaredInBody || declaredInParams) return;\n\n const statement = parseTsx(\n 'const locale = useParams({ strict: false }).locale ?? defaultLocale;'\n ).program.body[0];\n funcNode.body.body.unshift(statement);\n};\n\n/** Sets `lang={locale}` and `dir={getHTMLTextDir(locale)}` on the first `<html>` element. */\nconst setHtmlLangAndDir = (ast: any): void => {\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type !== 'JSXIdentifier' || node.name.name !== 'html') {\n this.traverse(path);\n return;\n }\n\n const upsertAttribute = (name: string, value: any): void => {\n const existing = node.attributes?.find(\n (attr: any) =>\n attr.type === 'JSXAttribute' && attr.name?.name === name\n ) as any;\n if (existing) {\n existing.value = value;\n } else {\n node.attributes.push(b.jsxAttribute(b.jsxIdentifier(name), value));\n }\n };\n\n upsertAttribute('lang', b.jsxExpressionContainer(b.identifier('locale')));\n upsertAttribute(\n 'dir',\n b.jsxExpressionContainer(\n b.callExpression(b.identifier('getHTMLTextDir'), [\n b.identifier('locale'),\n ])\n )\n );\n return false;\n },\n });\n};\n\n/**\n * Wraps the `{children}` of a TanStack Start root document with\n * `IntlayerProvider`, deriving the locale from the `{-$locale}` route param.\n * Safe and idempotent: bails (returns the original code) when the provider is\n * already present, when no `<html>` document function is found, or when there is\n * no `{children}` placeholder to wrap.\n */\nexport const wrapRootWithProvider = (code: string): TransformResult => {\n const ast = parseTsx(code);\n\n if (code.includes('IntlayerProvider')) return { code, status: 'already' };\n\n const funcNode = findHtmlDocumentFunction(ast);\n if (!funcNode) return { code, status: 'skipped' };\n\n let wrapped = false;\n recast.visit(funcNode, {\n visitJSXExpressionContainer(path) {\n if (wrapped) return false;\n const expression = path.node.expression;\n if (expression?.type === 'Identifier' && expression.name === 'children') {\n const template = parseTsx(\n 'const __wrap = <IntlayerProvider locale={locale}>{__child__}</IntlayerProvider>;'\n );\n const providerElement = template.program.body[0].declarations[0].init;\n providerElement.children = [path.node];\n path.replace(providerElement);\n wrapped = true;\n return false;\n }\n this.traverse(path);\n },\n });\n\n if (!wrapped) return { code, status: 'skipped' };\n\n ensureNamedImport(ast, 'IntlayerProvider', 'react-intlayer');\n ensureNamedImport(ast, 'useParams', '@tanstack/react-router');\n ensureNamedImport(ast, 'defaultLocale', 'intlayer');\n ensureNamedImport(ast, 'getHTMLTextDir', 'intlayer');\n ensureLocaleFromParams(funcNode);\n setHtmlLangAndDir(ast);\n\n return { code: recast.print(ast).code, status: 'wrapped' };\n};\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { getMetroConfigTemplate, replaceViteConfigPluginImportSource, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin } from "./utils/configManipulation.mjs";
2
2
  import { detectJsonLocalePattern, detectLinguiCatalogPattern, detectNextIntlMessagesPattern, ensureDirectory, exists, readFileFromRoot, writeFileToRoot } from "./utils/fileSystem.mjs";
3
- import { setRoutingModeInConfig } from "./cms.mjs";
3
+ import { setCompilerOutputInConfig, setRoutingModeInConfig } from "./cms.mjs";
4
4
  import { initConfig } from "../initConfig/index.mjs";
5
+ import { isVersionAtLeast } from "./utils/version.mjs";
5
6
  import { setupFramework } from "./frameworkSetup/index.mjs";
6
7
  import { getGithubWorkflows } from "./utils/githubActions.mjs";
7
8
  import { parseJSONWithComments } from "./utils/jsonParser.mjs";
@@ -101,6 +102,22 @@ const getDocumentationUrl = (packageJson) => {
101
102
  return DocumentationRouter.Default;
102
103
  };
103
104
  /**
105
+ * Resolves the default dev-server URL of the detected framework, used as the
106
+ * `editor.applicationURL` of the generated configuration file. Frameworks that
107
+ * embed Vite (Astro, SvelteKit, …) are checked before the bare Vite fallback so
108
+ * their own dev port wins.
109
+ */
110
+ const getDefaultApplicationURL = (dependencies) => {
111
+ if (dependencies.next) return "http://localhost:3000";
112
+ if (dependencies.astro) return "http://localhost:4321";
113
+ if (dependencies["@angular/core"]) return "http://localhost:4200";
114
+ if (dependencies.nuxt) return "http://localhost:3000";
115
+ if (dependencies["@sveltejs/kit"]) return "http://localhost:5173";
116
+ if (dependencies["react-scripts"]) return "http://localhost:3000";
117
+ if (dependencies.vite) return "http://localhost:5173";
118
+ return "http://localhost:3000";
119
+ };
120
+ /**
104
121
  * MAIN LOGIC
105
122
  */
106
123
  const initIntlayer = async (rootDir, options) => {
@@ -132,6 +149,8 @@ const initIntlayer = async (rootDir, options) => {
132
149
  const linguiCatalog = linguiPresent ? await detectLinguiCatalogPattern(rootDir) : null;
133
150
  const hintLinguiJson = Boolean(options?.hintDependencies?.["__lingui_json__"]);
134
151
  const { packagesToInstall, devPackagesToInstall, compatSyncConfig, compatVitePluginConfig } = detectMissingIntlayerPackages(effectiveAllDeps, { linguiCatalogFormat: linguiCatalog?.format ?? (linguiPresent ? hintLinguiJson ? "json" : "po" : null) });
152
+ const wantsJsonNamespaces = options?.contentStrategy === "json-namespaces" && !compatSyncConfig;
153
+ if (wantsJsonNamespaces && !effectiveAllDeps["@intlayer/sync-json-plugin"] && !devPackagesToInstall.includes("@intlayer/sync-json-plugin")) devPackagesToInstall.push("@intlayer/sync-json-plugin");
135
154
  if (!options?.noInstallPackages) {
136
155
  const withVersion = (packages) => options?.upgradeToVersion ? packages.map((pkg) => `${pkg}@${options.upgradeToVersion}`) : packages;
137
156
  if (packagesToInstall.length > 0) {
@@ -251,12 +270,20 @@ const initIntlayer = async (rootDir, options) => {
251
270
  }
252
271
  const format = hasTsConfig ? "intlayer.config.ts" : "intlayer.config.mjs";
253
272
  const detectedPattern = await detectJsonLocalePattern(rootDir);
254
- await initConfig(format, rootDir, detectedPattern?.locales);
255
- if (compatSyncConfig) {
273
+ await initConfig(format, rootDir, {
274
+ locales: detectedPattern?.locales,
275
+ applicationURL: getDefaultApplicationURL(allDeps)
276
+ });
277
+ if (options?.contentStrategy === "centralized") await setCompilerOutputInConfig(rootDir, "/locales/{{locale}}/{{key}}.content.json");
278
+ const syncConfigToInject = compatSyncConfig ?? (wantsJsonNamespaces ? {
279
+ format: "i18next",
280
+ sourceTemplate: detectedPattern?.template ?? "./locales/${locale}/${key}.json"
281
+ } : void 0);
282
+ if (syncConfigToInject) {
256
283
  const nextIntlMessagesPattern = allDeps["next-intl"] || allDeps["@intlayer/next-intl"] || allDeps["use-intl"] || allDeps["@intlayer/use-intl"] ? await detectNextIntlMessagesPattern(rootDir) : null;
257
284
  const sourceTemplate = linguiCatalog?.template ?? nextIntlMessagesPattern?.template ?? detectedPattern?.template;
258
285
  const resolvedSyncConfig = {
259
- ...compatSyncConfig,
286
+ ...syncConfigToInject,
260
287
  ...sourceTemplate ? { sourceTemplate } : {}
261
288
  };
262
289
  const syncPluginPackage = resolvedSyncConfig.plugin === "po" ? "@intlayer/sync-po-plugin" : "@intlayer/sync-json-plugin";
@@ -395,12 +422,6 @@ const initIntlayer = async (rootDir, options) => {
395
422
  logger(`${v} Created ${colorizePath(newMetroConfigFile)} with the Intlayer Metro plugin`);
396
423
  }
397
424
  }
398
- const isVersionGreaterOrEqual = (versionString, major) => {
399
- if (!versionString || typeof versionString !== "string") return false;
400
- const match = versionString.match(/^[^\d]*(\d+)/);
401
- if (!match?.[1]) return false;
402
- return parseInt(match[1], 10) >= major;
403
- };
404
425
  const backendIntlayerPackages = [
405
426
  "express-intlayer",
406
427
  "fastify-intlayer",
@@ -409,7 +430,7 @@ const initIntlayer = async (rootDir, options) => {
409
430
  ];
410
431
  const devScript = packageJson.scripts?.dev;
411
432
  let newDevScript;
412
- if ((isNextJsProject && allDeps.next && isVersionGreaterOrEqual(allDeps.next, 16) || backendIntlayerPackages.some((pkg) => allDeps[pkg])) && !devScript.includes("intlayer watch")) newDevScript = `intlayer watch --with '${devScript}'`;
433
+ if (devScript && (isNextJsProject && allDeps.next && isVersionAtLeast(allDeps.next, 16) || backendIntlayerPackages.some((pkg) => allDeps[pkg])) && !devScript.includes("intlayer watch")) newDevScript = `intlayer watch --with '${devScript}'`;
413
434
  if (newDevScript) {
414
435
  packageJson.scripts.dev = newDevScript;
415
436
  await writeFileToRoot(rootDir, packageJsonPath, JSON.stringify(packageJson, null, 2));
@@ -487,7 +508,9 @@ const initIntlayer = async (rootDir, options) => {
487
508
  }
488
509
  }
489
510
  }
490
- if (!options?.noFrameworkSetup) try {
511
+ const hasCompatLibrary = Boolean(compatSyncConfig || compatVitePluginConfig);
512
+ if (!options?.noFrameworkSetup && hasCompatLibrary) logger(`${v} Compat i18n library detected — keeping the app structure untouched (no route restructure, no provider injection)`);
513
+ if (!options?.noFrameworkSetup && !hasCompatLibrary) try {
491
514
  const routingMode = options?.routingMode ?? getConfiguration({ baseDir: rootDir }).routing.mode;
492
515
  await setupFramework({
493
516
  rootDir,
@@ -514,5 +537,5 @@ const initIntlayer = async (rootDir, options) => {
514
537
  };
515
538
 
516
539
  //#endregion
517
- export { initIntlayer };
540
+ export { getDefaultApplicationURL, initIntlayer };
518
541
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/init/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\nimport { initConfig } from '../initConfig';\nimport { setRoutingModeInConfig } from './cms';\nimport { setupFramework } from './frameworkSetup';\nimport type { RoutingMode } from './utils';\nimport {\n detectJsonLocalePattern,\n detectLinguiCatalogPattern,\n detectMissingIntlayerPackages,\n detectNextIntlMessagesPattern,\n detectOutdatedIntlayerPackages,\n detectPackageManager,\n ensureDirectory,\n exists,\n findTsConfigFiles,\n getGithubWorkflows,\n getMetroConfigTemplate,\n installPackages,\n parseJSONWithComments,\n readFileFromRoot,\n replaceViteConfigPluginImportSource,\n setupNextCompilerBabelConfig,\n updateAstroConfig,\n updateIntlayerConfigWithSyncPlugin,\n updateMetroConfig,\n updateNextConfig,\n updateNextConfigForNextI18next,\n updateNextConfigForNextIntl,\n updateNextConfigForNextTranslate,\n updateNuxtConfig,\n updateNuxtConfigForNuxtjsI18n,\n updateViteConfig,\n updateViteConfigForCompatPlugin,\n upgradePackages,\n writeFileToRoot,\n} from './utils';\n\n/**\n * Documentation URL Constants\n */\nconst DocumentationRouter = {\n NextJS: 'https://intlayer.org/doc/environment/nextjs.md',\n NextJS_15: 'https://intlayer.org/doc/environment/nextjs/15.md',\n NextJS_14: 'https://intlayer.org/doc/environment/nextjs/14.md',\n CRA: 'https://intlayer.org/doc/environment/create-react-app.md',\n Astro: 'https://intlayer.org/doc/environment/astro.md',\n ViteAndReact: 'https://intlayer.org/doc/environment/vite-and-react.md',\n ViteAndReact_ReactRouterV7:\n 'https://intlayer.org/doc/environment/vite-and-react/react-router-v7.md',\n ViteAndReact_ReactRouterV7_FSRoutes:\n 'https://intlayer.org/doc/environment/vite-and-react/react-router-v7-fs-routes.md',\n ViteAndVue: 'https://intlayer.org/doc/environment/vite-and-vue.md',\n ViteAndSolid: 'https://intlayer.org/doc/environment/vite-and-solid.md',\n ViteAndSvelte: 'https://intlayer.org/doc/environment/vite-and-svelte.md',\n ViteAndPreact: 'https://intlayer.org/doc/environment/vite-and-preact.md',\n TanStackRouter: 'https://intlayer.org/doc/environment/tanstack.md',\n NuxtAndVue: 'https://intlayer.org/doc/environment/nuxt-and-vue.md',\n Angular: 'https://intlayer.org/doc/environment/angular.md',\n SvelteKit: 'https://intlayer.org/doc/environment/sveltekit.md',\n ReactNativeAndExpo:\n 'https://intlayer.org/doc/environment/react-native-and-expo.md',\n Lynx: 'https://intlayer.org/doc/environment/lynx-and-react.md',\n Express: 'https://intlayer.org/doc/environment/express.md',\n NestJS: 'https://intlayer.org/doc/environment/nestjs.md',\n Fastify: 'https://intlayer.org/doc/environment/fastify.md',\n Default: 'https://intlayer.org/doc/get-started',\n\n // Intlayer Language Server (Go-to-Definition from getter keys to .content files)\n LSP: 'https://intlayer.org/doc/lsp.md',\n\n // Check for competitors libs\n NextIntl: 'https://intlayer.org/blog/intlayer-with-next-intl.md',\n ReactI18Next: 'https://intlayer.org/blog/intlayer-with-react-i18next.md',\n ReactIntl: 'https://intlayer.org/blog/intlayer-with-react-intl.md',\n NextI18Next: 'https://intlayer.org/blog/intlayer-with-next-i18next.md',\n VueI18n: 'https://intlayer.org/blog/intlayer-with-vue-i18n.md',\n};\n\n/**\n * Helper: Detects the environment and returns the doc URL\n */\nconst getDocumentationUrl = (packageJson: any): string => {\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n /**\n * Helper to check if a version string matches a specific major version\n * Matches: \"15\", \"^15.0.0\", \"~15.2\", \"15.0.0-beta\"\n */\n const isVersion = (versionString: string, major: number): boolean => {\n if (!versionString || typeof versionString !== 'string') return false;\n const regex = new RegExp(`^[\\\\^~]?${major}(?:\\\\.|$)`);\n return regex.test(versionString);\n };\n\n // Mobile / Cross-platform\n if (deps['@lynx-js/react'] || deps['@lynx-js/core']) {\n return DocumentationRouter.Lynx;\n }\n if (deps['react-native'] || deps.expo) {\n return DocumentationRouter.ReactNativeAndExpo;\n }\n\n // Meta-frameworks (Next, Nuxt, Astro, SvelteKit)\n if (deps.next) {\n const version = deps.next;\n\n if (isVersion(version, 14)) {\n return DocumentationRouter.NextJS_14;\n }\n\n if (isVersion(version, 15)) {\n return DocumentationRouter.NextJS_15;\n }\n\n return DocumentationRouter.NextJS;\n }\n\n if (deps.nuxt) return DocumentationRouter.NuxtAndVue;\n if (deps.astro) return DocumentationRouter.Astro;\n if (deps['@sveltejs/kit']) return DocumentationRouter.SvelteKit;\n\n // Routers (TanStack & React Router v7)\n if (deps['@tanstack/react-router']) {\n return DocumentationRouter.TanStackRouter;\n }\n\n // Check for React Router v7\n const reactRouterVersion = deps['react-router'];\n if (reactRouterVersion && typeof reactRouterVersion === 'string') {\n // Distinguish between standard v7 and v7 with FS routes\n if (deps['@react-router/fs-routes']) {\n return DocumentationRouter.ViteAndReact_ReactRouterV7_FSRoutes;\n }\n\n // Use Regex to ensure it is v7\n if (isVersion(reactRouterVersion, 7)) {\n return DocumentationRouter.ViteAndReact_ReactRouterV7;\n }\n }\n\n // Vite Ecosystem (General)\n if (deps.vite) {\n if (deps.vue) return DocumentationRouter.ViteAndVue;\n if (deps['solid-js']) return DocumentationRouter.ViteAndSolid;\n if (deps.svelte) return DocumentationRouter.ViteAndSvelte;\n if (deps.preact) return DocumentationRouter.ViteAndPreact;\n\n // Default to React if Vite is present but specific other frameworks aren't found\n return DocumentationRouter.ViteAndReact;\n }\n\n // Other Web Frameworks\n if (deps['react-scripts']) return DocumentationRouter.CRA;\n if (deps['@angular/core']) return DocumentationRouter.Angular;\n\n // Backend\n if (deps['@nestjs/core']) return DocumentationRouter.NestJS;\n if (deps.express) return DocumentationRouter.Express;\n if (deps.fastify) return DocumentationRouter.Fastify;\n\n // Competitor Libs (Migration Guides)\n // We check these last as specific environment setup is usually higher priority,\n // but if no specific framework logic matched (or as a fallback), we guide to migration.\n if (deps['next-intl']) return DocumentationRouter.NextIntl;\n if (deps['react-i18next'] || deps.i18next)\n return DocumentationRouter.ReactI18Next;\n if (deps['react-intl']) return DocumentationRouter.ReactIntl;\n if (deps['next-i18next']) return DocumentationRouter.NextI18Next;\n if (deps['vue-i18n']) return DocumentationRouter.VueI18n;\n\n return DocumentationRouter.Default;\n};\n\n/**\n * OPTIONS\n */\nexport type InitOptions = {\n noGitignore?: boolean;\n /** Skip scaffolding the `fill` and `test` GitHub Actions workflows. */\n noGithubActions?: boolean;\n /**\n * Skip installing missing Intlayer dependencies and upgrading outdated ones.\n */\n noInstallPackages?: boolean;\n /** Skip adding the Intlayer extension to `.vscode/extensions.json`. */\n noVscodeExtension?: boolean;\n /** Skip writing the Intlayer LSP configuration to `.vscode/settings.json`. */\n noLsp?: boolean;\n /**\n * Skip framework-specific scaffolding (middleware/proxy, providers in\n * layout/page, example content). Defaults to enabled.\n */\n noFrameworkSetup?: boolean;\n /**\n * Version that outdated Intlayer packages should be upgraded to (typically the\n * running CLI version). When omitted, installed packages are left untouched and\n * only missing ones are installed.\n */\n upgradeToVersion?: string;\n /**\n * Locale routing strategy to write to `routing.mode` in the generated/existing\n * Intlayer configuration file. When omitted, the configuration default\n * (`prefix-no-default`) is kept.\n */\n routingMode?: RoutingMode;\n /**\n * Extra packages hinted by the interactive init prompt (compat i18n library\n * selections made before those libraries are actually installed). These are\n * merged into the dependency map used by {@link detectMissingIntlayerPackages}\n * so the correct sync plugin and compat adapter are always scheduled.\n */\n hintDependencies?: Record<string, string>;\n};\n\n/**\n * MAIN LOGIC\n */\nexport const initIntlayer = async (rootDir: string, options?: InitOptions) => {\n logger(colorize('Checking Intlayer configuration...', ANSIColors.CYAN));\n\n // READ PACKAGE.JSON\n const packageJsonPath = 'package.json';\n if (!(await exists(rootDir, packageJsonPath))) {\n logger(\n `${x} No ${colorizePath('package.json')} found. Please run this script from the project root.`,\n { level: 'error' }\n );\n process.exit(1);\n }\n\n const packageJsonContent = await readFileFromRoot(rootDir, packageJsonPath);\n let packageJson: Record<string, any>;\n try {\n packageJson = JSON.parse(packageJsonContent);\n } catch {\n logger(`${x} Could not parse ${colorizePath('package.json')}.`, {\n level: 'error',\n });\n process.exit(1);\n }\n\n // Determine the correct documentation URL based on dependencies\n const guideUrl = getDocumentationUrl(packageJson);\n\n const allDeps: Record<string, string> = {\n ...(packageJson.dependencies ?? {}),\n ...(packageJson.devDependencies ?? {}),\n };\n\n // Effective deps = real deps + interactive hint-deps (compat library selections\n // from the interactive init prompt that haven't been installed yet).\n const effectiveAllDeps: Record<string, string> = {\n ...allDeps,\n ...(options?.hintDependencies ?? {}),\n };\n\n // INSTALL MISSING INTLAYER DEPENDENCIES\n const packageManager = detectPackageManager(rootDir);\n\n // lingui keeps its catalogs as `.po` (default) or `.json`. Detect which so the\n // matching sync plugin (`syncPO` / `syncJSON`) + dev dependency are chosen.\n // Also respect the `__lingui_json__` sentinel injected by the interactive init\n // prompt when the user explicitly selected \"Lingui (.json catalogs)\".\n const linguiPresent = Boolean(\n effectiveAllDeps['@lingui/core'] ||\n effectiveAllDeps['@lingui/react'] ||\n effectiveAllDeps['@intlayer/lingui']\n );\n\n // Determine format: prefer filesystem scan, then the interactive sentinel.\n const linguiCatalog = linguiPresent\n ? await detectLinguiCatalogPattern(rootDir)\n : null;\n\n const hintLinguiJson = Boolean(\n options?.hintDependencies?.['__lingui_json__']\n );\n // `linguiCatalogFormat` resolution:\n // 1. Filesystem scan result (authoritative when catalogs already exist)\n // 2. Interactive sentinel `__lingui_json__` → 'json'\n // 3. Fallback: 'po' (lingui's default) when lingui is selected but no\n // catalogs have been generated yet and no sentinel was injected.\n const linguiCatalogFormat: 'po' | 'json' | null =\n linguiCatalog?.format ??\n (linguiPresent ? (hintLinguiJson ? 'json' : 'po') : null);\n\n const {\n packagesToInstall,\n devPackagesToInstall,\n compatSyncConfig,\n compatVitePluginConfig,\n } = detectMissingIntlayerPackages(effectiveAllDeps, {\n linguiCatalogFormat,\n });\n\n if (!options?.noInstallPackages) {\n const withVersion = (packages: string[]): string[] =>\n options?.upgradeToVersion\n ? packages.map((pkg) => `${pkg}@${options.upgradeToVersion}`)\n : packages;\n\n if (packagesToInstall.length > 0) {\n logger(\n colorize('Installing missing Intlayer dependencies...', ANSIColors.CYAN)\n );\n try {\n installPackages(\n rootDir,\n withVersion(packagesToInstall),\n packageManager\n );\n logger(\n `${v} Installed: ${packagesToInstall.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to install packages. Please install manually: ${packagesToInstall.join(' ')}`,\n { level: 'warn' }\n );\n }\n }\n\n if (devPackagesToInstall.length > 0) {\n logger(\n colorize(\n 'Installing missing Intlayer dev dependencies...',\n ANSIColors.CYAN\n )\n );\n try {\n installPackages(\n rootDir,\n withVersion(devPackagesToInstall),\n packageManager,\n true\n );\n logger(\n `${v} Installed: ${devPackagesToInstall.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to install dev packages. Please install manually: ${devPackagesToInstall.join(' ')}`,\n { level: 'warn' }\n );\n }\n }\n\n // UPGRADE OUTDATED INTLAYER DEPENDENCIES\n // Only runs when a target version is provided (typically the running CLI\n // version). Already up-to-date packages are skipped. Prod and dev\n // dependencies are upgraded separately so their dependency type is kept.\n if (options?.upgradeToVersion) {\n const outdatedDependencies = detectOutdatedIntlayerPackages(\n rootDir,\n packageJson.dependencies ?? {},\n options.upgradeToVersion\n );\n const outdatedDevDependencies = detectOutdatedIntlayerPackages(\n rootDir,\n packageJson.devDependencies ?? {},\n options.upgradeToVersion\n );\n\n const allOutdated = [...outdatedDependencies, ...outdatedDevDependencies];\n\n if (allOutdated.length > 0) {\n logger(\n colorize(\n `Upgrading outdated Intlayer dependencies to ${options.upgradeToVersion}...`,\n ANSIColors.CYAN\n )\n );\n try {\n upgradePackages(\n rootDir,\n outdatedDependencies,\n packageManager,\n options.upgradeToVersion\n );\n upgradePackages(\n rootDir,\n outdatedDevDependencies,\n packageManager,\n options.upgradeToVersion,\n true\n );\n logger(\n `${v} Upgraded: ${allOutdated.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to upgrade packages. Please upgrade manually: ${allOutdated.join(' ')}`,\n { level: 'warn' }\n );\n }\n } else {\n logger(`${v} Intlayer dependencies are up to date`);\n }\n }\n }\n\n // CHECK .GITIGNORE\n const gitignorePath = '.gitignore';\n if (!options?.noGitignore && (await exists(rootDir, gitignorePath))) {\n const gitignoreContent = await readFileFromRoot(rootDir, gitignorePath);\n\n if (!gitignoreContent.includes('intlayer')) {\n const newContent = `${gitignoreContent}\\n# Intlayer\\n.intlayer\\n`;\n await writeFileToRoot(rootDir, gitignorePath, newContent);\n logger(\n `${v} Added ${colorizePath('.intlayer')} to ${colorizePath(gitignorePath)}`\n );\n } else {\n logger(`${v} ${colorizePath(gitignorePath)} already includes .intlayer`);\n }\n }\n\n // SCAFFOLD GITHUB ACTIONS WORKFLOWS (fill + test)\n // Generate two workflows whose commands match the detected package manager:\n // - intlayer-fill.yml: auto-fills missing translations on pull requests\n // - intlayer-test.yml: fails the PR when required locales are missing\n if (!options?.noGithubActions) {\n const workflows = getGithubWorkflows(packageManager);\n\n for (const workflow of workflows) {\n if (await exists(rootDir, workflow.filePath)) {\n logger(`${v} ${colorizePath(workflow.filePath)} already exists`);\n continue;\n }\n\n try {\n await ensureDirectory(rootDir, join('.github', 'workflows'));\n await writeFileToRoot(rootDir, workflow.filePath, workflow.content);\n logger(\n `${v} Added GitHub Actions workflow ${colorizePath(workflow.filePath)}`\n );\n } catch {\n logger(\n `${x} Could not create ${colorizePath(workflow.filePath)}. You may need to add it manually.`,\n { level: 'warn' }\n );\n }\n }\n }\n\n // CHECK VS CODE EXTENSION RECOMMENDATIONS\n const vscodeDir = '.vscode';\n const extensionsJsonPath = join(vscodeDir, 'extensions.json');\n const extensionId = 'intlayer.intlayer-vs-code-extension';\n\n if (!options?.noVscodeExtension) {\n try {\n let extensionsConfig: { recommendations: string[] } = {\n recommendations: [],\n };\n\n if (await exists(rootDir, extensionsJsonPath)) {\n const content = await readFileFromRoot(rootDir, extensionsJsonPath);\n extensionsConfig = parseJSONWithComments(content);\n } else {\n await ensureDirectory(rootDir, vscodeDir);\n }\n\n if (!extensionsConfig.recommendations) {\n extensionsConfig.recommendations = [];\n }\n\n if (!extensionsConfig.recommendations.includes(extensionId)) {\n extensionsConfig.recommendations.push(extensionId);\n await writeFileToRoot(\n rootDir,\n extensionsJsonPath,\n JSON.stringify(extensionsConfig, null, 2)\n );\n logger(\n `${v} Added ${colorize(extensionId, ANSIColors.MAGENTA)} to ${colorizePath(extensionsJsonPath)}`\n );\n } else {\n logger(\n `${v} ${colorizePath(extensionsJsonPath)} already includes ${colorize(extensionId, ANSIColors.MAGENTA)}`\n );\n }\n } catch {\n logger(\n `${x} Could not update ${colorizePath(extensionsJsonPath)}. You may need to add ${colorize(extensionId, ANSIColors.MAGENTA)} manually.`,\n { level: 'warn' }\n );\n }\n }\n\n // CHECK VS CODE LSP SETTINGS\n const settingsJsonPath = join(vscodeDir, 'settings.json');\n\n if (!options?.noLsp) {\n try {\n let settingsConfig: Record<string, unknown> = {};\n\n if (await exists(rootDir, settingsJsonPath)) {\n const content = await readFileFromRoot(rootDir, settingsJsonPath);\n settingsConfig = parseJSONWithComments(content);\n } else {\n await ensureDirectory(rootDir, vscodeDir);\n }\n\n let settingsUpdated = false;\n\n if (!settingsConfig['intlayer.languageServer.command']) {\n settingsConfig['intlayer.languageServer.command'] = 'npx';\n settingsUpdated = true;\n }\n\n if (!settingsConfig['intlayer.languageServer.args']) {\n settingsConfig['intlayer.languageServer.args'] = ['@intlayer/lsp'];\n settingsUpdated = true;\n }\n\n if (settingsUpdated) {\n await writeFileToRoot(\n rootDir,\n settingsJsonPath,\n JSON.stringify(settingsConfig, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(settingsJsonPath)} with LSP configuration`\n );\n } else {\n logger(\n `${v} ${colorizePath(settingsJsonPath)} already includes LSP configuration`\n );\n }\n } catch {\n logger(\n `${x} Could not update ${colorizePath(settingsJsonPath)}. You may need to add the LSP settings manually.`,\n { level: 'warn' }\n );\n }\n }\n\n // CHECK TSCONFIGS\n const tsConfigFiles = await findTsConfigFiles(rootDir);\n let hasTsConfig = false;\n\n for (const fileName of tsConfigFiles) {\n if (await exists(rootDir, fileName)) {\n hasTsConfig = true;\n try {\n const fileContent = await readFileFromRoot(rootDir, fileName);\n const config = parseJSONWithComments(fileContent);\n const typeDefinition = './.intlayer/**/*.ts';\n\n let updated = false;\n\n if (!config.include) {\n // Skip if no include array (solution-style)\n } else if (\n Array.isArray(config.include) &&\n !(config.include as string[]).some((pattern: string) =>\n pattern.includes('.intlayer')\n )\n ) {\n config.include.push(typeDefinition);\n updated = true;\n } else if (config.include.includes(typeDefinition)) {\n logger(\n `${v} ${colorizePath(fileName)} already includes intlayer types`\n );\n }\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n fileName,\n JSON.stringify(config, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(fileName)} to include intlayer types`\n );\n }\n } catch {\n logger(\n `${x} Could not parse or update ${colorizePath(fileName)}. You may need to add ${colorizePath('.intlayer/types/**/*.ts')} manually.`,\n { level: 'warn' }\n );\n }\n }\n }\n\n // INITIALIZE CONFIG FILE\n const format = hasTsConfig ? 'intlayer.config.ts' : 'intlayer.config.mjs';\n\n // Detect the locale JSON file pattern already in the project so we can\n // insert the matching locales into the config and produce the most\n // accurate source template for compat libraries.\n const detectedPattern = await detectJsonLocalePattern(rootDir);\n\n await initConfig(format, rootDir, detectedPattern?.locales);\n\n // INJECT SYNC-JSON PLUGIN FOR COMPAT LIBRARIES\n if (compatSyncConfig) {\n // For next-intl / use-intl, the messages path is authoritatively declared\n // in `i18n/request.ts` (e.g. `import(`../messages/${locale}.json`)`), so we\n // read it directly. It usually resolves to a single file per locale (no\n // `${key}` segment), whose first-level keys are namespaces — so the compat\n // config carries `splitKeys: true` to emit one dictionary per namespace.\n // Falls back to file-system globbing otherwise.\n const nextIntlMessagesPattern =\n allDeps['next-intl'] ||\n allDeps['@intlayer/next-intl'] ||\n allDeps['use-intl'] ||\n allDeps['@intlayer/use-intl']\n ? await detectNextIntlMessagesPattern(rootDir)\n : null;\n\n // lingui authoritatively resolves to `…/{locale}/messages.{po,json}`, where\n // the `messages` filename becomes the dictionary key. Prefer it so a `.po`\n // project gets `syncPO` (the generic JSON glob only sees `.json`).\n const sourceTemplate =\n linguiCatalog?.template ??\n nextIntlMessagesPattern?.template ??\n detectedPattern?.template;\n\n const resolvedSyncConfig = {\n ...compatSyncConfig,\n ...(sourceTemplate ? { sourceTemplate } : {}),\n };\n\n const syncPluginPackage =\n resolvedSyncConfig.plugin === 'po'\n ? '@intlayer/sync-po-plugin'\n : '@intlayer/sync-json-plugin';\n const syncPluginName =\n resolvedSyncConfig.plugin === 'po' ? 'syncPO' : 'syncJSON';\n\n // `splitKeys` only makes sense for a single file holding several namespaces.\n // If the resolved template addresses one namespace per file (`${key}`\n // segment), each file is already a single namespace — drop the flag so\n // syncJSON keeps one dictionary per file.\n if (\n resolvedSyncConfig.splitKeys &&\n resolvedSyncConfig.sourceTemplate.includes('${key}')\n ) {\n resolvedSyncConfig.splitKeys = false;\n }\n\n const intlayerConfigCandidates = [\n 'intlayer.config.ts',\n 'intlayer.config.mjs',\n 'intlayer.config.js',\n 'intlayer.config.cjs',\n ];\n\n for (const configFile of intlayerConfigCandidates) {\n if (await exists(rootDir, configFile)) {\n const configContent = await readFileFromRoot(rootDir, configFile);\n\n if (!configContent.includes(syncPluginPackage)) {\n const extension = configFile.split('.').pop()!;\n const updatedConfigContent = updateIntlayerConfigWithSyncPlugin(\n configContent,\n extension,\n resolvedSyncConfig\n );\n await writeFileToRoot(rootDir, configFile, updatedConfigContent);\n logger(\n `${v} Updated ${colorizePath(configFile)} with ${syncPluginName} compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(configFile)} already includes ${syncPluginName} plugin`\n );\n }\n break;\n }\n }\n }\n\n // APPLY ROUTING MODE\n // When a routing strategy was chosen (interactive init), write it to\n // `routing.mode` in the configuration file. Idempotent and comment-preserving.\n if (options?.routingMode) {\n await setRoutingModeInConfig(rootDir, options.routingMode);\n }\n\n let hasAliasConfiguration = false;\n\n // CHECK VITE CONFIG\n const viteConfigs = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];\n\n for (const file of viteConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n const content = await readFileFromRoot(rootDir, file);\n const extension = file.split('.').pop()!;\n\n if (compatVitePluginConfig) {\n const { replacesVitePlugin } = compatVitePluginConfig;\n\n if (content.includes(compatVitePluginConfig.pluginPackageSource)) {\n logger(\n `${v} ${colorizePath(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`\n );\n } else if (\n replacesVitePlugin &&\n content.includes(replacesVitePlugin.fromPackageSource)\n ) {\n // Drop-in replacement: rewrite the original i18n vite plugin's import\n // source, keeping its binding and call site (e.g. lingui).\n const updatedContent = replaceViteConfigPluginImportSource(\n content,\n replacesVitePlugin.importName,\n replacesVitePlugin.fromPackageSource,\n compatVitePluginConfig.pluginPackageSource\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to import ${replacesVitePlugin.importName} from ${compatVitePluginConfig.pluginPackageSource}`\n );\n } else {\n const updatedContent = updateViteConfigForCompatPlugin(\n content,\n extension,\n compatVitePluginConfig\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`\n );\n }\n } else if (!content.includes('vite-intlayer')) {\n const updatedContent = updateViteConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);\n }\n break;\n }\n }\n\n // CHECK NEXT CONFIG\n const nextConfigs = ['next.config.js', 'next.config.mjs', 'next.config.ts'];\n let isNextJsProject = false;\n\n for (const file of nextConfigs) {\n if (await exists(rootDir, file)) {\n isNextJsProject = true;\n hasAliasConfiguration = true;\n const content = await readFileFromRoot(rootDir, file);\n const extension = file.split('.').pop()!;\n\n if (allDeps['next-i18next']) {\n if (!content.includes('@intlayer/next-i18next')) {\n const updatedContent = updateNextConfigForNextI18next(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-i18next compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-i18next`\n );\n }\n } else if (allDeps['next-intl']) {\n if (!content.includes('@intlayer/next-intl/plugin')) {\n const updatedContent = updateNextConfigForNextIntl(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-intl compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-intl/plugin`\n );\n }\n } else if (allDeps['next-translate']) {\n if (!content.includes('@intlayer/next-translate')) {\n const updatedContent = updateNextConfigForNextTranslate(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-translate compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-translate`\n );\n }\n } else if (!content.includes('next-intlayer')) {\n const updatedContent = updateNextConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);\n }\n break;\n }\n }\n\n // CHECK NEXT.JS COMPILER (BABEL)\n // When a Next.js project already uses Babel, install @intlayer/babel and print\n // the compiler + build-optimization plugins (extract, purge, minify, optimize)\n // to add. SWC projects need no setup: withIntlayer injects @intlayer/swc.\n if (isNextJsProject) {\n await setupNextCompilerBabelConfig({\n rootDir,\n packageManager,\n allDeps,\n skipInstall: Boolean(options?.noInstallPackages),\n });\n }\n\n // CHECK OTHER FRAMEWORKS CONFIG\n const astroConfigs = [\n 'astro.config.mjs',\n 'astro.config.js',\n 'astro.config.ts',\n 'astro.config.cjs',\n ];\n\n for (const file of astroConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n\n if (file.startsWith('astro.config.')) {\n const content = await readFileFromRoot(rootDir, file);\n\n if (!content.includes('astro-intlayer')) {\n const extension = file.split('.').pop()!;\n const updatedContent = updateAstroConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer integration`\n );\n }\n }\n break;\n }\n }\n\n const nuxtConfigs = ['nuxt.config.js', 'nuxt.config.ts'];\n for (const file of nuxtConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n\n const content = await readFileFromRoot(rootDir, file);\n\n if (allDeps['@nuxtjs/i18n']) {\n if (!content.includes('@intlayer/nuxtjs-i18n')) {\n const updatedContent = updateNuxtConfigForNuxtjsI18n(content);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include @intlayer/nuxtjs-i18n module`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/nuxtjs-i18n`\n );\n }\n } else if (!content.includes('nuxt-intlayer')) {\n const updatedContent = updateNuxtConfig(content);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer module`);\n }\n break;\n }\n }\n\n // CHECK METRO CONFIG (React Native / Expo)\n // Metro is the React Native bundler. The Intlayer Metro plugin\n // (`react-native-intlayer/metro`) handles dictionary aliasing and building.\n // When no config exists we scaffold one; when one exists we safely wrap its\n // exported config with `configMetroIntlayerSync`, leaving custom async\n // (IIFE) configs untouched so existing setups are never broken.\n const isReactNativeProject = Boolean(allDeps['react-native'] || allDeps.expo);\n\n if (isReactNativeProject) {\n // Metro resolves Intlayer aliases itself, so skip the alias fallback below.\n hasAliasConfiguration = true;\n\n const metroConfigs = [\n 'metro.config.js',\n 'metro.config.cjs',\n 'metro.config.mjs',\n 'metro.config.ts',\n ];\n\n let metroConfigFile: string | undefined;\n\n for (const file of metroConfigs) {\n if (await exists(rootDir, file)) {\n metroConfigFile = file;\n break;\n }\n }\n\n if (metroConfigFile) {\n const content = await readFileFromRoot(rootDir, metroConfigFile);\n\n if (content.includes('react-native-intlayer')) {\n logger(\n `${v} ${colorizePath(metroConfigFile)} already includes the Intlayer Metro plugin`\n );\n } else {\n const extension = metroConfigFile.split('.').pop()!;\n const updatedContent = updateMetroConfig(content, extension);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, metroConfigFile, updatedContent);\n logger(\n `${v} Updated ${colorizePath(metroConfigFile)} to include the Intlayer Metro plugin`\n );\n } else {\n logger(\n `${x} Could not automatically update ${colorizePath(metroConfigFile)}. Wrap your exported config with ${colorize('configMetroIntlayer', ANSIColors.MAGENTA)}: ${colorizePath(DocumentationRouter.ReactNativeAndExpo)}`,\n { level: 'warn' }\n );\n }\n }\n } else {\n const newMetroConfigFile = 'metro.config.js';\n await writeFileToRoot(\n rootDir,\n newMetroConfigFile,\n getMetroConfigTemplate(Boolean(allDeps.expo))\n );\n logger(\n `${v} Created ${colorizePath(newMetroConfigFile)} with the Intlayer Metro plugin`\n );\n }\n }\n\n // UPDATE PACKAGE.JSON DEV SCRIPT\n // Next.js >= 16 uses a bun-specific wrapper; backend frameworks wrap whatever\n // the existing dev script is. Both use `intlayer watch --with`.\n const isVersionGreaterOrEqual = (\n versionString: string,\n major: number\n ): boolean => {\n if (!versionString || typeof versionString !== 'string') return false;\n const match = versionString.match(/^[^\\d]*(\\d+)/);\n\n if (!match?.[1]) return false;\n\n return parseInt(match[1], 10) >= major;\n };\n\n const backendIntlayerPackages = [\n 'express-intlayer',\n 'fastify-intlayer',\n 'adonis-intlayer',\n 'hono-intlayer',\n ];\n\n const devScript = packageJson.scripts?.dev;\n\n let newDevScript: string | undefined;\n\n if (\n ((isNextJsProject &&\n allDeps.next &&\n isVersionGreaterOrEqual(allDeps.next, 16)) ||\n backendIntlayerPackages.some((pkg) => allDeps[pkg])) &&\n !devScript.includes('intlayer watch')\n ) {\n newDevScript = `intlayer watch --with '${devScript}'`;\n }\n\n if (newDevScript) {\n packageJson.scripts.dev = newDevScript;\n\n await writeFileToRoot(\n rootDir,\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n\n logger(\n `${v} Updated ${colorizePath('package.json')} dev script to run intlayer watch`\n );\n }\n\n // CHECK WEBPACK CONFIG\n const webpackConfigs = [\n 'webpack.config.js',\n 'webpack.config.ts',\n 'webpack.config.mjs',\n 'webpack.config.cjs',\n ];\n\n for (const file of webpackConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n logger(\n `${v} Found ${colorizePath(\n file\n )}. Make sure to configure aliases manually or use the Intlayer Webpack plugin.`\n );\n break;\n }\n }\n\n const backendConfigPackages = [\n 'express',\n 'fastify',\n '@adonisjs/core',\n 'hono',\n ...backendIntlayerPackages,\n ];\n\n if (backendConfigPackages.some((pkg) => allDeps[pkg])) {\n hasAliasConfiguration = true;\n }\n\n if (!hasAliasConfiguration) {\n const configuration = getConfiguration({ baseDir: rootDir });\n const aliases = getAlias({ configuration });\n\n if (hasTsConfig && tsConfigFiles.length > 0) {\n const tsConfigPath =\n tsConfigFiles.find((file) => file === 'tsconfig.json') ||\n tsConfigFiles[0];\n\n if (tsConfigPath) {\n const tsConfigContent = await readFileFromRoot(rootDir, tsConfigPath);\n const config = parseJSONWithComments(tsConfigContent);\n\n config.compilerOptions ??= {};\n config.compilerOptions.paths ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n if (!config.compilerOptions.paths[alias]) {\n config.compilerOptions.paths[alias] = [path];\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n tsConfigPath,\n JSON.stringify(config, null, 2)\n );\n\n logger(\n `${v} Updated ${colorizePath(\n tsConfigPath\n )} to include Intlayer aliases`\n );\n }\n }\n } else {\n const jsConfigPath = 'jsconfig.json';\n\n if (await exists(rootDir, jsConfigPath)) {\n const jsConfigContent = await readFileFromRoot(rootDir, jsConfigPath);\n const config = parseJSONWithComments(jsConfigContent);\n\n config.compilerOptions ??= {};\n config.compilerOptions.paths ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n if (!config.compilerOptions.paths[alias]) {\n config.compilerOptions.paths[alias] = [path];\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n jsConfigPath,\n JSON.stringify(config, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(\n jsConfigPath\n )} to include Intlayer aliases`\n );\n }\n } else {\n packageJson.imports ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n const importAlias = alias.replace('@', '#');\n const importPath = path.startsWith('.') ? path : `./${path}`;\n\n if (!packageJson.imports[importAlias]) {\n packageJson.imports[importAlias] = importPath;\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(\n packageJsonPath\n )} to include Intlayer imports`\n );\n }\n }\n }\n }\n\n // FRAMEWORK-SPECIFIC SCAFFOLDING\n // Sets up middleware/proxy and wraps the layout/page with the Intlayer\n // providers for the detected framework (Next.js App Router today). Idempotent\n // and non-destructive: it never overwrites user code it cannot safely\n // transform, skipping with guidance instead.\n if (!options?.noFrameworkSetup) {\n try {\n // Prefer the user's interactive choice, else the configured routing mode\n // (which itself defaults to `prefix-no-default`). Drives whether the\n // locale path segment is required (`prefix-all`) or optional.\n const routingMode =\n options?.routingMode ??\n getConfiguration({ baseDir: rootDir }).routing.mode;\n\n await setupFramework({\n rootDir,\n allDeps,\n packageManager,\n useTypeScript: hasTsConfig,\n routingMode,\n });\n } catch {\n logger(\n `${x} Framework-specific scaffolding failed. Your existing files were left untouched; follow the documentation to finish the setup.`,\n { level: 'warn' }\n );\n }\n }\n\n // FINAL SUCCESS MESSAGE\n logger(`${v} ${colorize('Intlayer init setup complete.', ANSIColors.GREEN)}`);\n logger([\n colorize('Next →', ANSIColors.MAGENTA),\n colorize(\n `Follow the instructions in the documentation to complete the setup:`,\n ANSIColors.GREY_LIGHT\n ),\n colorizePath(guideUrl),\n ]);\n\n // INTLAYER LSP — instruction for the AI agent running `intlayer init`.\n // The Intlayer Language Server (`@intlayer/lsp`) provides Go-to-Definition\n // from `useIntlayer` / `getIntlayer` keys to their `.content` files, for both\n // IDEs and AI agents. Setup is editor-specific (VS Code, Cursor, Windsurf,\n // Zed, Neovim, Claude Code, …), so we don't scaffold anything here — instead\n // we point to the doc and ask the agent to confirm the target platform.\n logger([\n colorize('Intlayer LSP →', ANSIColors.MAGENTA),\n colorize(\n 'The Intlayer Language Server is available via the `@intlayer/lsp` package. It lets IDEs and AI agents jump from `useIntlayer`/`getIntlayer` keys to their `.content` files.',\n ANSIColors.GREY_LIGHT\n ),\n colorize(\n 'Ask the user which platform/editor they want to enable it on (VS Code, Cursor, Windsurf, Zed, Neovim, Claude Code, …), then follow the matching setup instructions:',\n ANSIColors.GREY_LIGHT\n ),\n colorizePath(DocumentationRouter.LSP),\n ]);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/init/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\nimport { initConfig } from '../initConfig';\nimport { setCompilerOutputInConfig, setRoutingModeInConfig } from './cms';\nimport { setupFramework } from './frameworkSetup';\nimport type { CompatSyncConfig, RoutingMode } from './utils';\nimport {\n detectJsonLocalePattern,\n detectLinguiCatalogPattern,\n detectMissingIntlayerPackages,\n detectNextIntlMessagesPattern,\n detectOutdatedIntlayerPackages,\n detectPackageManager,\n ensureDirectory,\n exists,\n findTsConfigFiles,\n getGithubWorkflows,\n getMetroConfigTemplate,\n installPackages,\n isVersionAtLeast,\n parseJSONWithComments,\n readFileFromRoot,\n replaceViteConfigPluginImportSource,\n setupNextCompilerBabelConfig,\n updateAstroConfig,\n updateIntlayerConfigWithSyncPlugin,\n updateMetroConfig,\n updateNextConfig,\n updateNextConfigForNextI18next,\n updateNextConfigForNextIntl,\n updateNextConfigForNextTranslate,\n updateNuxtConfig,\n updateNuxtConfigForNuxtjsI18n,\n updateViteConfig,\n updateViteConfigForCompatPlugin,\n upgradePackages,\n writeFileToRoot,\n} from './utils';\n\n/**\n * Documentation URL Constants\n */\nconst DocumentationRouter = {\n NextJS: 'https://intlayer.org/doc/environment/nextjs.md',\n NextJS_15: 'https://intlayer.org/doc/environment/nextjs/15.md',\n NextJS_14: 'https://intlayer.org/doc/environment/nextjs/14.md',\n CRA: 'https://intlayer.org/doc/environment/create-react-app.md',\n Astro: 'https://intlayer.org/doc/environment/astro.md',\n ViteAndReact: 'https://intlayer.org/doc/environment/vite-and-react.md',\n ViteAndReact_ReactRouterV7:\n 'https://intlayer.org/doc/environment/vite-and-react/react-router-v7.md',\n ViteAndReact_ReactRouterV7_FSRoutes:\n 'https://intlayer.org/doc/environment/vite-and-react/react-router-v7-fs-routes.md',\n ViteAndVue: 'https://intlayer.org/doc/environment/vite-and-vue.md',\n ViteAndSolid: 'https://intlayer.org/doc/environment/vite-and-solid.md',\n ViteAndSvelte: 'https://intlayer.org/doc/environment/vite-and-svelte.md',\n ViteAndPreact: 'https://intlayer.org/doc/environment/vite-and-preact.md',\n TanStackRouter: 'https://intlayer.org/doc/environment/tanstack.md',\n NuxtAndVue: 'https://intlayer.org/doc/environment/nuxt-and-vue.md',\n Angular: 'https://intlayer.org/doc/environment/angular.md',\n SvelteKit: 'https://intlayer.org/doc/environment/sveltekit.md',\n ReactNativeAndExpo:\n 'https://intlayer.org/doc/environment/react-native-and-expo.md',\n Lynx: 'https://intlayer.org/doc/environment/lynx-and-react.md',\n Express: 'https://intlayer.org/doc/environment/express.md',\n NestJS: 'https://intlayer.org/doc/environment/nestjs.md',\n Fastify: 'https://intlayer.org/doc/environment/fastify.md',\n Default: 'https://intlayer.org/doc/get-started',\n\n // Intlayer Language Server (Go-to-Definition from getter keys to .content files)\n LSP: 'https://intlayer.org/doc/lsp.md',\n\n // Check for competitors libs\n NextIntl: 'https://intlayer.org/blog/intlayer-with-next-intl.md',\n ReactI18Next: 'https://intlayer.org/blog/intlayer-with-react-i18next.md',\n ReactIntl: 'https://intlayer.org/blog/intlayer-with-react-intl.md',\n NextI18Next: 'https://intlayer.org/blog/intlayer-with-next-i18next.md',\n VueI18n: 'https://intlayer.org/blog/intlayer-with-vue-i18n.md',\n};\n\n/**\n * Helper: Detects the environment and returns the doc URL\n */\nconst getDocumentationUrl = (packageJson: any): string => {\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n /**\n * Helper to check if a version string matches a specific major version\n * Matches: \"15\", \"^15.0.0\", \"~15.2\", \"15.0.0-beta\"\n */\n const isVersion = (versionString: string, major: number): boolean => {\n if (!versionString || typeof versionString !== 'string') return false;\n const regex = new RegExp(`^[\\\\^~]?${major}(?:\\\\.|$)`);\n return regex.test(versionString);\n };\n\n // Mobile / Cross-platform\n if (deps['@lynx-js/react'] || deps['@lynx-js/core']) {\n return DocumentationRouter.Lynx;\n }\n if (deps['react-native'] || deps.expo) {\n return DocumentationRouter.ReactNativeAndExpo;\n }\n\n // Meta-frameworks (Next, Nuxt, Astro, SvelteKit)\n if (deps.next) {\n const version = deps.next;\n\n if (isVersion(version, 14)) {\n return DocumentationRouter.NextJS_14;\n }\n\n if (isVersion(version, 15)) {\n return DocumentationRouter.NextJS_15;\n }\n\n return DocumentationRouter.NextJS;\n }\n\n if (deps.nuxt) return DocumentationRouter.NuxtAndVue;\n if (deps.astro) return DocumentationRouter.Astro;\n if (deps['@sveltejs/kit']) return DocumentationRouter.SvelteKit;\n\n // Routers (TanStack & React Router v7)\n if (deps['@tanstack/react-router']) {\n return DocumentationRouter.TanStackRouter;\n }\n\n // Check for React Router v7\n const reactRouterVersion = deps['react-router'];\n if (reactRouterVersion && typeof reactRouterVersion === 'string') {\n // Distinguish between standard v7 and v7 with FS routes\n if (deps['@react-router/fs-routes']) {\n return DocumentationRouter.ViteAndReact_ReactRouterV7_FSRoutes;\n }\n\n // Use Regex to ensure it is v7\n if (isVersion(reactRouterVersion, 7)) {\n return DocumentationRouter.ViteAndReact_ReactRouterV7;\n }\n }\n\n // Vite Ecosystem (General)\n if (deps.vite) {\n if (deps.vue) return DocumentationRouter.ViteAndVue;\n if (deps['solid-js']) return DocumentationRouter.ViteAndSolid;\n if (deps.svelte) return DocumentationRouter.ViteAndSvelte;\n if (deps.preact) return DocumentationRouter.ViteAndPreact;\n\n // Default to React if Vite is present but specific other frameworks aren't found\n return DocumentationRouter.ViteAndReact;\n }\n\n // Other Web Frameworks\n if (deps['react-scripts']) return DocumentationRouter.CRA;\n if (deps['@angular/core']) return DocumentationRouter.Angular;\n\n // Backend\n if (deps['@nestjs/core']) return DocumentationRouter.NestJS;\n if (deps.express) return DocumentationRouter.Express;\n if (deps.fastify) return DocumentationRouter.Fastify;\n\n // Competitor Libs (Migration Guides)\n // We check these last as specific environment setup is usually higher priority,\n // but if no specific framework logic matched (or as a fallback), we guide to migration.\n if (deps['next-intl']) return DocumentationRouter.NextIntl;\n if (deps['react-i18next'] || deps.i18next)\n return DocumentationRouter.ReactI18Next;\n if (deps['react-intl']) return DocumentationRouter.ReactIntl;\n if (deps['next-i18next']) return DocumentationRouter.NextI18Next;\n if (deps['vue-i18n']) return DocumentationRouter.VueI18n;\n\n return DocumentationRouter.Default;\n};\n\n/**\n * Resolves the default dev-server URL of the detected framework, used as the\n * `editor.applicationURL` of the generated configuration file. Frameworks that\n * embed Vite (Astro, SvelteKit, …) are checked before the bare Vite fallback so\n * their own dev port wins.\n */\nexport const getDefaultApplicationURL = (\n dependencies: Record<string, string>\n): string => {\n if (dependencies.next) return 'http://localhost:3000';\n if (dependencies.astro) return 'http://localhost:4321';\n if (dependencies['@angular/core']) return 'http://localhost:4200';\n if (dependencies.nuxt) return 'http://localhost:3000';\n if (dependencies['@sveltejs/kit']) return 'http://localhost:5173';\n if (dependencies['react-scripts']) return 'http://localhost:3000';\n if (dependencies.vite) return 'http://localhost:5173';\n\n return 'http://localhost:3000';\n};\n\n/**\n * How the interactive init organizes autogenerated content (compiler output /\n * autofill):\n * - `per-component` — multilingual `.content` files co-located with components\n * (the configuration template default).\n * - `centralized` — per-locale JSON dictionaries under `/locales/{locale}/`.\n * - `json-namespaces` — plain per-locale JSON namespace files kept in sync\n * through `@intlayer/sync-json-plugin`.\n */\nexport type ContentStrategy =\n | 'per-component'\n | 'centralized'\n | 'json-namespaces';\n\n/**\n * OPTIONS\n */\nexport type InitOptions = {\n noGitignore?: boolean;\n /** Skip scaffolding the `fill` and `test` GitHub Actions workflows. */\n noGithubActions?: boolean;\n /**\n * Skip installing missing Intlayer dependencies and upgrading outdated ones.\n */\n noInstallPackages?: boolean;\n /** Skip adding the Intlayer extension to `.vscode/extensions.json`. */\n noVscodeExtension?: boolean;\n /** Skip writing the Intlayer LSP configuration to `.vscode/settings.json`. */\n noLsp?: boolean;\n /**\n * Skip framework-specific scaffolding (middleware/proxy, providers in\n * layout/page, example content). Defaults to enabled.\n */\n noFrameworkSetup?: boolean;\n /**\n * Version that outdated Intlayer packages should be upgraded to (typically the\n * running CLI version). When omitted, installed packages are left untouched and\n * only missing ones are installed.\n */\n upgradeToVersion?: string;\n /**\n * Locale routing strategy to write to `routing.mode` in the generated/existing\n * Intlayer configuration file. When omitted, the configuration default\n * (`prefix-no-default`) is kept.\n */\n routingMode?: RoutingMode;\n /**\n * Extra packages hinted by the interactive init prompt (compat i18n library\n * selections made before those libraries are actually installed). These are\n * merged into the dependency map used by {@link detectMissingIntlayerPackages}\n * so the correct sync plugin and compat adapter are always scheduled.\n */\n hintDependencies?: Record<string, string>;\n /**\n * Content organization strategy chosen by the interactive init prompt. Drives\n * the `compiler.output` template (`centralized`) or the injection of the\n * syncJSON plugin (`json-namespaces`). When omitted (or `per-component`), the\n * configuration template default is kept.\n */\n contentStrategy?: ContentStrategy;\n};\n\n/**\n * MAIN LOGIC\n */\nexport const initIntlayer = async (rootDir: string, options?: InitOptions) => {\n logger(colorize('Checking Intlayer configuration...', ANSIColors.CYAN));\n\n // READ PACKAGE.JSON\n const packageJsonPath = 'package.json';\n if (!(await exists(rootDir, packageJsonPath))) {\n logger(\n `${x} No ${colorizePath('package.json')} found. Please run this script from the project root.`,\n { level: 'error' }\n );\n process.exit(1);\n }\n\n const packageJsonContent = await readFileFromRoot(rootDir, packageJsonPath);\n let packageJson: Record<string, any>;\n try {\n packageJson = JSON.parse(packageJsonContent);\n } catch {\n logger(`${x} Could not parse ${colorizePath('package.json')}.`, {\n level: 'error',\n });\n process.exit(1);\n }\n\n // Determine the correct documentation URL based on dependencies\n const guideUrl = getDocumentationUrl(packageJson);\n\n const allDeps: Record<string, string> = {\n ...(packageJson.dependencies ?? {}),\n ...(packageJson.devDependencies ?? {}),\n };\n\n // Effective deps = real deps + interactive hint-deps (compat library selections\n // from the interactive init prompt that haven't been installed yet).\n const effectiveAllDeps: Record<string, string> = {\n ...allDeps,\n ...(options?.hintDependencies ?? {}),\n };\n\n // INSTALL MISSING INTLAYER DEPENDENCIES\n const packageManager = detectPackageManager(rootDir);\n\n // lingui keeps its catalogs as `.po` (default) or `.json`. Detect which so the\n // matching sync plugin (`syncPO` / `syncJSON`) + dev dependency are chosen.\n // Also respect the `__lingui_json__` sentinel injected by the interactive init\n // prompt when the user explicitly selected \"Lingui (.json catalogs)\".\n const linguiPresent = Boolean(\n effectiveAllDeps['@lingui/core'] ||\n effectiveAllDeps['@lingui/react'] ||\n effectiveAllDeps['@intlayer/lingui']\n );\n\n // Determine format: prefer filesystem scan, then the interactive sentinel.\n const linguiCatalog = linguiPresent\n ? await detectLinguiCatalogPattern(rootDir)\n : null;\n\n const hintLinguiJson = Boolean(\n options?.hintDependencies?.['__lingui_json__']\n );\n // `linguiCatalogFormat` resolution:\n // 1. Filesystem scan result (authoritative when catalogs already exist)\n // 2. Interactive sentinel `__lingui_json__` → 'json'\n // 3. Fallback: 'po' (lingui's default) when lingui is selected but no\n // catalogs have been generated yet and no sentinel was injected.\n const linguiCatalogFormat: 'po' | 'json' | null =\n linguiCatalog?.format ??\n (linguiPresent ? (hintLinguiJson ? 'json' : 'po') : null);\n\n const {\n packagesToInstall,\n devPackagesToInstall,\n compatSyncConfig,\n compatVitePluginConfig,\n } = detectMissingIntlayerPackages(effectiveAllDeps, {\n linguiCatalogFormat,\n });\n\n // The `json-namespaces` content strategy uses the same syncJSON pipeline as\n // the compat libraries: plain per-locale JSON namespace files synced through\n // `@intlayer/sync-json-plugin`. A detected compat library keeps precedence —\n // its own catalog format/template is authoritative.\n const wantsJsonNamespaces =\n options?.contentStrategy === 'json-namespaces' && !compatSyncConfig;\n\n if (\n wantsJsonNamespaces &&\n !effectiveAllDeps['@intlayer/sync-json-plugin'] &&\n !devPackagesToInstall.includes('@intlayer/sync-json-plugin')\n ) {\n devPackagesToInstall.push('@intlayer/sync-json-plugin');\n }\n\n if (!options?.noInstallPackages) {\n const withVersion = (packages: string[]): string[] =>\n options?.upgradeToVersion\n ? packages.map((pkg) => `${pkg}@${options.upgradeToVersion}`)\n : packages;\n\n if (packagesToInstall.length > 0) {\n logger(\n colorize('Installing missing Intlayer dependencies...', ANSIColors.CYAN)\n );\n try {\n installPackages(\n rootDir,\n withVersion(packagesToInstall),\n packageManager\n );\n logger(\n `${v} Installed: ${packagesToInstall.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to install packages. Please install manually: ${packagesToInstall.join(' ')}`,\n { level: 'warn' }\n );\n }\n }\n\n if (devPackagesToInstall.length > 0) {\n logger(\n colorize(\n 'Installing missing Intlayer dev dependencies...',\n ANSIColors.CYAN\n )\n );\n try {\n installPackages(\n rootDir,\n withVersion(devPackagesToInstall),\n packageManager,\n true\n );\n logger(\n `${v} Installed: ${devPackagesToInstall.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to install dev packages. Please install manually: ${devPackagesToInstall.join(' ')}`,\n { level: 'warn' }\n );\n }\n }\n\n // UPGRADE OUTDATED INTLAYER DEPENDENCIES\n // Only runs when a target version is provided (typically the running CLI\n // version). Already up-to-date packages are skipped. Prod and dev\n // dependencies are upgraded separately so their dependency type is kept.\n if (options?.upgradeToVersion) {\n const outdatedDependencies = detectOutdatedIntlayerPackages(\n rootDir,\n packageJson.dependencies ?? {},\n options.upgradeToVersion\n );\n const outdatedDevDependencies = detectOutdatedIntlayerPackages(\n rootDir,\n packageJson.devDependencies ?? {},\n options.upgradeToVersion\n );\n\n const allOutdated = [...outdatedDependencies, ...outdatedDevDependencies];\n\n if (allOutdated.length > 0) {\n logger(\n colorize(\n `Upgrading outdated Intlayer dependencies to ${options.upgradeToVersion}...`,\n ANSIColors.CYAN\n )\n );\n try {\n upgradePackages(\n rootDir,\n outdatedDependencies,\n packageManager,\n options.upgradeToVersion\n );\n upgradePackages(\n rootDir,\n outdatedDevDependencies,\n packageManager,\n options.upgradeToVersion,\n true\n );\n logger(\n `${v} Upgraded: ${allOutdated.map((pkg) => colorize(pkg, ANSIColors.MAGENTA)).join(', ')}`\n );\n } catch {\n logger(\n `${x} Failed to upgrade packages. Please upgrade manually: ${allOutdated.join(' ')}`,\n { level: 'warn' }\n );\n }\n } else {\n logger(`${v} Intlayer dependencies are up to date`);\n }\n }\n }\n\n // CHECK .GITIGNORE\n const gitignorePath = '.gitignore';\n if (!options?.noGitignore && (await exists(rootDir, gitignorePath))) {\n const gitignoreContent = await readFileFromRoot(rootDir, gitignorePath);\n\n if (!gitignoreContent.includes('intlayer')) {\n const newContent = `${gitignoreContent}\\n# Intlayer\\n.intlayer\\n`;\n await writeFileToRoot(rootDir, gitignorePath, newContent);\n logger(\n `${v} Added ${colorizePath('.intlayer')} to ${colorizePath(gitignorePath)}`\n );\n } else {\n logger(`${v} ${colorizePath(gitignorePath)} already includes .intlayer`);\n }\n }\n\n // SCAFFOLD GITHUB ACTIONS WORKFLOWS (fill + test)\n // Generate two workflows whose commands match the detected package manager:\n // - intlayer-fill.yml: auto-fills missing translations on pull requests\n // - intlayer-test.yml: fails the PR when required locales are missing\n if (!options?.noGithubActions) {\n const workflows = getGithubWorkflows(packageManager);\n\n for (const workflow of workflows) {\n if (await exists(rootDir, workflow.filePath)) {\n logger(`${v} ${colorizePath(workflow.filePath)} already exists`);\n continue;\n }\n\n try {\n await ensureDirectory(rootDir, join('.github', 'workflows'));\n await writeFileToRoot(rootDir, workflow.filePath, workflow.content);\n logger(\n `${v} Added GitHub Actions workflow ${colorizePath(workflow.filePath)}`\n );\n } catch {\n logger(\n `${x} Could not create ${colorizePath(workflow.filePath)}. You may need to add it manually.`,\n { level: 'warn' }\n );\n }\n }\n }\n\n // CHECK VS CODE EXTENSION RECOMMENDATIONS\n const vscodeDir = '.vscode';\n const extensionsJsonPath = join(vscodeDir, 'extensions.json');\n const extensionId = 'intlayer.intlayer-vs-code-extension';\n\n if (!options?.noVscodeExtension) {\n try {\n let extensionsConfig: { recommendations: string[] } = {\n recommendations: [],\n };\n\n if (await exists(rootDir, extensionsJsonPath)) {\n const content = await readFileFromRoot(rootDir, extensionsJsonPath);\n extensionsConfig = parseJSONWithComments(content);\n } else {\n await ensureDirectory(rootDir, vscodeDir);\n }\n\n if (!extensionsConfig.recommendations) {\n extensionsConfig.recommendations = [];\n }\n\n if (!extensionsConfig.recommendations.includes(extensionId)) {\n extensionsConfig.recommendations.push(extensionId);\n await writeFileToRoot(\n rootDir,\n extensionsJsonPath,\n JSON.stringify(extensionsConfig, null, 2)\n );\n logger(\n `${v} Added ${colorize(extensionId, ANSIColors.MAGENTA)} to ${colorizePath(extensionsJsonPath)}`\n );\n } else {\n logger(\n `${v} ${colorizePath(extensionsJsonPath)} already includes ${colorize(extensionId, ANSIColors.MAGENTA)}`\n );\n }\n } catch {\n logger(\n `${x} Could not update ${colorizePath(extensionsJsonPath)}. You may need to add ${colorize(extensionId, ANSIColors.MAGENTA)} manually.`,\n { level: 'warn' }\n );\n }\n }\n\n // CHECK VS CODE LSP SETTINGS\n const settingsJsonPath = join(vscodeDir, 'settings.json');\n\n if (!options?.noLsp) {\n try {\n let settingsConfig: Record<string, unknown> = {};\n\n if (await exists(rootDir, settingsJsonPath)) {\n const content = await readFileFromRoot(rootDir, settingsJsonPath);\n settingsConfig = parseJSONWithComments(content);\n } else {\n await ensureDirectory(rootDir, vscodeDir);\n }\n\n let settingsUpdated = false;\n\n if (!settingsConfig['intlayer.languageServer.command']) {\n settingsConfig['intlayer.languageServer.command'] = 'npx';\n settingsUpdated = true;\n }\n\n if (!settingsConfig['intlayer.languageServer.args']) {\n settingsConfig['intlayer.languageServer.args'] = ['@intlayer/lsp'];\n settingsUpdated = true;\n }\n\n if (settingsUpdated) {\n await writeFileToRoot(\n rootDir,\n settingsJsonPath,\n JSON.stringify(settingsConfig, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(settingsJsonPath)} with LSP configuration`\n );\n } else {\n logger(\n `${v} ${colorizePath(settingsJsonPath)} already includes LSP configuration`\n );\n }\n } catch {\n logger(\n `${x} Could not update ${colorizePath(settingsJsonPath)}. You may need to add the LSP settings manually.`,\n { level: 'warn' }\n );\n }\n }\n\n // CHECK TSCONFIGS\n const tsConfigFiles = await findTsConfigFiles(rootDir);\n let hasTsConfig = false;\n\n for (const fileName of tsConfigFiles) {\n if (await exists(rootDir, fileName)) {\n hasTsConfig = true;\n try {\n const fileContent = await readFileFromRoot(rootDir, fileName);\n const config = parseJSONWithComments(fileContent);\n const typeDefinition = './.intlayer/**/*.ts';\n\n let updated = false;\n\n if (!config.include) {\n // Skip if no include array (solution-style)\n } else if (\n Array.isArray(config.include) &&\n !(config.include as string[]).some((pattern: string) =>\n pattern.includes('.intlayer')\n )\n ) {\n config.include.push(typeDefinition);\n updated = true;\n } else if (config.include.includes(typeDefinition)) {\n logger(\n `${v} ${colorizePath(fileName)} already includes intlayer types`\n );\n }\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n fileName,\n JSON.stringify(config, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(fileName)} to include intlayer types`\n );\n }\n } catch {\n logger(\n `${x} Could not parse or update ${colorizePath(fileName)}. You may need to add ${colorizePath('.intlayer/types/**/*.ts')} manually.`,\n { level: 'warn' }\n );\n }\n }\n }\n\n // INITIALIZE CONFIG FILE\n const format = hasTsConfig ? 'intlayer.config.ts' : 'intlayer.config.mjs';\n\n // Detect the locale JSON file pattern already in the project so we can\n // insert the matching locales into the config and produce the most\n // accurate source template for compat libraries.\n const detectedPattern = await detectJsonLocalePattern(rootDir);\n\n await initConfig(format, rootDir, {\n locales: detectedPattern?.locales,\n applicationURL: getDefaultApplicationURL(allDeps),\n });\n\n // APPLY CONTENT STRATEGY — CENTRALIZED\n // Point `compiler.output` at per-locale JSON dictionaries under `/locales/`\n // instead of the per-component template default.\n if (options?.contentStrategy === 'centralized') {\n await setCompilerOutputInConfig(\n rootDir,\n '/locales/{{locale}}/{{key}}.content.json'\n );\n }\n\n // INJECT SYNC-JSON PLUGIN FOR COMPAT LIBRARIES / JSON-NAMESPACES STRATEGY\n const syncConfigToInject: CompatSyncConfig | undefined =\n compatSyncConfig ??\n (wantsJsonNamespaces\n ? {\n format: 'i18next',\n sourceTemplate:\n detectedPattern?.template ?? './locales/${locale}/${key}.json',\n }\n : undefined);\n\n if (syncConfigToInject) {\n // For next-intl / use-intl, the messages path is authoritatively declared\n // in `i18n/request.ts` (e.g. `import(`../messages/${locale}.json`)`), so we\n // read it directly. It usually resolves to a single file per locale (no\n // `${key}` segment), whose first-level keys are namespaces — so the compat\n // config carries `splitKeys: true` to emit one dictionary per namespace.\n // Falls back to file-system globbing otherwise.\n const nextIntlMessagesPattern =\n allDeps['next-intl'] ||\n allDeps['@intlayer/next-intl'] ||\n allDeps['use-intl'] ||\n allDeps['@intlayer/use-intl']\n ? await detectNextIntlMessagesPattern(rootDir)\n : null;\n\n // lingui authoritatively resolves to `…/{locale}/messages.{po,json}`, where\n // the `messages` filename becomes the dictionary key. Prefer it so a `.po`\n // project gets `syncPO` (the generic JSON glob only sees `.json`).\n const sourceTemplate =\n linguiCatalog?.template ??\n nextIntlMessagesPattern?.template ??\n detectedPattern?.template;\n\n const resolvedSyncConfig = {\n ...syncConfigToInject,\n ...(sourceTemplate ? { sourceTemplate } : {}),\n };\n\n const syncPluginPackage =\n resolvedSyncConfig.plugin === 'po'\n ? '@intlayer/sync-po-plugin'\n : '@intlayer/sync-json-plugin';\n const syncPluginName =\n resolvedSyncConfig.plugin === 'po' ? 'syncPO' : 'syncJSON';\n\n // `splitKeys` only makes sense for a single file holding several namespaces.\n // If the resolved template addresses one namespace per file (`${key}`\n // segment), each file is already a single namespace — drop the flag so\n // syncJSON keeps one dictionary per file.\n if (\n resolvedSyncConfig.splitKeys &&\n resolvedSyncConfig.sourceTemplate.includes('${key}')\n ) {\n resolvedSyncConfig.splitKeys = false;\n }\n\n const intlayerConfigCandidates = [\n 'intlayer.config.ts',\n 'intlayer.config.mjs',\n 'intlayer.config.js',\n 'intlayer.config.cjs',\n ];\n\n for (const configFile of intlayerConfigCandidates) {\n if (await exists(rootDir, configFile)) {\n const configContent = await readFileFromRoot(rootDir, configFile);\n\n if (!configContent.includes(syncPluginPackage)) {\n const extension = configFile.split('.').pop()!;\n const updatedConfigContent = updateIntlayerConfigWithSyncPlugin(\n configContent,\n extension,\n resolvedSyncConfig\n );\n await writeFileToRoot(rootDir, configFile, updatedConfigContent);\n logger(\n `${v} Updated ${colorizePath(configFile)} with ${syncPluginName} compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(configFile)} already includes ${syncPluginName} plugin`\n );\n }\n break;\n }\n }\n }\n\n // APPLY ROUTING MODE\n // When a routing strategy was chosen (interactive init), write it to\n // `routing.mode` in the configuration file. Idempotent and comment-preserving.\n if (options?.routingMode) {\n await setRoutingModeInConfig(rootDir, options.routingMode);\n }\n\n let hasAliasConfiguration = false;\n\n // CHECK VITE CONFIG\n const viteConfigs = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];\n\n for (const file of viteConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n const content = await readFileFromRoot(rootDir, file);\n const extension = file.split('.').pop()!;\n\n if (compatVitePluginConfig) {\n const { replacesVitePlugin } = compatVitePluginConfig;\n\n if (content.includes(compatVitePluginConfig.pluginPackageSource)) {\n logger(\n `${v} ${colorizePath(file)} already includes ${compatVitePluginConfig.pluginPackageSource}`\n );\n } else if (\n replacesVitePlugin &&\n content.includes(replacesVitePlugin.fromPackageSource)\n ) {\n // Drop-in replacement: rewrite the original i18n vite plugin's import\n // source, keeping its binding and call site (e.g. lingui).\n const updatedContent = replaceViteConfigPluginImportSource(\n content,\n replacesVitePlugin.importName,\n replacesVitePlugin.fromPackageSource,\n compatVitePluginConfig.pluginPackageSource\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to import ${replacesVitePlugin.importName} from ${compatVitePluginConfig.pluginPackageSource}`\n );\n } else {\n const updatedContent = updateViteConfigForCompatPlugin(\n content,\n extension,\n compatVitePluginConfig\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include ${compatVitePluginConfig.pluginFunctionName} compat plugin`\n );\n }\n } else if (!content.includes('vite-intlayer')) {\n const updatedContent = updateViteConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);\n }\n break;\n }\n }\n\n // CHECK NEXT CONFIG\n const nextConfigs = ['next.config.js', 'next.config.mjs', 'next.config.ts'];\n let isNextJsProject = false;\n\n for (const file of nextConfigs) {\n if (await exists(rootDir, file)) {\n isNextJsProject = true;\n hasAliasConfiguration = true;\n const content = await readFileFromRoot(rootDir, file);\n const extension = file.split('.').pop()!;\n\n if (allDeps['next-i18next']) {\n if (!content.includes('@intlayer/next-i18next')) {\n const updatedContent = updateNextConfigForNextI18next(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-i18next compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-i18next`\n );\n }\n } else if (allDeps['next-intl']) {\n if (!content.includes('@intlayer/next-intl/plugin')) {\n const updatedContent = updateNextConfigForNextIntl(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-intl compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-intl/plugin`\n );\n }\n } else if (allDeps['next-translate']) {\n if (!content.includes('@intlayer/next-translate')) {\n const updatedContent = updateNextConfigForNextTranslate(\n content,\n extension\n );\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer next-translate compat plugin`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/next-translate`\n );\n }\n } else if (!content.includes('next-intlayer')) {\n const updatedContent = updateNextConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer plugin`);\n }\n break;\n }\n }\n\n // CHECK NEXT.JS COMPILER (BABEL)\n // When a Next.js project already uses Babel, install @intlayer/babel and print\n // the compiler + build-optimization plugins (extract, purge, minify, optimize)\n // to add. SWC projects need no setup: withIntlayer injects @intlayer/swc.\n if (isNextJsProject) {\n await setupNextCompilerBabelConfig({\n rootDir,\n packageManager,\n allDeps,\n skipInstall: Boolean(options?.noInstallPackages),\n });\n }\n\n // CHECK OTHER FRAMEWORKS CONFIG\n const astroConfigs = [\n 'astro.config.mjs',\n 'astro.config.js',\n 'astro.config.ts',\n 'astro.config.cjs',\n ];\n\n for (const file of astroConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n\n if (file.startsWith('astro.config.')) {\n const content = await readFileFromRoot(rootDir, file);\n\n if (!content.includes('astro-intlayer')) {\n const extension = file.split('.').pop()!;\n const updatedContent = updateAstroConfig(content, extension);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include Intlayer integration`\n );\n }\n }\n break;\n }\n }\n\n const nuxtConfigs = ['nuxt.config.js', 'nuxt.config.ts'];\n for (const file of nuxtConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n\n const content = await readFileFromRoot(rootDir, file);\n\n if (allDeps['@nuxtjs/i18n']) {\n if (!content.includes('@intlayer/nuxtjs-i18n')) {\n const updatedContent = updateNuxtConfigForNuxtjsI18n(content);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(\n `${v} Updated ${colorizePath(file)} to include @intlayer/nuxtjs-i18n module`\n );\n } else {\n logger(\n `${v} ${colorizePath(file)} already includes @intlayer/nuxtjs-i18n`\n );\n }\n } else if (!content.includes('nuxt-intlayer')) {\n const updatedContent = updateNuxtConfig(content);\n await writeFileToRoot(rootDir, file, updatedContent);\n logger(`${v} Updated ${colorizePath(file)} to include Intlayer module`);\n }\n break;\n }\n }\n\n // CHECK METRO CONFIG (React Native / Expo)\n // Metro is the React Native bundler. The Intlayer Metro plugin\n // (`react-native-intlayer/metro`) handles dictionary aliasing and building.\n // When no config exists we scaffold one; when one exists we safely wrap its\n // exported config with `configMetroIntlayerSync`, leaving custom async\n // (IIFE) configs untouched so existing setups are never broken.\n const isReactNativeProject = Boolean(allDeps['react-native'] || allDeps.expo);\n\n if (isReactNativeProject) {\n // Metro resolves Intlayer aliases itself, so skip the alias fallback below.\n hasAliasConfiguration = true;\n\n const metroConfigs = [\n 'metro.config.js',\n 'metro.config.cjs',\n 'metro.config.mjs',\n 'metro.config.ts',\n ];\n\n let metroConfigFile: string | undefined;\n\n for (const file of metroConfigs) {\n if (await exists(rootDir, file)) {\n metroConfigFile = file;\n break;\n }\n }\n\n if (metroConfigFile) {\n const content = await readFileFromRoot(rootDir, metroConfigFile);\n\n if (content.includes('react-native-intlayer')) {\n logger(\n `${v} ${colorizePath(metroConfigFile)} already includes the Intlayer Metro plugin`\n );\n } else {\n const extension = metroConfigFile.split('.').pop()!;\n const updatedContent = updateMetroConfig(content, extension);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, metroConfigFile, updatedContent);\n logger(\n `${v} Updated ${colorizePath(metroConfigFile)} to include the Intlayer Metro plugin`\n );\n } else {\n logger(\n `${x} Could not automatically update ${colorizePath(metroConfigFile)}. Wrap your exported config with ${colorize('configMetroIntlayer', ANSIColors.MAGENTA)}: ${colorizePath(DocumentationRouter.ReactNativeAndExpo)}`,\n { level: 'warn' }\n );\n }\n }\n } else {\n const newMetroConfigFile = 'metro.config.js';\n await writeFileToRoot(\n rootDir,\n newMetroConfigFile,\n getMetroConfigTemplate(Boolean(allDeps.expo))\n );\n logger(\n `${v} Created ${colorizePath(newMetroConfigFile)} with the Intlayer Metro plugin`\n );\n }\n }\n\n // UPDATE PACKAGE.JSON DEV SCRIPT\n // Next.js >= 16 uses a bun-specific wrapper; backend frameworks wrap whatever\n // the existing dev script is. Both use `intlayer watch --with`.\n const backendIntlayerPackages = [\n 'express-intlayer',\n 'fastify-intlayer',\n 'adonis-intlayer',\n 'hono-intlayer',\n ];\n\n const devScript = packageJson.scripts?.dev;\n\n let newDevScript: string | undefined;\n\n if (\n devScript &&\n ((isNextJsProject && allDeps.next && isVersionAtLeast(allDeps.next, 16)) ||\n backendIntlayerPackages.some((pkg) => allDeps[pkg])) &&\n !devScript.includes('intlayer watch')\n ) {\n newDevScript = `intlayer watch --with '${devScript}'`;\n }\n\n if (newDevScript) {\n packageJson.scripts.dev = newDevScript;\n\n await writeFileToRoot(\n rootDir,\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n\n logger(\n `${v} Updated ${colorizePath('package.json')} dev script to run intlayer watch`\n );\n }\n\n // CHECK WEBPACK CONFIG\n const webpackConfigs = [\n 'webpack.config.js',\n 'webpack.config.ts',\n 'webpack.config.mjs',\n 'webpack.config.cjs',\n ];\n\n for (const file of webpackConfigs) {\n if (await exists(rootDir, file)) {\n hasAliasConfiguration = true;\n logger(\n `${v} Found ${colorizePath(\n file\n )}. Make sure to configure aliases manually or use the Intlayer Webpack plugin.`\n );\n break;\n }\n }\n\n const backendConfigPackages = [\n 'express',\n 'fastify',\n '@adonisjs/core',\n 'hono',\n ...backendIntlayerPackages,\n ];\n\n if (backendConfigPackages.some((pkg) => allDeps[pkg])) {\n hasAliasConfiguration = true;\n }\n\n if (!hasAliasConfiguration) {\n const configuration = getConfiguration({ baseDir: rootDir });\n const aliases = getAlias({ configuration });\n\n if (hasTsConfig && tsConfigFiles.length > 0) {\n const tsConfigPath =\n tsConfigFiles.find((file) => file === 'tsconfig.json') ||\n tsConfigFiles[0];\n\n if (tsConfigPath) {\n const tsConfigContent = await readFileFromRoot(rootDir, tsConfigPath);\n const config = parseJSONWithComments(tsConfigContent);\n\n config.compilerOptions ??= {};\n config.compilerOptions.paths ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n if (!config.compilerOptions.paths[alias]) {\n config.compilerOptions.paths[alias] = [path];\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n tsConfigPath,\n JSON.stringify(config, null, 2)\n );\n\n logger(\n `${v} Updated ${colorizePath(\n tsConfigPath\n )} to include Intlayer aliases`\n );\n }\n }\n } else {\n const jsConfigPath = 'jsconfig.json';\n\n if (await exists(rootDir, jsConfigPath)) {\n const jsConfigContent = await readFileFromRoot(rootDir, jsConfigPath);\n const config = parseJSONWithComments(jsConfigContent);\n\n config.compilerOptions ??= {};\n config.compilerOptions.paths ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n if (!config.compilerOptions.paths[alias]) {\n config.compilerOptions.paths[alias] = [path];\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n jsConfigPath,\n JSON.stringify(config, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(\n jsConfigPath\n )} to include Intlayer aliases`\n );\n }\n } else {\n packageJson.imports ??= {};\n\n let updated = false;\n\n Object.entries(aliases).forEach(([alias, path]) => {\n const importAlias = alias.replace('@', '#');\n const importPath = path.startsWith('.') ? path : `./${path}`;\n\n if (!packageJson.imports[importAlias]) {\n packageJson.imports[importAlias] = importPath;\n updated = true;\n }\n });\n\n if (updated) {\n await writeFileToRoot(\n rootDir,\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n logger(\n `${v} Updated ${colorizePath(\n packageJsonPath\n )} to include Intlayer imports`\n );\n }\n }\n }\n }\n\n // FRAMEWORK-SPECIFIC SCAFFOLDING\n // Sets up middleware/proxy and wraps the layout/page with the Intlayer\n // providers for the detected framework (Next.js App Router today). Idempotent\n // and non-destructive: it never overwrites user code it cannot safely\n // transform, skipping with guidance instead.\n //\n // Skipped entirely when a compat i18n library drives the app (i18next,\n // next-intl, vue-i18n, …): the app already owns its routing, providers and\n // layouts, and Intlayer only syncs its catalogs — restructuring routes or\n // injecting providers would break the existing setup.\n const hasCompatLibrary = Boolean(compatSyncConfig || compatVitePluginConfig);\n\n if (!options?.noFrameworkSetup && hasCompatLibrary) {\n logger(\n `${v} Compat i18n library detected — keeping the app structure untouched (no route restructure, no provider injection)`\n );\n }\n\n if (!options?.noFrameworkSetup && !hasCompatLibrary) {\n try {\n // Prefer the user's interactive choice, else the configured routing mode\n // (which itself defaults to `prefix-no-default`). Drives whether the\n // locale path segment is required (`prefix-all`) or optional.\n const routingMode =\n options?.routingMode ??\n getConfiguration({ baseDir: rootDir }).routing.mode;\n\n await setupFramework({\n rootDir,\n allDeps,\n packageManager,\n useTypeScript: hasTsConfig,\n routingMode,\n });\n } catch {\n logger(\n `${x} Framework-specific scaffolding failed. Your existing files were left untouched; follow the documentation to finish the setup.`,\n { level: 'warn' }\n );\n }\n }\n\n // FINAL SUCCESS MESSAGE\n logger(`${v} ${colorize('Intlayer init setup complete.', ANSIColors.GREEN)}`);\n logger([\n colorize('Next →', ANSIColors.MAGENTA),\n colorize(\n `Follow the instructions in the documentation to complete the setup:`,\n ANSIColors.GREY_LIGHT\n ),\n colorizePath(guideUrl),\n ]);\n\n // INTLAYER LSP — instruction for the AI agent running `intlayer init`.\n // The Intlayer Language Server (`@intlayer/lsp`) provides Go-to-Definition\n // from `useIntlayer` / `getIntlayer` keys to their `.content` files, for both\n // IDEs and AI agents. Setup is editor-specific (VS Code, Cursor, Windsurf,\n // Zed, Neovim, Claude Code, …), so we don't scaffold anything here — instead\n // we point to the doc and ask the agent to confirm the target platform.\n logger([\n colorize('Intlayer LSP →', ANSIColors.MAGENTA),\n colorize(\n 'The Intlayer Language Server is available via the `@intlayer/lsp` package. It lets IDEs and AI agents jump from `useIntlayer`/`getIntlayer` keys to their `.content` files.',\n ANSIColors.GREY_LIGHT\n ),\n colorize(\n 'Ask the user which platform/editor they want to enable it on (VS Code, Cursor, Windsurf, Zed, Neovim, Claude Code, …), then follow the matching setup instructions:',\n ANSIColors.GREY_LIGHT\n ),\n colorizePath(DocumentationRouter.LSP),\n ]);\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { __require } from "../../_virtual/_rolldown/runtime.mjs";
1
+ import { typescriptParser } from "../../utils/recastBabelParser.mjs";
2
2
  import { isModuleScopeBinding } from "./astImports.mjs";
3
3
  import * as recast from "recast";
4
4
 
@@ -58,7 +58,7 @@ const addEnvReferenceProperty = (objExpr, key, envVar) => {
58
58
  */
59
59
  const setIntlayerConfigRoutingMode = (content, extension, mode) => {
60
60
  if (extension === "json") return content.replace(/("mode"\s*:\s*)"(?:prefix-no-default|prefix-all|no-prefix|search-params)"/, `$1"${mode}"`);
61
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
61
+ const ast = recast.parse(content, { parser: typescriptParser });
62
62
  genericRecastVisit(ast, (objExpr) => {
63
63
  if (!isObjectExpression(objExpr)) return;
64
64
  const routingProperty = ensureObjectProperty(objExpr, "routing", b.objectExpression([]));
@@ -68,6 +68,32 @@ const setIntlayerConfigRoutingMode = (content, extension, mode) => {
68
68
  return recast.print(ast).code;
69
69
  };
70
70
  /**
71
+ * Sets `compiler.output` in an Intlayer configuration file to the given path
72
+ * template (the `{{variable}}` string form, e.g.
73
+ * `/locales/{{locale}}/{{key}}.content.json`). Idempotent: re-running with the
74
+ * same template produces identical output. Supports `.ts`, `.mjs`, `.js` and
75
+ * `.cjs` configs; JSON configs are supported too since the template is a plain
76
+ * string.
77
+ */
78
+ const setIntlayerConfigCompilerOutput = (content, extension, outputTemplate) => {
79
+ if (extension === "json") {
80
+ const parsed = JSON.parse(content);
81
+ parsed.compiler = {
82
+ ...parsed.compiler,
83
+ output: outputTemplate
84
+ };
85
+ return JSON.stringify(parsed, null, 2);
86
+ }
87
+ const ast = recast.parse(content, { parser: typescriptParser });
88
+ genericRecastVisit(ast, (objExpr) => {
89
+ if (!isObjectExpression(objExpr)) return;
90
+ const compilerProperty = ensureObjectProperty(objExpr, "compiler", b.objectExpression([]));
91
+ if (!isObjectExpression(compilerProperty.value)) return;
92
+ setObjectPropertyValue(compilerProperty.value, "output", b.stringLiteral(outputTemplate));
93
+ });
94
+ return recast.print(ast).code;
95
+ };
96
+ /**
71
97
  * Enables the Intlayer visual editor in a configuration file: sets
72
98
  * `editor.enabled` to `true` and wires `clientId` / `clientSecret` to the
73
99
  * `INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET` environment variables.
@@ -76,7 +102,7 @@ const setIntlayerConfigRoutingMode = (content, extension, mode) => {
76
102
  * (JSON cannot reference `process.env`).
77
103
  */
78
104
  const enableIntlayerEditorConfig = (content) => {
79
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
105
+ const ast = recast.parse(content, { parser: typescriptParser });
80
106
  genericRecastVisit(ast, (objExpr) => {
81
107
  if (!isObjectExpression(objExpr)) return;
82
108
  const editorProperty = ensureObjectProperty(objExpr, "editor", b.objectExpression([]));
@@ -152,19 +178,19 @@ const genericRecastVisit = (ast, updateConfigObject, callNames = ["defineConfig"
152
178
  });
153
179
  };
154
180
  const updateViteConfig = (content, extension) => {
155
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
181
+ const ast = recast.parse(content, { parser: typescriptParser });
156
182
  injectImport(ast, extension === "cjs" || content.includes("module.exports") && !content.includes("import "), "intlayer", "vite-intlayer");
157
183
  genericRecastVisit(ast, (obj) => updatePluginArray(obj, "plugins", "intlayer"));
158
184
  return recast.print(ast).code;
159
185
  };
160
186
  const updateAstroConfig = (content, extension) => {
161
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
187
+ const ast = recast.parse(content, { parser: typescriptParser });
162
188
  injectImport(ast, extension === "cjs" || content.includes("module.exports") && !content.includes("import "), "intlayer", "astro-intlayer");
163
189
  genericRecastVisit(ast, (obj) => updatePluginArray(obj, "integrations", "intlayer"));
164
190
  return recast.print(ast).code;
165
191
  };
166
192
  const updateNextConfig = (content, extension) => {
167
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
193
+ const ast = recast.parse(content, { parser: typescriptParser });
168
194
  injectImport(ast, extension === "cjs" || content.includes("module.exports"), "withIntlayer", "next-intlayer/server");
169
195
  recast.visit(ast, {
170
196
  visitExportDefaultDeclaration(path) {
@@ -200,7 +226,7 @@ const isImmediatelyInvokedFunction = (node) => n.CallExpression.check(node) && (
200
226
  */
201
227
  const updateMetroConfig = (content, extension) => {
202
228
  if (content.includes("react-native-intlayer")) return content;
203
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
229
+ const ast = recast.parse(content, { parser: typescriptParser });
204
230
  const isCJSFile = extension === "cjs" || content.includes("module.exports") && !content.includes("import ");
205
231
  const wrapperName = "configMetroIntlayerSync";
206
232
  const isWrappable = (node) => n.Expression.check(node) && !isImmediatelyInvokedFunction(node) && !(n.CallExpression.check(node) && n.Identifier.check(node.callee) && node.callee.name === wrapperName);
@@ -245,7 +271,7 @@ module.exports = (async () => {
245
271
  `;
246
272
  };
247
273
  const updateNuxtConfig = (content) => {
248
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
274
+ const ast = recast.parse(content, { parser: typescriptParser });
249
275
  const updateConfigObject = (objExpr) => {
250
276
  if (!objExpr || objExpr.type !== "ObjectExpression" && !n.ObjectExpression.check(objExpr)) return;
251
277
  let modulesProp = objExpr.properties.find((p) => {
@@ -272,7 +298,7 @@ const updateNuxtConfig = (content) => {
272
298
  * `@intlayer/vue-i18n/plugin` into the plugins array.
273
299
  */
274
300
  const updateViteConfigForVueI18n = (content, extension) => {
275
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
301
+ const ast = recast.parse(content, { parser: typescriptParser });
276
302
  injectImport(ast, extension === "cjs" || content.includes("module.exports") && !content.includes("import "), "vueI18nVitePlugin", "@intlayer/vue-i18n/plugin");
277
303
  genericRecastVisit(ast, (obj) => updatePluginArray(obj, "plugins", "vueI18nVitePlugin"));
278
304
  return recast.print(ast).code;
@@ -283,7 +309,7 @@ const updateViteConfigForVueI18n = (content, extension) => {
283
309
  * call to the `plugins` array.
284
310
  */
285
311
  const updateViteConfigForCompatPlugin = (content, extension, pluginConfig) => {
286
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
312
+ const ast = recast.parse(content, { parser: typescriptParser });
287
313
  injectImport(ast, extension === "cjs" || content.includes("module.exports") && !content.includes("import "), pluginConfig.pluginFunctionName, pluginConfig.pluginPackageSource);
288
314
  genericRecastVisit(ast, (obj) => updatePluginArray(obj, "plugins", pluginConfig.pluginFunctionName));
289
315
  return recast.print(ast).code;
@@ -298,7 +324,7 @@ const updateViteConfigForCompatPlugin = (content, extension, pluginConfig) => {
298
324
  * is found.
299
325
  */
300
326
  const replaceViteConfigPluginImportSource = (content, importName, fromPackageSource, toPackageSource) => {
301
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
327
+ const ast = recast.parse(content, { parser: typescriptParser });
302
328
  let changed = false;
303
329
  recast.visit(ast, { visitImportDeclaration(path) {
304
330
  const { source, specifiers } = path.node;
@@ -317,7 +343,7 @@ const replaceViteConfigPluginImportSource = (content, importName, fromPackageSou
317
343
  * wraps the default export / `module.exports` with a HOC call.
318
344
  */
319
345
  const wrapNextConfigWithHoc = (content, extension, hocFunctionName, pluginPackageSource) => {
320
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
346
+ const ast = recast.parse(content, { parser: typescriptParser });
321
347
  injectImport(ast, extension === "cjs" || content.includes("module.exports"), hocFunctionName, pluginPackageSource);
322
348
  recast.visit(ast, {
323
349
  visitExportDefaultDeclaration(path) {
@@ -343,7 +369,7 @@ const updateNextConfigForNextTranslate = (content, extension) => wrapNextConfigW
343
369
  * to the `modules` array.
344
370
  */
345
371
  const updateNuxtConfigForNuxtjsI18n = (content) => {
346
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
372
+ const ast = recast.parse(content, { parser: typescriptParser });
347
373
  const updateConfigObject = (objExpr) => {
348
374
  if (!objExpr || objExpr.type !== "ObjectExpression" && !n.ObjectExpression.check(objExpr)) return;
349
375
  let modulesProp = objExpr.properties.find((p) => {
@@ -377,7 +403,7 @@ const updateNextConfigForNextI18next = (content, extension) => wrapNextConfigWit
377
403
  * import is present.
378
404
  */
379
405
  const updateNextConfigForNextIntl = (content, extension) => {
380
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
406
+ const ast = recast.parse(content, { parser: typescriptParser });
381
407
  const isCJSFile = extension === "cjs" || content.includes("module.exports");
382
408
  let replacedExistingSource = false;
383
409
  recast.visit(ast, { visitImportDeclaration(path) {
@@ -435,7 +461,7 @@ const buildSyncCallNode = (syncConfig) => {
435
461
  const formatProperty = syncConfig.plugin === "po" ? "" : `format: '${syncConfig.format}', `;
436
462
  const splitKeysProperty = syncConfig.splitKeys ? ", splitKeys: true" : "";
437
463
  const snippet = `${functionName}({ ${formatProperty}source: (${paramDestructuring}) => \`${syncConfig.sourceTemplate}\`${splitKeysProperty} })`;
438
- return recast.parse(snippet, { parser: __require("recast/parsers/typescript") }).program.body[0].expression;
464
+ return recast.parse(snippet, { parser: typescriptParser }).program.body[0].expression;
439
465
  };
440
466
  /**
441
467
  * Injects or ensures `dictionary: { format: '<value>' }` exists in an object
@@ -465,7 +491,7 @@ const injectDictionaryFormat = (objExpr, format) => {
465
491
  * config file. Idempotent: skips when the plugin call is already present.
466
492
  */
467
493
  const updateIntlayerConfigWithSyncPlugin = (content, extension, syncConfig) => {
468
- const ast = recast.parse(content, { parser: __require("recast/parsers/typescript") });
494
+ const ast = recast.parse(content, { parser: typescriptParser });
469
495
  const isCJSFile = extension === "cjs" || content.includes("module.exports");
470
496
  const { functionName, packageSource } = getSyncPluginInfo(syncConfig);
471
497
  injectImport(ast, isCJSFile, functionName, packageSource);
@@ -495,5 +521,5 @@ const updateIntlayerConfigWithSyncPlugin = (content, extension, syncConfig) => {
495
521
  };
496
522
 
497
523
  //#endregion
498
- export { enableIntlayerEditorConfig, getMetroConfigTemplate, replaceViteConfigPluginImportSource, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n };
524
+ export { enableIntlayerEditorConfig, getMetroConfigTemplate, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n };
499
525
  //# sourceMappingURL=configManipulation.mjs.map