@intlayer/babel 8.12.3 → 8.12.4

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.
@@ -6,6 +6,7 @@ let node_path = require("node:path");
6
6
  let _intlayer_config_colors = require("@intlayer/config/colors");
7
7
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
8
8
  let _intlayer_config_logger = require("@intlayer/config/logger");
9
+ let _intlayer_config_utils = require("@intlayer/config/utils");
9
10
  let _babel_parser = require("@babel/parser");
10
11
 
11
12
  //#region src/babel-plugin-intlayer-extract.ts
@@ -34,7 +35,7 @@ const intlayerExtractBabelPlugin = (_babel) => {
34
35
  if (opts.enabled === false) return;
35
36
  const filename = state.file.opts.filename;
36
37
  if (!filename) return;
37
- if (opts.filesList && !opts.filesList.includes(filename)) return;
38
+ if (opts.filesList && !opts.filesList.map(_intlayer_config_utils.normalizePath).includes((0, _intlayer_config_utils.normalizePath)(filename))) return;
38
39
  const fileCode = state.file.code ?? "";
39
40
  if (!fileCode) return;
40
41
  const appLogger = (0, _intlayer_config_logger.getAppLogger)(opts.configuration);
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-extract.cjs","names":["detectPackageName","extractContentSync","ANSIColors"],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { extractContentSync } from './extractContent/extractContent';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: Locale;\n};\n\nexport type ExtractPluginOptions = {\n packageName?: PackageName;\n filesList: string[];\n enabled: boolean;\n\n shouldExtract?: (text: string) => boolean;\n configuration: IntlayerConfig;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n /**\n * Defines the output files path.\n */\n output?: FilePathPattern;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (_babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n // Merge plugin options with the unified compiler config\n const isEnabled = opts.enabled;\n\n if (isEnabled === false) return;\n\n const filename = state.file.opts.filename;\n\n if (!filename) return;\n\n if (opts.filesList && !opts.filesList.includes(filename)) return;\n\n const fileCode: string = state.file.code ?? '';\n if (!fileCode) return;\n\n const appLogger = getAppLogger(opts.configuration);\n const packageName = opts.packageName ?? detectPackageName(filename);\n\n const { saveComponents } = opts.configuration.compiler;\n\n const result = extractContentSync(filename, packageName, {\n configuration: opts.configuration,\n code: fileCode,\n onExtract: (extractResult: {\n key: string;\n content: Record<string, string>;\n }) => {\n if (opts.onExtract) {\n opts.onExtract({\n dictionaryKey: extractResult.key,\n filePath: filename,\n content: extractResult.content,\n locale: opts.configuration.internationalization.defaultLocale,\n });\n }\n },\n declarationOnly: !saveComponents,\n });\n\n if (!result) return;\n\n const { transformedCode: modifiedCode } = result;\n\n if (!modifiedCode) return;\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(opts.configuration.system.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n appLogger(\n [\n `Failed to parse transformed code for ${colorizePath(relative(opts.configuration.system.baseDir, filename))}:`,\n error,\n ],\n { level: 'error' }\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,MAAa,8BAA8B,WAEnB;AACtB,QAAO;EACL,MAAM;EAEN,SAAS,EACP,SAAS,EACP,MAAM,aAAa,OAAO;GACxB,MAAM,OAAO,MAAM;AAKnB,OAFkB,KAAK,YAEL,MAAO;GAEzB,MAAM,WAAW,MAAM,KAAK,KAAK;AAEjC,OAAI,CAAC,SAAU;AAEf,OAAI,KAAK,aAAa,CAAC,KAAK,UAAU,SAAS,SAAS,CAAE;GAE1D,MAAM,WAAmB,MAAM,KAAK,QAAQ;AAC5C,OAAI,CAAC,SAAU;GAEf,MAAM,sDAAyB,KAAK,cAAc;GAClD,MAAM,cAAc,KAAK,eAAeA,iEAAkB,SAAS;GAEnE,MAAM,EAAE,mBAAmB,KAAK,cAAc;GAE9C,MAAM,SAASC,yDAAmB,UAAU,aAAa;IACvD,eAAe,KAAK;IACpB,MAAM;IACN,YAAY,kBAGN;AACJ,SAAI,KAAK,UACP,MAAK,UAAU;MACb,eAAe,cAAc;MAC7B,UAAU;MACV,SAAS,cAAc;MACvB,QAAQ,KAAK,cAAc,qBAAqB;MACjD,CAAC;;IAGN,iBAAiB,CAAC;IACnB,CAAC;AAEF,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,iBAAiB,iBAAiB;AAE1C,OAAI,CAAC,aAAc;AAKnB,OAAI;IACF,MAAM,kCAAe,cAAc;KACjC,YAAY;KACZ,SAAS,CAAC,OAAO,aAAa;KAC/B,CAAC;AAEF,gBAAY,KAAK,OAAO,OAAO,QAAQ;AACvC,gBAAY,KAAK,aAAa,OAAO,QAAQ;AAE7C,cACE,yCAAY,aAAaC,wBAAW,UAAU,CAAC,4FAAgD,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,IAC5I,EAAE,OAAO,SAAS,CACnB;YACM,OAAO;AACd,cACE,CACE,0GAA8D,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,CAAC,IAC5G,MACD,EACD,EAAE,OAAO,SAAS,CACnB;;KAGN,EACF;EACF"}
1
+ {"version":3,"file":"babel-plugin-intlayer-extract.cjs","names":["normalizePath","detectPackageName","extractContentSync","ANSIColors"],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { extractContentSync } from './extractContent/extractContent';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: Locale;\n};\n\nexport type ExtractPluginOptions = {\n packageName?: PackageName;\n filesList: string[];\n enabled: boolean;\n\n shouldExtract?: (text: string) => boolean;\n configuration: IntlayerConfig;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n /**\n * Defines the output files path.\n */\n output?: FilePathPattern;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (_babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n // Merge plugin options with the unified compiler config\n const isEnabled = opts.enabled;\n\n if (isEnabled === false) return;\n\n const filename = state.file.opts.filename;\n\n if (!filename) return;\n\n // Compare as POSIX paths (babel filenames use OS separators on Windows).\n if (\n opts.filesList &&\n !opts.filesList.map(normalizePath).includes(normalizePath(filename))\n ) {\n return;\n }\n\n const fileCode: string = state.file.code ?? '';\n if (!fileCode) return;\n\n const appLogger = getAppLogger(opts.configuration);\n const packageName = opts.packageName ?? detectPackageName(filename);\n\n const { saveComponents } = opts.configuration.compiler;\n\n const result = extractContentSync(filename, packageName, {\n configuration: opts.configuration,\n code: fileCode,\n onExtract: (extractResult: {\n key: string;\n content: Record<string, string>;\n }) => {\n if (opts.onExtract) {\n opts.onExtract({\n dictionaryKey: extractResult.key,\n filePath: filename,\n content: extractResult.content,\n locale: opts.configuration.internationalization.defaultLocale,\n });\n }\n },\n declarationOnly: !saveComponents,\n });\n\n if (!result) return;\n\n const { transformedCode: modifiedCode } = result;\n\n if (!modifiedCode) return;\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(opts.configuration.system.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n appLogger(\n [\n `Failed to parse transformed code for ${colorizePath(relative(opts.configuration.system.baseDir, filename))}:`,\n error,\n ],\n { level: 'error' }\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,MAAa,8BAA8B,WAEnB;AACtB,QAAO;EACL,MAAM;EAEN,SAAS,EACP,SAAS,EACP,MAAM,aAAa,OAAO;GACxB,MAAM,OAAO,MAAM;AAKnB,OAFkB,KAAK,YAEL,MAAO;GAEzB,MAAM,WAAW,MAAM,KAAK,KAAK;AAEjC,OAAI,CAAC,SAAU;AAGf,OACE,KAAK,aACL,CAAC,KAAK,UAAU,IAAIA,qCAAc,CAAC,mDAAuB,SAAS,CAAC,CAEpE;GAGF,MAAM,WAAmB,MAAM,KAAK,QAAQ;AAC5C,OAAI,CAAC,SAAU;GAEf,MAAM,sDAAyB,KAAK,cAAc;GAClD,MAAM,cAAc,KAAK,eAAeC,iEAAkB,SAAS;GAEnE,MAAM,EAAE,mBAAmB,KAAK,cAAc;GAE9C,MAAM,SAASC,yDAAmB,UAAU,aAAa;IACvD,eAAe,KAAK;IACpB,MAAM;IACN,YAAY,kBAGN;AACJ,SAAI,KAAK,UACP,MAAK,UAAU;MACb,eAAe,cAAc;MAC7B,UAAU;MACV,SAAS,cAAc;MACvB,QAAQ,KAAK,cAAc,qBAAqB;MACjD,CAAC;;IAGN,iBAAiB,CAAC;IACnB,CAAC;AAEF,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,iBAAiB,iBAAiB;AAE1C,OAAI,CAAC,aAAc;AAKnB,OAAI;IACF,MAAM,kCAAe,cAAc;KACjC,YAAY;KACZ,SAAS,CAAC,OAAO,aAAa;KAC/B,CAAC;AAEF,gBAAY,KAAK,OAAO,OAAO,QAAQ;AACvC,gBAAY,KAAK,aAAa,OAAO,QAAQ;AAE7C,cACE,yCAAY,aAAaC,wBAAW,UAAU,CAAC,4FAAgD,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,IAC5I,EAAE,OAAO,SAAS,CACnB;YACM,OAAO;AACd,cACE,CACE,0GAA8D,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,CAAC,IAC5G,MACD,EACD,EAAE,OAAO,SAAS,CACnB;;KAGN,EACF;EACF"}
@@ -47,6 +47,13 @@ const STATIC_IMPORT_FUNCTION = {
47
47
  };
48
48
  const DYNAMIC_IMPORT_FUNCTION = { useIntlayer: "useDictionaryDynamic" };
49
49
  /**
50
+ * Packages whose SSR dynamic helper should render synchronously with a static
51
+ * dictionary. Solid streaming SSR can hydrate static output reliably, while
52
+ * its dynamic resource path either suspends during hydration or serializes the
53
+ * full dictionary into HTML.
54
+ */
55
+ const PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK = new Set(["solid-intlayer"]);
56
+ /**
50
57
  * Replicates the xxHash64 → Base-62 algorithm used by the SWC version
51
58
  * and prefixes an underscore so the generated identifiers never collide
52
59
  * with user-defined ones.
@@ -64,6 +71,13 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
64
71
  if (!rel.startsWith("./") && !rel.startsWith("../")) rel = `./${rel}`;
65
72
  return rel;
66
73
  };
74
+ const getKeyFromArgument = (arg, t) => {
75
+ if (arg && t.isStringLiteral(arg)) return arg.value;
76
+ if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) return arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
77
+ };
78
+ const isCallerName = (name) => CALLER_LIST.includes(name);
79
+ const isDynamicPackage = (packageName) => PACKAGE_LIST_DYNAMIC.includes(packageName);
80
+ const shouldUseStaticSsrDynamicFallback = (callerPackage, importMode, opts) => opts.isServer === true && importMode === "dynamic" && callerPackage !== void 0 && PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK.has(callerPackage);
67
81
  /**
68
82
  * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.
69
83
  *
@@ -119,11 +133,11 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
119
133
  * const content2 = getIntlayer(_dicHash);
120
134
  * ```
121
135
  *
122
- * ### Live Mode (`importMode = "live"`)
136
+ * ### Fetch Mode (`importMode = "fetch"`)
123
137
  *
124
- * Uses live-based dictionary loading for remote dictionaries:
138
+ * Uses fetch-based dictionary loading for remote dictionaries:
125
139
  *
126
- * **Output if `dictionaryModeMap` includes the key with "live" value:**
140
+ * **Output if `dictionaryModeMap` includes the key with "fetch" value:**
127
141
  * ```ts
128
142
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
129
143
  * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';
@@ -134,7 +148,7 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
134
148
  * const content2 = getIntlayer(_dicHash);
135
149
  * ```
136
150
  *
137
- * > If `dictionaryModeMap` does not include the key with "live" value, the plugin will fallback to the dynamic impor
151
+ * > If `dictionaryModeMap` does not include the key with "fetch" value, the plugin will fallback to the dynamic import mode.
138
152
  *
139
153
  * ```ts
140
154
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
@@ -154,6 +168,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
154
168
  this._newStaticImports = /* @__PURE__ */ new Map();
155
169
  this._newDynamicImports = /* @__PURE__ */ new Map();
156
170
  this._callerMap = /* @__PURE__ */ new Map();
171
+ this._callerPackageMap = /* @__PURE__ */ new Map();
157
172
  this._isIncluded = true;
158
173
  this._hasValidImport = false;
159
174
  this._isDictEntry = false;
@@ -162,9 +177,9 @@ const intlayerOptimizeBabelPlugin = (babel) => {
162
177
  this._isIncluded = false;
163
178
  return;
164
179
  }
165
- const filename = this.file.opts.filename;
180
+ const filename = this.file.opts.filename ? (0, _intlayer_config_utils.normalizePath)(this.file.opts.filename) : void 0;
166
181
  if (this.opts.filesList && filename) {
167
- if (!this.opts.filesList.includes(filename)) {
182
+ if (!this.opts.filesList.map(_intlayer_config_utils.normalizePath).includes(filename)) {
168
183
  this._isIncluded = false;
169
184
  return;
170
185
  }
@@ -172,8 +187,9 @@ const intlayerOptimizeBabelPlugin = (babel) => {
172
187
  },
173
188
  visitor: { Program: {
174
189
  enter(programPath, state) {
175
- const filename = state.file.opts.filename;
176
- if (state.opts.replaceDictionaryEntry && filename === state.opts.dictionariesEntryPath) {
190
+ const filename = state.file.opts.filename ? (0, _intlayer_config_utils.normalizePath)(state.file.opts.filename) : void 0;
191
+ const dictionariesEntryPath = state.opts.dictionariesEntryPath ? (0, _intlayer_config_utils.normalizePath)(state.opts.dictionariesEntryPath) : void 0;
192
+ if (state.opts.replaceDictionaryEntry && filename === dictionariesEntryPath) {
177
193
  state._isDictEntry = true;
178
194
  programPath.traverse({
179
195
  ImportDeclaration(path) {
@@ -196,30 +212,46 @@ const intlayerOptimizeBabelPlugin = (babel) => {
196
212
  exit(programPath, state) {
197
213
  if (state._isDictEntry) return;
198
214
  if (!state._isIncluded) return;
199
- let fileHasDynamicCall = false;
215
+ programPath.traverse({ ImportDeclaration(path) {
216
+ const src = path.node.source.value;
217
+ if (!PACKAGE_LIST.includes(src)) return;
218
+ state._hasValidImport = true;
219
+ for (const spec of path.node.specifiers) {
220
+ if (!t.isImportSpecifier(spec)) continue;
221
+ const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
222
+ if (isCallerName(importedName)) {
223
+ state._callerMap?.set(spec.local.name, importedName);
224
+ state._callerPackageMap?.set(spec.local.name, src);
225
+ }
226
+ }
227
+ } });
228
+ const packagesWithDynamicCall = /* @__PURE__ */ new Set();
229
+ const packagesWithFetchCall = /* @__PURE__ */ new Set();
200
230
  programPath.traverse({ CallExpression(path) {
201
231
  const callee = path.node.callee;
202
232
  if (!t.isIdentifier(callee)) return;
203
233
  if (state._callerMap?.get(callee.name) !== "useIntlayer") return;
204
- const arg = path.node.arguments[0];
205
- let key;
206
- if (arg && t.isStringLiteral(arg)) key = arg.value;
207
- else if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
234
+ const callerPackage = state._callerPackageMap?.get(callee.name);
235
+ if (!callerPackage) return;
236
+ const key = getKeyFromArgument(path.node.arguments[0], t);
208
237
  if (!key) return;
209
238
  const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];
210
- if (dictionaryOverrideMode === "dynamic" || dictionaryOverrideMode === "fetch") fileHasDynamicCall = true;
239
+ if (dictionaryOverrideMode === "dynamic") packagesWithDynamicCall.add(callerPackage);
240
+ else if (dictionaryOverrideMode === "fetch") packagesWithFetchCall.add(callerPackage);
211
241
  } });
212
242
  programPath.traverse({
213
243
  ImportDeclaration(path) {
214
244
  const src = path.node.source.value;
215
245
  if (!PACKAGE_LIST.includes(src)) return;
216
- state._hasValidImport = true;
217
246
  for (const spec of path.node.specifiers) {
218
247
  if (!t.isImportSpecifier(spec)) continue;
219
248
  const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
220
- if (CALLER_LIST.includes(importedName)) state._callerMap?.set(spec.local.name, importedName);
249
+ if (!isCallerName(importedName)) continue;
221
250
  const importMode = state.opts.importMode;
222
- const shouldUseDynamicHelpers = (importMode === "dynamic" || importMode === "fetch" || fileHasDynamicCall) && PACKAGE_LIST_DYNAMIC.includes(src);
251
+ const packageHasDynamicCall = packagesWithDynamicCall.has(src);
252
+ const packageHasFetchCall = packagesWithFetchCall.has(src);
253
+ const shouldUseStaticFallback = !packageHasFetchCall && shouldUseStaticSsrDynamicFallback(src, importMode === "dynamic" || packageHasDynamicCall ? "dynamic" : importMode, state.opts);
254
+ const shouldUseDynamicHelpers = isDynamicPackage(src) && (importMode === "fetch" || packageHasFetchCall || (importMode === "dynamic" || packageHasDynamicCall) && !shouldUseStaticFallback);
223
255
  if (shouldUseDynamicHelpers) state._useDynamicHelpers = true;
224
256
  let helperMap;
225
257
  if (shouldUseDynamicHelpers) helperMap = {
@@ -237,21 +269,22 @@ const intlayerOptimizeBabelPlugin = (babel) => {
237
269
  const originalImportedName = state._callerMap?.get(callee.name);
238
270
  if (!originalImportedName) return;
239
271
  state._hasValidImport = true;
240
- const arg = path.node.arguments[0];
241
- let key;
242
- if (arg && t.isStringLiteral(arg)) key = arg.value;
243
- else if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
272
+ const key = getKeyFromArgument(path.node.arguments[0], t);
244
273
  if (!key) return;
274
+ const callerPackage = state._callerPackageMap?.get(callee.name);
245
275
  const importMode = state.opts.importMode;
246
276
  const isUseIntlayer = originalImportedName === "useIntlayer";
247
- const useDynamicHelpers = Boolean(state._useDynamicHelpers);
248
- let perCallMode = "static";
249
277
  const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];
278
+ const effectiveImportMode = dictionaryOverrideMode ?? importMode;
279
+ const packageHasFetchCall = callerPackage !== void 0 && packagesWithFetchCall.has(callerPackage);
280
+ const usesStaticSsrDynamicFallback = isUseIntlayer && !packageHasFetchCall && shouldUseStaticSsrDynamicFallback(callerPackage, effectiveImportMode, state.opts);
281
+ const useDynamicHelpers = Boolean(state._useDynamicHelpers) && !usesStaticSsrDynamicFallback;
282
+ let perCallMode = "static";
250
283
  if (isUseIntlayer && useDynamicHelpers) {
251
284
  if (dictionaryOverrideMode) perCallMode = dictionaryOverrideMode;
252
285
  else if (importMode === "dynamic") perCallMode = "dynamic";
253
286
  else if (importMode === "fetch") perCallMode = "fetch";
254
- } else if (isUseIntlayer && !useDynamicHelpers) {
287
+ } else if (isUseIntlayer && !useDynamicHelpers && !usesStaticSsrDynamicFallback) {
255
288
  if (dictionaryOverrideMode === "dynamic" || dictionaryOverrideMode === "fetch") perCallMode = dictionaryOverrideMode;
256
289
  }
257
290
  let ident;
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-optimize.cjs","names":[],"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 * 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\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 /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether dynamic helpers are active for this file */\n _useDynamicHelpers?: 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\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 * ### Live Mode (`importMode = \"live\"`)\n *\n * Uses live-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"live\" 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 \"live\" value, the plugin will fallback to the dynamic impor\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._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n this._useDynamicHelpers = 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 if (this.opts.filesList && filename) {\n const isIncluded = this.opts.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\n // Check if this is the correct file to transform\n\n if (\n state.opts.replaceDictionaryEntry &&\n filename === state.opts.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\n // Pre-pass to determine if we should use dynamic helpers\n let fileHasDynamicCall = false;\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 arg = path.node.arguments[0];\n let key: string | undefined;\n if (arg && t.isStringLiteral(arg)) {\n key = arg.value;\n } else if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n if (!key) return;\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n fileHasDynamicCall = true;\n }\n },\n });\n\n programPath.traverse({\n /* Inspect every intlayer import */\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file\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 (CALLER_LIST.includes(importedName as any)) {\n state._callerMap?.set(\n spec.local.name,\n importedName as (typeof CALLER_LIST)[number]\n );\n }\n\n const importMode = state.opts.importMode;\n // Determine whether this import should use the dynamic helpers.\n const shouldUseDynamicHelpers =\n (importMode === 'dynamic' ||\n importMode === 'fetch' ||\n fileHasDynamicCall) &&\n PACKAGE_LIST_DYNAMIC.includes(src as any);\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n let helperMap: Record<string, string>;\n\n if (shouldUseDynamicHelpers) {\n // Use dynamic helpers for useIntlayer when dynamic mode is enabled\n helperMap = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>;\n } else {\n // Use static helpers by default\n helperMap = STATIC_IMPORT_FUNCTION as Record<string, string>;\n }\n\n const newIdentifier = helperMap[importedName];\n\n // Only rewrite when we actually have a mapping for the imported\n // specifier (ignore unrelated named imports).\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\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 arg = path.node.arguments[0];\n let key: string | undefined;\n if (arg && t.isStringLiteral(arg)) {\n key = arg.value;\n } else if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n if (!key) return;\n\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const useDynamicHelpers = Boolean(state._useDynamicHelpers);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'\n let perCallMode: 'static' | 'dynamic' | 'fetch' = 'static';\n\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (isUseIntlayer && useDynamicHelpers) {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic') {\n perCallMode = 'dynamic';\n } else if (importMode === 'fetch') {\n perCallMode = 'fetch';\n }\n } else if (isUseIntlayer && !useDynamicHelpers) {\n // If dynamic helpers are NOT active (global mode is static),\n // we STILL might want to force dynamic/live for this specific call\n\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 (live mode 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/live 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":["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\ntype CallerName = (typeof CALLER_LIST)[number];\ntype ImportMode = 'static' | 'dynamic' | 'fetch';\n\n/**\n * Packages whose SSR dynamic helper should render synchronously with a static\n * dictionary. Solid streaming SSR can hydrate static output reliably, while\n * its dynamic resource path either suspends during hydration or serializes the\n * full dictionary into HTML.\n */\nconst PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK = new Set<string>(['solid-intlayer']);\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 dynamic helpers are active for this file */\n _useDynamicHelpers?: 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\nconst shouldUseStaticSsrDynamicFallback = (\n callerPackage: string | undefined,\n importMode: ImportMode | undefined,\n opts: OptimizePluginOptions\n): boolean =>\n opts.isServer === true &&\n importMode === 'dynamic' &&\n callerPackage !== undefined &&\n PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK.has(callerPackage);\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 this._useDynamicHelpers = 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 programPath.traverse({\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\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 const importMode = state.opts.importMode;\n // Determine whether this import should use the dynamic helpers.\n const packageHasDynamicCall = packagesWithDynamicCall.has(src);\n const packageHasFetchCall = packagesWithFetchCall.has(src);\n // A package import can be rewritten to only one helper. Fetch\n // overrides therefore keep the dynamic helper for every\n // useIntlayer call from that package in this file.\n const shouldUseStaticFallback =\n !packageHasFetchCall &&\n shouldUseStaticSsrDynamicFallback(\n src,\n importMode === 'dynamic' || packageHasDynamicCall\n ? 'dynamic'\n : importMode,\n state.opts\n );\n const shouldUseDynamicHelpers =\n isDynamicPackage(src) &&\n (importMode === 'fetch' ||\n packageHasFetchCall ||\n ((importMode === 'dynamic' || packageHasDynamicCall) &&\n !shouldUseStaticFallback));\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n let helperMap: Record<string, string>;\n\n if (shouldUseDynamicHelpers) {\n // Use dynamic helpers for useIntlayer when dynamic mode is enabled\n helperMap = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>;\n } else {\n // Use static helpers by default\n helperMap = STATIC_IMPORT_FUNCTION as Record<string, string>;\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\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 effectiveImportMode = dictionaryOverrideMode ?? importMode;\n const packageHasFetchCall =\n callerPackage !== undefined &&\n packagesWithFetchCall.has(callerPackage);\n const usesStaticSsrDynamicFallback =\n isUseIntlayer &&\n !packageHasFetchCall &&\n shouldUseStaticSsrDynamicFallback(\n callerPackage,\n effectiveImportMode,\n state.opts\n );\n const useDynamicHelpers =\n Boolean(state._useDynamicHelpers) &&\n !usesStaticSsrDynamicFallback;\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'\n let perCallMode: ImportMode = 'static';\n\n if (isUseIntlayer && useDynamicHelpers) {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic') {\n perCallMode = 'dynamic';\n } else if (importMode === 'fetch') {\n perCallMode = 'fetch';\n }\n } else if (\n isUseIntlayer &&\n !useDynamicHelpers &&\n !usesStaticSsrDynamicFallback\n ) {\n // If dynamic helpers are NOT active (global mode is static),\n // we STILL might want to force dynamic/fetch for this specific call\n\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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"}
@@ -23,10 +23,11 @@ const loadDictionaries = (config) => {
23
23
  * needed for dictionary optimization and import rewriting.
24
24
  */
25
25
  const getOptimizePluginOptions = (params) => {
26
- const { configOptions, dictionaries: providedDictionaries, overrides } = params ?? {};
26
+ const { configOptions, dictionaries: providedDictionaries, isServer, overrides } = params ?? {};
27
27
  const config = (0, _intlayer_config_node.getConfiguration)(configOptions);
28
28
  const { mainDir, dictionariesDir, unmergedDictionariesDir, dynamicDictionariesDir, fetchDictionariesDir } = config.system;
29
- const { importMode, optimize } = config.build;
29
+ const importMode = config.build.importMode ?? config.dictionary?.importMode;
30
+ const optimize = config.build.optimize;
30
31
  const dictionariesEntryPath = (0, node_path.join)(mainDir, "dictionaries.mjs");
31
32
  const unmergedDictionariesEntryPath = (0, node_path.join)(mainDir, "unmerged_dictionaries.mjs");
32
33
  const dynamicDictionariesEntryPath = (0, node_path.join)(mainDir, "dynamic_dictionaries.mjs");
@@ -55,6 +56,7 @@ const getOptimizePluginOptions = (params) => {
55
56
  importMode,
56
57
  dictionaryModeMap,
57
58
  filesList,
59
+ isServer,
58
60
  ...overrides
59
61
  };
60
62
  };
@@ -1 +1 @@
1
- {"version":3,"file":"getOptimizePluginOptions.cjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { buildComponentFilesList } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config);\n\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const { importMode, optimize } = config.build;\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(config);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n ...overrides,\n };\n};\n"],"mappings":";;;;;;;;;;AA4BA,MAAM,oBAAoB,WAAyC;AACjE,KAAI;EAGF,MAAM,EAAE,oBAAoB,QAAQ,+BAA+B;EACnE,MAAM,qBAAqB,gBAAgB,OAAO;AAElD,SAAO,OAAO,OAAO,mBAAmB;SAClC;AAEN,SAAO,EAAE;;;;;;;;AASb,MAAa,4BACX,WAC0B;CAC1B,MAAM,EACJ,eACA,cAAc,sBACd,cACE,UAAU,EAAE;CAEhB,MAAM,qDAA0B,cAAc;CAC9C,MAAM,EACJ,SACA,iBACA,yBACA,wBACA,yBACE,OAAO;CACX,MAAM,EAAE,YAAY,aAAa,OAAO;CAExC,MAAM,4CAA6B,SAAS,mBAAmB;CAC/D,MAAM,oDACJ,SACA,4BACD;CACD,MAAM,mDACJ,SACA,2BACD;CACD,MAAM,iDAAkC,SAAS,yBAAyB;CAI1E,MAAM,YAAY;EAChB,yDAH+C,OAG5B;EACnB;EACA;EACD;CAGD,MAAM,eAAe,wBAAwB,iBAAiB,OAAO;CAErE,MAAM,oBAGF,EAAE;AAEN,cAAa,SAAS,eAAe;AACnC,oBAAkB,WAAW,OAAO,WAAW,cAAc;GAC7D;AAEF,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,wBAAwB;EACxB;EACA;EACA;EACA,GAAG;EACJ"}
1
+ {"version":3,"file":"getOptimizePluginOptions.cjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { buildComponentFilesList } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Whether the current transform is for an SSR bundle. When using Babel\n * directly (e.g. in `babel.config.js`), forward the bundler's server flag\n * here so SSR-specific transforms (such as the Solid static fallback) apply.\n */\n isServer?: boolean;\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config);\n\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n isServer,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const importMode = config.build.importMode ?? config.dictionary?.importMode;\n const optimize = config.build.optimize;\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(config);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n isServer,\n ...overrides,\n };\n};\n"],"mappings":";;;;;;;;;;AAkCA,MAAM,oBAAoB,WAAyC;AACjE,KAAI;EAGF,MAAM,EAAE,oBAAoB,QAAQ,+BAA+B;EACnE,MAAM,qBAAqB,gBAAgB,OAAO;AAElD,SAAO,OAAO,OAAO,mBAAmB;SAClC;AAEN,SAAO,EAAE;;;;;;;;AASb,MAAa,4BACX,WAC0B;CAC1B,MAAM,EACJ,eACA,cAAc,sBACd,UACA,cACE,UAAU,EAAE;CAEhB,MAAM,qDAA0B,cAAc;CAC9C,MAAM,EACJ,SACA,iBACA,yBACA,wBACA,yBACE,OAAO;CACX,MAAM,aAAa,OAAO,MAAM,cAAc,OAAO,YAAY;CACjE,MAAM,WAAW,OAAO,MAAM;CAE9B,MAAM,4CAA6B,SAAS,mBAAmB;CAC/D,MAAM,oDACJ,SACA,4BACD;CACD,MAAM,mDACJ,SACA,2BACD;CACD,MAAM,iDAAkC,SAAS,yBAAyB;CAI1E,MAAM,YAAY;EAChB,yDAH+C,OAG5B;EACnB;EACA;EACD;CAGD,MAAM,eAAe,wBAAwB,iBAAiB,OAAO;CAErE,MAAM,oBAGF,EAAE;AAEN,cAAa,SAAS,eAAe;AACnC,oBAAkB,WAAW,OAAO,WAAW,cAAc;GAC7D;AAEF,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,wBAAwB;EACxB;EACA;EACA;EACA;EACA,GAAG;EACJ"}
@@ -3,6 +3,7 @@ import { extractContentSync } from "./extractContent/extractContent.mjs";
3
3
  import { relative } from "node:path";
4
4
  import * as ANSIColors from "@intlayer/config/colors";
5
5
  import { colorize, colorizePath, getAppLogger } from "@intlayer/config/logger";
6
+ import { normalizePath } from "@intlayer/config/utils";
6
7
  import { parse } from "@babel/parser";
7
8
 
8
9
  //#region src/babel-plugin-intlayer-extract.ts
@@ -31,7 +32,7 @@ const intlayerExtractBabelPlugin = (_babel) => {
31
32
  if (opts.enabled === false) return;
32
33
  const filename = state.file.opts.filename;
33
34
  if (!filename) return;
34
- if (opts.filesList && !opts.filesList.includes(filename)) return;
35
+ if (opts.filesList && !opts.filesList.map(normalizePath).includes(normalizePath(filename))) return;
35
36
  const fileCode = state.file.code ?? "";
36
37
  if (!fileCode) return;
37
38
  const appLogger = getAppLogger(opts.configuration);
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-extract.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { extractContentSync } from './extractContent/extractContent';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: Locale;\n};\n\nexport type ExtractPluginOptions = {\n packageName?: PackageName;\n filesList: string[];\n enabled: boolean;\n\n shouldExtract?: (text: string) => boolean;\n configuration: IntlayerConfig;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n /**\n * Defines the output files path.\n */\n output?: FilePathPattern;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (_babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n // Merge plugin options with the unified compiler config\n const isEnabled = opts.enabled;\n\n if (isEnabled === false) return;\n\n const filename = state.file.opts.filename;\n\n if (!filename) return;\n\n if (opts.filesList && !opts.filesList.includes(filename)) return;\n\n const fileCode: string = state.file.code ?? '';\n if (!fileCode) return;\n\n const appLogger = getAppLogger(opts.configuration);\n const packageName = opts.packageName ?? detectPackageName(filename);\n\n const { saveComponents } = opts.configuration.compiler;\n\n const result = extractContentSync(filename, packageName, {\n configuration: opts.configuration,\n code: fileCode,\n onExtract: (extractResult: {\n key: string;\n content: Record<string, string>;\n }) => {\n if (opts.onExtract) {\n opts.onExtract({\n dictionaryKey: extractResult.key,\n filePath: filename,\n content: extractResult.content,\n locale: opts.configuration.internationalization.defaultLocale,\n });\n }\n },\n declarationOnly: !saveComponents,\n });\n\n if (!result) return;\n\n const { transformedCode: modifiedCode } = result;\n\n if (!modifiedCode) return;\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(opts.configuration.system.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n appLogger(\n [\n `Failed to parse transformed code for ${colorizePath(relative(opts.configuration.system.baseDir, filename))}:`,\n error,\n ],\n { level: 'error' }\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,MAAa,8BAA8B,WAEnB;AACtB,QAAO;EACL,MAAM;EAEN,SAAS,EACP,SAAS,EACP,MAAM,aAAa,OAAO;GACxB,MAAM,OAAO,MAAM;AAKnB,OAFkB,KAAK,YAEL,MAAO;GAEzB,MAAM,WAAW,MAAM,KAAK,KAAK;AAEjC,OAAI,CAAC,SAAU;AAEf,OAAI,KAAK,aAAa,CAAC,KAAK,UAAU,SAAS,SAAS,CAAE;GAE1D,MAAM,WAAmB,MAAM,KAAK,QAAQ;AAC5C,OAAI,CAAC,SAAU;GAEf,MAAM,YAAY,aAAa,KAAK,cAAc;GAClD,MAAM,cAAc,KAAK,eAAe,kBAAkB,SAAS;GAEnE,MAAM,EAAE,mBAAmB,KAAK,cAAc;GAE9C,MAAM,SAAS,mBAAmB,UAAU,aAAa;IACvD,eAAe,KAAK;IACpB,MAAM;IACN,YAAY,kBAGN;AACJ,SAAI,KAAK,UACP,MAAK,UAAU;MACb,eAAe,cAAc;MAC7B,UAAU;MACV,SAAS,cAAc;MACvB,QAAQ,KAAK,cAAc,qBAAqB;MACjD,CAAC;;IAGN,iBAAiB,CAAC;IACnB,CAAC;AAEF,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,iBAAiB,iBAAiB;AAE1C,OAAI,CAAC,aAAc;AAKnB,OAAI;IACF,MAAM,SAAS,MAAM,cAAc;KACjC,YAAY;KACZ,SAAS,CAAC,OAAO,aAAa;KAC/B,CAAC;AAEF,gBAAY,KAAK,OAAO,OAAO,QAAQ;AACvC,gBAAY,KAAK,aAAa,OAAO,QAAQ;AAE7C,cACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,0BAA0B,aAAa,SAAS,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,IAC5I,EAAE,OAAO,SAAS,CACnB;YACM,OAAO;AACd,cACE,CACE,wCAAwC,aAAa,SAAS,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,CAAC,IAC5G,MACD,EACD,EAAE,OAAO,SAAS,CACnB;;KAGN,EACF;EACF"}
1
+ {"version":3,"file":"babel-plugin-intlayer-extract.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport { normalizePath } from '@intlayer/config/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { extractContentSync } from './extractContent/extractContent';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: Locale;\n};\n\nexport type ExtractPluginOptions = {\n packageName?: PackageName;\n filesList: string[];\n enabled: boolean;\n\n shouldExtract?: (text: string) => boolean;\n configuration: IntlayerConfig;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n /**\n * Defines the output files path.\n */\n output?: FilePathPattern;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (_babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n // Merge plugin options with the unified compiler config\n const isEnabled = opts.enabled;\n\n if (isEnabled === false) return;\n\n const filename = state.file.opts.filename;\n\n if (!filename) return;\n\n // Compare as POSIX paths (babel filenames use OS separators on Windows).\n if (\n opts.filesList &&\n !opts.filesList.map(normalizePath).includes(normalizePath(filename))\n ) {\n return;\n }\n\n const fileCode: string = state.file.code ?? '';\n if (!fileCode) return;\n\n const appLogger = getAppLogger(opts.configuration);\n const packageName = opts.packageName ?? detectPackageName(filename);\n\n const { saveComponents } = opts.configuration.compiler;\n\n const result = extractContentSync(filename, packageName, {\n configuration: opts.configuration,\n code: fileCode,\n onExtract: (extractResult: {\n key: string;\n content: Record<string, string>;\n }) => {\n if (opts.onExtract) {\n opts.onExtract({\n dictionaryKey: extractResult.key,\n filePath: filename,\n content: extractResult.content,\n locale: opts.configuration.internationalization.defaultLocale,\n });\n }\n },\n declarationOnly: !saveComponents,\n });\n\n if (!result) return;\n\n const { transformedCode: modifiedCode } = result;\n\n if (!modifiedCode) return;\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(opts.configuration.system.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n appLogger(\n [\n `Failed to parse transformed code for ${colorizePath(relative(opts.configuration.system.baseDir, filename))}:`,\n error,\n ],\n { level: 'error' }\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,MAAa,8BAA8B,WAEnB;AACtB,QAAO;EACL,MAAM;EAEN,SAAS,EACP,SAAS,EACP,MAAM,aAAa,OAAO;GACxB,MAAM,OAAO,MAAM;AAKnB,OAFkB,KAAK,YAEL,MAAO;GAEzB,MAAM,WAAW,MAAM,KAAK,KAAK;AAEjC,OAAI,CAAC,SAAU;AAGf,OACE,KAAK,aACL,CAAC,KAAK,UAAU,IAAI,cAAc,CAAC,SAAS,cAAc,SAAS,CAAC,CAEpE;GAGF,MAAM,WAAmB,MAAM,KAAK,QAAQ;AAC5C,OAAI,CAAC,SAAU;GAEf,MAAM,YAAY,aAAa,KAAK,cAAc;GAClD,MAAM,cAAc,KAAK,eAAe,kBAAkB,SAAS;GAEnE,MAAM,EAAE,mBAAmB,KAAK,cAAc;GAE9C,MAAM,SAAS,mBAAmB,UAAU,aAAa;IACvD,eAAe,KAAK;IACpB,MAAM;IACN,YAAY,kBAGN;AACJ,SAAI,KAAK,UACP,MAAK,UAAU;MACb,eAAe,cAAc;MAC7B,UAAU;MACV,SAAS,cAAc;MACvB,QAAQ,KAAK,cAAc,qBAAqB;MACjD,CAAC;;IAGN,iBAAiB,CAAC;IACnB,CAAC;AAEF,OAAI,CAAC,OAAQ;GAEb,MAAM,EAAE,iBAAiB,iBAAiB;AAE1C,OAAI,CAAC,aAAc;AAKnB,OAAI;IACF,MAAM,SAAS,MAAM,cAAc;KACjC,YAAY;KACZ,SAAS,CAAC,OAAO,aAAa;KAC/B,CAAC;AAEF,gBAAY,KAAK,OAAO,OAAO,QAAQ;AACvC,gBAAY,KAAK,aAAa,OAAO,QAAQ;AAE7C,cACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,0BAA0B,aAAa,SAAS,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,IAC5I,EAAE,OAAO,SAAS,CACnB;YACM,OAAO;AACd,cACE,CACE,wCAAwC,aAAa,SAAS,KAAK,cAAc,OAAO,SAAS,SAAS,CAAC,CAAC,IAC5G,MACD,EACD,EAAE,OAAO,SAAS,CACnB;;KAGN,EACF;EACF"}
@@ -45,6 +45,13 @@ const STATIC_IMPORT_FUNCTION = {
45
45
  };
46
46
  const DYNAMIC_IMPORT_FUNCTION = { useIntlayer: "useDictionaryDynamic" };
47
47
  /**
48
+ * Packages whose SSR dynamic helper should render synchronously with a static
49
+ * dictionary. Solid streaming SSR can hydrate static output reliably, while
50
+ * its dynamic resource path either suspends during hydration or serializes the
51
+ * full dictionary into HTML.
52
+ */
53
+ const PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK = new Set(["solid-intlayer"]);
54
+ /**
48
55
  * Replicates the xxHash64 → Base-62 algorithm used by the SWC version
49
56
  * and prefixes an underscore so the generated identifiers never collide
50
57
  * with user-defined ones.
@@ -62,6 +69,13 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
62
69
  if (!rel.startsWith("./") && !rel.startsWith("../")) rel = `./${rel}`;
63
70
  return rel;
64
71
  };
72
+ const getKeyFromArgument = (arg, t) => {
73
+ if (arg && t.isStringLiteral(arg)) return arg.value;
74
+ if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) return arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
75
+ };
76
+ const isCallerName = (name) => CALLER_LIST.includes(name);
77
+ const isDynamicPackage = (packageName) => PACKAGE_LIST_DYNAMIC.includes(packageName);
78
+ const shouldUseStaticSsrDynamicFallback = (callerPackage, importMode, opts) => opts.isServer === true && importMode === "dynamic" && callerPackage !== void 0 && PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK.has(callerPackage);
65
79
  /**
66
80
  * Babel plugin that transforms Intlayer function calls and auto-imports dictionaries.
67
81
  *
@@ -117,11 +131,11 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
117
131
  * const content2 = getIntlayer(_dicHash);
118
132
  * ```
119
133
  *
120
- * ### Live Mode (`importMode = "live"`)
134
+ * ### Fetch Mode (`importMode = "fetch"`)
121
135
  *
122
- * Uses live-based dictionary loading for remote dictionaries:
136
+ * Uses fetch-based dictionary loading for remote dictionaries:
123
137
  *
124
- * **Output if `dictionaryModeMap` includes the key with "live" value:**
138
+ * **Output if `dictionaryModeMap` includes the key with "fetch" value:**
125
139
  * ```ts
126
140
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
127
141
  * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';
@@ -132,7 +146,7 @@ const computeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, fetchD
132
146
  * const content2 = getIntlayer(_dicHash);
133
147
  * ```
134
148
  *
135
- * > If `dictionaryModeMap` does not include the key with "live" value, the plugin will fallback to the dynamic impor
149
+ * > If `dictionaryModeMap` does not include the key with "fetch" value, the plugin will fallback to the dynamic import mode.
136
150
  *
137
151
  * ```ts
138
152
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
@@ -152,6 +166,7 @@ const intlayerOptimizeBabelPlugin = (babel) => {
152
166
  this._newStaticImports = /* @__PURE__ */ new Map();
153
167
  this._newDynamicImports = /* @__PURE__ */ new Map();
154
168
  this._callerMap = /* @__PURE__ */ new Map();
169
+ this._callerPackageMap = /* @__PURE__ */ new Map();
155
170
  this._isIncluded = true;
156
171
  this._hasValidImport = false;
157
172
  this._isDictEntry = false;
@@ -160,9 +175,9 @@ const intlayerOptimizeBabelPlugin = (babel) => {
160
175
  this._isIncluded = false;
161
176
  return;
162
177
  }
163
- const filename = this.file.opts.filename;
178
+ const filename = this.file.opts.filename ? normalizePath(this.file.opts.filename) : void 0;
164
179
  if (this.opts.filesList && filename) {
165
- if (!this.opts.filesList.includes(filename)) {
180
+ if (!this.opts.filesList.map(normalizePath).includes(filename)) {
166
181
  this._isIncluded = false;
167
182
  return;
168
183
  }
@@ -170,8 +185,9 @@ const intlayerOptimizeBabelPlugin = (babel) => {
170
185
  },
171
186
  visitor: { Program: {
172
187
  enter(programPath, state) {
173
- const filename = state.file.opts.filename;
174
- if (state.opts.replaceDictionaryEntry && filename === state.opts.dictionariesEntryPath) {
188
+ const filename = state.file.opts.filename ? normalizePath(state.file.opts.filename) : void 0;
189
+ const dictionariesEntryPath = state.opts.dictionariesEntryPath ? normalizePath(state.opts.dictionariesEntryPath) : void 0;
190
+ if (state.opts.replaceDictionaryEntry && filename === dictionariesEntryPath) {
175
191
  state._isDictEntry = true;
176
192
  programPath.traverse({
177
193
  ImportDeclaration(path) {
@@ -194,30 +210,46 @@ const intlayerOptimizeBabelPlugin = (babel) => {
194
210
  exit(programPath, state) {
195
211
  if (state._isDictEntry) return;
196
212
  if (!state._isIncluded) return;
197
- let fileHasDynamicCall = false;
213
+ programPath.traverse({ ImportDeclaration(path) {
214
+ const src = path.node.source.value;
215
+ if (!PACKAGE_LIST.includes(src)) return;
216
+ state._hasValidImport = true;
217
+ for (const spec of path.node.specifiers) {
218
+ if (!t.isImportSpecifier(spec)) continue;
219
+ const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
220
+ if (isCallerName(importedName)) {
221
+ state._callerMap?.set(spec.local.name, importedName);
222
+ state._callerPackageMap?.set(spec.local.name, src);
223
+ }
224
+ }
225
+ } });
226
+ const packagesWithDynamicCall = /* @__PURE__ */ new Set();
227
+ const packagesWithFetchCall = /* @__PURE__ */ new Set();
198
228
  programPath.traverse({ CallExpression(path) {
199
229
  const callee = path.node.callee;
200
230
  if (!t.isIdentifier(callee)) return;
201
231
  if (state._callerMap?.get(callee.name) !== "useIntlayer") return;
202
- const arg = path.node.arguments[0];
203
- let key;
204
- if (arg && t.isStringLiteral(arg)) key = arg.value;
205
- else if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
232
+ const callerPackage = state._callerPackageMap?.get(callee.name);
233
+ if (!callerPackage) return;
234
+ const key = getKeyFromArgument(path.node.arguments[0], t);
206
235
  if (!key) return;
207
236
  const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];
208
- if (dictionaryOverrideMode === "dynamic" || dictionaryOverrideMode === "fetch") fileHasDynamicCall = true;
237
+ if (dictionaryOverrideMode === "dynamic") packagesWithDynamicCall.add(callerPackage);
238
+ else if (dictionaryOverrideMode === "fetch") packagesWithFetchCall.add(callerPackage);
209
239
  } });
210
240
  programPath.traverse({
211
241
  ImportDeclaration(path) {
212
242
  const src = path.node.source.value;
213
243
  if (!PACKAGE_LIST.includes(src)) return;
214
- state._hasValidImport = true;
215
244
  for (const spec of path.node.specifiers) {
216
245
  if (!t.isImportSpecifier(spec)) continue;
217
246
  const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
218
- if (CALLER_LIST.includes(importedName)) state._callerMap?.set(spec.local.name, importedName);
247
+ if (!isCallerName(importedName)) continue;
219
248
  const importMode = state.opts.importMode;
220
- const shouldUseDynamicHelpers = (importMode === "dynamic" || importMode === "fetch" || fileHasDynamicCall) && PACKAGE_LIST_DYNAMIC.includes(src);
249
+ const packageHasDynamicCall = packagesWithDynamicCall.has(src);
250
+ const packageHasFetchCall = packagesWithFetchCall.has(src);
251
+ const shouldUseStaticFallback = !packageHasFetchCall && shouldUseStaticSsrDynamicFallback(src, importMode === "dynamic" || packageHasDynamicCall ? "dynamic" : importMode, state.opts);
252
+ const shouldUseDynamicHelpers = isDynamicPackage(src) && (importMode === "fetch" || packageHasFetchCall || (importMode === "dynamic" || packageHasDynamicCall) && !shouldUseStaticFallback);
221
253
  if (shouldUseDynamicHelpers) state._useDynamicHelpers = true;
222
254
  let helperMap;
223
255
  if (shouldUseDynamicHelpers) helperMap = {
@@ -235,21 +267,22 @@ const intlayerOptimizeBabelPlugin = (babel) => {
235
267
  const originalImportedName = state._callerMap?.get(callee.name);
236
268
  if (!originalImportedName) return;
237
269
  state._hasValidImport = true;
238
- const arg = path.node.arguments[0];
239
- let key;
240
- if (arg && t.isStringLiteral(arg)) key = arg.value;
241
- else if (arg && t.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1) key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;
270
+ const key = getKeyFromArgument(path.node.arguments[0], t);
242
271
  if (!key) return;
272
+ const callerPackage = state._callerPackageMap?.get(callee.name);
243
273
  const importMode = state.opts.importMode;
244
274
  const isUseIntlayer = originalImportedName === "useIntlayer";
245
- const useDynamicHelpers = Boolean(state._useDynamicHelpers);
246
- let perCallMode = "static";
247
275
  const dictionaryOverrideMode = state.opts.dictionaryModeMap?.[key];
276
+ const effectiveImportMode = dictionaryOverrideMode ?? importMode;
277
+ const packageHasFetchCall = callerPackage !== void 0 && packagesWithFetchCall.has(callerPackage);
278
+ const usesStaticSsrDynamicFallback = isUseIntlayer && !packageHasFetchCall && shouldUseStaticSsrDynamicFallback(callerPackage, effectiveImportMode, state.opts);
279
+ const useDynamicHelpers = Boolean(state._useDynamicHelpers) && !usesStaticSsrDynamicFallback;
280
+ let perCallMode = "static";
248
281
  if (isUseIntlayer && useDynamicHelpers) {
249
282
  if (dictionaryOverrideMode) perCallMode = dictionaryOverrideMode;
250
283
  else if (importMode === "dynamic") perCallMode = "dynamic";
251
284
  else if (importMode === "fetch") perCallMode = "fetch";
252
- } else if (isUseIntlayer && !useDynamicHelpers) {
285
+ } else if (isUseIntlayer && !useDynamicHelpers && !usesStaticSsrDynamicFallback) {
253
286
  if (dictionaryOverrideMode === "dynamic" || dictionaryOverrideMode === "fetch") perCallMode = dictionaryOverrideMode;
254
287
  }
255
288
  let ident;
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-optimize.mjs","names":[],"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 * 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\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 /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether dynamic helpers are active for this file */\n _useDynamicHelpers?: 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\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 * ### Live Mode (`importMode = \"live\"`)\n *\n * Uses live-based dictionary loading for remote dictionaries:\n *\n * **Output if `dictionaryModeMap` includes the key with \"live\" 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 \"live\" value, the plugin will fallback to the dynamic impor\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._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n this._useDynamicHelpers = 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 if (this.opts.filesList && filename) {\n const isIncluded = this.opts.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\n // Check if this is the correct file to transform\n\n if (\n state.opts.replaceDictionaryEntry &&\n filename === state.opts.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\n // Pre-pass to determine if we should use dynamic helpers\n let fileHasDynamicCall = false;\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 arg = path.node.arguments[0];\n let key: string | undefined;\n if (arg && t.isStringLiteral(arg)) {\n key = arg.value;\n } else if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n if (!key) return;\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (\n dictionaryOverrideMode === 'dynamic' ||\n dictionaryOverrideMode === 'fetch'\n ) {\n fileHasDynamicCall = true;\n }\n },\n });\n\n programPath.traverse({\n /* Inspect every intlayer import */\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file\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 (CALLER_LIST.includes(importedName as any)) {\n state._callerMap?.set(\n spec.local.name,\n importedName as (typeof CALLER_LIST)[number]\n );\n }\n\n const importMode = state.opts.importMode;\n // Determine whether this import should use the dynamic helpers.\n const shouldUseDynamicHelpers =\n (importMode === 'dynamic' ||\n importMode === 'fetch' ||\n fileHasDynamicCall) &&\n PACKAGE_LIST_DYNAMIC.includes(src as any);\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n let helperMap: Record<string, string>;\n\n if (shouldUseDynamicHelpers) {\n // Use dynamic helpers for useIntlayer when dynamic mode is enabled\n helperMap = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>;\n } else {\n // Use static helpers by default\n helperMap = STATIC_IMPORT_FUNCTION as Record<string, string>;\n }\n\n const newIdentifier = helperMap[importedName];\n\n // Only rewrite when we actually have a mapping for the imported\n // specifier (ignore unrelated named imports).\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\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 arg = path.node.arguments[0];\n let key: string | undefined;\n if (arg && t.isStringLiteral(arg)) {\n key = arg.value;\n } else if (\n arg &&\n t.isTemplateLiteral(arg) &&\n arg.expressions.length === 0 &&\n arg.quasis.length === 1\n ) {\n key = arg.quasis[0]?.value.cooked ?? arg.quasis[0]?.value.raw;\n }\n if (!key) return;\n\n const importMode = state.opts.importMode;\n const isUseIntlayer = originalImportedName === 'useIntlayer';\n const useDynamicHelpers = Boolean(state._useDynamicHelpers);\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'\n let perCallMode: 'static' | 'dynamic' | 'fetch' = 'static';\n\n const dictionaryOverrideMode =\n state.opts.dictionaryModeMap?.[key];\n\n if (isUseIntlayer && useDynamicHelpers) {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic') {\n perCallMode = 'dynamic';\n } else if (importMode === 'fetch') {\n perCallMode = 'fetch';\n }\n } else if (isUseIntlayer && !useDynamicHelpers) {\n // If dynamic helpers are NOT active (global mode is static),\n // we STILL might want to force dynamic/live for this specific call\n\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 (live mode 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/live 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.mjs","names":[],"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\ntype CallerName = (typeof CALLER_LIST)[number];\ntype ImportMode = 'static' | 'dynamic' | 'fetch';\n\n/**\n * Packages whose SSR dynamic helper should render synchronously with a static\n * dictionary. Solid streaming SSR can hydrate static output reliably, while\n * its dynamic resource path either suspends during hydration or serializes the\n * full dictionary into HTML.\n */\nconst PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK = new Set<string>(['solid-intlayer']);\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 dynamic helpers are active for this file */\n _useDynamicHelpers?: 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\nconst shouldUseStaticSsrDynamicFallback = (\n callerPackage: string | undefined,\n importMode: ImportMode | undefined,\n opts: OptimizePluginOptions\n): boolean =>\n opts.isServer === true &&\n importMode === 'dynamic' &&\n callerPackage !== undefined &&\n PACKAGE_SSR_DYNAMIC_STATIC_FALLBACK.has(callerPackage);\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 this._useDynamicHelpers = 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 programPath.traverse({\n ImportDeclaration(path) {\n const src = path.node.source.value;\n\n if (!PACKAGE_LIST.includes(src)) return;\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 const importMode = state.opts.importMode;\n // Determine whether this import should use the dynamic helpers.\n const packageHasDynamicCall = packagesWithDynamicCall.has(src);\n const packageHasFetchCall = packagesWithFetchCall.has(src);\n // A package import can be rewritten to only one helper. Fetch\n // overrides therefore keep the dynamic helper for every\n // useIntlayer call from that package in this file.\n const shouldUseStaticFallback =\n !packageHasFetchCall &&\n shouldUseStaticSsrDynamicFallback(\n src,\n importMode === 'dynamic' || packageHasDynamicCall\n ? 'dynamic'\n : importMode,\n state.opts\n );\n const shouldUseDynamicHelpers =\n isDynamicPackage(src) &&\n (importMode === 'fetch' ||\n packageHasFetchCall ||\n ((importMode === 'dynamic' || packageHasDynamicCall) &&\n !shouldUseStaticFallback));\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n let helperMap: Record<string, string>;\n\n if (shouldUseDynamicHelpers) {\n // Use dynamic helpers for useIntlayer when dynamic mode is enabled\n helperMap = {\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>;\n } else {\n // Use static helpers by default\n helperMap = STATIC_IMPORT_FUNCTION as Record<string, string>;\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\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 effectiveImportMode = dictionaryOverrideMode ?? importMode;\n const packageHasFetchCall =\n callerPackage !== undefined &&\n packagesWithFetchCall.has(callerPackage);\n const usesStaticSsrDynamicFallback =\n isUseIntlayer &&\n !packageHasFetchCall &&\n shouldUseStaticSsrDynamicFallback(\n callerPackage,\n effectiveImportMode,\n state.opts\n );\n const useDynamicHelpers =\n Boolean(state._useDynamicHelpers) &&\n !usesStaticSsrDynamicFallback;\n\n // Decide per-call mode: 'static' | 'dynamic' | 'fetch'\n let perCallMode: ImportMode = 'static';\n\n if (isUseIntlayer && useDynamicHelpers) {\n if (dictionaryOverrideMode) {\n perCallMode = dictionaryOverrideMode;\n } else if (importMode === 'dynamic') {\n perCallMode = 'dynamic';\n } else if (importMode === 'fetch') {\n perCallMode = 'fetch';\n }\n } else if (\n isUseIntlayer &&\n !useDynamicHelpers &&\n !usesStaticSsrDynamicFallback\n ) {\n // If dynamic helpers are NOT active (global mode is static),\n // we STILL might want to force dynamic/fetch for this specific call\n\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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"}
@@ -22,10 +22,11 @@ const loadDictionaries = (config) => {
22
22
  * needed for dictionary optimization and import rewriting.
23
23
  */
24
24
  const getOptimizePluginOptions = (params) => {
25
- const { configOptions, dictionaries: providedDictionaries, overrides } = params ?? {};
25
+ const { configOptions, dictionaries: providedDictionaries, isServer, overrides } = params ?? {};
26
26
  const config = getConfiguration(configOptions);
27
27
  const { mainDir, dictionariesDir, unmergedDictionariesDir, dynamicDictionariesDir, fetchDictionariesDir } = config.system;
28
- const { importMode, optimize } = config.build;
28
+ const importMode = config.build.importMode ?? config.dictionary?.importMode;
29
+ const optimize = config.build.optimize;
29
30
  const dictionariesEntryPath = join(mainDir, "dictionaries.mjs");
30
31
  const unmergedDictionariesEntryPath = join(mainDir, "unmerged_dictionaries.mjs");
31
32
  const dynamicDictionariesEntryPath = join(mainDir, "dynamic_dictionaries.mjs");
@@ -54,6 +55,7 @@ const getOptimizePluginOptions = (params) => {
54
55
  importMode,
55
56
  dictionaryModeMap,
56
57
  filesList,
58
+ isServer,
57
59
  ...overrides
58
60
  };
59
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"getOptimizePluginOptions.mjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { buildComponentFilesList } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config);\n\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const { importMode, optimize } = config.build;\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(config);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n ...overrides,\n };\n};\n"],"mappings":";;;;;;;;;AA4BA,MAAM,oBAAoB,WAAyC;AACjE,KAAI;EAGF,MAAM,EAAE,8BAA4B,+BAA+B;EACnE,MAAM,qBAAqB,gBAAgB,OAAO;AAElD,SAAO,OAAO,OAAO,mBAAmB;SAClC;AAEN,SAAO,EAAE;;;;;;;;AASb,MAAa,4BACX,WAC0B;CAC1B,MAAM,EACJ,eACA,cAAc,sBACd,cACE,UAAU,EAAE;CAEhB,MAAM,SAAS,iBAAiB,cAAc;CAC9C,MAAM,EACJ,SACA,iBACA,yBACA,wBACA,yBACE,OAAO;CACX,MAAM,EAAE,YAAY,aAAa,OAAO;CAExC,MAAM,wBAAwB,KAAK,SAAS,mBAAmB;CAC/D,MAAM,gCAAgC,KACpC,SACA,4BACD;CACD,MAAM,+BAA+B,KACnC,SACA,2BACD;CACD,MAAM,6BAA6B,KAAK,SAAS,yBAAyB;CAI1E,MAAM,YAAY;EAChB,GAHuB,wBAAwB,OAG5B;EACnB;EACA;EACD;CAGD,MAAM,eAAe,wBAAwB,iBAAiB,OAAO;CAErE,MAAM,oBAGF,EAAE;AAEN,cAAa,SAAS,eAAe;AACnC,oBAAkB,WAAW,OAAO,WAAW,cAAc;GAC7D;AAEF,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,wBAAwB;EACxB;EACA;EACA;EACA,GAAG;EACJ"}
1
+ {"version":3,"file":"getOptimizePluginOptions.mjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { buildComponentFilesList } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Whether the current transform is for an SSR bundle. When using Babel\n * directly (e.g. in `babel.config.js`), forward the bundler's server flag\n * here so SSR-specific transforms (such as the Solid static fallback) apply.\n */\n isServer?: boolean;\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config);\n\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n isServer,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const importMode = config.build.importMode ?? config.dictionary?.importMode;\n const optimize = config.build.optimize;\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(config);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n isServer,\n ...overrides,\n };\n};\n"],"mappings":";;;;;;;;;AAkCA,MAAM,oBAAoB,WAAyC;AACjE,KAAI;EAGF,MAAM,EAAE,8BAA4B,+BAA+B;EACnE,MAAM,qBAAqB,gBAAgB,OAAO;AAElD,SAAO,OAAO,OAAO,mBAAmB;SAClC;AAEN,SAAO,EAAE;;;;;;;;AASb,MAAa,4BACX,WAC0B;CAC1B,MAAM,EACJ,eACA,cAAc,sBACd,UACA,cACE,UAAU,EAAE;CAEhB,MAAM,SAAS,iBAAiB,cAAc;CAC9C,MAAM,EACJ,SACA,iBACA,yBACA,wBACA,yBACE,OAAO;CACX,MAAM,aAAa,OAAO,MAAM,cAAc,OAAO,YAAY;CACjE,MAAM,WAAW,OAAO,MAAM;CAE9B,MAAM,wBAAwB,KAAK,SAAS,mBAAmB;CAC/D,MAAM,gCAAgC,KACpC,SACA,4BACD;CACD,MAAM,+BAA+B,KACnC,SACA,2BACD;CACD,MAAM,6BAA6B,KAAK,SAAS,yBAAyB;CAI1E,MAAM,YAAY;EAChB,GAHuB,wBAAwB,OAG5B;EACnB;EACA;EACD;CAGD,MAAM,eAAe,wBAAwB,iBAAiB,OAAO;CAErE,MAAM,oBAGF,EAAE;AAEN,cAAa,SAAS,eAAe;AACnC,oBAAkB,WAAW,OAAO,WAAW,cAAc;GAC7D;AAEF,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,wBAAwB;EACxB;EACA;EACA;EACA;EACA,GAAG;EACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-extract.d.ts","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"mappings":";;;;;;;;KAaY,aAAA;EACV,aAAA;EACA,QAAA;EACA,OAAA,EAAS,MAAA;EACT,MAAA,EAAQ,MAAA;AAAA;AAAA,KAGE,oBAAA;EACV,WAAA,GAAc,WAAA;EACd,SAAA;EACA,OAAA;EAEA,aAAA,IAAiB,IAAA;EACjB,aAAA,EAAe,cAAA;EATD;;AAGhB;;;EAYE,SAAA,IAAa,MAAA,EAAQ,aAAA,YAAyB,OAAA;EAN/B;;;EAUf,MAAA,GAAS,eAAA;AAAA;AAAA,KAGN,KAAA,GAAQ,UAAA;EAAe,IAAA,EAAM,oBAAA;AAAA;;;;;;;;;;;;;;;AAFhC;;;cAqBW,0BAAA,GAA8B,MAAA;EACzC,KAAA,SAAc,UAAA;AAAA,MACZ,SAAA,CAAU,KAAA"}
1
+ {"version":3,"file":"babel-plugin-intlayer-extract.d.ts","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"mappings":";;;;;;;;KAcY,aAAA;EACV,aAAA;EACA,QAAA;EACA,OAAA,EAAS,MAAA;EACT,MAAA,EAAQ,MAAA;AAAA;AAAA,KAGE,oBAAA;EACV,WAAA,GAAc,WAAA;EACd,SAAA;EACA,OAAA;EAEA,aAAA,IAAiB,IAAA;EACjB,aAAA,EAAe,cAAA;EATD;;AAGhB;;;EAYE,SAAA,IAAa,MAAA,EAAQ,aAAA,YAAyB,OAAA;EAN/B;;;EAUf,MAAA,GAAS,eAAA;AAAA;AAAA,KAGN,KAAA,GAAQ,UAAA;EAAe,IAAA,EAAM,oBAAA;AAAA;;;;;;;;;;;;;;;AAFhC;;;cAqBW,0BAAA,GAA8B,MAAA;EACzC,KAAA,SAAc,UAAA;AAAA,MACZ,SAAA,CAAU,KAAA"}
@@ -59,13 +59,18 @@ type OptimizePluginOptions = {
59
59
  * Files list to traverse.
60
60
  */
61
61
  filesList: string[];
62
+ /**
63
+ * Whether the current transform is for an SSR bundle.
64
+ */
65
+ isServer?: boolean;
62
66
  };
63
67
  type State = PluginPass & {
64
68
  opts: OptimizePluginOptions; /** map key → generated ident (per-file) for static imports */
65
69
  _newStaticImports?: Map<string, BabelTypes.Identifier>; /** map key → generated ident (per-file) for dynamic imports */
66
70
  _newDynamicImports?: Map<string, BabelTypes.Identifier>; /** whether the current file imported *any* intlayer package */
67
71
  _hasValidImport?: boolean; /** map from local identifier name to the imported intlayer func name ('useIntlayer' | 'getIntlayer') */
68
- _callerMap?: Map<string, (typeof CALLER_LIST)[number]>; /** whether the current file *is* the dictionaries entry file */
72
+ _callerMap?: Map<string, (typeof CALLER_LIST)[number]>; /** map from local identifier name to the intlayer package it was imported from */
73
+ _callerPackageMap?: Map<string, string>; /** whether the current file *is* the dictionaries entry file */
69
74
  _isDictEntry?: boolean; /** whether dynamic helpers are active for this file */
70
75
  _useDynamicHelpers?: boolean; /** whether the current file is included in the filesList */
71
76
  _isIncluded?: boolean;
@@ -125,11 +130,11 @@ type State = PluginPass & {
125
130
  * const content2 = getIntlayer(_dicHash);
126
131
  * ```
127
132
  *
128
- * ### Live Mode (`importMode = "live"`)
133
+ * ### Fetch Mode (`importMode = "fetch"`)
129
134
  *
130
- * Uses live-based dictionary loading for remote dictionaries:
135
+ * Uses fetch-based dictionary loading for remote dictionaries:
131
136
  *
132
- * **Output if `dictionaryModeMap` includes the key with "live" value:**
137
+ * **Output if `dictionaryModeMap` includes the key with "fetch" value:**
133
138
  * ```ts
134
139
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
135
140
  * import _dicHash_fetch from '../../.intlayer/fetch_dictionaries/app.mjs';
@@ -140,7 +145,7 @@ type State = PluginPass & {
140
145
  * const content2 = getIntlayer(_dicHash);
141
146
  * ```
142
147
  *
143
- * > If `dictionaryModeMap` does not include the key with "live" value, the plugin will fallback to the dynamic impor
148
+ * > If `dictionaryModeMap` does not include the key with "fetch" value, the plugin will fallback to the dynamic import mode.
144
149
  *
145
150
  * ```ts
146
151
  * import _dicHash from '../../.intlayer/dictionaries/app.json' with { type: 'json' };
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-optimize.d.ts","names":[],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"mappings":";;;;cAwBM,WAAA;;AAtB0C;;KAuDpC,qBAAA;EAjC+C;;AAiC3D;EAIE,QAAA;;;;EAIA,eAAA;EAIA;;;EAAA,qBAAA;EAgBA;;;EAZA,6BAAA;EA4BA;;;EAxBA,uBAAA;EAmCS;;AACT;EAhCA,sBAAA;;;;EAIA,4BAAA;EAiCoB;;;EA7BpB,oBAAA;EAmCa;;;EA/Bb,0BAAA;EAuBA;;;EAnBA,sBAAA;EAqBgC;;;EAjBhC,UAAA;EAmBiC;;;EAfjC,iBAAA,GAAoB,MAAA;EAmBP;;;EAZb,SAAA;AAAA;AAAA,KAGG,KAAA,GAAQ,UAAA;EACX,IAAA,EAAM,qBAAA,EA+IK;EA7IX,iBAAA,GAAoB,GAAA,SAAY,UAAA,CAAW,UAAA;EAE3C,kBAAA,GAAqB,GAAA,SAAY,UAAA,CAAW,UAAA,GA6IhC;EA3IZ,eAAA,YA2IW;EAzIX,UAAA,GAAa,GAAA,iBAAoB,WAAA,YAwIjC;EAtIA,YAAA,YAqI0C;EAnI1C,kBAAA,YAqIY;EAnIZ,WAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiIW,2BAAA,GAA+B,KAAA;EAC1C,KAAA,SAAc,UAAA;AAAA,MACZ,SAAA,CAAU,KAAA"}
1
+ {"version":3,"file":"babel-plugin-intlayer-optimize.d.ts","names":[],"sources":["../../src/babel-plugin-intlayer-optimize.ts"],"mappings":";;;;cAwBM,WAAA;;AAtB0C;;KAkEpC,qBAAA;EA5C+C;;AA4C3D;EAIE,QAAA;;;;EAIA,eAAA;EAIA;;;EAAA,qBAAA;EAgBA;;;EAZA,6BAAA;EA4BA;;;EAxBA,uBAAA;EAuCA;;;EAnCA,sBAAA;EAsCQ;;;EAlCR,4BAAA;EAqCgC;;;EAjChC,oBAAA;EAuCiC;;;EAnCjC,0BAAA;EAqCuB;;;EAjCvB,sBAAA;EAyBA;;;EArBA,UAAA;EAuBA;;;EAnBA,iBAAA,GAAoB,MAAA;EAqBpB;;;EAdA,SAAA;EAkBA;;;EAdA,QAAA;AAAA;AAAA,KAGG,KAAA,GAAQ,UAAA;EACX,IAAA,EAAM,qBAAA,EAyLK;EAvLX,iBAAA,GAAoB,GAAA,SAAY,UAAA,CAAW,UAAA;EAE3C,kBAAA,GAAqB,GAAA,SAAY,UAAA,CAAW,UAAA,GAuLhC;EArLZ,eAAA,YAqLW;EAnLX,UAAA,GAAa,GAAA,iBAAoB,WAAA,YAkLjC;EAhLA,iBAAA,GAAoB,GAAA,kBA+KsB;EA7K1C,YAAA,YA+KY;EA7KZ,kBAAA,YA6KiB;EA3KjB,WAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyKW,2BAAA,GAA+B,KAAA;EAC1C,KAAA,SAAc,UAAA;AAAA,MACZ,SAAA,CAAU,KAAA"}
@@ -12,6 +12,12 @@ type GetOptimizePluginOptionsParams = {
12
12
  * Pre-loaded dictionaries (optional - will be loaded if not provided)
13
13
  */
14
14
  dictionaries?: Dictionary[];
15
+ /**
16
+ * Whether the current transform is for an SSR bundle. When using Babel
17
+ * directly (e.g. in `babel.config.js`), forward the bundler's server flag
18
+ * here so SSR-specific transforms (such as the Solid static fallback) apply.
19
+ */
20
+ isServer?: boolean;
15
21
  /**
16
22
  * Override specific options
17
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"getOptimizePluginOptions.d.ts","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"mappings":";;;;;KAUK,8BAAA;;AAFyE;;EAM5E,aAAA,GAAgB,uBAAA;EAAA;;;EAIhB,YAAA,GAAe,UAAA;EAII;;;EAAnB,SAAA,GAAY,OAAA,CAAQ,qBAAA;AAAA;;;;;;cAyBT,wBAAA,GACX,MAAA,GAAS,8BAAA,KACR,qBAAA"}
1
+ {"version":3,"file":"getOptimizePluginOptions.d.ts","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"mappings":";;;;;KAUK,8BAAA;;AAFyE;;EAM5E,aAAA,GAAgB,uBAAA;EAAA;;;EAIhB,YAAA,GAAe,UAAA;EAUI;;;;;EAJnB,QAAA;EAAA;;;EAIA,SAAA,GAAY,OAAA,CAAQ,qBAAA;AAAA;;AAyBtB;;;;cAAa,wBAAA,GACX,MAAA,GAAS,8BAAA,KACR,qBAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/babel",
3
- "version": "8.12.3",
3
+ "version": "8.12.4",
4
4
  "private": false,
5
5
  "description": "A Babel plugin for Intlayer that transforms declaration files and provides internationalization features during the build process according to the Intlayer configuration.",
6
6
  "keywords": [
@@ -81,12 +81,12 @@
81
81
  "@babel/plugin-syntax-jsx": "7.29.7",
82
82
  "@babel/traverse": "7.29.7",
83
83
  "@babel/types": "7.29.7",
84
- "@intlayer/chokidar": "8.12.3",
85
- "@intlayer/config": "8.12.3",
86
- "@intlayer/core": "8.12.3",
87
- "@intlayer/dictionaries-entry": "8.12.3",
88
- "@intlayer/types": "8.12.3",
89
- "@intlayer/unmerged-dictionaries-entry": "8.12.3",
84
+ "@intlayer/chokidar": "8.12.4",
85
+ "@intlayer/config": "8.12.4",
86
+ "@intlayer/core": "8.12.4",
87
+ "@intlayer/dictionaries-entry": "8.12.4",
88
+ "@intlayer/types": "8.12.4",
89
+ "@intlayer/unmerged-dictionaries-entry": "8.12.4",
90
90
  "@types/babel__core": "7.20.5",
91
91
  "@types/babel__generator": "7.27.0",
92
92
  "@types/babel__traverse": "7.28.0"
@@ -104,8 +104,8 @@
104
104
  "vitest": "4.1.8"
105
105
  },
106
106
  "peerDependencies": {
107
- "@intlayer/svelte-compiler": "8.12.3",
108
- "@intlayer/vue-compiler": "8.12.3"
107
+ "@intlayer/svelte-compiler": "8.12.4",
108
+ "@intlayer/vue-compiler": "8.12.4"
109
109
  },
110
110
  "peerDependenciesMeta": {
111
111
  "@intlayer/svelte-compiler": {