@intlayer/babel 9.5.10 → 9.5.12

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 (44) hide show
  1. package/dist/cjs/analyzeContentUsage.cjs +54 -26
  2. package/dist/cjs/analyzeContentUsage.cjs.map +1 -1
  3. package/dist/cjs/babel-plugin-intlayer-extract.cjs +11 -1
  4. package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
  5. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +39 -18
  6. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
  7. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +11 -1
  8. package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
  9. package/dist/cjs/babel-plugin-intlayer-purge.cjs +2 -0
  10. package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
  11. package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
  12. package/dist/cjs/staticAstReaders.cjs +96 -0
  13. package/dist/cjs/staticAstReaders.cjs.map +1 -1
  14. package/dist/cjs/transformers.cjs +36 -7
  15. package/dist/cjs/transformers.cjs.map +1 -1
  16. package/dist/esm/analyzeContentUsage.mjs +55 -27
  17. package/dist/esm/analyzeContentUsage.mjs.map +1 -1
  18. package/dist/esm/babel-plugin-intlayer-extract.mjs +11 -1
  19. package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
  20. package/dist/esm/babel-plugin-intlayer-field-rename.mjs +40 -19
  21. package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
  22. package/dist/esm/babel-plugin-intlayer-optimize.mjs +11 -1
  23. package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
  24. package/dist/esm/babel-plugin-intlayer-purge.mjs +2 -0
  25. package/dist/esm/babel-plugin-intlayer-purge.mjs.map +1 -1
  26. package/dist/esm/getExtractPluginOptions.mjs +1 -1
  27. package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
  28. package/dist/esm/staticAstReaders.mjs +94 -1
  29. package/dist/esm/staticAstReaders.mjs.map +1 -1
  30. package/dist/esm/transformers.mjs +36 -7
  31. package/dist/esm/transformers.mjs.map +1 -1
  32. package/dist/types/analyzeContentUsage.d.ts +6 -1
  33. package/dist/types/analyzeContentUsage.d.ts.map +1 -1
  34. package/dist/types/babel-plugin-intlayer-extract.d.ts +8 -22
  35. package/dist/types/babel-plugin-intlayer-extract.d.ts.map +1 -1
  36. package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  37. package/dist/types/babel-plugin-intlayer-optimize.d.ts +8 -112
  38. package/dist/types/babel-plugin-intlayer-optimize.d.ts.map +1 -1
  39. package/dist/types/babel-plugin-intlayer-purge.d.ts.map +1 -1
  40. package/dist/types/staticAstReaders.d.ts +41 -0
  41. package/dist/types/staticAstReaders.d.ts.map +1 -1
  42. package/dist/types/transformers.d.ts +8 -1
  43. package/dist/types/transformers.d.ts.map +1 -1
  44. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-field-rename.cjs","names":["CHAINABLE_RUNTIME_METHOD_NAMES","NATIVE_CALLER_NAME_SET","unwrapAwait"],"sources":["../../src/babel-plugin-intlayer-field-rename.ts"],"sourcesContent":["import type { NodePath, PluginObject } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport {\n CHAINABLE_RUNTIME_METHOD_NAMES,\n NATIVE_CALLER_NAME_SET,\n type NestedRenameEntry,\n type NestedRenameMap,\n type PruneContext,\n unwrapAwait,\n} from './babel-plugin-intlayer-usage-analyzer';\n\n// ── Field-name helpers ────────────────────────────────────────────────────────\n\n/**\n * Intlayer internal property names that must never be used as short-name\n * targets. These appear inside content-node values (e.g. `{ nodeType:\n * \"translation\", … }`) and are read by the intlayer runtime.\n */\nconst RESERVED_CONTENT_FIELD_NAMES = new Set(['nodeType']);\n\n/** Alphabet used to derive short field aliases (`a`, `b`, …, `aa`, `ab`, …). */\nconst SHORT_NAME_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n/**\n * Converts a zero-based index to a short alphabetic identifier.\n * 0 → 'a', 1 → 'b', …, 25 → 'z', 26 → 'aa', 27 → 'ab', …\n */\nexport const generateShortFieldName = (index: number): string => {\n if (!Number.isInteger(index) || index < 0) {\n throw new RangeError(\n `generateShortFieldName expects a non-negative integer index, received: ${index}`\n );\n }\n\n const remainder = index % SHORT_NAME_ALPHABET.length;\n const quotient = Math.floor(index / SHORT_NAME_ALPHABET.length);\n\n return quotient === 0 && SHORT_NAME_ALPHABET[remainder]\n ? SHORT_NAME_ALPHABET[remainder]\n : generateShortFieldName(quotient - 1) + SHORT_NAME_ALPHABET[remainder];\n};\n\n/**\n * Recursively builds a `NestedRenameMap` from a compiled dictionary content\n * value by traversing the intlayer node structure.\n *\n * Rules:\n * - If the value has `nodeType: 'translation'`, user-defined fields live\n * inside `translation[locale]`. Recurse into the first locale's value.\n * - All other intlayer runtime nodes (enumeration, condition, gender, …) are\n * treated as leaves — their internal keys must never be renamed.\n * - Arrays produce an empty children map. Array elements are not traversed\n * because consumers may access them via `.map()` / `.filter()` callbacks,\n * which the source-code rename walk cannot enter. Renaming element fields\n * in the JSON without the matching source-code rename would produce\n * mismatched key names and runtime crashes.\n * The `[0]` pass-through in `walkRenameChain` is preserved so that direct\n * indexed access (`field[0].sub`) silently terminates at the empty children\n * map without breaking anything.\n * - Plain objects are user-defined records: ALL non-reserved keys are renamed\n * with short alphabetic aliases (a, b, c, …) and each value is recursed into.\n * - Primitives produce an empty map (no further renaming).\n *\n * The rename map is built from ALL user-defined fields (not just consumed ones).\n * Both the JSON rename and the source-code rename use the same map, so the\n * short names are always consistent regardless of which fields are pruned.\n *\n * @param contentValue - The dictionary content value to analyse.\n */\nexport const buildNestedRenameMapFromContent = (\n contentValue: unknown\n): NestedRenameMap => {\n if (\n !contentValue ||\n typeof contentValue !== 'object' ||\n Array.isArray(contentValue)\n ) {\n return new Map();\n }\n\n const record = contentValue as Record<string, unknown>;\n\n // Any object with `nodeType: string` is an intlayer runtime node.\n if (typeof record.nodeType === 'string') {\n // Translation node: user-defined fields live inside translation[locale].\n if (\n record.nodeType === 'translation' &&\n record.translation &&\n typeof record.translation === 'object' &&\n !Array.isArray(record.translation)\n ) {\n const firstLocaleValue = Object.values(\n record.translation as Record<string, unknown>\n )[0];\n return buildNestedRenameMapFromContent(firstLocaleValue);\n }\n\n // All other intlayer nodes (enumeration, pluralization, conditions, …)\n // resolve to a single value at runtime through a call the source-code\n // rename walk cannot traverse (e.g. `content.myEnum(count)`), and the\n // JSON renamers only descend into translation nodes. Treat them as\n // leaves so the source and JSON sides always stay consistent.\n return new Map();\n }\n\n // Exclude React elements from being treated as user-defined records.\n // JSX elements in the compiled JSON have a $$typeof property (usually Symbol(react.element)).\n if (\n record.$$typeof ||\n (record.type && record.props && Object.hasOwn(record, 'ref'))\n ) {\n return new Map();\n }\n\n // User-defined record: rename ALL non-reserved keys with stable alphabetic\n // aliases sorted alphabetically so the mapping is deterministic.\n const sortedKeys = Object.keys(record)\n .filter((key) => !RESERVED_CONTENT_FIELD_NAMES.has(key))\n .sort();\n\n const renameMap: NestedRenameMap = new Map();\n\n for (let i = 0; i < sortedKeys.length; i++) {\n const key = sortedKeys[i];\n\n if (!key) continue;\n\n const children = buildNestedRenameMapFromContent(record[key]);\n\n renameMap.set(key, { shortName: generateShortFieldName(i), children });\n }\n\n return renameMap;\n};\n\n/**\n * Walks `fieldPath` through a {@link NestedRenameMap} and returns the entry at\n * the final path segment, or `undefined` when any segment is missing (e.g. the\n * path crosses an array or leaf value whose children are not mapped).\n *\n * Used to locate the rename entry of an opaquely-consumed content value so its\n * children map can be cleared before the JSON rename is applied.\n *\n * @param renameMap - The root rename map to walk.\n * @param fieldPath - Original (pre-rename) field names from the content root.\n */\nexport const getNestedRenameEntryAtPath = (\n renameMap: NestedRenameMap,\n fieldPath: readonly string[]\n): NestedRenameEntry | undefined => {\n let currentRenameMap = renameMap;\n let renameEntry: NestedRenameEntry | undefined;\n\n for (const fieldName of fieldPath) {\n renameEntry = currentRenameMap.get(fieldName);\n if (!renameEntry) return undefined;\n currentRenameMap = renameEntry.children;\n }\n\n return renameEntry;\n};\n\n// ── Serialisation for non-Babel consumers ─────────────────────────────────────\n\n/**\n * JSON-serialisable form of a {@link NestedRenameEntry}.\n *\n * Mirrors `FieldRenameNode` in the `@intlayer/swc` crate — both sides must stay\n * in sync.\n */\nexport type SerializedFieldRenameEntry = {\n /** Short alphabetic alias the field is renamed to (`'a'`, `'b'`, …). */\n shortName: string;\n /** Rename table of the fields nested inside this one. */\n children: SerializedFieldRenameMap;\n};\n\n/** JSON-serialisable form of a {@link NestedRenameMap}. */\nexport type SerializedFieldRenameMap = Record<\n string,\n SerializedFieldRenameEntry\n>;\n\n/** Recursively converts a {@link NestedRenameMap} to its serialisable form. */\nconst serializeNestedRenameMap = (\n renameMap: NestedRenameMap\n): SerializedFieldRenameMap => {\n const serialized: SerializedFieldRenameMap = {};\n\n for (const [fieldName, renameEntry] of renameMap) {\n serialized[fieldName] = {\n shortName: renameEntry.shortName,\n children: serializeNestedRenameMap(renameEntry.children),\n };\n }\n\n return serialized;\n};\n\n/**\n * Converts the field-rename tables of a {@link PruneContext} into a plain JSON\n * object, keyed by dictionary key.\n *\n * Consumed by bundler integrations that cannot run the Babel rename plugin and\n * must forward the tables to another transformer — currently the `@intlayer/swc`\n * Wasm plugin used by Next.js, which rewrites the source accesses itself.\n *\n * Dictionaries flagged as structural edge cases are omitted: the JSON pipeline\n * leaves them untouched, so their source accesses must stay untouched too.\n * Empty tables are omitted as well, so the result is empty when there is\n * nothing to rename.\n */\nexport const serializeFieldRenameMap = (\n pruneContext: PruneContext\n): Record<string, SerializedFieldRenameMap> => {\n const serialized: Record<string, SerializedFieldRenameMap> = {};\n\n for (const [\n dictionaryKey,\n renameMap,\n ] of pruneContext.dictionaryKeyToFieldRenameMap) {\n if (renameMap.size === 0) continue;\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) continue;\n\n serialized[dictionaryKey] = serializeNestedRenameMap(renameMap);\n }\n\n return serialized;\n};\n\n// ── Field-rename Babel plugin ─────────────────────────────────────────────────\n\n/**\n * Walks a MemberExpression chain starting from `startPath`, renaming each\n * property found in `currentRenameMap` at the corresponding nesting level.\n *\n * Numeric computed accesses (array indices such as `[0]`, `[1]`) are treated\n * as transparent pass-throughs: the rename map is kept unchanged and the walk\n * continues past the index. This means `content.field[0].sub` is handled\n * correctly — `field` and `sub` are both renamed while `[0]` is left intact.\n */\nconst walkRenameChain = (\n babelTypes: typeof BabelTypes,\n startPath: NodePath<BabelTypes.Node>,\n currentRenameMap: NestedRenameMap\n): {\n finalPath: NodePath<BabelTypes.Node>;\n finalRenameMap: NestedRenameMap;\n} => {\n let refPath: NodePath<BabelTypes.Node> = startPath;\n let renameMap = currentRenameMap;\n\n while (true) {\n const parentPath = refPath.parentPath;\n if (!parentPath) break;\n\n const parentNode = parentPath.node;\n\n if (\n (!babelTypes.isMemberExpression(parentNode) &&\n !babelTypes.isOptionalMemberExpression(parentNode)) ||\n (parentNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n break;\n }\n\n const memberNode = parentNode as BabelTypes.MemberExpression;\n\n // Numeric index access ([0], [1], …): advance past the array accessor\n // without touching the rename map. The next iteration will attempt to\n // rename the property that follows the index.\n if (\n memberNode.computed &&\n babelTypes.isNumericLiteral(memberNode.property)\n ) {\n refPath = parentPath;\n continue;\n }\n\n // Nothing left to rename at this level — stop.\n if (renameMap.size === 0) break;\n\n let fieldName: string | undefined;\n\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n fieldName = memberNode.property.name;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n fieldName = memberNode.property.value;\n } else {\n break; // dynamic computed key – stop\n }\n\n const renameEntry = renameMap.get(fieldName);\n if (!renameEntry) break; // not in map – stop\n\n // Apply the rename\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n memberNode.property.name = renameEntry.shortName;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n memberNode.property.value = renameEntry.shortName;\n }\n\n refPath = parentPath;\n renameMap = renameEntry.children;\n }\n\n return { finalPath: refPath, finalRenameMap: renameMap };\n};\n\n/**\n * Renames the properties of a destructuring `ObjectPattern` using `renameMap`,\n * recursing into nested patterns and following the references of bound local\n * variables.\n *\n * Handled property shapes:\n *\n * { fieldA } → { shortA: fieldA }\n * { fieldA: localVar } → { shortA: localVar }\n * { fieldA = fallback } → { shortA: fieldA = fallback }\n * { fieldA: { nested } } → { shortA: { shortN: nested } }\n * { ['fieldA']: x } → { ['shortA']: x }\n * { [dynamicKey]: x } → left untouched (dynamic key – not renamable)\n *\n * @param babelTypes - Babel types helper.\n * @param objectPattern - The destructuring pattern to rename.\n * @param scopePath - A path whose scope resolves the pattern's bindings.\n * @param renameMap - Rename table for the current nesting level.\n */\nconst renameObjectPatternProperties = (\n babelTypes: typeof BabelTypes,\n objectPattern: BabelTypes.ObjectPattern,\n scopePath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n for (const property of objectPattern.properties) {\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Computed keys: a static string key ({ ['title']: x }) is renamable in\n // place; any other computed key is dynamic and must be left untouched —\n // replacing it with an identifier would create a variable reference.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n continue;\n }\n\n const keyName = babelTypes.isIdentifier(property.key)\n ? property.key.name\n : babelTypes.isStringLiteral(property.key)\n ? property.key.value\n : null;\n if (!keyName) continue;\n\n const renameEntry = renameMap.get(keyName);\n if (!renameEntry) continue;\n\n if (property.computed) {\n // { ['fieldA']: x } → { ['shortA']: x }\n (property.key as BabelTypes.StringLiteral).value = renameEntry.shortName;\n } else {\n // { fieldA } → { shortA: fieldA }\n // { fieldA: localVar } → { shortA: localVar }\n if (property.shorthand) {\n property.shorthand = false;\n }\n property.key = babelTypes.identifier(renameEntry.shortName);\n }\n\n if (renameEntry.children.size === 0) continue;\n\n // A default value ({ fieldA = fallback }) wraps the actual binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n // Nested pattern: const { fieldA: { nested } } = … — rename its keys\n // with this entry's children map.\n if (babelTypes.isObjectPattern(bindingTarget)) {\n renameObjectPatternProperties(\n babelTypes,\n bindingTarget,\n scopePath,\n renameEntry.children\n );\n continue;\n }\n\n // Identifier binding: recursively walk references to the local variable.\n if (babelTypes.isIdentifier(bindingTarget)) {\n const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);\n if (!localVarBinding) continue;\n\n for (const nestedRefPath of localVarBinding.referencePaths) {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n nestedRefPath,\n renameEntry.children\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n }\n }\n }\n};\n\n/**\n * Walks an object-destructuring assignment whose right-hand side is `refPath`,\n * renaming each destructured key that is found in `renameMap`.\n *\n * Handles the \"secondary destructuring\" pattern that `walkRenameChain` cannot\n * reach because the reference is not a MemberExpression:\n *\n * const { webhooksSection } = useIntlayer('build-settings');\n * const { modal, validationErrors } = webhooksSection;\n * → const { a: modal, b: validationErrors } = webhooksSection;\n *\n * After renaming each key, {@link renameObjectPatternProperties} recursively\n * walks references to the newly-bound local variables, calling both\n * `walkRenameChain` (for subsequent member-access chains like\n * `validationErrors.invalidUrl`) and this function again (for further levels\n * of secondary destructuring).\n */\nconst walkObjectDestructuring = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const parentNode = refPath.parent;\n\n // Only handle: const { a, b } = refVar\n if (\n !babelTypes.isVariableDeclarator(parentNode) ||\n !babelTypes.isObjectPattern(parentNode.id) ||\n parentNode.init !== refPath.node\n ) {\n return;\n }\n\n renameObjectPatternProperties(babelTypes, parentNode.id, refPath, renameMap);\n};\n\n/**\n * Renames every field access reachable from `rootPath`, whose value is the\n * dictionary content root.\n *\n * Combines the three ways a content root is consumed: a member-access chain,\n * a destructuring assignment, and a chainable runtime helper such as\n * `.onChange(cb)`.\n */\nconst renameContentConsumers = (\n babelTypes: typeof BabelTypes,\n rootPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n rootPath,\n renameMap\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n renameChainedRuntimeCall(babelTypes, finalPath, finalRenameMap);\n};\n\n/**\n * Handles `content.onChange(cb)` — a runtime subscription rather than a field\n * access (see {@link CHAINABLE_RUNTIME_METHOD_NAMES}).\n *\n * `walkRenameChain` stops at `onChange` because it is absent from the rename\n * map, which would leave the callback body reading the original field names\n * while the compiled JSON has already been renamed. This restarts the rename\n * walk on both sides of the call:\n *\n * - the callback's first parameter receives the same content root, so its\n * accesses are renamed with the same map;\n * - the helper returns the content object, so the chain continues past it.\n *\n * @param refPath - Path whose value is the content root (the object the\n * chainable method would be called on).\n */\nconst renameChainedRuntimeCall = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const memberPath = refPath.parentPath;\n if (!memberPath) return;\n\n const memberNode = memberPath.node;\n if (\n (!babelTypes.isMemberExpression(memberNode) &&\n !babelTypes.isOptionalMemberExpression(memberNode)) ||\n (memberNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n return;\n }\n\n const propertyNode = (memberNode as BabelTypes.MemberExpression).property;\n const methodName = (memberNode as BabelTypes.MemberExpression).computed\n ? babelTypes.isStringLiteral(propertyNode)\n ? propertyNode.value\n : undefined\n : babelTypes.isIdentifier(propertyNode)\n ? propertyNode.name\n : undefined;\n\n if (!methodName || !CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;\n\n const callPath = memberPath.parentPath;\n if (!callPath) return;\n if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) {\n return;\n }\n if ((callPath.node as BabelTypes.CallExpression).callee !== memberNode) {\n return;\n }\n\n const argumentPaths = callPath.get(\n 'arguments'\n ) as NodePath<BabelTypes.Node>[];\n\n for (const argumentPath of argumentPaths) {\n if (\n !argumentPath.isArrowFunctionExpression() &&\n !argumentPath.isFunctionExpression()\n ) {\n continue;\n }\n\n const [firstParameterPath] = argumentPath.get(\n 'params'\n ) as NodePath<BabelTypes.Node>[];\n if (!firstParameterPath) continue;\n\n // ({ title }) => … — destructured directly in the parameter list.\n if (firstParameterPath.isObjectPattern()) {\n renameObjectPatternProperties(\n babelTypes,\n firstParameterPath.node,\n argumentPath,\n renameMap\n );\n continue;\n }\n\n // (content) => … — rename each access on the parameter.\n if (!firstParameterPath.isIdentifier()) continue;\n\n const parameterBinding = argumentPath.scope.getBinding(\n firstParameterPath.node.name\n );\n if (!parameterBinding) continue;\n\n for (const parameterRefPath of parameterBinding.referencePaths) {\n renameContentConsumers(babelTypes, parameterRefPath, renameMap);\n }\n }\n\n // The helper returns the content object itself, so keep walking past it —\n // both when the result is used inline and when it is stored in a variable\n // (`const content = useIntlayer('key').onChange(cb)`).\n renameContentConsumers(babelTypes, callPath, renameMap);\n\n const declaratorNode = callPath.parent;\n if (\n babelTypes.isVariableDeclarator(declaratorNode) &&\n babelTypes.isIdentifier(declaratorNode.id) &&\n declaratorNode.init === callPath.node\n ) {\n const resultBinding = callPath.scope.getBinding(declaratorNode.id.name);\n for (const resultRefPath of resultBinding?.referencePaths ?? []) {\n renameContentConsumers(babelTypes, resultRefPath, renameMap);\n }\n }\n};\n\n/**\n * Collects the local aliases under which `useIntlayer` / `getIntlayer` are\n * imported in the given program (e.g. `import { useIntlayer as useI } …`\n * yields `useI` → `useIntlayer`).\n *\n * Import declarations can only appear at the top level of a module, so the\n * program body is scanned directly instead of traversing the whole AST.\n */\nconst collectIntlayerCallerLocalNames = (\n babelTypes: typeof BabelTypes,\n programNode: BabelTypes.Program\n): Map<string, string> => {\n const intlayerCallerLocalNameMap = new Map<string, string>();\n\n for (const statement of programNode.body) {\n if (!babelTypes.isImportDeclaration(statement)) continue;\n\n for (const importSpecifier of statement.specifiers) {\n if (!babelTypes.isImportSpecifier(importSpecifier)) continue;\n\n const importedName = babelTypes.isIdentifier(importSpecifier.imported)\n ? importSpecifier.imported.name\n : importSpecifier.imported.value;\n\n if (NATIVE_CALLER_NAME_SET.has(importedName)) {\n intlayerCallerLocalNameMap.set(\n importSpecifier.local.name,\n importedName\n );\n }\n }\n }\n\n return intlayerCallerLocalNameMap;\n};\n\n/**\n * Rewrites dictionary content field accesses in the given program to the\n * short aliases defined in `pruneContext.dictionaryKeyToFieldRenameMap`.\n *\n * Handled patterns (mirrors the usage analyser):\n *\n * const { fieldA, fieldB } = useIntlayer('key')\n * → const { shortA: fieldA, shortB: fieldB } = useIntlayer('key')\n *\n * useIntlayer('key').fieldA\n * → useIntlayer('key').shortA\n *\n * const result = useIntlayer('key'); result.fieldA\n * → const result = useIntlayer('key'); result.shortA\n *\n * const { fieldA } = useIntlayer('key');\n * const { nested } = fieldA; // secondary destructuring\n * → const { shortA: fieldA } = useIntlayer('key');\n * const { shortN: nested } = fieldA;\n *\n * Exposed as a standalone function so that both\n * {@link makeFieldRenameBabelPlugin} and `intlayerMinifyBabelPlugin` can\n * invoke it from their own `Program.exit` visitors.\n */\nexport const renameIntlayerFieldAccesses = (\n babelTypes: typeof BabelTypes,\n programPath: NodePath<BabelTypes.Program>,\n pruneContext: PruneContext\n): void => {\n if (pruneContext.dictionaryKeyToFieldRenameMap.size === 0) return;\n\n const intlayerCallerLocalNameMap = collectIntlayerCallerLocalNames(\n babelTypes,\n programPath.node\n );\n if (intlayerCallerLocalNameMap.size === 0) return;\n\n // Visit all useIntlayer / getIntlayer call-sites and rename field accesses\n programPath.traverse({\n CallExpression: (callExpressionPath) => {\n const calleeNode = callExpressionPath.node.callee;\n let localCallerName: string | undefined;\n\n if (babelTypes.isIdentifier(calleeNode)) {\n localCallerName = calleeNode.name;\n } else if (\n babelTypes.isMemberExpression(calleeNode) &&\n babelTypes.isIdentifier(calleeNode.property)\n ) {\n localCallerName = calleeNode.property.name;\n }\n\n if (!localCallerName || !intlayerCallerLocalNameMap.has(localCallerName))\n return;\n\n const callArguments = callExpressionPath.node.arguments;\n if (callArguments.length === 0) return;\n\n const firstArgument = callArguments[0];\n let dictionaryKey: string | undefined;\n\n if (babelTypes.isStringLiteral(firstArgument)) {\n dictionaryKey = firstArgument.value;\n } else if (\n babelTypes.isTemplateLiteral(firstArgument) &&\n firstArgument.expressions.length === 0 &&\n firstArgument.quasis.length === 1 &&\n firstArgument.quasis[0]\n ) {\n dictionaryKey =\n firstArgument.quasis[0].value.cooked ??\n firstArgument.quasis[0].value.raw;\n }\n\n if (!dictionaryKey) return;\n\n // Dictionaries flagged as structural edge cases are left completely\n // untouched by the JSON pipeline — keep their source accesses untouched\n // too so both sides stay consistent.\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) return;\n\n const fieldRenameMap =\n pruneContext.dictionaryKeyToFieldRenameMap.get(dictionaryKey);\n if (!fieldRenameMap || fieldRenameMap.size === 0) return;\n\n // `getIntlayerAsync('key')` is consumed through its `await`, so the\n // content root is the await expression — the three cases below would\n // otherwise only ever see an `AwaitExpression` parent.\n const contentRootPath = unwrapAwait(babelTypes, callExpressionPath);\n const parentNode = contentRootPath.parent;\n\n // ── Case 1: const { fieldA, fieldB } = useIntlayer('key') ────────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isObjectPattern(parentNode.id)\n ) {\n walkObjectDestructuring(babelTypes, contentRootPath, fieldRenameMap);\n return;\n }\n\n // ── Case 2: useIntlayer('key').fieldA.nested ─────────────────────\n // (also useIntlayer('key').onChange(cb))\n if (\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object ===\n contentRootPath.node\n ) {\n renameContentConsumers(babelTypes, contentRootPath, fieldRenameMap);\n return;\n }\n\n // ── Case 3: const result = useIntlayer('key'); result.fieldA ─────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isIdentifier(parentNode.id)\n ) {\n const variableBinding = callExpressionPath.scope.getBinding(\n parentNode.id.name\n );\n if (!variableBinding) return;\n\n for (const variableReferencePath of variableBinding.referencePaths) {\n // Direct access: result.fieldA, const { fieldA } = result, or the\n // chainable result.onChange(cb)\n renameContentConsumers(\n babelTypes,\n variableReferencePath,\n fieldRenameMap\n );\n\n // Signal accessor: result().fieldA or const { fieldA } = result()\n // walkRenameChain stops at a CallExpression parent, so we need to\n // start a new walk from the call-expression node itself.\n const refParent = variableReferencePath.parent;\n if (\n (babelTypes.isCallExpression(refParent) ||\n babelTypes.isOptionalCallExpression(refParent)) &&\n (refParent as BabelTypes.CallExpression).callee ===\n variableReferencePath.node\n ) {\n const callPath = variableReferencePath.parentPath;\n if (callPath) {\n renameContentConsumers(babelTypes, callPath, fieldRenameMap);\n }\n }\n }\n }\n },\n });\n};\n\n/**\n * Creates a Babel plugin that rewrites dictionary content field accesses in\n * source files to their short aliases via\n * {@link renameIntlayerFieldAccesses}.\n *\n * This plugin must run in a separate `transformAsync` pass **before**\n * `intlayerOptimizeBabelPlugin`, because the latter replaces `useIntlayer`\n * with `useDictionary`, erasing the dictionary-key information needed here.\n */\nexport const makeFieldRenameBabelPlugin =\n (pruneContext: PruneContext) =>\n ({ types: babelTypes }: { types: typeof BabelTypes }): PluginObject => ({\n name: 'intlayer-field-rename',\n visitor: {\n Program: {\n exit: (programPath) => {\n renameIntlayerFieldAccesses(babelTypes, programPath, pruneContext);\n },\n },\n },\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"babel-plugin-intlayer-field-rename.cjs","names":["skipTransparentWrappers","CHAINABLE_RUNTIME_METHOD_NAMES","NATIVE_CALLER_NAME_SET","resolveContentRoot"],"sources":["../../src/babel-plugin-intlayer-field-rename.ts"],"sourcesContent":["import type { NodePath, PluginObject } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport {\n CHAINABLE_RUNTIME_METHOD_NAMES,\n NATIVE_CALLER_NAME_SET,\n type NestedRenameEntry,\n type NestedRenameMap,\n type PruneContext,\n} from './babel-plugin-intlayer-usage-analyzer';\nimport {\n resolveContentRoot,\n skipTransparentWrappers,\n} from './staticAstReaders';\n\n// ── Field-name helpers ────────────────────────────────────────────────────────\n\n/**\n * Intlayer internal property names that must never be used as short-name\n * targets. These appear inside content-node values (e.g. `{ nodeType:\n * \"translation\", … }`) and are read by the intlayer runtime.\n */\nconst RESERVED_CONTENT_FIELD_NAMES = new Set(['nodeType']);\n\n/** Alphabet used to derive short field aliases (`a`, `b`, …, `aa`, `ab`, …). */\nconst SHORT_NAME_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n/**\n * Converts a zero-based index to a short alphabetic identifier.\n * 0 → 'a', 1 → 'b', …, 25 → 'z', 26 → 'aa', 27 → 'ab', …\n */\nexport const generateShortFieldName = (index: number): string => {\n if (!Number.isInteger(index) || index < 0) {\n throw new RangeError(\n `generateShortFieldName expects a non-negative integer index, received: ${index}`\n );\n }\n\n const remainder = index % SHORT_NAME_ALPHABET.length;\n const quotient = Math.floor(index / SHORT_NAME_ALPHABET.length);\n\n return quotient === 0 && SHORT_NAME_ALPHABET[remainder]\n ? SHORT_NAME_ALPHABET[remainder]\n : generateShortFieldName(quotient - 1) + SHORT_NAME_ALPHABET[remainder];\n};\n\n/**\n * Recursively builds a `NestedRenameMap` from a compiled dictionary content\n * value by traversing the intlayer node structure.\n *\n * Rules:\n * - If the value has `nodeType: 'translation'`, user-defined fields live\n * inside `translation[locale]`. Recurse into the first locale's value.\n * - All other intlayer runtime nodes (enumeration, condition, gender, …) are\n * treated as leaves — their internal keys must never be renamed.\n * - Arrays produce an empty children map. Array elements are not traversed\n * because consumers may access them via `.map()` / `.filter()` callbacks,\n * which the source-code rename walk cannot enter. Renaming element fields\n * in the JSON without the matching source-code rename would produce\n * mismatched key names and runtime crashes.\n * The `[0]` pass-through in `walkRenameChain` is preserved so that direct\n * indexed access (`field[0].sub`) silently terminates at the empty children\n * map without breaking anything.\n * - Plain objects are user-defined records: ALL non-reserved keys are renamed\n * with short alphabetic aliases (a, b, c, …) and each value is recursed into.\n * - Primitives produce an empty map (no further renaming).\n *\n * The rename map is built from ALL user-defined fields (not just consumed ones).\n * Both the JSON rename and the source-code rename use the same map, so the\n * short names are always consistent regardless of which fields are pruned.\n *\n * @param contentValue - The dictionary content value to analyse.\n */\nexport const buildNestedRenameMapFromContent = (\n contentValue: unknown\n): NestedRenameMap => {\n if (\n !contentValue ||\n typeof contentValue !== 'object' ||\n Array.isArray(contentValue)\n ) {\n return new Map();\n }\n\n const record = contentValue as Record<string, unknown>;\n\n // Any object with `nodeType: string` is an intlayer runtime node.\n if (typeof record.nodeType === 'string') {\n // Translation node: user-defined fields live inside translation[locale].\n if (\n record.nodeType === 'translation' &&\n record.translation &&\n typeof record.translation === 'object' &&\n !Array.isArray(record.translation)\n ) {\n const firstLocaleValue = Object.values(\n record.translation as Record<string, unknown>\n )[0];\n return buildNestedRenameMapFromContent(firstLocaleValue);\n }\n\n // All other intlayer nodes (enumeration, pluralization, conditions, …)\n // resolve to a single value at runtime through a call the source-code\n // rename walk cannot traverse (e.g. `content.myEnum(count)`), and the\n // JSON renamers only descend into translation nodes. Treat them as\n // leaves so the source and JSON sides always stay consistent.\n return new Map();\n }\n\n // Exclude React elements from being treated as user-defined records.\n // JSX elements in the compiled JSON have a $$typeof property (usually Symbol(react.element)).\n if (\n record.$$typeof ||\n (record.type && record.props && Object.hasOwn(record, 'ref'))\n ) {\n return new Map();\n }\n\n // User-defined record: rename ALL non-reserved keys with stable alphabetic\n // aliases sorted alphabetically so the mapping is deterministic.\n const sortedKeys = Object.keys(record)\n .filter((key) => !RESERVED_CONTENT_FIELD_NAMES.has(key))\n .sort();\n\n const renameMap: NestedRenameMap = new Map();\n\n for (let i = 0; i < sortedKeys.length; i++) {\n const key = sortedKeys[i];\n\n if (!key) continue;\n\n const children = buildNestedRenameMapFromContent(record[key]);\n\n renameMap.set(key, { shortName: generateShortFieldName(i), children });\n }\n\n return renameMap;\n};\n\n/**\n * Walks `fieldPath` through a {@link NestedRenameMap} and returns the entry at\n * the final path segment, or `undefined` when any segment is missing (e.g. the\n * path crosses an array or leaf value whose children are not mapped).\n *\n * Used to locate the rename entry of an opaquely-consumed content value so its\n * children map can be cleared before the JSON rename is applied.\n *\n * @param renameMap - The root rename map to walk.\n * @param fieldPath - Original (pre-rename) field names from the content root.\n */\nexport const getNestedRenameEntryAtPath = (\n renameMap: NestedRenameMap,\n fieldPath: readonly string[]\n): NestedRenameEntry | undefined => {\n let currentRenameMap = renameMap;\n let renameEntry: NestedRenameEntry | undefined;\n\n for (const fieldName of fieldPath) {\n renameEntry = currentRenameMap.get(fieldName);\n if (!renameEntry) return undefined;\n currentRenameMap = renameEntry.children;\n }\n\n return renameEntry;\n};\n\n// ── Serialisation for non-Babel consumers ─────────────────────────────────────\n\n/**\n * JSON-serialisable form of a {@link NestedRenameEntry}.\n *\n * Mirrors `FieldRenameNode` in the `@intlayer/swc` crate — both sides must stay\n * in sync.\n */\nexport type SerializedFieldRenameEntry = {\n /** Short alphabetic alias the field is renamed to (`'a'`, `'b'`, …). */\n shortName: string;\n /** Rename table of the fields nested inside this one. */\n children: SerializedFieldRenameMap;\n};\n\n/** JSON-serialisable form of a {@link NestedRenameMap}. */\nexport type SerializedFieldRenameMap = Record<\n string,\n SerializedFieldRenameEntry\n>;\n\n/** Recursively converts a {@link NestedRenameMap} to its serialisable form. */\nconst serializeNestedRenameMap = (\n renameMap: NestedRenameMap\n): SerializedFieldRenameMap => {\n const serialized: SerializedFieldRenameMap = {};\n\n for (const [fieldName, renameEntry] of renameMap) {\n serialized[fieldName] = {\n shortName: renameEntry.shortName,\n children: serializeNestedRenameMap(renameEntry.children),\n };\n }\n\n return serialized;\n};\n\n/**\n * Converts the field-rename tables of a {@link PruneContext} into a plain JSON\n * object, keyed by dictionary key.\n *\n * Consumed by bundler integrations that cannot run the Babel rename plugin and\n * must forward the tables to another transformer — currently the `@intlayer/swc`\n * Wasm plugin used by Next.js, which rewrites the source accesses itself.\n *\n * Dictionaries flagged as structural edge cases are omitted: the JSON pipeline\n * leaves them untouched, so their source accesses must stay untouched too.\n * Empty tables are omitted as well, so the result is empty when there is\n * nothing to rename.\n */\nexport const serializeFieldRenameMap = (\n pruneContext: PruneContext\n): Record<string, SerializedFieldRenameMap> => {\n const serialized: Record<string, SerializedFieldRenameMap> = {};\n\n for (const [\n dictionaryKey,\n renameMap,\n ] of pruneContext.dictionaryKeyToFieldRenameMap) {\n if (renameMap.size === 0) continue;\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) continue;\n\n serialized[dictionaryKey] = serializeNestedRenameMap(renameMap);\n }\n\n return serialized;\n};\n\n// ── Field-rename Babel plugin ─────────────────────────────────────────────────\n\n/**\n * Walks a MemberExpression chain starting from `startPath`, renaming each\n * property found in `currentRenameMap` at the corresponding nesting level.\n *\n * Numeric computed accesses (array indices such as `[0]`, `[1]`) are treated\n * as transparent pass-throughs: the rename map is kept unchanged and the walk\n * continues past the index. This means `content.field[0].sub` is handled\n * correctly — `field` and `sub` are both renamed while `[0]` is left intact.\n * TypeScript casts are looked through as well: `(content.field as any).sub`.\n */\nconst walkRenameChain = (\n babelTypes: typeof BabelTypes,\n startPath: NodePath<BabelTypes.Node>,\n currentRenameMap: NestedRenameMap\n): {\n finalPath: NodePath<BabelTypes.Node>;\n finalRenameMap: NestedRenameMap;\n} => {\n let refPath: NodePath<BabelTypes.Node> = startPath;\n let renameMap = currentRenameMap;\n\n while (true) {\n refPath = skipTransparentWrappers(babelTypes, refPath);\n\n const parentPath = refPath.parentPath;\n if (!parentPath) break;\n\n const parentNode = parentPath.node;\n\n if (\n (!babelTypes.isMemberExpression(parentNode) &&\n !babelTypes.isOptionalMemberExpression(parentNode)) ||\n (parentNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n break;\n }\n\n const memberNode = parentNode as BabelTypes.MemberExpression;\n\n // Numeric index access ([0], [1], …): advance past the array accessor\n // without touching the rename map. The next iteration will attempt to\n // rename the property that follows the index.\n if (\n memberNode.computed &&\n babelTypes.isNumericLiteral(memberNode.property)\n ) {\n refPath = parentPath;\n continue;\n }\n\n // Nothing left to rename at this level — stop.\n if (renameMap.size === 0) break;\n\n let fieldName: string | undefined;\n\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n fieldName = memberNode.property.name;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n fieldName = memberNode.property.value;\n } else {\n break; // dynamic computed key – stop\n }\n\n const renameEntry = renameMap.get(fieldName);\n if (!renameEntry) break; // not in map – stop\n\n // Apply the rename\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n memberNode.property.name = renameEntry.shortName;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n memberNode.property.value = renameEntry.shortName;\n }\n\n refPath = parentPath;\n renameMap = renameEntry.children;\n }\n\n return { finalPath: refPath, finalRenameMap: renameMap };\n};\n\n/**\n * Renames the properties of a destructuring `ObjectPattern` using `renameMap`,\n * recursing into nested patterns and following the references of bound local\n * variables.\n *\n * Handled property shapes:\n *\n * { fieldA } → { shortA: fieldA }\n * { fieldA: localVar } → { shortA: localVar }\n * { fieldA = fallback } → { shortA: fieldA = fallback }\n * { fieldA: { nested } } → { shortA: { shortN: nested } }\n * { ['fieldA']: x } → { ['shortA']: x }\n * { [dynamicKey]: x } → left untouched (dynamic key – not renamable)\n *\n * @param babelTypes - Babel types helper.\n * @param objectPattern - The destructuring pattern to rename.\n * @param scopePath - A path whose scope resolves the pattern's bindings.\n * @param renameMap - Rename table for the current nesting level.\n */\nconst renameObjectPatternProperties = (\n babelTypes: typeof BabelTypes,\n objectPattern: BabelTypes.ObjectPattern,\n scopePath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n for (const property of objectPattern.properties) {\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Computed keys: a static string key ({ ['title']: x }) is renamable in\n // place; any other computed key is dynamic and must be left untouched —\n // replacing it with an identifier would create a variable reference.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n continue;\n }\n\n const keyName = babelTypes.isIdentifier(property.key)\n ? property.key.name\n : babelTypes.isStringLiteral(property.key)\n ? property.key.value\n : null;\n if (!keyName) continue;\n\n const renameEntry = renameMap.get(keyName);\n if (!renameEntry) continue;\n\n if (property.computed) {\n // { ['fieldA']: x } → { ['shortA']: x }\n (property.key as BabelTypes.StringLiteral).value = renameEntry.shortName;\n } else {\n // { fieldA } → { shortA: fieldA }\n // { fieldA: localVar } → { shortA: localVar }\n if (property.shorthand) {\n property.shorthand = false;\n }\n property.key = babelTypes.identifier(renameEntry.shortName);\n }\n\n if (renameEntry.children.size === 0) continue;\n\n // A default value ({ fieldA = fallback }) wraps the actual binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n // Nested pattern: const { fieldA: { nested } } = … — rename its keys\n // with this entry's children map.\n if (babelTypes.isObjectPattern(bindingTarget)) {\n renameObjectPatternProperties(\n babelTypes,\n bindingTarget,\n scopePath,\n renameEntry.children\n );\n continue;\n }\n\n // Identifier binding: recursively walk references to the local variable.\n if (babelTypes.isIdentifier(bindingTarget)) {\n const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);\n if (!localVarBinding) continue;\n\n for (const nestedRefPath of localVarBinding.referencePaths) {\n renameFieldConsumers(babelTypes, nestedRefPath, renameEntry.children);\n }\n }\n }\n};\n\n/**\n * Walks an object-destructuring assignment whose right-hand side is `refPath`,\n * renaming each destructured key that is found in `renameMap`.\n *\n * Handles the \"secondary destructuring\" pattern that `walkRenameChain` cannot\n * reach because the reference is not a MemberExpression:\n *\n * const { webhooksSection } = useIntlayer('build-settings');\n * const { modal, validationErrors } = webhooksSection;\n * → const { a: modal, b: validationErrors } = webhooksSection;\n *\n * After renaming each key, {@link renameObjectPatternProperties} recursively\n * walks references to the newly-bound local variables, calling both\n * `walkRenameChain` (for subsequent member-access chains like\n * `validationErrors.invalidUrl`) and this function again (for further levels\n * of secondary destructuring).\n */\nconst walkObjectDestructuring = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const parentNode = refPath.parent;\n\n // Only handle: const { a, b } = refVar\n if (\n !babelTypes.isVariableDeclarator(parentNode) ||\n !babelTypes.isObjectPattern(parentNode.id) ||\n parentNode.init !== refPath.node\n ) {\n return;\n }\n\n renameObjectPatternProperties(babelTypes, parentNode.id, refPath, renameMap);\n};\n\n/**\n * Renames the field accesses reachable from `refPath`, a reference to a\n * content value: a member-access chain, then a destructuring assignment or an\n * alias (`const table = content.summary.table`) of where the chain ends.\n */\nconst renameFieldConsumers = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): {\n finalPath: NodePath<BabelTypes.Node>;\n finalRenameMap: NestedRenameMap;\n} => {\n const chainEnd = walkRenameChain(babelTypes, refPath, renameMap);\n walkObjectDestructuring(\n babelTypes,\n chainEnd.finalPath,\n chainEnd.finalRenameMap\n );\n renameAliasReferences(\n babelTypes,\n chainEnd.finalPath,\n chainEnd.finalRenameMap\n );\n return chainEnd;\n};\n\n/**\n * Follows `const alias = <valuePath>` and renames the accesses made through\n * `alias`, mirroring the analyser's alias tracking.\n */\nconst renameAliasReferences = (\n babelTypes: typeof BabelTypes,\n valuePath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const parentNode = valuePath.parent;\n if (\n !babelTypes.isVariableDeclarator(parentNode) ||\n !babelTypes.isIdentifier(parentNode.id) ||\n parentNode.init !== valuePath.node\n ) {\n return;\n }\n\n const aliasBinding = valuePath.scope.getBinding(parentNode.id.name);\n for (const aliasReferencePath of aliasBinding?.referencePaths ?? []) {\n renameFieldConsumers(babelTypes, aliasReferencePath, renameMap);\n }\n};\n\n/**\n * Renames every field access reachable from `rootPath`, whose value is the\n * dictionary content root.\n *\n * Combines the three ways a content root is consumed: a member-access chain,\n * a destructuring assignment, and a chainable runtime helper such as\n * `.onChange(cb)`.\n */\nconst renameContentConsumers = (\n babelTypes: typeof BabelTypes,\n rootPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n const { finalPath, finalRenameMap } = renameFieldConsumers(\n babelTypes,\n rootPath,\n renameMap\n );\n renameChainedRuntimeCall(babelTypes, finalPath, finalRenameMap);\n};\n\n/**\n * Handles `content.onChange(cb)` — a runtime subscription rather than a field\n * access (see {@link CHAINABLE_RUNTIME_METHOD_NAMES}).\n *\n * `walkRenameChain` stops at `onChange` because it is absent from the rename\n * map, which would leave the callback body reading the original field names\n * while the compiled JSON has already been renamed. This restarts the rename\n * walk on both sides of the call:\n *\n * - the callback's first parameter receives the same content root, so its\n * accesses are renamed with the same map;\n * - the helper returns the content object, so the chain continues past it.\n *\n * @param refPath - Path whose value is the content root (the object the\n * chainable method would be called on).\n */\nconst renameChainedRuntimeCall = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const memberPath = refPath.parentPath;\n if (!memberPath) return;\n\n const memberNode = memberPath.node;\n if (\n (!babelTypes.isMemberExpression(memberNode) &&\n !babelTypes.isOptionalMemberExpression(memberNode)) ||\n (memberNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n return;\n }\n\n const propertyNode = (memberNode as BabelTypes.MemberExpression).property;\n const methodName = (memberNode as BabelTypes.MemberExpression).computed\n ? babelTypes.isStringLiteral(propertyNode)\n ? propertyNode.value\n : undefined\n : babelTypes.isIdentifier(propertyNode)\n ? propertyNode.name\n : undefined;\n\n if (!methodName || !CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;\n\n const callPath = memberPath.parentPath;\n if (!callPath) return;\n if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) {\n return;\n }\n if ((callPath.node as BabelTypes.CallExpression).callee !== memberNode) {\n return;\n }\n\n const argumentPaths = callPath.get(\n 'arguments'\n ) as NodePath<BabelTypes.Node>[];\n\n for (const argumentPath of argumentPaths) {\n if (\n !argumentPath.isArrowFunctionExpression() &&\n !argumentPath.isFunctionExpression()\n ) {\n continue;\n }\n\n const [firstParameterPath] = argumentPath.get(\n 'params'\n ) as NodePath<BabelTypes.Node>[];\n if (!firstParameterPath) continue;\n\n // ({ title }) => … — destructured directly in the parameter list.\n if (firstParameterPath.isObjectPattern()) {\n renameObjectPatternProperties(\n babelTypes,\n firstParameterPath.node,\n argumentPath,\n renameMap\n );\n continue;\n }\n\n // (content) => … — rename each access on the parameter.\n if (!firstParameterPath.isIdentifier()) continue;\n\n const parameterBinding = argumentPath.scope.getBinding(\n firstParameterPath.node.name\n );\n if (!parameterBinding) continue;\n\n for (const parameterRefPath of parameterBinding.referencePaths) {\n renameContentConsumers(babelTypes, parameterRefPath, renameMap);\n }\n }\n\n // The helper returns the content object itself, so keep walking past it —\n // both when the result is used inline and when it is stored in a variable\n // (`const content = useIntlayer('key').onChange(cb)`).\n renameContentConsumers(babelTypes, callPath, renameMap);\n\n const declaratorNode = callPath.parent;\n if (\n babelTypes.isVariableDeclarator(declaratorNode) &&\n babelTypes.isIdentifier(declaratorNode.id) &&\n declaratorNode.init === callPath.node\n ) {\n const resultBinding = callPath.scope.getBinding(declaratorNode.id.name);\n for (const resultRefPath of resultBinding?.referencePaths ?? []) {\n renameContentConsumers(babelTypes, resultRefPath, renameMap);\n }\n }\n};\n\n/**\n * Collects the local aliases under which `useIntlayer` / `getIntlayer` are\n * imported in the given program (e.g. `import { useIntlayer as useI } …`\n * yields `useI` → `useIntlayer`).\n *\n * Import declarations can only appear at the top level of a module, so the\n * program body is scanned directly instead of traversing the whole AST.\n */\nconst collectIntlayerCallerLocalNames = (\n babelTypes: typeof BabelTypes,\n programNode: BabelTypes.Program\n): Map<string, string> => {\n const intlayerCallerLocalNameMap = new Map<string, string>();\n\n for (const statement of programNode.body) {\n if (!babelTypes.isImportDeclaration(statement)) continue;\n\n for (const importSpecifier of statement.specifiers) {\n if (!babelTypes.isImportSpecifier(importSpecifier)) continue;\n\n const importedName = babelTypes.isIdentifier(importSpecifier.imported)\n ? importSpecifier.imported.name\n : importSpecifier.imported.value;\n\n if (NATIVE_CALLER_NAME_SET.has(importedName)) {\n intlayerCallerLocalNameMap.set(\n importSpecifier.local.name,\n importedName\n );\n }\n }\n }\n\n return intlayerCallerLocalNameMap;\n};\n\n/**\n * Rewrites dictionary content field accesses in the given program to the\n * short aliases defined in `pruneContext.dictionaryKeyToFieldRenameMap`.\n *\n * Handled patterns (mirrors the usage analyser):\n *\n * const { fieldA, fieldB } = useIntlayer('key')\n * → const { shortA: fieldA, shortB: fieldB } = useIntlayer('key')\n *\n * useIntlayer('key').fieldA\n * → useIntlayer('key').shortA\n *\n * const result = useIntlayer('key'); result.fieldA\n * → const result = useIntlayer('key'); result.shortA\n *\n * const { fieldA } = useIntlayer('key');\n * const { nested } = fieldA; // secondary destructuring\n * → const { shortA: fieldA } = useIntlayer('key');\n * const { shortN: nested } = fieldA;\n *\n * Exposed as a standalone function so that both\n * {@link makeFieldRenameBabelPlugin} and `intlayerMinifyBabelPlugin` can\n * invoke it from their own `Program.exit` visitors.\n */\nexport const renameIntlayerFieldAccesses = (\n babelTypes: typeof BabelTypes,\n programPath: NodePath<BabelTypes.Program>,\n pruneContext: PruneContext\n): void => {\n if (pruneContext.dictionaryKeyToFieldRenameMap.size === 0) return;\n\n const intlayerCallerLocalNameMap = collectIntlayerCallerLocalNames(\n babelTypes,\n programPath.node\n );\n if (intlayerCallerLocalNameMap.size === 0) return;\n\n // Visit all useIntlayer / getIntlayer call-sites and rename field accesses\n programPath.traverse({\n CallExpression: (callExpressionPath) => {\n const calleeNode = callExpressionPath.node.callee;\n let localCallerName: string | undefined;\n\n if (babelTypes.isIdentifier(calleeNode)) {\n localCallerName = calleeNode.name;\n } else if (\n babelTypes.isMemberExpression(calleeNode) &&\n babelTypes.isIdentifier(calleeNode.property)\n ) {\n localCallerName = calleeNode.property.name;\n }\n\n if (!localCallerName || !intlayerCallerLocalNameMap.has(localCallerName))\n return;\n\n const callArguments = callExpressionPath.node.arguments;\n if (callArguments.length === 0) return;\n\n const firstArgument = callArguments[0];\n let dictionaryKey: string | undefined;\n\n if (babelTypes.isStringLiteral(firstArgument)) {\n dictionaryKey = firstArgument.value;\n } else if (\n babelTypes.isTemplateLiteral(firstArgument) &&\n firstArgument.expressions.length === 0 &&\n firstArgument.quasis.length === 1 &&\n firstArgument.quasis[0]\n ) {\n dictionaryKey =\n firstArgument.quasis[0].value.cooked ??\n firstArgument.quasis[0].value.raw;\n }\n\n if (!dictionaryKey) return;\n\n // Dictionaries flagged as structural edge cases are left completely\n // untouched by the JSON pipeline — keep their source accesses untouched\n // too so both sides stay consistent.\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) return;\n\n const fieldRenameMap =\n pruneContext.dictionaryKeyToFieldRenameMap.get(dictionaryKey);\n if (!fieldRenameMap || fieldRenameMap.size === 0) return;\n\n // Looks through `await`, TypeScript casts and `Promise.all` array\n // destructuring — the same resolution the usage analyser applies.\n const resolution = resolveContentRoot(babelTypes, callExpressionPath);\n if (resolution.kind === 'discarded') return;\n\n const { rootPath: contentRootPath } = resolution;\n\n if (resolution.kind === 'binding') {\n const { bindingTarget } = resolution;\n\n // ── Case 1: const { fieldA, fieldB } = useIntlayer('key') ──────\n if (babelTypes.isObjectPattern(bindingTarget)) {\n renameObjectPatternProperties(\n babelTypes,\n bindingTarget,\n contentRootPath,\n fieldRenameMap\n );\n return;\n }\n\n // ── Case 3: const result = useIntlayer('key'); result.fieldA ───\n const variableBinding = contentRootPath.scope.getBinding(\n bindingTarget.name\n );\n if (!variableBinding) return;\n\n for (const variableReferencePath of variableBinding.referencePaths) {\n // Direct access: result.fieldA, const { fieldA } = result, or the\n // chainable result.onChange(cb)\n renameContentConsumers(\n babelTypes,\n variableReferencePath,\n fieldRenameMap\n );\n\n // Signal accessor: result().fieldA or const { fieldA } = result()\n // walkRenameChain stops at a CallExpression parent, so we need to\n // start a new walk from the call-expression node itself.\n const refParent = variableReferencePath.parent;\n if (\n (babelTypes.isCallExpression(refParent) ||\n babelTypes.isOptionalCallExpression(refParent)) &&\n (refParent as BabelTypes.CallExpression).callee ===\n variableReferencePath.node\n ) {\n const callPath = variableReferencePath.parentPath;\n if (callPath) {\n renameContentConsumers(babelTypes, callPath, fieldRenameMap);\n }\n }\n }\n return;\n }\n\n // ── Case 2: useIntlayer('key').fieldA.nested ─────────────────────\n // (also useIntlayer('key').onChange(cb))\n const parentNode = contentRootPath.parent;\n if (\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object ===\n contentRootPath.node\n ) {\n renameContentConsumers(babelTypes, contentRootPath, fieldRenameMap);\n }\n },\n });\n};\n\n/**\n * Creates a Babel plugin that rewrites dictionary content field accesses in\n * source files to their short aliases via\n * {@link renameIntlayerFieldAccesses}.\n *\n * This plugin must run in a separate `transformAsync` pass **before**\n * `intlayerOptimizeBabelPlugin`, because the latter replaces `useIntlayer`\n * with `useDictionary`, erasing the dictionary-key information needed here.\n */\nexport const makeFieldRenameBabelPlugin =\n (pruneContext: PruneContext) =>\n ({ types: babelTypes }: { types: typeof BabelTypes }): PluginObject => ({\n name: 'intlayer-field-rename',\n visitor: {\n Program: {\n exit: (programPath) => {\n renameIntlayerFieldAccesses(babelTypes, programPath, pruneContext);\n },\n },\n },\n });\n"],"mappings":"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"}
@@ -244,7 +244,7 @@ const buildDictionaryImportDeclarations = (babelTypes, state, imports) => {
244
244
  * const content2 = getIntlayer(_dicHash);
245
245
  * ```
246
246
  */
247
- const intlayerOptimizeBabelPlugin = (babel) => {
247
+ const optimizeBabelPlugin = (babel) => {
248
248
  const { types: t } = babel;
249
249
  return {
250
250
  name: "babel-plugin-intlayer-transform",
@@ -446,6 +446,16 @@ const intlayerOptimizeBabelPlugin = (babel) => {
446
446
  } }
447
447
  };
448
448
  };
449
+ /**
450
+ * Intlayer optimize Babel plugin (see `optimizeBabelPlugin`), typed as Babel's
451
+ * `PluginTarget`.
452
+ *
453
+ * Babel types tuple options as `object` (`[PluginTarget<object>, object]`), so
454
+ * a plugin whose handlers read typed `this.opts` is rejected in
455
+ * `plugins: [[plugin, options]]` under `strict`. The options passed in the
456
+ * tuple are the typed options read by the handlers.
457
+ */
458
+ const intlayerOptimizeBabelPlugin = optimizeBabelPlugin;
449
459
 
450
460
  //#endregion
451
461
  exports.intlayerOptimizeBabelPlugin = intlayerOptimizeBabelPlugin;
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-optimize.cjs","names":["normalizePath","relative","dirname","join","getNormalizedFilesListSet","createDictionaryImportRegistry","createCompatOptimizePass","readStaticString"],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"sourcesContent":["import { dirname, join, relative } from 'node:path';\nimport type { PluginObject, PluginPass } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport type { CallerDescriptor } from '@intlayer/config/callers';\nimport { normalizePath } from '@intlayer/config/utils';\nimport {\n createCompatOptimizePass,\n type JsxSiteNode,\n} from './compat/optimizePass';\nimport {\n createDictionaryImportRegistry,\n type DictionaryImportRegistry,\n type ImportMode,\n} from './dictionaryImports';\nimport { getNormalizedFilesListSet } from './normalizedFilesList';\nimport { readStaticString } from './staticAstReaders';\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n '@intlayer/core/interpreter',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n 'astro-intlayer',\n 'remix-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer', 'getIntlayerAsync'] as const;\n\n/** Membership sets for the tables above — hit once per import and per call. */\nconst NATIVE_PACKAGE_SET: ReadonlySet<string> = new Set(PACKAGE_LIST);\nconst CALLER_NAME_SET: ReadonlySet<string> = new Set(CALLER_LIST);\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'preact-intlayer',\n 'vue-intlayer',\n 'solid-intlayer',\n 'svelte-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n] as const;\n\nconst DYNAMIC_PACKAGE_SET: ReadonlySet<string> = new Set(PACKAGE_LIST_DYNAMIC);\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n // `getIntlayerAsync` always reads a per-locale chunk, in every import mode,\n // so its helper is the same on both sides of the static/dynamic split.\n getIntlayerAsync: 'getDictionaryAsync',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/** Import rename table applied when the helper plan for a package is `dynamic`. */\nconst DYNAMIC_HELPER_MAP: Record<string, string> = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n};\n\n/**\n * Packages whose SSR-static `useDictionary` lives in a `/server` subpath\n * because it differs from the root one. Solid's reserves one hydration\n * resource slot so hydration ids stay aligned with the client's\n * `useDictionaryDynamic`; for other frameworks the root `useDictionary` is\n * already the correct SSR-static implementation.\n */\nconst SSR_STATIC_IMPORT_SOURCE: Partial<Record<string, string>> = {\n 'solid-intlayer': 'solid-intlayer/server',\n};\n\ntype CallerName = (typeof CALLER_LIST)[number];\n\n/**\n * Options for the optimization Babel plugin\n */\nexport type OptimizePluginOptions = {\n /**\n * If false, the plugin will not apply any transformation.\n */\n optimize?: boolean;\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries entry file.\n */\n unmergedDictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries directory.\n */\n unmergedDictionariesDir: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * The path to the fetch dictionaries directory.\n */\n fetchDictionariesDir: string;\n /**\n * The path to the fetch dictionaries entry file.\n */\n fetchDictionariesEntryPath: string;\n /**\n * If true, the plugin will replace the dictionary entry file with `export default {}`.\n */\n replaceDictionaryEntry: boolean;\n /**\n * Keys of the dictionaries that reference other dictionaries through\n * `nest()`.\n *\n * For those, the injected static import points at the generated companion\n * module (`<dictionariesDir>/nested/<key>.mjs`) instead of the raw JSON. The\n * companion re-exports the dictionary with its nest targets attached, so\n * `getNesting` resolves them from that local reference rather than from the\n * global registry this plugin empties — and each target lands in the chunk of\n * the dictionary referencing it.\n *\n * Dynamic and fetch modes need nothing here: their generated loaders already\n * attach the same targets per locale.\n */\n nestingDictionaryKeys?: string[];\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries. It will rely on Suspense to load the dictionaries.\n */\n importMode: 'static' | 'dynamic' | 'fetch' | undefined;\n /**\n * Map of dictionary keys to their specific import mode.\n */\n dictionaryModeMap?: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n >;\n /**\n * Files list to traverse.\n */\n filesList: string[];\n /**\n * Whether the current transform is for an SSR bundle.\n */\n isServer?: boolean;\n /**\n * Compat-adapter caller descriptors injected by the compat packages'\n * bundler plugins (e.g. `@intlayer/react-i18next/plugin`).\n *\n * Callers carrying `staticReplacement` / `dynamicReplacement` are rewritten\n * the same way as native `useIntlayer` calls: the namespace string argument\n * is replaced by a pre-imported dictionary object and the import specifier\n * is re-pointed to the dictionary-accepting variant, e.g.\n * `useTranslation('about')` → `useDictionary(_dictHash)`.\n *\n * No compat-specific name is hard-coded in this plugin — the whole rewrite\n * is driven by these descriptors.\n */\n compatCallers?: CallerDescriptor[];\n};\n\n/**\n * Per-file plugin state.\n *\n * Only the two flags that have to survive from `pre` / `Program.enter` into\n * `Program.exit` live here — the caller maps and the import registry are built\n * and consumed inside `exit`, so they stay local to it.\n */\ntype State = PluginPass & {\n opts: OptimizePluginOptions;\n /** Whether the current file *is* a generated dictionaries entry file. */\n _isDictEntry?: boolean;\n /** Whether the current file is covered by the `filesList` allowlist. */\n _isIncluded?: boolean;\n};\n\n/**\n * Builds the module specifier pointing at `targetPath` from `fromFile`, with\n * forward slashes and an explicit `./` prefix so bundlers never treat it as a\n * bare package specifier.\n */\nconst toRelativeSpecifier = (fromFile: string, targetPath: string): string => {\n // Fix windows path\n const relativePath = normalizePath(relative(dirname(fromFile), targetPath));\n\n // Fix relative path\n if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {\n return `./${relativePath}`;\n }\n\n return relativePath;\n};\n\n/**\n * Subdirectory of the compiled dictionaries holding the companion modules that\n * re-export a dictionary with its `nest()` targets attached. Mirrors\n * `NESTED_DICTIONARIES_SUBDIR` in `@intlayer/engine`.\n */\nconst NESTED_DICTIONARIES_SUBDIR = 'nested';\n\nconst computeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n fetchDictionariesDir: string,\n key: string,\n importMode: 'static' | 'dynamic' | 'fetch',\n hasNestedDictionaries = false\n): string => {\n // Static mode is the only one needing the companion: the dynamic and fetch\n // loaders already attach the nest targets per locale.\n let dictionaryPath = hasNestedDictionaries\n ? join(dictionariesDir, NESTED_DICTIONARIES_SUBDIR, `${key}.mjs`)\n : join(dictionariesDir, `${key}.json`);\n\n if (importMode === 'fetch') {\n dictionaryPath = join(fetchDictionariesDir, `${key}.mjs`);\n }\n\n if (importMode === 'dynamic') {\n dictionaryPath = join(dynamicDictionariesDir, `${key}.mjs`);\n }\n\n return toRelativeSpecifier(fromFile, dictionaryPath);\n};\n\nconst isCallerName = (name: string): name is CallerName =>\n CALLER_NAME_SET.has(name);\n\nconst isDynamicPackage = (packageName: string): boolean =>\n DYNAMIC_PACKAGE_SET.has(packageName);\n\n/** The name an import specifier brings in, whether written as an identifier or a string. */\nconst importedSpecifierName = (\n babelTypes: typeof BabelTypes,\n specifier: BabelTypes.ImportSpecifier\n): string =>\n babelTypes.isIdentifier(specifier.imported)\n ? specifier.imported.name\n : specifier.imported.value;\n\nconst EMPTY_KEY_SET: ReadonlySet<string> = new Set<string>();\n\n/**\n * `nestingDictionaryKeys` as a set, cached by array reference: Babel reuses one\n * options object for the whole build, so the set is built once instead of once\n * per transformed file.\n */\nconst nestingKeysCache = new WeakMap<readonly string[], ReadonlySet<string>>();\n\nconst getNestingDictionaryKeySet = (\n nestingDictionaryKeys: readonly string[] | undefined\n): ReadonlySet<string> => {\n if (!nestingDictionaryKeys) return EMPTY_KEY_SET;\n\n let keySet = nestingKeysCache.get(nestingDictionaryKeys);\n\n if (!keySet) {\n keySet = new Set(nestingDictionaryKeys);\n nestingKeysCache.set(nestingDictionaryKeys, keySet);\n }\n\n return keySet;\n};\n\n/**\n * Helper family every `useIntlayer`/`getIntlayer` call from one package import\n * resolves to in the current file. `ssrStatic` is the SSR bundle of a\n * dynamic-mode file: rewritten to the static `useDictionary` (from the\n * package's `/server` entry when it has one — see\n * `SSR_STATIC_IMPORT_SOURCE`) so the server renders static JSON while the\n * client keeps the dynamic loader.\n */\ntype PackageHelperPlan = 'static' | 'dynamic' | 'ssrStatic';\n\n/**\n * Decides, once per package import, which helper family applies to this file.\n * The import rewrite and the per-call rewrite must both derive from this\n * single decision, or the emitted helper and its argument shape diverge.\n *\n * Fetch wins over `ssrStatic`: fetch dictionaries are runtime content, so the\n * server must keep the real fetch path instead of rendering build-time JSON.\n */\nconst resolveHelperPlan = (\n packageName: string,\n importMode: ImportMode | undefined,\n isServer: boolean | undefined,\n packageHasDynamicCall: boolean,\n packageHasFetchCall: boolean\n): PackageHelperPlan => {\n if (!isDynamicPackage(packageName)) return 'static';\n\n if (importMode === 'fetch' || packageHasFetchCall) return 'dynamic';\n\n if (importMode === 'dynamic' || packageHasDynamicCall) {\n return isServer === true ? 'ssrStatic' : 'dynamic';\n }\n\n return 'static';\n};\n\n/**\n * Builds the dictionary import declarations the rewrite accumulated for one\n * file — the compiled JSON (or its `nest()` companion) for static reads, and\n * the generated per-locale loader for dynamic and fetch ones.\n */\nconst buildDictionaryImportDeclarations = (\n babelTypes: typeof BabelTypes,\n state: State,\n imports: DictionaryImportRegistry\n): BabelTypes.ImportDeclaration[] => {\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n nestingDictionaryKeys,\n } = state.opts;\n const fromFile = state.file.opts.filename!;\n const nestingKeys = getNestingDictionaryKeySet(nestingDictionaryKeys);\n\n const importDeclarations: BabelTypes.ImportDeclaration[] = [];\n\n // Static JSON imports — `getIntlayer` always reads a JSON dictionary.\n for (const [key, ident] of imports.staticImports) {\n // A dictionary holding `nest()` references is imported through its\n // companion module, which re-exports it with the nest targets attached.\n const hasNestedDictionaries = nestingKeys.has(key);\n\n const specifier = computeImport(\n fromFile,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n 'static',\n hasNestedDictionaries\n );\n\n const importDeclaration = babelTypes.importDeclaration(\n [babelTypes.importDefaultSpecifier(babelTypes.identifier(ident.name))],\n babelTypes.stringLiteral(specifier)\n );\n\n if (!hasNestedDictionaries) {\n importDeclaration.attributes = [\n babelTypes.importAttribute(\n babelTypes.identifier('type'),\n babelTypes.stringLiteral('json')\n ),\n ];\n }\n\n importDeclarations.push(importDeclaration);\n }\n\n // Per-locale loaders — `useIntlayer` under a dynamic or fetch helper.\n for (const [key, ident] of imports.dynamicImports) {\n const mode: ImportMode = ident.name.endsWith('_fetch')\n ? 'fetch'\n : 'dynamic';\n\n importDeclarations.push(\n babelTypes.importDeclaration(\n [babelTypes.importDefaultSpecifier(babelTypes.identifier(ident.name))],\n babelTypes.stringLiteral(\n computeImport(\n fromFile,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n mode\n )\n )\n )\n );\n }\n\n return importDeclarations;\n};\n\n/**\n * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.\n *\n * This plugin transforms calls to `useIntlayer()`, `getIntlayer()` and\n * `getIntlayerAsync()` from various Intlayer packages into optimized dictionary\n * access patterns, automatically importing the required dictionary files based\n * on the configured import mode.\n *\n * ## Supported Input Patterns\n *\n * The plugin recognizes these function calls:\n *\n * ```ts\n * // useIntlayer\n * import { useIntlayer } from 'react-intlayer';\n * import { useIntlayer } from 'next-intlayer';\n *\n * // getIntlayer / getIntlayerAsync\n * import { getIntlayer, getIntlayerAsync } from 'intlayer';\n *\n * // Usage\n * const content = useIntlayer('app');\n * const content = getIntlayer('app');\n * const content = await getIntlayerAsync('app', locale);\n * ```\n *\n * `getIntlayerAsync` is the exception to the mode table below: it always\n * resolves to the per-locale loader (`getDictionaryAsync`), in every import\n * mode, since loading a single locale is what it exists for.\n *\n * **Output (any mode):**\n * ```ts\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { getDictionaryAsync as getIntlayerAsync } from 'intlayer';\n *\n * const content = await getIntlayerAsync(_dicHash_dyn, 'app', locale);\n * ```\n *\n * ## Transformation Modes\n *\n * ### Static Mode (default: `importMode = \"static\"`)\n *\n * Imports JSON dictionaries directly and replaces function calls with dictionary access:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash);\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Dynamic Mode (`importMode = \"dynamic\"`)\n *\n * Uses dynamic dictionary loading with Suspense support:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Fetch Mode (`importMode = \"fetch\"`)\n *\n * Uses fetch-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"fetch\" value:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_fetch, \"app\");\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * > If `dictionaryModeMap` does not include the key with \"fetch\" value, the plugin will fallback to the dynamic import mode.\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n */\nexport const intlayerOptimizeBabelPlugin = (babel: {\n types: typeof BabelTypes;\n}): PluginObject<State> => {\n const { types: t } = babel;\n\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._isIncluded = true;\n this._isDictEntry = false;\n\n // If optimize is false, skip processing entirely\n if (this.opts.optimize === false) {\n this._isIncluded = false;\n return;\n }\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename\n ? normalizePath(this.file.opts.filename)\n : undefined;\n if (this.opts.filesList && filename) {\n const isIncluded = getNormalizedFilesListSet(this.opts.filesList).has(\n filename\n );\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n // Safe access to filename\n const filename = state.file.opts.filename\n ? normalizePath(state.file.opts.filename)\n : undefined;\n const dictionariesEntryPath = state.opts.dictionariesEntryPath\n ? normalizePath(state.opts.dictionariesEntryPath)\n : undefined;\n\n // If this file *is* the dictionaries entry, short-circuit: export {}\n // Note: unmerged_dictionaries.mjs is used by the visual editor and CMS\n // and must not be replaced with an empty dictionary map.\n if (\n state.opts.replaceDictionaryEntry &&\n filename &&\n filename === dictionariesEntryPath\n ) {\n state._isDictEntry = true;\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n t.exportNamedDeclaration(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier('getDictionaries'),\n t.arrowFunctionExpression([], t.objectExpression([]))\n ),\n ])\n ),\n ];\n }\n },\n\n /**\n * After full traversal, process imports and call expressions, then inject the JSON dictionary imports.\n *\n * We do the transformation in Program.exit (via a manual traverse) rather than using\n * top-level ImportDeclaration/CallExpression visitors. This ensures that if another plugin\n * (like babel-plugin-intlayer-extract) adds new useIntlayer calls in its Program.exit,\n * we will see and transform them here because our Program.exit runs after theirs.\n */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n\n if (!state._isIncluded) return; // early-out if file is not included\n\n const imports = createDictionaryImportRegistry(t);\n\n // Compat adapters plug in here and nowhere else: with no descriptor\n // injected the pass is `null`, every `compat?.` below is a no-op and\n // the native rewrite runs exactly as if the adapters did not exist.\n const compat = createCompatOptimizePass(\n t,\n state.opts.compatCallers ?? [],\n imports,\n {\n importMode: state.opts.importMode,\n dictionaryModeMap: state.opts.dictionaryModeMap,\n }\n );\n\n // ── Step 1 — imports.\n //\n // An import declaration is only ever a direct child of Program, so\n // the body is scanned instead of walking the whole AST, and the\n // result is complete before any call site is inspected (a file may\n // import below the calls it governs).\n const programBody = programPath.node.body;\n const nativeImportNodes: BabelTypes.ImportDeclaration[] = [];\n const compatImportNodes: BabelTypes.ImportDeclaration[] = [];\n /** Local alias → the native caller it was imported as. */\n const callerMap = new Map<string, CallerName>();\n /** Local alias → the intlayer package it was imported from. */\n const callerPackageMap = new Map<string, string>();\n /** Whether the file imported any native or compat caller at all. */\n let hasValidImport = false;\n\n for (const statement of programBody) {\n if (!t.isImportDeclaration(statement)) continue;\n\n const src = statement.source.value;\n const isNativePackage = NATIVE_PACKAGE_SET.has(src);\n const isCompatPackage = compat?.ownsImportSource(src) ?? false;\n\n if (!isNativePackage && !isCompatPackage) continue;\n\n hasValidImport = true;\n if (isNativePackage) nativeImportNodes.push(statement);\n if (isCompatPackage) compatImportNodes.push(statement);\n\n for (const spec of statement.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = importedSpecifierName(t, spec);\n\n if (isNativePackage && isCallerName(importedName)) {\n callerMap.set(spec.local.name, importedName);\n callerPackageMap.set(spec.local.name, src);\n }\n\n if (isCompatPackage) {\n compat?.noteImport(src, importedName, spec.local.name);\n }\n }\n }\n\n // ── Step 2 — the file's only AST walk, collecting the call sites\n // that either half of the rewrite can act on. Everything after\n // this point works on the collected arrays.\n const nativeCallNodes: BabelTypes.CallExpression[] = [];\n const compatCallNodes: BabelTypes.CallExpression[] = [];\n /**\n * Compat JSX elements bound by their id attribute (`<Trans id>`),\n * as source JSX or as the `jsx(Trans, …)` call the framework plugin\n * already compiled them into.\n */\n const compatJsxNodes: JsxSiteNode[] = [];\n\n // A root-scope compat caller (`useLingui()`) names its dictionaries\n // through the message ids used elsewhere in the file, so those\n // id-carrying sites are handed to the compat pass from the same walk.\n const collectMessageIds = compat?.needsMessageIdSites() ?? false;\n\n if (callerMap.size > 0 || compat?.hasCallers()) {\n programPath.traverse({\n CallExpression(path) {\n if (collectMessageIds) compat?.collectMessageIdSite(path.node);\n if (compat?.ownsJsxSite(path.node)) {\n compatJsxNodes.push(path.node);\n }\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n\n if (callerMap.has(callee.name)) {\n nativeCallNodes.push(path.node);\n } else if (compat?.ownsLocalName(callee.name)) {\n compatCallNodes.push(path.node);\n\n // `const { i18n, _, t } = useLingui()` — the destructured\n // names are how bare `t('…')` sites are told apart from\n // unrelated helpers of the same name.\n const declarator = path.parent;\n if (\n t.isVariableDeclarator(declarator) &&\n t.isObjectPattern(declarator.id)\n ) {\n compat.noteDestructuredResult(\n callee.name,\n declarator.id.properties.flatMap((property) =>\n t.isObjectProperty(property) &&\n t.isIdentifier(property.value)\n ? [property.value.name]\n : []\n )\n );\n }\n }\n },\n ...(collectMessageIds\n ? {\n TaggedTemplateExpression(path) {\n compat?.collectMessageIdSite(path.node);\n },\n }\n : {}),\n ...(compat\n ? {\n JSXOpeningElement(path) {\n if (collectMessageIds) {\n compat.collectMessageIdSite(path.node);\n }\n if (compat.ownsJsxSite(path.node)) {\n compatJsxNodes.push(path.node);\n }\n },\n }\n : {}),\n });\n }\n\n // ── Step 3 — analysis.\n //\n // A per-dictionary override reached from this file can promote a\n // whole package import to a dynamic loader, so the helper family is\n // decided per package before anything is rewritten.\n const packagesWithDynamicCall = new Set<string>();\n const packagesWithFetchCall = new Set<string>();\n\n for (const callNode of nativeCallNodes) {\n const callee = callNode.callee as BabelTypes.Identifier;\n if (callerMap.get(callee.name) !== 'useIntlayer') continue;\n\n const callerPackage = callerPackageMap.get(callee.name);\n if (!callerPackage) continue;\n\n const key = readStaticString(t, callNode.arguments[0]);\n if (!key) continue;\n\n const overrideMode = state.opts.dictionaryModeMap?.[key];\n\n if (overrideMode === 'dynamic') {\n packagesWithDynamicCall.add(callerPackage);\n } else if (overrideMode === 'fetch') {\n packagesWithFetchCall.add(callerPackage);\n }\n }\n\n // The compat half decides its own file-level helper family and drops\n // the callers whose call sites it cannot resolve.\n compat?.analyzeCalls(\n compatCallNodes,\n compatJsxNodes,\n (localName) =>\n programPath.scope.getBinding(localName)?.referencePaths.length ??\n 0\n );\n\n const helperPlanCache = new Map<string, PackageHelperPlan>();\n\n const getHelperPlan = (packageName: string): PackageHelperPlan => {\n let plan = helperPlanCache.get(packageName);\n\n if (plan === undefined) {\n plan = resolveHelperPlan(\n packageName,\n state.opts.importMode,\n state.opts.isServer,\n packagesWithDynamicCall.has(packageName),\n packagesWithFetchCall.has(packageName)\n );\n helperPlanCache.set(packageName, plan);\n }\n\n return plan;\n };\n\n // ── Step 4 — rewrite the imports.\n //\n // Moving a helper to a package's `/server` entry is the only edit\n // that changes the program body; the new declarations are recorded\n // here and applied with the dictionary imports in step 6, so no\n // stored node is invalidated mid-rewrite.\n const serverImportsByAnchor = new Map<\n BabelTypes.ImportDeclaration,\n BabelTypes.ImportDeclaration\n >();\n const emptiedImportNodes = new Set<BabelTypes.ImportDeclaration>();\n\n for (const importNode of compatImportNodes) {\n // Compat caller import rename: point the specifier at the\n // dictionary-accepting helper exported by the compat package\n // (`useTranslation` → `useDictionary`), keeping the local alias so\n // call sites read unchanged.\n compat?.rewriteImportSpecifiers(importNode);\n }\n\n for (const importNode of nativeImportNodes) {\n // Per-import swap, mirrored across bundles — Solid hydration ids\n // rely on the SSR and client helpers consuming one resource slot\n // per call alike (see solid-intlayer/server).\n const helperPlan = getHelperPlan(importNode.source.value);\n const serverSource =\n helperPlan === 'ssrStatic'\n ? SSR_STATIC_IMPORT_SOURCE[importNode.source.value]\n : undefined;\n\n const helperMap: Record<string, string> =\n helperPlan === 'dynamic'\n ? DYNAMIC_HELPER_MAP\n : STATIC_IMPORT_FUNCTION;\n\n const serverSpecifiers: BabelTypes.ImportSpecifier[] = [];\n\n for (const spec of importNode.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = importedSpecifierName(t, spec);\n if (!isCallerName(importedName)) continue;\n\n if (serverSource && importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n serverSpecifiers.push(spec);\n continue;\n }\n\n const newIdentifier = helperMap[importedName];\n\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n\n if (serverSpecifiers.length > 0 && serverSource) {\n // Move the helper to the /server entry, keeping any other\n // specifiers (useLocale, …) on the original import.\n serverImportsByAnchor.set(\n importNode,\n t.importDeclaration(\n serverSpecifiers,\n t.stringLiteral(serverSource)\n )\n );\n\n const serverSpecifierSet = new Set<BabelTypes.Node>(\n serverSpecifiers\n );\n importNode.specifiers = importNode.specifiers.filter(\n (spec) => !serverSpecifierSet.has(spec)\n );\n\n if (importNode.specifiers.length === 0) {\n emptiedImportNodes.add(importNode);\n }\n }\n }\n\n // ── Step 5 — rewrite the call sites and bound JSX elements.\n for (const callNode of compatCallNodes) {\n compat?.rewriteCall(callNode);\n }\n\n for (const jsxNode of compatJsxNodes) {\n compat?.rewriteJsxSite(jsxNode);\n }\n\n for (const callNode of nativeCallNodes) {\n const callee = callNode.callee as BabelTypes.Identifier;\n const originalImportedName = callerMap.get(callee.name)!;\n\n const key = readStaticString(t, callNode.arguments[0]);\n if (!key) continue;\n\n const callerPackage = callerPackageMap.get(callee.name);\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const isGetIntlayerAsync =\n originalImportedName === 'getIntlayerAsync';\n const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];\n const helperPlan =\n callerPackage === undefined\n ? 'static'\n : getHelperPlan(callerPackage);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'.\n let perCallMode: ImportMode = 'static';\n\n if (isGetIntlayerAsync) {\n // Loading a single locale is the whole point of the async\n // getter, so it reads a per-locale loader whatever the file's\n // import mode is — the fetch loader when the dictionary is\n // remote, the dynamic one otherwise.\n perCallMode =\n dictionaryOverrideMode === 'fetch' ? 'fetch' : 'dynamic';\n } else if (isUseIntlayer && helperPlan === 'dynamic') {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic' || importMode === 'fetch') {\n perCallMode = importMode;\n }\n } else if (isUseIntlayer && helperPlan === 'static') {\n // The global mode is static, but a per-dictionary override can\n // still force dynamic/fetch for this specific call.\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n perCallMode = dictionaryOverrideMode;\n }\n }\n\n const ident = imports.identFor(key, perCallMode);\n\n if (perCallMode === 'static') {\n // Static helper (useDictionary / getDictionary): replace the key\n // argument with the imported dictionary object.\n callNode.arguments[0] = t.identifier(ident.name);\n } else {\n // Dynamic / fetch helper: first argument is the loader, the key\n // stays as the second one.\n callNode.arguments = [\n t.identifier(ident.name),\n ...callNode.arguments,\n ];\n }\n }\n\n // ── Step 6 — apply every body edit in one pass.\n const dictionaryImports = hasValidImport\n ? buildDictionaryImportDeclarations(t, state, imports)\n : [];\n\n const hasImportMoves =\n serverImportsByAnchor.size > 0 || emptiedImportNodes.size > 0;\n\n if (dictionaryImports.length === 0 && !hasImportMoves) return;\n\n const nextBody: BabelTypes.Statement[] = [];\n\n for (const statement of programBody) {\n if (\n t.isImportDeclaration(statement) &&\n emptiedImportNodes.has(statement)\n ) {\n // Every specifier moved to the /server entry; drop the husk.\n const serverImport = serverImportsByAnchor.get(statement);\n if (serverImport) nextBody.push(serverImport);\n continue;\n }\n\n nextBody.push(statement);\n\n if (t.isImportDeclaration(statement)) {\n const serverImport = serverImportsByAnchor.get(statement);\n if (serverImport) nextBody.push(serverImport);\n }\n }\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n let insertPos = 0;\n for (const statement of nextBody) {\n if (\n t.isExpressionStatement(statement) &&\n t.isStringLiteral(statement.expression) &&\n !statement.expression.value.startsWith('import') &&\n !statement.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n nextBody.splice(insertPos, 0, ...dictionaryImports);\n programPath.node.body = nextBody;\n },\n },\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"babel-plugin-intlayer-optimize.cjs","names":["normalizePath","relative","dirname","join","getNormalizedFilesListSet","createDictionaryImportRegistry","createCompatOptimizePass","readStaticString"],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"sourcesContent":["import { dirname, join, relative } from 'node:path';\nimport type { PluginObject, PluginPass, PluginTarget } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport type { CallerDescriptor } from '@intlayer/config/callers';\nimport { normalizePath } from '@intlayer/config/utils';\nimport {\n createCompatOptimizePass,\n type JsxSiteNode,\n} from './compat/optimizePass';\nimport {\n createDictionaryImportRegistry,\n type DictionaryImportRegistry,\n type ImportMode,\n} from './dictionaryImports';\nimport { getNormalizedFilesListSet } from './normalizedFilesList';\nimport { readStaticString } from './staticAstReaders';\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n '@intlayer/core/interpreter',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n 'astro-intlayer',\n 'remix-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer', 'getIntlayerAsync'] as const;\n\n/** Membership sets for the tables above — hit once per import and per call. */\nconst NATIVE_PACKAGE_SET: ReadonlySet<string> = new Set(PACKAGE_LIST);\nconst CALLER_NAME_SET: ReadonlySet<string> = new Set(CALLER_LIST);\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'preact-intlayer',\n 'vue-intlayer',\n 'solid-intlayer',\n 'svelte-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n] as const;\n\nconst DYNAMIC_PACKAGE_SET: ReadonlySet<string> = new Set(PACKAGE_LIST_DYNAMIC);\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n // `getIntlayerAsync` always reads a per-locale chunk, in every import mode,\n // so its helper is the same on both sides of the static/dynamic split.\n getIntlayerAsync: 'getDictionaryAsync',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/** Import rename table applied when the helper plan for a package is `dynamic`. */\nconst DYNAMIC_HELPER_MAP: Record<string, string> = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n};\n\n/**\n * Packages whose SSR-static `useDictionary` lives in a `/server` subpath\n * because it differs from the root one. Solid's reserves one hydration\n * resource slot so hydration ids stay aligned with the client's\n * `useDictionaryDynamic`; for other frameworks the root `useDictionary` is\n * already the correct SSR-static implementation.\n */\nconst SSR_STATIC_IMPORT_SOURCE: Partial<Record<string, string>> = {\n 'solid-intlayer': 'solid-intlayer/server',\n};\n\ntype CallerName = (typeof CALLER_LIST)[number];\n\n/**\n * Options for the optimization Babel plugin\n */\nexport type OptimizePluginOptions = {\n /**\n * If false, the plugin will not apply any transformation.\n */\n optimize?: boolean;\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries entry file.\n */\n unmergedDictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries directory.\n */\n unmergedDictionariesDir: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * The path to the fetch dictionaries directory.\n */\n fetchDictionariesDir: string;\n /**\n * The path to the fetch dictionaries entry file.\n */\n fetchDictionariesEntryPath: string;\n /**\n * If true, the plugin will replace the dictionary entry file with `export default {}`.\n */\n replaceDictionaryEntry: boolean;\n /**\n * Keys of the dictionaries that reference other dictionaries through\n * `nest()`.\n *\n * For those, the injected static import points at the generated companion\n * module (`<dictionariesDir>/nested/<key>.mjs`) instead of the raw JSON. The\n * companion re-exports the dictionary with its nest targets attached, so\n * `getNesting` resolves them from that local reference rather than from the\n * global registry this plugin empties — and each target lands in the chunk of\n * the dictionary referencing it.\n *\n * Dynamic and fetch modes need nothing here: their generated loaders already\n * attach the same targets per locale.\n */\n nestingDictionaryKeys?: string[];\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries. It will rely on Suspense to load the dictionaries.\n */\n importMode: 'static' | 'dynamic' | 'fetch' | undefined;\n /**\n * Map of dictionary keys to their specific import mode.\n */\n dictionaryModeMap?: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n >;\n /**\n * Files list to traverse.\n */\n filesList: string[];\n /**\n * Whether the current transform is for an SSR bundle.\n */\n isServer?: boolean;\n /**\n * Compat-adapter caller descriptors injected by the compat packages'\n * bundler plugins (e.g. `@intlayer/react-i18next/plugin`).\n *\n * Callers carrying `staticReplacement` / `dynamicReplacement` are rewritten\n * the same way as native `useIntlayer` calls: the namespace string argument\n * is replaced by a pre-imported dictionary object and the import specifier\n * is re-pointed to the dictionary-accepting variant, e.g.\n * `useTranslation('about')` → `useDictionary(_dictHash)`.\n *\n * No compat-specific name is hard-coded in this plugin — the whole rewrite\n * is driven by these descriptors.\n */\n compatCallers?: CallerDescriptor[];\n};\n\n/**\n * Per-file plugin state.\n *\n * Only the two flags that have to survive from `pre` / `Program.enter` into\n * `Program.exit` live here — the caller maps and the import registry are built\n * and consumed inside `exit`, so they stay local to it.\n */\ntype State = PluginPass & {\n opts: OptimizePluginOptions;\n /** Whether the current file *is* a generated dictionaries entry file. */\n _isDictEntry?: boolean;\n /** Whether the current file is covered by the `filesList` allowlist. */\n _isIncluded?: boolean;\n};\n\n/**\n * Builds the module specifier pointing at `targetPath` from `fromFile`, with\n * forward slashes and an explicit `./` prefix so bundlers never treat it as a\n * bare package specifier.\n */\nconst toRelativeSpecifier = (fromFile: string, targetPath: string): string => {\n // Fix windows path\n const relativePath = normalizePath(relative(dirname(fromFile), targetPath));\n\n // Fix relative path\n if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {\n return `./${relativePath}`;\n }\n\n return relativePath;\n};\n\n/**\n * Subdirectory of the compiled dictionaries holding the companion modules that\n * re-export a dictionary with its `nest()` targets attached. Mirrors\n * `NESTED_DICTIONARIES_SUBDIR` in `@intlayer/engine`.\n */\nconst NESTED_DICTIONARIES_SUBDIR = 'nested';\n\nconst computeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n fetchDictionariesDir: string,\n key: string,\n importMode: 'static' | 'dynamic' | 'fetch',\n hasNestedDictionaries = false\n): string => {\n // Static mode is the only one needing the companion: the dynamic and fetch\n // loaders already attach the nest targets per locale.\n let dictionaryPath = hasNestedDictionaries\n ? join(dictionariesDir, NESTED_DICTIONARIES_SUBDIR, `${key}.mjs`)\n : join(dictionariesDir, `${key}.json`);\n\n if (importMode === 'fetch') {\n dictionaryPath = join(fetchDictionariesDir, `${key}.mjs`);\n }\n\n if (importMode === 'dynamic') {\n dictionaryPath = join(dynamicDictionariesDir, `${key}.mjs`);\n }\n\n return toRelativeSpecifier(fromFile, dictionaryPath);\n};\n\nconst isCallerName = (name: string): name is CallerName =>\n CALLER_NAME_SET.has(name);\n\nconst isDynamicPackage = (packageName: string): boolean =>\n DYNAMIC_PACKAGE_SET.has(packageName);\n\n/** The name an import specifier brings in, whether written as an identifier or a string. */\nconst importedSpecifierName = (\n babelTypes: typeof BabelTypes,\n specifier: BabelTypes.ImportSpecifier\n): string =>\n babelTypes.isIdentifier(specifier.imported)\n ? specifier.imported.name\n : specifier.imported.value;\n\nconst EMPTY_KEY_SET: ReadonlySet<string> = new Set<string>();\n\n/**\n * `nestingDictionaryKeys` as a set, cached by array reference: Babel reuses one\n * options object for the whole build, so the set is built once instead of once\n * per transformed file.\n */\nconst nestingKeysCache = new WeakMap<readonly string[], ReadonlySet<string>>();\n\nconst getNestingDictionaryKeySet = (\n nestingDictionaryKeys: readonly string[] | undefined\n): ReadonlySet<string> => {\n if (!nestingDictionaryKeys) return EMPTY_KEY_SET;\n\n let keySet = nestingKeysCache.get(nestingDictionaryKeys);\n\n if (!keySet) {\n keySet = new Set(nestingDictionaryKeys);\n nestingKeysCache.set(nestingDictionaryKeys, keySet);\n }\n\n return keySet;\n};\n\n/**\n * Helper family every `useIntlayer`/`getIntlayer` call from one package import\n * resolves to in the current file. `ssrStatic` is the SSR bundle of a\n * dynamic-mode file: rewritten to the static `useDictionary` (from the\n * package's `/server` entry when it has one — see\n * `SSR_STATIC_IMPORT_SOURCE`) so the server renders static JSON while the\n * client keeps the dynamic loader.\n */\ntype PackageHelperPlan = 'static' | 'dynamic' | 'ssrStatic';\n\n/**\n * Decides, once per package import, which helper family applies to this file.\n * The import rewrite and the per-call rewrite must both derive from this\n * single decision, or the emitted helper and its argument shape diverge.\n *\n * Fetch wins over `ssrStatic`: fetch dictionaries are runtime content, so the\n * server must keep the real fetch path instead of rendering build-time JSON.\n */\nconst resolveHelperPlan = (\n packageName: string,\n importMode: ImportMode | undefined,\n isServer: boolean | undefined,\n packageHasDynamicCall: boolean,\n packageHasFetchCall: boolean\n): PackageHelperPlan => {\n if (!isDynamicPackage(packageName)) return 'static';\n\n if (importMode === 'fetch' || packageHasFetchCall) return 'dynamic';\n\n if (importMode === 'dynamic' || packageHasDynamicCall) {\n return isServer === true ? 'ssrStatic' : 'dynamic';\n }\n\n return 'static';\n};\n\n/**\n * Builds the dictionary import declarations the rewrite accumulated for one\n * file — the compiled JSON (or its `nest()` companion) for static reads, and\n * the generated per-locale loader for dynamic and fetch ones.\n */\nconst buildDictionaryImportDeclarations = (\n babelTypes: typeof BabelTypes,\n state: State,\n imports: DictionaryImportRegistry\n): BabelTypes.ImportDeclaration[] => {\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n nestingDictionaryKeys,\n } = state.opts;\n const fromFile = state.file.opts.filename!;\n const nestingKeys = getNestingDictionaryKeySet(nestingDictionaryKeys);\n\n const importDeclarations: BabelTypes.ImportDeclaration[] = [];\n\n // Static JSON imports — `getIntlayer` always reads a JSON dictionary.\n for (const [key, ident] of imports.staticImports) {\n // A dictionary holding `nest()` references is imported through its\n // companion module, which re-exports it with the nest targets attached.\n const hasNestedDictionaries = nestingKeys.has(key);\n\n const specifier = computeImport(\n fromFile,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n 'static',\n hasNestedDictionaries\n );\n\n const importDeclaration = babelTypes.importDeclaration(\n [babelTypes.importDefaultSpecifier(babelTypes.identifier(ident.name))],\n babelTypes.stringLiteral(specifier)\n );\n\n if (!hasNestedDictionaries) {\n importDeclaration.attributes = [\n babelTypes.importAttribute(\n babelTypes.identifier('type'),\n babelTypes.stringLiteral('json')\n ),\n ];\n }\n\n importDeclarations.push(importDeclaration);\n }\n\n // Per-locale loaders — `useIntlayer` under a dynamic or fetch helper.\n for (const [key, ident] of imports.dynamicImports) {\n const mode: ImportMode = ident.name.endsWith('_fetch')\n ? 'fetch'\n : 'dynamic';\n\n importDeclarations.push(\n babelTypes.importDeclaration(\n [babelTypes.importDefaultSpecifier(babelTypes.identifier(ident.name))],\n babelTypes.stringLiteral(\n computeImport(\n fromFile,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n mode\n )\n )\n )\n );\n }\n\n return importDeclarations;\n};\n\n/**\n * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.\n *\n * This plugin transforms calls to `useIntlayer()`, `getIntlayer()` and\n * `getIntlayerAsync()` from various Intlayer packages into optimized dictionary\n * access patterns, automatically importing the required dictionary files based\n * on the configured import mode.\n *\n * ## Supported Input Patterns\n *\n * The plugin recognizes these function calls:\n *\n * ```ts\n * // useIntlayer\n * import { useIntlayer } from 'react-intlayer';\n * import { useIntlayer } from 'next-intlayer';\n *\n * // getIntlayer / getIntlayerAsync\n * import { getIntlayer, getIntlayerAsync } from 'intlayer';\n *\n * // Usage\n * const content = useIntlayer('app');\n * const content = getIntlayer('app');\n * const content = await getIntlayerAsync('app', locale);\n * ```\n *\n * `getIntlayerAsync` is the exception to the mode table below: it always\n * resolves to the per-locale loader (`getDictionaryAsync`), in every import\n * mode, since loading a single locale is what it exists for.\n *\n * **Output (any mode):**\n * ```ts\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { getDictionaryAsync as getIntlayerAsync } from 'intlayer';\n *\n * const content = await getIntlayerAsync(_dicHash_dyn, 'app', locale);\n * ```\n *\n * ## Transformation Modes\n *\n * ### Static Mode (default: `importMode = \"static\"`)\n *\n * Imports JSON dictionaries directly and replaces function calls with dictionary access:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash);\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Dynamic Mode (`importMode = \"dynamic\"`)\n *\n * Uses dynamic dictionary loading with Suspense support:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Fetch Mode (`importMode = \"fetch\"`)\n *\n * Uses fetch-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"fetch\" value:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_fetch, \"app\");\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * > If `dictionaryModeMap` does not include the key with \"fetch\" value, the plugin will fallback to the dynamic import mode.\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n */\nconst optimizeBabelPlugin = (babel: {\n types: typeof BabelTypes;\n}): PluginObject<State> => {\n const { types: t } = babel;\n\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._isIncluded = true;\n this._isDictEntry = false;\n\n // If optimize is false, skip processing entirely\n if (this.opts.optimize === false) {\n this._isIncluded = false;\n return;\n }\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename\n ? normalizePath(this.file.opts.filename)\n : undefined;\n if (this.opts.filesList && filename) {\n const isIncluded = getNormalizedFilesListSet(this.opts.filesList).has(\n filename\n );\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n // Safe access to filename\n const filename = state.file.opts.filename\n ? normalizePath(state.file.opts.filename)\n : undefined;\n const dictionariesEntryPath = state.opts.dictionariesEntryPath\n ? normalizePath(state.opts.dictionariesEntryPath)\n : undefined;\n\n // If this file *is* the dictionaries entry, short-circuit: export {}\n // Note: unmerged_dictionaries.mjs is used by the visual editor and CMS\n // and must not be replaced with an empty dictionary map.\n if (\n state.opts.replaceDictionaryEntry &&\n filename &&\n filename === dictionariesEntryPath\n ) {\n state._isDictEntry = true;\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n t.exportNamedDeclaration(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier('getDictionaries'),\n t.arrowFunctionExpression([], t.objectExpression([]))\n ),\n ])\n ),\n ];\n }\n },\n\n /**\n * After full traversal, process imports and call expressions, then inject the JSON dictionary imports.\n *\n * We do the transformation in Program.exit (via a manual traverse) rather than using\n * top-level ImportDeclaration/CallExpression visitors. This ensures that if another plugin\n * (like babel-plugin-intlayer-extract) adds new useIntlayer calls in its Program.exit,\n * we will see and transform them here because our Program.exit runs after theirs.\n */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n\n if (!state._isIncluded) return; // early-out if file is not included\n\n const imports = createDictionaryImportRegistry(t);\n\n // Compat adapters plug in here and nowhere else: with no descriptor\n // injected the pass is `null`, every `compat?.` below is a no-op and\n // the native rewrite runs exactly as if the adapters did not exist.\n const compat = createCompatOptimizePass(\n t,\n state.opts.compatCallers ?? [],\n imports,\n {\n importMode: state.opts.importMode,\n dictionaryModeMap: state.opts.dictionaryModeMap,\n }\n );\n\n // ── Step 1 — imports.\n //\n // An import declaration is only ever a direct child of Program, so\n // the body is scanned instead of walking the whole AST, and the\n // result is complete before any call site is inspected (a file may\n // import below the calls it governs).\n const programBody = programPath.node.body;\n const nativeImportNodes: BabelTypes.ImportDeclaration[] = [];\n const compatImportNodes: BabelTypes.ImportDeclaration[] = [];\n /** Local alias → the native caller it was imported as. */\n const callerMap = new Map<string, CallerName>();\n /** Local alias → the intlayer package it was imported from. */\n const callerPackageMap = new Map<string, string>();\n /** Whether the file imported any native or compat caller at all. */\n let hasValidImport = false;\n\n for (const statement of programBody) {\n if (!t.isImportDeclaration(statement)) continue;\n\n const src = statement.source.value;\n const isNativePackage = NATIVE_PACKAGE_SET.has(src);\n const isCompatPackage = compat?.ownsImportSource(src) ?? false;\n\n if (!isNativePackage && !isCompatPackage) continue;\n\n hasValidImport = true;\n if (isNativePackage) nativeImportNodes.push(statement);\n if (isCompatPackage) compatImportNodes.push(statement);\n\n for (const spec of statement.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = importedSpecifierName(t, spec);\n\n if (isNativePackage && isCallerName(importedName)) {\n callerMap.set(spec.local.name, importedName);\n callerPackageMap.set(spec.local.name, src);\n }\n\n if (isCompatPackage) {\n compat?.noteImport(src, importedName, spec.local.name);\n }\n }\n }\n\n // ── Step 2 — the file's only AST walk, collecting the call sites\n // that either half of the rewrite can act on. Everything after\n // this point works on the collected arrays.\n const nativeCallNodes: BabelTypes.CallExpression[] = [];\n const compatCallNodes: BabelTypes.CallExpression[] = [];\n /**\n * Compat JSX elements bound by their id attribute (`<Trans id>`),\n * as source JSX or as the `jsx(Trans, …)` call the framework plugin\n * already compiled them into.\n */\n const compatJsxNodes: JsxSiteNode[] = [];\n\n // A root-scope compat caller (`useLingui()`) names its dictionaries\n // through the message ids used elsewhere in the file, so those\n // id-carrying sites are handed to the compat pass from the same walk.\n const collectMessageIds = compat?.needsMessageIdSites() ?? false;\n\n if (callerMap.size > 0 || compat?.hasCallers()) {\n programPath.traverse({\n CallExpression(path) {\n if (collectMessageIds) compat?.collectMessageIdSite(path.node);\n if (compat?.ownsJsxSite(path.node)) {\n compatJsxNodes.push(path.node);\n }\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n\n if (callerMap.has(callee.name)) {\n nativeCallNodes.push(path.node);\n } else if (compat?.ownsLocalName(callee.name)) {\n compatCallNodes.push(path.node);\n\n // `const { i18n, _, t } = useLingui()` — the destructured\n // names are how bare `t('…')` sites are told apart from\n // unrelated helpers of the same name.\n const declarator = path.parent;\n if (\n t.isVariableDeclarator(declarator) &&\n t.isObjectPattern(declarator.id)\n ) {\n compat.noteDestructuredResult(\n callee.name,\n declarator.id.properties.flatMap((property) =>\n t.isObjectProperty(property) &&\n t.isIdentifier(property.value)\n ? [property.value.name]\n : []\n )\n );\n }\n }\n },\n ...(collectMessageIds\n ? {\n TaggedTemplateExpression(path) {\n compat?.collectMessageIdSite(path.node);\n },\n }\n : {}),\n ...(compat\n ? {\n JSXOpeningElement(path) {\n if (collectMessageIds) {\n compat.collectMessageIdSite(path.node);\n }\n if (compat.ownsJsxSite(path.node)) {\n compatJsxNodes.push(path.node);\n }\n },\n }\n : {}),\n });\n }\n\n // ── Step 3 — analysis.\n //\n // A per-dictionary override reached from this file can promote a\n // whole package import to a dynamic loader, so the helper family is\n // decided per package before anything is rewritten.\n const packagesWithDynamicCall = new Set<string>();\n const packagesWithFetchCall = new Set<string>();\n\n for (const callNode of nativeCallNodes) {\n const callee = callNode.callee as BabelTypes.Identifier;\n if (callerMap.get(callee.name) !== 'useIntlayer') continue;\n\n const callerPackage = callerPackageMap.get(callee.name);\n if (!callerPackage) continue;\n\n const key = readStaticString(t, callNode.arguments[0]);\n if (!key) continue;\n\n const overrideMode = state.opts.dictionaryModeMap?.[key];\n\n if (overrideMode === 'dynamic') {\n packagesWithDynamicCall.add(callerPackage);\n } else if (overrideMode === 'fetch') {\n packagesWithFetchCall.add(callerPackage);\n }\n }\n\n // The compat half decides its own file-level helper family and drops\n // the callers whose call sites it cannot resolve.\n compat?.analyzeCalls(\n compatCallNodes,\n compatJsxNodes,\n (localName) =>\n programPath.scope.getBinding(localName)?.referencePaths.length ??\n 0\n );\n\n const helperPlanCache = new Map<string, PackageHelperPlan>();\n\n const getHelperPlan = (packageName: string): PackageHelperPlan => {\n let plan = helperPlanCache.get(packageName);\n\n if (plan === undefined) {\n plan = resolveHelperPlan(\n packageName,\n state.opts.importMode,\n state.opts.isServer,\n packagesWithDynamicCall.has(packageName),\n packagesWithFetchCall.has(packageName)\n );\n helperPlanCache.set(packageName, plan);\n }\n\n return plan;\n };\n\n // ── Step 4 — rewrite the imports.\n //\n // Moving a helper to a package's `/server` entry is the only edit\n // that changes the program body; the new declarations are recorded\n // here and applied with the dictionary imports in step 6, so no\n // stored node is invalidated mid-rewrite.\n const serverImportsByAnchor = new Map<\n BabelTypes.ImportDeclaration,\n BabelTypes.ImportDeclaration\n >();\n const emptiedImportNodes = new Set<BabelTypes.ImportDeclaration>();\n\n for (const importNode of compatImportNodes) {\n // Compat caller import rename: point the specifier at the\n // dictionary-accepting helper exported by the compat package\n // (`useTranslation` → `useDictionary`), keeping the local alias so\n // call sites read unchanged.\n compat?.rewriteImportSpecifiers(importNode);\n }\n\n for (const importNode of nativeImportNodes) {\n // Per-import swap, mirrored across bundles — Solid hydration ids\n // rely on the SSR and client helpers consuming one resource slot\n // per call alike (see solid-intlayer/server).\n const helperPlan = getHelperPlan(importNode.source.value);\n const serverSource =\n helperPlan === 'ssrStatic'\n ? SSR_STATIC_IMPORT_SOURCE[importNode.source.value]\n : undefined;\n\n const helperMap: Record<string, string> =\n helperPlan === 'dynamic'\n ? DYNAMIC_HELPER_MAP\n : STATIC_IMPORT_FUNCTION;\n\n const serverSpecifiers: BabelTypes.ImportSpecifier[] = [];\n\n for (const spec of importNode.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = importedSpecifierName(t, spec);\n if (!isCallerName(importedName)) continue;\n\n if (serverSource && importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n serverSpecifiers.push(spec);\n continue;\n }\n\n const newIdentifier = helperMap[importedName];\n\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n\n if (serverSpecifiers.length > 0 && serverSource) {\n // Move the helper to the /server entry, keeping any other\n // specifiers (useLocale, …) on the original import.\n serverImportsByAnchor.set(\n importNode,\n t.importDeclaration(\n serverSpecifiers,\n t.stringLiteral(serverSource)\n )\n );\n\n const serverSpecifierSet = new Set<BabelTypes.Node>(\n serverSpecifiers\n );\n importNode.specifiers = importNode.specifiers.filter(\n (spec) => !serverSpecifierSet.has(spec)\n );\n\n if (importNode.specifiers.length === 0) {\n emptiedImportNodes.add(importNode);\n }\n }\n }\n\n // ── Step 5 — rewrite the call sites and bound JSX elements.\n for (const callNode of compatCallNodes) {\n compat?.rewriteCall(callNode);\n }\n\n for (const jsxNode of compatJsxNodes) {\n compat?.rewriteJsxSite(jsxNode);\n }\n\n for (const callNode of nativeCallNodes) {\n const callee = callNode.callee as BabelTypes.Identifier;\n const originalImportedName = callerMap.get(callee.name)!;\n\n const key = readStaticString(t, callNode.arguments[0]);\n if (!key) continue;\n\n const callerPackage = callerPackageMap.get(callee.name);\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const isGetIntlayerAsync =\n originalImportedName === 'getIntlayerAsync';\n const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];\n const helperPlan =\n callerPackage === undefined\n ? 'static'\n : getHelperPlan(callerPackage);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'.\n let perCallMode: ImportMode = 'static';\n\n if (isGetIntlayerAsync) {\n // Loading a single locale is the whole point of the async\n // getter, so it reads a per-locale loader whatever the file's\n // import mode is — the fetch loader when the dictionary is\n // remote, the dynamic one otherwise.\n perCallMode =\n dictionaryOverrideMode === 'fetch' ? 'fetch' : 'dynamic';\n } else if (isUseIntlayer && helperPlan === 'dynamic') {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic' || importMode === 'fetch') {\n perCallMode = importMode;\n }\n } else if (isUseIntlayer && helperPlan === 'static') {\n // The global mode is static, but a per-dictionary override can\n // still force dynamic/fetch for this specific call.\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n perCallMode = dictionaryOverrideMode;\n }\n }\n\n const ident = imports.identFor(key, perCallMode);\n\n if (perCallMode === 'static') {\n // Static helper (useDictionary / getDictionary): replace the key\n // argument with the imported dictionary object.\n callNode.arguments[0] = t.identifier(ident.name);\n } else {\n // Dynamic / fetch helper: first argument is the loader, the key\n // stays as the second one.\n callNode.arguments = [\n t.identifier(ident.name),\n ...callNode.arguments,\n ];\n }\n }\n\n // ── Step 6 — apply every body edit in one pass.\n const dictionaryImports = hasValidImport\n ? buildDictionaryImportDeclarations(t, state, imports)\n : [];\n\n const hasImportMoves =\n serverImportsByAnchor.size > 0 || emptiedImportNodes.size > 0;\n\n if (dictionaryImports.length === 0 && !hasImportMoves) return;\n\n const nextBody: BabelTypes.Statement[] = [];\n\n for (const statement of programBody) {\n if (\n t.isImportDeclaration(statement) &&\n emptiedImportNodes.has(statement)\n ) {\n // Every specifier moved to the /server entry; drop the husk.\n const serverImport = serverImportsByAnchor.get(statement);\n if (serverImport) nextBody.push(serverImport);\n continue;\n }\n\n nextBody.push(statement);\n\n if (t.isImportDeclaration(statement)) {\n const serverImport = serverImportsByAnchor.get(statement);\n if (serverImport) nextBody.push(serverImport);\n }\n }\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n let insertPos = 0;\n for (const statement of nextBody) {\n if (\n t.isExpressionStatement(statement) &&\n t.isStringLiteral(statement.expression) &&\n !statement.expression.value.startsWith('import') &&\n !statement.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n nextBody.splice(insertPos, 0, ...dictionaryImports);\n programPath.node.body = nextBody;\n },\n },\n },\n };\n};\n\n/**\n * Intlayer optimize Babel plugin (see `optimizeBabelPlugin`), typed as Babel's\n * `PluginTarget`.\n *\n * Babel types tuple options as `object` (`[PluginTarget<object>, object]`), so\n * a plugin whose handlers read typed `this.opts` is rejected in\n * `plugins: [[plugin, options]]` under `strict`. The options passed in the\n * tuple are the typed options read by the handlers.\n */\nexport const intlayerOptimizeBabelPlugin: PluginTarget =\n optimizeBabelPlugin as PluginTarget;\n"],"mappings":"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"}
@@ -139,6 +139,8 @@ const analyzeCodeBlockSync = (code, sourceFilePath, pruneContext, compatCallers)
139
139
  filename: sourceFilePath,
140
140
  plugins: [require_babel_plugin_intlayer_usage_analyzer.makeUsageAnalyzerBabelPlugin(pruneContext, { compatCallers })],
141
141
  parserOpts: require_transformers.BABEL_PARSER_OPTIONS,
142
+ babelrc: false,
143
+ configFile: false,
142
144
  ast: false,
143
145
  code: false
144
146
  });