next-intlayer 9.4.4 → 9.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +0 -2
  2. package/dist/cjs/extractorLoader.cjs +148 -0
  3. package/dist/cjs/extractorLoader.cjs.map +1 -0
  4. package/dist/cjs/proxy/intlayerProxy.cjs +1 -1
  5. package/dist/cjs/server/prepareSwcOptimization.cjs +11 -19
  6. package/dist/cjs/server/prepareSwcOptimization.cjs.map +1 -1
  7. package/dist/cjs/server/startContentWatcher.cjs +98 -0
  8. package/dist/cjs/server/startContentWatcher.cjs.map +1 -0
  9. package/dist/cjs/server/useLocale.cjs +1 -1
  10. package/dist/cjs/server/useLocale.cjs.map +1 -1
  11. package/dist/cjs/server/withIntlayer.cjs +98 -20
  12. package/dist/cjs/server/withIntlayer.cjs.map +1 -1
  13. package/dist/esm/extractorLoader.mjs +146 -0
  14. package/dist/esm/extractorLoader.mjs.map +1 -0
  15. package/dist/esm/proxy/intlayerProxy.mjs +1 -1
  16. package/dist/esm/server/prepareSwcOptimization.mjs +11 -19
  17. package/dist/esm/server/prepareSwcOptimization.mjs.map +1 -1
  18. package/dist/esm/server/startContentWatcher.mjs +97 -0
  19. package/dist/esm/server/startContentWatcher.mjs.map +1 -0
  20. package/dist/esm/server/useLocale.mjs +1 -1
  21. package/dist/esm/server/useLocale.mjs.map +1 -1
  22. package/dist/esm/server/withIntlayer.mjs +98 -20
  23. package/dist/esm/server/withIntlayer.mjs.map +1 -1
  24. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts +1 -0
  25. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  26. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-optimize.d.ts +1 -1
  27. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-purge.d.ts +1 -0
  28. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +3 -2
  29. package/dist/types/@intlayer/babel/dist/types/index.d.ts +2 -0
  30. package/dist/types/@intlayer/babel/dist/types/pruneContext.d.ts +1 -0
  31. package/dist/types/@intlayer/babel/dist/types/staticAstReaders.d.ts +2 -0
  32. package/dist/types/@intlayer/babel/dist/types/transformers.d.ts +1 -0
  33. package/dist/types/extractorLoader.d.ts +63 -0
  34. package/dist/types/extractorLoader.d.ts.map +1 -0
  35. package/dist/types/generateStaticParams.d.ts +3 -1
  36. package/dist/types/generateStaticParams.d.ts.map +1 -1
  37. package/dist/types/server/prepareSwcOptimization.d.ts +2 -2
  38. package/dist/types/server/prepareSwcOptimization.d.ts.map +1 -1
  39. package/dist/types/server/startContentWatcher.d.ts +5 -0
  40. package/dist/types/server/startContentWatcher.d.ts.map +1 -0
  41. package/dist/types/server/useLocale.d.ts.map +1 -1
  42. package/dist/types/server/withIntlayer.d.ts +8 -2
  43. package/dist/types/server/withIntlayer.d.ts.map +1 -1
  44. package/package.json +16 -9
@@ -1,21 +1,22 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_server_prepareSwcOptimization = require('./prepareSwcOptimization.cjs');
4
+ const require_server_startContentWatcher = require('./startContentWatcher.cjs');
4
5
  const require_server_swcPluginCompatibility = require('./swcPluginCompatibility.cjs');
5
- let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
6
6
  let node_path = require("node:path");
7
7
  let _intlayer_config_colors = require("@intlayer/config/colors");
8
8
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
9
- let _intlayer_config_envVars = require("@intlayer/config/envVars");
10
9
  let _intlayer_config_logger = require("@intlayer/config/logger");
11
10
  let _intlayer_config_node = require("@intlayer/config/node");
12
11
  let _intlayer_config_utils = require("@intlayer/config/utils");
12
+ let _intlayer_engine_utils = require("@intlayer/engine/utils");
13
+ let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
14
+ let _intlayer_config_callers = require("@intlayer/config/callers");
15
+ let _intlayer_config_envVars = require("@intlayer/config/envVars");
13
16
  let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
14
17
  let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
15
18
  let _intlayer_engine_build = require("@intlayer/engine/build");
16
19
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
17
- let _intlayer_engine_utils = require("@intlayer/engine/utils");
18
- let _intlayer_webpack = require("@intlayer/webpack");
19
20
  let defu = require("defu");
20
21
  let next_package_json = require("next/package.json");
21
22
  next_package_json = require_runtime.__toESM(next_package_json);
@@ -65,7 +66,70 @@ const resolvePluginPath = (pluginPath, intlayerConfig, isTurbopackEnabled) => {
65
66
  if (isTurbopackEnabled) return (0, _intlayer_config_utils.normalizePath)(`./${(0, node_path.relative)(process.cwd(), pluginPathResolved)}`);
66
67
  return pluginPathResolved;
67
68
  };
68
- const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, isDevCommand, isGteNext13, isSwcPluginSupported, nextVersion, swcExtraCallers, fieldRenameMap }) => {
69
+ /**
70
+ * Extensions the extraction loader is registered for.
71
+ *
72
+ * The compiler reads its content out of JSX — element text and the
73
+ * translatable attributes — so a file with no JSX in it has nothing to give,
74
+ * and `*.ts` is left out. `*.js` is in because a plain-JavaScript Next.js app
75
+ * writes its components there.
76
+ */
77
+ const EXTRACTOR_LOADER_EXTENSIONS = [
78
+ "tsx",
79
+ "jsx",
80
+ "js"
81
+ ];
82
+ /**
83
+ * The subset safe to register as a Turbopack rule on any Next.js version.
84
+ *
85
+ * Turbopack rules match every module it processes, dependencies included, and
86
+ * only Next.js 16 can express "skip `node_modules`" (see
87
+ * {@link TURBOPACK_PROJECT_FILES_CONDITION}). Below that, `*.js` would hand
88
+ * every dependency file to a Node loader worker, so it is left out rather than
89
+ * made to cost a cold dev start.
90
+ */
91
+ const TURBOPACK_ALWAYS_SAFE_EXTENSIONS = ["tsx", "jsx"];
92
+ /**
93
+ * Restricts a Turbopack rule to the project's own files. `foreign` is
94
+ * Turbopack's builtin condition for a module inside `node_modules`.
95
+ *
96
+ * Only understood from Next.js 16 on — earlier releases carry no `condition`
97
+ * field on a rule at all.
98
+ */
99
+ const TURBOPACK_PROJECT_FILES_CONDITION = { not: "foreign" };
100
+ /**
101
+ * Whether the Intlayer compiler should extract content for this command.
102
+ *
103
+ * Mirrors `getExtractPluginOptions`, which the loader re-evaluates on its side:
104
+ * this is only about not registering a loader that would do nothing.
105
+ */
106
+ const getIsCompilerEnabled = (intlayerConfig, isDevCommand) => {
107
+ const enabled = intlayerConfig.compiler?.enabled ?? _intlayer_config_defaultValues.COMPILER_ENABLED;
108
+ if (enabled === "build-only") return !isDevCommand;
109
+ return enabled !== false;
110
+ };
111
+ /**
112
+ * Describes the extraction loader for both bundlers, or `null` when the
113
+ * compiler is off or `@intlayer/babel` is not installed.
114
+ *
115
+ * The loader replaces the `babel.config.js` the compiler used to need on
116
+ * Next.js: Turbopack never reads a Babel config, and on webpack the mere
117
+ * presence of one opts the whole project out of SWC — including the
118
+ * `@intlayer/swc` optimize pass.
119
+ */
120
+ const getExtractorLoader = (intlayerConfig, isTurbopackEnabled, isDevCommand) => {
121
+ if (!getIsCompilerEnabled(intlayerConfig, isDevCommand)) return null;
122
+ if (!getIsBabelExtractPluginAvailable(intlayerConfig)) return null;
123
+ try {
124
+ return {
125
+ loaderPath: resolvePluginPath("next-intlayer/extractor-loader", intlayerConfig, isTurbopackEnabled),
126
+ mode: isDevCommand ? "dev" : "build"
127
+ };
128
+ } catch {
129
+ return null;
130
+ }
131
+ };
132
+ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, isDevCommand, isGteNext13, isSwcPluginSupported, nextVersion, compatCallers, fieldRenameMap }) => {
69
133
  const { optimize, minify, purge } = intlayerConfig.build;
70
134
  const importMode = intlayerConfig.build.importMode ?? intlayerConfig.dictionary?.importMode;
71
135
  const { dictionariesDir, unmergedDictionariesDir, dynamicDictionariesDir, fetchDictionariesDir, mainDir } = intlayerConfig.system;
@@ -91,7 +155,7 @@ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, is
91
155
  (0, _intlayer_config_logger.colorize)(importMode ?? _intlayer_config_defaultValues.IMPORT_MODE, _intlayer_config_colors.BLUE),
92
156
  (0, _intlayer_config_logger.colorize)(`)`, _intlayer_config_colors.GREY_DARK)
93
157
  ]);
94
- const isPurgePipelineEnabled = !swcExtraCallers?.length && require_server_prepareSwcOptimization.getIsPurgePipelineAvailable(intlayerConfig);
158
+ const isPurgePipelineEnabled = require_server_prepareSwcOptimization.getIsPurgePipelineAvailable(intlayerConfig);
95
159
  if (isPurgePipelineEnabled && minify) logger(`Dictionary minification ${(0, _intlayer_config_logger.colorize)("enabled", _intlayer_config_colors.GREEN)}`);
96
160
  if (isPurgePipelineEnabled && purge) logger(`Dictionary purge unused keys ${(0, _intlayer_config_logger.colorize)("enabled", _intlayer_config_colors.GREEN)}`);
97
161
  } else logger([
@@ -113,11 +177,7 @@ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, is
113
177
  const dynamicDictionariesEntryPath = (0, node_path.join)(mainDir, "dynamic_dictionaries.mjs");
114
178
  const unmergedDictionariesEntryPath = (0, node_path.join)(mainDir, "unmerged_dictionaries.mjs");
115
179
  const fetchDictionariesEntryPath = (0, node_path.join)(mainDir, "fetch_dictionaries.mjs");
116
- const filesList = [
117
- ...(0, _intlayer_engine_utils.buildComponentFilesList)(intlayerConfig),
118
- dictionariesEntryPath,
119
- unmergedDictionariesEntryPath
120
- ];
180
+ const filesList = [...(0, _intlayer_engine_utils.buildComponentFilesList)(intlayerConfig), dictionariesEntryPath];
121
181
  const dictionaries = (0, _intlayer_dictionaries_entry.getDictionaries)(intlayerConfig);
122
182
  const dictionaryModeMap = {};
123
183
  Object.values(dictionaries).forEach((dictionary) => {
@@ -138,7 +198,7 @@ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, is
138
198
  replaceDictionaryEntry: true,
139
199
  nestingDictionaryKeys,
140
200
  dictionaryModeMap,
141
- extraCallers: swcExtraCallers ?? [],
201
+ extraCallers: (0, _intlayer_config_callers.toSwcExtraCallers)(compatCallers ?? []),
142
202
  fieldRenameMap: fieldRenameMap ?? {},
143
203
  logLevel: require_server_prepareSwcOptimization.resolveSwcLogLevel(intlayerConfig)
144
204
  }]] } };
@@ -203,15 +263,26 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
203
263
  const isTurbopackEnabled = configOptions?.enableTurbopack ?? isTurbopackEnabledFromCommand;
204
264
  if (isTurbopackEnabled && typeof nextConfig.webpack !== "undefined") appLogger("Turbopack is enabled but a custom webpack config is present. It will be ignored.");
205
265
  const { isBuildCommand, isDevCommand } = getCommandsEvent();
266
+ const extractorLoader = getExtractorLoader(intlayerConfig, isTurbopackEnabled ?? false, isDevCommand);
267
+ if (isDevCommand) require_server_startContentWatcher.startContentWatcher(intlayerConfig);
206
268
  const turboConfig = {
207
269
  resolveAlias: (0, _intlayer_config_utils.getAlias)({
208
270
  configuration: intlayerConfig,
209
271
  formatter: (value) => `./${value}`
210
272
  }),
211
- rules: { "*.node": {
212
- as: "*.node",
213
- loaders: ["node-loader"]
214
- } }
273
+ rules: {
274
+ "*.node": {
275
+ as: "*.node",
276
+ loaders: ["node-loader"]
277
+ },
278
+ ...extractorLoader ? Object.fromEntries((isGteNext16 ? EXTRACTOR_LOADER_EXTENSIONS : TURBOPACK_ALWAYS_SAFE_EXTENSIONS).map((extension) => [`*.${extension}`, {
279
+ loaders: [{
280
+ loader: extractorLoader.loaderPath,
281
+ options: { mode: extractorLoader.mode }
282
+ }],
283
+ ...isGteNext16 ? { condition: TURBOPACK_PROJECT_FILES_CONDITION } : {}
284
+ }])) : {}
285
+ }
215
286
  };
216
287
  const serverExternalPackages = [
217
288
  "esbuild",
@@ -269,7 +340,6 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
269
340
  } else config = {
270
341
  ...config,
271
342
  webpack: (config, options) => {
272
- const { isServer, nextRuntime } = options;
273
343
  if (typeof nextConfig.webpack === "function") config = nextConfig.webpack(config, options);
274
344
  if (config.externals === false) config.externals = [];
275
345
  const externalExact = /* @__PURE__ */ new Set([
@@ -289,6 +359,15 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
289
359
  test: /\.node$/,
290
360
  loader: "node-loader"
291
361
  });
362
+ if (extractorLoader) config.module.rules.push({
363
+ test: new RegExp(`\\.(${EXTRACTOR_LOADER_EXTENSIONS.join("|")})$`),
364
+ exclude: /node_modules/,
365
+ enforce: "pre",
366
+ use: [{
367
+ loader: extractorLoader.loaderPath,
368
+ options: { mode: extractorLoader.mode }
369
+ }]
370
+ });
292
371
  config.resolve.alias = {
293
372
  ...config.resolve.alias,
294
373
  ...(0, _intlayer_config_utils.getAlias)({
@@ -296,7 +375,6 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
296
375
  formatter: (value) => (0, node_path.resolve)(value)
297
376
  })
298
377
  };
299
- if (isDevCommand && isServer && nextRuntime === "nodejs") config.plugins.push(new _intlayer_webpack.IntlayerPlugin(intlayerConfig));
300
378
  return config;
301
379
  }
302
380
  };
@@ -310,7 +388,7 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
310
388
  isGteNext13,
311
389
  isSwcPluginSupported,
312
390
  nextVersion,
313
- swcExtraCallers: configOptions?.swcExtraCallers,
391
+ compatCallers: configOptions?.compatCallers,
314
392
  fieldRenameMap: configOptions?.fieldRenameMap
315
393
  });
316
394
  const intlayerNextConfig = (0, defu.defu)(getNewConfig(), pruneConfig);
@@ -345,7 +423,7 @@ const withIntlayer = async (nextConfig = {}, configOptions) => {
345
423
  const { isSwcPluginSupported } = getNextVersionFlags(intlayerConfig);
346
424
  const fieldRenameMap = isBuildCommand ? await require_server_prepareSwcOptimization.prepareSwcOptimization(intlayerConfig, {
347
425
  configOptions: resolvedConfigOptions,
348
- swcExtraCallers: configOptions?.swcExtraCallers,
426
+ compatCallers: configOptions?.compatCallers,
349
427
  isSwcPluginUsable: isSwcPluginSupported && getIsSwcPluginAvailable(intlayerConfig)
350
428
  }) : {};
351
429
  const nextConfigResolved = await nextConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"withIntlayer.cjs","names":["nextPackageJSON","getProjectRequire","compareVersions","getIsSwcPluginSupported","normalizePath","relative","getAppLogger","join","colorize","ANSIColors","MINIMUM_SWC_PLUGIN_NEXT_VERSION","IMPORT_MODE","getIsPurgePipelineAvailable","buildComponentFilesList","getDictionaries","getNestedDictionaryGraph","resolveSwcLogLevel","getConfiguration","getAlias","getUnusedNodeTypes","formatNodeTypeToEnvVar","formatOptimizedNestingEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","getConfigEnvVars","resolve","IntlayerPlugin","prepareIntlayer","prepareSwcOptimization"],"sources":["../../../src/server/withIntlayer.ts"],"sourcesContent":["import { join, relative, resolve } from 'node:path';\nimport type { SwcExtraCallerConfig } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { IMPORT_MODE } from '@intlayer/config/defaultValues';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n formatOptimizedNestingEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n compareVersions,\n getAlias,\n getHasDictionarySelector,\n getProjectRequire,\n getUnusedNodeTypes,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getNestedDictionaryGraph } from '@intlayer/core/dictionaryManipulator';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, runOnce } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { IntlayerPlugin } from '@intlayer/webpack';\nimport { defu } from 'defu';\nimport type { NextConfig } from 'next';\nimport type { NextJsWebpackConfig } from 'next/dist/server/config-shared';\nimport nextPackageJSON from 'next/package.json' with { type: 'json' };\nimport {\n type FieldRenameMapByDictionaryKey,\n getIsPurgePipelineAvailable,\n prepareSwcOptimization,\n resolveSwcLogLevel,\n} from './prepareSwcOptimization';\nimport {\n getIsSwcPluginSupported,\n MINIMUM_SWC_PLUGIN_NEXT_VERSION,\n} from './swcPluginCompatibility';\n\nexport {\n getIsSwcPluginSupported,\n MINIMUM_SWC_PLUGIN_NEXT_VERSION,\n} from './swcPluginCompatibility';\n\n/**\n * Resolve the Next.js version from the *user's* project at runtime.\n * A static `import from 'next/package.json'` would resolve relative to\n * next-intlayer's own node_modules, which may differ in a monorepo.\n */\nconst getNextVersionFlags = (intlayerConfig: IntlayerConfig) => {\n let nextVersion = nextPackageJSON.version;\n\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n const pkg = requireFunction('next/package.json') as { version: string };\n nextVersion = pkg.version;\n } catch {\n // keep default\n }\n\n return {\n nextVersion,\n isGteNext13: compareVersions(nextVersion, '≥', '13.0.0'),\n isGteNext15: compareVersions(nextVersion, '≥', '15.0.0'),\n isGteNext16: compareVersions(nextVersion, '≥', '16.0.0'),\n isTurbopackStable: compareVersions(nextVersion, '≥', '15.3.0'),\n /**\n * Whether this Next.js release can load the `@intlayer/swc` Wasm plugin.\n * See {@link MINIMUM_SWC_PLUGIN_NEXT_VERSION}.\n */\n isSwcPluginSupported: getIsSwcPluginSupported(nextVersion),\n };\n};\n\n// Check if SWC plugin is available\nconst getIsSwcPluginAvailable = (intlayerConfig: IntlayerConfig) => {\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n requireFunction.resolve('@intlayer/swc');\n return true;\n } catch (_e) {\n return false;\n }\n};\n\n// Check if Babel plugin is available\nconst getIsBabelExtractPluginAvailable = (intlayerConfig: IntlayerConfig) => {\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n requireFunction.resolve('@intlayer/babel');\n return true;\n } catch (_e) {\n return false;\n }\n};\n\nconst resolvePluginPath = (\n pluginPath: string,\n intlayerConfig: IntlayerConfig,\n isTurbopackEnabled: boolean\n): string => {\n const requireFunction = intlayerConfig.build?.require ?? getProjectRequire();\n const pluginPathResolved = requireFunction?.resolve(pluginPath);\n\n if (isTurbopackEnabled)\n // Relative path for turbopack\n return normalizePath(`./${relative(process.cwd(), pluginPathResolved)}`);\n\n // Absolute path for webpack\n return pluginPathResolved;\n};\n\ntype GetPruneConfigParams = {\n intlayerConfig: IntlayerConfig;\n isBuildCommand: boolean;\n isTurbopackEnabled: boolean;\n isDevCommand: boolean;\n isGteNext13: boolean;\n /** Whether the resolved Next.js version can load the Wasm plugin. */\n isSwcPluginSupported: boolean;\n /** Resolved Next.js version, reported when the plugin has to stand down. */\n nextVersion: string;\n swcExtraCallers?: SwcExtraCallerConfig[];\n fieldRenameMap?: FieldRenameMapByDictionaryKey;\n};\n\nconst getPruneConfig = ({\n intlayerConfig,\n isBuildCommand,\n isTurbopackEnabled,\n isDevCommand,\n isGteNext13,\n isSwcPluginSupported,\n nextVersion,\n swcExtraCallers,\n fieldRenameMap,\n}: GetPruneConfigParams): Partial<NextConfig> => {\n const { optimize, minify, purge } = intlayerConfig.build;\n const importMode =\n intlayerConfig.build.importMode ?? intlayerConfig.dictionary?.importMode;\n const {\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n } = intlayerConfig.system;\n const { baseDir } = intlayerConfig.system;\n const logger = getAppLogger(intlayerConfig);\n\n if (optimize === false) {\n return {};\n }\n if (optimize === undefined && !isBuildCommand) {\n return {};\n }\n\n if (!isGteNext13) return {};\n\n const isSwcPluginAvailable = getIsSwcPluginAvailable(intlayerConfig);\n\n runOnce(\n join(baseDir, '.intlayer', 'cache', 'intlayer-prune-plugin-enabled.lock'),\n () => {\n if (isSwcPluginAvailable && !isSwcPluginSupported) {\n logger(\n [\n `Build optimization ${colorize('disabled', ANSIColors.GREY_DARK)}:`,\n colorize('@intlayer/swc', ANSIColors.GREY_LIGHT),\n colorize(\n `cannot run on Next.js ${nextVersion} — its bundled SWC predates the`,\n ANSIColors.GREY\n ),\n colorize(\n 'stable Wasm plugin ABI. Upgrade to Next.js',\n ANSIColors.GREY\n ),\n colorize(MINIMUM_SWC_PLUGIN_NEXT_VERSION, ANSIColors.BLUE),\n colorize('or later to enable it.', ANSIColors.GREY),\n ],\n { level: 'warn' }\n );\n } else if (isSwcPluginAvailable) {\n logger([\n `Build optimization ${colorize('enabled', ANSIColors.GREEN)}`,\n colorize(`(import mode:`, ANSIColors.GREY_DARK),\n colorize(importMode ?? IMPORT_MODE, ANSIColors.BLUE),\n colorize(`)`, ANSIColors.GREY_DARK),\n ]);\n\n // The purge / minify pipeline stands down — with its own explanation —\n // when compat-adapter callers hide call sites from the usage analyser,\n // or when `@intlayer/babel` (which runs it) is not resolvable. The\n // editor only stands the field-rename step down, not the pipeline.\n const isPurgePipelineEnabled =\n !swcExtraCallers?.length &&\n getIsPurgePipelineAvailable(intlayerConfig);\n\n // The purge pipeline reports the field-rename step standing down when\n // the editor is enabled, so this line stays a plain one.\n if (isPurgePipelineEnabled && minify) {\n logger(\n `Dictionary minification ${colorize('enabled', ANSIColors.GREEN)}`\n );\n }\n\n if (isPurgePipelineEnabled && purge) {\n logger(\n `Dictionary purge unused keys ${colorize('enabled', ANSIColors.GREEN)}`\n );\n }\n } else {\n logger([\n colorize('Recommended: Install', ANSIColors.GREY),\n colorize('@intlayer/swc', ANSIColors.GREY_LIGHT),\n colorize(\n 'package to enable build optimization. See documentation:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://intlayer.org/docs/bundle-optimization',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n }\n },\n {\n cacheTimeoutMs: 1000 * 30, // 30 seconds\n }\n );\n\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-compiler-plugin-enabled.lock'\n ),\n () => {\n const isBabelExtractPluginAvailable =\n getIsBabelExtractPluginAvailable(intlayerConfig);\n\n if (isBabelExtractPluginAvailable) {\n let isEnabled = intlayerConfig.compiler?.enabled ?? true;\n\n if (isEnabled === 'build-only') {\n isEnabled = !isDevCommand;\n }\n\n // Only the enabled state is reported: disabling the compiler is an\n // explicit configuration choice, so announcing it on every build adds\n // noise without telling the user anything they did not ask for.\n if (isEnabled) {\n logger('Intlayer compiler enabled');\n }\n }\n },\n {\n cacheTimeoutMs: 1000 * 30, // 30 seconds\n }\n );\n\n // Registering the plugin on a host that cannot load it is not a degraded\n // build but a failed one: SWC aborts with `failed to invoke plugin`. Standing\n // down leaves the app running off the runtime dictionary registry, which the\n // transform would otherwise have emptied.\n if (!isSwcPluginAvailable || !isSwcPluginSupported) {\n return {};\n }\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(intlayerConfig);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries(intlayerConfig);\n\n const dictionaryModeMap: Record<string, 'static' | 'dynamic' | 'fetch'> = {};\n\n (Object.values(dictionaries) as Dictionary[]).forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] =\n dictionary.importMode ?? importMode ?? IMPORT_MODE;\n });\n\n // Dictionaries holding `nest()` references: their static import is re-pointed\n // at the companion module carrying the nest targets.\n const nestingDictionaryKeys = [\n ...getNestedDictionaryGraph(Object.values(dictionaries)).keys(),\n ];\n\n return {\n experimental: {\n swcPlugins: [\n [\n resolvePluginPath(\n '@intlayer/swc',\n intlayerConfig,\n isTurbopackEnabled\n ),\n {\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n nestingDictionaryKeys,\n dictionaryModeMap,\n extraCallers: swcExtraCallers ?? [],\n // Rewrites `content.title` → `content.a` to match the compiled\n // dictionaries the `build.minify` pass already renamed.\n fieldRenameMap: fieldRenameMap ?? {},\n logLevel: resolveSwcLogLevel(intlayerConfig),\n },\n ],\n ],\n },\n };\n};\n\nconst getCommandsEvent = () => {\n const lifecycleEvent = process.env['npm_lifecycle_event'];\n const lifecycleScript = process.env['npm_lifecycle_script'] ?? '';\n\n const isDevCommand =\n lifecycleEvent === 'dev' ||\n process.argv.some((arg) => arg === 'dev') ||\n /(^|\\s)(next\\s+)?dev(\\s|$)/.test(lifecycleScript);\n\n const isBuildCommand =\n lifecycleEvent === 'build' ||\n process.argv.some((arg) => arg === 'build') ||\n /(^|\\s)(next\\s+)?build(\\s|$)/.test(lifecycleScript);\n\n const isStartCommand =\n lifecycleEvent === 'start' ||\n process.argv.some((arg) => arg === 'start') ||\n /(^|\\s)(next\\s+)?start(\\s|$)/.test(lifecycleScript);\n\n return {\n isDevCommand,\n isBuildCommand,\n isStartCommand,\n };\n};\n\ntype WebpackParams = Parameters<NextJsWebpackConfig>;\n\ntype WithIntlayerOptions = GetConfigurationOptions & {\n enableTurbopack?: boolean;\n swcExtraCallers?: SwcExtraCallerConfig[];\n\n /**\n * Field-rename tables produced by the purge / minify pipeline, forwarded to\n * the `@intlayer/swc` plugin so it rewrites source accesses to match the\n * renamed dictionaries.\n *\n * @internal Set by {@link withIntlayer}; `withIntlayerSync` on its own runs\n * no dictionary rewrite, so it leaves this unset and no rename is applied.\n */\n fieldRenameMap?: FieldRenameMapByDictionaryKey;\n};\n\n/**\n * Pin the env file used to resolve the Intlayer configuration to the Next.js\n * command being run (`dev` → `development`, `build`/`start` → `production`).\n *\n * Next.js loads the config file in several processes during a single command\n * (the main `build` process plus one or more Turbopack/webpack workers), and\n * `process.env.NODE_ENV` is not guaranteed to hold the same value in all of\n * them. Since `getConfiguration` falls back to `NODE_ENV` to pick its env file\n * (`.env.development.local` vs `.env.production.local`), those processes could\n * otherwise resolve *different* env values (e.g. `applicationURL`,\n * `INTLAYER_CLIENT_ID`). The resulting configuration would differ between\n * processes, defeating the `isCachedConfigurationUpToDate` check and forcing a\n * redundant full dictionary rebuild.\n *\n * Passing an explicit `env` keeps configuration resolution deterministic across\n * every process of the command. An `env` already set by the caller is\n * respected, and when the command cannot be determined we fall back to\n * `getConfiguration`'s own default (i.e. leave `env` unset).\n */\nconst resolveConfigOptions = (\n configOptions?: WithIntlayerOptions\n): WithIntlayerOptions | undefined => {\n // Respect an explicit override from the caller (idempotent on re-entry).\n if (configOptions?.env) return configOptions;\n\n const { isDevCommand, isBuildCommand, isStartCommand } = getCommandsEvent();\n\n const env = isDevCommand\n ? 'development'\n : isBuildCommand || isStartCommand\n ? 'production'\n : undefined;\n\n if (!env) return configOptions;\n\n return {\n ...configOptions,\n env,\n };\n};\n\n/**\n * A Next.js plugin that adds the intlayer configuration to the webpack configuration\n * and sets the environment variables\n *\n * Usage:\n *\n * ```ts\n * // next.config.js\n * export default withIntlayerSync(nextConfig)\n * ```\n */\nexport const withIntlayerSync = <T extends Partial<NextConfig>>(\n nextConfig: T = {} as T,\n configOptions?: WithIntlayerOptions\n): NextConfig & T => {\n if (typeof nextConfig !== 'object') {\n nextConfig = {} as T;\n }\n\n const resolvedConfigOptions = resolveConfigOptions(configOptions);\n\n const intlayerConfig = getConfiguration(resolvedConfigOptions);\n\n logConfigDetails(resolvedConfigOptions);\n\n const appLogger = getAppLogger(intlayerConfig);\n\n const {\n nextVersion,\n isGteNext13,\n isGteNext15,\n isGteNext16,\n isTurbopackStable,\n isSwcPluginSupported,\n } = getNextVersionFlags(intlayerConfig);\n\n const isTurbopackEnabledFromCommand = isGteNext16\n ? // Next@16 enables turbopack by default; disable with --webpack\n !process.env['npm_lifecycle_script']?.includes('--webpack')\n : // Next@15 uses --turbopack, Next@14 uses --turbo\n process.env['npm_lifecycle_script']?.includes('--turbo');\n\n const isTurbopackEnabled =\n configOptions?.enableTurbopack ?? isTurbopackEnabledFromCommand;\n\n if (isTurbopackEnabled && typeof nextConfig.webpack !== 'undefined') {\n appLogger(\n 'Turbopack is enabled but a custom webpack config is present. It will be ignored.'\n );\n }\n\n const { isBuildCommand, isDevCommand } = getCommandsEvent();\n\n // Only provide turbo-specific config if user explicitly sets it\n const turboConfig = {\n resolveAlias: getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => `./${value}`, // prefix by './' to consider the path as relative to the project root. This is necessary for turbopack to work correctly.\n }),\n\n rules: {\n '*.node': {\n as: '*.node',\n loaders: ['node-loader'],\n },\n },\n };\n\n const serverExternalPackages = [\n 'esbuild',\n 'module',\n 'fs',\n 'chokidar',\n 'fsevents',\n 'recast',\n '@intlayer/engine',\n '@intlayer/webpack',\n ];\n\n let env: Record<string, string> = {};\n\n if (isBuildCommand) {\n const dictionaries = getDictionaries(intlayerConfig);\n\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = getUnusedNodeTypes(dictionaries);\n\n if (unusedNodeTypes && unusedNodeTypes.length > 0) {\n appLogger(\n [\n 'Filtering out unused logic:',\n unusedNodeTypes\n .filter(\n (key) => !['reactNode', 'solidNode', 'preactNode'].includes(key)\n )\n .map((key) => colorize(key, ANSIColors.BLUE))\n .join(', '),\n ],\n {\n isVerbose: true,\n }\n );\n }\n\n env = {\n ...env,\n\n // Tree shacking based on unused node types\n ...formatNodeTypeToEnvVar(unusedNodeTypes),\n\n // Selects the local `nest()` resolver, which reads the nest targets\n // attached to each dictionary by the optimize transform instead of the\n // registry that transform empties.\n ...formatOptimizedNestingEnvVar(intlayerConfig.build.optimize !== false),\n\n // Tree shacking the dictionary selector logic\n // (collections / variants)\n ...formatDictionarySelectorEnvVar(getHasDictionarySelector(dictionaries)),\n\n // Tree shacking based on config\n ...getConfigEnvVars(intlayerConfig),\n };\n }\n\n const getNewConfig = (): Partial<NextConfig> => {\n let config: Partial<NextConfig> = {\n env,\n };\n\n if (isGteNext15) {\n config = {\n ...config,\n serverExternalPackages,\n };\n }\n\n if (isGteNext13 && !isGteNext15) {\n config = {\n ...config,\n experimental: {\n ...(config?.experimental ?? {}),\n serverComponentsExternalPackages: serverExternalPackages,\n },\n };\n }\n\n if (isTurbopackEnabled) {\n if (isGteNext15 && isTurbopackStable) {\n config = {\n ...config,\n turbopack: turboConfig,\n };\n } else {\n config = {\n ...config,\n experimental: {\n ...(config?.experimental ?? {}),\n // @ts-ignore exist in next@14\n turbo: turboConfig,\n },\n };\n }\n } else {\n config = {\n ...config,\n webpack: (config: WebpackParams['0'], options: WebpackParams[1]) => {\n // Only add Intlayer plugin on server side (node runtime)\n const { isServer, nextRuntime } = options;\n\n // If the user has defined their own webpack config, call it\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, options);\n }\n\n // Rspack set external as false by default\n // Overwrite it to allow pushing the desired externals\n if (config.externals === false) {\n config.externals = [];\n }\n\n // Mark server-only modules as externals (function form handles subpaths)\n const externalExact = new Set([\n 'esbuild',\n 'module',\n 'fs',\n 'chokidar',\n 'fsevents',\n 'recast',\n ]);\n const externalPrefixes = ['@intlayer/engine', '@intlayer/webpack'];\n config.externals.push(\n (\n { request }: { request?: string },\n callback: (err: Error | null, result?: string) => void\n ) => {\n if (\n request &&\n (externalExact.has(request) ||\n externalPrefixes.some(\n (prefix) =>\n request === prefix || request.startsWith(`${prefix}/`)\n ))\n ) {\n return callback(null, `commonjs ${request}`);\n }\n callback(null);\n }\n );\n\n // Use `node-loader` for any `.node` files\n config.module.rules.push({\n test: /\\.node$/,\n loader: 'node-loader',\n });\n\n // Always alias on the server (node/edge) for stability.\n // On the client, alias only when not using live sync.\n config.resolve.alias = {\n ...config.resolve.alias,\n ...getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value), // get absolute path\n }),\n };\n\n // Activate watch mode webpack plugin\n if (isDevCommand && isServer && nextRuntime === 'nodejs') {\n // Optional as rspack not support plugin yet\n config.plugins.push(new IntlayerPlugin(intlayerConfig));\n }\n\n return config;\n },\n };\n }\n\n return config;\n };\n\n const pruneConfig: Partial<NextConfig> = getPruneConfig({\n intlayerConfig,\n isBuildCommand,\n isTurbopackEnabled: isTurbopackEnabled ?? false,\n isDevCommand,\n isGteNext13,\n isSwcPluginSupported,\n nextVersion,\n swcExtraCallers: configOptions?.swcExtraCallers,\n fieldRenameMap: configOptions?.fieldRenameMap,\n });\n\n const intlayerNextConfig: Partial<NextConfig> = defu(\n getNewConfig(),\n pruneConfig\n );\n\n // Merge the new config with the user's config\n const result = defu(intlayerNextConfig, nextConfig) as NextConfig & T;\n\n return result;\n};\n\n/**\n * A Next.js plugin that adds the intlayer configuration to the webpack configuration\n * and sets the environment variables\n *\n * Usage:\n *\n * ```ts\n * // next.config.js\n * export default withIntlayer(nextConfig)\n * ```\n *\n * > Node withIntlayer is a promise function. Use withIntlayerSync instead if you want to use it synchronously.\n * > Using the promise allows to prepare the intlayer dictionaries before the build starts.\n *\n */\nexport const withIntlayer = async <T extends NextConfig | Partial<NextConfig>>(\n nextConfig: T | Promise<T> = {} as T,\n configOptions?: WithIntlayerOptions\n): Promise<NextConfig & T> => {\n const { isBuildCommand, isDevCommand, isStartCommand } = getCommandsEvent();\n\n process.env.INTLAYER_IS_DEV_COMMAND = isDevCommand ? 'true' : 'false';\n\n const resolvedConfigOptions = resolveConfigOptions(configOptions);\n\n const intlayerConfig = getConfiguration(resolvedConfigOptions);\n\n const { mode } = intlayerConfig.build;\n\n // Only call prepareIntlayer during `dev` or `build` (not during `start`)\n // If prod: clean and rebuild once\n // If dev: rebuild only once if it's more than 1 hour since last rebuild\n if (!isStartCommand && (isDevCommand || isBuildCommand || mode === 'auto')) {\n // prepareIntlayer use runOnce to ensure to run only once because will run twice on client and server side otherwise\n await prepareIntlayer(intlayerConfig, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build (to ensure to rebuild all dictionaries)\n : 1000 * 60 * 60, // 1 hour for dev (default cache timeout)\n env: isBuildCommand ? 'prod' : 'dev',\n });\n }\n\n // Remove unused content fields and rename the remaining ones to short\n // aliases, then hand the rename tables to `withIntlayerSync` so the SWC\n // plugin rewrites the matching source accesses. Only meaningful for a\n // production build — the optimize pipeline is off during `next dev`.\n //\n // `isSwcPluginUsable` gates the dictionary rewrite on the plugin actually\n // running: it is the only half that fixes up the source, so minifying without\n // it would leave the code reading field names the dictionaries no longer have.\n const { isSwcPluginSupported } = getNextVersionFlags(intlayerConfig);\n\n const fieldRenameMap = isBuildCommand\n ? await prepareSwcOptimization(intlayerConfig, {\n configOptions: resolvedConfigOptions,\n swcExtraCallers: configOptions?.swcExtraCallers,\n isSwcPluginUsable:\n isSwcPluginSupported && getIsSwcPluginAvailable(intlayerConfig),\n })\n : {};\n\n const nextConfigResolved = await nextConfig;\n\n return withIntlayerSync(nextConfigResolved, {\n ...resolvedConfigOptions,\n fieldRenameMap,\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"withIntlayer.cjs","names":["nextPackageJSON","getProjectRequire","compareVersions","getIsSwcPluginSupported","normalizePath","relative","COMPILER_ENABLED","getAppLogger","join","colorize","ANSIColors","MINIMUM_SWC_PLUGIN_NEXT_VERSION","IMPORT_MODE","getIsPurgePipelineAvailable","buildComponentFilesList","getDictionaries","getNestedDictionaryGraph","toSwcExtraCallers","resolveSwcLogLevel","getConfiguration","getAlias","getUnusedNodeTypes","formatNodeTypeToEnvVar","formatOptimizedNestingEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","getConfigEnvVars","resolve","prepareIntlayer","prepareSwcOptimization"],"sources":["../../../src/server/withIntlayer.ts"],"sourcesContent":["import { join, relative, resolve } from 'node:path';\nimport {\n type CallerDescriptor,\n toSwcExtraCallers,\n} from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { COMPILER_ENABLED, IMPORT_MODE } from '@intlayer/config/defaultValues';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n formatOptimizedNestingEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n compareVersions,\n getAlias,\n getHasDictionarySelector,\n getProjectRequire,\n getUnusedNodeTypes,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getNestedDictionaryGraph } from '@intlayer/core/dictionaryManipulator';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, runOnce } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { defu } from 'defu';\nimport type { NextConfig } from 'next';\nimport type { NextJsWebpackConfig } from 'next/dist/server/config-shared';\nimport nextPackageJSON from 'next/package.json' with { type: 'json' };\nimport {\n type FieldRenameMapByDictionaryKey,\n getIsPurgePipelineAvailable,\n prepareSwcOptimization,\n resolveSwcLogLevel,\n} from './prepareSwcOptimization';\nimport { startContentWatcher } from './startContentWatcher';\nimport {\n getIsSwcPluginSupported,\n MINIMUM_SWC_PLUGIN_NEXT_VERSION,\n} from './swcPluginCompatibility';\n\nexport {\n getIsSwcPluginSupported,\n MINIMUM_SWC_PLUGIN_NEXT_VERSION,\n} from './swcPluginCompatibility';\n\n/**\n * Resolve the Next.js version from the *user's* project at runtime.\n * A static `import from 'next/package.json'` would resolve relative to\n * next-intlayer's own node_modules, which may differ in a monorepo.\n */\nconst getNextVersionFlags = (intlayerConfig: IntlayerConfig) => {\n let nextVersion = nextPackageJSON.version;\n\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n const pkg = requireFunction('next/package.json') as { version: string };\n nextVersion = pkg.version;\n } catch {\n // keep default\n }\n\n return {\n nextVersion,\n isGteNext13: compareVersions(nextVersion, '≥', '13.0.0'),\n isGteNext15: compareVersions(nextVersion, '≥', '15.0.0'),\n isGteNext16: compareVersions(nextVersion, '≥', '16.0.0'),\n isTurbopackStable: compareVersions(nextVersion, '≥', '15.3.0'),\n /**\n * Whether this Next.js release can load the `@intlayer/swc` Wasm plugin.\n * See {@link MINIMUM_SWC_PLUGIN_NEXT_VERSION}.\n */\n isSwcPluginSupported: getIsSwcPluginSupported(nextVersion),\n };\n};\n\n// Check if SWC plugin is available\nconst getIsSwcPluginAvailable = (intlayerConfig: IntlayerConfig) => {\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n requireFunction.resolve('@intlayer/swc');\n return true;\n } catch (_e) {\n return false;\n }\n};\n\n// Check if Babel plugin is available\nconst getIsBabelExtractPluginAvailable = (intlayerConfig: IntlayerConfig) => {\n try {\n const requireFunction =\n intlayerConfig.build?.require ?? getProjectRequire();\n requireFunction.resolve('@intlayer/babel');\n return true;\n } catch (_e) {\n return false;\n }\n};\n\nconst resolvePluginPath = (\n pluginPath: string,\n intlayerConfig: IntlayerConfig,\n isTurbopackEnabled: boolean\n): string => {\n const requireFunction = intlayerConfig.build?.require ?? getProjectRequire();\n const pluginPathResolved = requireFunction?.resolve(pluginPath);\n\n if (isTurbopackEnabled)\n // Relative path for turbopack\n return normalizePath(`./${relative(process.cwd(), pluginPathResolved)}`);\n\n // Absolute path for webpack\n return pluginPathResolved;\n};\n\n/**\n * Extensions the extraction loader is registered for.\n *\n * The compiler reads its content out of JSX — element text and the\n * translatable attributes — so a file with no JSX in it has nothing to give,\n * and `*.ts` is left out. `*.js` is in because a plain-JavaScript Next.js app\n * writes its components there.\n */\nconst EXTRACTOR_LOADER_EXTENSIONS = ['tsx', 'jsx', 'js'] as const;\n\n/**\n * The subset safe to register as a Turbopack rule on any Next.js version.\n *\n * Turbopack rules match every module it processes, dependencies included, and\n * only Next.js 16 can express \"skip `node_modules`\" (see\n * {@link TURBOPACK_PROJECT_FILES_CONDITION}). Below that, `*.js` would hand\n * every dependency file to a Node loader worker, so it is left out rather than\n * made to cost a cold dev start.\n */\nconst TURBOPACK_ALWAYS_SAFE_EXTENSIONS = ['tsx', 'jsx'] as const;\n\n/**\n * Restricts a Turbopack rule to the project's own files. `foreign` is\n * Turbopack's builtin condition for a module inside `node_modules`.\n *\n * Only understood from Next.js 16 on — earlier releases carry no `condition`\n * field on a rule at all.\n */\nconst TURBOPACK_PROJECT_FILES_CONDITION = { not: 'foreign' } as const;\n\n/** Mode reported to the extraction loader, which cannot read the command. */\ntype ExtractorLoaderMode = 'dev' | 'build';\n\n/**\n * Whether the Intlayer compiler should extract content for this command.\n *\n * Mirrors `getExtractPluginOptions`, which the loader re-evaluates on its side:\n * this is only about not registering a loader that would do nothing.\n */\nconst getIsCompilerEnabled = (\n intlayerConfig: IntlayerConfig,\n isDevCommand: boolean\n): boolean => {\n const enabled = intlayerConfig.compiler?.enabled ?? COMPILER_ENABLED;\n\n if (enabled === 'build-only') return !isDevCommand;\n\n return enabled !== false;\n};\n\n/**\n * Describes the extraction loader for both bundlers, or `null` when the\n * compiler is off or `@intlayer/babel` is not installed.\n *\n * The loader replaces the `babel.config.js` the compiler used to need on\n * Next.js: Turbopack never reads a Babel config, and on webpack the mere\n * presence of one opts the whole project out of SWC — including the\n * `@intlayer/swc` optimize pass.\n */\nconst getExtractorLoader = (\n intlayerConfig: IntlayerConfig,\n isTurbopackEnabled: boolean,\n isDevCommand: boolean\n): { loaderPath: string; mode: ExtractorLoaderMode } | null => {\n if (!getIsCompilerEnabled(intlayerConfig, isDevCommand)) return null;\n if (!getIsBabelExtractPluginAvailable(intlayerConfig)) return null;\n\n try {\n return {\n loaderPath: resolvePluginPath(\n 'next-intlayer/extractor-loader',\n intlayerConfig,\n isTurbopackEnabled\n ),\n mode: isDevCommand ? 'dev' : 'build',\n };\n } catch {\n // An installed `next-intlayer` that cannot resolve its own subpath means a\n // version predating the loader — the Babel setup still applies there.\n return null;\n }\n};\n\ntype GetPruneConfigParams = {\n intlayerConfig: IntlayerConfig;\n isBuildCommand: boolean;\n isTurbopackEnabled: boolean;\n isDevCommand: boolean;\n isGteNext13: boolean;\n /** Whether the resolved Next.js version can load the Wasm plugin. */\n isSwcPluginSupported: boolean;\n /** Resolved Next.js version, reported when the plugin has to stand down. */\n nextVersion: string;\n compatCallers?: CallerDescriptor[];\n fieldRenameMap?: FieldRenameMapByDictionaryKey;\n};\n\nconst getPruneConfig = ({\n intlayerConfig,\n isBuildCommand,\n isTurbopackEnabled,\n isDevCommand,\n isGteNext13,\n isSwcPluginSupported,\n nextVersion,\n compatCallers,\n fieldRenameMap,\n}: GetPruneConfigParams): Partial<NextConfig> => {\n const { optimize, minify, purge } = intlayerConfig.build;\n const importMode =\n intlayerConfig.build.importMode ?? intlayerConfig.dictionary?.importMode;\n const {\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n } = intlayerConfig.system;\n const { baseDir } = intlayerConfig.system;\n const logger = getAppLogger(intlayerConfig);\n\n if (optimize === false) {\n return {};\n }\n if (optimize === undefined && !isBuildCommand) {\n return {};\n }\n\n if (!isGteNext13) return {};\n\n const isSwcPluginAvailable = getIsSwcPluginAvailable(intlayerConfig);\n\n runOnce(\n join(baseDir, '.intlayer', 'cache', 'intlayer-prune-plugin-enabled.lock'),\n () => {\n if (isSwcPluginAvailable && !isSwcPluginSupported) {\n logger(\n [\n `Build optimization ${colorize('disabled', ANSIColors.GREY_DARK)}:`,\n colorize('@intlayer/swc', ANSIColors.GREY_LIGHT),\n colorize(\n `cannot run on Next.js ${nextVersion} — its bundled SWC predates the`,\n ANSIColors.GREY\n ),\n colorize(\n 'stable Wasm plugin ABI. Upgrade to Next.js',\n ANSIColors.GREY\n ),\n colorize(MINIMUM_SWC_PLUGIN_NEXT_VERSION, ANSIColors.BLUE),\n colorize('or later to enable it.', ANSIColors.GREY),\n ],\n { level: 'warn' }\n );\n } else if (isSwcPluginAvailable) {\n logger([\n `Build optimization ${colorize('enabled', ANSIColors.GREEN)}`,\n colorize(`(import mode:`, ANSIColors.GREY_DARK),\n colorize(importMode ?? IMPORT_MODE, ANSIColors.BLUE),\n colorize(`)`, ANSIColors.GREY_DARK),\n ]);\n\n // The purge / minify pipeline stands down — with its own explanation —\n // when `@intlayer/babel` (which runs it) is not resolvable. The editor\n // only stands the field-rename step down, not the pipeline.\n const isPurgePipelineEnabled =\n getIsPurgePipelineAvailable(intlayerConfig);\n\n // The purge pipeline reports the field-rename step standing down when\n // the editor is enabled, so this line stays a plain one.\n if (isPurgePipelineEnabled && minify) {\n logger(\n `Dictionary minification ${colorize('enabled', ANSIColors.GREEN)}`\n );\n }\n\n if (isPurgePipelineEnabled && purge) {\n logger(\n `Dictionary purge unused keys ${colorize('enabled', ANSIColors.GREEN)}`\n );\n }\n } else {\n logger([\n colorize('Recommended: Install', ANSIColors.GREY),\n colorize('@intlayer/swc', ANSIColors.GREY_LIGHT),\n colorize(\n 'package to enable build optimization. See documentation:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://intlayer.org/docs/bundle-optimization',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n }\n },\n {\n cacheTimeoutMs: 1000 * 30, // 30 seconds\n }\n );\n\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-compiler-plugin-enabled.lock'\n ),\n () => {\n const isBabelExtractPluginAvailable =\n getIsBabelExtractPluginAvailable(intlayerConfig);\n\n if (isBabelExtractPluginAvailable) {\n let isEnabled = intlayerConfig.compiler?.enabled ?? true;\n\n if (isEnabled === 'build-only') {\n isEnabled = !isDevCommand;\n }\n\n // Only the enabled state is reported: disabling the compiler is an\n // explicit configuration choice, so announcing it on every build adds\n // noise without telling the user anything they did not ask for.\n if (isEnabled) {\n logger('Intlayer compiler enabled');\n }\n }\n },\n {\n cacheTimeoutMs: 1000 * 30, // 30 seconds\n }\n );\n\n // Registering the plugin on a host that cannot load it is not a degraded\n // build but a failed one: SWC aborts with `failed to invoke plugin`. Standing\n // down leaves the app running off the runtime dictionary registry, which the\n // transform would otherwise have emptied.\n if (!isSwcPluginAvailable || !isSwcPluginSupported) {\n return {};\n }\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesListPattern = buildComponentFilesList(intlayerConfig);\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries(intlayerConfig);\n\n const dictionaryModeMap: Record<string, 'static' | 'dynamic' | 'fetch'> = {};\n\n (Object.values(dictionaries) as Dictionary[]).forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] =\n dictionary.importMode ?? importMode ?? IMPORT_MODE;\n });\n\n // Dictionaries holding `nest()` references: their static import is re-pointed\n // at the companion module carrying the nest targets.\n const nestingDictionaryKeys = [\n ...getNestedDictionaryGraph(Object.values(dictionaries)).keys(),\n ];\n\n return {\n experimental: {\n swcPlugins: [\n [\n resolvePluginPath(\n '@intlayer/swc',\n intlayerConfig,\n isTurbopackEnabled\n ),\n {\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n nestingDictionaryKeys,\n dictionaryModeMap,\n // Compat adapters reach the Wasm plugin as descriptors serialised\n // to its wire format; with none injected the option is empty and\n // the plugin runs the base intlayer rewrite alone.\n extraCallers: toSwcExtraCallers(compatCallers ?? []),\n // Rewrites `content.title` → `content.a` to match the compiled\n // dictionaries the `build.minify` pass already renamed.\n fieldRenameMap: fieldRenameMap ?? {},\n logLevel: resolveSwcLogLevel(intlayerConfig),\n },\n ],\n ],\n },\n };\n};\n\nconst getCommandsEvent = () => {\n const lifecycleEvent = process.env['npm_lifecycle_event'];\n const lifecycleScript = process.env['npm_lifecycle_script'] ?? '';\n\n const isDevCommand =\n lifecycleEvent === 'dev' ||\n process.argv.some((arg) => arg === 'dev') ||\n /(^|\\s)(next\\s+)?dev(\\s|$)/.test(lifecycleScript);\n\n const isBuildCommand =\n lifecycleEvent === 'build' ||\n process.argv.some((arg) => arg === 'build') ||\n /(^|\\s)(next\\s+)?build(\\s|$)/.test(lifecycleScript);\n\n const isStartCommand =\n lifecycleEvent === 'start' ||\n process.argv.some((arg) => arg === 'start') ||\n /(^|\\s)(next\\s+)?start(\\s|$)/.test(lifecycleScript);\n\n return {\n isDevCommand,\n isBuildCommand,\n isStartCommand,\n };\n};\n\ntype WebpackParams = Parameters<NextJsWebpackConfig>;\n\ntype WithIntlayerOptions = GetConfigurationOptions & {\n enableTurbopack?: boolean;\n /**\n * Compat-adapter caller descriptors injected by a compat package's bundler\n * plugin (e.g. `@intlayer/next-intl/plugin`). They drive both the SWC\n * optimize rewrite and the Node-side usage analysis, so one registry slice\n * is all a compat plugin has to pass.\n */\n compatCallers?: CallerDescriptor[];\n\n /**\n * Field-rename tables produced by the purge / minify pipeline, forwarded to\n * the `@intlayer/swc` plugin so it rewrites source accesses to match the\n * renamed dictionaries.\n *\n * @internal Set by {@link withIntlayer}; `withIntlayerSync` on its own runs\n * no dictionary rewrite, so it leaves this unset and no rename is applied.\n */\n fieldRenameMap?: FieldRenameMapByDictionaryKey;\n};\n\n/**\n * Pin the env file used to resolve the Intlayer configuration to the Next.js\n * command being run (`dev` → `development`, `build`/`start` → `production`).\n *\n * Next.js loads the config file in several processes during a single command\n * (the main `build` process plus one or more Turbopack/webpack workers), and\n * `process.env.NODE_ENV` is not guaranteed to hold the same value in all of\n * them. Since `getConfiguration` falls back to `NODE_ENV` to pick its env file\n * (`.env.development.local` vs `.env.production.local`), those processes could\n * otherwise resolve *different* env values (e.g. `applicationURL`,\n * `INTLAYER_CLIENT_ID`). The resulting configuration would differ between\n * processes, defeating the `isCachedConfigurationUpToDate` check and forcing a\n * redundant full dictionary rebuild.\n *\n * Passing an explicit `env` keeps configuration resolution deterministic across\n * every process of the command. An `env` already set by the caller is\n * respected, and when the command cannot be determined we fall back to\n * `getConfiguration`'s own default (i.e. leave `env` unset).\n */\nconst resolveConfigOptions = (\n configOptions?: WithIntlayerOptions\n): WithIntlayerOptions | undefined => {\n // Respect an explicit override from the caller (idempotent on re-entry).\n if (configOptions?.env) return configOptions;\n\n const { isDevCommand, isBuildCommand, isStartCommand } = getCommandsEvent();\n\n const env = isDevCommand\n ? 'development'\n : isBuildCommand || isStartCommand\n ? 'production'\n : undefined;\n\n if (!env) return configOptions;\n\n return {\n ...configOptions,\n env,\n };\n};\n\n/**\n * A Next.js plugin that adds the intlayer configuration to the webpack configuration\n * and sets the environment variables\n *\n * Usage:\n *\n * ```ts\n * // next.config.js\n * export default withIntlayerSync(nextConfig)\n * ```\n */\nexport const withIntlayerSync = <T extends Partial<NextConfig>>(\n nextConfig: T = {} as T,\n configOptions?: WithIntlayerOptions\n): NextConfig & T => {\n if (typeof nextConfig !== 'object') {\n nextConfig = {} as T;\n }\n\n const resolvedConfigOptions = resolveConfigOptions(configOptions);\n\n const intlayerConfig = getConfiguration(resolvedConfigOptions);\n\n logConfigDetails(resolvedConfigOptions);\n\n const appLogger = getAppLogger(intlayerConfig);\n\n const {\n nextVersion,\n isGteNext13,\n isGteNext15,\n isGteNext16,\n isTurbopackStable,\n isSwcPluginSupported,\n } = getNextVersionFlags(intlayerConfig);\n\n const isTurbopackEnabledFromCommand = isGteNext16\n ? // Next@16 enables turbopack by default; disable with --webpack\n !process.env['npm_lifecycle_script']?.includes('--webpack')\n : // Next@15 uses --turbopack, Next@14 uses --turbo\n process.env['npm_lifecycle_script']?.includes('--turbo');\n\n const isTurbopackEnabled =\n configOptions?.enableTurbopack ?? isTurbopackEnabledFromCommand;\n\n if (isTurbopackEnabled && typeof nextConfig.webpack !== 'undefined') {\n appLogger(\n 'Turbopack is enabled but a custom webpack config is present. It will be ignored.'\n );\n }\n\n const { isBuildCommand, isDevCommand } = getCommandsEvent();\n\n const extractorLoader = getExtractorLoader(\n intlayerConfig,\n isTurbopackEnabled ?? false,\n isDevCommand\n );\n\n // Watches on both bundlers: Turbopack cannot run a webpack plugin, and on\n // webpack this replaces `IntlayerPlugin`, whose watcher took no ownership\n // lock and so kept rebuilding alongside a parallel `intlayer watch`.\n if (isDevCommand) {\n startContentWatcher(intlayerConfig);\n }\n\n // Only provide turbo-specific config if user explicitly sets it\n const turboConfig = {\n resolveAlias: getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => `./${value}`, // prefix by './' to consider the path as relative to the project root. This is necessary for turbopack to work correctly.\n }),\n\n rules: {\n '*.node': {\n as: '*.node',\n loaders: ['node-loader'],\n },\n\n // Turbopack serialises loader options to JSON, so the loader reads the\n // Intlayer configuration itself and only the command mode is passed here.\n //\n // No `as`: it renames the module, and naming the extension the rule\n // already matches turns `Component.tsx` into `Component.tsx.tsx`, which\n // then fails to resolve. Left out, Turbopack keeps handling the loader\n // output as the TSX/JSX it still is.\n ...(extractorLoader\n ? Object.fromEntries(\n (isGteNext16\n ? EXTRACTOR_LOADER_EXTENSIONS\n : TURBOPACK_ALWAYS_SAFE_EXTENSIONS\n ).map((extension) => [\n `*.${extension}`,\n {\n loaders: [\n {\n loader: extractorLoader.loaderPath,\n options: { mode: extractorLoader.mode },\n },\n ],\n ...(isGteNext16\n ? { condition: TURBOPACK_PROJECT_FILES_CONDITION }\n : {}),\n },\n ])\n )\n : {}),\n },\n };\n\n const serverExternalPackages = [\n 'esbuild',\n 'module',\n 'fs',\n 'chokidar',\n 'fsevents',\n 'recast',\n '@intlayer/engine',\n '@intlayer/webpack',\n ];\n\n let env: Record<string, string> = {};\n\n if (isBuildCommand) {\n const dictionaries = getDictionaries(intlayerConfig);\n\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = getUnusedNodeTypes(dictionaries);\n\n if (unusedNodeTypes && unusedNodeTypes.length > 0) {\n appLogger(\n [\n 'Filtering out unused logic:',\n unusedNodeTypes\n .filter(\n (key) => !['reactNode', 'solidNode', 'preactNode'].includes(key)\n )\n .map((key) => colorize(key, ANSIColors.BLUE))\n .join(', '),\n ],\n {\n isVerbose: true,\n }\n );\n }\n\n env = {\n ...env,\n\n // Tree shacking based on unused node types\n ...formatNodeTypeToEnvVar(unusedNodeTypes),\n\n // Selects the local `nest()` resolver, which reads the nest targets\n // attached to each dictionary by the optimize transform instead of the\n // registry that transform empties.\n ...formatOptimizedNestingEnvVar(intlayerConfig.build.optimize !== false),\n\n // Tree shacking the dictionary selector logic\n // (collections / variants)\n ...formatDictionarySelectorEnvVar(getHasDictionarySelector(dictionaries)),\n\n // Tree shacking based on config\n ...getConfigEnvVars(intlayerConfig),\n };\n }\n\n const getNewConfig = (): Partial<NextConfig> => {\n let config: Partial<NextConfig> = {\n env,\n };\n\n if (isGteNext15) {\n config = {\n ...config,\n serverExternalPackages,\n };\n }\n\n if (isGteNext13 && !isGteNext15) {\n config = {\n ...config,\n experimental: {\n ...(config?.experimental ?? {}),\n serverComponentsExternalPackages: serverExternalPackages,\n },\n };\n }\n\n if (isTurbopackEnabled) {\n if (isGteNext15 && isTurbopackStable) {\n config = {\n ...config,\n turbopack: turboConfig,\n };\n } else {\n config = {\n ...config,\n experimental: {\n ...(config?.experimental ?? {}),\n // @ts-ignore exist in next@14\n turbo: turboConfig,\n },\n };\n }\n } else {\n config = {\n ...config,\n webpack: (config: WebpackParams['0'], options: WebpackParams[1]) => {\n // If the user has defined their own webpack config, call it\n if (typeof nextConfig.webpack === 'function') {\n config = nextConfig.webpack(config, options);\n }\n\n // Rspack set external as false by default\n // Overwrite it to allow pushing the desired externals\n if (config.externals === false) {\n config.externals = [];\n }\n\n // Mark server-only modules as externals (function form handles subpaths)\n const externalExact = new Set([\n 'esbuild',\n 'module',\n 'fs',\n 'chokidar',\n 'fsevents',\n 'recast',\n ]);\n const externalPrefixes = ['@intlayer/engine', '@intlayer/webpack'];\n config.externals.push(\n (\n { request }: { request?: string },\n callback: (err: Error | null, result?: string) => void\n ) => {\n if (\n request &&\n (externalExact.has(request) ||\n externalPrefixes.some(\n (prefix) =>\n request === prefix || request.startsWith(`${prefix}/`)\n ))\n ) {\n return callback(null, `commonjs ${request}`);\n }\n callback(null);\n }\n );\n\n // Use `node-loader` for any `.node` files\n config.module.rules.push({\n test: /\\.node$/,\n loader: 'node-loader',\n });\n\n // `enforce: 'pre'` puts the extraction ahead of `next-swc-loader`,\n // so the loader reads the original JSX rather than its compiled\n // output. Declaring it here (instead of in a `babel.config.js`)\n // keeps Next.js on SWC, and with it the `@intlayer/swc` optimize\n // pass a Babel config would silently disable.\n if (extractorLoader) {\n config.module.rules.push({\n test: new RegExp(\n `\\\\.(${EXTRACTOR_LOADER_EXTENSIONS.join('|')})$`\n ),\n exclude: /node_modules/,\n enforce: 'pre',\n use: [\n {\n loader: extractorLoader.loaderPath,\n options: { mode: extractorLoader.mode },\n },\n ],\n });\n }\n\n // Always alias on the server (node/edge) for stability.\n // On the client, alias only when not using live sync.\n config.resolve.alias = {\n ...config.resolve.alias,\n ...getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value), // get absolute path\n }),\n };\n\n return config;\n },\n };\n }\n\n return config;\n };\n\n const pruneConfig: Partial<NextConfig> = getPruneConfig({\n intlayerConfig,\n isBuildCommand,\n isTurbopackEnabled: isTurbopackEnabled ?? false,\n isDevCommand,\n isGteNext13,\n isSwcPluginSupported,\n nextVersion,\n compatCallers: configOptions?.compatCallers,\n fieldRenameMap: configOptions?.fieldRenameMap,\n });\n\n const intlayerNextConfig: Partial<NextConfig> = defu(\n getNewConfig(),\n pruneConfig\n );\n\n // Merge the new config with the user's config\n const result = defu(intlayerNextConfig, nextConfig) as NextConfig & T;\n\n return result;\n};\n\n/**\n * A Next.js plugin that adds the intlayer configuration to the webpack configuration\n * and sets the environment variables\n *\n * Usage:\n *\n * ```ts\n * // next.config.js\n * export default withIntlayer(nextConfig)\n * ```\n *\n * > Node withIntlayer is a promise function. Use withIntlayerSync instead if you want to use it synchronously.\n * > Using the promise allows to prepare the intlayer dictionaries before the build starts.\n *\n */\nexport const withIntlayer = async <T extends NextConfig | Partial<NextConfig>>(\n nextConfig: T | Promise<T> = {} as T,\n configOptions?: WithIntlayerOptions\n): Promise<NextConfig & T> => {\n const { isBuildCommand, isDevCommand, isStartCommand } = getCommandsEvent();\n\n process.env.INTLAYER_IS_DEV_COMMAND = isDevCommand ? 'true' : 'false';\n\n const resolvedConfigOptions = resolveConfigOptions(configOptions);\n\n const intlayerConfig = getConfiguration(resolvedConfigOptions);\n\n const { mode } = intlayerConfig.build;\n\n // Only call prepareIntlayer during `dev` or `build` (not during `start`)\n // If prod: clean and rebuild once\n // If dev: rebuild only once if it's more than 1 hour since last rebuild\n if (!isStartCommand && (isDevCommand || isBuildCommand || mode === 'auto')) {\n // prepareIntlayer use runOnce to ensure to run only once because will run twice on client and server side otherwise\n await prepareIntlayer(intlayerConfig, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build (to ensure to rebuild all dictionaries)\n : 1000 * 60 * 60, // 1 hour for dev (default cache timeout)\n env: isBuildCommand ? 'prod' : 'dev',\n });\n }\n\n // Remove unused content fields and rename the remaining ones to short\n // aliases, then hand the rename tables to `withIntlayerSync` so the SWC\n // plugin rewrites the matching source accesses. Only meaningful for a\n // production build — the optimize pipeline is off during `next dev`.\n //\n // `isSwcPluginUsable` gates the dictionary rewrite on the plugin actually\n // running: it is the only half that fixes up the source, so minifying without\n // it would leave the code reading field names the dictionaries no longer have.\n const { isSwcPluginSupported } = getNextVersionFlags(intlayerConfig);\n\n const fieldRenameMap = isBuildCommand\n ? await prepareSwcOptimization(intlayerConfig, {\n configOptions: resolvedConfigOptions,\n compatCallers: configOptions?.compatCallers,\n isSwcPluginUsable:\n isSwcPluginSupported && getIsSwcPluginAvailable(intlayerConfig),\n })\n : {};\n\n const nextConfigResolved = await nextConfig;\n\n return withIntlayerSync(nextConfigResolved, {\n ...resolvedConfigOptions,\n fieldRenameMap,\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import { dirname, join, relative } from "node:path";
2
+ import * as ANSIColors from "@intlayer/config/colors";
3
+ import { colorize, colorizePath, getAppLogger } from "@intlayer/config/logger";
4
+ import { getConfiguration } from "@intlayer/config/node";
5
+ import { getProjectRequire, normalizePath } from "@intlayer/config/utils";
6
+ import { withFileLock } from "@intlayer/engine/utils";
7
+
8
+ //#region src/extractorLoader.ts
9
+ const REQUIRED_BABEL_EXPORTS = [
10
+ "detectPackageName",
11
+ "extractContent",
12
+ "getExtractPluginOptions",
13
+ "writeContentHelper"
14
+ ];
15
+ /**
16
+ * Serialises the dictionary writes of every process taking part in the build.
17
+ * `writeContentHelper` rebuilds the merged `.intlayer` artifacts, which is a
18
+ * read-modify-write over every dictionary on disk — two extractions running it
19
+ * at the same time would each merge a half-written state.
20
+ */
21
+ const WRITE_LOCK_FILE_NAME = "intlayer-compiler-write.lock";
22
+ /** Set once per process: the loader runs in a long-lived bundler worker. */
23
+ let cachedConfiguration;
24
+ let cachedExtractOptions;
25
+ let cachedFilesListSet;
26
+ let cachedBabelModule;
27
+ /** Intlayer package detected per component directory. */
28
+ const packageNameByDirectory = /* @__PURE__ */ new Map();
29
+ /**
30
+ * Content already written for a given dictionary key, as a stable hash.
31
+ *
32
+ * Next.js compiles the same file once per compilation (client, server, edge),
33
+ * and Turbopack re-runs the loader whenever the file changes. Re-writing a
34
+ * dictionary whose content did not move costs a full `.intlayer` rebuild for
35
+ * nothing.
36
+ */
37
+ const writtenContentHashByDictionaryKey = /* @__PURE__ */ new Map();
38
+ /** Serialises the writes issued by this process, before the file lock. */
39
+ let pendingWrite = Promise.resolve();
40
+ /**
41
+ * Lazily loads `@intlayer/babel`, or `null` when it is not installed or too old
42
+ * to expose the extraction API.
43
+ */
44
+ const loadIntlayerBabel = (configuration) => {
45
+ if (cachedBabelModule !== void 0) return cachedBabelModule;
46
+ try {
47
+ const intlayerBabel = (configuration.build?.require ?? getProjectRequire())("@intlayer/babel");
48
+ cachedBabelModule = REQUIRED_BABEL_EXPORTS.every((exportName) => typeof intlayerBabel?.[exportName] === "function") ? intlayerBabel : null;
49
+ } catch {
50
+ cachedBabelModule = null;
51
+ }
52
+ return cachedBabelModule;
53
+ };
54
+ const getOptions = (context) => {
55
+ if (typeof context.getOptions === "function") return context.getOptions();
56
+ if (typeof context.query === "object" && context.query) return context.query;
57
+ return {};
58
+ };
59
+ const hashContent = (content) => JSON.stringify(Object.keys(content).sort().map((key) => [key, content[key]]));
60
+ /**
61
+ * Writes one extracted dictionary, skipping the write when its content is
62
+ * already on disk and holding the cross-process lock while `.intlayer` is
63
+ * rebuilt.
64
+ */
65
+ const writeDictionary = async (intlayerBabel, configuration, dictionaryKey, content, filePath) => {
66
+ const contentHash = hashContent(content);
67
+ if (writtenContentHashByDictionaryKey.get(dictionaryKey) === contentHash) return;
68
+ const lockFilePath = join(configuration.system.baseDir, ".intlayer", "cache", WRITE_LOCK_FILE_NAME);
69
+ await withFileLock(lockFilePath, () => intlayerBabel.writeContentHelper(content, dictionaryKey, filePath, configuration));
70
+ writtenContentHashByDictionaryKey.set(dictionaryKey, contentHash);
71
+ };
72
+ /**
73
+ * Extracts the translatable content of one file and returns the rewritten
74
+ * source, or the original source when there is nothing to extract.
75
+ */
76
+ const extractFile = async (filePath, source, mode) => {
77
+ cachedConfiguration ??= getConfiguration();
78
+ const configuration = cachedConfiguration;
79
+ const intlayerBabel = loadIntlayerBabel(configuration);
80
+ if (!intlayerBabel) return source;
81
+ cachedExtractOptions ??= intlayerBabel.getExtractPluginOptions(configuration, mode);
82
+ if (!cachedExtractOptions.enabled) return source;
83
+ cachedFilesListSet ??= new Set((cachedExtractOptions.filesList ?? []).map(normalizePath));
84
+ if (!cachedFilesListSet.has(normalizePath(filePath))) return source;
85
+ const appLogger = getAppLogger(configuration);
86
+ const componentDirectory = dirname(filePath);
87
+ let packageName = packageNameByDirectory.get(componentDirectory);
88
+ if (!packageName) {
89
+ packageName = intlayerBabel.detectPackageName(componentDirectory);
90
+ packageNameByDirectory.set(componentDirectory, packageName);
91
+ }
92
+ const result = await intlayerBabel.extractContent(filePath, packageName, {
93
+ configuration,
94
+ code: source,
95
+ declarationOnly: !configuration.compiler.saveComponents,
96
+ onExtract: ({ key, content }) => {
97
+ pendingWrite = pendingWrite.then(() => writeDictionary(intlayerBabel, configuration, key, content, filePath)).catch((error) => {
98
+ appLogger([`${colorize("Compiler:", ANSIColors.GREY_DARK)} Failed to write the dictionary extracted from ${colorizePath(relative(configuration.system.baseDir, filePath))}:`, error], { level: "error" });
99
+ });
100
+ return pendingWrite;
101
+ }
102
+ });
103
+ if (!result?.transformedCode) return source;
104
+ appLogger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(configuration.system.baseDir, filePath))}`, { level: "debug" });
105
+ return result.transformedCode;
106
+ };
107
+ /**
108
+ * Webpack-compatible loader running the Intlayer compiler extraction pass.
109
+ *
110
+ * It replaces the `babel.config.js` setup on Next.js: Turbopack never reads a
111
+ * Babel config, and on webpack a Babel config would opt the whole project out
112
+ * of SWC. Registered automatically by `withIntlayer` on both bundlers.
113
+ *
114
+ * @example next.config.ts — registered by hand
115
+ * ```ts
116
+ * export default {
117
+ * turbopack: {
118
+ * rules: {
119
+ * // No `as`: it renames the module, so naming the extension the rule
120
+ * // already matches would ask for `Component.tsx.tsx`.
121
+ * '*.tsx': {
122
+ * loaders: [
123
+ * {
124
+ * loader: require.resolve('next-intlayer/extractor-loader'),
125
+ * options: { mode: 'dev' },
126
+ * },
127
+ * ],
128
+ * },
129
+ * },
130
+ * },
131
+ * };
132
+ * ```
133
+ */
134
+ const intlayerExtractorLoader = function(source) {
135
+ const callback = this.async();
136
+ const { mode } = getOptions(this);
137
+ const filePath = this.resourcePath;
138
+ extractFile(filePath, source, mode ?? "build").then((code) => callback(null, code)).catch((error) => {
139
+ getAppLogger(cachedConfiguration)([`${colorize("Compiler:", ANSIColors.GREY_DARK)} Failed to extract content from ${colorizePath(filePath)}:`, error], { level: "error" });
140
+ callback(null, source);
141
+ });
142
+ };
143
+
144
+ //#endregion
145
+ export { intlayerExtractorLoader as default };
146
+ //# sourceMappingURL=extractorLoader.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractorLoader.mjs","names":[],"sources":["../../src/extractorLoader.ts"],"sourcesContent":["import { dirname, join, relative } from 'node:path';\nimport type {\n detectPackageName as DetectPackageName,\n extractContent as ExtractContent,\n ExtractPluginOptions,\n getExtractPluginOptions as GetExtractPluginOptions,\n PackageName,\n writeContentHelper as WriteContentHelper,\n} from '@intlayer/babel';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { getProjectRequire, normalizePath } from '@intlayer/config/utils';\nimport { withFileLock } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Options the loader accepts. Turbopack serialises loader options to JSON, so\n * every field has to stay a plain JSON value — the Intlayer configuration\n * itself (which carries functions, e.g. `compiler.output`) is therefore loaded\n * by the loader rather than handed to it.\n */\nexport type IntlayerExtractorLoaderOptions = {\n /**\n * Whether the host bundler is serving (`dev`) or building (`build`).\n *\n * Passed explicitly because a Turbopack loader runs in a worker process whose\n * environment does not necessarily carry `INTLAYER_IS_DEV_COMMAND`.\n */\n mode?: 'dev' | 'build';\n};\n\n/**\n * Structural view of the loader context, limited to what this loader uses.\n * Typed locally rather than imported from `webpack` because the same file is\n * also run by Turbopack's webpack-loader compatibility layer, and `webpack` is\n * only an optional peer dependency.\n */\ntype IntlayerLoaderContext = {\n /** Absolute path of the file being compiled. */\n resourcePath: string;\n /** Switches the loader to asynchronous mode. */\n async: () => (error: Error | null, content?: string) => void;\n /** webpack 5 / Turbopack accessor for the loader options. */\n getOptions?: () => IntlayerExtractorLoaderOptions;\n /** Legacy options holder, used when `getOptions` is unavailable. */\n query?: IntlayerExtractorLoaderOptions | string;\n};\n\n/**\n * Subset of `@intlayer/babel` the loader needs. The package is an optional\n * dependency, so it is required lazily and never imported at module scope.\n */\ntype IntlayerBabelModule = {\n detectPackageName: typeof DetectPackageName;\n extractContent: typeof ExtractContent;\n getExtractPluginOptions: typeof GetExtractPluginOptions;\n writeContentHelper: typeof WriteContentHelper;\n};\n\nconst REQUIRED_BABEL_EXPORTS = [\n 'detectPackageName',\n 'extractContent',\n 'getExtractPluginOptions',\n 'writeContentHelper',\n] as const satisfies readonly (keyof IntlayerBabelModule)[];\n\n/**\n * Serialises the dictionary writes of every process taking part in the build.\n * `writeContentHelper` rebuilds the merged `.intlayer` artifacts, which is a\n * read-modify-write over every dictionary on disk — two extractions running it\n * at the same time would each merge a half-written state.\n */\nconst WRITE_LOCK_FILE_NAME = 'intlayer-compiler-write.lock';\n\n/** Set once per process: the loader runs in a long-lived bundler worker. */\nlet cachedConfiguration: IntlayerConfig | undefined;\nlet cachedExtractOptions: ExtractPluginOptions | undefined;\nlet cachedFilesListSet: Set<string> | undefined;\nlet cachedBabelModule: IntlayerBabelModule | null | undefined;\n\n/** Intlayer package detected per component directory. */\nconst packageNameByDirectory = new Map<string, PackageName>();\n\n/**\n * Content already written for a given dictionary key, as a stable hash.\n *\n * Next.js compiles the same file once per compilation (client, server, edge),\n * and Turbopack re-runs the loader whenever the file changes. Re-writing a\n * dictionary whose content did not move costs a full `.intlayer` rebuild for\n * nothing.\n */\nconst writtenContentHashByDictionaryKey = new Map<string, string>();\n\n/** Serialises the writes issued by this process, before the file lock. */\nlet pendingWrite: Promise<void> = Promise.resolve();\n\n/**\n * Lazily loads `@intlayer/babel`, or `null` when it is not installed or too old\n * to expose the extraction API.\n */\nconst loadIntlayerBabel = (\n configuration: IntlayerConfig\n): IntlayerBabelModule | null => {\n if (cachedBabelModule !== undefined) return cachedBabelModule;\n\n try {\n const requireFunction = configuration.build?.require ?? getProjectRequire();\n\n const intlayerBabel = requireFunction(\n '@intlayer/babel'\n ) as Partial<IntlayerBabelModule>;\n\n const hasEveryRequiredExport = REQUIRED_BABEL_EXPORTS.every(\n (exportName) => typeof intlayerBabel?.[exportName] === 'function'\n );\n\n cachedBabelModule = hasEveryRequiredExport\n ? (intlayerBabel as IntlayerBabelModule)\n : null;\n } catch {\n cachedBabelModule = null;\n }\n\n return cachedBabelModule;\n};\n\nconst getOptions = (\n context: IntlayerLoaderContext\n): IntlayerExtractorLoaderOptions => {\n if (typeof context.getOptions === 'function') return context.getOptions();\n if (typeof context.query === 'object' && context.query) return context.query;\n\n return {};\n};\n\nconst hashContent = (content: Record<string, string>): string =>\n JSON.stringify(\n Object.keys(content)\n .sort()\n .map((key) => [key, content[key]])\n );\n\n/**\n * Writes one extracted dictionary, skipping the write when its content is\n * already on disk and holding the cross-process lock while `.intlayer` is\n * rebuilt.\n */\nconst writeDictionary = async (\n intlayerBabel: IntlayerBabelModule,\n configuration: IntlayerConfig,\n dictionaryKey: string,\n content: Record<string, string>,\n filePath: string\n): Promise<void> => {\n const contentHash = hashContent(content);\n\n if (writtenContentHashByDictionaryKey.get(dictionaryKey) === contentHash) {\n return;\n }\n\n const lockFilePath = join(\n configuration.system.baseDir,\n '.intlayer',\n 'cache',\n WRITE_LOCK_FILE_NAME\n );\n\n await withFileLock(lockFilePath, () =>\n intlayerBabel.writeContentHelper(\n content,\n dictionaryKey,\n filePath,\n configuration\n )\n );\n\n writtenContentHashByDictionaryKey.set(dictionaryKey, contentHash);\n};\n\n/**\n * Extracts the translatable content of one file and returns the rewritten\n * source, or the original source when there is nothing to extract.\n */\nconst extractFile = async (\n filePath: string,\n source: string,\n mode: 'dev' | 'build'\n): Promise<string> => {\n cachedConfiguration ??= getConfiguration();\n const configuration = cachedConfiguration;\n\n const intlayerBabel = loadIntlayerBabel(configuration);\n\n // Without `@intlayer/babel` there is no extraction to run; `withIntlayer`\n // only registers this loader when the package resolves, so reaching this\n // branch means it was removed after the config was read.\n if (!intlayerBabel) return source;\n\n cachedExtractOptions ??= intlayerBabel.getExtractPluginOptions(\n configuration,\n mode\n );\n\n if (!cachedExtractOptions.enabled) return source;\n\n cachedFilesListSet ??= new Set(\n (cachedExtractOptions.filesList ?? []).map(normalizePath)\n );\n\n if (!cachedFilesListSet.has(normalizePath(filePath))) return source;\n\n const appLogger = getAppLogger(configuration);\n const componentDirectory = dirname(filePath);\n\n let packageName = packageNameByDirectory.get(componentDirectory);\n\n if (!packageName) {\n packageName = intlayerBabel.detectPackageName(componentDirectory);\n packageNameByDirectory.set(componentDirectory, packageName);\n }\n\n const result = await intlayerBabel.extractContent(filePath, packageName, {\n configuration,\n code: source,\n // `extractContent` rewrites the component on disk unless told otherwise,\n // so the config flag has to be forwarded — the transform is meant to stay\n // in the bundle output until the user opts into `saveComponents`.\n declarationOnly: !configuration.compiler.saveComponents,\n // Supplying `onExtract` turns off the internal dictionary write, so the\n // writes stay serialised behind the lock below.\n onExtract: ({ key, content }) => {\n pendingWrite = pendingWrite\n .then(() =>\n writeDictionary(intlayerBabel, configuration, key, content, filePath)\n )\n .catch((error) => {\n appLogger(\n [\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to write the dictionary extracted from ${colorizePath(\n relative(configuration.system.baseDir, filePath)\n )}:`,\n error,\n ],\n { level: 'error' }\n );\n });\n\n return pendingWrite;\n },\n });\n\n if (!result?.transformedCode) return source;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(\n relative(configuration.system.baseDir, filePath)\n )}`,\n { level: 'debug' }\n );\n\n return result.transformedCode;\n};\n\n/**\n * Webpack-compatible loader running the Intlayer compiler extraction pass.\n *\n * It replaces the `babel.config.js` setup on Next.js: Turbopack never reads a\n * Babel config, and on webpack a Babel config would opt the whole project out\n * of SWC. Registered automatically by `withIntlayer` on both bundlers.\n *\n * @example next.config.ts — registered by hand\n * ```ts\n * export default {\n * turbopack: {\n * rules: {\n * // No `as`: it renames the module, so naming the extension the rule\n * // already matches would ask for `Component.tsx.tsx`.\n * '*.tsx': {\n * loaders: [\n * {\n * loader: require.resolve('next-intlayer/extractor-loader'),\n * options: { mode: 'dev' },\n * },\n * ],\n * },\n * },\n * },\n * };\n * ```\n */\nconst intlayerExtractorLoader = function (\n this: IntlayerLoaderContext,\n source: string\n): void {\n const callback = this.async();\n const { mode } = getOptions(this);\n const filePath = this.resourcePath;\n\n extractFile(filePath, source, mode ?? 'build')\n .then((code) => callback(null, code))\n .catch((error) => {\n // An extraction failure must not take the build down: the file simply\n // keeps its own hardcoded strings.\n const appLogger = getAppLogger(cachedConfiguration);\n\n appLogger(\n [\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to extract content from ${colorizePath(filePath)}:`,\n error,\n ],\n { level: 'error' }\n );\n\n callback(null, source);\n });\n};\n\nexport default intlayerExtractorLoader;\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { localeDetector as localeDetector$1 } from "./localeDetector.mjs";
2
+ import { getAppLogger } from "@intlayer/config/logger";
2
3
  import { formatProxyEnabledMessage, getCanonicalPath, getDomainHostname, getDomainOrigin, getInternalPath, getLocaleFromDomain, getRewriteRules, isProxyStorageLocaleEnabled, resolveLocalizedPath, resolveProxyMode } from "@intlayer/core/localization";
3
4
  import { getLocaleFromStorageServer, setLocaleInStorageServer } from "@intlayer/core/utils";
4
5
  import { internationalization, log, routing } from "@intlayer/config/built";
5
6
  import { ROUTING_MODE } from "@intlayer/config/defaultValues";
6
- import { getAppLogger } from "@intlayer/config/logger";
7
7
  import { NextResponse } from "next/server";
8
8
 
9
9
  //#region src/proxy/intlayerProxy.ts