@intlayer/babel 9.0.0-canary.2 → 9.0.0-canary.21

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 (152) hide show
  1. package/dist/cjs/babel-plugin-intlayer-extract.cjs +3 -2
  2. package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
  3. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +160 -99
  4. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
  5. package/dist/cjs/babel-plugin-intlayer-minify.cjs +11 -28
  6. package/dist/cjs/babel-plugin-intlayer-minify.cjs.map +1 -1
  7. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +143 -13
  8. package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
  9. package/dist/cjs/babel-plugin-intlayer-purge.cjs +38 -96
  10. package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
  11. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +151 -52
  12. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
  13. package/dist/cjs/babelParser.cjs +62 -0
  14. package/dist/cjs/babelParser.cjs.map +1 -0
  15. package/dist/cjs/extractContent/babelProcessor.cjs +144 -71
  16. package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
  17. package/dist/cjs/extractContent/contentWriter.cjs +10 -14
  18. package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
  19. package/dist/cjs/extractContent/extractContent.cjs +3 -3
  20. package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
  21. package/dist/cjs/extractContent/processTsxFile.cjs +4 -7
  22. package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
  23. package/dist/cjs/extractContent/utils/constants.cjs +2 -2
  24. package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
  25. package/dist/cjs/extractContent/utils/detectPackageName.cjs +0 -1
  26. package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
  27. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +4 -4
  28. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -1
  29. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs +2 -3
  30. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
  31. package/dist/cjs/extractContent/utils/generateKey.cjs.map +1 -1
  32. package/dist/cjs/extractContent/utils/getComponentName.cjs.map +1 -1
  33. package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs.map +1 -1
  34. package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs.map +1 -1
  35. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs +0 -1
  36. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
  37. package/dist/cjs/extractContent/utils/shouldExtract.cjs +2 -0
  38. package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +1 -1
  39. package/dist/cjs/extractScriptBlocks.cjs +0 -1
  40. package/dist/cjs/extractScriptBlocks.cjs.map +1 -1
  41. package/dist/cjs/getExtractPluginOptions.cjs +2 -2
  42. package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
  43. package/dist/cjs/getOptimizePluginOptions.cjs +2 -3
  44. package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
  45. package/dist/cjs/getPurgePluginOptions.cjs +2 -3
  46. package/dist/cjs/getPurgePluginOptions.cjs.map +1 -1
  47. package/dist/cjs/index.cjs +3 -0
  48. package/dist/cjs/normalizedFilesList.cjs +30 -0
  49. package/dist/cjs/normalizedFilesList.cjs.map +1 -0
  50. package/dist/cjs/transformers.cjs +20 -2
  51. package/dist/cjs/transformers.cjs.map +1 -1
  52. package/dist/esm/babel-plugin-intlayer-extract.mjs +3 -2
  53. package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
  54. package/dist/esm/babel-plugin-intlayer-field-rename.mjs +159 -100
  55. package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
  56. package/dist/esm/babel-plugin-intlayer-minify.mjs +12 -29
  57. package/dist/esm/babel-plugin-intlayer-minify.mjs.map +1 -1
  58. package/dist/esm/babel-plugin-intlayer-optimize.mjs +140 -9
  59. package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
  60. package/dist/esm/babel-plugin-intlayer-purge.mjs +40 -97
  61. package/dist/esm/babel-plugin-intlayer-purge.mjs.map +1 -1
  62. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +151 -52
  63. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
  64. package/dist/esm/babelParser.mjs +60 -0
  65. package/dist/esm/babelParser.mjs.map +1 -0
  66. package/dist/esm/extractContent/babelProcessor.mjs +144 -71
  67. package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
  68. package/dist/esm/extractContent/contentWriter.mjs +6 -10
  69. package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
  70. package/dist/esm/extractContent/extractContent.mjs +1 -1
  71. package/dist/esm/extractContent/extractContent.mjs.map +1 -1
  72. package/dist/esm/extractContent/processTsxFile.mjs +3 -6
  73. package/dist/esm/extractContent/processTsxFile.mjs.map +1 -1
  74. package/dist/esm/extractContent/utils/constants.mjs +2 -2
  75. package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
  76. package/dist/esm/extractContent/utils/detectPackageName.mjs.map +1 -1
  77. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +1 -1
  78. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -1
  79. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs +1 -1
  80. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs.map +1 -1
  81. package/dist/esm/extractContent/utils/generateKey.mjs.map +1 -1
  82. package/dist/esm/extractContent/utils/getComponentName.mjs.map +1 -1
  83. package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs.map +1 -1
  84. package/dist/esm/extractContent/utils/getOrGenerateKey.mjs.map +1 -1
  85. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs.map +1 -1
  86. package/dist/esm/extractContent/utils/shouldExtract.mjs +2 -0
  87. package/dist/esm/extractContent/utils/shouldExtract.mjs.map +1 -1
  88. package/dist/esm/extractScriptBlocks.mjs.map +1 -1
  89. package/dist/esm/getExtractPluginOptions.mjs +1 -1
  90. package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
  91. package/dist/esm/getOptimizePluginOptions.mjs +1 -1
  92. package/dist/esm/getOptimizePluginOptions.mjs.map +1 -1
  93. package/dist/esm/getPurgePluginOptions.mjs +1 -1
  94. package/dist/esm/getPurgePluginOptions.mjs.map +1 -1
  95. package/dist/esm/index.mjs +3 -3
  96. package/dist/esm/normalizedFilesList.mjs +29 -0
  97. package/dist/esm/normalizedFilesList.mjs.map +1 -0
  98. package/dist/esm/transformers.mjs +20 -2
  99. package/dist/esm/transformers.mjs.map +1 -1
  100. package/dist/types/babel-plugin-intlayer-extract.d.ts +2 -3
  101. package/dist/types/babel-plugin-intlayer-extract.d.ts.map +1 -1
  102. package/dist/types/babel-plugin-intlayer-field-rename.d.ts +29 -11
  103. package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  104. package/dist/types/babel-plugin-intlayer-minify.d.ts +2 -3
  105. package/dist/types/babel-plugin-intlayer-minify.d.ts.map +1 -1
  106. package/dist/types/babel-plugin-intlayer-optimize.d.ts +34 -11
  107. package/dist/types/babel-plugin-intlayer-optimize.d.ts.map +1 -1
  108. package/dist/types/babel-plugin-intlayer-purge.d.ts +2 -3
  109. package/dist/types/babel-plugin-intlayer-purge.d.ts.map +1 -1
  110. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +35 -113
  111. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
  112. package/dist/types/babelParser.d.ts +12 -0
  113. package/dist/types/babelParser.d.ts.map +1 -0
  114. package/dist/types/extractContent/babelProcessor.d.ts +5 -2
  115. package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
  116. package/dist/types/extractContent/contentWriter.d.ts +0 -1
  117. package/dist/types/extractContent/contentWriter.d.ts.map +1 -1
  118. package/dist/types/extractContent/extractContent.d.ts +1 -1
  119. package/dist/types/extractContent/extractContent.d.ts.map +1 -1
  120. package/dist/types/extractContent/index.d.ts +1 -1
  121. package/dist/types/extractContent/processTsxFile.d.ts +1 -1
  122. package/dist/types/extractContent/processTsxFile.d.ts.map +1 -1
  123. package/dist/types/extractContent/utils/constants.d.ts +3 -3
  124. package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
  125. package/dist/types/extractContent/utils/detectPackageName.d.ts +0 -1
  126. package/dist/types/extractContent/utils/detectPackageName.d.ts.map +1 -1
  127. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts +0 -1
  128. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts.map +1 -1
  129. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts.map +1 -1
  130. package/dist/types/extractContent/utils/generateKey.d.ts.map +1 -1
  131. package/dist/types/extractContent/utils/getComponentName.d.ts +0 -1
  132. package/dist/types/extractContent/utils/getComponentName.d.ts.map +1 -1
  133. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts +8 -5
  134. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts.map +1 -1
  135. package/dist/types/extractContent/utils/getOrGenerateKey.d.ts.map +1 -1
  136. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts +0 -1
  137. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts.map +1 -1
  138. package/dist/types/extractContent/utils/shouldExtract.d.ts +1 -0
  139. package/dist/types/extractContent/utils/shouldExtract.d.ts.map +1 -1
  140. package/dist/types/extractScriptBlocks.d.ts.map +1 -1
  141. package/dist/types/getExtractPluginOptions.d.ts +0 -1
  142. package/dist/types/getExtractPluginOptions.d.ts.map +1 -1
  143. package/dist/types/getOptimizePluginOptions.d.ts +0 -1
  144. package/dist/types/getOptimizePluginOptions.d.ts.map +1 -1
  145. package/dist/types/getPurgePluginOptions.d.ts +0 -1
  146. package/dist/types/getPurgePluginOptions.d.ts.map +1 -1
  147. package/dist/types/index.d.ts +6 -5
  148. package/dist/types/normalizedFilesList.d.ts +12 -0
  149. package/dist/types/normalizedFilesList.d.ts.map +1 -0
  150. package/dist/types/transformers.d.ts +7 -2
  151. package/dist/types/transformers.d.ts.map +1 -1
  152. package/package.json +31 -23
@@ -1,8 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
2
+ const require_normalizedFilesList = require('./normalizedFilesList.cjs');
3
3
  let node_path = require("node:path");
4
- let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
4
+ let _intlayer_engine_utils = require("@intlayer/engine/utils");
5
5
  let _intlayer_config_utils = require("@intlayer/config/utils");
6
+ let _intlayer_config_callers = require("@intlayer/config/callers");
6
7
 
7
8
  //#region src/babel-plugin-intlayer-optimize.ts
8
9
  const PACKAGE_LIST = [
@@ -46,6 +47,11 @@ const STATIC_IMPORT_FUNCTION = {
46
47
  useIntlayer: "useDictionary"
47
48
  };
48
49
  const DYNAMIC_IMPORT_FUNCTION = { useIntlayer: "useDictionaryDynamic" };
50
+ /** Import rename table applied when the helper plan for a package is `dynamic`. */
51
+ const DYNAMIC_HELPER_MAP = {
52
+ ...STATIC_IMPORT_FUNCTION,
53
+ ...DYNAMIC_IMPORT_FUNCTION
54
+ };
49
55
  /**
50
56
  * Packages whose SSR-static `useDictionary` lives in a `/server` subpath
51
57
  * because it differs from the root one. Solid's reserves one hydration
@@ -60,7 +66,7 @@ const SSR_STATIC_IMPORT_SOURCE = { "solid-intlayer": "solid-intlayer/server" };
60
66
  * with user-defined ones.
61
67
  */
62
68
  const makeIdent = (key, t) => {
63
- const hash = (0, _intlayer_chokidar_utils.getPathHash)(key);
69
+ const hash = (0, _intlayer_engine_utils.getPathHash)(key);
64
70
  return t.identifier(`_${hash}`);
65
71
  };
66
72
  const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchDictionariesDir, key, importMode) => {
@@ -77,6 +83,60 @@ const getKeyFromArgument = (arg, t) => {
77
83
  if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) return arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
78
84
  };
79
85
  const isCallerName = (name) => CALLER_LIST.includes(name);
86
+ /**
87
+ * Splits a namespace string at the first `.` to separate the dictionary key
88
+ * from an optional key prefix for nested namespaces, mirroring the SWC
89
+ * plugin's `split_namespace`.
90
+ *
91
+ * `'about'` → `{ dictionaryKey: 'about', keyPrefix: '' }`
92
+ * `'about.counter'` → `{ dictionaryKey: 'about', keyPrefix: 'counter' }`
93
+ */
94
+ const splitNamespace = (namespace) => {
95
+ const dotPosition = namespace.indexOf(".");
96
+ if (dotPosition === -1) return {
97
+ dictionaryKey: namespace,
98
+ keyPrefix: ""
99
+ };
100
+ return {
101
+ dictionaryKey: namespace.slice(0, dotPosition),
102
+ keyPrefix: namespace.slice(dotPosition + 1)
103
+ };
104
+ };
105
+ /**
106
+ * Statically resolves the namespace of a compat caller call-site from its
107
+ * descriptor's `namespaceSources` (argument / option / fixed — the
108
+ * per-message-id `path-first-segment` form cannot bind one dictionary to the
109
+ * call site and is skipped). Returns `undefined` when the namespace is absent
110
+ * or dynamic, in which case the call is left untouched and resolves through
111
+ * the runtime dictionary registry.
112
+ */
113
+ const resolveCompatNamespaceMatch = (t, callArguments, descriptor) => {
114
+ for (const source of descriptor.namespaceSources) {
115
+ if (source.from === "fixed") return { fullNamespace: source.value };
116
+ if (source.from === "argument") {
117
+ const namespace = getKeyFromArgument(callArguments[source.index], t);
118
+ if (namespace !== void 0) return {
119
+ fullNamespace: namespace,
120
+ argumentIndex: source.index
121
+ };
122
+ continue;
123
+ }
124
+ if (source.from === "option") {
125
+ const optionsArgument = callArguments[source.argumentIndex];
126
+ if (!optionsArgument || !t.isObjectExpression(optionsArgument)) continue;
127
+ for (const property of optionsArgument.properties) {
128
+ if (!t.isObjectProperty(property)) continue;
129
+ if (!(t.isIdentifier(property.key) && property.key.name === source.property || t.isStringLiteral(property.key) && property.key.value === source.property)) continue;
130
+ const namespace = getKeyFromArgument(property.value, t);
131
+ if (namespace !== void 0) return {
132
+ fullNamespace: namespace,
133
+ optionProperty: property,
134
+ optionsObject: optionsArgument
135
+ };
136
+ }
137
+ }
138
+ }
139
+ };
80
140
  const isDynamicPackage = (packageName) => PACKAGE_LIST_DYNAMIC.includes(packageName);
81
141
  /**
82
142
  * Decides, once per package import, which helper family applies to this file.
@@ -183,6 +243,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
183
243
  this._newDynamicImports = /* @__PURE__ */ new Map();
184
244
  this._callerMap = /* @__PURE__ */ new Map();
185
245
  this._callerPackageMap = /* @__PURE__ */ new Map();
246
+ this._compatCallerMap = /* @__PURE__ */ new Map();
186
247
  this._isIncluded = true;
187
248
  this._hasValidImport = false;
188
249
  this._isDictEntry = false;
@@ -192,7 +253,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
192
253
  }
193
254
  const filename = this.file.opts.filename ? (0, _intlayer_config_utils.normalizePath)(this.file.opts.filename) : void 0;
194
255
  if (this.opts.filesList && filename) {
195
- if (!this.opts.filesList.map(_intlayer_config_utils.normalizePath).includes(filename)) {
256
+ if (!require_normalizedFilesList.getNormalizedFilesListSet(this.opts.filesList).has(filename)) {
196
257
  this._isIncluded = false;
197
258
  return;
198
259
  }
@@ -225,24 +286,43 @@ const intlayerOptimizeBabelPlugin = (babel) => {
225
286
  exit(programPath, state) {
226
287
  if (state._isDictEntry) return;
227
288
  if (!state._isIncluded) return;
289
+ const rewritableCompatCallers = (0, _intlayer_config_callers.getRewritableCallers)(state.opts.compatCallers ?? []);
228
290
  programPath.traverse({ ImportDeclaration(path) {
229
291
  const src = path.node.source.value;
230
- if (!PACKAGE_LIST.includes(src)) return;
292
+ const isNativePackage = PACKAGE_LIST.includes(src);
293
+ const compatCallersForSource = rewritableCompatCallers.filter((descriptor) => descriptor.importSources.includes(src));
294
+ if (!isNativePackage && compatCallersForSource.length === 0) return;
231
295
  state._hasValidImport = true;
232
296
  for (const spec of path.node.specifiers) {
233
297
  if (!t.isImportSpecifier(spec)) continue;
234
298
  const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
235
- if (isCallerName(importedName)) {
299
+ if (isNativePackage && isCallerName(importedName)) {
236
300
  state._callerMap?.set(spec.local.name, importedName);
237
301
  state._callerPackageMap?.set(spec.local.name, src);
238
302
  }
303
+ const compatDescriptor = compatCallersForSource.find((descriptor) => descriptor.callerName === importedName);
304
+ if (compatDescriptor) state._compatCallerMap?.set(spec.local.name, compatDescriptor);
239
305
  }
240
306
  } });
241
307
  const packagesWithDynamicCall = /* @__PURE__ */ new Set();
242
308
  const packagesWithFetchCall = /* @__PURE__ */ new Set();
309
+ let compatHasDynamicCall = false;
310
+ const unresolvableCompatLocalNames = /* @__PURE__ */ new Set();
243
311
  programPath.traverse({ CallExpression(path) {
244
312
  const callee = path.node.callee;
245
313
  if (!t.isIdentifier(callee)) return;
314
+ const compatDescriptor = state._compatCallerMap?.get(callee.name);
315
+ if (compatDescriptor) {
316
+ const namespaceMatch = resolveCompatNamespaceMatch(t, path.node.arguments, compatDescriptor);
317
+ if (!namespaceMatch) {
318
+ unresolvableCompatLocalNames.add(callee.name);
319
+ return;
320
+ }
321
+ const { dictionaryKey } = splitNamespace(namespaceMatch.fullNamespace);
322
+ const compatOverrideMode = state.opts.dictionaryModeMap?.[dictionaryKey];
323
+ if (compatOverrideMode === "dynamic" || compatOverrideMode === "fetch") compatHasDynamicCall = true;
324
+ return;
325
+ }
246
326
  if (state._callerMap?.get(callee.name) !== "useIntlayer") return;
247
327
  const callerPackage = state._callerPackageMap?.get(callee.name);
248
328
  if (!callerPackage) return;
@@ -252,17 +332,23 @@ const intlayerOptimizeBabelPlugin = (babel) => {
252
332
  if (dictionaryOverrideMode === "dynamic") packagesWithDynamicCall.add(callerPackage);
253
333
  else if (dictionaryOverrideMode === "fetch") packagesWithFetchCall.add(callerPackage);
254
334
  } });
335
+ for (const localName of unresolvableCompatLocalNames) state._compatCallerMap?.delete(localName);
255
336
  const getHelperPlan = (packageName) => resolveHelperPlan(packageName, state.opts.importMode, state.opts.isServer, packagesWithDynamicCall.has(packageName), packagesWithFetchCall.has(packageName));
337
+ const compatUseDynamicHelpers = state.opts.importMode === "dynamic" || state.opts.importMode === "fetch" || compatHasDynamicCall;
256
338
  programPath.traverse({
257
339
  ImportDeclaration(path) {
258
340
  const src = path.node.source.value;
341
+ for (const spec of path.node.specifiers) {
342
+ if (!t.isImportSpecifier(spec)) continue;
343
+ const compatDescriptor = state._compatCallerMap?.get(spec.local.name);
344
+ if (!compatDescriptor) continue;
345
+ if (!compatDescriptor.importSources.includes(src)) continue;
346
+ spec.imported = t.identifier(compatUseDynamicHelpers ? compatDescriptor.dynamicReplacement : compatDescriptor.staticReplacement);
347
+ }
259
348
  if (!PACKAGE_LIST.includes(src)) return;
260
349
  const helperPlan = getHelperPlan(src);
261
350
  const serverSource = helperPlan === "ssrStatic" ? SSR_STATIC_IMPORT_SOURCE[src] : void 0;
262
- const helperMap = helperPlan === "dynamic" ? {
263
- ...STATIC_IMPORT_FUNCTION,
264
- ...DYNAMIC_IMPORT_FUNCTION
265
- } : { ...STATIC_IMPORT_FUNCTION };
351
+ const helperMap = helperPlan === "dynamic" ? DYNAMIC_HELPER_MAP : STATIC_IMPORT_FUNCTION;
266
352
  const serverSpecifiers = [];
267
353
  for (const spec of path.node.specifiers) {
268
354
  if (!t.isImportSpecifier(spec)) continue;
@@ -285,6 +371,49 @@ const intlayerOptimizeBabelPlugin = (babel) => {
285
371
  CallExpression(path) {
286
372
  const callee = path.node.callee;
287
373
  if (!t.isIdentifier(callee)) return;
374
+ const compatDescriptor = state._compatCallerMap?.get(callee.name);
375
+ if (compatDescriptor) {
376
+ const callArguments = path.node.arguments;
377
+ const namespaceMatch = resolveCompatNamespaceMatch(t, callArguments, compatDescriptor);
378
+ if (!namespaceMatch) return;
379
+ state._hasValidImport = true;
380
+ const { dictionaryKey, keyPrefix } = splitNamespace(namespaceMatch.fullNamespace);
381
+ const compatOverrideMode = state.opts.dictionaryModeMap?.[dictionaryKey];
382
+ let compatCallMode = "static";
383
+ if (compatUseDynamicHelpers) if (compatOverrideMode === "dynamic" || compatOverrideMode === "fetch") compatCallMode = compatOverrideMode;
384
+ else if (state.opts.importMode === "dynamic" || state.opts.importMode === "fetch") compatCallMode = state.opts.importMode;
385
+ else compatCallMode = "dynamic";
386
+ let dictionaryIdent;
387
+ if (compatCallMode === "static") {
388
+ let staticIdent = state._newStaticImports?.get(dictionaryKey);
389
+ if (!staticIdent) {
390
+ staticIdent = makeIdent(dictionaryKey, t);
391
+ state._newStaticImports?.set(dictionaryKey, staticIdent);
392
+ }
393
+ dictionaryIdent = staticIdent;
394
+ } else {
395
+ let dynamicIdent = state._newDynamicImports?.get(dictionaryKey);
396
+ if (!dynamicIdent) {
397
+ const hash = (0, _intlayer_engine_utils.getPathHash)(dictionaryKey);
398
+ const suffix = compatCallMode === "fetch" ? "fetch" : "dyn";
399
+ dynamicIdent = t.identifier(`_${hash}_${suffix}`);
400
+ state._newDynamicImports?.set(dictionaryKey, dynamicIdent);
401
+ }
402
+ dictionaryIdent = dynamicIdent;
403
+ }
404
+ if (namespaceMatch.argumentIndex !== void 0) {
405
+ callArguments[namespaceMatch.argumentIndex] = t.identifier(dictionaryIdent.name);
406
+ const insertAt = namespaceMatch.argumentIndex + 1;
407
+ const insertedArguments = [];
408
+ if (compatCallMode !== "static") insertedArguments.push(t.stringLiteral(dictionaryKey));
409
+ if (keyPrefix) insertedArguments.push(t.stringLiteral(keyPrefix));
410
+ callArguments.splice(insertAt, 0, ...insertedArguments);
411
+ } else if (compatCallMode !== "static") callArguments.unshift(t.identifier(dictionaryIdent.name), t.stringLiteral(dictionaryKey));
412
+ else callArguments.unshift(t.identifier(dictionaryIdent.name));
413
+ if (namespaceMatch.optionProperty && namespaceMatch.optionsObject) if (keyPrefix) namespaceMatch.optionProperty.value = t.stringLiteral(keyPrefix);
414
+ else namespaceMatch.optionsObject.properties = namespaceMatch.optionsObject.properties.filter((property) => property !== namespaceMatch.optionProperty);
415
+ return;
416
+ }
288
417
  const originalImportedName = state._callerMap?.get(callee.name);
289
418
  if (!originalImportedName) return;
290
419
  state._hasValidImport = true;
@@ -306,7 +435,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
306
435
  if (perCallMode === "fetch") {
307
436
  let dynamicIdent = state._newDynamicImports?.get(key);
308
437
  if (!dynamicIdent) {
309
- const hash = (0, _intlayer_chokidar_utils.getPathHash)(key);
438
+ const hash = (0, _intlayer_engine_utils.getPathHash)(key);
310
439
  dynamicIdent = t.identifier(`_${hash}_fetch`);
311
440
  state._newDynamicImports?.set(key, dynamicIdent);
312
441
  }
@@ -315,7 +444,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
315
444
  } else if (perCallMode === "dynamic") {
316
445
  let dynamicIdent = state._newDynamicImports?.get(key);
317
446
  if (!dynamicIdent) {
318
- const hash = (0, _intlayer_chokidar_utils.getPathHash)(key);
447
+ const hash = (0, _intlayer_engine_utils.getPathHash)(key);
319
448
  dynamicIdent = t.identifier(`_${hash}_dyn`);
320
449
  state._newDynamicImports?.set(key, dynamicIdent);
321
450
  }
@@ -345,7 +474,8 @@ const intlayerOptimizeBabelPlugin = (babel) => {
345
474
  imports.push(importDeclarationNode);
346
475
  }
347
476
  for (const [key, ident] of state._newDynamicImports) {
348
- const rel = computeImport(file, dictionariesDir, dynamicDictionariesDir, fetchDictionariesDir, key, ident.name.endsWith("_fetch") ? "fetch" : "dynamic");
477
+ const modeForThisIdent = ident.name.endsWith("_fetch") ? "fetch" : "dynamic";
478
+ const rel = computeImport(file, dictionariesDir, dynamicDictionariesDir, fetchDictionariesDir, key, modeForThisIdent);
349
479
  imports.push(t.importDeclaration([t.importDefaultSpecifier(t.identifier(ident.name))], t.stringLiteral(rel)));
350
480
  }
351
481
  if (!imports.length) return;
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-optimize.cjs","names":["normalizePath"],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"sourcesContent":["import { dirname, join, relative } from 'node:path';\nimport type { NodePath, PluginObj, PluginPass } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport { getPathHash } from '@intlayer/chokidar/utils';\nimport { normalizePath } from '@intlayer/config/utils';\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'preact-intlayer',\n 'vue-intlayer',\n 'solid-intlayer',\n 'svelte-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n] as const;\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/**\n * Packages whose SSR-static `useDictionary` lives in a `/server` subpath\n * because it differs from the root one. Solid's reserves one hydration\n * resource slot so hydration ids stay aligned with the client's\n * `useDictionaryDynamic`; for other frameworks the root `useDictionary` is\n * already the correct SSR-static implementation.\n */\nconst SSR_STATIC_IMPORT_SOURCE: Partial<Record<string, string>> = {\n 'solid-intlayer': 'solid-intlayer/server',\n};\n\ntype CallerName = (typeof CALLER_LIST)[number];\ntype ImportMode = 'static' | 'dynamic' | 'fetch';\n\n/**\n * Options for the optimization Babel plugin\n */\nexport type OptimizePluginOptions = {\n /**\n * If false, the plugin will not apply any transformation.\n */\n optimize?: boolean;\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries entry file.\n */\n unmergedDictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries directory.\n */\n unmergedDictionariesDir: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * The path to the fetch dictionaries directory.\n */\n fetchDictionariesDir: string;\n /**\n * The path to the fetch dictionaries entry file.\n */\n fetchDictionariesEntryPath: string;\n /**\n * If true, the plugin will replace the dictionary entry file with `export default {}`.\n */\n replaceDictionaryEntry: boolean;\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries. It will rely on Suspense to load the dictionaries.\n */\n importMode: 'static' | 'dynamic' | 'fetch' | undefined;\n /**\n * Map of dictionary keys to their specific import mode.\n */\n dictionaryModeMap?: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n >;\n /**\n * Files list to traverse.\n */\n filesList: string[];\n /**\n * Whether the current transform is for an SSR bundle.\n */\n isServer?: boolean;\n};\n\ntype State = PluginPass & {\n opts: OptimizePluginOptions;\n /** map key → generated ident (per-file) for static imports */\n _newStaticImports?: Map<string, BabelTypes.Identifier>;\n /** map key → generated ident (per-file) for dynamic imports */\n _newDynamicImports?: Map<string, BabelTypes.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** map from local identifier name to the imported intlayer func name ('useIntlayer' | 'getIntlayer') */\n _callerMap?: Map<string, (typeof CALLER_LIST)[number]>;\n /** map from local identifier name to the intlayer package it was imported from */\n _callerPackageMap?: Map<string, string>;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether the current file is included in the filesList */\n _isIncluded?: boolean;\n};\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (\n key: string,\n t: typeof BabelTypes\n): BabelTypes.Identifier => {\n const hash = getPathHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n fetchDictionariesDir: string,\n key: string,\n importMode: 'static' | 'dynamic' | 'fetch'\n): string => {\n let relativePath = join(dictionariesDir, `${key}.json`);\n\n if (importMode === 'fetch') {\n relativePath = join(fetchDictionariesDir, `${key}.mjs`);\n }\n\n if (importMode === 'dynamic') {\n relativePath = join(dynamicDictionariesDir, `${key}.mjs`);\n }\n\n let rel = relative(dirname(fromFile), relativePath);\n\n // Fix windows path\n rel = normalizePath(rel);\n\n // Fix relative path\n if (!rel.startsWith('./') && !rel.startsWith('../')) {\n rel = `./${rel}`;\n }\n\n return rel;\n};\n\nconst getKeyFromArgument = (\n arg: BabelTypes.Node | null | undefined,\n t: typeof BabelTypes\n): string | undefined => {\n if (arg && t.isStringLiteral(arg)) {\n return arg.value;\n }\n\n if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n return arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n\n return undefined;\n};\n\nconst isCallerName = (name: string): name is CallerName =>\n CALLER_LIST.includes(name as CallerName);\n\nconst isDynamicPackage = (\n packageName: string\n): packageName is (typeof PACKAGE_LIST_DYNAMIC)[number] =>\n PACKAGE_LIST_DYNAMIC.includes(\n packageName as (typeof PACKAGE_LIST_DYNAMIC)[number]\n );\n\n/**\n * Helper family every `useIntlayer`/`getIntlayer` call from one package import\n * resolves to in the current file. `ssrStatic` is the SSR bundle of a\n * dynamic-mode file: rewritten to the static `useDictionary` (from the\n * package's `/server` entry when it has one — see\n * `SSR_STATIC_IMPORT_SOURCE`) so the server renders static JSON while the\n * client keeps the dynamic loader.\n */\ntype PackageHelperPlan = 'static' | 'dynamic' | 'ssrStatic';\n\n/**\n * Decides, once per package import, which helper family applies to this file.\n * The import rewrite and the per-call rewrite must both derive from this\n * single decision, or the emitted helper and its argument shape diverge.\n *\n * Fetch wins over `ssrStatic`: fetch dictionaries are runtime content, so the\n * server must keep the real fetch path instead of rendering build-time JSON.\n */\nconst resolveHelperPlan = (\n packageName: string,\n importMode: ImportMode | undefined,\n isServer: boolean | undefined,\n packageHasDynamicCall: boolean,\n packageHasFetchCall: boolean\n): PackageHelperPlan => {\n if (!isDynamicPackage(packageName)) return 'static';\n\n if (importMode === 'fetch' || packageHasFetchCall) return 'dynamic';\n\n if (importMode === 'dynamic' || packageHasDynamicCall) {\n return isServer === true ? 'ssrStatic' : 'dynamic';\n }\n\n return 'static';\n};\n\n/**\n * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.\n *\n * This plugin transforms calls to `useIntlayer()` and `getIntlayer()` from various Intlayer\n * packages into optimized dictionary access patterns, automatically importing the required\n * dictionary files based on the configured import mode.\n *\n * ## Supported Input Patterns\n *\n * The plugin recognizes these function calls:\n *\n * ```ts\n * // useIntlayer\n * import { useIntlayer } from 'react-intlayer';\n * import { useIntlayer } from 'next-intlayer';\n *\n * // getIntlayer\n * import { getIntlayer } from 'intlayer';\n *\n * // Usage\n * const content = useIntlayer('app');\n * const content = getIntlayer('app');\n * ```\n *\n * ## Transformation Modes\n *\n * ### Static Mode (default: `importMode = \"static\"`)\n *\n * Imports JSON dictionaries directly and replaces function calls with dictionary access:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash);\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Dynamic Mode (`importMode = \"dynamic\"`)\n *\n * Uses dynamic dictionary loading with Suspense support:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Fetch Mode (`importMode = \"fetch\"`)\n *\n * Uses fetch-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"fetch\" value:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_fetch, \"app\");\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * > If `dictionaryModeMap` does not include the key with \"fetch\" value, the plugin will fallback to the dynamic import mode.\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n */\nexport const intlayerOptimizeBabelPlugin = (babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n const { types: t } = babel;\n\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newStaticImports = new Map();\n this._newDynamicImports = new Map();\n this._callerMap = new Map();\n this._callerPackageMap = new Map();\n this._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n\n // If optimize is false, skip processing entirely\n if (this.opts.optimize === false) {\n this._isIncluded = false;\n return;\n }\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename\n ? normalizePath(this.file.opts.filename)\n : undefined;\n if (this.opts.filesList && filename) {\n const filesList = this.opts.filesList.map(normalizePath);\n const isIncluded = filesList.includes(filename);\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n // Safe access to filename\n const filename = state.file.opts.filename\n ? normalizePath(state.file.opts.filename)\n : undefined;\n const dictionariesEntryPath = state.opts.dictionariesEntryPath\n ? normalizePath(state.opts.dictionariesEntryPath)\n : undefined;\n\n // Check if this is the correct file to transform\n\n if (\n state.opts.replaceDictionaryEntry &&\n filename === dictionariesEntryPath\n ) {\n state._isDictEntry = true;\n\n // Traverse the program to surgically remove/edit specific parts\n programPath.traverse({\n // Remove all import statements (cleaning up 'sssss.json')\n ImportDeclaration(path) {\n path.remove();\n },\n\n // Find the variable definition and empty the object\n VariableDeclarator(path) {\n // We look for: const x = { ... }\n\n if (t.isObjectExpression(path.node.init)) {\n // Set the object properties to an empty array: {}\n path.node.init.properties = [];\n }\n },\n });\n\n // (Optional) Stop other plugins from processing this file further if needed\n // programPath.stop();\n }\n },\n\n /**\n * After full traversal, process imports and call expressions, then inject the JSON dictionary imports.\n *\n * We do the transformation in Program.exit (via a manual traverse) rather than using\n * top-level ImportDeclaration/CallExpression visitors. This ensures that if another plugin\n * (like babel-plugin-intlayer-extract) adds new useIntlayer calls in its Program.exit,\n * we will see and transform them here because our Program.exit runs after theirs.\n */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n\n if (!state._isIncluded) return; // early-out if file is not included\n\n // Manual traversal to process imports and call expressions\n // This runs AFTER all other plugins' visitors have completed\n programPath.traverse({\n /* Inspect every intlayer import before deciding helper rewrites. */\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\n\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as BabelTypes.StringLiteral).value;\n\n if (isCallerName(importedName)) {\n state._callerMap?.set(spec.local.name, importedName);\n state._callerPackageMap?.set(spec.local.name, src);\n }\n }\n },\n });\n\n // Pre-pass to determine if dictionary-level overrides require the\n // dynamic helper in an otherwise static file.\n const packagesWithDynamicCall = new Set<string>();\n const packagesWithFetchCall = new Set<string>();\n programPath.traverse({\n CallExpression(path) {\n const callee = path.node.callee;\n\n if (!t.isIdentifier(callee)) return;\n\n const originalImportedName = state._callerMap?.get(callee.name);\n if (originalImportedName !== 'useIntlayer') return;\n\n const callerPackage = state._callerPackageMap?.get(callee.name);\n if (!callerPackage) return;\n\n const key = getKeyFromArgument(path.node.arguments[0], t);\n if (!key) return;\n\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (dictionaryOverrideMode === 'dynamic') {\n packagesWithDynamicCall.add(callerPackage);\n } else if (dictionaryOverrideMode === 'fetch') {\n packagesWithFetchCall.add(callerPackage);\n }\n },\n });\n\n const getHelperPlan = (packageName: string): PackageHelperPlan =>\n resolveHelperPlan(\n packageName,\n state.opts.importMode,\n state.opts.isServer,\n packagesWithDynamicCall.has(packageName),\n packagesWithFetchCall.has(packageName)\n );\n\n programPath.traverse({\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Per-import swap, mirrored across bundles — Solid hydration\n // ids rely on the SSR and client helpers consuming one\n // resource slot per call alike (see solid-intlayer/server).\n const helperPlan = getHelperPlan(src);\n const serverSource =\n helperPlan === 'ssrStatic'\n ? SSR_STATIC_IMPORT_SOURCE[src]\n : undefined;\n\n const helperMap: Record<string, string> =\n helperPlan === 'dynamic'\n ? { ...STATIC_IMPORT_FUNCTION, ...DYNAMIC_IMPORT_FUNCTION }\n : { ...STATIC_IMPORT_FUNCTION };\n\n const serverSpecifiers: BabelTypes.ImportSpecifier[] = [];\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as BabelTypes.StringLiteral).value;\n\n if (!isCallerName(importedName)) continue;\n\n if (serverSource && importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n serverSpecifiers.push(spec);\n continue;\n }\n\n const newIdentifier = helperMap[importedName];\n\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n\n if (serverSpecifiers.length > 0 && serverSource) {\n // Move the helper to the /server entry, keeping any other\n // specifiers (useLocale, …) on the original import.\n path.insertAfter(\n t.importDeclaration(\n serverSpecifiers,\n t.stringLiteral(serverSource)\n )\n );\n path.node.specifiers = path.node.specifiers.filter(\n (spec) =>\n !serverSpecifiers.includes(\n spec as BabelTypes.ImportSpecifier\n )\n );\n if (path.node.specifiers.length === 0) {\n path.remove();\n }\n }\n },\n\n /* Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) or useDictionaryDynamic(_hash, \"foo\") */\n CallExpression(path) {\n const callee = path.node.callee;\n\n if (!t.isIdentifier(callee)) return;\n\n const originalImportedName = state._callerMap?.get(callee.name);\n if (!originalImportedName) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn't import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const key = getKeyFromArgument(path.node.arguments[0], t);\n if (!key) return;\n\n const callerPackage = state._callerPackageMap?.get(callee.name);\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n const helperPlan =\n callerPackage === undefined\n ? 'static'\n : getHelperPlan(callerPackage);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'.\n let perCallMode: ImportMode = 'static';\n\n if (isUseIntlayer && helperPlan === 'dynamic') {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic' || importMode === 'fetch') {\n perCallMode = importMode;\n }\n } else if (isUseIntlayer && helperPlan === 'static') {\n // The global mode is static, but a per-dictionary override can\n // still force dynamic/fetch for this specific call.\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n perCallMode = dictionaryOverrideMode;\n }\n }\n\n let ident: BabelTypes.Identifier;\n\n if (perCallMode === 'fetch') {\n // Use fetch dictionaries entry for selected keys\n let dynamicIdent = state._newDynamicImports?.get(key);\n\n if (!dynamicIdent) {\n const hash = getPathHash(key);\n dynamicIdent = t.identifier(`_${hash}_fetch`);\n state._newDynamicImports?.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Helper: first argument is the dictionary entry, second is the key\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else if (perCallMode === 'dynamic') {\n // Use dynamic dictionaries entry\n let dynamicIdent = state._newDynamicImports?.get(key);\n\n if (!dynamicIdent) {\n // Create a unique identifier for dynamic imports by appending a suffix\n const hash = getPathHash(key);\n dynamicIdent = t.identifier(`_${hash}_dyn`);\n state._newDynamicImports?.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Dynamic helper: first argument is the dictionary, second is the key.\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else {\n // Use static imports for getIntlayer or useIntlayer when not using dynamic helpers\n let staticIdent = state._newStaticImports?.get(key);\n\n if (!staticIdent) {\n staticIdent = makeIdent(key, t);\n state._newStaticImports?.set(key, staticIdent);\n }\n ident = staticIdent;\n\n // Static helper (useDictionary / getDictionary): replace key with ident.\n // After the splice above the key is always at index 0.\n path.node.arguments[0] = t.identifier(ident.name);\n }\n },\n });\n\n // Early-out if we touched nothing\n\n if (!state._hasValidImport) return;\n\n const file = state.file.opts.filename!;\n const dictionariesDir = state.opts.dictionariesDir;\n const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;\n const fetchDictionariesDir = state.opts.fetchDictionariesDir;\n const imports: BabelTypes.ImportDeclaration[] = [];\n\n // Generate static JSON imports (getIntlayer always uses JSON dictionaries)\n for (const [key, ident] of state._newStaticImports!) {\n const rel = computeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n 'static'\n );\n\n const importDeclarationNode = t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n );\n\n // Add 'type: json' attribute for JSON files\n importDeclarationNode.attributes = [\n t.importAttribute(t.identifier('type'), t.stringLiteral('json')),\n ];\n\n imports.push(importDeclarationNode);\n }\n\n // Generate dynamic/fetch imports (for useIntlayer when using dynamic/fetch helpers)\n for (const [key, ident] of state._newDynamicImports!) {\n const modeForThisIdent: 'dynamic' | 'fetch' = ident.name.endsWith(\n '_fetch'\n )\n ? 'fetch'\n : 'dynamic';\n\n const rel = computeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n modeForThisIdent\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get(\n 'body'\n ) as NodePath<BabelTypes.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n !stmt.expression.value.startsWith('import') &&\n !stmt.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"babel-plugin-intlayer-optimize.cjs","names":["getNormalizedFilesListSet"],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"sourcesContent":["import { dirname, join, relative } from 'node:path';\nimport type { NodePath, PluginObject, PluginPass } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport {\n type CallerDescriptor,\n getRewritableCallers,\n} from '@intlayer/config/callers';\nimport { normalizePath } from '@intlayer/config/utils';\nimport { getPathHash } from '@intlayer/engine/utils';\nimport { getNormalizedFilesListSet } from './normalizedFilesList';\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'preact-intlayer',\n 'vue-intlayer',\n 'solid-intlayer',\n 'svelte-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'vanilla-intlayer',\n] as const;\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/** Import rename table applied when the helper plan for a package is `dynamic`. */\nconst DYNAMIC_HELPER_MAP: Record<string, string> = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n};\n\n/**\n * Packages whose SSR-static `useDictionary` lives in a `/server` subpath\n * because it differs from the root one. Solid's reserves one hydration\n * resource slot so hydration ids stay aligned with the client's\n * `useDictionaryDynamic`; for other frameworks the root `useDictionary` is\n * already the correct SSR-static implementation.\n */\nconst SSR_STATIC_IMPORT_SOURCE: Partial<Record<string, string>> = {\n 'solid-intlayer': 'solid-intlayer/server',\n};\n\ntype CallerName = (typeof CALLER_LIST)[number];\ntype ImportMode = 'static' | 'dynamic' | 'fetch';\n\n/**\n * Options for the optimization Babel plugin\n */\nexport type OptimizePluginOptions = {\n /**\n * If false, the plugin will not apply any transformation.\n */\n optimize?: boolean;\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries entry file.\n */\n unmergedDictionariesEntryPath: string;\n /**\n * The path to the unmerged dictionaries directory.\n */\n unmergedDictionariesDir: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * The path to the fetch dictionaries directory.\n */\n fetchDictionariesDir: string;\n /**\n * The path to the fetch dictionaries entry file.\n */\n fetchDictionariesEntryPath: string;\n /**\n * If true, the plugin will replace the dictionary entry file with `export default {}`.\n */\n replaceDictionaryEntry: boolean;\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries. It will rely on Suspense to load the dictionaries.\n */\n importMode: 'static' | 'dynamic' | 'fetch' | undefined;\n /**\n * Map of dictionary keys to their specific import mode.\n */\n dictionaryModeMap?: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n >;\n /**\n * Files list to traverse.\n */\n filesList: string[];\n /**\n * Whether the current transform is for an SSR bundle.\n */\n isServer?: boolean;\n /**\n * Compat-adapter caller descriptors injected by the compat packages'\n * bundler plugins (e.g. `@intlayer/react-i18next/plugin`).\n *\n * Callers carrying `staticReplacement` / `dynamicReplacement` are rewritten\n * the same way as native `useIntlayer` calls: the namespace string argument\n * is replaced by a pre-imported dictionary object and the import specifier\n * is re-pointed to the dictionary-accepting variant, e.g.\n * `useTranslation('about')` → `useDictionary(_dictHash)`.\n *\n * No compat-specific name is hard-coded in this plugin — the whole rewrite\n * is driven by these descriptors.\n */\n compatCallers?: CallerDescriptor[];\n};\n\ntype State = PluginPass & {\n opts: OptimizePluginOptions;\n /** map key → generated ident (per-file) for static imports */\n _newStaticImports?: Map<string, BabelTypes.Identifier>;\n /** map key → generated ident (per-file) for dynamic imports */\n _newDynamicImports?: Map<string, BabelTypes.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** map from local identifier name to the imported intlayer func name ('useIntlayer' | 'getIntlayer') */\n _callerMap?: Map<string, (typeof CALLER_LIST)[number]>;\n /** map from local identifier name to the intlayer package it was imported from */\n _callerPackageMap?: Map<string, string>;\n /** map from local identifier name to the compat caller descriptor it was imported as */\n _compatCallerMap?: Map<string, CallerDescriptor>;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether the current file is included in the filesList */\n _isIncluded?: boolean;\n};\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (\n key: string,\n t: typeof BabelTypes\n): BabelTypes.Identifier => {\n const hash = getPathHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n fetchDictionariesDir: string,\n key: string,\n importMode: 'static' | 'dynamic' | 'fetch'\n): string => {\n let relativePath = join(dictionariesDir, `${key}.json`);\n\n if (importMode === 'fetch') {\n relativePath = join(fetchDictionariesDir, `${key}.mjs`);\n }\n\n if (importMode === 'dynamic') {\n relativePath = join(dynamicDictionariesDir, `${key}.mjs`);\n }\n\n let rel = relative(dirname(fromFile), relativePath);\n\n // Fix windows path\n rel = normalizePath(rel);\n\n // Fix relative path\n if (!rel.startsWith('./') && !rel.startsWith('../')) {\n rel = `./${rel}`;\n }\n\n return rel;\n};\n\nconst getKeyFromArgument = (\n arg: BabelTypes.Node | null | undefined,\n t: typeof BabelTypes\n): string | undefined => {\n if (arg && t.isStringLiteral(arg)) {\n return arg.value;\n }\n\n if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n return arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n\n return undefined;\n};\n\nconst isCallerName = (name: string): name is CallerName =>\n CALLER_LIST.includes(name as CallerName);\n\n/**\n * Splits a namespace string at the first `.` to separate the dictionary key\n * from an optional key prefix for nested namespaces, mirroring the SWC\n * plugin's `split_namespace`.\n *\n * `'about'` → `{ dictionaryKey: 'about', keyPrefix: '' }`\n * `'about.counter'` → `{ dictionaryKey: 'about', keyPrefix: 'counter' }`\n */\nconst splitNamespace = (\n namespace: string\n): { dictionaryKey: string; keyPrefix: string } => {\n const dotPosition = namespace.indexOf('.');\n if (dotPosition === -1) return { dictionaryKey: namespace, keyPrefix: '' };\n return {\n dictionaryKey: namespace.slice(0, dotPosition),\n keyPrefix: namespace.slice(dotPosition + 1),\n };\n};\n\n/**\n * Result of statically resolving the namespace of a compat caller call-site.\n */\ntype CompatNamespaceMatch = {\n /** The full namespace string, e.g. `'about.counter'`. */\n fullNamespace: string;\n /** Index of the positional namespace argument, when read from an argument. */\n argumentIndex?: number;\n /**\n * The options-object property holding the namespace, when read from an\n * option. The rewrite mutates it in place (key-prefix remainder) or removes\n * it from `optionsObject`.\n */\n optionProperty?: BabelTypes.ObjectProperty;\n /** The options object owning `optionProperty`. */\n optionsObject?: BabelTypes.ObjectExpression;\n};\n\n/**\n * Statically resolves the namespace of a compat caller call-site from its\n * descriptor's `namespaceSources` (argument / option / fixed — the\n * per-message-id `path-first-segment` form cannot bind one dictionary to the\n * call site and is skipped). Returns `undefined` when the namespace is absent\n * or dynamic, in which case the call is left untouched and resolves through\n * the runtime dictionary registry.\n */\nconst resolveCompatNamespaceMatch = (\n t: typeof BabelTypes,\n callArguments: BabelTypes.CallExpression['arguments'],\n descriptor: CallerDescriptor\n): CompatNamespaceMatch | undefined => {\n for (const source of descriptor.namespaceSources) {\n if (source.from === 'fixed') {\n return { fullNamespace: source.value };\n }\n\n if (source.from === 'argument') {\n const namespace = getKeyFromArgument(callArguments[source.index], t);\n if (namespace !== undefined) {\n return { fullNamespace: namespace, argumentIndex: source.index };\n }\n continue;\n }\n\n if (source.from === 'option') {\n const optionsArgument = callArguments[source.argumentIndex];\n if (!optionsArgument || !t.isObjectExpression(optionsArgument)) continue;\n\n for (const property of optionsArgument.properties) {\n if (!t.isObjectProperty(property)) continue;\n const keyMatches =\n (t.isIdentifier(property.key) &&\n property.key.name === source.property) ||\n (t.isStringLiteral(property.key) &&\n property.key.value === source.property);\n if (!keyMatches) continue;\n\n const namespace = getKeyFromArgument(property.value, t);\n if (namespace !== undefined) {\n return {\n fullNamespace: namespace,\n optionProperty: property,\n optionsObject: optionsArgument,\n };\n }\n }\n }\n }\n\n return undefined;\n};\n\nconst isDynamicPackage = (\n packageName: string\n): packageName is (typeof PACKAGE_LIST_DYNAMIC)[number] =>\n PACKAGE_LIST_DYNAMIC.includes(\n packageName as (typeof PACKAGE_LIST_DYNAMIC)[number]\n );\n\n/**\n * Helper family every `useIntlayer`/`getIntlayer` call from one package import\n * resolves to in the current file. `ssrStatic` is the SSR bundle of a\n * dynamic-mode file: rewritten to the static `useDictionary` (from the\n * package's `/server` entry when it has one — see\n * `SSR_STATIC_IMPORT_SOURCE`) so the server renders static JSON while the\n * client keeps the dynamic loader.\n */\ntype PackageHelperPlan = 'static' | 'dynamic' | 'ssrStatic';\n\n/**\n * Decides, once per package import, which helper family applies to this file.\n * The import rewrite and the per-call rewrite must both derive from this\n * single decision, or the emitted helper and its argument shape diverge.\n *\n * Fetch wins over `ssrStatic`: fetch dictionaries are runtime content, so the\n * server must keep the real fetch path instead of rendering build-time JSON.\n */\nconst resolveHelperPlan = (\n packageName: string,\n importMode: ImportMode | undefined,\n isServer: boolean | undefined,\n packageHasDynamicCall: boolean,\n packageHasFetchCall: boolean\n): PackageHelperPlan => {\n if (!isDynamicPackage(packageName)) return 'static';\n\n if (importMode === 'fetch' || packageHasFetchCall) return 'dynamic';\n\n if (importMode === 'dynamic' || packageHasDynamicCall) {\n return isServer === true ? 'ssrStatic' : 'dynamic';\n }\n\n return 'static';\n};\n\n/**\n * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.\n *\n * This plugin transforms calls to `useIntlayer()` and `getIntlayer()` from various Intlayer\n * packages into optimized dictionary access patterns, automatically importing the required\n * dictionary files based on the configured import mode.\n *\n * ## Supported Input Patterns\n *\n * The plugin recognizes these function calls:\n *\n * ```ts\n * // useIntlayer\n * import { useIntlayer } from 'react-intlayer';\n * import { useIntlayer } from 'next-intlayer';\n *\n * // getIntlayer\n * import { getIntlayer } from 'intlayer';\n *\n * // Usage\n * const content = useIntlayer('app');\n * const content = getIntlayer('app');\n * ```\n *\n * ## Transformation Modes\n *\n * ### Static Mode (default: `importMode = \"static\"`)\n *\n * Imports JSON dictionaries directly and replaces function calls with dictionary access:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash);\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Dynamic Mode (`importMode = \"dynamic\"`)\n *\n * Uses dynamic dictionary loading with Suspense support:\n *\n * **Output:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * ### Fetch Mode (`importMode = \"fetch\"`)\n *\n * Uses fetch-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"fetch\" value:**\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_fetch, \"app\");\n * const content2 = getIntlayer(_dicHash);\n * ```\n *\n * > If `dictionaryModeMap` does not include the key with \"fetch\" value, the plugin will fallback to the dynamic import mode.\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };\n * import _dicHash_dyn from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n * import { getDictionary as getIntlayer } from 'intlayer';\n *\n * const content1 = useIntlayer(_dicHash_dyn, 'app');\n * const content2 = getIntlayer(_dicHash);\n * ```\n */\nexport const intlayerOptimizeBabelPlugin = (babel: {\n types: typeof BabelTypes;\n}): PluginObject<State> => {\n const { types: t } = babel;\n\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newStaticImports = new Map();\n this._newDynamicImports = new Map();\n this._callerMap = new Map();\n this._callerPackageMap = new Map();\n this._compatCallerMap = new Map();\n this._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n\n // If optimize is false, skip processing entirely\n if (this.opts.optimize === false) {\n this._isIncluded = false;\n return;\n }\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename\n ? normalizePath(this.file.opts.filename)\n : undefined;\n if (this.opts.filesList && filename) {\n const isIncluded = getNormalizedFilesListSet(this.opts.filesList).has(\n filename\n );\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n // Safe access to filename\n const filename = state.file.opts.filename\n ? normalizePath(state.file.opts.filename)\n : undefined;\n const dictionariesEntryPath = state.opts.dictionariesEntryPath\n ? normalizePath(state.opts.dictionariesEntryPath)\n : undefined;\n\n // Check if this is the correct file to transform\n\n if (\n state.opts.replaceDictionaryEntry &&\n filename === dictionariesEntryPath\n ) {\n state._isDictEntry = true;\n\n // Traverse the program to surgically remove/edit specific parts\n programPath.traverse({\n // Remove all import statements (cleaning up 'sssss.json')\n ImportDeclaration(path) {\n path.remove();\n },\n\n // Find the variable definition and empty the object\n VariableDeclarator(path) {\n // We look for: const x = { ... }\n\n if (t.isObjectExpression(path.node.init)) {\n // Set the object properties to an empty array: {}\n path.node.init.properties = [];\n }\n },\n });\n\n // (Optional) Stop other plugins from processing this file further if needed\n // programPath.stop();\n }\n },\n\n /**\n * After full traversal, process imports and call expressions, then inject the JSON dictionary imports.\n *\n * We do the transformation in Program.exit (via a manual traverse) rather than using\n * top-level ImportDeclaration/CallExpression visitors. This ensures that if another plugin\n * (like babel-plugin-intlayer-extract) adds new useIntlayer calls in its Program.exit,\n * we will see and transform them here because our Program.exit runs after theirs.\n */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n\n if (!state._isIncluded) return; // early-out if file is not included\n\n // Compat callers the optimize pass can rewrite (injected by the\n // compat packages' bundler plugins — nothing is hard-coded here).\n const rewritableCompatCallers = getRewritableCallers(\n state.opts.compatCallers ?? []\n );\n\n // Manual traversal to process imports and call expressions\n // This runs AFTER all other plugins' visitors have completed\n programPath.traverse({\n /* Inspect every intlayer import before deciding helper rewrites. */\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n const isNativePackage = PACKAGE_LIST.includes(src);\n const compatCallersForSource = rewritableCompatCallers.filter(\n (descriptor) => descriptor.importSources.includes(src)\n );\n\n if (!isNativePackage && compatCallersForSource.length === 0) {\n return;\n }\n\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as BabelTypes.StringLiteral).value;\n\n if (isNativePackage && isCallerName(importedName)) {\n state._callerMap?.set(spec.local.name, importedName);\n state._callerPackageMap?.set(spec.local.name, src);\n }\n\n const compatDescriptor = compatCallersForSource.find(\n (descriptor) => descriptor.callerName === importedName\n );\n if (compatDescriptor) {\n state._compatCallerMap?.set(\n spec.local.name,\n compatDescriptor\n );\n }\n }\n },\n });\n\n // Pre-pass to determine if dictionary-level overrides require the\n // dynamic helper in an otherwise static file, and to disable the\n // rewrite for compat callers with unresolvable call sites.\n const packagesWithDynamicCall = new Set<string>();\n const packagesWithFetchCall = new Set<string>();\n let compatHasDynamicCall = false;\n const unresolvableCompatLocalNames = new Set<string>();\n programPath.traverse({\n CallExpression(path) {\n const callee = path.node.callee;\n\n if (!t.isIdentifier(callee)) return;\n\n const compatDescriptor = state._compatCallerMap?.get(callee.name);\n if (compatDescriptor) {\n const namespaceMatch = resolveCompatNamespaceMatch(\n t,\n path.node.arguments,\n compatDescriptor\n );\n\n if (!namespaceMatch) {\n // Dynamic/absent namespace: the whole local caller must keep\n // its original implementation — rewriting the import while\n // leaving this call untouched would hand a raw namespace\n // string to the dictionary-accepting helper.\n unresolvableCompatLocalNames.add(callee.name);\n return;\n }\n\n const { dictionaryKey } = splitNamespace(\n namespaceMatch.fullNamespace\n );\n const compatOverrideMode =\n state.opts.dictionaryModeMap?.[dictionaryKey];\n if (\n compatOverrideMode === 'dynamic' ||\n compatOverrideMode === 'fetch'\n ) {\n compatHasDynamicCall = true;\n }\n return;\n }\n\n const originalImportedName = state._callerMap?.get(callee.name);\n if (originalImportedName !== 'useIntlayer') return;\n\n const callerPackage = state._callerPackageMap?.get(callee.name);\n if (!callerPackage) return;\n\n const key = getKeyFromArgument(path.node.arguments[0], t);\n if (!key) return;\n\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (dictionaryOverrideMode === 'dynamic') {\n packagesWithDynamicCall.add(callerPackage);\n } else if (dictionaryOverrideMode === 'fetch') {\n packagesWithFetchCall.add(callerPackage);\n }\n },\n });\n\n for (const localName of unresolvableCompatLocalNames) {\n state._compatCallerMap?.delete(localName);\n }\n\n const getHelperPlan = (packageName: string): PackageHelperPlan =>\n resolveHelperPlan(\n packageName,\n state.opts.importMode,\n state.opts.isServer,\n packagesWithDynamicCall.has(packageName),\n packagesWithFetchCall.has(packageName)\n );\n\n // Compat helpers are swapped per file (one import specifier serves\n // every call), so the dynamic decision is file-level: a global\n // dynamic/fetch mode or any per-dictionary override flips all\n // rewritten compat calls to the dynamic helper.\n const compatUseDynamicHelpers =\n state.opts.importMode === 'dynamic' ||\n state.opts.importMode === 'fetch' ||\n compatHasDynamicCall;\n\n programPath.traverse({\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n // Compat caller import rename: point the specifier at the\n // dictionary-accepting helper exported by the compat package\n // (`useTranslation` → `useDictionary`), keeping the local alias\n // so call sites read unchanged. Locals with unresolvable call\n // sites were dropped from the map and keep the original import.\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const compatDescriptor = state._compatCallerMap?.get(\n spec.local.name\n );\n if (!compatDescriptor) continue;\n if (!compatDescriptor.importSources.includes(src)) continue;\n\n spec.imported = t.identifier(\n compatUseDynamicHelpers\n ? compatDescriptor.dynamicReplacement!\n : compatDescriptor.staticReplacement!\n );\n }\n\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Per-import swap, mirrored across bundles — Solid hydration\n // ids rely on the SSR and client helpers consuming one\n // resource slot per call alike (see solid-intlayer/server).\n const helperPlan = getHelperPlan(src);\n const serverSource =\n helperPlan === 'ssrStatic'\n ? SSR_STATIC_IMPORT_SOURCE[src]\n : undefined;\n\n const helperMap: Record<string, string> =\n helperPlan === 'dynamic'\n ? DYNAMIC_HELPER_MAP\n : STATIC_IMPORT_FUNCTION;\n\n const serverSpecifiers: BabelTypes.ImportSpecifier[] = [];\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as BabelTypes.StringLiteral).value;\n\n if (!isCallerName(importedName)) continue;\n\n if (serverSource && importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n serverSpecifiers.push(spec);\n continue;\n }\n\n const newIdentifier = helperMap[importedName];\n\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n\n if (serverSpecifiers.length > 0 && serverSource) {\n // Move the helper to the /server entry, keeping any other\n // specifiers (useLocale, …) on the original import.\n path.insertAfter(\n t.importDeclaration(\n serverSpecifiers,\n t.stringLiteral(serverSource)\n )\n );\n path.node.specifiers = path.node.specifiers.filter(\n (spec) =>\n !serverSpecifiers.includes(\n spec as BabelTypes.ImportSpecifier\n )\n );\n if (path.node.specifiers.length === 0) {\n path.remove();\n }\n }\n },\n\n /* Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) or useDictionaryDynamic(_hash, \"foo\") */\n CallExpression(path) {\n const callee = path.node.callee;\n\n if (!t.isIdentifier(callee)) return;\n\n // Compat caller rewrite, e.g. (mirroring the SWC plugin):\n // static: useTranslation('about.counter', opts)\n // → useDictionary(_hash, 'counter', opts)\n // dynamic: useTranslation('about.counter', opts)\n // → useDictionaryDynamic(_hash_dyn, 'about', 'counter', opts)\n // option: useI18n({ namespace: 'about' })\n // → useDictionary(_hash, {})\n // fixed: useLingui() → useDictionary(_hash)\n const compatDescriptor = state._compatCallerMap?.get(callee.name);\n if (compatDescriptor) {\n const callArguments = path.node.arguments;\n const namespaceMatch = resolveCompatNamespaceMatch(\n t,\n callArguments,\n compatDescriptor\n );\n if (!namespaceMatch) return; // filtered by the pre-pass — stay safe\n\n state._hasValidImport = true;\n\n const { dictionaryKey, keyPrefix } = splitNamespace(\n namespaceMatch.fullNamespace\n );\n const compatOverrideMode =\n state.opts.dictionaryModeMap?.[dictionaryKey];\n\n // The import specifier serves every call in the file, so a\n // dynamic file receives a dynamic loader for every call.\n let compatCallMode: ImportMode = 'static';\n if (compatUseDynamicHelpers) {\n if (\n compatOverrideMode === 'dynamic' ||\n compatOverrideMode === 'fetch'\n ) {\n compatCallMode = compatOverrideMode;\n } else if (\n state.opts.importMode === 'dynamic' ||\n state.opts.importMode === 'fetch'\n ) {\n compatCallMode = state.opts.importMode;\n } else {\n compatCallMode = 'dynamic';\n }\n }\n\n let dictionaryIdent: BabelTypes.Identifier;\n if (compatCallMode === 'static') {\n let staticIdent = state._newStaticImports?.get(dictionaryKey);\n if (!staticIdent) {\n staticIdent = makeIdent(dictionaryKey, t);\n state._newStaticImports?.set(dictionaryKey, staticIdent);\n }\n dictionaryIdent = staticIdent;\n } else {\n let dynamicIdent =\n state._newDynamicImports?.get(dictionaryKey);\n if (!dynamicIdent) {\n const hash = getPathHash(dictionaryKey);\n const suffix = compatCallMode === 'fetch' ? 'fetch' : 'dyn';\n dynamicIdent = t.identifier(`_${hash}_${suffix}`);\n state._newDynamicImports?.set(dictionaryKey, dynamicIdent);\n }\n dictionaryIdent = dynamicIdent;\n }\n\n if (namespaceMatch.argumentIndex !== undefined) {\n // Positional namespace: replace the string with the\n // dictionary, then (dynamic) key and (nested) prefix.\n callArguments[namespaceMatch.argumentIndex] = t.identifier(\n dictionaryIdent.name\n );\n const insertAt = namespaceMatch.argumentIndex + 1;\n const insertedArguments: BabelTypes.Expression[] = [];\n if (compatCallMode !== 'static') {\n insertedArguments.push(t.stringLiteral(dictionaryKey));\n }\n if (keyPrefix) {\n insertedArguments.push(t.stringLiteral(keyPrefix));\n }\n callArguments.splice(insertAt, 0, ...insertedArguments);\n } else if (compatCallMode !== 'static') {\n // Fixed / option namespace, dynamic helper: prepend the\n // loader and the dictionary key.\n callArguments.unshift(\n t.identifier(dictionaryIdent.name),\n t.stringLiteral(dictionaryKey)\n );\n } else {\n // Fixed / option namespace, static helper: prepend the\n // dictionary object.\n callArguments.unshift(t.identifier(dictionaryIdent.name));\n }\n\n // Option namespace: leave only the key-prefix remainder in the\n // options object (or drop the property for a plain namespace),\n // so the runtime helper does not re-apply the dictionary key\n // as a lookup prefix.\n if (\n namespaceMatch.optionProperty &&\n namespaceMatch.optionsObject\n ) {\n if (keyPrefix) {\n namespaceMatch.optionProperty.value =\n t.stringLiteral(keyPrefix);\n } else {\n namespaceMatch.optionsObject.properties =\n namespaceMatch.optionsObject.properties.filter(\n (property) => property !== namespaceMatch.optionProperty\n );\n }\n }\n\n return;\n }\n\n const originalImportedName = state._callerMap?.get(callee.name);\n if (!originalImportedName) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn't import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const key = getKeyFromArgument(path.node.arguments[0], t);\n if (!key) return;\n\n const callerPackage = state._callerPackageMap?.get(callee.name);\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n const helperPlan =\n callerPackage === undefined\n ? 'static'\n : getHelperPlan(callerPackage);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'.\n let perCallMode: ImportMode = 'static';\n\n if (isUseIntlayer && helperPlan === 'dynamic') {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic' || importMode === 'fetch') {\n perCallMode = importMode;\n }\n } else if (isUseIntlayer && helperPlan === 'static') {\n // The global mode is static, but a per-dictionary override can\n // still force dynamic/fetch for this specific call.\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n perCallMode = dictionaryOverrideMode;\n }\n }\n\n let ident: BabelTypes.Identifier;\n\n if (perCallMode === 'fetch') {\n // Use fetch dictionaries entry for selected keys\n let dynamicIdent = state._newDynamicImports?.get(key);\n\n if (!dynamicIdent) {\n const hash = getPathHash(key);\n dynamicIdent = t.identifier(`_${hash}_fetch`);\n state._newDynamicImports?.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Helper: first argument is the dictionary entry, second is the key\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else if (perCallMode === 'dynamic') {\n // Use dynamic dictionaries entry\n let dynamicIdent = state._newDynamicImports?.get(key);\n\n if (!dynamicIdent) {\n // Create a unique identifier for dynamic imports by appending a suffix\n const hash = getPathHash(key);\n dynamicIdent = t.identifier(`_${hash}_dyn`);\n state._newDynamicImports?.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Dynamic helper: first argument is the dictionary, second is the key.\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else {\n // Use static imports for getIntlayer or useIntlayer when not using dynamic helpers\n let staticIdent = state._newStaticImports?.get(key);\n\n if (!staticIdent) {\n staticIdent = makeIdent(key, t);\n state._newStaticImports?.set(key, staticIdent);\n }\n ident = staticIdent;\n\n // Static helper (useDictionary / getDictionary): replace key with ident.\n // After the splice above the key is always at index 0.\n path.node.arguments[0] = t.identifier(ident.name);\n }\n },\n });\n\n // Early-out if we touched nothing\n\n if (!state._hasValidImport) return;\n\n const file = state.file.opts.filename!;\n const dictionariesDir = state.opts.dictionariesDir;\n const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;\n const fetchDictionariesDir = state.opts.fetchDictionariesDir;\n const imports: BabelTypes.ImportDeclaration[] = [];\n\n // Generate static JSON imports (getIntlayer always uses JSON dictionaries)\n for (const [key, ident] of state._newStaticImports!) {\n const rel = computeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n 'static'\n );\n\n const importDeclarationNode = t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n );\n\n // Add 'type: json' attribute for JSON files\n importDeclarationNode.attributes = [\n t.importAttribute(t.identifier('type'), t.stringLiteral('json')),\n ];\n\n imports.push(importDeclarationNode);\n }\n\n // Generate dynamic/fetch imports (for useIntlayer when using dynamic/fetch helpers)\n for (const [key, ident] of state._newDynamicImports!) {\n const modeForThisIdent: 'dynamic' | 'fetch' = ident.name.endsWith(\n '_fetch'\n )\n ? 'fetch'\n : 'dynamic';\n\n const rel = computeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n key,\n modeForThisIdent\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get(\n 'body'\n ) as NodePath<BabelTypes.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n !stmt.expression.value.startsWith('import') &&\n !stmt.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n },\n };\n};\n"],"mappings":";;;;;;;;AAWA,MAAM,eAAe;CACnB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,cAAc,CAAC,eAAe,aAAa;;;;AAKjD,MAAM,uBAAuB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,yBAAyB;CAC7B,aAAa;CACb,aAAa;AACf;AAEA,MAAM,0BAA0B,EAC9B,aAAa,uBACf;;AAGA,MAAM,qBAA6C;CACjD,GAAG;CACH,GAAG;AACL;;;;;;;;AASA,MAAM,2BAA4D,EAChE,kBAAkB,wBACpB;;;;;;AA6GA,MAAM,aACJ,KACA,MAC0B;CAC1B,MAAM,+CAAmB,GAAG;CAC5B,OAAO,EAAE,WAAW,IAAI,MAAM;AAChC;AAEA,MAAM,iBACJ,UACA,iBACA,wBACA,sBACA,KACA,eACW;CACX,IAAI,mCAAoB,iBAAiB,GAAG,IAAI,MAAM;CAEtD,IAAI,eAAe,SACjB,mCAAoB,sBAAsB,GAAG,IAAI,KAAK;CAGxD,IAAI,eAAe,WACjB,mCAAoB,wBAAwB,GAAG,IAAI,KAAK;CAG1D,IAAI,qDAAuB,QAAQ,GAAG,YAAY;CAGlD,gDAAoB,GAAG;CAGvB,IAAI,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,GAChD,MAAM,KAAK;CAGb,OAAO;AACT;AAEA,MAAM,sBACJ,KACA,MACuB;CACvB,IAAI,OAAO,EAAE,gBAAgB,GAAG,GAC9B,OAAO,IAAI;CAGb,IACE,OACA,EAAE,kBAAkB,GAAG,KACvB,IAAI,YAAY,WAAW,KAC3B,IAAI,OAAO,WAAW,GAEtB,OAAO,IAAI,OAAO,EAAE,EAAE,MAAM,UAAU,IAAI,OAAO,EAAE,EAAE,MAAM;AAI/D;AAEA,MAAM,gBAAgB,SACpB,YAAY,SAAS,IAAkB;;;;;;;;;AAUzC,MAAM,kBACJ,cACiD;CACjD,MAAM,cAAc,UAAU,QAAQ,GAAG;CACzC,IAAI,gBAAgB,IAAI,OAAO;EAAE,eAAe;EAAW,WAAW;CAAG;CACzE,OAAO;EACL,eAAe,UAAU,MAAM,GAAG,WAAW;EAC7C,WAAW,UAAU,MAAM,cAAc,CAAC;CAC5C;AACF;;;;;;;;;AA4BA,MAAM,+BACJ,GACA,eACA,eACqC;CACrC,KAAK,MAAM,UAAU,WAAW,kBAAkB;EAChD,IAAI,OAAO,SAAS,SAClB,OAAO,EAAE,eAAe,OAAO,MAAM;EAGvC,IAAI,OAAO,SAAS,YAAY;GAC9B,MAAM,YAAY,mBAAmB,cAAc,OAAO,QAAQ,CAAC;GACnE,IAAI,cAAc,QAChB,OAAO;IAAE,eAAe;IAAW,eAAe,OAAO;GAAM;GAEjE;EACF;EAEA,IAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,kBAAkB,cAAc,OAAO;GAC7C,IAAI,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,eAAe,GAAG;GAEhE,KAAK,MAAM,YAAY,gBAAgB,YAAY;IACjD,IAAI,CAAC,EAAE,iBAAiB,QAAQ,GAAG;IAMnC,IAAI,EAJD,EAAE,aAAa,SAAS,GAAG,KAC1B,SAAS,IAAI,SAAS,OAAO,YAC9B,EAAE,gBAAgB,SAAS,GAAG,KAC7B,SAAS,IAAI,UAAU,OAAO,WACjB;IAEjB,MAAM,YAAY,mBAAmB,SAAS,OAAO,CAAC;IACtD,IAAI,cAAc,QAChB,OAAO;KACL,eAAe;KACf,gBAAgB;KAChB,eAAe;IACjB;GAEJ;EACF;CACF;AAGF;AAEA,MAAM,oBACJ,gBAEA,qBAAqB,SACnB,WACF;;;;;;;;;AAoBF,MAAM,qBACJ,aACA,YACA,UACA,uBACA,wBACsB;CACtB,IAAI,CAAC,iBAAiB,WAAW,GAAG,OAAO;CAE3C,IAAI,eAAe,WAAW,qBAAqB,OAAO;CAE1D,IAAI,eAAe,aAAa,uBAC9B,OAAO,aAAa,OAAO,cAAc;CAG3C,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,MAAa,+BAA+B,UAEjB;CACzB,MAAM,EAAE,OAAO,MAAM;CAErB,OAAO;EACL,MAAM;EAEN,MAAM;GACJ,KAAK,oCAAoB,IAAI,IAAI;GACjC,KAAK,qCAAqB,IAAI,IAAI;GAClC,KAAK,6BAAa,IAAI,IAAI;GAC1B,KAAK,oCAAoB,IAAI,IAAI;GACjC,KAAK,mCAAmB,IAAI,IAAI;GAChC,KAAK,cAAc;GACnB,KAAK,kBAAkB;GACvB,KAAK,eAAe;GAGpB,IAAI,KAAK,KAAK,aAAa,OAAO;IAChC,KAAK,cAAc;IACnB;GACF;GAGA,MAAM,WAAW,KAAK,KAAK,KAAK,qDACd,KAAK,KAAK,KAAK,QAAQ,IACrC;GACJ,IAAI,KAAK,KAAK,aAAa,UAKzB;QAAI,CAJeA,sDAA0B,KAAK,KAAK,SAAS,CAAC,CAAC,IAChE,QAGY,GAAG;KAEf,KAAK,cAAc;KACnB;IACF;;EAEJ;EAEA,SAAS,EAEP,SAAS;GACP,MAAM,aAAa,OAAO;IAExB,MAAM,WAAW,MAAM,KAAK,KAAK,qDACf,MAAM,KAAK,KAAK,QAAQ,IACtC;IACJ,MAAM,wBAAwB,MAAM,KAAK,kEACvB,MAAM,KAAK,qBAAqB,IAC9C;IAIJ,IACE,MAAM,KAAK,0BACX,aAAa,uBACb;KACA,MAAM,eAAe;KAGrB,YAAY,SAAS;MAEnB,kBAAkB,MAAM;OACtB,KAAK,OAAO;MACd;MAGA,mBAAmB,MAAM;OAGvB,IAAI,EAAE,mBAAmB,KAAK,KAAK,IAAI,GAErC,KAAK,KAAK,KAAK,aAAa,CAAC;MAEjC;KACF,CAAC;IAIH;GACF;;;;;;;;;GAUA,KAAK,aAAa,OAAO;IACvB,IAAI,MAAM,cAAc;IAExB,IAAI,CAAC,MAAM,aAAa;IAIxB,MAAM,6EACJ,MAAM,KAAK,iBAAiB,CAAC,CAC/B;IAIA,YAAY,SAAS,EAEnB,kBAAkB,MAAM;KACtB,MAAM,MAAM,KAAK,KAAK,OAAO;KAE7B,MAAM,kBAAkB,aAAa,SAAS,GAAG;KACjD,MAAM,yBAAyB,wBAAwB,QACpD,eAAe,WAAW,cAAc,SAAS,GAAG,CACvD;KAEA,IAAI,CAAC,mBAAmB,uBAAuB,WAAW,GACxD;KAGF,MAAM,kBAAkB;KAExB,KAAK,MAAM,QAAQ,KAAK,KAAK,YAAY;MACvC,IAAI,CAAC,EAAE,kBAAkB,IAAI,GAAG;MAEhC,MAAM,eAAe,EAAE,aAAa,KAAK,QAAQ,IAC7C,KAAK,SAAS,OACb,KAAK,SAAsC;MAEhD,IAAI,mBAAmB,aAAa,YAAY,GAAG;OACjD,MAAM,YAAY,IAAI,KAAK,MAAM,MAAM,YAAY;OACnD,MAAM,mBAAmB,IAAI,KAAK,MAAM,MAAM,GAAG;MACnD;MAEA,MAAM,mBAAmB,uBAAuB,MAC7C,eAAe,WAAW,eAAe,YAC5C;MACA,IAAI,kBACF,MAAM,kBAAkB,IACtB,KAAK,MAAM,MACX,gBACF;KAEJ;IACF,EACF,CAAC;IAKD,MAAM,0CAA0B,IAAI,IAAY;IAChD,MAAM,wCAAwB,IAAI,IAAY;IAC9C,IAAI,uBAAuB;IAC3B,MAAM,+CAA+B,IAAI,IAAY;IACrD,YAAY,SAAS,EACnB,eAAe,MAAM;KACnB,MAAM,SAAS,KAAK,KAAK;KAEzB,IAAI,CAAC,EAAE,aAAa,MAAM,GAAG;KAE7B,MAAM,mBAAmB,MAAM,kBAAkB,IAAI,OAAO,IAAI;KAChE,IAAI,kBAAkB;MACpB,MAAM,iBAAiB,4BACrB,GACA,KAAK,KAAK,WACV,gBACF;MAEA,IAAI,CAAC,gBAAgB;OAKnB,6BAA6B,IAAI,OAAO,IAAI;OAC5C;MACF;MAEA,MAAM,EAAE,kBAAkB,eACxB,eAAe,aACjB;MACA,MAAM,qBACJ,MAAM,KAAK,oBAAoB;MACjC,IACE,uBAAuB,aACvB,uBAAuB,SAEvB,uBAAuB;MAEzB;KACF;KAGA,IAD6B,MAAM,YAAY,IAAI,OAAO,IAAI,MACjC,eAAe;KAE5C,MAAM,gBAAgB,MAAM,mBAAmB,IAAI,OAAO,IAAI;KAC9D,IAAI,CAAC,eAAe;KAEpB,MAAM,MAAM,mBAAmB,KAAK,KAAK,UAAU,IAAI,CAAC;KACxD,IAAI,CAAC,KAAK;KAEV,MAAM,yBACJ,MAAM,KAAK,oBAAoB;KAEjC,IAAI,2BAA2B,WAC7B,wBAAwB,IAAI,aAAa;UACpC,IAAI,2BAA2B,SACpC,sBAAsB,IAAI,aAAa;IAE3C,EACF,CAAC;IAED,KAAK,MAAM,aAAa,8BACtB,MAAM,kBAAkB,OAAO,SAAS;IAG1C,MAAM,iBAAiB,gBACrB,kBACE,aACA,MAAM,KAAK,YACX,MAAM,KAAK,UACX,wBAAwB,IAAI,WAAW,GACvC,sBAAsB,IAAI,WAAW,CACvC;IAMF,MAAM,0BACJ,MAAM,KAAK,eAAe,aAC1B,MAAM,KAAK,eAAe,WAC1B;IAEF,YAAY,SAAS;KACnB,kBAAkB,MAAM;MACtB,MAAM,MAAM,KAAK,KAAK,OAAO;MAO7B,KAAK,MAAM,QAAQ,KAAK,KAAK,YAAY;OACvC,IAAI,CAAC,EAAE,kBAAkB,IAAI,GAAG;OAEhC,MAAM,mBAAmB,MAAM,kBAAkB,IAC/C,KAAK,MAAM,IACb;OACA,IAAI,CAAC,kBAAkB;OACvB,IAAI,CAAC,iBAAiB,cAAc,SAAS,GAAG,GAAG;OAEnD,KAAK,WAAW,EAAE,WAChB,0BACI,iBAAiB,qBACjB,iBAAiB,iBACvB;MACF;MAEA,IAAI,CAAC,aAAa,SAAS,GAAG,GAAG;MAKjC,MAAM,aAAa,cAAc,GAAG;MACpC,MAAM,eACJ,eAAe,cACX,yBAAyB,OACzB;MAEN,MAAM,YACJ,eAAe,YACX,qBACA;MAEN,MAAM,mBAAiD,CAAC;MAExD,KAAK,MAAM,QAAQ,KAAK,KAAK,YAAY;OACvC,IAAI,CAAC,EAAE,kBAAkB,IAAI,GAAG;OAEhC,MAAM,eAAe,EAAE,aAAa,KAAK,QAAQ,IAC7C,KAAK,SAAS,OACb,KAAK,SAAsC;OAEhD,IAAI,CAAC,aAAa,YAAY,GAAG;OAEjC,IAAI,gBAAgB,iBAAiB,eAAe;QAClD,KAAK,WAAW,EAAE,WAAW,eAAe;QAC5C,iBAAiB,KAAK,IAAI;QAC1B;OACF;OAEA,MAAM,gBAAgB,UAAU;OAEhC,IAAI,eAIF,KAAK,WAAW,EAAE,WAAW,aAAa;MAE9C;MAEA,IAAI,iBAAiB,SAAS,KAAK,cAAc;OAG/C,KAAK,YACH,EAAE,kBACA,kBACA,EAAE,cAAc,YAAY,CAC9B,CACF;OACA,KAAK,KAAK,aAAa,KAAK,KAAK,WAAW,QACzC,SACC,CAAC,iBAAiB,SAChB,IACF,CACJ;OACA,IAAI,KAAK,KAAK,WAAW,WAAW,GAClC,KAAK,OAAO;MAEhB;KACF;KAGA,eAAe,MAAM;MACnB,MAAM,SAAS,KAAK,KAAK;MAEzB,IAAI,CAAC,EAAE,aAAa,MAAM,GAAG;MAU7B,MAAM,mBAAmB,MAAM,kBAAkB,IAAI,OAAO,IAAI;MAChE,IAAI,kBAAkB;OACpB,MAAM,gBAAgB,KAAK,KAAK;OAChC,MAAM,iBAAiB,4BACrB,GACA,eACA,gBACF;OACA,IAAI,CAAC,gBAAgB;OAErB,MAAM,kBAAkB;OAExB,MAAM,EAAE,eAAe,cAAc,eACnC,eAAe,aACjB;OACA,MAAM,qBACJ,MAAM,KAAK,oBAAoB;OAIjC,IAAI,iBAA6B;OACjC,IAAI,yBACF,IACE,uBAAuB,aACvB,uBAAuB,SAEvB,iBAAiB;YACZ,IACL,MAAM,KAAK,eAAe,aAC1B,MAAM,KAAK,eAAe,SAE1B,iBAAiB,MAAM,KAAK;YAE5B,iBAAiB;OAIrB,IAAI;OACJ,IAAI,mBAAmB,UAAU;QAC/B,IAAI,cAAc,MAAM,mBAAmB,IAAI,aAAa;QAC5D,IAAI,CAAC,aAAa;SAChB,cAAc,UAAU,eAAe,CAAC;SACxC,MAAM,mBAAmB,IAAI,eAAe,WAAW;QACzD;QACA,kBAAkB;OACpB,OAAO;QACL,IAAI,eACF,MAAM,oBAAoB,IAAI,aAAa;QAC7C,IAAI,CAAC,cAAc;SACjB,MAAM,+CAAmB,aAAa;SACtC,MAAM,SAAS,mBAAmB,UAAU,UAAU;SACtD,eAAe,EAAE,WAAW,IAAI,KAAK,GAAG,QAAQ;SAChD,MAAM,oBAAoB,IAAI,eAAe,YAAY;QAC3D;QACA,kBAAkB;OACpB;OAEA,IAAI,eAAe,kBAAkB,QAAW;QAG9C,cAAc,eAAe,iBAAiB,EAAE,WAC9C,gBAAgB,IAClB;QACA,MAAM,WAAW,eAAe,gBAAgB;QAChD,MAAM,oBAA6C,CAAC;QACpD,IAAI,mBAAmB,UACrB,kBAAkB,KAAK,EAAE,cAAc,aAAa,CAAC;QAEvD,IAAI,WACF,kBAAkB,KAAK,EAAE,cAAc,SAAS,CAAC;QAEnD,cAAc,OAAO,UAAU,GAAG,GAAG,iBAAiB;OACxD,OAAO,IAAI,mBAAmB,UAG5B,cAAc,QACZ,EAAE,WAAW,gBAAgB,IAAI,GACjC,EAAE,cAAc,aAAa,CAC/B;YAIA,cAAc,QAAQ,EAAE,WAAW,gBAAgB,IAAI,CAAC;OAO1D,IACE,eAAe,kBACf,eAAe,eAEf,IAAI,WACF,eAAe,eAAe,QAC5B,EAAE,cAAc,SAAS;YAE3B,eAAe,cAAc,aAC3B,eAAe,cAAc,WAAW,QACrC,aAAa,aAAa,eAAe,cAC5C;OAIN;MACF;MAEA,MAAM,uBAAuB,MAAM,YAAY,IAAI,OAAO,IAAI;MAC9D,IAAI,CAAC,sBAAsB;MAK3B,MAAM,kBAAkB;MAExB,MAAM,MAAM,mBAAmB,KAAK,KAAK,UAAU,IAAI,CAAC;MACxD,IAAI,CAAC,KAAK;MAEV,MAAM,gBAAgB,MAAM,mBAAmB,IAAI,OAAO,IAAI;MAC9D,MAAM,aAAa,MAAM,KAAK;MAC9B,MAAM,gBAAgB,yBAAyB;MAC/C,MAAM,yBACJ,MAAM,KAAK,oBAAoB;MACjC,MAAM,aACJ,kBAAkB,SACd,WACA,cAAc,aAAa;MAGjC,IAAI,cAA0B;MAE9B,IAAI,iBAAiB,eAAe,WAClC;WAAI,wBACF,cAAc;YACT,IAAI,eAAe,aAAa,eAAe,SACpD,cAAc;MAChB,OACK,IAAI,iBAAiB,eAAe,UAGzC;WACE,2BAA2B,aAC3B,2BAA2B,SAE3B,cAAc;MAChB;MAGF,IAAI;MAEJ,IAAI,gBAAgB,SAAS;OAE3B,IAAI,eAAe,MAAM,oBAAoB,IAAI,GAAG;OAEpD,IAAI,CAAC,cAAc;QACjB,MAAM,+CAAmB,GAAG;QAC5B,eAAe,EAAE,WAAW,IAAI,KAAK,OAAO;QAC5C,MAAM,oBAAoB,IAAI,KAAK,YAAY;OACjD;OACA,QAAQ;OAGR,KAAK,KAAK,YAAY,CACpB,EAAE,WAAW,MAAM,IAAI,GACvB,GAAG,KAAK,KAAK,SACf;MACF,OAAO,IAAI,gBAAgB,WAAW;OAEpC,IAAI,eAAe,MAAM,oBAAoB,IAAI,GAAG;OAEpD,IAAI,CAAC,cAAc;QAEjB,MAAM,+CAAmB,GAAG;QAC5B,eAAe,EAAE,WAAW,IAAI,KAAK,KAAK;QAC1C,MAAM,oBAAoB,IAAI,KAAK,YAAY;OACjD;OACA,QAAQ;OAGR,KAAK,KAAK,YAAY,CACpB,EAAE,WAAW,MAAM,IAAI,GACvB,GAAG,KAAK,KAAK,SACf;MACF,OAAO;OAEL,IAAI,cAAc,MAAM,mBAAmB,IAAI,GAAG;OAElD,IAAI,CAAC,aAAa;QAChB,cAAc,UAAU,KAAK,CAAC;QAC9B,MAAM,mBAAmB,IAAI,KAAK,WAAW;OAC/C;OACA,QAAQ;OAIR,KAAK,KAAK,UAAU,KAAK,EAAE,WAAW,MAAM,IAAI;MAClD;KACF;IACF,CAAC;IAID,IAAI,CAAC,MAAM,iBAAiB;IAE5B,MAAM,OAAO,MAAM,KAAK,KAAK;IAC7B,MAAM,kBAAkB,MAAM,KAAK;IACnC,MAAM,yBAAyB,MAAM,KAAK;IAC1C,MAAM,uBAAuB,MAAM,KAAK;IACxC,MAAM,UAA0C,CAAC;IAGjD,KAAK,MAAM,CAAC,KAAK,UAAU,MAAM,mBAAoB;KACnD,MAAM,MAAM,cACV,MACA,iBACA,wBACA,sBACA,KACA,QACF;KAEA,MAAM,wBAAwB,EAAE,kBAC9B,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC,GACnD,EAAE,cAAc,GAAG,CACrB;KAGA,sBAAsB,aAAa,CACjC,EAAE,gBAAgB,EAAE,WAAW,MAAM,GAAG,EAAE,cAAc,MAAM,CAAC,CACjE;KAEA,QAAQ,KAAK,qBAAqB;IACpC;IAGA,KAAK,MAAM,CAAC,KAAK,UAAU,MAAM,oBAAqB;KACpD,MAAM,mBAAwC,MAAM,KAAK,SACvD,QACF,IACI,UACA;KAEJ,MAAM,MAAM,cACV,MACA,iBACA,wBACA,sBACA,KACA,gBACF;KACA,QAAQ,KACN,EAAE,kBACA,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC,GACnD,EAAE,cAAc,GAAG,CACrB,CACF;IACF;IAEA,IAAI,CAAC,QAAQ,QAAQ;IAGrB,MAAM,YAAY,YAAY,IAC5B,MACF;IACA,IAAI,YAAY;IAChB,KAAK,MAAM,YAAY,WAAW;KAChC,MAAM,OAAO,SAAS;KAEtB,IACE,EAAE,sBAAsB,IAAI,KAC5B,EAAE,gBAAgB,KAAK,UAAU,KACjC,CAAC,KAAK,WAAW,MAAM,WAAW,QAAQ,KAC1C,CAAC,KAAK,WAAW,MAAM,WAAW,SAAS,GAE3C,aAAa;UAEb;IAEJ;IAEA,YAAY,KAAK,KAAK,OAAO,WAAW,GAAG,GAAG,OAAO;GACvD;EACF,EACF;CACF;AACF"}