@intlayer/babel 9.4.4 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +0 -2
  2. package/dist/cjs/analyzeContentUsage.cjs +301 -0
  3. package/dist/cjs/analyzeContentUsage.cjs.map +1 -0
  4. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +5 -4
  5. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
  6. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +173 -282
  7. package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
  8. package/dist/cjs/babel-plugin-intlayer-purge.cjs +4 -3
  9. package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
  10. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +49 -699
  11. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
  12. package/dist/cjs/compat/namespaceResolution.cjs +124 -0
  13. package/dist/cjs/compat/namespaceResolution.cjs.map +1 -0
  14. package/dist/cjs/compat/optimizePass.cjs +144 -0
  15. package/dist/cjs/compat/optimizePass.cjs.map +1 -0
  16. package/dist/cjs/compat/usageAnalysis.cjs +195 -0
  17. package/dist/cjs/compat/usageAnalysis.cjs.map +1 -0
  18. package/dist/cjs/dictionaryImports.cjs +40 -0
  19. package/dist/cjs/dictionaryImports.cjs.map +1 -0
  20. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +1 -1
  21. package/dist/cjs/getExtractPluginOptions.cjs +1 -1
  22. package/dist/cjs/getOptimizePluginOptions.cjs +1 -1
  23. package/dist/cjs/getPurgePluginOptions.cjs +1 -1
  24. package/dist/cjs/index.cjs +9 -5
  25. package/dist/cjs/nativeCallers.cjs +41 -0
  26. package/dist/cjs/nativeCallers.cjs.map +1 -0
  27. package/dist/cjs/pruneContext.cjs +79 -0
  28. package/dist/cjs/pruneContext.cjs.map +1 -0
  29. package/dist/cjs/staticAstReaders.cjs +140 -0
  30. package/dist/cjs/staticAstReaders.cjs.map +1 -0
  31. package/dist/cjs/transformers.cjs +2 -1
  32. package/dist/cjs/transformers.cjs.map +1 -1
  33. package/dist/esm/analyzeContentUsage.mjs +300 -0
  34. package/dist/esm/analyzeContentUsage.mjs.map +1 -0
  35. package/dist/esm/babel-plugin-intlayer-field-rename.mjs +3 -2
  36. package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
  37. package/dist/esm/babel-plugin-intlayer-optimize.mjs +173 -282
  38. package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
  39. package/dist/esm/babel-plugin-intlayer-purge.mjs +3 -2
  40. package/dist/esm/babel-plugin-intlayer-purge.mjs.map +1 -1
  41. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +43 -694
  42. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
  43. package/dist/esm/compat/namespaceResolution.mjs +120 -0
  44. package/dist/esm/compat/namespaceResolution.mjs.map +1 -0
  45. package/dist/esm/compat/optimizePass.mjs +143 -0
  46. package/dist/esm/compat/optimizePass.mjs.map +1 -0
  47. package/dist/esm/compat/usageAnalysis.mjs +193 -0
  48. package/dist/esm/compat/usageAnalysis.mjs.map +1 -0
  49. package/dist/esm/dictionaryImports.mjs +38 -0
  50. package/dist/esm/dictionaryImports.mjs.map +1 -0
  51. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +1 -1
  52. package/dist/esm/getExtractPluginOptions.mjs +1 -1
  53. package/dist/esm/getOptimizePluginOptions.mjs +1 -1
  54. package/dist/esm/getPurgePluginOptions.mjs +1 -1
  55. package/dist/esm/index.mjs +5 -2
  56. package/dist/esm/nativeCallers.mjs +38 -0
  57. package/dist/esm/nativeCallers.mjs.map +1 -0
  58. package/dist/esm/pruneContext.mjs +76 -0
  59. package/dist/esm/pruneContext.mjs.map +1 -0
  60. package/dist/esm/staticAstReaders.mjs +129 -0
  61. package/dist/esm/staticAstReaders.mjs.map +1 -0
  62. package/dist/esm/transformers.mjs +2 -1
  63. package/dist/esm/transformers.mjs.map +1 -1
  64. package/dist/types/analyzeContentUsage.d.ts +18 -0
  65. package/dist/types/analyzeContentUsage.d.ts.map +1 -0
  66. package/dist/types/babel-plugin-intlayer-field-rename.d.ts +2 -1
  67. package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  68. package/dist/types/babel-plugin-intlayer-optimize.d.ts +9 -15
  69. package/dist/types/babel-plugin-intlayer-optimize.d.ts.map +1 -1
  70. package/dist/types/babel-plugin-intlayer-purge.d.ts +3 -2
  71. package/dist/types/babel-plugin-intlayer-purge.d.ts.map +1 -1
  72. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +20 -187
  73. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
  74. package/dist/types/compat/namespaceResolution.d.ts +66 -0
  75. package/dist/types/compat/namespaceResolution.d.ts.map +1 -0
  76. package/dist/types/compat/optimizePass.d.ts +58 -0
  77. package/dist/types/compat/optimizePass.d.ts.map +1 -0
  78. package/dist/types/compat/usageAnalysis.d.ts +75 -0
  79. package/dist/types/compat/usageAnalysis.d.ts.map +1 -0
  80. package/dist/types/dictionaryImports.d.ts +46 -0
  81. package/dist/types/dictionaryImports.d.ts.map +1 -0
  82. package/dist/types/index.d.ts +5 -2
  83. package/dist/types/nativeCallers.d.ts +33 -0
  84. package/dist/types/nativeCallers.d.ts.map +1 -0
  85. package/dist/types/pruneContext.d.ts +152 -0
  86. package/dist/types/pruneContext.d.ts.map +1 -0
  87. package/dist/types/staticAstReaders.d.ts +84 -0
  88. package/dist/types/staticAstReaders.d.ts.map +1 -0
  89. package/dist/types/transformers.d.ts +2 -1
  90. package/dist/types/transformers.d.ts.map +1 -1
  91. package/package.json +10 -10
package/README.md CHANGED
@@ -69,8 +69,6 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
69
69
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
70
70
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
71
71
 
72
- ---
73
-
74
72
  ## 📦 Installation
75
73
 
76
74
  Start your journey with Intlayer today and experience a smoother, more powerful approach to internationalization.
@@ -0,0 +1,301 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_nativeCallers = require('./nativeCallers.cjs');
3
+ const require_pruneContext = require('./pruneContext.cjs');
4
+ const require_staticAstReaders = require('./staticAstReaders.cjs');
5
+
6
+ //#region src/analyzeContentUsage.ts
7
+ /**
8
+ * Analyses how the result of a single `useIntlayer('key')` / `getIntlayer('key')`
9
+ * call expression is consumed, then records the field usage into `pruneContext`.
10
+ *
11
+ * Recognised patterns:
12
+ * const { fieldA, fieldB } = useIntlayer('key') → records {fieldA, fieldB}
13
+ * useIntlayer('key').fieldA → records {fieldA}
14
+ * useIntlayer('key')['fieldA'] → records {fieldA}
15
+ * const { ...rest } = useIntlayer('key') → records 'all' (spread)
16
+ * const result = useIntlayer('key') → records 'all' (untracked binding)
17
+ */
18
+ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath, dictionaryKey, currentSourceFilePath, isSfcFile) => {
19
+ /** Mark the dictionary key as having an untracked binding in this file. */
20
+ const markUntrackedBinding = () => {
21
+ const existingPaths = pruneContext.dictionaryKeysWithUntrackedBindings.get(dictionaryKey) ?? [];
22
+ if (!existingPaths.includes(currentSourceFilePath)) pruneContext.dictionaryKeysWithUntrackedBindings.set(dictionaryKey, [...existingPaths, currentSourceFilePath]);
23
+ require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, "all");
24
+ };
25
+ /** Record that the content value at `fieldPath` is consumed opaquely. */
26
+ const markOpaqueField = (fieldPath, line) => {
27
+ const pathToOccurrence = pruneContext.dictionaryKeysWithOpaqueFields.get(dictionaryKey) ?? /* @__PURE__ */ new Map();
28
+ const location = line !== void 0 ? `${currentSourceFilePath}:${line}` : currentSourceFilePath;
29
+ const joinedFieldPath = fieldPath.join(".");
30
+ const occurrence = pathToOccurrence.get(joinedFieldPath) ?? {
31
+ fieldPath: [...fieldPath],
32
+ locations: []
33
+ };
34
+ if (!occurrence.locations.includes(location)) occurrence.locations.push(location);
35
+ pathToOccurrence.set(joinedFieldPath, occurrence);
36
+ pruneContext.dictionaryKeysWithOpaqueFields.set(dictionaryKey, pathToOccurrence);
37
+ };
38
+ /** Register a plain variable binding in an SFC file for a second-pass analysis. */
39
+ const deferFrameworkAnalysis = (variableName) => {
40
+ const existing = pruneContext.pendingFrameworkAnalysis.get(currentSourceFilePath) ?? [];
41
+ if (!existing.some((e) => e.variableName === variableName && e.dictionaryKey === dictionaryKey)) existing.push({
42
+ variableName,
43
+ dictionaryKey
44
+ });
45
+ pruneContext.pendingFrameworkAnalysis.set(currentSourceFilePath, existing);
46
+ };
47
+ /**
48
+ * Analyses how the content value at `fieldPath` (currently referenced by
49
+ * `refPath`) is consumed, to detect opaque consumption (passing a dictionary
50
+ * value as-is to a prop or function argument).
51
+ *
52
+ * Member-access chains and destructuring are followed recursively with an
53
+ * extended field path, so the *terminal* consumption of a chain like
54
+ * `content.sections.hero` decides opacity — mirroring how far the
55
+ * source-code renamer can rewrite accesses. When the terminal consumption
56
+ * escapes static tracking, the deepest reached field path is marked opaque
57
+ * so the children of that value keep their original key names.
58
+ */
59
+ const analyzeOpaqueUsage = (refPath, fieldPath) => {
60
+ const parentNode = refPath.parent;
61
+ const parentPath = refPath.parentPath;
62
+ if (parentPath && (babelTypes.isMemberExpression(parentNode) || babelTypes.isOptionalMemberExpression(parentNode)) && parentNode.object === refPath.node) {
63
+ const memberNode = parentNode;
64
+ if (memberNode.computed && babelTypes.isNumericLiteral(memberNode.property)) {
65
+ analyzeOpaqueUsage(parentPath, fieldPath);
66
+ return;
67
+ }
68
+ if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {
69
+ analyzeOpaqueUsage(parentPath, [...fieldPath, memberNode.property.name]);
70
+ return;
71
+ }
72
+ if (memberNode.computed && babelTypes.isStringLiteral(memberNode.property)) {
73
+ analyzeOpaqueUsage(parentPath, [...fieldPath, memberNode.property.value]);
74
+ return;
75
+ }
76
+ markOpaqueField(fieldPath, refPath.node.loc?.start.line);
77
+ return;
78
+ }
79
+ if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isObjectPattern(parentNode.id) && parentNode.init === refPath.node) {
80
+ analyzeOpaqueDestructuring(parentNode.id, refPath, fieldPath);
81
+ return;
82
+ }
83
+ if (babelTypes.isArrayExpression(parentNode)) return;
84
+ markOpaqueField(fieldPath, refPath.node.loc?.start.line);
85
+ };
86
+ /**
87
+ * Analyses a destructuring pattern applied to the content value at
88
+ * `fieldPath`, recursively following each bound local variable's references
89
+ * via {@link analyzeOpaqueUsage}.
90
+ *
91
+ * Patterns the source-code renamer cannot rewrite (rest elements, dynamic
92
+ * computed keys, array patterns) mark the corresponding path opaque.
93
+ */
94
+ const analyzeOpaqueDestructuring = (objectPattern, scopePath, fieldPath) => {
95
+ for (const property of objectPattern.properties) {
96
+ if (babelTypes.isRestElement(property)) {
97
+ markOpaqueField(fieldPath, property.loc?.start.line);
98
+ continue;
99
+ }
100
+ if (!babelTypes.isObjectProperty(property)) continue;
101
+ if (property.computed && !babelTypes.isStringLiteral(property.key)) {
102
+ markOpaqueField(fieldPath, property.loc?.start.line);
103
+ continue;
104
+ }
105
+ const keyName = babelTypes.isIdentifier(property.key) ? property.key.name : babelTypes.isStringLiteral(property.key) ? property.key.value : null;
106
+ if (!keyName) continue;
107
+ const childFieldPath = [...fieldPath, keyName];
108
+ const bindingTarget = babelTypes.isAssignmentPattern(property.value) ? property.value.left : property.value;
109
+ if (babelTypes.isObjectPattern(bindingTarget)) {
110
+ analyzeOpaqueDestructuring(bindingTarget, scopePath, childFieldPath);
111
+ continue;
112
+ }
113
+ if (babelTypes.isIdentifier(bindingTarget)) {
114
+ const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);
115
+ if (!localVarBinding) continue;
116
+ for (const referencePath of localVarBinding.referencePaths) analyzeOpaqueUsage(referencePath, childFieldPath);
117
+ continue;
118
+ }
119
+ markOpaqueField(childFieldPath, property.loc?.start.line);
120
+ }
121
+ };
122
+ /**
123
+ * Helper to collect field names from an ObjectPattern (destructuring).
124
+ * Returns true if successful, false when the accessed fields cannot be
125
+ * determined statically (rest element or dynamic computed key → 'all').
126
+ */
127
+ const collectFieldsFromObjectPattern = (pattern, initPath, targetSet) => {
128
+ if (pattern.properties.some((prop) => babelTypes.isRestElement(prop))) return false;
129
+ for (const property of pattern.properties) {
130
+ if (!babelTypes.isObjectProperty(property)) continue;
131
+ if (property.computed && !babelTypes.isStringLiteral(property.key)) return false;
132
+ let fieldName;
133
+ if (!property.computed && babelTypes.isIdentifier(property.key)) fieldName = property.key.name;
134
+ else if (babelTypes.isStringLiteral(property.key)) fieldName = property.key.value;
135
+ if (!fieldName) continue;
136
+ targetSet.add(fieldName);
137
+ const bindingTarget = babelTypes.isAssignmentPattern(property.value) ? property.value.left : property.value;
138
+ if (babelTypes.isIdentifier(bindingTarget)) {
139
+ const variableBinding = initPath.scope.getBinding(bindingTarget.name);
140
+ if (variableBinding) for (const refPath of variableBinding.referencePaths) analyzeOpaqueUsage(refPath, [fieldName]);
141
+ } else if (babelTypes.isObjectPattern(bindingTarget)) analyzeOpaqueDestructuring(bindingTarget, initPath, [fieldName]);
142
+ else markOpaqueField([fieldName], property.loc?.start.line);
143
+ }
144
+ return true;
145
+ };
146
+ /**
147
+ * Returns the call path when `memberExprPath` is a chainable runtime helper
148
+ * being invoked (`content.onChange(cb)`), otherwise `undefined`.
149
+ *
150
+ * See {@link CHAINABLE_RUNTIME_METHOD_NAMES}: a bare `content.onChange`
151
+ * reference that is never called is treated as an ordinary field access, so
152
+ * only the invoked form is looked through.
153
+ */
154
+ const getChainedRuntimeCallPath = (memberExprPath, fieldName) => {
155
+ if (!require_nativeCallers.CHAINABLE_RUNTIME_METHOD_NAMES.has(fieldName)) return void 0;
156
+ if (!memberExprPath) return void 0;
157
+ const callPath = memberExprPath.parentPath;
158
+ if (!callPath) return void 0;
159
+ if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) return;
160
+ if (callPath.node.callee !== memberExprPath.node) return;
161
+ return callPath;
162
+ };
163
+ /**
164
+ * Analyses the callbacks handed to a chainable runtime helper.
165
+ *
166
+ * The callback receives the freshly-resolved content root, so its parameter
167
+ * is walked exactly like `const content = useIntlayer('key')` — either as a
168
+ * plain binding or as a destructuring pattern.
169
+ */
170
+ const analyzeChainedCallbackArguments = (callPath) => {
171
+ const argumentPaths = callPath.get("arguments");
172
+ for (const argumentPath of argumentPaths) {
173
+ if (!argumentPath.isArrowFunctionExpression() && !argumentPath.isFunctionExpression()) continue;
174
+ const [firstParameterPath] = argumentPath.get("params");
175
+ if (!firstParameterPath) continue;
176
+ if (firstParameterPath.isIdentifier()) {
177
+ const parameterBinding = argumentPath.scope.getBinding(firstParameterPath.node.name);
178
+ if (!parameterBinding) {
179
+ markUntrackedBinding();
180
+ continue;
181
+ }
182
+ const accessedFieldNames = /* @__PURE__ */ new Set();
183
+ if (analyzeContentBindingReferences(parameterBinding, accessedFieldNames)) markUntrackedBinding();
184
+ else require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
185
+ continue;
186
+ }
187
+ if (firstParameterPath.isObjectPattern()) {
188
+ const accessedFieldNames = /* @__PURE__ */ new Set();
189
+ if (collectFieldsFromObjectPattern(firstParameterPath.node, argumentPath, accessedFieldNames)) require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
190
+ else require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, "all");
191
+ continue;
192
+ }
193
+ markUntrackedBinding();
194
+ }
195
+ };
196
+ /**
197
+ * Walks every reference of a local binding holding the content root,
198
+ * collecting the top-level fields it reads into `accessedTopLevelFieldNames`.
199
+ *
200
+ * @returns `true` when a reference escaped static tracking, meaning the whole
201
+ * dictionary must be kept.
202
+ */
203
+ const analyzeContentBindingReferences = (variableBinding, accessedTopLevelFieldNames) => {
204
+ for (const variableReferencePath of variableBinding.referencePaths) {
205
+ const referenceParentNode = variableReferencePath.parent;
206
+ if ((babelTypes.isMemberExpression(referenceParentNode) || babelTypes.isOptionalMemberExpression(referenceParentNode)) && referenceParentNode.object === variableReferencePath.node) {
207
+ const memberExpressionNode = referenceParentNode;
208
+ let fieldName;
209
+ if (!memberExpressionNode.computed && babelTypes.isIdentifier(memberExpressionNode.property)) fieldName = memberExpressionNode.property.name;
210
+ else if (memberExpressionNode.computed && babelTypes.isStringLiteral(memberExpressionNode.property)) fieldName = memberExpressionNode.property.value;
211
+ if (fieldName) {
212
+ const memberExprPath = variableReferencePath.parentPath;
213
+ const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
214
+ if (chainedCallPath) {
215
+ analyzeChainedCallbackArguments(chainedCallPath);
216
+ analyzeContentRoot(chainedCallPath);
217
+ continue;
218
+ }
219
+ accessedTopLevelFieldNames.add(fieldName);
220
+ if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
221
+ } else return true;
222
+ } else if (babelTypes.isArrayExpression(referenceParentNode)) return true;
223
+ else if ((babelTypes.isCallExpression(referenceParentNode) || babelTypes.isOptionalCallExpression(referenceParentNode)) && referenceParentNode.callee === variableReferencePath.node) {
224
+ const callExprPath = variableReferencePath.parentPath;
225
+ const callParent = callExprPath?.parent;
226
+ if (callParent && (babelTypes.isMemberExpression(callParent) || babelTypes.isOptionalMemberExpression(callParent)) && callParent.object === callExprPath?.node) {
227
+ const memberExpr = callParent;
228
+ let fieldName;
229
+ if (!memberExpr.computed && babelTypes.isIdentifier(memberExpr.property)) fieldName = memberExpr.property.name;
230
+ else if (memberExpr.computed && babelTypes.isStringLiteral(memberExpr.property)) fieldName = memberExpr.property.value;
231
+ if (fieldName) {
232
+ const memberExprPath = callExprPath?.parentPath;
233
+ const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
234
+ if (chainedCallPath) {
235
+ analyzeChainedCallbackArguments(chainedCallPath);
236
+ analyzeContentRoot(chainedCallPath);
237
+ continue;
238
+ }
239
+ accessedTopLevelFieldNames.add(fieldName);
240
+ if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
241
+ } else return true;
242
+ } else if (callParent && babelTypes.isVariableDeclarator(callParent) && babelTypes.isObjectPattern(callParent.id) && callExprPath && collectFieldsFromObjectPattern(callParent.id, callExprPath, accessedTopLevelFieldNames)) {} else return true;
243
+ } else return true;
244
+ }
245
+ return false;
246
+ };
247
+ /**
248
+ * Analyses how the content root referenced by `rootPath` is consumed.
249
+ *
250
+ * `rootPath` is the `useIntlayer('key')` call itself, or any expression that
251
+ * evaluates back to the same content object — currently the result of a
252
+ * chainable runtime helper such as `.onChange(…)`.
253
+ */
254
+ const analyzeContentRoot = (rootPath) => {
255
+ const parentNode = rootPath.parent;
256
+ if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isObjectPattern(parentNode.id)) {
257
+ const accessedFieldNames = /* @__PURE__ */ new Set();
258
+ if (collectFieldsFromObjectPattern(parentNode.id, rootPath, accessedFieldNames)) require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
259
+ else require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, "all");
260
+ return;
261
+ }
262
+ if ((babelTypes.isMemberExpression(parentNode) || babelTypes.isOptionalMemberExpression(parentNode)) && parentNode.object === rootPath.node) {
263
+ let fieldName;
264
+ if (!parentNode.computed && babelTypes.isIdentifier(parentNode.property)) fieldName = parentNode.property.name;
265
+ else if (parentNode.computed && babelTypes.isStringLiteral(parentNode.property)) fieldName = parentNode.property.value;
266
+ if (fieldName) {
267
+ const memberExprPath = rootPath.parentPath;
268
+ const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
269
+ if (chainedCallPath) {
270
+ analyzeChainedCallbackArguments(chainedCallPath);
271
+ analyzeContentRoot(chainedCallPath);
272
+ return;
273
+ }
274
+ require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([fieldName]));
275
+ if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
276
+ } else markUntrackedBinding();
277
+ return;
278
+ }
279
+ if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isIdentifier(parentNode.id)) {
280
+ const variableName = parentNode.id.name;
281
+ const variableBinding = rootPath.scope.getBinding(variableName);
282
+ if (!variableBinding) {
283
+ markUntrackedBinding();
284
+ return;
285
+ }
286
+ const accessedTopLevelFieldNames = /* @__PURE__ */ new Set();
287
+ if (analyzeContentBindingReferences(variableBinding, accessedTopLevelFieldNames)) markUntrackedBinding();
288
+ else if (isSfcFile) deferFrameworkAnalysis(variableName);
289
+ else if (variableBinding.referencePaths.length === 0) markUntrackedBinding();
290
+ else require_pruneContext.recordFieldUsage(pruneContext, dictionaryKey, accessedTopLevelFieldNames);
291
+ return;
292
+ }
293
+ if (babelTypes.isExpressionStatement(parentNode)) return;
294
+ markUntrackedBinding();
295
+ };
296
+ analyzeContentRoot(require_staticAstReaders.unwrapAwait(babelTypes, callExpressionPath));
297
+ };
298
+
299
+ //#endregion
300
+ exports.analyzeCallExpressionUsage = analyzeCallExpressionUsage;
301
+ //# sourceMappingURL=analyzeContentUsage.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzeContentUsage.cjs","names":["CHAINABLE_RUNTIME_METHOD_NAMES","unwrapAwait"],"sources":["../../src/analyzeContentUsage.ts"],"sourcesContent":["import type { NodePath } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport { CHAINABLE_RUNTIME_METHOD_NAMES } from './nativeCallers';\nimport {\n type OpaqueFieldOccurrence,\n type PruneContext,\n recordFieldUsage,\n} from './pruneContext';\nimport { unwrapAwait } from './staticAstReaders';\n\n/**\n * Analyses how the result of a single `useIntlayer('key')` / `getIntlayer('key')`\n * call expression is consumed, then records the field usage into `pruneContext`.\n *\n * Recognised patterns:\n * const { fieldA, fieldB } = useIntlayer('key') → records {fieldA, fieldB}\n * useIntlayer('key').fieldA → records {fieldA}\n * useIntlayer('key')['fieldA'] → records {fieldA}\n * const { ...rest } = useIntlayer('key') → records 'all' (spread)\n * const result = useIntlayer('key') → records 'all' (untracked binding)\n */\nexport const analyzeCallExpressionUsage = (\n babelTypes: typeof BabelTypes,\n pruneContext: PruneContext,\n callExpressionPath: NodePath<BabelTypes.CallExpression>,\n dictionaryKey: string,\n currentSourceFilePath: string,\n isSfcFile: boolean\n): void => {\n /** Mark the dictionary key as having an untracked binding in this file. */\n const markUntrackedBinding = (): void => {\n const existingPaths =\n pruneContext.dictionaryKeysWithUntrackedBindings.get(dictionaryKey) ?? [];\n if (!existingPaths.includes(currentSourceFilePath)) {\n pruneContext.dictionaryKeysWithUntrackedBindings.set(dictionaryKey, [\n ...existingPaths,\n currentSourceFilePath,\n ]);\n }\n recordFieldUsage(pruneContext, dictionaryKey, 'all');\n };\n\n /** Record that the content value at `fieldPath` is consumed opaquely. */\n const markOpaqueField = (\n fieldPath: string[],\n line: number | undefined\n ): void => {\n const pathToOccurrence =\n pruneContext.dictionaryKeysWithOpaqueFields.get(dictionaryKey) ??\n new Map<string, OpaqueFieldOccurrence>();\n const location =\n line !== undefined\n ? `${currentSourceFilePath}:${line}`\n : currentSourceFilePath;\n const joinedFieldPath = fieldPath.join('.');\n const occurrence = pathToOccurrence.get(joinedFieldPath) ?? {\n fieldPath: [...fieldPath],\n locations: [],\n };\n if (!occurrence.locations.includes(location)) {\n occurrence.locations.push(location);\n }\n pathToOccurrence.set(joinedFieldPath, occurrence);\n pruneContext.dictionaryKeysWithOpaqueFields.set(\n dictionaryKey,\n pathToOccurrence\n );\n };\n\n /** Register a plain variable binding in an SFC file for a second-pass analysis. */\n const deferFrameworkAnalysis = (variableName: string): void => {\n const existing =\n pruneContext.pendingFrameworkAnalysis.get(currentSourceFilePath) ?? [];\n if (\n !existing.some(\n (e) =>\n e.variableName === variableName && e.dictionaryKey === dictionaryKey\n )\n ) {\n existing.push({ variableName, dictionaryKey });\n }\n pruneContext.pendingFrameworkAnalysis.set(currentSourceFilePath, existing);\n };\n\n /**\n * Analyses how the content value at `fieldPath` (currently referenced by\n * `refPath`) is consumed, to detect opaque consumption (passing a dictionary\n * value as-is to a prop or function argument).\n *\n * Member-access chains and destructuring are followed recursively with an\n * extended field path, so the *terminal* consumption of a chain like\n * `content.sections.hero` decides opacity — mirroring how far the\n * source-code renamer can rewrite accesses. When the terminal consumption\n * escapes static tracking, the deepest reached field path is marked opaque\n * so the children of that value keep their original key names.\n */\n const analyzeOpaqueUsage = (\n refPath: NodePath<BabelTypes.Node>,\n fieldPath: string[]\n ): void => {\n const parentNode = refPath.parent;\n const parentPath = refPath.parentPath;\n\n // 1. Chained member access (e.g. field.sub or field?.sub): follow the\n // chain with an extended path and analyse the terminal consumption.\n if (\n parentPath &&\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object === refPath.node\n ) {\n const memberNode = parentNode as BabelTypes.MemberExpression;\n\n // Numeric index access ([0], [1], …) is transparent: the JSON renamers\n // apply the same rename map to every array element.\n if (\n memberNode.computed &&\n babelTypes.isNumericLiteral(memberNode.property)\n ) {\n analyzeOpaqueUsage(parentPath, fieldPath);\n return;\n }\n\n if (\n !memberNode.computed &&\n babelTypes.isIdentifier(memberNode.property)\n ) {\n analyzeOpaqueUsage(parentPath, [\n ...fieldPath,\n memberNode.property.name,\n ]);\n return;\n }\n\n if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n analyzeOpaqueUsage(parentPath, [\n ...fieldPath,\n memberNode.property.value,\n ]);\n return;\n }\n\n // Dynamic computed access (field[expr]): the renamer cannot rewrite the\n // key, so the children of the current path must keep their names.\n markOpaqueField(fieldPath, refPath.node.loc?.start.line);\n return;\n }\n\n // 2. Destructuring (e.g. const { sub } = field): follow each binding.\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isObjectPattern(parentNode.id) &&\n parentNode.init === refPath.node\n ) {\n analyzeOpaqueDestructuring(parentNode.id, refPath, fieldPath);\n return;\n }\n\n // 3. Ignored patterns (e.g. array literals [content])\n if (babelTypes.isArrayExpression(parentNode)) {\n return;\n }\n\n // 4. Opaque consumption (passed to prop, function, etc.)\n markOpaqueField(fieldPath, refPath.node.loc?.start.line);\n };\n\n /**\n * Analyses a destructuring pattern applied to the content value at\n * `fieldPath`, recursively following each bound local variable's references\n * via {@link analyzeOpaqueUsage}.\n *\n * Patterns the source-code renamer cannot rewrite (rest elements, dynamic\n * computed keys, array patterns) mark the corresponding path opaque.\n */\n const analyzeOpaqueDestructuring = (\n objectPattern: BabelTypes.ObjectPattern,\n scopePath: NodePath<BabelTypes.Node>,\n fieldPath: string[]\n ): void => {\n for (const property of objectPattern.properties) {\n // A rest element re-exposes the remaining fields under their original\n // names — nothing at this level may be renamed.\n if (babelTypes.isRestElement(property)) {\n markOpaqueField(fieldPath, property.loc?.start.line);\n continue;\n }\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Dynamic computed keys ({ [expr]: x }) cannot be renamed.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n markOpaqueField(fieldPath, property.loc?.start.line);\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 childFieldPath = [...fieldPath, keyName];\n\n // A default value ({ field = fallback }) wraps the binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n if (babelTypes.isObjectPattern(bindingTarget)) {\n analyzeOpaqueDestructuring(bindingTarget, scopePath, childFieldPath);\n continue;\n }\n\n if (babelTypes.isIdentifier(bindingTarget)) {\n const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);\n if (!localVarBinding) continue;\n for (const referencePath of localVarBinding.referencePaths) {\n analyzeOpaqueUsage(referencePath, childFieldPath);\n }\n continue;\n }\n\n // Array patterns and other targets escape the rename walk.\n markOpaqueField(childFieldPath, property.loc?.start.line);\n }\n };\n\n /**\n * Helper to collect field names from an ObjectPattern (destructuring).\n * Returns true if successful, false when the accessed fields cannot be\n * determined statically (rest element or dynamic computed key → 'all').\n */\n const collectFieldsFromObjectPattern = (\n pattern: BabelTypes.ObjectPattern,\n initPath: NodePath<BabelTypes.Node>,\n targetSet: Set<string>\n ): boolean => {\n if (pattern.properties.some((prop) => babelTypes.isRestElement(prop))) {\n return false;\n }\n\n for (const property of pattern.properties) {\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Dynamic computed keys ({ [expr]: x }) cannot be attributed to a\n // specific field — the whole dictionary must be kept.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n return false;\n }\n\n let fieldName: string | undefined;\n\n if (!property.computed && babelTypes.isIdentifier(property.key)) {\n fieldName = property.key.name;\n } else if (babelTypes.isStringLiteral(property.key)) {\n fieldName = property.key.value;\n }\n\n if (!fieldName) continue;\n\n targetSet.add(fieldName);\n\n // A default value ({ field = fallback }) wraps the binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n if (babelTypes.isIdentifier(bindingTarget)) {\n const variableBinding = initPath.scope.getBinding(bindingTarget.name);\n if (variableBinding) {\n for (const refPath of variableBinding.referencePaths) {\n analyzeOpaqueUsage(refPath, [fieldName]);\n }\n }\n } else if (babelTypes.isObjectPattern(bindingTarget)) {\n // Nested pattern: const { fieldA: { nested } } = … — follow each\n // nested binding so deeper opaque consumption is detected.\n analyzeOpaqueDestructuring(bindingTarget, initPath, [fieldName]);\n } else {\n // Array patterns and other targets escape the rename walk.\n markOpaqueField([fieldName], property.loc?.start.line);\n }\n }\n return true;\n };\n\n /**\n * Returns the call path when `memberExprPath` is a chainable runtime helper\n * being invoked (`content.onChange(cb)`), otherwise `undefined`.\n *\n * See {@link CHAINABLE_RUNTIME_METHOD_NAMES}: a bare `content.onChange`\n * reference that is never called is treated as an ordinary field access, so\n * only the invoked form is looked through.\n */\n const getChainedRuntimeCallPath = (\n memberExprPath: NodePath<BabelTypes.Node> | null | undefined,\n fieldName: string\n ): NodePath<BabelTypes.Node> | undefined => {\n if (!CHAINABLE_RUNTIME_METHOD_NAMES.has(fieldName)) return undefined;\n if (!memberExprPath) return undefined;\n\n const callPath = memberExprPath.parentPath;\n if (!callPath) return undefined;\n if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) {\n return undefined;\n }\n if (\n (callPath.node as BabelTypes.CallExpression).callee !==\n memberExprPath.node\n ) {\n return undefined;\n }\n\n return callPath;\n };\n\n /**\n * Analyses the callbacks handed to a chainable runtime helper.\n *\n * The callback receives the freshly-resolved content root, so its parameter\n * is walked exactly like `const content = useIntlayer('key')` — either as a\n * plain binding or as a destructuring pattern.\n */\n const analyzeChainedCallbackArguments = (\n callPath: NodePath<BabelTypes.Node>\n ): void => {\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; // not a callback (e.g. an options object) – nothing to read\n }\n\n const [firstParameterPath] = argumentPath.get(\n 'params'\n ) as NodePath<BabelTypes.Node>[];\n if (!firstParameterPath) continue; // callback ignores the content\n\n // (content) => … — walk the parameter's references.\n if (firstParameterPath.isIdentifier()) {\n const parameterBinding = argumentPath.scope.getBinding(\n firstParameterPath.node.name\n );\n if (!parameterBinding) {\n markUntrackedBinding();\n continue;\n }\n\n const accessedFieldNames = new Set<string>();\n if (\n analyzeContentBindingReferences(parameterBinding, accessedFieldNames)\n ) {\n markUntrackedBinding();\n } else {\n recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);\n }\n continue;\n }\n\n // ({ title }) => … — destructured directly in the parameter list.\n if (firstParameterPath.isObjectPattern()) {\n const accessedFieldNames = new Set<string>();\n if (\n collectFieldsFromObjectPattern(\n firstParameterPath.node,\n argumentPath,\n accessedFieldNames\n )\n ) {\n recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);\n } else {\n recordFieldUsage(pruneContext, dictionaryKey, 'all');\n }\n continue;\n }\n\n markUntrackedBinding();\n }\n };\n\n /**\n * Walks every reference of a local binding holding the content root,\n * collecting the top-level fields it reads into `accessedTopLevelFieldNames`.\n *\n * @returns `true` when a reference escaped static tracking, meaning the whole\n * dictionary must be kept.\n */\n const analyzeContentBindingReferences = (\n variableBinding: { referencePaths: NodePath<BabelTypes.Node>[] },\n accessedTopLevelFieldNames: Set<string>\n ): boolean => {\n for (const variableReferencePath of variableBinding.referencePaths) {\n const referenceParentNode = variableReferencePath.parent;\n\n if (\n (babelTypes.isMemberExpression(referenceParentNode) ||\n babelTypes.isOptionalMemberExpression(referenceParentNode)) &&\n (referenceParentNode as BabelTypes.MemberExpression).object ===\n variableReferencePath.node\n ) {\n const memberExpressionNode =\n referenceParentNode as BabelTypes.MemberExpression;\n let fieldName: string | undefined;\n\n if (\n !memberExpressionNode.computed &&\n babelTypes.isIdentifier(memberExpressionNode.property)\n ) {\n fieldName = memberExpressionNode.property.name;\n } else if (\n memberExpressionNode.computed &&\n babelTypes.isStringLiteral(memberExpressionNode.property)\n ) {\n fieldName = memberExpressionNode.property.value;\n }\n\n if (fieldName) {\n const memberExprPath = variableReferencePath.parentPath;\n\n // content.onChange(cb) — a runtime subscription, not a field read.\n const chainedCallPath = getChainedRuntimeCallPath(\n memberExprPath,\n fieldName\n );\n if (chainedCallPath) {\n analyzeChainedCallbackArguments(chainedCallPath);\n analyzeContentRoot(chainedCallPath);\n continue;\n }\n\n accessedTopLevelFieldNames.add(fieldName);\n\n // Check usage of the field to look for opaque consumption\n if (memberExprPath) {\n analyzeOpaqueUsage(memberExprPath, [fieldName]);\n }\n } else {\n // Dynamic computed access – cannot resolve statically\n return true;\n }\n } else if (babelTypes.isArrayExpression(referenceParentNode)) {\n // The binding's value escapes into an array literal\n // (e.g. `[appleWatch, airpods].map((entry) => entry.name)`). Its fields\n // are then accessed through iteration that Babel cannot follow back to\n // this dictionary, so we cannot know which fields are used. This is the\n // canonical meta-record / collection access pattern — conservatively\n // keep every field rather than pruning the content to nothing.\n return true;\n } else if (\n // Solid / Angular: content() signal accessor → content().field\n (babelTypes.isCallExpression(referenceParentNode) ||\n babelTypes.isOptionalCallExpression(referenceParentNode)) &&\n (referenceParentNode as BabelTypes.CallExpression).callee ===\n variableReferencePath.node\n ) {\n const callExprPath = variableReferencePath.parentPath;\n const callParent = callExprPath?.parent;\n\n if (\n callParent &&\n (babelTypes.isMemberExpression(callParent) ||\n babelTypes.isOptionalMemberExpression(callParent)) &&\n (callParent as BabelTypes.MemberExpression).object ===\n callExprPath?.node\n ) {\n // content().field\n const memberExpr = callParent as BabelTypes.MemberExpression;\n let fieldName: string | undefined;\n\n if (\n !memberExpr.computed &&\n babelTypes.isIdentifier(memberExpr.property)\n ) {\n fieldName = memberExpr.property.name;\n } else if (\n memberExpr.computed &&\n babelTypes.isStringLiteral(memberExpr.property)\n ) {\n fieldName = memberExpr.property.value;\n }\n\n if (fieldName) {\n const memberExprPath = callExprPath?.parentPath;\n\n // content().onChange(cb) — a runtime subscription, not a field.\n const chainedCallPath = getChainedRuntimeCallPath(\n memberExprPath,\n fieldName\n );\n if (chainedCallPath) {\n analyzeChainedCallbackArguments(chainedCallPath);\n analyzeContentRoot(chainedCallPath);\n continue;\n }\n\n accessedTopLevelFieldNames.add(fieldName);\n if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);\n } else {\n // content()[dynamicKey] – cannot resolve statically\n return true;\n }\n } else if (\n callParent &&\n babelTypes.isVariableDeclarator(callParent) &&\n babelTypes.isObjectPattern(callParent.id) &&\n callExprPath &&\n collectFieldsFromObjectPattern(\n callParent.id,\n callExprPath,\n accessedTopLevelFieldNames\n )\n ) {\n // const { title } = content()\n // fields already added to accessedTopLevelFieldNames by collectFieldsFromObjectPattern\n } else {\n // content() with no field access or passed opaquely → cannot prune\n return true;\n }\n } else {\n // Variable used in a non-member-access context (spread, function arg, etc.)\n return true;\n }\n }\n\n return false;\n };\n\n /**\n * Analyses how the content root referenced by `rootPath` is consumed.\n *\n * `rootPath` is the `useIntlayer('key')` call itself, or any expression that\n * evaluates back to the same content object — currently the result of a\n * chainable runtime helper such as `.onChange(…)`.\n */\n const analyzeContentRoot = (rootPath: NodePath<BabelTypes.Node>): void => {\n const parentNode = rootPath.parent;\n\n // ── Pattern 1: const { fieldA, fieldB } = useIntlayer('key') ────────────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isObjectPattern(parentNode.id)\n ) {\n const accessedFieldNames = new Set<string>();\n if (\n collectFieldsFromObjectPattern(\n parentNode.id,\n rootPath,\n accessedFieldNames\n )\n ) {\n recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);\n } else {\n recordFieldUsage(pruneContext, dictionaryKey, 'all');\n }\n return;\n }\n\n // ── Pattern 2: useIntlayer('key').fieldA / useIntlayer('key')?.fieldA ────\n if (\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object === rootPath.node\n ) {\n let fieldName: string | undefined;\n\n if (\n !parentNode.computed &&\n babelTypes.isIdentifier(parentNode.property)\n ) {\n fieldName = parentNode.property.name;\n } else if (\n parentNode.computed &&\n babelTypes.isStringLiteral(parentNode.property)\n ) {\n fieldName = parentNode.property.value;\n }\n\n if (fieldName) {\n const memberExprPath = rootPath.parentPath;\n\n // useIntlayer('key').onChange(cb) — a runtime subscription: read the\n // fields out of the callback instead of recording `onChange` itself.\n const chainedCallPath = getChainedRuntimeCallPath(\n memberExprPath,\n fieldName\n );\n if (chainedCallPath) {\n analyzeChainedCallbackArguments(chainedCallPath);\n analyzeContentRoot(chainedCallPath);\n return;\n }\n\n recordFieldUsage(pruneContext, dictionaryKey, new Set([fieldName]));\n\n // Check for opaque usage (e.g. passed directly to a prop)\n if (memberExprPath) {\n analyzeOpaqueUsage(memberExprPath, [fieldName]);\n }\n } else {\n markUntrackedBinding();\n }\n return;\n }\n\n // ── Pattern 3: const content = useIntlayer('key') ───────────────────────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isIdentifier(parentNode.id)\n ) {\n const variableName = parentNode.id.name;\n const variableBinding = rootPath.scope.getBinding(variableName);\n\n if (!variableBinding) {\n markUntrackedBinding();\n return;\n }\n\n const accessedTopLevelFieldNames = new Set<string>();\n const hasUntrackedReferenceAccess = analyzeContentBindingReferences(\n variableBinding,\n accessedTopLevelFieldNames\n );\n\n if (hasUntrackedReferenceAccess) {\n markUntrackedBinding();\n } else if (isSfcFile) {\n // Vue / Svelte SFC: defer to the framework-specific extractor because\n // Babel scope analysis cannot see through `.value` or `$` indirection.\n deferFrameworkAnalysis(variableName);\n } else if (variableBinding.referencePaths.length === 0) {\n // Non-SFC file with no visible references – keep all fields.\n markUntrackedBinding();\n } else {\n recordFieldUsage(\n pruneContext,\n dictionaryKey,\n accessedTopLevelFieldNames\n );\n }\n return;\n }\n\n // ── Pattern 4: bare call – result is discarded ──────────────────────────\n if (babelTypes.isExpressionStatement(parentNode)) {\n return; // no usage to record\n }\n\n // ── Fallback: result passed as argument, used in ternary, etc. ──────────\n markUntrackedBinding();\n };\n\n // `getIntlayerAsync('key')` is consumed through its `await`, so the content\n // root is the await expression — reading the call's own parent would see\n // only the `AwaitExpression` and give up on every field.\n analyzeContentRoot(unwrapAwait(babelTypes, callExpressionPath));\n};\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_babel_plugin_intlayer_usage_analyzer = require('./babel-plugin-intlayer-usage-analyzer.cjs');
2
+ const require_nativeCallers = require('./nativeCallers.cjs');
3
+ const require_staticAstReaders = require('./staticAstReaders.cjs');
3
4
 
4
5
  //#region src/babel-plugin-intlayer-field-rename.ts
5
6
  /**
@@ -270,7 +271,7 @@ const renameChainedRuntimeCall = (babelTypes, refPath, renameMap) => {
270
271
  if (!babelTypes.isMemberExpression(memberNode) && !babelTypes.isOptionalMemberExpression(memberNode) || memberNode.object !== refPath.node) return;
271
272
  const propertyNode = memberNode.property;
272
273
  const methodName = memberNode.computed ? babelTypes.isStringLiteral(propertyNode) ? propertyNode.value : void 0 : babelTypes.isIdentifier(propertyNode) ? propertyNode.name : void 0;
273
- if (!methodName || !require_babel_plugin_intlayer_usage_analyzer.CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;
274
+ if (!methodName || !require_nativeCallers.CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;
274
275
  const callPath = memberPath.parentPath;
275
276
  if (!callPath) return;
276
277
  if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) return;
@@ -311,7 +312,7 @@ const collectIntlayerCallerLocalNames = (babelTypes, programNode) => {
311
312
  for (const importSpecifier of statement.specifiers) {
312
313
  if (!babelTypes.isImportSpecifier(importSpecifier)) continue;
313
314
  const importedName = babelTypes.isIdentifier(importSpecifier.imported) ? importSpecifier.imported.name : importSpecifier.imported.value;
314
- if (require_babel_plugin_intlayer_usage_analyzer.INTLAYER_CALLER_NAMES.includes(importedName)) intlayerCallerLocalNameMap.set(importSpecifier.local.name, importedName);
315
+ if (require_nativeCallers.NATIVE_CALLER_NAME_SET.has(importedName)) intlayerCallerLocalNameMap.set(importSpecifier.local.name, importedName);
315
316
  }
316
317
  }
317
318
  return intlayerCallerLocalNameMap;
@@ -360,7 +361,7 @@ const renameIntlayerFieldAccesses = (babelTypes, programPath, pruneContext) => {
360
361
  if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) return;
361
362
  const fieldRenameMap = pruneContext.dictionaryKeyToFieldRenameMap.get(dictionaryKey);
362
363
  if (!fieldRenameMap || fieldRenameMap.size === 0) return;
363
- const contentRootPath = require_babel_plugin_intlayer_usage_analyzer.unwrapAwait(babelTypes, callExpressionPath);
364
+ const contentRootPath = require_staticAstReaders.unwrapAwait(babelTypes, callExpressionPath);
364
365
  const parentNode = contentRootPath.parent;
365
366
  if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isObjectPattern(parentNode.id)) {
366
367
  walkObjectDestructuring(babelTypes, contentRootPath, fieldRenameMap);
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-field-rename.cjs","names":["CHAINABLE_RUNTIME_METHOD_NAMES","INTLAYER_CALLER_NAMES","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 INTLAYER_CALLER_NAMES,\n type IntlayerCallerName,\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 (INTLAYER_CALLER_NAMES.includes(importedName as IntlayerCallerName)) {\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":["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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"}