next-intlayer 9.4.3 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) 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 +12 -20
  6. package/dist/cjs/server/prepareSwcOptimization.cjs.map +1 -1
  7. package/dist/cjs/server/startContentWatcher.cjs +91 -0
  8. package/dist/cjs/server/startContentWatcher.cjs.map +1 -0
  9. package/dist/cjs/server/withIntlayer.cjs +98 -13
  10. package/dist/cjs/server/withIntlayer.cjs.map +1 -1
  11. package/dist/esm/extractorLoader.mjs +146 -0
  12. package/dist/esm/extractorLoader.mjs.map +1 -0
  13. package/dist/esm/proxy/intlayerProxy.mjs +1 -1
  14. package/dist/esm/server/prepareSwcOptimization.mjs +12 -20
  15. package/dist/esm/server/prepareSwcOptimization.mjs.map +1 -1
  16. package/dist/esm/server/startContentWatcher.mjs +90 -0
  17. package/dist/esm/server/startContentWatcher.mjs.map +1 -0
  18. package/dist/esm/server/withIntlayer.mjs +98 -13
  19. package/dist/esm/server/withIntlayer.mjs.map +1 -1
  20. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts +1 -0
  21. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  22. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-optimize.d.ts +1 -1
  23. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-purge.d.ts +1 -0
  24. package/dist/types/@intlayer/babel/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +3 -2
  25. package/dist/types/@intlayer/babel/dist/types/index.d.ts +2 -0
  26. package/dist/types/@intlayer/babel/dist/types/pruneContext.d.ts +1 -0
  27. package/dist/types/@intlayer/babel/dist/types/staticAstReaders.d.ts +2 -0
  28. package/dist/types/@intlayer/babel/dist/types/transformers.d.ts +1 -0
  29. package/dist/types/extractorLoader.d.ts +63 -0
  30. package/dist/types/extractorLoader.d.ts.map +1 -0
  31. package/dist/types/server/prepareSwcOptimization.d.ts +2 -2
  32. package/dist/types/server/prepareSwcOptimization.d.ts.map +1 -1
  33. package/dist/types/server/startContentWatcher.d.ts +5 -0
  34. package/dist/types/server/startContentWatcher.d.ts.map +1 -0
  35. package/dist/types/server/withIntlayer.d.ts +8 -2
  36. package/dist/types/server/withIntlayer.d.ts.map +1 -1
  37. package/package.json +17 -9
@@ -1 +1 @@
1
- {"version":3,"file":"prepareSwcOptimization.mjs","names":[],"sources":["../../../src/server/prepareSwcOptimization.ts"],"sourcesContent":["import { readFileSync, rmSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type {\n getPurgePluginOptions as GetPurgePluginOptions,\n runIntlayerPurgePipeline as RunIntlayerPurgePipeline,\n SerializedFieldRenameMap,\n serializeFieldRenameMap as SerializeFieldRenameMap,\n} from '@intlayer/babel';\nimport type { SwcExtraCallerConfig } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport type { GetConfigurationOptions } from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Field-rename tables keyed by dictionary key, forwarded to the\n * `@intlayer/swc` plugin's `fieldRenameMap` option.\n */\nexport type FieldRenameMapByDictionaryKey = Record<\n string,\n SerializedFieldRenameMap\n>;\n\n/** Verbosity forwarded to the `@intlayer/swc` plugin's `logLevel` option. */\nexport type SwcLogLevel = 'off' | 'info' | 'debug';\n\n/**\n * Subset of `@intlayer/babel` this module needs. The package is only an\n * optional runtime dependency, so it is required lazily and never imported at\n * module scope.\n */\ntype IntlayerBabelModule = {\n getPurgePluginOptions: typeof GetPurgePluginOptions;\n runIntlayerPurgePipeline: typeof RunIntlayerPurgePipeline;\n serializeFieldRenameMap: typeof SerializeFieldRenameMap;\n};\n\n/**\n * Opt-in to the SWC plugin's per-file tracing.\n *\n * The plugin transforms one file at a time with no cross-file state, so all it\n * can report is a line per file — hundreds of them on a real project, and with\n * no counterpart in the Vite build output. The purge and minify summaries that\n * `log.mode` does control are emitted by the pipeline itself, in Node; this\n * variable is purely a debugging aid on top.\n */\nconst SWC_LOG_LEVEL_ENV_VAR = 'INTLAYER_SWC_LOG_LEVEL';\n\n/** Sentinel coordinating the pipeline across the processes of one build. */\nconst PURGE_SENTINEL_FILE_NAME = 'intlayer-swc-purge.lock';\n\n/** Where the serialised field-rename tables are cached between processes. */\nconst FIELD_RENAME_MAP_FILE_NAME = 'swc-field-rename-map.json';\n\n/**\n * Next.js evaluates `next.config.*` in the main build process and again in each\n * Turbopack/webpack worker. The dictionary rewrite must happen exactly once —\n * a second run would derive the short aliases from the already-renamed JSON —\n * so the sentinel window has to cover a whole build startup.\n */\nconst PURGE_CACHE_TIMEOUT_MS = 30 * 1000;\n\n/** Absolute path of a file in the intlayer cache directory. */\nconst getCacheFilePath = (\n intlayerConfig: IntlayerConfig,\n fileName: string\n): string =>\n join(intlayerConfig.system.baseDir, '.intlayer', 'cache', fileName);\n\n/**\n * Resolves the verbosity the `@intlayer/swc` plugin should report at.\n *\n * Off unless {@link SWC_LOG_LEVEL_ENV_VAR} asks for tracing: `log.mode` governs\n * the purge and minify reporting, which the pipeline emits in Node so the\n * Next.js build reads the same as the Vite one.\n */\nexport const resolveSwcLogLevel = (\n intlayerConfig: IntlayerConfig\n): SwcLogLevel => {\n if (intlayerConfig.log.mode === 'disabled') return 'off';\n\n const requestedLogLevel = process.env[SWC_LOG_LEVEL_ENV_VAR];\n\n return requestedLogLevel === 'info' || requestedLogLevel === 'debug'\n ? requestedLogLevel\n : 'off';\n};\n\n/**\n * Whether the purge / minify pipeline should run for this build.\n *\n * Compat-adapter callers disable it: their descriptors reach `withIntlayer`\n * only in the SWC plugin's lossy wire format, so the usage analyser would not\n * recognise `useTranslation(...)` & co. and would purge fields those call sites\n * still read.\n */\nconst getIsPurgePipelineEnabled = (\n intlayerConfig: IntlayerConfig,\n swcExtraCallers: SwcExtraCallerConfig[] | undefined,\n isSwcPluginUsable: boolean\n): boolean => {\n const { purge, minify, optimize } = intlayerConfig.build;\n\n if (optimize === false) return false;\n if (!purge && !minify) return false;\n\n // The pipeline rewrites the compiled dictionaries in place — dropping unused\n // fields and renaming the rest to short aliases. Only the SWC plugin rewrites\n // the matching source accesses, so running this without it would ship\n // dictionaries whose keys no longer match the code reading them.\n if (!isSwcPluginUsable) return false;\n\n // `editor.enabled` is deliberately not checked here: it only stands the\n // field-rename step down — inside the pipeline, and with its own explanation\n // — the same way the Vite build does. Purging still runs, and the rename map\n // the SWC plugin receives comes back empty, so source and JSON stay in sync.\n\n if (swcExtraCallers && swcExtraCallers.length > 0) {\n getAppLogger(intlayerConfig)(\n [\n 'Dictionary purge and minification are',\n colorize('disabled', ANSIColors.GREY_DARK),\n 'because compat-adapter callers are configured — their call sites are',\n 'not visible to the usage analyser.',\n ],\n { level: 'warn' }\n );\n return false;\n }\n\n return true;\n};\n\n/**\n * Exports this module needs from `@intlayer/babel`. Checked one by one so a\n * version predating the purge pipeline is rejected like a missing package,\n * instead of failing later with `runIntlayerPurgePipeline is not a function`.\n */\nconst REQUIRED_BABEL_EXPORTS = [\n 'getPurgePluginOptions',\n 'runIntlayerPurgePipeline',\n 'serializeFieldRenameMap',\n] as const satisfies readonly (keyof IntlayerBabelModule)[];\n\n/**\n * Lazily loads `@intlayer/babel`, or `null` when it is not installed or too old\n * to expose the purge pipeline.\n */\nconst loadIntlayerBabel = (\n intlayerConfig: IntlayerConfig\n): IntlayerBabelModule | null => {\n try {\n const requireFunction =\n intlayerConfig.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 if (!hasEveryRequiredExport) return null;\n\n return intlayerBabel as IntlayerBabelModule;\n } catch {\n return null;\n }\n};\n\n/**\n * Whether the purge / minify pipeline can run at all, i.e. whether a usable\n * `@intlayer/babel` is resolvable from the project.\n *\n * Used by `withIntlayer` to keep the build report honest: announcing\n * `Dictionary minification enabled` while the pipeline cannot load would describe a\n * pass that never happens.\n */\nexport const getIsPurgePipelineAvailable = (\n intlayerConfig: IntlayerConfig\n): boolean => loadIntlayerBabel(intlayerConfig) !== null;\n\n/**\n * Runs the purge / minify pipeline and writes the resulting field-rename\n * tables to the cache file so every process of the build reads the same ones.\n */\nconst runPurgePipelineOnce = async (\n intlayerConfig: IntlayerConfig,\n configOptions: GetConfigurationOptions | undefined,\n dictionaries: Dictionary[] | undefined,\n fieldRenameMapFilePath: string\n): Promise<void> => {\n const appLogger = getAppLogger(intlayerConfig);\n\n const intlayerBabel = loadIntlayerBabel(intlayerConfig);\n\n if (!intlayerBabel) {\n // Not verbose: the build asked for purge / minify and is silently getting\n // neither, which is exactly the kind of thing a default build must report.\n appLogger(\n [\n 'Dictionary purge and minification are',\n colorize('disabled', ANSIColors.GREY_DARK),\n 'because',\n colorize('@intlayer/babel', ANSIColors.GREY_LIGHT),\n 'is missing or too old to expose the purge pipeline — install it in',\n 'this project to enable them.',\n ],\n { level: 'warn' }\n );\n return;\n }\n\n const {\n getPurgePluginOptions,\n runIntlayerPurgePipeline,\n serializeFieldRenameMap,\n } = intlayerBabel;\n\n // `runOnce` discards whatever this callback throws, so a pipeline failure\n // would otherwise leave the build with no dictionaries rewritten and no\n // explanation of why.\n let fieldRenameMap: FieldRenameMapByDictionaryKey;\n\n try {\n // The pipeline reports what it purged and minified through the intlayer\n // logger, matching the Vite build output.\n const pruneContext = runIntlayerPurgePipeline(\n getPurgePluginOptions({ configOptions, dictionaries })\n );\n\n fieldRenameMap = serializeFieldRenameMap(pruneContext);\n } catch (pipelineError) {\n appLogger(\n [\n 'Dictionary purge and minification',\n colorize('failed', ANSIColors.RED),\n '— the compiled dictionaries are left untouched.',\n pipelineError instanceof Error\n ? `(${pipelineError.message})`\n : String(pipelineError),\n ],\n { level: 'error' }\n );\n return;\n }\n\n await mkdir(dirname(fieldRenameMapFilePath), { recursive: true });\n await writeFile(\n fieldRenameMapFilePath,\n JSON.stringify(fieldRenameMap),\n 'utf-8'\n );\n};\n\n/** Reads the cached field-rename tables, or `{}` when none were written. */\nconst readFieldRenameMapFile = (\n fieldRenameMapFilePath: string\n): FieldRenameMapByDictionaryKey => {\n try {\n return JSON.parse(\n readFileSync(fieldRenameMapFilePath, 'utf-8')\n ) as FieldRenameMapByDictionaryKey;\n } catch {\n return {};\n }\n};\n\n/** Removes the cached field-rename tables, ignoring a missing file. */\nconst removeFieldRenameMapFile = (fieldRenameMapFilePath: string): void => {\n try {\n rmSync(fieldRenameMapFilePath, { force: true });\n } catch {\n // Nothing to clean up.\n }\n};\n\ntype PrepareSwcOptimizationParams = {\n /** Options forwarded to the intlayer configuration loader. */\n configOptions?: GetConfigurationOptions;\n /** Pre-loaded dictionaries, to avoid a second `getDictionaries` call. */\n dictionaries?: Dictionary[];\n /** Compat-adapter callers declared by the consuming plugin, if any. */\n swcExtraCallers?: SwcExtraCallerConfig[];\n /**\n * Whether the `@intlayer/swc` plugin is installed *and* the resolved Next.js\n * version can load it. False leaves the compiled dictionaries untouched.\n */\n isSwcPluginUsable: boolean;\n};\n\n/**\n * Prepares the parts of the build optimisation the `@intlayer/swc` plugin\n * cannot do itself, and returns the field-rename tables it needs.\n *\n * Removing unused content fields (`build.purge`) and assigning short field\n * aliases (`build.minify`) require reading every component source file and\n * rewriting the compiled dictionary JSON — file I/O and cross-file state that a\n * per-file Wasm transform has no access to. That analysis therefore runs here,\n * in Node, through `@intlayer/babel`; the plugin only receives the resulting\n * tables and rewrites the matching source accesses\n * (`content.title` → `content.a`).\n *\n * The work is coordinated by a sentinel file: Next.js loads `next.config.*` in\n * several processes per build, and running the minify pass twice would derive\n * the aliases from the already-renamed dictionaries. Processes that lose the\n * race read the tables the winner cached.\n *\n * @returns The field-rename tables, keyed by dictionary key. Empty when the\n * pipeline is disabled, unavailable, or renamed nothing.\n */\nexport const prepareSwcOptimization = async (\n intlayerConfig: IntlayerConfig,\n params: PrepareSwcOptimizationParams\n): Promise<FieldRenameMapByDictionaryKey> => {\n const { configOptions, dictionaries, swcExtraCallers, isSwcPluginUsable } =\n params;\n\n const fieldRenameMapFilePath = getCacheFilePath(\n intlayerConfig,\n FIELD_RENAME_MAP_FILE_NAME\n );\n\n // A stale file from an earlier build would rename source accesses that the\n // dictionaries no longer match.\n if (\n !getIsPurgePipelineEnabled(\n intlayerConfig,\n swcExtraCallers,\n isSwcPluginUsable\n )\n ) {\n removeFieldRenameMapFile(fieldRenameMapFilePath);\n return {};\n }\n\n await runOnce(\n getCacheFilePath(intlayerConfig, PURGE_SENTINEL_FILE_NAME),\n () =>\n runPurgePipelineOnce(\n intlayerConfig,\n configOptions,\n dictionaries,\n fieldRenameMapFilePath\n ),\n { cacheTimeoutMs: PURGE_CACHE_TIMEOUT_MS }\n );\n\n return readFieldRenameMapFile(fieldRenameMapFilePath);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"prepareSwcOptimization.mjs","names":[],"sources":["../../../src/server/prepareSwcOptimization.ts"],"sourcesContent":["import { readFileSync, rmSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport type {\n getPurgePluginOptions as GetPurgePluginOptions,\n runIntlayerPurgePipeline as RunIntlayerPurgePipeline,\n SerializedFieldRenameMap,\n serializeFieldRenameMap as SerializeFieldRenameMap,\n} from '@intlayer/babel';\nimport type { CallerDescriptor } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport type { GetConfigurationOptions } from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Field-rename tables keyed by dictionary key, forwarded to the\n * `@intlayer/swc` plugin's `fieldRenameMap` option.\n */\nexport type FieldRenameMapByDictionaryKey = Record<\n string,\n SerializedFieldRenameMap\n>;\n\n/** Verbosity forwarded to the `@intlayer/swc` plugin's `logLevel` option. */\nexport type SwcLogLevel = 'off' | 'info' | 'debug';\n\n/**\n * Subset of `@intlayer/babel` this module needs. The package is only an\n * optional runtime dependency, so it is required lazily and never imported at\n * module scope.\n */\ntype IntlayerBabelModule = {\n getPurgePluginOptions: typeof GetPurgePluginOptions;\n runIntlayerPurgePipeline: typeof RunIntlayerPurgePipeline;\n serializeFieldRenameMap: typeof SerializeFieldRenameMap;\n};\n\n/**\n * Opt-in to the SWC plugin's per-file tracing.\n *\n * The plugin transforms one file at a time with no cross-file state, so all it\n * can report is a line per file — hundreds of them on a real project, and with\n * no counterpart in the Vite build output. The purge and minify summaries that\n * `log.mode` does control are emitted by the pipeline itself, in Node; this\n * variable is purely a debugging aid on top.\n */\nconst SWC_LOG_LEVEL_ENV_VAR = 'INTLAYER_SWC_LOG_LEVEL';\n\n/** Sentinel coordinating the pipeline across the processes of one build. */\nconst PURGE_SENTINEL_FILE_NAME = 'intlayer-swc-purge.lock';\n\n/** Where the serialised field-rename tables are cached between processes. */\nconst FIELD_RENAME_MAP_FILE_NAME = 'swc-field-rename-map.json';\n\n/**\n * Next.js evaluates `next.config.*` in the main build process and again in each\n * Turbopack/webpack worker. The dictionary rewrite must happen exactly once —\n * a second run would derive the short aliases from the already-renamed JSON —\n * so the sentinel window has to cover a whole build startup.\n */\nconst PURGE_CACHE_TIMEOUT_MS = 30 * 1000;\n\n/** Absolute path of a file in the intlayer cache directory. */\nconst getCacheFilePath = (\n intlayerConfig: IntlayerConfig,\n fileName: string\n): string =>\n join(intlayerConfig.system.baseDir, '.intlayer', 'cache', fileName);\n\n/**\n * Resolves the verbosity the `@intlayer/swc` plugin should report at.\n *\n * Off unless {@link SWC_LOG_LEVEL_ENV_VAR} asks for tracing: `log.mode` governs\n * the purge and minify reporting, which the pipeline emits in Node so the\n * Next.js build reads the same as the Vite one.\n */\nexport const resolveSwcLogLevel = (\n intlayerConfig: IntlayerConfig\n): SwcLogLevel => {\n if (intlayerConfig.log.mode === 'disabled') return 'off';\n\n const requestedLogLevel = process.env[SWC_LOG_LEVEL_ENV_VAR];\n\n return requestedLogLevel === 'info' || requestedLogLevel === 'debug'\n ? requestedLogLevel\n : 'off';\n};\n\n/**\n * Whether the purge / minify pipeline should run for this build.\n *\n * Compat-adapter callers do not disable it: their descriptors reach the usage\n * analyser intact (`compatCallers`), which records the dictionaries they read\n * and marks those as unrenamable — so purging stays field-accurate and the\n * minify step leaves them alone.\n */\nconst getIsPurgePipelineEnabled = (\n intlayerConfig: IntlayerConfig,\n isSwcPluginUsable: boolean\n): boolean => {\n const { purge, minify, optimize } = intlayerConfig.build;\n\n if (optimize === false) return false;\n if (!purge && !minify) return false;\n\n // The pipeline rewrites the compiled dictionaries in place — dropping unused\n // fields and renaming the rest to short aliases. Only the SWC plugin rewrites\n // the matching source accesses, so running this without it would ship\n // dictionaries whose keys no longer match the code reading them.\n if (!isSwcPluginUsable) return false;\n\n // `editor.enabled` is deliberately not checked here: it only stands the\n // field-rename step down — inside the pipeline, and with its own explanation\n // — the same way the Vite build does. Purging still runs, and the rename map\n // the SWC plugin receives comes back empty, so source and JSON stay in sync.\n\n return true;\n};\n\n/**\n * Exports this module needs from `@intlayer/babel`. Checked one by one so a\n * version predating the purge pipeline is rejected like a missing package,\n * instead of failing later with `runIntlayerPurgePipeline is not a function`.\n */\nconst REQUIRED_BABEL_EXPORTS = [\n 'getPurgePluginOptions',\n 'runIntlayerPurgePipeline',\n 'serializeFieldRenameMap',\n] as const satisfies readonly (keyof IntlayerBabelModule)[];\n\n/**\n * Lazily loads `@intlayer/babel`, or `null` when it is not installed or too old\n * to expose the purge pipeline.\n */\nconst loadIntlayerBabel = (\n intlayerConfig: IntlayerConfig\n): IntlayerBabelModule | null => {\n try {\n const requireFunction =\n intlayerConfig.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 if (!hasEveryRequiredExport) return null;\n\n return intlayerBabel as IntlayerBabelModule;\n } catch {\n return null;\n }\n};\n\n/**\n * Whether the purge / minify pipeline can run at all, i.e. whether a usable\n * `@intlayer/babel` is resolvable from the project.\n *\n * Used by `withIntlayer` to keep the build report honest: announcing\n * `Dictionary minification enabled` while the pipeline cannot load would describe a\n * pass that never happens.\n */\nexport const getIsPurgePipelineAvailable = (\n intlayerConfig: IntlayerConfig\n): boolean => loadIntlayerBabel(intlayerConfig) !== null;\n\n/**\n * Runs the purge / minify pipeline and writes the resulting field-rename\n * tables to the cache file so every process of the build reads the same ones.\n */\nconst runPurgePipelineOnce = async (\n intlayerConfig: IntlayerConfig,\n configOptions: GetConfigurationOptions | undefined,\n dictionaries: Dictionary[] | undefined,\n compatCallers: CallerDescriptor[] | undefined,\n fieldRenameMapFilePath: string\n): Promise<void> => {\n const appLogger = getAppLogger(intlayerConfig);\n\n const intlayerBabel = loadIntlayerBabel(intlayerConfig);\n\n if (!intlayerBabel) {\n // Not verbose: the build asked for purge / minify and is silently getting\n // neither, which is exactly the kind of thing a default build must report.\n appLogger(\n [\n 'Dictionary purge and minification are',\n colorize('disabled', ANSIColors.GREY_DARK),\n 'because',\n colorize('@intlayer/babel', ANSIColors.GREY_LIGHT),\n 'is missing or too old to expose the purge pipeline — install it in',\n 'this project to enable them.',\n ],\n { level: 'warn' }\n );\n return;\n }\n\n const {\n getPurgePluginOptions,\n runIntlayerPurgePipeline,\n serializeFieldRenameMap,\n } = intlayerBabel;\n\n // `runOnce` discards whatever this callback throws, so a pipeline failure\n // would otherwise leave the build with no dictionaries rewritten and no\n // explanation of why.\n let fieldRenameMap: FieldRenameMapByDictionaryKey;\n\n try {\n // The pipeline reports what it purged and minified through the intlayer\n // logger, matching the Vite build output.\n const pruneContext = runIntlayerPurgePipeline(\n getPurgePluginOptions({\n configOptions,\n dictionaries,\n // Without them the analyser would not recognise `useTranslation(...)`\n // & co. and would purge the fields those call sites read.\n overrides: compatCallers?.length ? { compatCallers } : undefined,\n })\n );\n\n fieldRenameMap = serializeFieldRenameMap(pruneContext);\n } catch (pipelineError) {\n appLogger(\n [\n 'Dictionary purge and minification',\n colorize('failed', ANSIColors.RED),\n '— the compiled dictionaries are left untouched.',\n pipelineError instanceof Error\n ? `(${pipelineError.message})`\n : String(pipelineError),\n ],\n { level: 'error' }\n );\n return;\n }\n\n await mkdir(dirname(fieldRenameMapFilePath), { recursive: true });\n await writeFile(\n fieldRenameMapFilePath,\n JSON.stringify(fieldRenameMap),\n 'utf-8'\n );\n};\n\n/** Reads the cached field-rename tables, or `{}` when none were written. */\nconst readFieldRenameMapFile = (\n fieldRenameMapFilePath: string\n): FieldRenameMapByDictionaryKey => {\n try {\n return JSON.parse(\n readFileSync(fieldRenameMapFilePath, 'utf-8')\n ) as FieldRenameMapByDictionaryKey;\n } catch {\n return {};\n }\n};\n\n/** Removes the cached field-rename tables, ignoring a missing file. */\nconst removeFieldRenameMapFile = (fieldRenameMapFilePath: string): void => {\n try {\n rmSync(fieldRenameMapFilePath, { force: true });\n } catch {\n // Nothing to clean up.\n }\n};\n\ntype PrepareSwcOptimizationParams = {\n /** Options forwarded to the intlayer configuration loader. */\n configOptions?: GetConfigurationOptions;\n /** Pre-loaded dictionaries, to avoid a second `getDictionaries` call. */\n dictionaries?: Dictionary[];\n /** Compat-adapter callers declared by the consuming plugin, if any. */\n compatCallers?: CallerDescriptor[];\n /**\n * Whether the `@intlayer/swc` plugin is installed *and* the resolved Next.js\n * version can load it. False leaves the compiled dictionaries untouched.\n */\n isSwcPluginUsable: boolean;\n};\n\n/**\n * Prepares the parts of the build optimisation the `@intlayer/swc` plugin\n * cannot do itself, and returns the field-rename tables it needs.\n *\n * Removing unused content fields (`build.purge`) and assigning short field\n * aliases (`build.minify`) require reading every component source file and\n * rewriting the compiled dictionary JSON — file I/O and cross-file state that a\n * per-file Wasm transform has no access to. That analysis therefore runs here,\n * in Node, through `@intlayer/babel`; the plugin only receives the resulting\n * tables and rewrites the matching source accesses\n * (`content.title` → `content.a`).\n *\n * The work is coordinated by a sentinel file: Next.js loads `next.config.*` in\n * several processes per build, and running the minify pass twice would derive\n * the aliases from the already-renamed dictionaries. Processes that lose the\n * race read the tables the winner cached.\n *\n * @returns The field-rename tables, keyed by dictionary key. Empty when the\n * pipeline is disabled, unavailable, or renamed nothing.\n */\nexport const prepareSwcOptimization = async (\n intlayerConfig: IntlayerConfig,\n params: PrepareSwcOptimizationParams\n): Promise<FieldRenameMapByDictionaryKey> => {\n const { configOptions, dictionaries, compatCallers, isSwcPluginUsable } =\n params;\n\n const fieldRenameMapFilePath = getCacheFilePath(\n intlayerConfig,\n FIELD_RENAME_MAP_FILE_NAME\n );\n\n // A stale file from an earlier build would rename source accesses that the\n // dictionaries no longer match.\n if (!getIsPurgePipelineEnabled(intlayerConfig, isSwcPluginUsable)) {\n removeFieldRenameMapFile(fieldRenameMapFilePath);\n return {};\n }\n\n await runOnce(\n getCacheFilePath(intlayerConfig, PURGE_SENTINEL_FILE_NAME),\n () =>\n runPurgePipelineOnce(\n intlayerConfig,\n configOptions,\n dictionaries,\n compatCallers,\n fieldRenameMapFilePath\n ),\n { cacheTimeoutMs: PURGE_CACHE_TIMEOUT_MS }\n );\n\n return readFieldRenameMapFile(fieldRenameMapFilePath);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkDA,MAAM,wBAAwB;;AAG9B,MAAM,2BAA2B;;AAGjC,MAAM,6BAA6B;;;;;;;AAQnC,MAAM,yBAAyB;;AAG/B,MAAM,oBACJ,gBACA,aAEA,KAAK,eAAe,OAAO,SAAS,aAAa,SAAS,QAAQ;;;;;;;;AASpE,MAAa,sBACX,mBACgB;CAChB,IAAI,eAAe,IAAI,SAAS,YAAY,OAAO;CAEnD,MAAM,oBAAoB,QAAQ,IAAI;CAEtC,OAAO,sBAAsB,UAAU,sBAAsB,UACzD,oBACA;AACN;;;;;;;;;AAUA,MAAM,6BACJ,gBACA,sBACY;CACZ,MAAM,EAAE,OAAO,QAAQ,aAAa,eAAe;CAEnD,IAAI,aAAa,OAAO,OAAO;CAC/B,IAAI,CAAC,SAAS,CAAC,QAAQ,OAAO;CAM9B,IAAI,CAAC,mBAAmB,OAAO;CAO/B,OAAO;AACT;;;;;;AAOA,MAAM,yBAAyB;CAC7B;CACA;CACA;AACF;;;;;AAMA,MAAM,qBACJ,mBAC+B;CAC/B,IAAI;EAIF,MAAM,iBAFJ,eAAe,OAAO,WAAW,kBAAkB,EAEhB,CACnC,iBACF;EAMA,IAAI,CAJ2B,uBAAuB,OACnD,eAAe,OAAO,gBAAgB,gBAAgB,UAG/B,GAAG,OAAO;EAEpC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;AAUA,MAAa,+BACX,mBACY,kBAAkB,cAAc,MAAM;;;;;AAMpD,MAAM,uBAAuB,OAC3B,gBACA,eACA,cACA,eACA,2BACkB;CAClB,MAAM,YAAY,aAAa,cAAc;CAE7C,MAAM,gBAAgB,kBAAkB,cAAc;CAEtD,IAAI,CAAC,eAAe;EAGlB,UACE;GACE;GACA,SAAS,YAAY,WAAW,SAAS;GACzC;GACA,SAAS,mBAAmB,WAAW,UAAU;GACjD;GACA;EACF,GACA,EAAE,OAAO,OAAO,CAClB;EACA;CACF;CAEA,MAAM,EACJ,uBACA,0BACA,4BACE;CAKJ,IAAI;CAEJ,IAAI;EAaF,iBAAiB,wBAVI,yBACnB,sBAAsB;GACpB;GACA;GAGA,WAAW,eAAe,SAAS,EAAE,cAAc,IAAI;EACzD,CAAC,CAGiD,CAAC;CACvD,SAAS,eAAe;EACtB,UACE;GACE;GACA,SAAS,UAAU,WAAW,GAAG;GACjC;GACA,yBAAyB,QACrB,IAAI,cAAc,QAAQ,KAC1B,OAAO,aAAa;EAC1B,GACA,EAAE,OAAO,QAAQ,CACnB;EACA;CACF;CAEA,MAAM,MAAM,QAAQ,sBAAsB,GAAG,EAAE,WAAW,KAAK,CAAC;CAChE,MAAM,UACJ,wBACA,KAAK,UAAU,cAAc,GAC7B,OACF;AACF;;AAGA,MAAM,0BACJ,2BACkC;CAClC,IAAI;EACF,OAAO,KAAK,MACV,aAAa,wBAAwB,OAAO,CAC9C;CACF,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;AAGA,MAAM,4BAA4B,2BAAyC;CACzE,IAAI;EACF,OAAO,wBAAwB,EAAE,OAAO,KAAK,CAAC;CAChD,QAAQ,CAER;AACF;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,yBAAyB,OACpC,gBACA,WAC2C;CAC3C,MAAM,EAAE,eAAe,cAAc,eAAe,sBAClD;CAEF,MAAM,yBAAyB,iBAC7B,gBACA,0BACF;CAIA,IAAI,CAAC,0BAA0B,gBAAgB,iBAAiB,GAAG;EACjE,yBAAyB,sBAAsB;EAC/C,OAAO,CAAC;CACV;CAEA,MAAM,QACJ,iBAAiB,gBAAgB,wBAAwB,SAEvD,qBACE,gBACA,eACA,cACA,eACA,sBACF,GACF,EAAE,gBAAgB,uBAAuB,CAC3C;CAEA,OAAO,uBAAuB,sBAAsB;AACtD"}
@@ -0,0 +1,90 @@
1
+ import { getAppLogger } from "@intlayer/config/logger";
2
+ import { acquireContentWatcherLock, getCliContentWatcherLabel, getContentWatcherOwner, reportRedundantContentWatcher } from "@intlayer/engine/utils";
3
+
4
+ //#region src/server/startContentWatcher.ts
5
+ /**
6
+ * Release from which `withIntlayer` watches the content declarations on
7
+ * Turbopack, making `intlayer watch --with` redundant on Next.js.
8
+ */
9
+ const SELF_WATCHING_RELEASE = "9.5.0";
10
+ /**
11
+ * How often a process that lost the ownership race checks whether the owner is
12
+ * gone. Next.js's short-lived config processes release the lock when they exit,
13
+ * so the long-lived dev server has to be able to pick it up afterwards.
14
+ */
15
+ const TAKEOVER_POLL_INTERVAL_MS = 5e3;
16
+ /** Set once the watcher is running in this process. */
17
+ let isWatching = false;
18
+ /**
19
+ * Set while an ownership attempt is in flight.
20
+ *
21
+ * Taking the lock is asynchronous, and `next.config.*` is evaluated several
22
+ * times per command — without this, those evaluations would pile up concurrent
23
+ * attempts, each awaiting the same lock.
24
+ */
25
+ let isClaimInFlight = false;
26
+ /** Reports a redundant `intlayer watch` running alongside this dev server. */
27
+ const reportRedundantCliWatcher = (configuration, cliWatcherLabel) => reportRedundantContentWatcher(configuration, {
28
+ cliLabel: cliWatcherLabel,
29
+ bundlerLabel: "next-intlayer",
30
+ since: SELF_WATCHING_RELEASE
31
+ });
32
+ /**
33
+ * Starts the content declaration watcher for a Turbopack dev server.
34
+ *
35
+ * On webpack this is done by `IntlayerPlugin`, which Turbopack cannot run — so
36
+ * before {@link SELF_WATCHING_RELEASE} a Turbopack app had to be started
37
+ * through `intlayer watch --with next dev` for `.content` edits to rebuild
38
+ * `.intlayer`.
39
+ *
40
+ * Stands down — with an explanation — when that CLI watcher is running anyway,
41
+ * since two watchers would rebuild the same dictionaries at the same time.
42
+ * Otherwise starting is idempotent: the first process to take the lock watches,
43
+ * and the others retry in the background so a short-lived config process
44
+ * handing the lock back does not leave the session unwatched.
45
+ *
46
+ * @param configuration - The resolved Intlayer configuration.
47
+ */
48
+ const claimAndWatch = async (configuration) => {
49
+ const appLogger = getAppLogger(configuration);
50
+ if (!await acquireContentWatcherLock(configuration, {
51
+ source: "bundler",
52
+ label: "next-intlayer",
53
+ since: SELF_WATCHING_RELEASE
54
+ })) {
55
+ const owner = await getContentWatcherOwner(configuration);
56
+ if (owner?.source === "cli") {
57
+ reportRedundantCliWatcher(configuration, owner.label);
58
+ return;
59
+ }
60
+ setTimeout(() => {
61
+ startContentWatcher(configuration);
62
+ }, TAKEOVER_POLL_INTERVAL_MS).unref?.();
63
+ return;
64
+ }
65
+ isWatching = true;
66
+ try {
67
+ const { watch } = await import("@intlayer/engine/watcher");
68
+ await watch({ configuration });
69
+ } catch (error) {
70
+ isWatching = false;
71
+ appLogger(["Failed to watch Intlayer content declarations:", error], { level: "error" });
72
+ }
73
+ };
74
+ const startContentWatcher = (configuration) => {
75
+ if (isWatching || isClaimInFlight) return;
76
+ if (!configuration.content.watch) return;
77
+ const cliWatcherLabel = getCliContentWatcherLabel();
78
+ if (cliWatcherLabel) {
79
+ reportRedundantCliWatcher(configuration, cliWatcherLabel);
80
+ return;
81
+ }
82
+ isClaimInFlight = true;
83
+ claimAndWatch(configuration).finally(() => {
84
+ isClaimInFlight = false;
85
+ });
86
+ };
87
+
88
+ //#endregion
89
+ export { startContentWatcher };
90
+ //# sourceMappingURL=startContentWatcher.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startContentWatcher.mjs","names":[],"sources":["../../../src/server/startContentWatcher.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config/logger';\nimport {\n acquireContentWatcherLock,\n getCliContentWatcherLabel,\n getContentWatcherOwner,\n reportRedundantContentWatcher,\n} from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Release from which `withIntlayer` watches the content declarations on\n * Turbopack, making `intlayer watch --with` redundant on Next.js.\n */\nconst SELF_WATCHING_RELEASE = '9.5.0';\n\n/**\n * How often a process that lost the ownership race checks whether the owner is\n * gone. Next.js's short-lived config processes release the lock when they exit,\n * so the long-lived dev server has to be able to pick it up afterwards.\n */\nconst TAKEOVER_POLL_INTERVAL_MS = 5000;\n\n/** Set once the watcher is running in this process. */\nlet isWatching = false;\n\n/**\n * Set while an ownership attempt is in flight.\n *\n * Taking the lock is asynchronous, and `next.config.*` is evaluated several\n * times per command — without this, those evaluations would pile up concurrent\n * attempts, each awaiting the same lock.\n */\nlet isClaimInFlight = false;\n\n/** Reports a redundant `intlayer watch` running alongside this dev server. */\nconst reportRedundantCliWatcher = (\n configuration: IntlayerConfig,\n cliWatcherLabel: string\n): void =>\n reportRedundantContentWatcher(configuration, {\n cliLabel: cliWatcherLabel,\n bundlerLabel: 'next-intlayer',\n since: SELF_WATCHING_RELEASE,\n });\n\n/**\n * Starts the content declaration watcher for a Turbopack dev server.\n *\n * On webpack this is done by `IntlayerPlugin`, which Turbopack cannot run — so\n * before {@link SELF_WATCHING_RELEASE} a Turbopack app had to be started\n * through `intlayer watch --with next dev` for `.content` edits to rebuild\n * `.intlayer`.\n *\n * Stands down — with an explanation — when that CLI watcher is running anyway,\n * since two watchers would rebuild the same dictionaries at the same time.\n * Otherwise starting is idempotent: the first process to take the lock watches,\n * and the others retry in the background so a short-lived config process\n * handing the lock back does not leave the session unwatched.\n *\n * @param configuration - The resolved Intlayer configuration.\n */\nconst claimAndWatch = async (configuration: IntlayerConfig): Promise<void> => {\n const appLogger = getAppLogger(configuration);\n\n const hasAcquiredLock = await acquireContentWatcherLock(configuration, {\n source: 'bundler',\n label: 'next-intlayer',\n since: SELF_WATCHING_RELEASE,\n });\n\n if (!hasAcquiredLock) {\n // A CLI watcher started from another terminal is just as redundant as one\n // wrapping this command, and worth the same explanation.\n const owner = await getContentWatcherOwner(configuration);\n\n if (owner?.source === 'cli') {\n reportRedundantCliWatcher(configuration, owner.label);\n return;\n }\n\n const retryTimer = setTimeout(() => {\n startContentWatcher(configuration);\n }, TAKEOVER_POLL_INTERVAL_MS);\n\n // Unreferenced so a process whose only remaining work is this retry can\n // still exit.\n retryTimer.unref?.();\n\n return;\n }\n\n isWatching = true;\n\n try {\n // Imported lazily: `@intlayer/engine/watcher` pulls in `@parcel/watcher`, a\n // native module that has no business being loaded during a production\n // build. `withIntlayer` already awaited `prepareIntlayer`, so the watcher\n // only has to pick up the changes that follow.\n const { watch } = await import('@intlayer/engine/watcher');\n\n await watch({ configuration });\n } catch (error) {\n isWatching = false;\n\n appLogger(['Failed to watch Intlayer content declarations:', error], {\n level: 'error',\n });\n }\n};\n\nexport const startContentWatcher = (configuration: IntlayerConfig): void => {\n if (isWatching || isClaimInFlight) return;\n if (!configuration.content.watch) return;\n\n // Spawned by `intlayer watch --with`: the CLI watcher covers the project, and\n // this is known from the environment alone — no need to touch the lock.\n const cliWatcherLabel = getCliContentWatcherLabel();\n\n if (cliWatcherLabel) {\n reportRedundantCliWatcher(configuration, cliWatcherLabel);\n return;\n }\n\n isClaimInFlight = true;\n\n // Deliberately not awaited: `withIntlayerSync` is synchronous, and the dev\n // server must not wait on the watcher to start serving.\n claimAndWatch(configuration).finally(() => {\n isClaimInFlight = false;\n });\n};\n"],"mappings":";;;;;;;;AAaA,MAAM,wBAAwB;;;;;;AAO9B,MAAM,4BAA4B;;AAGlC,IAAI,aAAa;;;;;;;;AASjB,IAAI,kBAAkB;;AAGtB,MAAM,6BACJ,eACA,oBAEA,8BAA8B,eAAe;CAC3C,UAAU;CACV,cAAc;CACd,OAAO;AACT,CAAC;;;;;;;;;;;;;;;;;AAkBH,MAAM,gBAAgB,OAAO,kBAAiD;CAC5E,MAAM,YAAY,aAAa,aAAa;CAQ5C,IAAI,CAAC,MANyB,0BAA0B,eAAe;EACrE,QAAQ;EACR,OAAO;EACP,OAAO;CACT,CAAC,GAEqB;EAGpB,MAAM,QAAQ,MAAM,uBAAuB,aAAa;EAExD,IAAI,OAAO,WAAW,OAAO;GAC3B,0BAA0B,eAAe,MAAM,KAAK;GACpD;EACF;EAQA,AANmB,iBAAiB;GAClC,oBAAoB,aAAa;EACnC,GAAG,yBAIM,CAAC,CAAC,QAAQ;EAEnB;CACF;CAEA,aAAa;CAEb,IAAI;EAKF,MAAM,EAAE,UAAU,MAAM,OAAO;EAE/B,MAAM,MAAM,EAAE,cAAc,CAAC;CAC/B,SAAS,OAAO;EACd,aAAa;EAEb,UAAU,CAAC,kDAAkD,KAAK,GAAG,EACnE,OAAO,QACT,CAAC;CACH;AACF;AAEA,MAAa,uBAAuB,kBAAwC;CAC1E,IAAI,cAAc,iBAAiB;CACnC,IAAI,CAAC,cAAc,QAAQ,OAAO;CAIlC,MAAM,kBAAkB,0BAA0B;CAElD,IAAI,iBAAiB;EACnB,0BAA0B,eAAe,eAAe;EACxD;CACF;CAEA,kBAAkB;CAIlB,cAAc,aAAa,CAAC,CAAC,cAAc;EACzC,kBAAkB;CACpB,CAAC;AACH"}
@@ -1,17 +1,19 @@
1
1
  import { getIsPurgePipelineAvailable, prepareSwcOptimization, resolveSwcLogLevel } from "./prepareSwcOptimization.mjs";
2
+ import { startContentWatcher } from "./startContentWatcher.mjs";
2
3
  import { MINIMUM_SWC_PLUGIN_NEXT_VERSION, getIsSwcPluginSupported } from "./swcPluginCompatibility.mjs";
3
- import { IMPORT_MODE } from "@intlayer/config/defaultValues";
4
- import { colorize, getAppLogger } from "@intlayer/config/logger";
5
4
  import { join, relative, resolve } from "node:path";
6
5
  import * as ANSIColors from "@intlayer/config/colors";
7
- import { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar, formatOptimizedNestingEnvVar, getConfigEnvVars } from "@intlayer/config/envVars";
6
+ import { colorize, getAppLogger } from "@intlayer/config/logger";
8
7
  import { getConfiguration } from "@intlayer/config/node";
9
8
  import { compareVersions, getAlias, getHasDictionarySelector, getProjectRequire, getUnusedNodeTypes, normalizePath } from "@intlayer/config/utils";
9
+ import { buildComponentFilesList, runOnce } from "@intlayer/engine/utils";
10
+ import { COMPILER_ENABLED, IMPORT_MODE } from "@intlayer/config/defaultValues";
11
+ import { toSwcExtraCallers } from "@intlayer/config/callers";
12
+ import { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar, formatOptimizedNestingEnvVar, getConfigEnvVars } from "@intlayer/config/envVars";
10
13
  import { getNestedDictionaryGraph } from "@intlayer/core/dictionaryManipulator";
11
14
  import { getDictionaries } from "@intlayer/dictionaries-entry";
12
15
  import { prepareIntlayer } from "@intlayer/engine/build";
13
16
  import { logConfigDetails } from "@intlayer/engine/cli";
14
- import { buildComponentFilesList, runOnce } from "@intlayer/engine/utils";
15
17
  import { IntlayerPlugin } from "@intlayer/webpack";
16
18
  import { defu } from "defu";
17
19
  import nextPackageJSON from "next/package.json" with { type: "json" };
@@ -61,7 +63,70 @@ const resolvePluginPath = (pluginPath, intlayerConfig, isTurbopackEnabled) => {
61
63
  if (isTurbopackEnabled) return normalizePath(`./${relative(process.cwd(), pluginPathResolved)}`);
62
64
  return pluginPathResolved;
63
65
  };
64
- const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, isDevCommand, isGteNext13, isSwcPluginSupported, nextVersion, swcExtraCallers, fieldRenameMap }) => {
66
+ /**
67
+ * Extensions the extraction loader is registered for.
68
+ *
69
+ * The compiler reads its content out of JSX — element text and the
70
+ * translatable attributes — so a file with no JSX in it has nothing to give,
71
+ * and `*.ts` is left out. `*.js` is in because a plain-JavaScript Next.js app
72
+ * writes its components there.
73
+ */
74
+ const EXTRACTOR_LOADER_EXTENSIONS = [
75
+ "tsx",
76
+ "jsx",
77
+ "js"
78
+ ];
79
+ /**
80
+ * The subset safe to register as a Turbopack rule on any Next.js version.
81
+ *
82
+ * Turbopack rules match every module it processes, dependencies included, and
83
+ * only Next.js 16 can express "skip `node_modules`" (see
84
+ * {@link TURBOPACK_PROJECT_FILES_CONDITION}). Below that, `*.js` would hand
85
+ * every dependency file to a Node loader worker, so it is left out rather than
86
+ * made to cost a cold dev start.
87
+ */
88
+ const TURBOPACK_ALWAYS_SAFE_EXTENSIONS = ["tsx", "jsx"];
89
+ /**
90
+ * Restricts a Turbopack rule to the project's own files. `foreign` is
91
+ * Turbopack's builtin condition for a module inside `node_modules`.
92
+ *
93
+ * Only understood from Next.js 16 on — earlier releases carry no `condition`
94
+ * field on a rule at all.
95
+ */
96
+ const TURBOPACK_PROJECT_FILES_CONDITION = { not: "foreign" };
97
+ /**
98
+ * Whether the Intlayer compiler should extract content for this command.
99
+ *
100
+ * Mirrors `getExtractPluginOptions`, which the loader re-evaluates on its side:
101
+ * this is only about not registering a loader that would do nothing.
102
+ */
103
+ const getIsCompilerEnabled = (intlayerConfig, isDevCommand) => {
104
+ const enabled = intlayerConfig.compiler?.enabled ?? COMPILER_ENABLED;
105
+ if (enabled === "build-only") return !isDevCommand;
106
+ return enabled !== false;
107
+ };
108
+ /**
109
+ * Describes the extraction loader for both bundlers, or `null` when the
110
+ * compiler is off or `@intlayer/babel` is not installed.
111
+ *
112
+ * The loader replaces the `babel.config.js` the compiler used to need on
113
+ * Next.js: Turbopack never reads a Babel config, and on webpack the mere
114
+ * presence of one opts the whole project out of SWC — including the
115
+ * `@intlayer/swc` optimize pass.
116
+ */
117
+ const getExtractorLoader = (intlayerConfig, isTurbopackEnabled, isDevCommand) => {
118
+ if (!getIsCompilerEnabled(intlayerConfig, isDevCommand)) return null;
119
+ if (!getIsBabelExtractPluginAvailable(intlayerConfig)) return null;
120
+ try {
121
+ return {
122
+ loaderPath: resolvePluginPath("next-intlayer/extractor-loader", intlayerConfig, isTurbopackEnabled),
123
+ mode: isDevCommand ? "dev" : "build"
124
+ };
125
+ } catch {
126
+ return null;
127
+ }
128
+ };
129
+ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, isDevCommand, isGteNext13, isSwcPluginSupported, nextVersion, compatCallers, fieldRenameMap }) => {
65
130
  const { optimize, minify, purge } = intlayerConfig.build;
66
131
  const importMode = intlayerConfig.build.importMode ?? intlayerConfig.dictionary?.importMode;
67
132
  const { dictionariesDir, unmergedDictionariesDir, dynamicDictionariesDir, fetchDictionariesDir, mainDir } = intlayerConfig.system;
@@ -87,7 +152,7 @@ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, is
87
152
  colorize(importMode ?? IMPORT_MODE, ANSIColors.BLUE),
88
153
  colorize(`)`, ANSIColors.GREY_DARK)
89
154
  ]);
90
- const isPurgePipelineEnabled = !swcExtraCallers?.length && getIsPurgePipelineAvailable(intlayerConfig);
155
+ const isPurgePipelineEnabled = getIsPurgePipelineAvailable(intlayerConfig);
91
156
  if (isPurgePipelineEnabled && minify) logger(`Dictionary minification ${colorize("enabled", ANSIColors.GREEN)}`);
92
157
  if (isPurgePipelineEnabled && purge) logger(`Dictionary purge unused keys ${colorize("enabled", ANSIColors.GREEN)}`);
93
158
  } else logger([
@@ -134,7 +199,7 @@ const getPruneConfig = ({ intlayerConfig, isBuildCommand, isTurbopackEnabled, is
134
199
  replaceDictionaryEntry: true,
135
200
  nestingDictionaryKeys,
136
201
  dictionaryModeMap,
137
- extraCallers: swcExtraCallers ?? [],
202
+ extraCallers: toSwcExtraCallers(compatCallers ?? []),
138
203
  fieldRenameMap: fieldRenameMap ?? {},
139
204
  logLevel: resolveSwcLogLevel(intlayerConfig)
140
205
  }]] } };
@@ -199,15 +264,26 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
199
264
  const isTurbopackEnabled = configOptions?.enableTurbopack ?? isTurbopackEnabledFromCommand;
200
265
  if (isTurbopackEnabled && typeof nextConfig.webpack !== "undefined") appLogger("Turbopack is enabled but a custom webpack config is present. It will be ignored.");
201
266
  const { isBuildCommand, isDevCommand } = getCommandsEvent();
267
+ const extractorLoader = getExtractorLoader(intlayerConfig, isTurbopackEnabled ?? false, isDevCommand);
268
+ if (isTurbopackEnabled && isDevCommand) startContentWatcher(intlayerConfig);
202
269
  const turboConfig = {
203
270
  resolveAlias: getAlias({
204
271
  configuration: intlayerConfig,
205
272
  formatter: (value) => `./${value}`
206
273
  }),
207
- rules: { "*.node": {
208
- as: "*.node",
209
- loaders: ["node-loader"]
210
- } }
274
+ rules: {
275
+ "*.node": {
276
+ as: "*.node",
277
+ loaders: ["node-loader"]
278
+ },
279
+ ...extractorLoader ? Object.fromEntries((isGteNext16 ? EXTRACTOR_LOADER_EXTENSIONS : TURBOPACK_ALWAYS_SAFE_EXTENSIONS).map((extension) => [`*.${extension}`, {
280
+ loaders: [{
281
+ loader: extractorLoader.loaderPath,
282
+ options: { mode: extractorLoader.mode }
283
+ }],
284
+ ...isGteNext16 ? { condition: TURBOPACK_PROJECT_FILES_CONDITION } : {}
285
+ }])) : {}
286
+ }
211
287
  };
212
288
  const serverExternalPackages = [
213
289
  "esbuild",
@@ -285,6 +361,15 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
285
361
  test: /\.node$/,
286
362
  loader: "node-loader"
287
363
  });
364
+ if (extractorLoader) config.module.rules.push({
365
+ test: new RegExp(`\\.(${EXTRACTOR_LOADER_EXTENSIONS.join("|")})$`),
366
+ exclude: /node_modules/,
367
+ enforce: "pre",
368
+ use: [{
369
+ loader: extractorLoader.loaderPath,
370
+ options: { mode: extractorLoader.mode }
371
+ }]
372
+ });
288
373
  config.resolve.alias = {
289
374
  ...config.resolve.alias,
290
375
  ...getAlias({
@@ -306,7 +391,7 @@ const withIntlayerSync = (nextConfig = {}, configOptions) => {
306
391
  isGteNext13,
307
392
  isSwcPluginSupported,
308
393
  nextVersion,
309
- swcExtraCallers: configOptions?.swcExtraCallers,
394
+ compatCallers: configOptions?.compatCallers,
310
395
  fieldRenameMap: configOptions?.fieldRenameMap
311
396
  });
312
397
  const intlayerNextConfig = defu(getNewConfig(), pruneConfig);
@@ -341,7 +426,7 @@ const withIntlayer = async (nextConfig = {}, configOptions) => {
341
426
  const { isSwcPluginSupported } = getNextVersionFlags(intlayerConfig);
342
427
  const fieldRenameMap = isBuildCommand ? await prepareSwcOptimization(intlayerConfig, {
343
428
  configOptions: resolvedConfigOptions,
344
- swcExtraCallers: configOptions?.swcExtraCallers,
429
+ compatCallers: configOptions?.compatCallers,
345
430
  isSwcPluginUsable: isSwcPluginSupported && getIsSwcPluginAvailable(intlayerConfig)
346
431
  }) : {};
347
432
  const nextConfigResolved = await nextConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"withIntlayer.mjs","names":[],"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.mjs","names":[],"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 { 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 { 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 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 // 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 // Turbopack cannot run `IntlayerPlugin`, which is what starts the content\n // watcher on webpack. Without this the dev server had to be wrapped in\n // `intlayer watch --with next dev` for a `.content` edit to reach `.intlayer`.\n if (isTurbopackEnabled && 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 // 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 // `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 // 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 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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"}
@@ -1,3 +1,4 @@
1
+ import "./pruneContext.js";
1
2
  import "./babel-plugin-intlayer-usage-analyzer.js";
2
3
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+core@8.0.1/node_modules/@babel/core/lib/index.js";
3
4
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+types@8.0.4/node_modules/@babel/types/lib/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-field-rename.d.ts","names":[],"sources":["../../../../../../../@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts"],"mappings":";;;;;;;;;;YAuDY;;EAEV;;EAEA,UAAU;;;YAGA,2BAA2B,eAAe"}
1
+ {"version":3,"file":"babel-plugin-intlayer-field-rename.d.ts","names":[],"sources":["../../../../../../../@intlayer/babel/dist/types/babel-plugin-intlayer-field-rename.d.ts"],"mappings":";;;;;;;;;;;YAwDY;;EAEV;;EAEA,UAAU;;;YAGA,2BAA2B,eAAe"}
@@ -1,3 +1,3 @@
1
- import "@intlayer/config/callers";
1
+ import { CallerDescriptor } from "@intlayer/config/callers";
2
2
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+core@8.0.1/node_modules/@babel/core/lib/index.js";
3
3
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+types@8.0.4/node_modules/@babel/types/lib/index.js";
@@ -1,3 +1,4 @@
1
+ import "./pruneContext.js";
1
2
  import "./babel-plugin-intlayer-usage-analyzer.js";
2
3
  import "@intlayer/core/dictionaryManipulator";
3
4
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+core@8.0.1/node_modules/@babel/core/lib/index.js";
@@ -1,4 +1,5 @@
1
- import "@intlayer/core/dictionaryManipulator";
2
- import "@intlayer/config/callers";
1
+ import "./pruneContext.js";
2
+ import "./staticAstReaders.js";
3
+ import { CallerDescriptor } from "@intlayer/config/callers";
3
4
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+core@8.0.1/node_modules/@babel/core/lib/index.js";
4
5
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+types@8.0.4/node_modules/@babel/types/lib/index.js";
@@ -1,4 +1,6 @@
1
+ import "./pruneContext.js";
1
2
  import "./babel-plugin-intlayer-extract.js";
3
+ import "./staticAstReaders.js";
2
4
  import "./babel-plugin-intlayer-usage-analyzer.js";
3
5
  import { SerializedFieldRenameEntry, SerializedFieldRenameMap } from "./babel-plugin-intlayer-field-rename.js";
4
6
  import "./babel-plugin-intlayer-minify.js";
@@ -0,0 +1 @@
1
+ import "@intlayer/core/dictionaryManipulator";
@@ -0,0 +1,2 @@
1
+ import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+core@8.0.1/node_modules/@babel/core/lib/index.js";
2
+ import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+types@8.0.4/node_modules/@babel/types/lib/index.js";
@@ -1,3 +1,4 @@
1
+ import "./pruneContext.js";
1
2
  import "./babel-plugin-intlayer-usage-analyzer.js";
2
3
  import "./babel-plugin-intlayer-optimize.js";
3
4
  import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/@babel+parser@8.0.4/node_modules/@babel/parser/lib/index.js";