{"version":3,"file":"createModuleAugmentation.mjs","names":[],"sources":["../../../src/createType/createModuleAugmentation.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { basename, extname, join, relative } from 'node:path';\nimport { kebabCaseToCamelCase, normalizePath } from '@intlayer/config/utils';\nimport {\n  getDomainOrigin,\n  getRewriteRules,\n  isLocaleExclusiveOnDomain,\n} from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig, RoutingConfig } from '@intlayer/types/config';\nimport fg from 'fast-glob';\nimport { getPathHash } from '../utils';\nimport { writeFileIfChanged } from '../writeFileIfChanged';\n\nexport const getTypeName = (key: string): string =>\n  `${kebabCaseToCamelCase(key)}Content`;\n\n/** Returns lines like: [Locales.FRENCH]: 1; */\nconst formatLocales = (locales: Locale[]) =>\n  locales.map((locale) => `    \"${locale}\": 1;`).join('\\n');\n\n/**\n * Serializes the `url` rewrite rules as a type literal, so `getLocalizedPath`\n * and `getLocalizedUrl` can resolve a canonical path to its localized literal at\n * the type level. Returns an empty string when the project declares no rewrite —\n * the consuming types then localize every path to itself.\n *\n * Rules are emitted in their normalized form (`:param`, no locale prefix), which\n * is exactly what the runtime matches against.\n */\nexport const formatRewriteRules = (\n  rewrite: RoutingConfig['rewrite']\n): string => {\n  const rewriteRules = getRewriteRules(rewrite, 'url');\n\n  if (!rewriteRules?.rules?.length) return '';\n\n  const formattedRules = rewriteRules.rules\n    .map(({ canonical, localized }) => {\n      const formattedLocalized = Object.entries(localized)\n        .filter(([, pattern]) => typeof pattern === 'string')\n        .map(([locale, pattern]) => `'${locale}': '${pattern}'`)\n        .join('; ');\n\n      return `'${canonical}': { ${formattedLocalized} }`;\n    })\n    .join('; ');\n\n  return `; rewrite: { ${formattedRules} }`;\n};\n\n/**\n * Serializes the `routing.domains` map as a type literal, so `getLocalizedUrl`\n * and `getLocalizedPath` can resolve the origin of a locale — and the\n * suppression of its path prefix — at the type level. Returns an empty string\n * when the project maps no locale to a domain.\n *\n * Each entry carries the two facts the consuming types need, both computed with\n * the very helpers the runtime uses:\n * - `origin`: the normalized origin ({@link getDomainOrigin}), prepended to the\n *   localized path when the target locale lives on another domain.\n * - `exclusive`: whether the locale is the only one on that hostname\n *   ({@link isLocaleExclusiveOnDomain}), in which case the domain identifies the\n *   locale and no path prefix is emitted.\n */\nexport const formatDomains = (domains: RoutingConfig['domains']): string => {\n  const domainEntries = Object.entries(domains ?? {}).filter(\n    ([, domain]) => typeof domain === 'string' && domain.length > 0\n  ) as [string, string][];\n\n  if (!domainEntries.length) return '';\n\n  const formattedDomains = domainEntries\n    .map(\n      ([locale, domain]) =>\n        `'${locale}': { origin: '${getDomainOrigin(domain)}'; exclusive: ${isLocaleExclusiveOnDomain(locale, domains)} }`\n    )\n    .join('; ');\n\n  return `; domains: { ${formattedDomains} }`;\n};\n\nconst zodToTsString = (schema: any): string => {\n  if (!schema) return 'any';\n\n  // Support both real Zod objects (_def) and serialized versions (def or nested)\n  const def = schema._def ?? schema.def ?? schema;\n\n  // Handle serialized type names (sometimes 'type' instead of 'typeName')\n  const typeName = def.typeName ?? def.type;\n\n  switch (typeName) {\n    case 'ZodString':\n    case 'string':\n      return 'string';\n    case 'ZodNumber':\n    case 'number':\n      return 'number';\n    case 'ZodBoolean':\n    case 'boolean':\n      return 'boolean';\n    case 'ZodNull':\n    case 'null':\n      return 'null';\n    case 'ZodUndefined':\n    case 'undefined':\n      return 'undefined';\n    case 'ZodArray':\n    case 'array':\n      return `${zodToTsString(def.type ?? def.element)}[]`;\n    case 'ZodObject':\n    case 'object': {\n      const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n      if (!shape) return 'Record<string, any>';\n\n      const entries = Object.entries(shape)\n        .map(([k, v]) => `      \"${k}\": ${zodToTsString(v)};`)\n        .join('\\n');\n      return `{\\n${entries}\\n    }`;\n    }\n    case 'ZodOptional':\n    case 'optional':\n      return `${zodToTsString(def.innerType ?? def.wrapped)} | undefined`;\n    case 'ZodNullable':\n    case 'nullable':\n      return `${zodToTsString(def.innerType ?? def.wrapped)} | null`;\n    case 'ZodUnion':\n    case 'union': {\n      const options = def.options ?? [];\n      return options.map(zodToTsString).join(' | ');\n    }\n    case 'ZodIntersection':\n    case 'intersection':\n      return `${zodToTsString(def.left)} & ${zodToTsString(def.right)}`;\n    case 'ZodEnum':\n    case 'enum': {\n      const values = def.values ?? [];\n      return values.map((v: string) => `\"${v}\"`).join(' | ');\n    }\n    case 'ZodLiteral':\n    case 'literal': {\n      const value = def.value;\n      return typeof value === 'string' ? `\"${value}\"` : String(value);\n    }\n    default:\n      return 'any';\n  }\n};\n\ntype ZodToTsFns = {\n  zodToTs: (schema: any, opts?: any) => { node: any };\n  printNode: (node: any) => string;\n  createAuxiliaryTypeStore: () => any;\n};\n\n/** Generate the content of the module augmentation file */\nconst generateTypeIndexContent = (\n  typeFiles: string[],\n  configuration: IntlayerConfig,\n  zodToTsFns: ZodToTsFns | null\n): string => {\n  const { internationalization, system, editor, routing } = configuration;\n  const { moduleAugmentationDir } = system;\n  const { enabled } = editor;\n  const { locales, requiredLocales, strictMode, defaultLocale } =\n    internationalization;\n\n  let fileContent = 'import \"intlayer\";\\n';\n\n  // Build dictionary refs\n  const dictionariesRef = typeFiles.map((dictionaryPath) => ({\n    relativePath: `./${normalizePath(relative(moduleAugmentationDir, dictionaryPath))}`,\n    id: basename(dictionaryPath, extname(dictionaryPath)),\n    hash: `_${getPathHash(dictionaryPath)}`,\n  }));\n\n  // Import all dictionaries\n  for (const dictionary of dictionariesRef) {\n    fileContent += `import ${dictionary.hash} from '${dictionary.relativePath}';\\n`;\n  }\n  fileContent += '\\n';\n\n  // Dictionary map entries (id: typeof <hash>)\n  const formattedDictionaryMap: string = dictionariesRef\n    .map((dictionary) => `    \"${dictionary.id}\": typeof ${dictionary.hash};`)\n    .join('\\n');\n\n  // Ensure required ⊆ declared; if empty, default required = declared\n  const declared = locales;\n  const requiredSanitized = requiredLocales?.length\n    ? requiredLocales.filter((requiredLocales) =>\n        declared.includes(requiredLocales)\n      )\n    : declared;\n\n  const formattedDeclaredLocales = formatLocales(declared);\n  const formattedRequiredLocales = formatLocales(requiredSanitized);\n\n  // Build schema registry\n  const schemas = configuration.schemas ?? {};\n  const formattedSchemas = Object.entries(schemas)\n    .map(([key, schema]) => {\n      let typeStr = 'any';\n\n      if (schema) {\n        try {\n          if (zodToTsFns) {\n            const { node } = zodToTsFns.zodToTs(schema, {\n              auxiliaryTypeStore: zodToTsFns.createAuxiliaryTypeStore(),\n            });\n            // 133 is the kind for AnyKeyword in TypeScript\n            if ((node as any).kind !== 133) {\n              typeStr = zodToTsFns.printNode(node);\n            } else {\n              typeStr = zodToTsString(schema);\n            }\n          } else {\n            typeStr = zodToTsString(schema);\n          }\n        } catch (_e) {\n          // Fallback to custom string generator\n          typeStr = zodToTsString(schema);\n        }\n      }\n      return `    \"${key}\": ${typeStr};`;\n    })\n    .join('\\n');\n\n  // Choose strict mode registry key\n  const strictKey =\n    strictMode === 'strict'\n      ? 'strict'\n      : strictMode === 'inclusive'\n        ? 'inclusive'\n        : 'loose';\n\n  /**\n   * Module augmentation that ONLY adds keys to registries.\n   * No types/aliases redefined here—avoids merge conflicts.\n   */\n  fileContent += `declare module 'intlayer' {\\n`;\n  // Dictionaries registry\n  fileContent += `  interface __DictionaryRegistry {\\n${formattedDictionaryMap}\\n  }\\n\\n`;\n  // Locales registries\n  fileContent += `  interface __DeclaredLocalesRegistry {\\n${formattedDeclaredLocales}\\n  }\\n\\n`;\n  fileContent += `  interface __RequiredLocalesRegistry {\\n${formattedRequiredLocales}\\n  }\\n\\n`;\n  // Schema registry\n  fileContent += `  interface __SchemaRegistry {\\n${formattedSchemas}\\n  }\\n\\n`;\n  // Resolved strict mode (narrow the literal at build time)\n  fileContent += `  interface __StrictModeRegistry { mode: '${strictKey}' }\\n\\n`;\n  // Editor registry\n  fileContent += `  interface __EditorRegistry { enabled : ${enabled} }\\n\\n`;\n  // Routing registry (mode + defaultLocale narrowed to literals, rewrite rules\n  // and domain map serialized as type literals)\n  const routingMode = routing?.mode ?? 'prefix-no-default';\n  const formattedRewriteRules = formatRewriteRules(routing?.rewrite);\n  const formattedDomains = formatDomains(routing?.domains);\n  fileContent += `  interface __RoutingRegistry { mode: '${routingMode}'; defaultLocale: '${defaultLocale}'${formattedRewriteRules}${formattedDomains} }\\n`;\n  fileContent += `}\\n`;\n\n  return fileContent;\n};\n\n/** Generate the index file merging all the types */\nexport const createModuleAugmentation = async (\n  configuration: IntlayerConfig\n) => {\n  const { moduleAugmentationDir, typesDir } = configuration.system;\n\n  await mkdir(moduleAugmentationDir, { recursive: true });\n\n  const dictionariesTypesDefinitions: string[] = await fg(\n    normalizePath(`${typesDir}/*.ts`),\n    { ignore: ['**/*.d.ts'] }\n  );\n\n  let zodToTsFns: ZodToTsFns | null = null;\n\n  const hasSchemas = Object.keys(configuration.schemas ?? {}).length > 0;\n\n  // zod-to-ts drags in the whole `typescript` package (~300ms import), so\n  // only load it when there are schemas to convert.\n  if (hasSchemas) {\n    try {\n      const mod = await import('zod-to-ts');\n      zodToTsFns = {\n        zodToTs: mod.zodToTs,\n        printNode: mod.printNode,\n        createAuxiliaryTypeStore: mod.createAuxiliaryTypeStore,\n      };\n    } catch {\n      // typescript peer dep not installed (plain JS project), use fallback\n    }\n  }\n\n  const tsContent = generateTypeIndexContent(\n    dictionariesTypesDefinitions,\n    configuration,\n    zodToTsFns\n  );\n\n  const tsFilePath = join(moduleAugmentationDir, 'intlayer.d.ts');\n  await writeFileIfChanged(tsFilePath, tsContent);\n};\n"],"mappings":"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"}