@intlayer/config 9.3.2 → 9.3.3
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.
- package/dist/cjs/bundle/index.cjs +1 -1
- package/dist/cjs/configFile/buildConfigurationFields.cjs +24 -0
- package/dist/cjs/configFile/buildConfigurationFields.cjs.map +1 -1
- package/dist/cjs/defaultValues/build.cjs +4 -0
- package/dist/cjs/defaultValues/build.cjs.map +1 -1
- package/dist/cjs/defaultValues/dictionary.cjs +41 -0
- package/dist/cjs/defaultValues/dictionary.cjs.map +1 -1
- package/dist/cjs/defaultValues/index.cjs +6 -0
- package/dist/cjs/dictionaryPreload.cjs +149 -0
- package/dist/cjs/dictionaryPreload.cjs.map +1 -0
- package/dist/esm/bundle/index.mjs +1 -1
- package/dist/esm/configFile/buildConfigurationFields.mjs +25 -1
- package/dist/esm/configFile/buildConfigurationFields.mjs.map +1 -1
- package/dist/esm/defaultValues/build.mjs +3 -1
- package/dist/esm/defaultValues/build.mjs.map +1 -1
- package/dist/esm/defaultValues/dictionary.mjs +38 -1
- package/dist/esm/defaultValues/dictionary.mjs.map +1 -1
- package/dist/esm/defaultValues/index.mjs +3 -3
- package/dist/esm/dictionaryPreload.mjs +144 -0
- package/dist/esm/dictionaryPreload.mjs.map +1 -0
- package/dist/types/configFile/buildConfigurationFields.d.ts.map +1 -1
- package/dist/types/defaultValues/build.d.ts +3 -1
- package/dist/types/defaultValues/build.d.ts.map +1 -1
- package/dist/types/defaultValues/dictionary.d.ts +38 -1
- package/dist/types/defaultValues/dictionary.d.ts.map +1 -1
- package/dist/types/defaultValues/index.d.ts +3 -3
- package/dist/types/dictionaryPreload.d.ts +79 -0
- package/dist/types/dictionaryPreload.d.ts.map +1 -0
- package/package.json +8 -3
|
@@ -2,8 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_utils_alias = require('../utils/alias.cjs');
|
|
4
4
|
const require_configFile_getConfiguration = require('../configFile/getConfiguration.cjs');
|
|
5
|
-
const require_bundle_logBundle = require('./logBundle.cjs');
|
|
6
5
|
const require_envVars_envVars = require('../envVars/envVars.cjs');
|
|
6
|
+
const require_bundle_logBundle = require('./logBundle.cjs');
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
let node_fs_promises = require("node:fs/promises");
|
|
9
9
|
let _intlayer_types_package_json = require("@intlayer/types/package.json");
|
|
@@ -256,6 +256,30 @@ const buildBuildFields = (customConfiguration) => ({
|
|
|
256
256
|
*/
|
|
257
257
|
purge: customConfiguration?.purge ?? false,
|
|
258
258
|
/**
|
|
259
|
+
* Group the per-locale dictionary chunks by the code-split boundary that uses
|
|
260
|
+
* them, so a lazily loaded page fetches its content in one request.
|
|
261
|
+
*
|
|
262
|
+
* Default: true
|
|
263
|
+
*
|
|
264
|
+
* Note:
|
|
265
|
+
* - Only applies to dictionaries using `importMode: 'dynamic'`.
|
|
266
|
+
* - Only applies to the client build, and only when bundling (not in dev).
|
|
267
|
+
*/
|
|
268
|
+
chunkGrouping: customConfiguration?.chunkGrouping ?? true,
|
|
269
|
+
/**
|
|
270
|
+
* Load a dictionary together with the chunk that uses it, instead of fetching
|
|
271
|
+
* it once that chunk renders — so a reader renders synchronously rather than
|
|
272
|
+
* suspending, and navigating no longer flashes a loading state.
|
|
273
|
+
*
|
|
274
|
+
* Default: true
|
|
275
|
+
*
|
|
276
|
+
* Note:
|
|
277
|
+
* - Only applies to dictionaries using `importMode: 'dynamic'`.
|
|
278
|
+
* - Only applies to the client build; the server keeps loading on demand.
|
|
279
|
+
* - Requires a bundler supporting top-level await (Vite, esbuild).
|
|
280
|
+
*/
|
|
281
|
+
dictionariesPreload: customConfiguration?.dictionariesPreload ?? true,
|
|
282
|
+
/**
|
|
259
283
|
* Pattern to traverse the code to optimize.
|
|
260
284
|
*
|
|
261
285
|
* Allows to avoid to traverse the code that is not relevant to the optimization.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildConfigurationFields.cjs","names":["getProjectRequire","isAbsolute","join","statSync","dirname","FILE_EXTENSIONS","CONTENT_DIR","CODE_DIR","EXCLUDED_PATHS","TRAVERSE_PATTERN","OUTPUT_FORMAT","intlayerConfigSchema","buildBrowserConfiguration","buildInternationalizationFields","buildEditorFields","buildLogFields","buildAnalyticsFields"],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type {\n AiConfig,\n BuildConfig,\n CompilerConfig,\n ContentConfig,\n CustomIntlayerConfig,\n DictionaryConfig,\n IntlayerConfig,\n LogFunctions,\n SystemConfig,\n} from '@intlayer/types/config';\nimport {\n BUILD_MODE,\n CACHE,\n MINIFY,\n OUTPUT_FORMAT,\n PURGE,\n TRAVERSE_PATTERN,\n TYPE_CHECKING,\n} from '../defaultValues/build';\nimport {\n COMPILER_DICTIONARY_KEY_PREFIX,\n COMPILER_ENABLED,\n COMPILER_NO_METADATA,\n COMPILER_SAVE_COMPONENTS,\n} from '../defaultValues/compiler';\nimport {\n CODE_DIR,\n CONTENT_DIR,\n EXCLUDED_PATHS,\n FILE_EXTENSIONS,\n WATCH,\n} from '../defaultValues/content';\nimport {\n CONTENT_AUTO_TRANSFORMATION,\n FILL,\n IMPORT_MODE,\n LOCATION,\n} from '../defaultValues/dictionary';\nimport {\n CACHE_DIR,\n CONFIG_DIR,\n DICTIONARIES_DIR,\n DYNAMIC_DICTIONARIES_DIR,\n FETCH_DICTIONARIES_DIR,\n MAIN_DIR,\n MODULE_AUGMENTATION_DIR,\n REMOTE_DICTIONARIES_DIR,\n TEMP_DIR,\n TYPES_DIR,\n UNMERGED_DICTIONARIES_DIR,\n} from '../defaultValues/system';\nimport { getProjectRequire } from '../utils';\nimport {\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n} from './buildBrowserConfiguration';\nimport { intlayerConfigSchema } from './configurationSchema';\n\nexport {\n type BrowserIntlayerConfig,\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n buildRoutingFields,\n extractBrowserConfiguration,\n} from './buildBrowserConfiguration';\n\nlet storedConfiguration: IntlayerConfig;\n\n// ---------------------------------------------------------------------------\n// Server-only field builders (Node.js — not browser-safe)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the `system` section of the Intlayer configuration.\n *\n * Resolves all directory paths (dictionaries, types, cache, …) relative to\n * the project base directory, using Node.js `require.resolve` where available\n * and falling back to `path.join` otherwise.\n *\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param customConfiguration - Partial user-supplied system config.\n * @returns A fully-resolved {@link SystemConfig}.\n */\nconst buildSystemFields = (\n baseDir?: string,\n customConfiguration?: Partial<SystemConfig>\n): SystemConfig => {\n const projectBaseDir = baseDir ?? process.cwd();\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(projectBaseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [projectBaseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [projectBaseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(projectBaseDir, pathInput);\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const dictionariesDir = optionalJoinBaseDir(\n customConfiguration?.dictionariesDir ?? DICTIONARIES_DIR\n );\n\n return {\n baseDir: projectBaseDir,\n moduleAugmentationDir: optionalJoinBaseDir(\n customConfiguration?.moduleAugmentationDir ?? MODULE_AUGMENTATION_DIR\n ),\n unmergedDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.unmergedDictionariesDir ?? UNMERGED_DICTIONARIES_DIR\n ),\n remoteDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.remoteDictionariesDir ?? REMOTE_DICTIONARIES_DIR\n ),\n dictionariesDir,\n dynamicDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.dynamicDictionariesDir ?? DYNAMIC_DICTIONARIES_DIR\n ),\n fetchDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.fetchDictionariesDir ?? FETCH_DICTIONARIES_DIR\n ),\n typesDir: optionalJoinBaseDir(customConfiguration?.typesDir ?? TYPES_DIR),\n mainDir: optionalJoinBaseDir(customConfiguration?.mainDir ?? MAIN_DIR),\n configDir: optionalJoinBaseDir(\n customConfiguration?.configDir ?? CONFIG_DIR\n ),\n cacheDir: optionalJoinBaseDir(customConfiguration?.cacheDir ?? CACHE_DIR),\n tempDir: optionalJoinBaseDir(customConfiguration?.tempDir ?? TEMP_DIR),\n };\n};\n\n/**\n * Build the `content` section of the Intlayer configuration.\n *\n * Resolves content and code directories relative to the project base using\n * `require.resolve`, falling back to `path.join`.\n *\n * @param systemConfig - Already-built system configuration (provides `baseDir`).\n * @param customConfiguration - Partial user-supplied content config.\n * @returns A fully-resolved {@link ContentConfig}.\n */\nconst buildContentFields = (\n systemConfig: SystemConfig,\n customConfiguration?: Partial<ContentConfig>\n): ContentConfig => {\n const fileExtensions = customConfiguration?.fileExtensions ?? FILE_EXTENSIONS;\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(systemConfig.baseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n try {\n try {\n absolutePath = require.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = require.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(systemConfig.baseDir, pathInput);\n }\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const contentDir = (customConfiguration?.contentDir ?? CONTENT_DIR).map(\n optionalJoinBaseDir\n );\n const codeDir = (customConfiguration?.codeDir ?? CODE_DIR).map(\n optionalJoinBaseDir\n );\n\n return {\n fileExtensions,\n contentDir,\n codeDir,\n excludedPath: customConfiguration?.excludedPath ?? EXCLUDED_PATHS,\n watch: customConfiguration?.watch ?? WATCH,\n formatCommand: customConfiguration?.formatCommand,\n };\n};\n\n/**\n * Build the `ai` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied AI config.\n * @returns A fully-defaulted {@link AiConfig}.\n */\nconst buildAiFields = (customConfiguration?: Partial<AiConfig>): AiConfig => ({\n /**\n * AI configuration\n */\n provider: customConfiguration?.provider,\n\n /**\n * API key\n */\n apiKey: customConfiguration?.apiKey,\n\n /**\n * API model\n */\n model: customConfiguration?.model,\n\n /**\n * Temperature\n */\n temperature: customConfiguration?.temperature,\n\n /**\n * Application context\n *\n * Default: undefined\n *\n * The application context.\n *\n * Example: `'My application context'`\n *\n * Note: Can be used to provide additional context about the application to the AI model. You can add more rules (e.g. \"You should not transform urls\").\n */\n applicationContext: customConfiguration?.applicationContext,\n\n /**\n * Base URL for the AI API\n *\n * Default: undefined\n *\n * The base URL for the AI API.\n *\n * Example: `'http://localhost:5000'`\n *\n * Note: Can be used to point to a local, or custom AI API endpoint.\n */\n baseURL: customConfiguration?.baseURL,\n\n /**\n * Data serialization\n *\n * Options:\n * - \"json\": The industry standard. Highly reliable and structured, but consumes more tokens.\n * - \"toon\": An optimized format designed to reduce token consumption (cost-effective). However, it may slightly increase the risk of output inconsistency compared to standard JSON\n *\n * Default: `\"json\"`\n */\n dataSerialization: customConfiguration?.dataSerialization,\n});\n\n/**\n * Build the `build` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied build config.\n * @returns A fully-defaulted {@link BuildConfig}.\n */\nconst buildBuildFields = (\n customConfiguration?: Partial<BuildConfig>\n): BuildConfig => ({\n /**\n * Indicates the mode of the build\n *\n * Default: 'auto'\n *\n * If 'auto', the build will be enabled automatically when the application is built.\n * If 'manual', the build will be set only when the build command is executed.\n *\n * Can be used to disable dictionaries build, for instance when execution on Node.js environment should be avoided.\n */\n mode: customConfiguration?.mode ?? BUILD_MODE,\n\n /**\n * Indicates if the build should be optimized\n *\n * Default: process.env.NODE_ENV === 'production'\n *\n * If true, the build will be optimized.\n * If false, the build will not be optimized.\n *\n * Intlayer will replace all calls of dictionaries to optimize chunking. That way the final bundle will import only the dictionaries that are used.\n * All imports will stay as static import to avoid async processing when loading the dictionaries.\n *\n * Note:\n * - Intlayer will replace all call of `useIntlayer` with the defined mode by the `importMode` option.\n * - Intlayer will replace all call of `getIntlayer` with `getDictionary`.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - In most cases, \"dynamic\" will be used for React applications, \"async\" for Vue.js applications.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n */\n optimize: customConfiguration?.optimize,\n\n /**\n * Indicates the mode of import to use for the dictionaries.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as \"dynamic\" mode.\n *\n * Default: \"static\"\n *\n * By default, when a dictionary is loaded, it imports content for all locales as it's imported statically.\n *\n * Note:\n * - Dynamic imports rely on Suspense and may slightly impact rendering performance.\n * - If disabled all locales will be loaded at once, even if they are not used.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n * - This option will be ignored if `optimize` is disabled.\n * - This option will not impact the `getIntlayer`, `getDictionary`, `useDictionary`, `useDictionaryAsync` and `useDictionaryDynamic` functions. You can still use them to refine you code on manual optimization.\n * - The \"live\" allows to sync the dictionaries to the live sync server.\n *\n * @deprecated Use `dictionary.importMode` instead.\n */\n importMode: customConfiguration?.importMode,\n\n /**\n * Minify the dictionaries to reduce the bundle size.\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignore if `editor.enabled` is true.\n * - If there is edge cases where the minification is not working properly, the dictionary will be not minified.\n */\n minify: customConfiguration?.minify ?? MINIFY,\n\n /**\n * Purge the unused keys in a dictionaries\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignored if `editor.enabled` is true.\n */\n purge: customConfiguration?.purge ?? PURGE,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * Allows to avoid to traverse the code that is not relevant to the optimization.\n * Improve build performance.\n *\n * Default: ['**\\/*.{js,ts,mjs,cjs,jsx,tsx}', '!**\\/node_modules/**']\n *\n * Example: `['src/**\\/*.{ts,tsx}', '../ui-library/**\\/*.{ts,tsx}']`\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - Use glob pattern.\n */\n traversePattern: customConfiguration?.traversePattern ?? TRAVERSE_PATTERN,\n\n /**\n * Output format of the dictionaries\n *\n * Can be set on large projects to improve build performance.\n *\n * Default: ['cjs', 'esm']\n *\n * The output format of the dictionaries. It can be either 'cjs' or 'esm'.\n * - 'cjs': The dictionaries are outputted as CommonJS modules.\n * - 'esm': The dictionaries are outputted as ES modules.\n */\n outputFormat: customConfiguration?.outputFormat ?? OUTPUT_FORMAT,\n\n /**\n * Cache\n */\n cache: customConfiguration?.cache ?? CACHE,\n\n /**\n * Require function\n */\n require: customConfiguration?.require,\n\n /**\n * Indicates if the build should check TypeScript types\n *\n * Default: `false`\n *\n * If true, the build will check TypeScript types and log errors.\n * Note: This can slow down the build.\n */\n checkTypes: customConfiguration?.checkTypes ?? TYPE_CHECKING,\n});\n\n/**\n * Build the `compiler` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied compiler config.\n * @returns A fully-defaulted {@link CompilerConfig}.\n */\nconst buildCompilerFields = (\n customConfiguration?: Partial<CompilerConfig>\n): CompilerConfig => ({\n /**\n * Indicates if the compiler should be enabled\n */\n enabled: customConfiguration?.enabled ?? COMPILER_ENABLED,\n\n /**\n * Prefix for the extracted dictionary keys\n */\n dictionaryKeyPrefix:\n customConfiguration?.dictionaryKeyPrefix ?? COMPILER_DICTIONARY_KEY_PREFIX,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * @deprecated use `build.traversePattern` instead\n */\n transformPattern: customConfiguration?.transformPattern,\n\n /**\n * Pattern to exclude from the optimization.\n *\n * @deprecated use `build.traversePattern` instead\n */\n excludePattern: customConfiguration?.excludePattern,\n\n /**\n * Defines the output files path. Replaces `outputDir`.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - Including the `{{locale}}` variable in the path will trigger the generation of separate dictionaries per locale.\n *\n * @example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * output: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // output: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * output: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // output: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create per-locale JSON files with locale-specific output paths\n * output: {\n * en: ({ fileName, locale }) => `${fileName}.${locale}.content.json`,\n * fr: '{{fileName}}.{{locale}}.content.json',\n * es: false, // skip this locale\n * },\n * }\n * ```\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n output: customConfiguration?.output,\n\n /**\n * Indicates if the metadata should be saved in the file.\n *\n * If true, the compiler will not save the metadata of the dictionaries.\n *\n * If `true`:\n *\n * ```json\n * {\n * \"key\": \"value\"\n * }\n * ```\n *\n * If `false`:\n *\n * ```json\n * {\n * \"key\": \"value\",\n * \"content\": {\n * \"key\": \"value\"\n * }\n * }\n * ```\n *\n * Default: `false`\n *\n * Note: Useful if used with loadJSON plugin\n */\n noMetadata: customConfiguration?.noMetadata ?? COMPILER_NO_METADATA,\n\n /**\n * Indicates if the components should be saved after being transformed.\n */\n saveComponents:\n customConfiguration?.saveComponents ?? COMPILER_SAVE_COMPONENTS,\n});\n\n/**\n * Build the `dictionary` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied dictionary config.\n * @returns A fully-defaulted {@link DictionaryConfig}.\n */\nconst buildDictionaryFields = (\n customConfiguration?: Partial<DictionaryConfig>\n): DictionaryConfig => {\n const contentAutoTransformation =\n customConfiguration?.contentAutoTransformation ??\n CONTENT_AUTO_TRANSFORMATION;\n\n return {\n /**\n * Indicate how the dictionary should be filled using AI.\n *\n * Default: `true`\n *\n * - If `true`, will consider the `compiler.output` field.\n * - If `false`, will skip the fill process.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.\n *\n * Example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * fill: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // fill: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create custom output based on the locale\n * fill: {\n * en: ({ key }) => `/locales/en/${key}.content.json`,\n * fr: '/locales/fr/{{key}}.content.json',\n * es: false,\n * de: true,\n * },\n * }\n * ```\n *\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n fill: customConfiguration?.fill ?? FILL,\n\n /**\n * Indicates if the content of the dictionary should be automatically transformed.\n *\n * Default: `false`\n */\n contentAutoTransformation:\n typeof contentAutoTransformation === 'object'\n ? {\n markdown: contentAutoTransformation.markdown ?? false,\n html: contentAutoTransformation.html ?? false,\n insertion: contentAutoTransformation.insertion ?? false,\n }\n : contentAutoTransformation,\n\n /**\n * The location of the dictionary.\n *\n * Default: `\"local\"`\n */\n location: customConfiguration?.location ?? LOCATION,\n\n /**\n * Transform the dictionary in a per-locale dictionary.\n * Each field declared in a per-locale dictionary will be transformed in a translation node.\n * If missing, the dictionary will be treated as a multilingual dictionary.\n */\n locale: customConfiguration?.locale,\n\n /**\n * The title of the dictionary.\n */\n title: customConfiguration?.title,\n\n /**\n * The description of the dictionary.\n */\n description: customConfiguration?.description,\n\n /**\n * Tags to categorize the dictionaries.\n */\n tags: customConfiguration?.tags,\n\n /**\n * The priority of the dictionary.\n */\n priority: customConfiguration?.priority,\n\n /**\n * Indicates the mode of import to use for the dictionary.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n *\n * Default: `\"static\"`\n */\n importMode: customConfiguration?.importMode ?? IMPORT_MODE,\n\n /**\n * The default message format for all dictionaries in the project.\n *\n * Default: 'intlayer'\n */\n format: customConfiguration?.format,\n };\n};\n\n// ---------------------------------------------------------------------------\n// Main export\n// ---------------------------------------------------------------------------\n\n/**\n * Build the complete Intlayer configuration by merging user-supplied values\n * with defaults.\n *\n * Internally this function:\n * 1. Calls {@link buildBrowserConfiguration} to produce the browser-safe\n * subset (internationalization, routing, editor public fields, log, metadata).\n * 2. Extends the result with full server-side fields:\n * - `internationalization` — adds `requiredLocales` and `strictMode`.\n * - `editor` — adds `clientId` and `clientSecret`.\n * - `log` — adds custom log functions.\n * - `system`, `content`, `ai`, `build`, `compiler`, `dictionary`.\n *\n * @param customConfiguration - Optional user-supplied configuration object.\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param logFunctions - Optional custom logging functions.\n * @returns A fully-built {@link IntlayerConfig}.\n */\nexport const buildConfigurationFields = (\n customConfiguration?: CustomIntlayerConfig,\n baseDir?: string,\n logFunctions?: LogFunctions\n): IntlayerConfig => {\n if (customConfiguration) {\n const result = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!result.success) {\n const logError = logFunctions?.error ?? console.error;\n\n for (const issue of result.error.issues) {\n logError(`${issue.path.join('.')}: ${issue.message}`);\n }\n }\n }\n\n // build browser-safe config (shared defaults, no Node.js deps)\n const browserConfig = buildBrowserConfiguration(customConfiguration);\n\n // extend shared fields with server-only additions\n const internationalizationConfig = buildInternationalizationFields(\n customConfiguration?.internationalization\n );\n\n const editorConfig = buildEditorFields(customConfiguration?.editor);\n\n const logConfig = buildLogFields(customConfiguration?.log, logFunctions);\n\n // build server-only fields\n const systemConfig = buildSystemFields(baseDir, customConfiguration?.system);\n\n const contentConfig = buildContentFields(\n systemConfig,\n customConfiguration?.content\n );\n\n storedConfiguration = {\n // Shared browser fields\n routing: browserConfig.routing,\n // Full (extended) shared fields\n internationalization: internationalizationConfig,\n editor: editorConfig,\n analytics: buildAnalyticsFields(customConfiguration?.analytics),\n log: logConfig,\n // Server-only fields\n system: systemConfig,\n content: contentConfig,\n ai: buildAiFields(customConfiguration?.ai),\n build: buildBuildFields(customConfiguration?.build),\n compiler: buildCompilerFields(customConfiguration?.compiler),\n dictionary: buildDictionaryFields(customConfiguration?.dictionary),\n plugins: customConfiguration?.plugins,\n schemas: customConfiguration?.schemas,\n } as IntlayerConfig;\n\n return storedConfiguration;\n};\n"],"mappings":";;;;;;;;;;;;;AA2EA,IAAI;;;;;;;;;;;;AAiBJ,MAAM,qBACJ,SACA,wBACiB;CACjB,MAAM,iBAAiB,WAAW,QAAQ,IAAI;CAE9C,MAAM,uBAAuB,cAAsB;EACjD,IAAI;EAEJ,IAAI;GACF,MAAM,kBAAkBA,+CAAkB,cAAc;GACxD,IAAI;IACF,eAAe,gBAAgB,QAAQ,WAAW,EAChD,OAAO,CAAC,cAAc,EACxB,CAAC;GACH,SAAS,KAAK;IACZ,IAAI,CAAC,UAAU,WAAW,GAAG,KAAK,KAACC,sBAAW,SAAS,GACrD,eAAe,gBAAgB,QAAQ,GAAG,UAAU,gBAAgB,EAClE,OAAO,CAAC,cAAc,EACxB,CAAC;SAED,MAAM;GAEV;EACF,QAAQ;GACN,mBAAeA,sBAAW,SAAS,IAC/B,gBACAC,gBAAK,gBAAgB,SAAS;EACpC;EAEA,IAAI;GAEF,QADcC,kBAAS,YACf,CAAC,CAAC,OAAO,GACf,WAAOC,mBAAQ,YAAY;EAE/B,QAAQ;GACN,IAAI,gBAAgB,KAAK,YAAY,GACnC,WAAOA,mBAAQ,YAAY;EAE/B;EAEA,OAAO;CACT;CAEA,MAAM,kBAAkB,oBACtB,qBAAqB,yCACvB;CAEA,OAAO;EACL,SAAS;EACT,uBAAuB,oBACrB,qBAAqB,0CACvB;EACA,yBAAyB,oBACvB,qBAAqB,0DACvB;EACA,uBAAuB,oBACrB,qBAAqB,sDACvB;EACA;EACA,wBAAwB,oBACtB,qBAAqB,wDACvB;EACA,sBAAsB,oBACpB,qBAAqB,oDACvB;EACA,UAAU,oBAAoB,qBAAqB,6BAAqB;EACxE,SAAS,oBAAoB,qBAAqB,2BAAmB;EACrE,WAAW,oBACT,qBAAqB,+BACvB;EACA,UAAU,oBAAoB,qBAAqB,6BAAqB;EACxE,SAAS,oBAAoB,qBAAqB,0BAAmB;CACvE;AACF;;;;;;;;;;;AAYA,MAAM,sBACJ,cACA,wBACkB;CAClB,MAAM,iBAAiB,qBAAqB,kBAAkBC;CAE9D,MAAM,uBAAuB,cAAsB;EACjD,IAAI;EAEJ,IAAI;GACF,MAAM,kBAAkBL,+CAAkB,aAAa,OAAO;GAC9D,IAAI;IACF,eAAe,gBAAgB,QAAQ,WAAW,EAChD,OAAO,CAAC,aAAa,OAAO,EAC9B,CAAC;GACH,SAAS,KAAK;IACZ,IAAI,CAAC,UAAU,WAAW,GAAG,KAAK,KAACC,sBAAW,SAAS,GACrD,eAAe,gBAAgB,QAAQ,GAAG,UAAU,gBAAgB,EAClE,OAAO,CAAC,aAAa,OAAO,EAC9B,CAAC;SAED,MAAM;GAEV;EACF,QAAQ;GACN,IAAI;IACF,IAAI;KACF,eAAe,QAAQ,QAAQ,WAAW,EACxC,OAAO,CAAC,aAAa,OAAO,EAC9B,CAAC;IACH,SAAS,KAAK;KACZ,IAAI,CAAC,UAAU,WAAW,GAAG,KAAK,KAACA,sBAAW,SAAS,GACrD,eAAe,QAAQ,QAAQ,GAAG,UAAU,gBAAgB,EAC1D,OAAO,CAAC,aAAa,OAAO,EAC9B,CAAC;UAED,MAAM;IAEV;GACF,QAAQ;IACN,mBAAeA,sBAAW,SAAS,IAC/B,gBACAC,gBAAK,aAAa,SAAS,SAAS;GAC1C;EACF;EAEA,IAAI;GAEF,QADcC,kBAAS,YACf,CAAC,CAAC,OAAO,GACf,WAAOC,mBAAQ,YAAY;EAE/B,QAAQ;GACN,IAAI,gBAAgB,KAAK,YAAY,GACnC,WAAOA,mBAAQ,YAAY;EAE/B;EAEA,OAAO;CACT;CASA,OAAO;EACL;EACA,aATkB,qBAAqB,cAAcE,0CAAW,CAAE,IAClE,mBAQS;EACT,UAPe,qBAAqB,WAAWC,uCAAQ,CAAE,IACzD,mBAMM;EACN,cAAc,qBAAqB,gBAAgBC;EACnD,OAAO,qBAAqB;EAC5B,eAAe,qBAAqB;CACtC;AACF;;;;;;;AAQA,MAAM,iBAAiB,yBAAuD;;;;CAI5E,UAAU,qBAAqB;;;;CAK/B,QAAQ,qBAAqB;;;;CAK7B,OAAO,qBAAqB;;;;CAK5B,aAAa,qBAAqB;;;;;;;;;;;;CAalC,oBAAoB,qBAAqB;;;;;;;;;;;;CAazC,SAAS,qBAAqB;;;;;;;;;;CAW9B,mBAAmB,qBAAqB;AAC1C;;;;;;;AAQA,MAAM,oBACJ,yBACiB;;;;;;;;;;;CAWjB,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;CAoB3B,UAAU,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B/B,YAAY,qBAAqB;;;;;;;;;;;CAYjC,QAAQ,qBAAqB;;;;;;;;;;CAW7B,OAAO,qBAAqB;;;;;;;;;;;;;;;CAgB5B,iBAAiB,qBAAqB,mBAAmBC;;;;;;;;;;;;CAazD,cAAc,qBAAqB,gBAAgBC;;;;CAKnD,OAAO,qBAAqB;;;;CAK5B,SAAS,qBAAqB;;;;;;;;;CAU9B,YAAY,qBAAqB;AACnC;;;;;;;AAQA,MAAM,uBACJ,yBACoB;;;;CAIpB,SAAS,qBAAqB;;;;CAK9B,qBACE,qBAAqB;;;;;;CAOvB,kBAAkB,qBAAqB;;;;;;CAOvC,gBAAgB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDrC,QAAQ,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8B7B,YAAY,qBAAqB;;;;CAKjC,gBACE,qBAAqB;AACzB;;;;;;;AAQA,MAAM,yBACJ,wBACqB;CACrB,MAAM,4BACJ,qBAAqB;CAGvB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDL,MAAM,qBAAqB;;;;;;EAO3B,2BACE,OAAO,8BAA8B,WACjC;GACE,UAAU,0BAA0B,YAAY;GAChD,MAAM,0BAA0B,QAAQ;GACxC,WAAW,0BAA0B,aAAa;EACpD,IACA;;;;;;EAON,UAAU,qBAAqB;;;;;;EAO/B,QAAQ,qBAAqB;;;;EAK7B,OAAO,qBAAqB;;;;EAK5B,aAAa,qBAAqB;;;;EAKlC,MAAM,qBAAqB;;;;EAK3B,UAAU,qBAAqB;;;;;;;;;;;EAY/B,YAAY,qBAAqB;;;;;;EAOjC,QAAQ,qBAAqB;CAC/B;AACF;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,4BACX,qBACA,SACA,iBACmB;CACnB,IAAI,qBAAqB;EACvB,MAAM,SAASC,4DAAqB,UAAU,mBAAmB;EAEjE,IAAI,CAAC,OAAO,SAAS;GACnB,MAAM,WAAW,cAAc,SAAS,QAAQ;GAEhD,KAAK,MAAM,SAAS,OAAO,MAAM,QAC/B,SAAS,GAAG,MAAM,KAAK,KAAK,GAAG,EAAE,IAAI,MAAM,SAAS;EAExD;CACF;CAGA,MAAM,gBAAgBC,uEAA0B,mBAAmB;CAGnE,MAAM,6BAA6BC,6EACjC,qBAAqB,oBACvB;CAEA,MAAM,eAAeC,+DAAkB,qBAAqB,MAAM;CAElE,MAAM,YAAYC,4DAAe,qBAAqB,KAAK,YAAY;CAGvE,MAAM,eAAe,kBAAkB,SAAS,qBAAqB,MAAM;CAE3E,MAAM,gBAAgB,mBACpB,cACA,qBAAqB,OACvB;CAEA,sBAAsB;EAEpB,SAAS,cAAc;EAEvB,sBAAsB;EACtB,QAAQ;EACR,WAAWC,kEAAqB,qBAAqB,SAAS;EAC9D,KAAK;EAEL,QAAQ;EACR,SAAS;EACT,IAAI,cAAc,qBAAqB,EAAE;EACzC,OAAO,iBAAiB,qBAAqB,KAAK;EAClD,UAAU,oBAAoB,qBAAqB,QAAQ;EAC3D,YAAY,sBAAsB,qBAAqB,UAAU;EACjE,SAAS,qBAAqB;EAC9B,SAAS,qBAAqB;CAChC;CAEA,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"buildConfigurationFields.cjs","names":["getProjectRequire","isAbsolute","join","statSync","dirname","FILE_EXTENSIONS","CONTENT_DIR","CODE_DIR","EXCLUDED_PATHS","TRAVERSE_PATTERN","OUTPUT_FORMAT","intlayerConfigSchema","buildBrowserConfiguration","buildInternationalizationFields","buildEditorFields","buildLogFields","buildAnalyticsFields"],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type {\n AiConfig,\n BuildConfig,\n CompilerConfig,\n ContentConfig,\n CustomIntlayerConfig,\n DictionaryConfig,\n IntlayerConfig,\n LogFunctions,\n SystemConfig,\n} from '@intlayer/types/config';\nimport {\n BUILD_MODE,\n CACHE,\n CHUNK_GROUPING,\n DICTIONARIES_PRELOAD,\n MINIFY,\n OUTPUT_FORMAT,\n PURGE,\n TRAVERSE_PATTERN,\n TYPE_CHECKING,\n} from '../defaultValues/build';\nimport {\n COMPILER_DICTIONARY_KEY_PREFIX,\n COMPILER_ENABLED,\n COMPILER_NO_METADATA,\n COMPILER_SAVE_COMPONENTS,\n} from '../defaultValues/compiler';\nimport {\n CODE_DIR,\n CONTENT_DIR,\n EXCLUDED_PATHS,\n FILE_EXTENSIONS,\n WATCH,\n} from '../defaultValues/content';\nimport {\n CONTENT_AUTO_TRANSFORMATION,\n FILL,\n IMPORT_MODE,\n LOCATION,\n} from '../defaultValues/dictionary';\nimport {\n CACHE_DIR,\n CONFIG_DIR,\n DICTIONARIES_DIR,\n DYNAMIC_DICTIONARIES_DIR,\n FETCH_DICTIONARIES_DIR,\n MAIN_DIR,\n MODULE_AUGMENTATION_DIR,\n REMOTE_DICTIONARIES_DIR,\n TEMP_DIR,\n TYPES_DIR,\n UNMERGED_DICTIONARIES_DIR,\n} from '../defaultValues/system';\nimport { getProjectRequire } from '../utils';\nimport {\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n} from './buildBrowserConfiguration';\nimport { intlayerConfigSchema } from './configurationSchema';\n\nexport {\n type BrowserIntlayerConfig,\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n buildRoutingFields,\n extractBrowserConfiguration,\n} from './buildBrowserConfiguration';\n\nlet storedConfiguration: IntlayerConfig;\n\n// ---------------------------------------------------------------------------\n// Server-only field builders (Node.js — not browser-safe)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the `system` section of the Intlayer configuration.\n *\n * Resolves all directory paths (dictionaries, types, cache, …) relative to\n * the project base directory, using Node.js `require.resolve` where available\n * and falling back to `path.join` otherwise.\n *\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param customConfiguration - Partial user-supplied system config.\n * @returns A fully-resolved {@link SystemConfig}.\n */\nconst buildSystemFields = (\n baseDir?: string,\n customConfiguration?: Partial<SystemConfig>\n): SystemConfig => {\n const projectBaseDir = baseDir ?? process.cwd();\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(projectBaseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [projectBaseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [projectBaseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(projectBaseDir, pathInput);\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const dictionariesDir = optionalJoinBaseDir(\n customConfiguration?.dictionariesDir ?? DICTIONARIES_DIR\n );\n\n return {\n baseDir: projectBaseDir,\n moduleAugmentationDir: optionalJoinBaseDir(\n customConfiguration?.moduleAugmentationDir ?? MODULE_AUGMENTATION_DIR\n ),\n unmergedDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.unmergedDictionariesDir ?? UNMERGED_DICTIONARIES_DIR\n ),\n remoteDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.remoteDictionariesDir ?? REMOTE_DICTIONARIES_DIR\n ),\n dictionariesDir,\n dynamicDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.dynamicDictionariesDir ?? DYNAMIC_DICTIONARIES_DIR\n ),\n fetchDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.fetchDictionariesDir ?? FETCH_DICTIONARIES_DIR\n ),\n typesDir: optionalJoinBaseDir(customConfiguration?.typesDir ?? TYPES_DIR),\n mainDir: optionalJoinBaseDir(customConfiguration?.mainDir ?? MAIN_DIR),\n configDir: optionalJoinBaseDir(\n customConfiguration?.configDir ?? CONFIG_DIR\n ),\n cacheDir: optionalJoinBaseDir(customConfiguration?.cacheDir ?? CACHE_DIR),\n tempDir: optionalJoinBaseDir(customConfiguration?.tempDir ?? TEMP_DIR),\n };\n};\n\n/**\n * Build the `content` section of the Intlayer configuration.\n *\n * Resolves content and code directories relative to the project base using\n * `require.resolve`, falling back to `path.join`.\n *\n * @param systemConfig - Already-built system configuration (provides `baseDir`).\n * @param customConfiguration - Partial user-supplied content config.\n * @returns A fully-resolved {@link ContentConfig}.\n */\nconst buildContentFields = (\n systemConfig: SystemConfig,\n customConfiguration?: Partial<ContentConfig>\n): ContentConfig => {\n const fileExtensions = customConfiguration?.fileExtensions ?? FILE_EXTENSIONS;\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(systemConfig.baseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n try {\n try {\n absolutePath = require.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = require.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(systemConfig.baseDir, pathInput);\n }\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const contentDir = (customConfiguration?.contentDir ?? CONTENT_DIR).map(\n optionalJoinBaseDir\n );\n const codeDir = (customConfiguration?.codeDir ?? CODE_DIR).map(\n optionalJoinBaseDir\n );\n\n return {\n fileExtensions,\n contentDir,\n codeDir,\n excludedPath: customConfiguration?.excludedPath ?? EXCLUDED_PATHS,\n watch: customConfiguration?.watch ?? WATCH,\n formatCommand: customConfiguration?.formatCommand,\n };\n};\n\n/**\n * Build the `ai` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied AI config.\n * @returns A fully-defaulted {@link AiConfig}.\n */\nconst buildAiFields = (customConfiguration?: Partial<AiConfig>): AiConfig => ({\n /**\n * AI configuration\n */\n provider: customConfiguration?.provider,\n\n /**\n * API key\n */\n apiKey: customConfiguration?.apiKey,\n\n /**\n * API model\n */\n model: customConfiguration?.model,\n\n /**\n * Temperature\n */\n temperature: customConfiguration?.temperature,\n\n /**\n * Application context\n *\n * Default: undefined\n *\n * The application context.\n *\n * Example: `'My application context'`\n *\n * Note: Can be used to provide additional context about the application to the AI model. You can add more rules (e.g. \"You should not transform urls\").\n */\n applicationContext: customConfiguration?.applicationContext,\n\n /**\n * Base URL for the AI API\n *\n * Default: undefined\n *\n * The base URL for the AI API.\n *\n * Example: `'http://localhost:5000'`\n *\n * Note: Can be used to point to a local, or custom AI API endpoint.\n */\n baseURL: customConfiguration?.baseURL,\n\n /**\n * Data serialization\n *\n * Options:\n * - \"json\": The industry standard. Highly reliable and structured, but consumes more tokens.\n * - \"toon\": An optimized format designed to reduce token consumption (cost-effective). However, it may slightly increase the risk of output inconsistency compared to standard JSON\n *\n * Default: `\"json\"`\n */\n dataSerialization: customConfiguration?.dataSerialization,\n});\n\n/**\n * Build the `build` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied build config.\n * @returns A fully-defaulted {@link BuildConfig}.\n */\nconst buildBuildFields = (\n customConfiguration?: Partial<BuildConfig>\n): BuildConfig => ({\n /**\n * Indicates the mode of the build\n *\n * Default: 'auto'\n *\n * If 'auto', the build will be enabled automatically when the application is built.\n * If 'manual', the build will be set only when the build command is executed.\n *\n * Can be used to disable dictionaries build, for instance when execution on Node.js environment should be avoided.\n */\n mode: customConfiguration?.mode ?? BUILD_MODE,\n\n /**\n * Indicates if the build should be optimized\n *\n * Default: process.env.NODE_ENV === 'production'\n *\n * If true, the build will be optimized.\n * If false, the build will not be optimized.\n *\n * Intlayer will replace all calls of dictionaries to optimize chunking. That way the final bundle will import only the dictionaries that are used.\n * All imports will stay as static import to avoid async processing when loading the dictionaries.\n *\n * Note:\n * - Intlayer will replace all call of `useIntlayer` with the defined mode by the `importMode` option.\n * - Intlayer will replace all call of `getIntlayer` with `getDictionary`.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - In most cases, \"dynamic\" will be used for React applications, \"async\" for Vue.js applications.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n */\n optimize: customConfiguration?.optimize,\n\n /**\n * Indicates the mode of import to use for the dictionaries.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as \"dynamic\" mode.\n *\n * Default: \"static\"\n *\n * By default, when a dictionary is loaded, it imports content for all locales as it's imported statically.\n *\n * Note:\n * - Dynamic imports rely on Suspense and may slightly impact rendering performance.\n * - If disabled all locales will be loaded at once, even if they are not used.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n * - This option will be ignored if `optimize` is disabled.\n * - This option will not impact the `getIntlayer`, `getDictionary`, `useDictionary`, `useDictionaryAsync` and `useDictionaryDynamic` functions. You can still use them to refine you code on manual optimization.\n * - The \"live\" allows to sync the dictionaries to the live sync server.\n *\n * @deprecated Use `dictionary.importMode` instead.\n */\n importMode: customConfiguration?.importMode,\n\n /**\n * Minify the dictionaries to reduce the bundle size.\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignore if `editor.enabled` is true.\n * - If there is edge cases where the minification is not working properly, the dictionary will be not minified.\n */\n minify: customConfiguration?.minify ?? MINIFY,\n\n /**\n * Purge the unused keys in a dictionaries\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignored if `editor.enabled` is true.\n */\n purge: customConfiguration?.purge ?? PURGE,\n\n /**\n * Group the per-locale dictionary chunks by the code-split boundary that uses\n * them, so a lazily loaded page fetches its content in one request.\n *\n * Default: true\n *\n * Note:\n * - Only applies to dictionaries using `importMode: 'dynamic'`.\n * - Only applies to the client build, and only when bundling (not in dev).\n */\n chunkGrouping: customConfiguration?.chunkGrouping ?? CHUNK_GROUPING,\n\n /**\n * Load a dictionary together with the chunk that uses it, instead of fetching\n * it once that chunk renders — so a reader renders synchronously rather than\n * suspending, and navigating no longer flashes a loading state.\n *\n * Default: true\n *\n * Note:\n * - Only applies to dictionaries using `importMode: 'dynamic'`.\n * - Only applies to the client build; the server keeps loading on demand.\n * - Requires a bundler supporting top-level await (Vite, esbuild).\n */\n dictionariesPreload:\n customConfiguration?.dictionariesPreload ?? DICTIONARIES_PRELOAD,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * Allows to avoid to traverse the code that is not relevant to the optimization.\n * Improve build performance.\n *\n * Default: ['**\\/*.{js,ts,mjs,cjs,jsx,tsx}', '!**\\/node_modules/**']\n *\n * Example: `['src/**\\/*.{ts,tsx}', '../ui-library/**\\/*.{ts,tsx}']`\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - Use glob pattern.\n */\n traversePattern: customConfiguration?.traversePattern ?? TRAVERSE_PATTERN,\n\n /**\n * Output format of the dictionaries\n *\n * Can be set on large projects to improve build performance.\n *\n * Default: ['cjs', 'esm']\n *\n * The output format of the dictionaries. It can be either 'cjs' or 'esm'.\n * - 'cjs': The dictionaries are outputted as CommonJS modules.\n * - 'esm': The dictionaries are outputted as ES modules.\n */\n outputFormat: customConfiguration?.outputFormat ?? OUTPUT_FORMAT,\n\n /**\n * Cache\n */\n cache: customConfiguration?.cache ?? CACHE,\n\n /**\n * Require function\n */\n require: customConfiguration?.require,\n\n /**\n * Indicates if the build should check TypeScript types\n *\n * Default: `false`\n *\n * If true, the build will check TypeScript types and log errors.\n * Note: This can slow down the build.\n */\n checkTypes: customConfiguration?.checkTypes ?? TYPE_CHECKING,\n});\n\n/**\n * Build the `compiler` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied compiler config.\n * @returns A fully-defaulted {@link CompilerConfig}.\n */\nconst buildCompilerFields = (\n customConfiguration?: Partial<CompilerConfig>\n): CompilerConfig => ({\n /**\n * Indicates if the compiler should be enabled\n */\n enabled: customConfiguration?.enabled ?? COMPILER_ENABLED,\n\n /**\n * Prefix for the extracted dictionary keys\n */\n dictionaryKeyPrefix:\n customConfiguration?.dictionaryKeyPrefix ?? COMPILER_DICTIONARY_KEY_PREFIX,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * @deprecated use `build.traversePattern` instead\n */\n transformPattern: customConfiguration?.transformPattern,\n\n /**\n * Pattern to exclude from the optimization.\n *\n * @deprecated use `build.traversePattern` instead\n */\n excludePattern: customConfiguration?.excludePattern,\n\n /**\n * Defines the output files path. Replaces `outputDir`.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - Including the `{{locale}}` variable in the path will trigger the generation of separate dictionaries per locale.\n *\n * @example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * output: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // output: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * output: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // output: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create per-locale JSON files with locale-specific output paths\n * output: {\n * en: ({ fileName, locale }) => `${fileName}.${locale}.content.json`,\n * fr: '{{fileName}}.{{locale}}.content.json',\n * es: false, // skip this locale\n * },\n * }\n * ```\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n output: customConfiguration?.output,\n\n /**\n * Indicates if the metadata should be saved in the file.\n *\n * If true, the compiler will not save the metadata of the dictionaries.\n *\n * If `true`:\n *\n * ```json\n * {\n * \"key\": \"value\"\n * }\n * ```\n *\n * If `false`:\n *\n * ```json\n * {\n * \"key\": \"value\",\n * \"content\": {\n * \"key\": \"value\"\n * }\n * }\n * ```\n *\n * Default: `false`\n *\n * Note: Useful if used with loadJSON plugin\n */\n noMetadata: customConfiguration?.noMetadata ?? COMPILER_NO_METADATA,\n\n /**\n * Indicates if the components should be saved after being transformed.\n */\n saveComponents:\n customConfiguration?.saveComponents ?? COMPILER_SAVE_COMPONENTS,\n});\n\n/**\n * Build the `dictionary` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied dictionary config.\n * @returns A fully-defaulted {@link DictionaryConfig}.\n */\nconst buildDictionaryFields = (\n customConfiguration?: Partial<DictionaryConfig>\n): DictionaryConfig => {\n const contentAutoTransformation =\n customConfiguration?.contentAutoTransformation ??\n CONTENT_AUTO_TRANSFORMATION;\n\n return {\n /**\n * Indicate how the dictionary should be filled using AI.\n *\n * Default: `true`\n *\n * - If `true`, will consider the `compiler.output` field.\n * - If `false`, will skip the fill process.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.\n *\n * Example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * fill: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // fill: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create custom output based on the locale\n * fill: {\n * en: ({ key }) => `/locales/en/${key}.content.json`,\n * fr: '/locales/fr/{{key}}.content.json',\n * es: false,\n * de: true,\n * },\n * }\n * ```\n *\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n fill: customConfiguration?.fill ?? FILL,\n\n /**\n * Indicates if the content of the dictionary should be automatically transformed.\n *\n * Default: `false`\n */\n contentAutoTransformation:\n typeof contentAutoTransformation === 'object'\n ? {\n markdown: contentAutoTransformation.markdown ?? false,\n html: contentAutoTransformation.html ?? false,\n insertion: contentAutoTransformation.insertion ?? false,\n }\n : contentAutoTransformation,\n\n /**\n * The location of the dictionary.\n *\n * Default: `\"local\"`\n */\n location: customConfiguration?.location ?? LOCATION,\n\n /**\n * Transform the dictionary in a per-locale dictionary.\n * Each field declared in a per-locale dictionary will be transformed in a translation node.\n * If missing, the dictionary will be treated as a multilingual dictionary.\n */\n locale: customConfiguration?.locale,\n\n /**\n * The title of the dictionary.\n */\n title: customConfiguration?.title,\n\n /**\n * The description of the dictionary.\n */\n description: customConfiguration?.description,\n\n /**\n * Tags to categorize the dictionaries.\n */\n tags: customConfiguration?.tags,\n\n /**\n * The priority of the dictionary.\n */\n priority: customConfiguration?.priority,\n\n /**\n * Indicates the mode of import to use for the dictionary.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n *\n * Default: `\"static\"`\n */\n importMode: customConfiguration?.importMode ?? IMPORT_MODE,\n\n /**\n * The default message format for all dictionaries in the project.\n *\n * Default: 'intlayer'\n */\n format: customConfiguration?.format,\n };\n};\n\n// ---------------------------------------------------------------------------\n// Main export\n// ---------------------------------------------------------------------------\n\n/**\n * Build the complete Intlayer configuration by merging user-supplied values\n * with defaults.\n *\n * Internally this function:\n * 1. Calls {@link buildBrowserConfiguration} to produce the browser-safe\n * subset (internationalization, routing, editor public fields, log, metadata).\n * 2. Extends the result with full server-side fields:\n * - `internationalization` — adds `requiredLocales` and `strictMode`.\n * - `editor` — adds `clientId` and `clientSecret`.\n * - `log` — adds custom log functions.\n * - `system`, `content`, `ai`, `build`, `compiler`, `dictionary`.\n *\n * @param customConfiguration - Optional user-supplied configuration object.\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param logFunctions - Optional custom logging functions.\n * @returns A fully-built {@link IntlayerConfig}.\n */\nexport const buildConfigurationFields = (\n customConfiguration?: CustomIntlayerConfig,\n baseDir?: string,\n logFunctions?: LogFunctions\n): IntlayerConfig => {\n if (customConfiguration) {\n const result = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!result.success) {\n const logError = logFunctions?.error ?? console.error;\n\n for (const issue of result.error.issues) {\n logError(`${issue.path.join('.')}: ${issue.message}`);\n }\n }\n }\n\n // build browser-safe config (shared defaults, no Node.js deps)\n const browserConfig = buildBrowserConfiguration(customConfiguration);\n\n // extend shared fields with server-only additions\n const internationalizationConfig = buildInternationalizationFields(\n customConfiguration?.internationalization\n );\n\n const editorConfig = buildEditorFields(customConfiguration?.editor);\n\n const logConfig = buildLogFields(customConfiguration?.log, logFunctions);\n\n // build server-only fields\n const systemConfig = buildSystemFields(baseDir, customConfiguration?.system);\n\n const contentConfig = buildContentFields(\n systemConfig,\n customConfiguration?.content\n );\n\n storedConfiguration = {\n // Shared browser fields\n routing: browserConfig.routing,\n // Full (extended) shared fields\n internationalization: internationalizationConfig,\n editor: editorConfig,\n analytics: buildAnalyticsFields(customConfiguration?.analytics),\n log: logConfig,\n // Server-only fields\n system: systemConfig,\n content: contentConfig,\n ai: buildAiFields(customConfiguration?.ai),\n build: buildBuildFields(customConfiguration?.build),\n compiler: buildCompilerFields(customConfiguration?.compiler),\n dictionary: buildDictionaryFields(customConfiguration?.dictionary),\n plugins: customConfiguration?.plugins,\n schemas: customConfiguration?.schemas,\n } as IntlayerConfig;\n\n return storedConfiguration;\n};\n"],"mappings":"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"}
|
|
@@ -29,10 +29,14 @@ const CACHE = true;
|
|
|
29
29
|
const TYPE_CHECKING = false;
|
|
30
30
|
const MINIFY = false;
|
|
31
31
|
const PURGE = false;
|
|
32
|
+
const CHUNK_GROUPING = true;
|
|
33
|
+
const DICTIONARIES_PRELOAD = true;
|
|
32
34
|
|
|
33
35
|
//#endregion
|
|
34
36
|
exports.BUILD_MODE = BUILD_MODE;
|
|
35
37
|
exports.CACHE = CACHE;
|
|
38
|
+
exports.CHUNK_GROUPING = CHUNK_GROUPING;
|
|
39
|
+
exports.DICTIONARIES_PRELOAD = DICTIONARIES_PRELOAD;
|
|
36
40
|
exports.MINIFY = MINIFY;
|
|
37
41
|
exports.OPTIMIZE = OPTIMIZE;
|
|
38
42
|
exports.OUTPUT_FORMAT = OUTPUT_FORMAT;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.cjs","names":[],"sources":["../../../src/defaultValues/build.ts"],"sourcesContent":["export const BUILD_MODE = 'auto';\n\nexport const OPTIMIZE = undefined;\n\nexport const TRAVERSE_PATTERN = [\n // Included files to parse\n '**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,astro}',\n\n // Excluded paths\n '!**/node_modules/**',\n '!**/dist/**',\n '!**/build/**',\n '!**/.intlayer/**',\n '!**/.next/**',\n '!**/.nuxt/**',\n '!**/.expo/**',\n '!**/.vercel/**',\n '!**/.turbo/**',\n '!**/.tanstack/**',\n '!**/.output/**',\n '!**/.svelte-kit/**',\n '!**/*.config.*',\n '!**/*.test.*',\n '!**/*.spec.*',\n '!**/*.stories.*',\n '!**/*.d.ts',\n '!**/*.d.ts.map',\n '!**/*.map',\n];\n\nexport const OUTPUT_FORMAT: ('cjs' | 'esm')[] = ['esm', 'cjs'];\n\nexport const CACHE = true;\n\nexport const TYPE_CHECKING = false;\n\nexport const MINIFY = false;\n\nexport const PURGE = false;\n"],"mappings":";;AAAA,MAAa,aAAa;AAE1B,MAAa,WAAW;AAExB,MAAa,mBAAmB;CAE9B;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gBAAmC,CAAC,OAAO,KAAK;AAE7D,MAAa,QAAQ;AAErB,MAAa,gBAAgB;AAE7B,MAAa,SAAS;AAEtB,MAAa,QAAQ"}
|
|
1
|
+
{"version":3,"file":"build.cjs","names":[],"sources":["../../../src/defaultValues/build.ts"],"sourcesContent":["export const BUILD_MODE = 'auto';\n\nexport const OPTIMIZE = undefined;\n\nexport const TRAVERSE_PATTERN = [\n // Included files to parse\n '**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,astro}',\n\n // Excluded paths\n '!**/node_modules/**',\n '!**/dist/**',\n '!**/build/**',\n '!**/.intlayer/**',\n '!**/.next/**',\n '!**/.nuxt/**',\n '!**/.expo/**',\n '!**/.vercel/**',\n '!**/.turbo/**',\n '!**/.tanstack/**',\n '!**/.output/**',\n '!**/.svelte-kit/**',\n '!**/*.config.*',\n '!**/*.test.*',\n '!**/*.spec.*',\n '!**/*.stories.*',\n '!**/*.d.ts',\n '!**/*.d.ts.map',\n '!**/*.map',\n];\n\nexport const OUTPUT_FORMAT: ('cjs' | 'esm')[] = ['esm', 'cjs'];\n\nexport const CACHE = true;\n\nexport const TYPE_CHECKING = false;\n\nexport const MINIFY = false;\n\nexport const PURGE = false;\n\nexport const CHUNK_GROUPING = true;\n\nexport const DICTIONARIES_PRELOAD = true;\n"],"mappings":";;AAAA,MAAa,aAAa;AAE1B,MAAa,WAAW;AAExB,MAAa,mBAAmB;CAE9B;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gBAAmC,CAAC,OAAO,KAAK;AAE7D,MAAa,QAAQ;AAErB,MAAa,gBAAgB;AAE7B,MAAa,SAAS;AAEtB,MAAa,QAAQ;AAErB,MAAa,iBAAiB;AAE9B,MAAa,uBAAuB"}
|
|
@@ -4,10 +4,51 @@ const FILL = true;
|
|
|
4
4
|
const LOCATION = "local";
|
|
5
5
|
const CONTENT_AUTO_TRANSFORMATION = false;
|
|
6
6
|
const IMPORT_MODE = "static";
|
|
7
|
+
/**
|
|
8
|
+
* Directory the per-locale JSON chunks of `importMode: 'dynamic'` are written
|
|
9
|
+
* under, relative to `system.dynamicDictionariesDir`.
|
|
10
|
+
*
|
|
11
|
+
* Plain dictionaries land at `<subdir>/<key>/<locale>.json`, qualified ones
|
|
12
|
+
* (collections, variants) nest one directory per dimension in between. The
|
|
13
|
+
* static first segment is required by Turbopack, and build-tool plugins match
|
|
14
|
+
* module ids against this layout — hence the shared constant rather than a
|
|
15
|
+
* literal repeated on both sides.
|
|
16
|
+
*/
|
|
17
|
+
const DYNAMIC_DICTIONARIES_JSON_SUBDIR = "json";
|
|
18
|
+
/**
|
|
19
|
+
* Marker property carrying the ordered qualifier dimensions on a dynamic loader
|
|
20
|
+
* map. Its presence distinguishes a qualified group loader map (a nested tree
|
|
21
|
+
* of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed
|
|
22
|
+
* and unlikely to collide with a real locale code.
|
|
23
|
+
*/
|
|
24
|
+
const QUALIFIER_DYNAMIC_TYPES_KEY = "__intlayerQualifierTypes";
|
|
25
|
+
/**
|
|
26
|
+
* Marker property carrying the dictionary a generated dynamic entry point
|
|
27
|
+
* already resolved for the browsing locale, before any component rendered.
|
|
28
|
+
*
|
|
29
|
+
* Build-tool plugins prepend a top-level `await` to those entry points, so the
|
|
30
|
+
* chunk that statically imports one only finishes evaluating once the awaited
|
|
31
|
+
* locale chunk has landed. A read during render then finds the content in place
|
|
32
|
+
* instead of suspending.
|
|
33
|
+
*/
|
|
34
|
+
const PRELOADED_DYNAMIC_KEY = "__intlayerPreloaded";
|
|
35
|
+
/**
|
|
36
|
+
* Name of the local binding a generated dynamic entry point holds its loader
|
|
37
|
+
* map in, before exporting it as default.
|
|
38
|
+
*
|
|
39
|
+
* The preload preamble is appended to that generated source and mutates the
|
|
40
|
+
* binding, so the code generator and the build plugins have to agree on the
|
|
41
|
+
* name — hence the shared constant rather than a literal repeated in both.
|
|
42
|
+
*/
|
|
43
|
+
const DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = "content";
|
|
7
44
|
|
|
8
45
|
//#endregion
|
|
9
46
|
exports.CONTENT_AUTO_TRANSFORMATION = CONTENT_AUTO_TRANSFORMATION;
|
|
47
|
+
exports.DYNAMIC_DICTIONARIES_JSON_SUBDIR = DYNAMIC_DICTIONARIES_JSON_SUBDIR;
|
|
48
|
+
exports.DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER;
|
|
10
49
|
exports.FILL = FILL;
|
|
11
50
|
exports.IMPORT_MODE = IMPORT_MODE;
|
|
12
51
|
exports.LOCATION = LOCATION;
|
|
52
|
+
exports.PRELOADED_DYNAMIC_KEY = PRELOADED_DYNAMIC_KEY;
|
|
53
|
+
exports.QUALIFIER_DYNAMIC_TYPES_KEY = QUALIFIER_DYNAMIC_TYPES_KEY;
|
|
13
54
|
//# sourceMappingURL=dictionary.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictionary.cjs","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"sourcesContent":["import type { DictionaryLocation } from '@intlayer/types/dictionary';\n\nexport const FILL = true;\nexport const LOCATION: DictionaryLocation = 'local';\nexport const CONTENT_AUTO_TRANSFORMATION = false;\nexport const IMPORT_MODE = 'static';\n"],"mappings":";;AAEA,MAAa,OAAO;AACpB,MAAa,WAA+B;AAC5C,MAAa,8BAA8B;AAC3C,MAAa,cAAc"}
|
|
1
|
+
{"version":3,"file":"dictionary.cjs","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"sourcesContent":["import type { DictionaryLocation } from '@intlayer/types/dictionary';\n\nexport const FILL = true;\nexport const LOCATION: DictionaryLocation = 'local';\nexport const CONTENT_AUTO_TRANSFORMATION = false;\nexport const IMPORT_MODE = 'static';\n\n/**\n * Directory the per-locale JSON chunks of `importMode: 'dynamic'` are written\n * under, relative to `system.dynamicDictionariesDir`.\n *\n * Plain dictionaries land at `<subdir>/<key>/<locale>.json`, qualified ones\n * (collections, variants) nest one directory per dimension in between. The\n * static first segment is required by Turbopack, and build-tool plugins match\n * module ids against this layout — hence the shared constant rather than a\n * literal repeated on both sides.\n */\nexport const DYNAMIC_DICTIONARIES_JSON_SUBDIR = 'json';\n\n/**\n * Marker property carrying the ordered qualifier dimensions on a dynamic loader\n * map. Its presence distinguishes a qualified group loader map (a nested tree\n * of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed\n * and unlikely to collide with a real locale code.\n */\nexport const QUALIFIER_DYNAMIC_TYPES_KEY = '__intlayerQualifierTypes';\n\n/**\n * Marker property carrying the dictionary a generated dynamic entry point\n * already resolved for the browsing locale, before any component rendered.\n *\n * Build-tool plugins prepend a top-level `await` to those entry points, so the\n * chunk that statically imports one only finishes evaluating once the awaited\n * locale chunk has landed. A read during render then finds the content in place\n * instead of suspending.\n */\nexport const PRELOADED_DYNAMIC_KEY = '__intlayerPreloaded';\n\n/**\n * Name of the local binding a generated dynamic entry point holds its loader\n * map in, before exporting it as default.\n *\n * The preload preamble is appended to that generated source and mutates the\n * binding, so the code generator and the build plugins have to agree on the\n * name — hence the shared constant rather than a literal repeated in both.\n */\nexport const DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = 'content';\n"],"mappings":";;AAEA,MAAa,OAAO;AACpB,MAAa,WAA+B;AAC5C,MAAa,8BAA8B;AAC3C,MAAa,cAAc;;;;;;;;;;;AAY3B,MAAa,mCAAmC;;;;;;;AAQhD,MAAa,8BAA8B;;;;;;;;;;AAW3C,MAAa,wBAAwB;;;;;;;;;AAUrC,MAAa,sCAAsC"}
|
|
@@ -19,6 +19,7 @@ exports.BASE_PATH = require_defaultValues_routing.BASE_PATH;
|
|
|
19
19
|
exports.BUILD_MODE = require_defaultValues_build.BUILD_MODE;
|
|
20
20
|
exports.CACHE = require_defaultValues_build.CACHE;
|
|
21
21
|
exports.CACHE_DIR = require_defaultValues_system.CACHE_DIR;
|
|
22
|
+
exports.CHUNK_GROUPING = require_defaultValues_build.CHUNK_GROUPING;
|
|
22
23
|
exports.CMS_URL = require_defaultValues_editor.CMS_URL;
|
|
23
24
|
exports.CODE_DIR = require_defaultValues_content.CODE_DIR;
|
|
24
25
|
exports.COMPILER_DICTIONARY_KEY_PREFIX = require_defaultValues_compiler.COMPILER_DICTIONARY_KEY_PREFIX;
|
|
@@ -31,8 +32,11 @@ exports.CONTENT_DIR = require_defaultValues_content.CONTENT_DIR;
|
|
|
31
32
|
exports.COOKIE_NAME = require_defaultValues_routing.COOKIE_NAME;
|
|
32
33
|
exports.DEFAULT_LOCALE = require_defaultValues_internationalization.DEFAULT_LOCALE;
|
|
33
34
|
exports.DICTIONARIES_DIR = require_defaultValues_system.DICTIONARIES_DIR;
|
|
35
|
+
exports.DICTIONARIES_PRELOAD = require_defaultValues_build.DICTIONARIES_PRELOAD;
|
|
34
36
|
exports.DICTIONARY_PRIORITY_STRATEGY = require_defaultValues_editor.DICTIONARY_PRIORITY_STRATEGY;
|
|
35
37
|
exports.DYNAMIC_DICTIONARIES_DIR = require_defaultValues_system.DYNAMIC_DICTIONARIES_DIR;
|
|
38
|
+
exports.DYNAMIC_DICTIONARIES_JSON_SUBDIR = require_defaultValues_dictionary.DYNAMIC_DICTIONARIES_JSON_SUBDIR;
|
|
39
|
+
exports.DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = require_defaultValues_dictionary.DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER;
|
|
36
40
|
exports.EDITOR_URL = require_defaultValues_editor.EDITOR_URL;
|
|
37
41
|
exports.ENABLE_PROXY = require_defaultValues_routing.ENABLE_PROXY;
|
|
38
42
|
exports.EXCLUDED_PATHS = require_defaultValues_content.EXCLUDED_PATHS;
|
|
@@ -57,7 +61,9 @@ exports.OPTIMIZE = require_defaultValues_build.OPTIMIZE;
|
|
|
57
61
|
exports.OUTPUT_FORMAT = require_defaultValues_build.OUTPUT_FORMAT;
|
|
58
62
|
exports.PORT = require_defaultValues_editor.PORT;
|
|
59
63
|
exports.PREFIX = require_defaultValues_log.PREFIX;
|
|
64
|
+
exports.PRELOADED_DYNAMIC_KEY = require_defaultValues_dictionary.PRELOADED_DYNAMIC_KEY;
|
|
60
65
|
exports.PURGE = require_defaultValues_build.PURGE;
|
|
66
|
+
exports.QUALIFIER_DYNAMIC_TYPES_KEY = require_defaultValues_dictionary.QUALIFIER_DYNAMIC_TYPES_KEY;
|
|
61
67
|
exports.REACT_INTL_MESSAGES_DIR = require_defaultValues_content.REACT_INTL_MESSAGES_DIR;
|
|
62
68
|
exports.REMOTE_DICTIONARIES_DIR = require_defaultValues_system.REMOTE_DICTIONARIES_DIR;
|
|
63
69
|
exports.REQUIRED_LOCALES = require_defaultValues_internationalization.REQUIRED_LOCALES;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_defaultValues_dictionary = require('./defaultValues/dictionary.cjs');
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
|
|
5
|
+
//#region src/dictionaryPreload.ts
|
|
6
|
+
/**
|
|
7
|
+
* Matches a generated dynamic entry point, whose layout is
|
|
8
|
+
* `<dynamicDictionariesDir>/<key>.mjs`. The per-locale JSON chunks it imports
|
|
9
|
+
* live one directory deeper, under `json/`, and are deliberately excluded.
|
|
10
|
+
*/
|
|
11
|
+
const DYNAMIC_ENTRY_PATTERN = /\/(?<key>[^/]+)\.mjs$/;
|
|
12
|
+
/** Escapes a literal path segment for embedding in a regular expression. */
|
|
13
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14
|
+
/**
|
|
15
|
+
* Builds a filter matching only the generated dynamic entry points, for
|
|
16
|
+
* bundlers whose load hook is selected by a regular expression over the raw
|
|
17
|
+
* file path (esbuild).
|
|
18
|
+
*
|
|
19
|
+
* A hook registered on every `.mjs` would call back into JavaScript for each
|
|
20
|
+
* such file in the build, `node_modules` included, so the filter is anchored on
|
|
21
|
+
* the dictionaries directory name. It matches both path separators because
|
|
22
|
+
* esbuild tests the platform path, which is backslash-separated on Windows —
|
|
23
|
+
* the directory name itself never contains one.
|
|
24
|
+
*
|
|
25
|
+
* The name alone is not proof of location, so the callback must still confirm
|
|
26
|
+
* the full path lies inside `dynamicDictionariesDir`.
|
|
27
|
+
*
|
|
28
|
+
* @param dynamicDictionariesDir - Absolute dictionaries root, any separator.
|
|
29
|
+
*/
|
|
30
|
+
const createDynamicEntryFilter = (dynamicDictionariesDir) => {
|
|
31
|
+
const directoryName = dynamicDictionariesDir.split(/[\\/]/).filter(Boolean).pop() ?? "";
|
|
32
|
+
return new RegExp(`[\\\\/]${escapeRegExp(directoryName)}[\\\\/][^\\\\/]+\\.mjs$`);
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Specifier of the module the injected preamble reads the locale from, as the
|
|
36
|
+
* bundler plugins are expected to resolve it.
|
|
37
|
+
*
|
|
38
|
+
* Never emitted as-is: a generated entry point lives in the *application's*
|
|
39
|
+
* `.intlayer` directory, and an application depends on `intlayer` and its
|
|
40
|
+
* framework binding — not on `@intlayer/core` — so a bare specifier would
|
|
41
|
+
* resolve from a directory where the package is absent, or, worse, silently
|
|
42
|
+
* hit an unrelated copy hoisted higher up the tree.
|
|
43
|
+
*/
|
|
44
|
+
const PRELOAD_MODULE_SPECIFIER = "@intlayer/core/localization";
|
|
45
|
+
/** Package and subpath {@link PRELOAD_MODULE_SPECIFIER} is composed of. */
|
|
46
|
+
const PRELOAD_PACKAGE_NAME = "@intlayer/core";
|
|
47
|
+
const PRELOAD_PACKAGE_SUBPATH = "./localization";
|
|
48
|
+
/**
|
|
49
|
+
* Resolves {@link PRELOAD_MODULE_SPECIFIER} to an absolute id the injected
|
|
50
|
+
* preamble can import, from a package that actually depends on it.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately not `require.resolve(PRELOAD_MODULE_SPECIFIER)`: that applies
|
|
53
|
+
* the `require` condition and lands on the package's CommonJS build, which the
|
|
54
|
+
* preamble would then pull into a *browser* bundle behind a CommonJS interop
|
|
55
|
+
* wrapper — a second copy of the module alongside the ESM one the application
|
|
56
|
+
* already imports, each with its own memoized locale. The manifest is resolved
|
|
57
|
+
* instead (a condition-free subpath) and its `import` entry read directly.
|
|
58
|
+
*
|
|
59
|
+
* @param requireFn - `require`, or `createRequire(import.meta.url)`, from the
|
|
60
|
+
* plugin package.
|
|
61
|
+
* @returns Absolute path to the ESM build, falling back to whatever the
|
|
62
|
+
* standard resolution yields if the package ever stops publishing one.
|
|
63
|
+
*/
|
|
64
|
+
const resolvePreloadModuleId = (requireFn) => {
|
|
65
|
+
const manifestPath = requireFn.resolve(`${PRELOAD_PACKAGE_NAME}/package.json`);
|
|
66
|
+
const subpathExport = requireFn(manifestPath).exports?.[PRELOAD_PACKAGE_SUBPATH];
|
|
67
|
+
const esmEntry = typeof subpathExport === "string" ? subpathExport : subpathExport?.import;
|
|
68
|
+
if (!esmEntry) return requireFn.resolve(PRELOAD_MODULE_SPECIFIER);
|
|
69
|
+
return (0, node_path.resolve)((0, node_path.dirname)(manifestPath), esmEntry);
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Builds the import the injected preamble relies on, hoisted ahead of the
|
|
73
|
+
* generated source.
|
|
74
|
+
*
|
|
75
|
+
* @param preloadModuleId - Specifier resolving to {@link PRELOAD_MODULE_SPECIFIER}
|
|
76
|
+
* from the plugin package, which does depend on it.
|
|
77
|
+
*/
|
|
78
|
+
const buildPreloadImport = (preloadModuleId) => `import { getPreloadLocale as __intlayerGetPreloadLocale } from '${preloadModuleId}';\n`;
|
|
79
|
+
/**
|
|
80
|
+
* Preamble appended to a generated dynamic entry point.
|
|
81
|
+
*
|
|
82
|
+
* The load is started while the entry point evaluates, but is deliberately
|
|
83
|
+
* *not* awaited at the top level. Awaiting would make the entry point an async
|
|
84
|
+
* module, which delays the resolution of every chunk that statically imports
|
|
85
|
+
* it — including the chunks behind a `React.lazy` boundary. A boundary whose
|
|
86
|
+
* module resolves that late during hydration stays on its fallback for good:
|
|
87
|
+
* the framework has already swapped the server markup for the pending state and
|
|
88
|
+
* does not retry, so the section never appears. Starting the request here and
|
|
89
|
+
* letting the reader pick the result up keeps the whole benefit of the early
|
|
90
|
+
* fetch without ever holding up module evaluation.
|
|
91
|
+
*
|
|
92
|
+
* The gain is in *when* the request starts: it leaves as soon as the chunk that
|
|
93
|
+
* needs the dictionary is evaluated — on a router's `import()` of a route,
|
|
94
|
+
* including a preload on hover — rather than once the consuming component
|
|
95
|
+
* renders. By the time the reader runs, the marker is usually already set and
|
|
96
|
+
* the read is synchronous, so no loading state is revealed.
|
|
97
|
+
*
|
|
98
|
+
* Only the resolved locale is requested, so a page still downloads exactly the
|
|
99
|
+
* language it renders.
|
|
100
|
+
*
|
|
101
|
+
* A failed load is swallowed: leaving the marker unset drops the read back onto
|
|
102
|
+
* the asynchronous path, where the existing loading state surfaces the error.
|
|
103
|
+
*/
|
|
104
|
+
const PRELOAD_PREAMBLE = [
|
|
105
|
+
"",
|
|
106
|
+
"// Injected by Intlayer: starts the browsing locale load with this module.",
|
|
107
|
+
"const __intlayerLocale = __intlayerGetPreloadLocale();",
|
|
108
|
+
`const __intlayerLoader = ${require_defaultValues_dictionary.DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}[__intlayerLocale];`,
|
|
109
|
+
"",
|
|
110
|
+
`if (typeof window !== 'undefined' && typeof __intlayerLoader === 'function') {`,
|
|
111
|
+
" __intlayerLoader().then(",
|
|
112
|
+
" (__intlayerDictionary) => {",
|
|
113
|
+
` ${require_defaultValues_dictionary.DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}['${require_defaultValues_dictionary.PRELOADED_DYNAMIC_KEY}'] = {`,
|
|
114
|
+
" locale: __intlayerLocale,",
|
|
115
|
+
" dictionary: __intlayerDictionary,",
|
|
116
|
+
" };",
|
|
117
|
+
" },",
|
|
118
|
+
" () => undefined",
|
|
119
|
+
" );",
|
|
120
|
+
"}",
|
|
121
|
+
""
|
|
122
|
+
].join("\n");
|
|
123
|
+
/**
|
|
124
|
+
* Adds the browsing-locale preload to a generated dynamic entry point.
|
|
125
|
+
*
|
|
126
|
+
* Bundler-agnostic on purpose: the Vite plugin and the esbuild plugin apply the
|
|
127
|
+
* identical transform, and keeping one implementation means the emitted shape
|
|
128
|
+
* cannot drift between them. The caller decides *which* modules to hand over
|
|
129
|
+
* (the id is matched against the dynamic dictionaries directory) and how to
|
|
130
|
+
* report a skip.
|
|
131
|
+
*
|
|
132
|
+
* @param code - Source of the generated `<key>.mjs` entry point.
|
|
133
|
+
* @param preloadModuleId - Specifier the preamble imports the locale resolver
|
|
134
|
+
* from, already resolved against the plugin package.
|
|
135
|
+
* @returns The transformed source, or the reason it was left alone.
|
|
136
|
+
*/
|
|
137
|
+
const addDynamicEntryPreload = (code, preloadModuleId) => {
|
|
138
|
+
if (code.includes("__intlayerQualifierTypes")) return { skipped: "qualified" };
|
|
139
|
+
if (!code.includes(`const ${"content"} =`)) return { skipped: "unrecognized-shape" };
|
|
140
|
+
return { code: buildPreloadImport(preloadModuleId) + code + PRELOAD_PREAMBLE };
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
144
|
+
exports.DYNAMIC_ENTRY_PATTERN = DYNAMIC_ENTRY_PATTERN;
|
|
145
|
+
exports.PRELOAD_MODULE_SPECIFIER = PRELOAD_MODULE_SPECIFIER;
|
|
146
|
+
exports.addDynamicEntryPreload = addDynamicEntryPreload;
|
|
147
|
+
exports.createDynamicEntryFilter = createDynamicEntryFilter;
|
|
148
|
+
exports.resolvePreloadModuleId = resolvePreloadModuleId;
|
|
149
|
+
//# sourceMappingURL=dictionaryPreload.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaryPreload.cjs","names":["resolve","dirname","DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER","PRELOADED_DYNAMIC_KEY"],"sources":["../../src/dictionaryPreload.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path';\nimport {\n DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER,\n PRELOADED_DYNAMIC_KEY,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n} from './defaultValues/dictionary';\n\n/**\n * Matches a generated dynamic entry point, whose layout is\n * `<dynamicDictionariesDir>/<key>.mjs`. The per-locale JSON chunks it imports\n * live one directory deeper, under `json/`, and are deliberately excluded.\n */\nexport const DYNAMIC_ENTRY_PATTERN = /\\/(?<key>[^/]+)\\.mjs$/;\n\n/** Escapes a literal path segment for embedding in a regular expression. */\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Builds a filter matching only the generated dynamic entry points, for\n * bundlers whose load hook is selected by a regular expression over the raw\n * file path (esbuild).\n *\n * A hook registered on every `.mjs` would call back into JavaScript for each\n * such file in the build, `node_modules` included, so the filter is anchored on\n * the dictionaries directory name. It matches both path separators because\n * esbuild tests the platform path, which is backslash-separated on Windows —\n * the directory name itself never contains one.\n *\n * The name alone is not proof of location, so the callback must still confirm\n * the full path lies inside `dynamicDictionariesDir`.\n *\n * @param dynamicDictionariesDir - Absolute dictionaries root, any separator.\n */\nexport const createDynamicEntryFilter = (\n dynamicDictionariesDir: string\n): RegExp => {\n const directoryName =\n dynamicDictionariesDir.split(/[\\\\/]/).filter(Boolean).pop() ?? '';\n\n return new RegExp(\n `[\\\\\\\\/]${escapeRegExp(directoryName)}[\\\\\\\\/][^\\\\\\\\/]+\\\\.mjs$`\n );\n};\n\n/**\n * Specifier of the module the injected preamble reads the locale from, as the\n * bundler plugins are expected to resolve it.\n *\n * Never emitted as-is: a generated entry point lives in the *application's*\n * `.intlayer` directory, and an application depends on `intlayer` and its\n * framework binding — not on `@intlayer/core` — so a bare specifier would\n * resolve from a directory where the package is absent, or, worse, silently\n * hit an unrelated copy hoisted higher up the tree.\n */\nexport const PRELOAD_MODULE_SPECIFIER = '@intlayer/core/localization';\n\n/** Package and subpath {@link PRELOAD_MODULE_SPECIFIER} is composed of. */\nconst PRELOAD_PACKAGE_NAME = '@intlayer/core';\nconst PRELOAD_PACKAGE_SUBPATH = './localization';\n\n/** The subset of a `package.json` this resolution reads. */\ntype PackageManifest = {\n exports?: Record<string, { import?: string } | string | undefined>;\n};\n\n/**\n * Resolves {@link PRELOAD_MODULE_SPECIFIER} to an absolute id the injected\n * preamble can import, from a package that actually depends on it.\n *\n * Deliberately not `require.resolve(PRELOAD_MODULE_SPECIFIER)`: that applies\n * the `require` condition and lands on the package's CommonJS build, which the\n * preamble would then pull into a *browser* bundle behind a CommonJS interop\n * wrapper — a second copy of the module alongside the ESM one the application\n * already imports, each with its own memoized locale. The manifest is resolved\n * instead (a condition-free subpath) and its `import` entry read directly.\n *\n * @param requireFn - `require`, or `createRequire(import.meta.url)`, from the\n * plugin package.\n * @returns Absolute path to the ESM build, falling back to whatever the\n * standard resolution yields if the package ever stops publishing one.\n */\nexport const resolvePreloadModuleId = (requireFn: NodeRequire): string => {\n const manifestPath = requireFn.resolve(\n `${PRELOAD_PACKAGE_NAME}/package.json`\n );\n const manifest = requireFn(manifestPath) as PackageManifest;\n const subpathExport = manifest.exports?.[PRELOAD_PACKAGE_SUBPATH];\n\n const esmEntry =\n typeof subpathExport === 'string' ? subpathExport : subpathExport?.import;\n\n if (!esmEntry) return requireFn.resolve(PRELOAD_MODULE_SPECIFIER);\n\n return resolve(dirname(manifestPath), esmEntry);\n};\n\n/**\n * Builds the import the injected preamble relies on, hoisted ahead of the\n * generated source.\n *\n * @param preloadModuleId - Specifier resolving to {@link PRELOAD_MODULE_SPECIFIER}\n * from the plugin package, which does depend on it.\n */\nconst buildPreloadImport = (preloadModuleId: string): string =>\n `import { getPreloadLocale as __intlayerGetPreloadLocale } from '${preloadModuleId}';\\n`;\n\n/**\n * Preamble appended to a generated dynamic entry point.\n *\n * The load is started while the entry point evaluates, but is deliberately\n * *not* awaited at the top level. Awaiting would make the entry point an async\n * module, which delays the resolution of every chunk that statically imports\n * it — including the chunks behind a `React.lazy` boundary. A boundary whose\n * module resolves that late during hydration stays on its fallback for good:\n * the framework has already swapped the server markup for the pending state and\n * does not retry, so the section never appears. Starting the request here and\n * letting the reader pick the result up keeps the whole benefit of the early\n * fetch without ever holding up module evaluation.\n *\n * The gain is in *when* the request starts: it leaves as soon as the chunk that\n * needs the dictionary is evaluated — on a router's `import()` of a route,\n * including a preload on hover — rather than once the consuming component\n * renders. By the time the reader runs, the marker is usually already set and\n * the read is synchronous, so no loading state is revealed.\n *\n * Only the resolved locale is requested, so a page still downloads exactly the\n * language it renders.\n *\n * A failed load is swallowed: leaving the marker unset drops the read back onto\n * the asynchronous path, where the existing loading state surfaces the error.\n */\nconst PRELOAD_PREAMBLE = [\n '',\n '// Injected by Intlayer: starts the browsing locale load with this module.',\n 'const __intlayerLocale = __intlayerGetPreloadLocale();',\n `const __intlayerLoader = ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}[__intlayerLocale];`,\n '',\n `if (typeof window !== 'undefined' && typeof __intlayerLoader === 'function') {`,\n ' __intlayerLoader().then(',\n ' (__intlayerDictionary) => {',\n ` ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}['${PRELOADED_DYNAMIC_KEY}'] = {`,\n ' locale: __intlayerLocale,',\n ' dictionary: __intlayerDictionary,',\n ' };',\n ' },',\n ' () => undefined',\n ' );',\n '}',\n '',\n].join('\\n');\n\n/** Why a generated entry point was left untransformed. */\nexport type PreloadSkipReason = 'qualified' | 'unrecognized-shape';\n\nexport type PreloadTransformResult =\n | { code: string; skipped?: undefined }\n | { code?: undefined; skipped: PreloadSkipReason };\n\n/**\n * Adds the browsing-locale preload to a generated dynamic entry point.\n *\n * Bundler-agnostic on purpose: the Vite plugin and the esbuild plugin apply the\n * identical transform, and keeping one implementation means the emitted shape\n * cannot drift between them. The caller decides *which* modules to hand over\n * (the id is matched against the dynamic dictionaries directory) and how to\n * report a skip.\n *\n * @param code - Source of the generated `<key>.mjs` entry point.\n * @param preloadModuleId - Specifier the preamble imports the locale resolver\n * from, already resolved against the plugin package.\n * @returns The transformed source, or the reason it was left alone.\n */\nexport const addDynamicEntryPreload = (\n code: string,\n preloadModuleId: string\n): PreloadTransformResult => {\n // Qualified entry points (collections, variants) expose a nested tree of\n // loaders per locale rather than one loader, so preloading them would have to\n // guess which coordinate the call site targets — and would fetch every chunk\n // to avoid guessing wrong.\n if (code.includes(QUALIFIER_DYNAMIC_TYPES_KEY)) {\n return { skipped: 'qualified' };\n }\n\n // The preamble mutates the generated binding; if the code generator ever\n // stops emitting it, skipping keeps the build correct (and merely\n // unoptimized) instead of emitting a reference error.\n if (!code.includes(`const ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER} =`)) {\n return { skipped: 'unrecognized-shape' };\n }\n\n return {\n code: buildPreloadImport(preloadModuleId) + code + PRELOAD_PREAMBLE,\n };\n};\n"],"mappings":";;;;;;;;;;AAYA,MAAa,wBAAwB;;AAGrC,MAAM,gBAAgB,UACpB,MAAM,QAAQ,uBAAuB,MAAM;;;;;;;;;;;;;;;;;AAkB7C,MAAa,4BACX,2BACW;CACX,MAAM,gBACJ,uBAAuB,MAAM,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK;CAEjE,OAAO,IAAI,OACT,UAAU,aAAa,aAAa,EAAE,wBACxC;AACF;;;;;;;;;;;AAYA,MAAa,2BAA2B;;AAGxC,MAAM,uBAAuB;AAC7B,MAAM,0BAA0B;;;;;;;;;;;;;;;;;AAuBhC,MAAa,0BAA0B,cAAmC;CACxE,MAAM,eAAe,UAAU,QAC7B,GAAG,qBAAqB,cAC1B;CAEA,MAAM,gBADW,UAAU,YACE,CAAC,CAAC,UAAU;CAEzC,MAAM,WACJ,OAAO,kBAAkB,WAAW,gBAAgB,eAAe;CAErE,IAAI,CAAC,UAAU,OAAO,UAAU,QAAQ,wBAAwB;CAEhE,WAAOA,uBAAQC,mBAAQ,YAAY,GAAG,QAAQ;AAChD;;;;;;;;AASA,MAAM,sBAAsB,oBAC1B,mEAAmE,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BrF,MAAM,mBAAmB;CACvB;CACA;CACA;CACA,4BAA4BC,qEAAoC;CAChE;CACA;CACA;CACA;CACA,SAASA,qEAAoC,IAAIC,uDAAsB;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;AAuBX,MAAa,0BACX,MACA,oBAC2B;CAK3B,IAAI,KAAK,mCAAoC,GAC3C,OAAO,EAAE,SAAS,YAAY;CAMhC,IAAI,CAAC,KAAK,SAAS,mBAA6C,GAAG,GACjE,OAAO,EAAE,SAAS,qBAAqB;CAGzC,OAAO,EACL,MAAM,mBAAmB,eAAe,IAAI,OAAO,iBACrD;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAlias } from "../utils/alias.mjs";
|
|
2
2
|
import { getConfiguration } from "../configFile/getConfiguration.mjs";
|
|
3
|
-
import { BundleLogger } from "./logBundle.mjs";
|
|
4
3
|
import { getConfigEnvVars } from "../envVars/envVars.mjs";
|
|
4
|
+
import { BundleLogger } from "./logBundle.mjs";
|
|
5
5
|
import { isAbsolute, join, resolve } from "node:path";
|
|
6
6
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
7
|
import configPackageJson from "@intlayer/types/package.json" with { type: "json" };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __require } from "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
-
import { BUILD_MODE, CACHE, MINIFY, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "../defaultValues/build.mjs";
|
|
2
|
+
import { BUILD_MODE, CACHE, CHUNK_GROUPING, DICTIONARIES_PRELOAD, MINIFY, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "../defaultValues/build.mjs";
|
|
3
3
|
import { COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS } from "../defaultValues/compiler.mjs";
|
|
4
4
|
import { CODE_DIR, CONTENT_DIR, EXCLUDED_PATHS, FILE_EXTENSIONS, WATCH } from "../defaultValues/content.mjs";
|
|
5
5
|
import { CONTENT_AUTO_TRANSFORMATION, FILL, IMPORT_MODE, LOCATION } from "../defaultValues/dictionary.mjs";
|
|
@@ -256,6 +256,30 @@ const buildBuildFields = (customConfiguration) => ({
|
|
|
256
256
|
*/
|
|
257
257
|
purge: customConfiguration?.purge ?? false,
|
|
258
258
|
/**
|
|
259
|
+
* Group the per-locale dictionary chunks by the code-split boundary that uses
|
|
260
|
+
* them, so a lazily loaded page fetches its content in one request.
|
|
261
|
+
*
|
|
262
|
+
* Default: true
|
|
263
|
+
*
|
|
264
|
+
* Note:
|
|
265
|
+
* - Only applies to dictionaries using `importMode: 'dynamic'`.
|
|
266
|
+
* - Only applies to the client build, and only when bundling (not in dev).
|
|
267
|
+
*/
|
|
268
|
+
chunkGrouping: customConfiguration?.chunkGrouping ?? true,
|
|
269
|
+
/**
|
|
270
|
+
* Load a dictionary together with the chunk that uses it, instead of fetching
|
|
271
|
+
* it once that chunk renders — so a reader renders synchronously rather than
|
|
272
|
+
* suspending, and navigating no longer flashes a loading state.
|
|
273
|
+
*
|
|
274
|
+
* Default: true
|
|
275
|
+
*
|
|
276
|
+
* Note:
|
|
277
|
+
* - Only applies to dictionaries using `importMode: 'dynamic'`.
|
|
278
|
+
* - Only applies to the client build; the server keeps loading on demand.
|
|
279
|
+
* - Requires a bundler supporting top-level await (Vite, esbuild).
|
|
280
|
+
*/
|
|
281
|
+
dictionariesPreload: customConfiguration?.dictionariesPreload ?? true,
|
|
282
|
+
/**
|
|
259
283
|
* Pattern to traverse the code to optimize.
|
|
260
284
|
*
|
|
261
285
|
* Allows to avoid to traverse the code that is not relevant to the optimization.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildConfigurationFields.mjs","names":[],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type {\n AiConfig,\n BuildConfig,\n CompilerConfig,\n ContentConfig,\n CustomIntlayerConfig,\n DictionaryConfig,\n IntlayerConfig,\n LogFunctions,\n SystemConfig,\n} from '@intlayer/types/config';\nimport {\n BUILD_MODE,\n CACHE,\n MINIFY,\n OUTPUT_FORMAT,\n PURGE,\n TRAVERSE_PATTERN,\n TYPE_CHECKING,\n} from '../defaultValues/build';\nimport {\n COMPILER_DICTIONARY_KEY_PREFIX,\n COMPILER_ENABLED,\n COMPILER_NO_METADATA,\n COMPILER_SAVE_COMPONENTS,\n} from '../defaultValues/compiler';\nimport {\n CODE_DIR,\n CONTENT_DIR,\n EXCLUDED_PATHS,\n FILE_EXTENSIONS,\n WATCH,\n} from '../defaultValues/content';\nimport {\n CONTENT_AUTO_TRANSFORMATION,\n FILL,\n IMPORT_MODE,\n LOCATION,\n} from '../defaultValues/dictionary';\nimport {\n CACHE_DIR,\n CONFIG_DIR,\n DICTIONARIES_DIR,\n DYNAMIC_DICTIONARIES_DIR,\n FETCH_DICTIONARIES_DIR,\n MAIN_DIR,\n MODULE_AUGMENTATION_DIR,\n REMOTE_DICTIONARIES_DIR,\n TEMP_DIR,\n TYPES_DIR,\n UNMERGED_DICTIONARIES_DIR,\n} from '../defaultValues/system';\nimport { getProjectRequire } from '../utils';\nimport {\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n} from './buildBrowserConfiguration';\nimport { intlayerConfigSchema } from './configurationSchema';\n\nexport {\n type BrowserIntlayerConfig,\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n buildRoutingFields,\n extractBrowserConfiguration,\n} from './buildBrowserConfiguration';\n\nlet storedConfiguration: IntlayerConfig;\n\n// ---------------------------------------------------------------------------\n// Server-only field builders (Node.js — not browser-safe)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the `system` section of the Intlayer configuration.\n *\n * Resolves all directory paths (dictionaries, types, cache, …) relative to\n * the project base directory, using Node.js `require.resolve` where available\n * and falling back to `path.join` otherwise.\n *\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param customConfiguration - Partial user-supplied system config.\n * @returns A fully-resolved {@link SystemConfig}.\n */\nconst buildSystemFields = (\n baseDir?: string,\n customConfiguration?: Partial<SystemConfig>\n): SystemConfig => {\n const projectBaseDir = baseDir ?? process.cwd();\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(projectBaseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [projectBaseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [projectBaseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(projectBaseDir, pathInput);\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const dictionariesDir = optionalJoinBaseDir(\n customConfiguration?.dictionariesDir ?? DICTIONARIES_DIR\n );\n\n return {\n baseDir: projectBaseDir,\n moduleAugmentationDir: optionalJoinBaseDir(\n customConfiguration?.moduleAugmentationDir ?? MODULE_AUGMENTATION_DIR\n ),\n unmergedDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.unmergedDictionariesDir ?? UNMERGED_DICTIONARIES_DIR\n ),\n remoteDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.remoteDictionariesDir ?? REMOTE_DICTIONARIES_DIR\n ),\n dictionariesDir,\n dynamicDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.dynamicDictionariesDir ?? DYNAMIC_DICTIONARIES_DIR\n ),\n fetchDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.fetchDictionariesDir ?? FETCH_DICTIONARIES_DIR\n ),\n typesDir: optionalJoinBaseDir(customConfiguration?.typesDir ?? TYPES_DIR),\n mainDir: optionalJoinBaseDir(customConfiguration?.mainDir ?? MAIN_DIR),\n configDir: optionalJoinBaseDir(\n customConfiguration?.configDir ?? CONFIG_DIR\n ),\n cacheDir: optionalJoinBaseDir(customConfiguration?.cacheDir ?? CACHE_DIR),\n tempDir: optionalJoinBaseDir(customConfiguration?.tempDir ?? TEMP_DIR),\n };\n};\n\n/**\n * Build the `content` section of the Intlayer configuration.\n *\n * Resolves content and code directories relative to the project base using\n * `require.resolve`, falling back to `path.join`.\n *\n * @param systemConfig - Already-built system configuration (provides `baseDir`).\n * @param customConfiguration - Partial user-supplied content config.\n * @returns A fully-resolved {@link ContentConfig}.\n */\nconst buildContentFields = (\n systemConfig: SystemConfig,\n customConfiguration?: Partial<ContentConfig>\n): ContentConfig => {\n const fileExtensions = customConfiguration?.fileExtensions ?? FILE_EXTENSIONS;\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(systemConfig.baseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n try {\n try {\n absolutePath = require.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = require.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(systemConfig.baseDir, pathInput);\n }\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const contentDir = (customConfiguration?.contentDir ?? CONTENT_DIR).map(\n optionalJoinBaseDir\n );\n const codeDir = (customConfiguration?.codeDir ?? CODE_DIR).map(\n optionalJoinBaseDir\n );\n\n return {\n fileExtensions,\n contentDir,\n codeDir,\n excludedPath: customConfiguration?.excludedPath ?? EXCLUDED_PATHS,\n watch: customConfiguration?.watch ?? WATCH,\n formatCommand: customConfiguration?.formatCommand,\n };\n};\n\n/**\n * Build the `ai` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied AI config.\n * @returns A fully-defaulted {@link AiConfig}.\n */\nconst buildAiFields = (customConfiguration?: Partial<AiConfig>): AiConfig => ({\n /**\n * AI configuration\n */\n provider: customConfiguration?.provider,\n\n /**\n * API key\n */\n apiKey: customConfiguration?.apiKey,\n\n /**\n * API model\n */\n model: customConfiguration?.model,\n\n /**\n * Temperature\n */\n temperature: customConfiguration?.temperature,\n\n /**\n * Application context\n *\n * Default: undefined\n *\n * The application context.\n *\n * Example: `'My application context'`\n *\n * Note: Can be used to provide additional context about the application to the AI model. You can add more rules (e.g. \"You should not transform urls\").\n */\n applicationContext: customConfiguration?.applicationContext,\n\n /**\n * Base URL for the AI API\n *\n * Default: undefined\n *\n * The base URL for the AI API.\n *\n * Example: `'http://localhost:5000'`\n *\n * Note: Can be used to point to a local, or custom AI API endpoint.\n */\n baseURL: customConfiguration?.baseURL,\n\n /**\n * Data serialization\n *\n * Options:\n * - \"json\": The industry standard. Highly reliable and structured, but consumes more tokens.\n * - \"toon\": An optimized format designed to reduce token consumption (cost-effective). However, it may slightly increase the risk of output inconsistency compared to standard JSON\n *\n * Default: `\"json\"`\n */\n dataSerialization: customConfiguration?.dataSerialization,\n});\n\n/**\n * Build the `build` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied build config.\n * @returns A fully-defaulted {@link BuildConfig}.\n */\nconst buildBuildFields = (\n customConfiguration?: Partial<BuildConfig>\n): BuildConfig => ({\n /**\n * Indicates the mode of the build\n *\n * Default: 'auto'\n *\n * If 'auto', the build will be enabled automatically when the application is built.\n * If 'manual', the build will be set only when the build command is executed.\n *\n * Can be used to disable dictionaries build, for instance when execution on Node.js environment should be avoided.\n */\n mode: customConfiguration?.mode ?? BUILD_MODE,\n\n /**\n * Indicates if the build should be optimized\n *\n * Default: process.env.NODE_ENV === 'production'\n *\n * If true, the build will be optimized.\n * If false, the build will not be optimized.\n *\n * Intlayer will replace all calls of dictionaries to optimize chunking. That way the final bundle will import only the dictionaries that are used.\n * All imports will stay as static import to avoid async processing when loading the dictionaries.\n *\n * Note:\n * - Intlayer will replace all call of `useIntlayer` with the defined mode by the `importMode` option.\n * - Intlayer will replace all call of `getIntlayer` with `getDictionary`.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - In most cases, \"dynamic\" will be used for React applications, \"async\" for Vue.js applications.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n */\n optimize: customConfiguration?.optimize,\n\n /**\n * Indicates the mode of import to use for the dictionaries.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as \"dynamic\" mode.\n *\n * Default: \"static\"\n *\n * By default, when a dictionary is loaded, it imports content for all locales as it's imported statically.\n *\n * Note:\n * - Dynamic imports rely on Suspense and may slightly impact rendering performance.\n * - If disabled all locales will be loaded at once, even if they are not used.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n * - This option will be ignored if `optimize` is disabled.\n * - This option will not impact the `getIntlayer`, `getDictionary`, `useDictionary`, `useDictionaryAsync` and `useDictionaryDynamic` functions. You can still use them to refine you code on manual optimization.\n * - The \"live\" allows to sync the dictionaries to the live sync server.\n *\n * @deprecated Use `dictionary.importMode` instead.\n */\n importMode: customConfiguration?.importMode,\n\n /**\n * Minify the dictionaries to reduce the bundle size.\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignore if `editor.enabled` is true.\n * - If there is edge cases where the minification is not working properly, the dictionary will be not minified.\n */\n minify: customConfiguration?.minify ?? MINIFY,\n\n /**\n * Purge the unused keys in a dictionaries\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignored if `editor.enabled` is true.\n */\n purge: customConfiguration?.purge ?? PURGE,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * Allows to avoid to traverse the code that is not relevant to the optimization.\n * Improve build performance.\n *\n * Default: ['**\\/*.{js,ts,mjs,cjs,jsx,tsx}', '!**\\/node_modules/**']\n *\n * Example: `['src/**\\/*.{ts,tsx}', '../ui-library/**\\/*.{ts,tsx}']`\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - Use glob pattern.\n */\n traversePattern: customConfiguration?.traversePattern ?? TRAVERSE_PATTERN,\n\n /**\n * Output format of the dictionaries\n *\n * Can be set on large projects to improve build performance.\n *\n * Default: ['cjs', 'esm']\n *\n * The output format of the dictionaries. It can be either 'cjs' or 'esm'.\n * - 'cjs': The dictionaries are outputted as CommonJS modules.\n * - 'esm': The dictionaries are outputted as ES modules.\n */\n outputFormat: customConfiguration?.outputFormat ?? OUTPUT_FORMAT,\n\n /**\n * Cache\n */\n cache: customConfiguration?.cache ?? CACHE,\n\n /**\n * Require function\n */\n require: customConfiguration?.require,\n\n /**\n * Indicates if the build should check TypeScript types\n *\n * Default: `false`\n *\n * If true, the build will check TypeScript types and log errors.\n * Note: This can slow down the build.\n */\n checkTypes: customConfiguration?.checkTypes ?? TYPE_CHECKING,\n});\n\n/**\n * Build the `compiler` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied compiler config.\n * @returns A fully-defaulted {@link CompilerConfig}.\n */\nconst buildCompilerFields = (\n customConfiguration?: Partial<CompilerConfig>\n): CompilerConfig => ({\n /**\n * Indicates if the compiler should be enabled\n */\n enabled: customConfiguration?.enabled ?? COMPILER_ENABLED,\n\n /**\n * Prefix for the extracted dictionary keys\n */\n dictionaryKeyPrefix:\n customConfiguration?.dictionaryKeyPrefix ?? COMPILER_DICTIONARY_KEY_PREFIX,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * @deprecated use `build.traversePattern` instead\n */\n transformPattern: customConfiguration?.transformPattern,\n\n /**\n * Pattern to exclude from the optimization.\n *\n * @deprecated use `build.traversePattern` instead\n */\n excludePattern: customConfiguration?.excludePattern,\n\n /**\n * Defines the output files path. Replaces `outputDir`.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - Including the `{{locale}}` variable in the path will trigger the generation of separate dictionaries per locale.\n *\n * @example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * output: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // output: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * output: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // output: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create per-locale JSON files with locale-specific output paths\n * output: {\n * en: ({ fileName, locale }) => `${fileName}.${locale}.content.json`,\n * fr: '{{fileName}}.{{locale}}.content.json',\n * es: false, // skip this locale\n * },\n * }\n * ```\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n output: customConfiguration?.output,\n\n /**\n * Indicates if the metadata should be saved in the file.\n *\n * If true, the compiler will not save the metadata of the dictionaries.\n *\n * If `true`:\n *\n * ```json\n * {\n * \"key\": \"value\"\n * }\n * ```\n *\n * If `false`:\n *\n * ```json\n * {\n * \"key\": \"value\",\n * \"content\": {\n * \"key\": \"value\"\n * }\n * }\n * ```\n *\n * Default: `false`\n *\n * Note: Useful if used with loadJSON plugin\n */\n noMetadata: customConfiguration?.noMetadata ?? COMPILER_NO_METADATA,\n\n /**\n * Indicates if the components should be saved after being transformed.\n */\n saveComponents:\n customConfiguration?.saveComponents ?? COMPILER_SAVE_COMPONENTS,\n});\n\n/**\n * Build the `dictionary` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied dictionary config.\n * @returns A fully-defaulted {@link DictionaryConfig}.\n */\nconst buildDictionaryFields = (\n customConfiguration?: Partial<DictionaryConfig>\n): DictionaryConfig => {\n const contentAutoTransformation =\n customConfiguration?.contentAutoTransformation ??\n CONTENT_AUTO_TRANSFORMATION;\n\n return {\n /**\n * Indicate how the dictionary should be filled using AI.\n *\n * Default: `true`\n *\n * - If `true`, will consider the `compiler.output` field.\n * - If `false`, will skip the fill process.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.\n *\n * Example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * fill: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // fill: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create custom output based on the locale\n * fill: {\n * en: ({ key }) => `/locales/en/${key}.content.json`,\n * fr: '/locales/fr/{{key}}.content.json',\n * es: false,\n * de: true,\n * },\n * }\n * ```\n *\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n fill: customConfiguration?.fill ?? FILL,\n\n /**\n * Indicates if the content of the dictionary should be automatically transformed.\n *\n * Default: `false`\n */\n contentAutoTransformation:\n typeof contentAutoTransformation === 'object'\n ? {\n markdown: contentAutoTransformation.markdown ?? false,\n html: contentAutoTransformation.html ?? false,\n insertion: contentAutoTransformation.insertion ?? false,\n }\n : contentAutoTransformation,\n\n /**\n * The location of the dictionary.\n *\n * Default: `\"local\"`\n */\n location: customConfiguration?.location ?? LOCATION,\n\n /**\n * Transform the dictionary in a per-locale dictionary.\n * Each field declared in a per-locale dictionary will be transformed in a translation node.\n * If missing, the dictionary will be treated as a multilingual dictionary.\n */\n locale: customConfiguration?.locale,\n\n /**\n * The title of the dictionary.\n */\n title: customConfiguration?.title,\n\n /**\n * The description of the dictionary.\n */\n description: customConfiguration?.description,\n\n /**\n * Tags to categorize the dictionaries.\n */\n tags: customConfiguration?.tags,\n\n /**\n * The priority of the dictionary.\n */\n priority: customConfiguration?.priority,\n\n /**\n * Indicates the mode of import to use for the dictionary.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n *\n * Default: `\"static\"`\n */\n importMode: customConfiguration?.importMode ?? IMPORT_MODE,\n\n /**\n * The default message format for all dictionaries in the project.\n *\n * Default: 'intlayer'\n */\n format: customConfiguration?.format,\n };\n};\n\n// ---------------------------------------------------------------------------\n// Main export\n// ---------------------------------------------------------------------------\n\n/**\n * Build the complete Intlayer configuration by merging user-supplied values\n * with defaults.\n *\n * Internally this function:\n * 1. Calls {@link buildBrowserConfiguration} to produce the browser-safe\n * subset (internationalization, routing, editor public fields, log, metadata).\n * 2. Extends the result with full server-side fields:\n * - `internationalization` — adds `requiredLocales` and `strictMode`.\n * - `editor` — adds `clientId` and `clientSecret`.\n * - `log` — adds custom log functions.\n * - `system`, `content`, `ai`, `build`, `compiler`, `dictionary`.\n *\n * @param customConfiguration - Optional user-supplied configuration object.\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param logFunctions - Optional custom logging functions.\n * @returns A fully-built {@link IntlayerConfig}.\n */\nexport const buildConfigurationFields = (\n customConfiguration?: CustomIntlayerConfig,\n baseDir?: string,\n logFunctions?: LogFunctions\n): IntlayerConfig => {\n if (customConfiguration) {\n const result = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!result.success) {\n const logError = logFunctions?.error ?? console.error;\n\n for (const issue of result.error.issues) {\n logError(`${issue.path.join('.')}: ${issue.message}`);\n }\n }\n }\n\n // build browser-safe config (shared defaults, no Node.js deps)\n const browserConfig = buildBrowserConfiguration(customConfiguration);\n\n // extend shared fields with server-only additions\n const internationalizationConfig = buildInternationalizationFields(\n customConfiguration?.internationalization\n );\n\n const editorConfig = buildEditorFields(customConfiguration?.editor);\n\n const logConfig = buildLogFields(customConfiguration?.log, logFunctions);\n\n // build server-only fields\n const systemConfig = buildSystemFields(baseDir, customConfiguration?.system);\n\n const contentConfig = buildContentFields(\n systemConfig,\n customConfiguration?.content\n );\n\n storedConfiguration = {\n // Shared browser fields\n routing: browserConfig.routing,\n // Full (extended) shared fields\n internationalization: internationalizationConfig,\n editor: editorConfig,\n analytics: buildAnalyticsFields(customConfiguration?.analytics),\n log: logConfig,\n // Server-only fields\n system: systemConfig,\n content: contentConfig,\n ai: buildAiFields(customConfiguration?.ai),\n build: buildBuildFields(customConfiguration?.build),\n compiler: buildCompilerFields(customConfiguration?.compiler),\n dictionary: buildDictionaryFields(customConfiguration?.dictionary),\n plugins: customConfiguration?.plugins,\n schemas: customConfiguration?.schemas,\n } as IntlayerConfig;\n\n return storedConfiguration;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"buildConfigurationFields.mjs","names":[],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type {\n AiConfig,\n BuildConfig,\n CompilerConfig,\n ContentConfig,\n CustomIntlayerConfig,\n DictionaryConfig,\n IntlayerConfig,\n LogFunctions,\n SystemConfig,\n} from '@intlayer/types/config';\nimport {\n BUILD_MODE,\n CACHE,\n CHUNK_GROUPING,\n DICTIONARIES_PRELOAD,\n MINIFY,\n OUTPUT_FORMAT,\n PURGE,\n TRAVERSE_PATTERN,\n TYPE_CHECKING,\n} from '../defaultValues/build';\nimport {\n COMPILER_DICTIONARY_KEY_PREFIX,\n COMPILER_ENABLED,\n COMPILER_NO_METADATA,\n COMPILER_SAVE_COMPONENTS,\n} from '../defaultValues/compiler';\nimport {\n CODE_DIR,\n CONTENT_DIR,\n EXCLUDED_PATHS,\n FILE_EXTENSIONS,\n WATCH,\n} from '../defaultValues/content';\nimport {\n CONTENT_AUTO_TRANSFORMATION,\n FILL,\n IMPORT_MODE,\n LOCATION,\n} from '../defaultValues/dictionary';\nimport {\n CACHE_DIR,\n CONFIG_DIR,\n DICTIONARIES_DIR,\n DYNAMIC_DICTIONARIES_DIR,\n FETCH_DICTIONARIES_DIR,\n MAIN_DIR,\n MODULE_AUGMENTATION_DIR,\n REMOTE_DICTIONARIES_DIR,\n TEMP_DIR,\n TYPES_DIR,\n UNMERGED_DICTIONARIES_DIR,\n} from '../defaultValues/system';\nimport { getProjectRequire } from '../utils';\nimport {\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n} from './buildBrowserConfiguration';\nimport { intlayerConfigSchema } from './configurationSchema';\n\nexport {\n type BrowserIntlayerConfig,\n buildAnalyticsFields,\n buildBrowserConfiguration,\n buildEditorFields,\n buildInternationalizationFields,\n buildLogFields,\n buildRoutingFields,\n extractBrowserConfiguration,\n} from './buildBrowserConfiguration';\n\nlet storedConfiguration: IntlayerConfig;\n\n// ---------------------------------------------------------------------------\n// Server-only field builders (Node.js — not browser-safe)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the `system` section of the Intlayer configuration.\n *\n * Resolves all directory paths (dictionaries, types, cache, …) relative to\n * the project base directory, using Node.js `require.resolve` where available\n * and falling back to `path.join` otherwise.\n *\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param customConfiguration - Partial user-supplied system config.\n * @returns A fully-resolved {@link SystemConfig}.\n */\nconst buildSystemFields = (\n baseDir?: string,\n customConfiguration?: Partial<SystemConfig>\n): SystemConfig => {\n const projectBaseDir = baseDir ?? process.cwd();\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(projectBaseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [projectBaseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [projectBaseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(projectBaseDir, pathInput);\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const dictionariesDir = optionalJoinBaseDir(\n customConfiguration?.dictionariesDir ?? DICTIONARIES_DIR\n );\n\n return {\n baseDir: projectBaseDir,\n moduleAugmentationDir: optionalJoinBaseDir(\n customConfiguration?.moduleAugmentationDir ?? MODULE_AUGMENTATION_DIR\n ),\n unmergedDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.unmergedDictionariesDir ?? UNMERGED_DICTIONARIES_DIR\n ),\n remoteDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.remoteDictionariesDir ?? REMOTE_DICTIONARIES_DIR\n ),\n dictionariesDir,\n dynamicDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.dynamicDictionariesDir ?? DYNAMIC_DICTIONARIES_DIR\n ),\n fetchDictionariesDir: optionalJoinBaseDir(\n customConfiguration?.fetchDictionariesDir ?? FETCH_DICTIONARIES_DIR\n ),\n typesDir: optionalJoinBaseDir(customConfiguration?.typesDir ?? TYPES_DIR),\n mainDir: optionalJoinBaseDir(customConfiguration?.mainDir ?? MAIN_DIR),\n configDir: optionalJoinBaseDir(\n customConfiguration?.configDir ?? CONFIG_DIR\n ),\n cacheDir: optionalJoinBaseDir(customConfiguration?.cacheDir ?? CACHE_DIR),\n tempDir: optionalJoinBaseDir(customConfiguration?.tempDir ?? TEMP_DIR),\n };\n};\n\n/**\n * Build the `content` section of the Intlayer configuration.\n *\n * Resolves content and code directories relative to the project base using\n * `require.resolve`, falling back to `path.join`.\n *\n * @param systemConfig - Already-built system configuration (provides `baseDir`).\n * @param customConfiguration - Partial user-supplied content config.\n * @returns A fully-resolved {@link ContentConfig}.\n */\nconst buildContentFields = (\n systemConfig: SystemConfig,\n customConfiguration?: Partial<ContentConfig>\n): ContentConfig => {\n const fileExtensions = customConfiguration?.fileExtensions ?? FILE_EXTENSIONS;\n\n const optionalJoinBaseDir = (pathInput: string) => {\n let absolutePath: string;\n\n try {\n const requireFunction = getProjectRequire(systemConfig.baseDir);\n try {\n absolutePath = requireFunction.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = requireFunction.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n try {\n try {\n absolutePath = require.resolve(pathInput, {\n paths: [systemConfig.baseDir],\n });\n } catch (err) {\n if (!pathInput.startsWith('.') && !isAbsolute(pathInput)) {\n absolutePath = require.resolve(`${pathInput}/package.json`, {\n paths: [systemConfig.baseDir],\n });\n } else {\n throw err;\n }\n }\n } catch {\n absolutePath = isAbsolute(pathInput)\n ? pathInput\n : join(systemConfig.baseDir, pathInput);\n }\n }\n\n try {\n const stats = statSync(absolutePath);\n if (stats.isFile()) {\n return dirname(absolutePath);\n }\n } catch {\n if (/\\.[a-z0-9]+$/i.test(absolutePath)) {\n return dirname(absolutePath);\n }\n }\n\n return absolutePath;\n };\n\n const contentDir = (customConfiguration?.contentDir ?? CONTENT_DIR).map(\n optionalJoinBaseDir\n );\n const codeDir = (customConfiguration?.codeDir ?? CODE_DIR).map(\n optionalJoinBaseDir\n );\n\n return {\n fileExtensions,\n contentDir,\n codeDir,\n excludedPath: customConfiguration?.excludedPath ?? EXCLUDED_PATHS,\n watch: customConfiguration?.watch ?? WATCH,\n formatCommand: customConfiguration?.formatCommand,\n };\n};\n\n/**\n * Build the `ai` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied AI config.\n * @returns A fully-defaulted {@link AiConfig}.\n */\nconst buildAiFields = (customConfiguration?: Partial<AiConfig>): AiConfig => ({\n /**\n * AI configuration\n */\n provider: customConfiguration?.provider,\n\n /**\n * API key\n */\n apiKey: customConfiguration?.apiKey,\n\n /**\n * API model\n */\n model: customConfiguration?.model,\n\n /**\n * Temperature\n */\n temperature: customConfiguration?.temperature,\n\n /**\n * Application context\n *\n * Default: undefined\n *\n * The application context.\n *\n * Example: `'My application context'`\n *\n * Note: Can be used to provide additional context about the application to the AI model. You can add more rules (e.g. \"You should not transform urls\").\n */\n applicationContext: customConfiguration?.applicationContext,\n\n /**\n * Base URL for the AI API\n *\n * Default: undefined\n *\n * The base URL for the AI API.\n *\n * Example: `'http://localhost:5000'`\n *\n * Note: Can be used to point to a local, or custom AI API endpoint.\n */\n baseURL: customConfiguration?.baseURL,\n\n /**\n * Data serialization\n *\n * Options:\n * - \"json\": The industry standard. Highly reliable and structured, but consumes more tokens.\n * - \"toon\": An optimized format designed to reduce token consumption (cost-effective). However, it may slightly increase the risk of output inconsistency compared to standard JSON\n *\n * Default: `\"json\"`\n */\n dataSerialization: customConfiguration?.dataSerialization,\n});\n\n/**\n * Build the `build` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied build config.\n * @returns A fully-defaulted {@link BuildConfig}.\n */\nconst buildBuildFields = (\n customConfiguration?: Partial<BuildConfig>\n): BuildConfig => ({\n /**\n * Indicates the mode of the build\n *\n * Default: 'auto'\n *\n * If 'auto', the build will be enabled automatically when the application is built.\n * If 'manual', the build will be set only when the build command is executed.\n *\n * Can be used to disable dictionaries build, for instance when execution on Node.js environment should be avoided.\n */\n mode: customConfiguration?.mode ?? BUILD_MODE,\n\n /**\n * Indicates if the build should be optimized\n *\n * Default: process.env.NODE_ENV === 'production'\n *\n * If true, the build will be optimized.\n * If false, the build will not be optimized.\n *\n * Intlayer will replace all calls of dictionaries to optimize chunking. That way the final bundle will import only the dictionaries that are used.\n * All imports will stay as static import to avoid async processing when loading the dictionaries.\n *\n * Note:\n * - Intlayer will replace all call of `useIntlayer` with the defined mode by the `importMode` option.\n * - Intlayer will replace all call of `getIntlayer` with `getDictionary`.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - In most cases, \"dynamic\" will be used for React applications, \"async\" for Vue.js applications.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n */\n optimize: customConfiguration?.optimize,\n\n /**\n * Indicates the mode of import to use for the dictionaries.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.\n * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as \"dynamic\" mode.\n *\n * Default: \"static\"\n *\n * By default, when a dictionary is loaded, it imports content for all locales as it's imported statically.\n *\n * Note:\n * - Dynamic imports rely on Suspense and may slightly impact rendering performance.\n * - If disabled all locales will be loaded at once, even if they are not used.\n * - This option relies on the `@intlayer/babel` and `@intlayer/swc` plugins.\n * - Ensure all keys are declared statically in the `useIntlayer` calls. e.g. `useIntlayer('navbar')`.\n * - This option will be ignored if `optimize` is disabled.\n * - This option will not impact the `getIntlayer`, `getDictionary`, `useDictionary`, `useDictionaryAsync` and `useDictionaryDynamic` functions. You can still use them to refine you code on manual optimization.\n * - The \"live\" allows to sync the dictionaries to the live sync server.\n *\n * @deprecated Use `dictionary.importMode` instead.\n */\n importMode: customConfiguration?.importMode,\n\n /**\n * Minify the dictionaries to reduce the bundle size.\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignore if `editor.enabled` is true.\n * - If there is edge cases where the minification is not working properly, the dictionary will be not minified.\n */\n minify: customConfiguration?.minify ?? MINIFY,\n\n /**\n * Purge the unused keys in a dictionaries\n *\n * Default: false\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - This option will be ignored if `editor.enabled` is true.\n */\n purge: customConfiguration?.purge ?? PURGE,\n\n /**\n * Group the per-locale dictionary chunks by the code-split boundary that uses\n * them, so a lazily loaded page fetches its content in one request.\n *\n * Default: true\n *\n * Note:\n * - Only applies to dictionaries using `importMode: 'dynamic'`.\n * - Only applies to the client build, and only when bundling (not in dev).\n */\n chunkGrouping: customConfiguration?.chunkGrouping ?? CHUNK_GROUPING,\n\n /**\n * Load a dictionary together with the chunk that uses it, instead of fetching\n * it once that chunk renders — so a reader renders synchronously rather than\n * suspending, and navigating no longer flashes a loading state.\n *\n * Default: true\n *\n * Note:\n * - Only applies to dictionaries using `importMode: 'dynamic'`.\n * - Only applies to the client build; the server keeps loading on demand.\n * - Requires a bundler supporting top-level await (Vite, esbuild).\n */\n dictionariesPreload:\n customConfiguration?.dictionariesPreload ?? DICTIONARIES_PRELOAD,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * Allows to avoid to traverse the code that is not relevant to the optimization.\n * Improve build performance.\n *\n * Default: ['**\\/*.{js,ts,mjs,cjs,jsx,tsx}', '!**\\/node_modules/**']\n *\n * Example: `['src/**\\/*.{ts,tsx}', '../ui-library/**\\/*.{ts,tsx}']`\n *\n * Note:\n * - This option will be ignored if `optimize` is disabled.\n * - Use glob pattern.\n */\n traversePattern: customConfiguration?.traversePattern ?? TRAVERSE_PATTERN,\n\n /**\n * Output format of the dictionaries\n *\n * Can be set on large projects to improve build performance.\n *\n * Default: ['cjs', 'esm']\n *\n * The output format of the dictionaries. It can be either 'cjs' or 'esm'.\n * - 'cjs': The dictionaries are outputted as CommonJS modules.\n * - 'esm': The dictionaries are outputted as ES modules.\n */\n outputFormat: customConfiguration?.outputFormat ?? OUTPUT_FORMAT,\n\n /**\n * Cache\n */\n cache: customConfiguration?.cache ?? CACHE,\n\n /**\n * Require function\n */\n require: customConfiguration?.require,\n\n /**\n * Indicates if the build should check TypeScript types\n *\n * Default: `false`\n *\n * If true, the build will check TypeScript types and log errors.\n * Note: This can slow down the build.\n */\n checkTypes: customConfiguration?.checkTypes ?? TYPE_CHECKING,\n});\n\n/**\n * Build the `compiler` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied compiler config.\n * @returns A fully-defaulted {@link CompilerConfig}.\n */\nconst buildCompilerFields = (\n customConfiguration?: Partial<CompilerConfig>\n): CompilerConfig => ({\n /**\n * Indicates if the compiler should be enabled\n */\n enabled: customConfiguration?.enabled ?? COMPILER_ENABLED,\n\n /**\n * Prefix for the extracted dictionary keys\n */\n dictionaryKeyPrefix:\n customConfiguration?.dictionaryKeyPrefix ?? COMPILER_DICTIONARY_KEY_PREFIX,\n\n /**\n * Pattern to traverse the code to optimize.\n *\n * @deprecated use `build.traversePattern` instead\n */\n transformPattern: customConfiguration?.transformPattern,\n\n /**\n * Pattern to exclude from the optimization.\n *\n * @deprecated use `build.traversePattern` instead\n */\n excludePattern: customConfiguration?.excludePattern,\n\n /**\n * Defines the output files path. Replaces `outputDir`.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - Including the `{{locale}}` variable in the path will trigger the generation of separate dictionaries per locale.\n *\n * @example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * output: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // output: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * output: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // output: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create per-locale JSON files with locale-specific output paths\n * output: {\n * en: ({ fileName, locale }) => `${fileName}.${locale}.content.json`,\n * fr: '{{fileName}}.{{locale}}.content.json',\n * es: false, // skip this locale\n * },\n * }\n * ```\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n output: customConfiguration?.output,\n\n /**\n * Indicates if the metadata should be saved in the file.\n *\n * If true, the compiler will not save the metadata of the dictionaries.\n *\n * If `true`:\n *\n * ```json\n * {\n * \"key\": \"value\"\n * }\n * ```\n *\n * If `false`:\n *\n * ```json\n * {\n * \"key\": \"value\",\n * \"content\": {\n * \"key\": \"value\"\n * }\n * }\n * ```\n *\n * Default: `false`\n *\n * Note: Useful if used with loadJSON plugin\n */\n noMetadata: customConfiguration?.noMetadata ?? COMPILER_NO_METADATA,\n\n /**\n * Indicates if the components should be saved after being transformed.\n */\n saveComponents:\n customConfiguration?.saveComponents ?? COMPILER_SAVE_COMPONENTS,\n});\n\n/**\n * Build the `dictionary` section of the Intlayer configuration.\n *\n * @param customConfiguration - Partial user-supplied dictionary config.\n * @returns A fully-defaulted {@link DictionaryConfig}.\n */\nconst buildDictionaryFields = (\n customConfiguration?: Partial<DictionaryConfig>\n): DictionaryConfig => {\n const contentAutoTransformation =\n customConfiguration?.contentAutoTransformation ??\n CONTENT_AUTO_TRANSFORMATION;\n\n return {\n /**\n * Indicate how the dictionary should be filled using AI.\n *\n * Default: `true`\n *\n * - If `true`, will consider the `compiler.output` field.\n * - If `false`, will skip the fill process.\n *\n * - `./` paths are resolved relative to the component directory.\n * - `/` paths are resolved relative to the project root (`baseDir`).\n *\n * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.\n *\n * Example:\n * ```ts\n * {\n * // Create Multilingual .content.ts files close to the component\n * fill: ({ fileName, extension }) => `./${fileName}${extension}`,\n *\n * // fill: './{{fileName}}{{extension}}', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create centralize per-locale JSON at the root of the project\n * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,\n *\n * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string\n * }\n * ```\n *\n * ```ts\n * {\n * // Create custom output based on the locale\n * fill: {\n * en: ({ key }) => `/locales/en/${key}.content.json`,\n * fr: '/locales/fr/{{key}}.content.json',\n * es: false,\n * de: true,\n * },\n * }\n * ```\n *\n *\n * Variable list:\n * - `fileName`: The name of the file.\n * - `key`: The key of the content.\n * - `locale`: The locale of the content.\n * - `extension`: The extension of the file.\n * - `componentFileName`: The name of the component file.\n * - `componentExtension`: The extension of the component file.\n * - `format`: The format of the dictionary.\n * - `componentFormat`: The format of the component dictionary.\n * - `componentDirPath`: The directory path of the component.\n */\n fill: customConfiguration?.fill ?? FILL,\n\n /**\n * Indicates if the content of the dictionary should be automatically transformed.\n *\n * Default: `false`\n */\n contentAutoTransformation:\n typeof contentAutoTransformation === 'object'\n ? {\n markdown: contentAutoTransformation.markdown ?? false,\n html: contentAutoTransformation.html ?? false,\n insertion: contentAutoTransformation.insertion ?? false,\n }\n : contentAutoTransformation,\n\n /**\n * The location of the dictionary.\n *\n * Default: `\"local\"`\n */\n location: customConfiguration?.location ?? LOCATION,\n\n /**\n * Transform the dictionary in a per-locale dictionary.\n * Each field declared in a per-locale dictionary will be transformed in a translation node.\n * If missing, the dictionary will be treated as a multilingual dictionary.\n */\n locale: customConfiguration?.locale,\n\n /**\n * The title of the dictionary.\n */\n title: customConfiguration?.title,\n\n /**\n * The description of the dictionary.\n */\n description: customConfiguration?.description,\n\n /**\n * Tags to categorize the dictionaries.\n */\n tags: customConfiguration?.tags,\n\n /**\n * The priority of the dictionary.\n */\n priority: customConfiguration?.priority,\n\n /**\n * Indicates the mode of import to use for the dictionary.\n *\n * Available modes:\n * - \"static\": The dictionaries are imported statically.\n * - \"dynamic\": The dictionaries are imported dynamically in a synchronous component using the suspense API.\n * - \"live\": The dictionaries are imported dynamically using the live sync API.\n *\n * Default: `\"static\"`\n */\n importMode: customConfiguration?.importMode ?? IMPORT_MODE,\n\n /**\n * The default message format for all dictionaries in the project.\n *\n * Default: 'intlayer'\n */\n format: customConfiguration?.format,\n };\n};\n\n// ---------------------------------------------------------------------------\n// Main export\n// ---------------------------------------------------------------------------\n\n/**\n * Build the complete Intlayer configuration by merging user-supplied values\n * with defaults.\n *\n * Internally this function:\n * 1. Calls {@link buildBrowserConfiguration} to produce the browser-safe\n * subset (internationalization, routing, editor public fields, log, metadata).\n * 2. Extends the result with full server-side fields:\n * - `internationalization` — adds `requiredLocales` and `strictMode`.\n * - `editor` — adds `clientId` and `clientSecret`.\n * - `log` — adds custom log functions.\n * - `system`, `content`, `ai`, `build`, `compiler`, `dictionary`.\n *\n * @param customConfiguration - Optional user-supplied configuration object.\n * @param baseDir - Project root directory. Defaults to `process.cwd()`.\n * @param logFunctions - Optional custom logging functions.\n * @returns A fully-built {@link IntlayerConfig}.\n */\nexport const buildConfigurationFields = (\n customConfiguration?: CustomIntlayerConfig,\n baseDir?: string,\n logFunctions?: LogFunctions\n): IntlayerConfig => {\n if (customConfiguration) {\n const result = intlayerConfigSchema.safeParse(customConfiguration);\n\n if (!result.success) {\n const logError = logFunctions?.error ?? console.error;\n\n for (const issue of result.error.issues) {\n logError(`${issue.path.join('.')}: ${issue.message}`);\n }\n }\n }\n\n // build browser-safe config (shared defaults, no Node.js deps)\n const browserConfig = buildBrowserConfiguration(customConfiguration);\n\n // extend shared fields with server-only additions\n const internationalizationConfig = buildInternationalizationFields(\n customConfiguration?.internationalization\n );\n\n const editorConfig = buildEditorFields(customConfiguration?.editor);\n\n const logConfig = buildLogFields(customConfiguration?.log, logFunctions);\n\n // build server-only fields\n const systemConfig = buildSystemFields(baseDir, customConfiguration?.system);\n\n const contentConfig = buildContentFields(\n systemConfig,\n customConfiguration?.content\n );\n\n storedConfiguration = {\n // Shared browser fields\n routing: browserConfig.routing,\n // Full (extended) shared fields\n internationalization: internationalizationConfig,\n editor: editorConfig,\n analytics: buildAnalyticsFields(customConfiguration?.analytics),\n log: logConfig,\n // Server-only fields\n system: systemConfig,\n content: contentConfig,\n ai: buildAiFields(customConfiguration?.ai),\n build: buildBuildFields(customConfiguration?.build),\n compiler: buildCompilerFields(customConfiguration?.compiler),\n dictionary: buildDictionaryFields(customConfiguration?.dictionary),\n plugins: customConfiguration?.plugins,\n schemas: customConfiguration?.schemas,\n } as IntlayerConfig;\n\n return storedConfiguration;\n};\n"],"mappings":"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"}
|
|
@@ -28,7 +28,9 @@ const CACHE = true;
|
|
|
28
28
|
const TYPE_CHECKING = false;
|
|
29
29
|
const MINIFY = false;
|
|
30
30
|
const PURGE = false;
|
|
31
|
+
const CHUNK_GROUPING = true;
|
|
32
|
+
const DICTIONARIES_PRELOAD = true;
|
|
31
33
|
|
|
32
34
|
//#endregion
|
|
33
|
-
export { BUILD_MODE, CACHE, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING };
|
|
35
|
+
export { BUILD_MODE, CACHE, CHUNK_GROUPING, DICTIONARIES_PRELOAD, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING };
|
|
34
36
|
//# sourceMappingURL=build.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.mjs","names":[],"sources":["../../../src/defaultValues/build.ts"],"sourcesContent":["export const BUILD_MODE = 'auto';\n\nexport const OPTIMIZE = undefined;\n\nexport const TRAVERSE_PATTERN = [\n // Included files to parse\n '**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,astro}',\n\n // Excluded paths\n '!**/node_modules/**',\n '!**/dist/**',\n '!**/build/**',\n '!**/.intlayer/**',\n '!**/.next/**',\n '!**/.nuxt/**',\n '!**/.expo/**',\n '!**/.vercel/**',\n '!**/.turbo/**',\n '!**/.tanstack/**',\n '!**/.output/**',\n '!**/.svelte-kit/**',\n '!**/*.config.*',\n '!**/*.test.*',\n '!**/*.spec.*',\n '!**/*.stories.*',\n '!**/*.d.ts',\n '!**/*.d.ts.map',\n '!**/*.map',\n];\n\nexport const OUTPUT_FORMAT: ('cjs' | 'esm')[] = ['esm', 'cjs'];\n\nexport const CACHE = true;\n\nexport const TYPE_CHECKING = false;\n\nexport const MINIFY = false;\n\nexport const PURGE = false;\n"],"mappings":";AAAA,MAAa,aAAa;AAE1B,MAAa,WAAW;AAExB,MAAa,mBAAmB;CAE9B;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gBAAmC,CAAC,OAAO,KAAK;AAE7D,MAAa,QAAQ;AAErB,MAAa,gBAAgB;AAE7B,MAAa,SAAS;AAEtB,MAAa,QAAQ"}
|
|
1
|
+
{"version":3,"file":"build.mjs","names":[],"sources":["../../../src/defaultValues/build.ts"],"sourcesContent":["export const BUILD_MODE = 'auto';\n\nexport const OPTIMIZE = undefined;\n\nexport const TRAVERSE_PATTERN = [\n // Included files to parse\n '**/*.{tsx,ts,js,mjs,cjs,jsx,vue,svelte,astro}',\n\n // Excluded paths\n '!**/node_modules/**',\n '!**/dist/**',\n '!**/build/**',\n '!**/.intlayer/**',\n '!**/.next/**',\n '!**/.nuxt/**',\n '!**/.expo/**',\n '!**/.vercel/**',\n '!**/.turbo/**',\n '!**/.tanstack/**',\n '!**/.output/**',\n '!**/.svelte-kit/**',\n '!**/*.config.*',\n '!**/*.test.*',\n '!**/*.spec.*',\n '!**/*.stories.*',\n '!**/*.d.ts',\n '!**/*.d.ts.map',\n '!**/*.map',\n];\n\nexport const OUTPUT_FORMAT: ('cjs' | 'esm')[] = ['esm', 'cjs'];\n\nexport const CACHE = true;\n\nexport const TYPE_CHECKING = false;\n\nexport const MINIFY = false;\n\nexport const PURGE = false;\n\nexport const CHUNK_GROUPING = true;\n\nexport const DICTIONARIES_PRELOAD = true;\n"],"mappings":";AAAA,MAAa,aAAa;AAE1B,MAAa,WAAW;AAExB,MAAa,mBAAmB;CAE9B;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gBAAmC,CAAC,OAAO,KAAK;AAE7D,MAAa,QAAQ;AAErB,MAAa,gBAAgB;AAE7B,MAAa,SAAS;AAEtB,MAAa,QAAQ;AAErB,MAAa,iBAAiB;AAE9B,MAAa,uBAAuB"}
|
|
@@ -3,7 +3,44 @@ const FILL = true;
|
|
|
3
3
|
const LOCATION = "local";
|
|
4
4
|
const CONTENT_AUTO_TRANSFORMATION = false;
|
|
5
5
|
const IMPORT_MODE = "static";
|
|
6
|
+
/**
|
|
7
|
+
* Directory the per-locale JSON chunks of `importMode: 'dynamic'` are written
|
|
8
|
+
* under, relative to `system.dynamicDictionariesDir`.
|
|
9
|
+
*
|
|
10
|
+
* Plain dictionaries land at `<subdir>/<key>/<locale>.json`, qualified ones
|
|
11
|
+
* (collections, variants) nest one directory per dimension in between. The
|
|
12
|
+
* static first segment is required by Turbopack, and build-tool plugins match
|
|
13
|
+
* module ids against this layout — hence the shared constant rather than a
|
|
14
|
+
* literal repeated on both sides.
|
|
15
|
+
*/
|
|
16
|
+
const DYNAMIC_DICTIONARIES_JSON_SUBDIR = "json";
|
|
17
|
+
/**
|
|
18
|
+
* Marker property carrying the ordered qualifier dimensions on a dynamic loader
|
|
19
|
+
* map. Its presence distinguishes a qualified group loader map (a nested tree
|
|
20
|
+
* of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed
|
|
21
|
+
* and unlikely to collide with a real locale code.
|
|
22
|
+
*/
|
|
23
|
+
const QUALIFIER_DYNAMIC_TYPES_KEY = "__intlayerQualifierTypes";
|
|
24
|
+
/**
|
|
25
|
+
* Marker property carrying the dictionary a generated dynamic entry point
|
|
26
|
+
* already resolved for the browsing locale, before any component rendered.
|
|
27
|
+
*
|
|
28
|
+
* Build-tool plugins prepend a top-level `await` to those entry points, so the
|
|
29
|
+
* chunk that statically imports one only finishes evaluating once the awaited
|
|
30
|
+
* locale chunk has landed. A read during render then finds the content in place
|
|
31
|
+
* instead of suspending.
|
|
32
|
+
*/
|
|
33
|
+
const PRELOADED_DYNAMIC_KEY = "__intlayerPreloaded";
|
|
34
|
+
/**
|
|
35
|
+
* Name of the local binding a generated dynamic entry point holds its loader
|
|
36
|
+
* map in, before exporting it as default.
|
|
37
|
+
*
|
|
38
|
+
* The preload preamble is appended to that generated source and mutates the
|
|
39
|
+
* binding, so the code generator and the build plugins have to agree on the
|
|
40
|
+
* name — hence the shared constant rather than a literal repeated in both.
|
|
41
|
+
*/
|
|
42
|
+
const DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = "content";
|
|
6
43
|
|
|
7
44
|
//#endregion
|
|
8
|
-
export { CONTENT_AUTO_TRANSFORMATION, FILL, IMPORT_MODE, LOCATION };
|
|
45
|
+
export { CONTENT_AUTO_TRANSFORMATION, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, FILL, IMPORT_MODE, LOCATION, PRELOADED_DYNAMIC_KEY, QUALIFIER_DYNAMIC_TYPES_KEY };
|
|
9
46
|
//# sourceMappingURL=dictionary.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictionary.mjs","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"sourcesContent":["import type { DictionaryLocation } from '@intlayer/types/dictionary';\n\nexport const FILL = true;\nexport const LOCATION: DictionaryLocation = 'local';\nexport const CONTENT_AUTO_TRANSFORMATION = false;\nexport const IMPORT_MODE = 'static';\n"],"mappings":";AAEA,MAAa,OAAO;AACpB,MAAa,WAA+B;AAC5C,MAAa,8BAA8B;AAC3C,MAAa,cAAc"}
|
|
1
|
+
{"version":3,"file":"dictionary.mjs","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"sourcesContent":["import type { DictionaryLocation } from '@intlayer/types/dictionary';\n\nexport const FILL = true;\nexport const LOCATION: DictionaryLocation = 'local';\nexport const CONTENT_AUTO_TRANSFORMATION = false;\nexport const IMPORT_MODE = 'static';\n\n/**\n * Directory the per-locale JSON chunks of `importMode: 'dynamic'` are written\n * under, relative to `system.dynamicDictionariesDir`.\n *\n * Plain dictionaries land at `<subdir>/<key>/<locale>.json`, qualified ones\n * (collections, variants) nest one directory per dimension in between. The\n * static first segment is required by Turbopack, and build-tool plugins match\n * module ids against this layout — hence the shared constant rather than a\n * literal repeated on both sides.\n */\nexport const DYNAMIC_DICTIONARIES_JSON_SUBDIR = 'json';\n\n/**\n * Marker property carrying the ordered qualifier dimensions on a dynamic loader\n * map. Its presence distinguishes a qualified group loader map (a nested tree\n * of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed\n * and unlikely to collide with a real locale code.\n */\nexport const QUALIFIER_DYNAMIC_TYPES_KEY = '__intlayerQualifierTypes';\n\n/**\n * Marker property carrying the dictionary a generated dynamic entry point\n * already resolved for the browsing locale, before any component rendered.\n *\n * Build-tool plugins prepend a top-level `await` to those entry points, so the\n * chunk that statically imports one only finishes evaluating once the awaited\n * locale chunk has landed. A read during render then finds the content in place\n * instead of suspending.\n */\nexport const PRELOADED_DYNAMIC_KEY = '__intlayerPreloaded';\n\n/**\n * Name of the local binding a generated dynamic entry point holds its loader\n * map in, before exporting it as default.\n *\n * The preload preamble is appended to that generated source and mutates the\n * binding, so the code generator and the build plugins have to agree on the\n * name — hence the shared constant rather than a literal repeated in both.\n */\nexport const DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = 'content';\n"],"mappings":";AAEA,MAAa,OAAO;AACpB,MAAa,WAA+B;AAC5C,MAAa,8BAA8B;AAC3C,MAAa,cAAc;;;;;;;;;;;AAY3B,MAAa,mCAAmC;;;;;;;AAQhD,MAAa,8BAA8B;;;;;;;;;;AAW3C,MAAa,wBAAwB;;;;;;;;;AAUrC,MAAa,sCAAsC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BUILD_MODE, CACHE, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "./build.mjs";
|
|
1
|
+
import { BUILD_MODE, CACHE, CHUNK_GROUPING, DICTIONARIES_PRELOAD, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "./build.mjs";
|
|
2
2
|
import { COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS } from "./compiler.mjs";
|
|
3
3
|
import { CODE_DIR, CONTENT_DIR, EXCLUDED_PATHS, FILE_EXTENSIONS, I18NEXT_DICTIONARIES_DIR, REACT_INTL_MESSAGES_DIR, WATCH } from "./content.mjs";
|
|
4
|
-
import { CONTENT_AUTO_TRANSFORMATION, FILL, IMPORT_MODE, LOCATION } from "./dictionary.mjs";
|
|
4
|
+
import { CONTENT_AUTO_TRANSFORMATION, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, FILL, IMPORT_MODE, LOCATION, PRELOADED_DYNAMIC_KEY, QUALIFIER_DYNAMIC_TYPES_KEY } from "./dictionary.mjs";
|
|
5
5
|
import { CACHE_DIR, CONFIG_DIR, DICTIONARIES_DIR, DYNAMIC_DICTIONARIES_DIR, FETCH_DICTIONARIES_DIR, MAIN_DIR, MASKS_DIR, MODULE_AUGMENTATION_DIR, REMOTE_DICTIONARIES_DIR, TEMP_DIR, TYPES_DIR, UNMERGED_DICTIONARIES_DIR } from "./system.mjs";
|
|
6
6
|
import { BASE_PATH, COOKIE_NAME, ENABLE_PROXY, HEADER_NAME, LOCALE_STORAGE_NAME, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE } from "./routing.mjs";
|
|
7
7
|
import { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE } from "./analytics.mjs";
|
|
@@ -9,4 +9,4 @@ import { APPLICATION_URL, BACKEND_URL, CMS_URL, DICTIONARY_PRIORITY_STRATEGY, ED
|
|
|
9
9
|
import { DEFAULT_LOCALE, LOCALES, REQUIRED_LOCALES, STRICT_MODE } from "./internationalization.mjs";
|
|
10
10
|
import { MODE, PREFIX } from "./log.mjs";
|
|
11
11
|
|
|
12
|
-
export { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE, APPLICATION_URL, BACKEND_URL, BASE_PATH, BUILD_MODE, CACHE, CACHE_DIR, CMS_URL, CODE_DIR, COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS, CONFIG_DIR, CONTENT_AUTO_TRANSFORMATION, CONTENT_DIR, COOKIE_NAME, DEFAULT_LOCALE, DICTIONARIES_DIR, DICTIONARY_PRIORITY_STRATEGY, DYNAMIC_DICTIONARIES_DIR, EDITOR_URL, ENABLE_PROXY, EXCLUDED_PATHS, FETCH_DICTIONARIES_DIR, FILE_EXTENSIONS, FILL, HEADER_NAME, I18NEXT_DICTIONARIES_DIR, IMPORT_MODE, IS_ENABLED, LIVE_SYNC, LIVE_SYNC_PORT, LOCALES, LOCALE_STORAGE_NAME, LOCATION, MAIN_DIR, MASKS_DIR, MINIFY, MODE, MODULE_AUGMENTATION_DIR, OPTIMIZE, OUTPUT_FORMAT, PORT, PREFIX, PURGE, REACT_INTL_MESSAGES_DIR, REMOTE_DICTIONARIES_DIR, REQUIRED_LOCALES, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE, STRICT_MODE, TEMP_DIR, TRAVERSE_PATTERN, TYPES_DIR, TYPE_CHECKING, UNMERGED_DICTIONARIES_DIR, WATCH };
|
|
12
|
+
export { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE, APPLICATION_URL, BACKEND_URL, BASE_PATH, BUILD_MODE, CACHE, CACHE_DIR, CHUNK_GROUPING, CMS_URL, CODE_DIR, COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS, CONFIG_DIR, CONTENT_AUTO_TRANSFORMATION, CONTENT_DIR, COOKIE_NAME, DEFAULT_LOCALE, DICTIONARIES_DIR, DICTIONARIES_PRELOAD, DICTIONARY_PRIORITY_STRATEGY, DYNAMIC_DICTIONARIES_DIR, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, EDITOR_URL, ENABLE_PROXY, EXCLUDED_PATHS, FETCH_DICTIONARIES_DIR, FILE_EXTENSIONS, FILL, HEADER_NAME, I18NEXT_DICTIONARIES_DIR, IMPORT_MODE, IS_ENABLED, LIVE_SYNC, LIVE_SYNC_PORT, LOCALES, LOCALE_STORAGE_NAME, LOCATION, MAIN_DIR, MASKS_DIR, MINIFY, MODE, MODULE_AUGMENTATION_DIR, OPTIMIZE, OUTPUT_FORMAT, PORT, PREFIX, PRELOADED_DYNAMIC_KEY, PURGE, QUALIFIER_DYNAMIC_TYPES_KEY, REACT_INTL_MESSAGES_DIR, REMOTE_DICTIONARIES_DIR, REQUIRED_LOCALES, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE, STRICT_MODE, TEMP_DIR, TRAVERSE_PATTERN, TYPES_DIR, TYPE_CHECKING, UNMERGED_DICTIONARIES_DIR, WATCH };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, PRELOADED_DYNAMIC_KEY, QUALIFIER_DYNAMIC_TYPES_KEY } from "./defaultValues/dictionary.mjs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
//#region src/dictionaryPreload.ts
|
|
5
|
+
/**
|
|
6
|
+
* Matches a generated dynamic entry point, whose layout is
|
|
7
|
+
* `<dynamicDictionariesDir>/<key>.mjs`. The per-locale JSON chunks it imports
|
|
8
|
+
* live one directory deeper, under `json/`, and are deliberately excluded.
|
|
9
|
+
*/
|
|
10
|
+
const DYNAMIC_ENTRY_PATTERN = /\/(?<key>[^/]+)\.mjs$/;
|
|
11
|
+
/** Escapes a literal path segment for embedding in a regular expression. */
|
|
12
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13
|
+
/**
|
|
14
|
+
* Builds a filter matching only the generated dynamic entry points, for
|
|
15
|
+
* bundlers whose load hook is selected by a regular expression over the raw
|
|
16
|
+
* file path (esbuild).
|
|
17
|
+
*
|
|
18
|
+
* A hook registered on every `.mjs` would call back into JavaScript for each
|
|
19
|
+
* such file in the build, `node_modules` included, so the filter is anchored on
|
|
20
|
+
* the dictionaries directory name. It matches both path separators because
|
|
21
|
+
* esbuild tests the platform path, which is backslash-separated on Windows —
|
|
22
|
+
* the directory name itself never contains one.
|
|
23
|
+
*
|
|
24
|
+
* The name alone is not proof of location, so the callback must still confirm
|
|
25
|
+
* the full path lies inside `dynamicDictionariesDir`.
|
|
26
|
+
*
|
|
27
|
+
* @param dynamicDictionariesDir - Absolute dictionaries root, any separator.
|
|
28
|
+
*/
|
|
29
|
+
const createDynamicEntryFilter = (dynamicDictionariesDir) => {
|
|
30
|
+
const directoryName = dynamicDictionariesDir.split(/[\\/]/).filter(Boolean).pop() ?? "";
|
|
31
|
+
return new RegExp(`[\\\\/]${escapeRegExp(directoryName)}[\\\\/][^\\\\/]+\\.mjs$`);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Specifier of the module the injected preamble reads the locale from, as the
|
|
35
|
+
* bundler plugins are expected to resolve it.
|
|
36
|
+
*
|
|
37
|
+
* Never emitted as-is: a generated entry point lives in the *application's*
|
|
38
|
+
* `.intlayer` directory, and an application depends on `intlayer` and its
|
|
39
|
+
* framework binding — not on `@intlayer/core` — so a bare specifier would
|
|
40
|
+
* resolve from a directory where the package is absent, or, worse, silently
|
|
41
|
+
* hit an unrelated copy hoisted higher up the tree.
|
|
42
|
+
*/
|
|
43
|
+
const PRELOAD_MODULE_SPECIFIER = "@intlayer/core/localization";
|
|
44
|
+
/** Package and subpath {@link PRELOAD_MODULE_SPECIFIER} is composed of. */
|
|
45
|
+
const PRELOAD_PACKAGE_NAME = "@intlayer/core";
|
|
46
|
+
const PRELOAD_PACKAGE_SUBPATH = "./localization";
|
|
47
|
+
/**
|
|
48
|
+
* Resolves {@link PRELOAD_MODULE_SPECIFIER} to an absolute id the injected
|
|
49
|
+
* preamble can import, from a package that actually depends on it.
|
|
50
|
+
*
|
|
51
|
+
* Deliberately not `require.resolve(PRELOAD_MODULE_SPECIFIER)`: that applies
|
|
52
|
+
* the `require` condition and lands on the package's CommonJS build, which the
|
|
53
|
+
* preamble would then pull into a *browser* bundle behind a CommonJS interop
|
|
54
|
+
* wrapper — a second copy of the module alongside the ESM one the application
|
|
55
|
+
* already imports, each with its own memoized locale. The manifest is resolved
|
|
56
|
+
* instead (a condition-free subpath) and its `import` entry read directly.
|
|
57
|
+
*
|
|
58
|
+
* @param requireFn - `require`, or `createRequire(import.meta.url)`, from the
|
|
59
|
+
* plugin package.
|
|
60
|
+
* @returns Absolute path to the ESM build, falling back to whatever the
|
|
61
|
+
* standard resolution yields if the package ever stops publishing one.
|
|
62
|
+
*/
|
|
63
|
+
const resolvePreloadModuleId = (requireFn) => {
|
|
64
|
+
const manifestPath = requireFn.resolve(`${PRELOAD_PACKAGE_NAME}/package.json`);
|
|
65
|
+
const subpathExport = requireFn(manifestPath).exports?.[PRELOAD_PACKAGE_SUBPATH];
|
|
66
|
+
const esmEntry = typeof subpathExport === "string" ? subpathExport : subpathExport?.import;
|
|
67
|
+
if (!esmEntry) return requireFn.resolve(PRELOAD_MODULE_SPECIFIER);
|
|
68
|
+
return resolve(dirname(manifestPath), esmEntry);
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Builds the import the injected preamble relies on, hoisted ahead of the
|
|
72
|
+
* generated source.
|
|
73
|
+
*
|
|
74
|
+
* @param preloadModuleId - Specifier resolving to {@link PRELOAD_MODULE_SPECIFIER}
|
|
75
|
+
* from the plugin package, which does depend on it.
|
|
76
|
+
*/
|
|
77
|
+
const buildPreloadImport = (preloadModuleId) => `import { getPreloadLocale as __intlayerGetPreloadLocale } from '${preloadModuleId}';\n`;
|
|
78
|
+
/**
|
|
79
|
+
* Preamble appended to a generated dynamic entry point.
|
|
80
|
+
*
|
|
81
|
+
* The load is started while the entry point evaluates, but is deliberately
|
|
82
|
+
* *not* awaited at the top level. Awaiting would make the entry point an async
|
|
83
|
+
* module, which delays the resolution of every chunk that statically imports
|
|
84
|
+
* it — including the chunks behind a `React.lazy` boundary. A boundary whose
|
|
85
|
+
* module resolves that late during hydration stays on its fallback for good:
|
|
86
|
+
* the framework has already swapped the server markup for the pending state and
|
|
87
|
+
* does not retry, so the section never appears. Starting the request here and
|
|
88
|
+
* letting the reader pick the result up keeps the whole benefit of the early
|
|
89
|
+
* fetch without ever holding up module evaluation.
|
|
90
|
+
*
|
|
91
|
+
* The gain is in *when* the request starts: it leaves as soon as the chunk that
|
|
92
|
+
* needs the dictionary is evaluated — on a router's `import()` of a route,
|
|
93
|
+
* including a preload on hover — rather than once the consuming component
|
|
94
|
+
* renders. By the time the reader runs, the marker is usually already set and
|
|
95
|
+
* the read is synchronous, so no loading state is revealed.
|
|
96
|
+
*
|
|
97
|
+
* Only the resolved locale is requested, so a page still downloads exactly the
|
|
98
|
+
* language it renders.
|
|
99
|
+
*
|
|
100
|
+
* A failed load is swallowed: leaving the marker unset drops the read back onto
|
|
101
|
+
* the asynchronous path, where the existing loading state surfaces the error.
|
|
102
|
+
*/
|
|
103
|
+
const PRELOAD_PREAMBLE = [
|
|
104
|
+
"",
|
|
105
|
+
"// Injected by Intlayer: starts the browsing locale load with this module.",
|
|
106
|
+
"const __intlayerLocale = __intlayerGetPreloadLocale();",
|
|
107
|
+
`const __intlayerLoader = ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}[__intlayerLocale];`,
|
|
108
|
+
"",
|
|
109
|
+
`if (typeof window !== 'undefined' && typeof __intlayerLoader === 'function') {`,
|
|
110
|
+
" __intlayerLoader().then(",
|
|
111
|
+
" (__intlayerDictionary) => {",
|
|
112
|
+
` ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}['${PRELOADED_DYNAMIC_KEY}'] = {`,
|
|
113
|
+
" locale: __intlayerLocale,",
|
|
114
|
+
" dictionary: __intlayerDictionary,",
|
|
115
|
+
" };",
|
|
116
|
+
" },",
|
|
117
|
+
" () => undefined",
|
|
118
|
+
" );",
|
|
119
|
+
"}",
|
|
120
|
+
""
|
|
121
|
+
].join("\n");
|
|
122
|
+
/**
|
|
123
|
+
* Adds the browsing-locale preload to a generated dynamic entry point.
|
|
124
|
+
*
|
|
125
|
+
* Bundler-agnostic on purpose: the Vite plugin and the esbuild plugin apply the
|
|
126
|
+
* identical transform, and keeping one implementation means the emitted shape
|
|
127
|
+
* cannot drift between them. The caller decides *which* modules to hand over
|
|
128
|
+
* (the id is matched against the dynamic dictionaries directory) and how to
|
|
129
|
+
* report a skip.
|
|
130
|
+
*
|
|
131
|
+
* @param code - Source of the generated `<key>.mjs` entry point.
|
|
132
|
+
* @param preloadModuleId - Specifier the preamble imports the locale resolver
|
|
133
|
+
* from, already resolved against the plugin package.
|
|
134
|
+
* @returns The transformed source, or the reason it was left alone.
|
|
135
|
+
*/
|
|
136
|
+
const addDynamicEntryPreload = (code, preloadModuleId) => {
|
|
137
|
+
if (code.includes("__intlayerQualifierTypes")) return { skipped: "qualified" };
|
|
138
|
+
if (!code.includes(`const ${"content"} =`)) return { skipped: "unrecognized-shape" };
|
|
139
|
+
return { code: buildPreloadImport(preloadModuleId) + code + PRELOAD_PREAMBLE };
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { DYNAMIC_ENTRY_PATTERN, PRELOAD_MODULE_SPECIFIER, addDynamicEntryPreload, createDynamicEntryFilter, resolvePreloadModuleId };
|
|
144
|
+
//# sourceMappingURL=dictionaryPreload.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaryPreload.mjs","names":[],"sources":["../../src/dictionaryPreload.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path';\nimport {\n DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER,\n PRELOADED_DYNAMIC_KEY,\n QUALIFIER_DYNAMIC_TYPES_KEY,\n} from './defaultValues/dictionary';\n\n/**\n * Matches a generated dynamic entry point, whose layout is\n * `<dynamicDictionariesDir>/<key>.mjs`. The per-locale JSON chunks it imports\n * live one directory deeper, under `json/`, and are deliberately excluded.\n */\nexport const DYNAMIC_ENTRY_PATTERN = /\\/(?<key>[^/]+)\\.mjs$/;\n\n/** Escapes a literal path segment for embedding in a regular expression. */\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Builds a filter matching only the generated dynamic entry points, for\n * bundlers whose load hook is selected by a regular expression over the raw\n * file path (esbuild).\n *\n * A hook registered on every `.mjs` would call back into JavaScript for each\n * such file in the build, `node_modules` included, so the filter is anchored on\n * the dictionaries directory name. It matches both path separators because\n * esbuild tests the platform path, which is backslash-separated on Windows —\n * the directory name itself never contains one.\n *\n * The name alone is not proof of location, so the callback must still confirm\n * the full path lies inside `dynamicDictionariesDir`.\n *\n * @param dynamicDictionariesDir - Absolute dictionaries root, any separator.\n */\nexport const createDynamicEntryFilter = (\n dynamicDictionariesDir: string\n): RegExp => {\n const directoryName =\n dynamicDictionariesDir.split(/[\\\\/]/).filter(Boolean).pop() ?? '';\n\n return new RegExp(\n `[\\\\\\\\/]${escapeRegExp(directoryName)}[\\\\\\\\/][^\\\\\\\\/]+\\\\.mjs$`\n );\n};\n\n/**\n * Specifier of the module the injected preamble reads the locale from, as the\n * bundler plugins are expected to resolve it.\n *\n * Never emitted as-is: a generated entry point lives in the *application's*\n * `.intlayer` directory, and an application depends on `intlayer` and its\n * framework binding — not on `@intlayer/core` — so a bare specifier would\n * resolve from a directory where the package is absent, or, worse, silently\n * hit an unrelated copy hoisted higher up the tree.\n */\nexport const PRELOAD_MODULE_SPECIFIER = '@intlayer/core/localization';\n\n/** Package and subpath {@link PRELOAD_MODULE_SPECIFIER} is composed of. */\nconst PRELOAD_PACKAGE_NAME = '@intlayer/core';\nconst PRELOAD_PACKAGE_SUBPATH = './localization';\n\n/** The subset of a `package.json` this resolution reads. */\ntype PackageManifest = {\n exports?: Record<string, { import?: string } | string | undefined>;\n};\n\n/**\n * Resolves {@link PRELOAD_MODULE_SPECIFIER} to an absolute id the injected\n * preamble can import, from a package that actually depends on it.\n *\n * Deliberately not `require.resolve(PRELOAD_MODULE_SPECIFIER)`: that applies\n * the `require` condition and lands on the package's CommonJS build, which the\n * preamble would then pull into a *browser* bundle behind a CommonJS interop\n * wrapper — a second copy of the module alongside the ESM one the application\n * already imports, each with its own memoized locale. The manifest is resolved\n * instead (a condition-free subpath) and its `import` entry read directly.\n *\n * @param requireFn - `require`, or `createRequire(import.meta.url)`, from the\n * plugin package.\n * @returns Absolute path to the ESM build, falling back to whatever the\n * standard resolution yields if the package ever stops publishing one.\n */\nexport const resolvePreloadModuleId = (requireFn: NodeRequire): string => {\n const manifestPath = requireFn.resolve(\n `${PRELOAD_PACKAGE_NAME}/package.json`\n );\n const manifest = requireFn(manifestPath) as PackageManifest;\n const subpathExport = manifest.exports?.[PRELOAD_PACKAGE_SUBPATH];\n\n const esmEntry =\n typeof subpathExport === 'string' ? subpathExport : subpathExport?.import;\n\n if (!esmEntry) return requireFn.resolve(PRELOAD_MODULE_SPECIFIER);\n\n return resolve(dirname(manifestPath), esmEntry);\n};\n\n/**\n * Builds the import the injected preamble relies on, hoisted ahead of the\n * generated source.\n *\n * @param preloadModuleId - Specifier resolving to {@link PRELOAD_MODULE_SPECIFIER}\n * from the plugin package, which does depend on it.\n */\nconst buildPreloadImport = (preloadModuleId: string): string =>\n `import { getPreloadLocale as __intlayerGetPreloadLocale } from '${preloadModuleId}';\\n`;\n\n/**\n * Preamble appended to a generated dynamic entry point.\n *\n * The load is started while the entry point evaluates, but is deliberately\n * *not* awaited at the top level. Awaiting would make the entry point an async\n * module, which delays the resolution of every chunk that statically imports\n * it — including the chunks behind a `React.lazy` boundary. A boundary whose\n * module resolves that late during hydration stays on its fallback for good:\n * the framework has already swapped the server markup for the pending state and\n * does not retry, so the section never appears. Starting the request here and\n * letting the reader pick the result up keeps the whole benefit of the early\n * fetch without ever holding up module evaluation.\n *\n * The gain is in *when* the request starts: it leaves as soon as the chunk that\n * needs the dictionary is evaluated — on a router's `import()` of a route,\n * including a preload on hover — rather than once the consuming component\n * renders. By the time the reader runs, the marker is usually already set and\n * the read is synchronous, so no loading state is revealed.\n *\n * Only the resolved locale is requested, so a page still downloads exactly the\n * language it renders.\n *\n * A failed load is swallowed: leaving the marker unset drops the read back onto\n * the asynchronous path, where the existing loading state surfaces the error.\n */\nconst PRELOAD_PREAMBLE = [\n '',\n '// Injected by Intlayer: starts the browsing locale load with this module.',\n 'const __intlayerLocale = __intlayerGetPreloadLocale();',\n `const __intlayerLoader = ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}[__intlayerLocale];`,\n '',\n `if (typeof window !== 'undefined' && typeof __intlayerLoader === 'function') {`,\n ' __intlayerLoader().then(',\n ' (__intlayerDictionary) => {',\n ` ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER}['${PRELOADED_DYNAMIC_KEY}'] = {`,\n ' locale: __intlayerLocale,',\n ' dictionary: __intlayerDictionary,',\n ' };',\n ' },',\n ' () => undefined',\n ' );',\n '}',\n '',\n].join('\\n');\n\n/** Why a generated entry point was left untransformed. */\nexport type PreloadSkipReason = 'qualified' | 'unrecognized-shape';\n\nexport type PreloadTransformResult =\n | { code: string; skipped?: undefined }\n | { code?: undefined; skipped: PreloadSkipReason };\n\n/**\n * Adds the browsing-locale preload to a generated dynamic entry point.\n *\n * Bundler-agnostic on purpose: the Vite plugin and the esbuild plugin apply the\n * identical transform, and keeping one implementation means the emitted shape\n * cannot drift between them. The caller decides *which* modules to hand over\n * (the id is matched against the dynamic dictionaries directory) and how to\n * report a skip.\n *\n * @param code - Source of the generated `<key>.mjs` entry point.\n * @param preloadModuleId - Specifier the preamble imports the locale resolver\n * from, already resolved against the plugin package.\n * @returns The transformed source, or the reason it was left alone.\n */\nexport const addDynamicEntryPreload = (\n code: string,\n preloadModuleId: string\n): PreloadTransformResult => {\n // Qualified entry points (collections, variants) expose a nested tree of\n // loaders per locale rather than one loader, so preloading them would have to\n // guess which coordinate the call site targets — and would fetch every chunk\n // to avoid guessing wrong.\n if (code.includes(QUALIFIER_DYNAMIC_TYPES_KEY)) {\n return { skipped: 'qualified' };\n }\n\n // The preamble mutates the generated binding; if the code generator ever\n // stops emitting it, skipping keeps the build correct (and merely\n // unoptimized) instead of emitting a reference error.\n if (!code.includes(`const ${DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER} =`)) {\n return { skipped: 'unrecognized-shape' };\n }\n\n return {\n code: buildPreloadImport(preloadModuleId) + code + PRELOAD_PREAMBLE,\n };\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,wBAAwB;;AAGrC,MAAM,gBAAgB,UACpB,MAAM,QAAQ,uBAAuB,MAAM;;;;;;;;;;;;;;;;;AAkB7C,MAAa,4BACX,2BACW;CACX,MAAM,gBACJ,uBAAuB,MAAM,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK;CAEjE,OAAO,IAAI,OACT,UAAU,aAAa,aAAa,EAAE,wBACxC;AACF;;;;;;;;;;;AAYA,MAAa,2BAA2B;;AAGxC,MAAM,uBAAuB;AAC7B,MAAM,0BAA0B;;;;;;;;;;;;;;;;;AAuBhC,MAAa,0BAA0B,cAAmC;CACxE,MAAM,eAAe,UAAU,QAC7B,GAAG,qBAAqB,cAC1B;CAEA,MAAM,gBADW,UAAU,YACE,CAAC,CAAC,UAAU;CAEzC,MAAM,WACJ,OAAO,kBAAkB,WAAW,gBAAgB,eAAe;CAErE,IAAI,CAAC,UAAU,OAAO,UAAU,QAAQ,wBAAwB;CAEhE,OAAO,QAAQ,QAAQ,YAAY,GAAG,QAAQ;AAChD;;;;;;;;AASA,MAAM,sBAAsB,oBAC1B,mEAAmE,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BrF,MAAM,mBAAmB;CACvB;CACA;CACA;CACA,4BAA4B,oCAAoC;CAChE;CACA;CACA;CACA;CACA,SAAS,oCAAoC,IAAI,sBAAsB;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;AAuBX,MAAa,0BACX,MACA,oBAC2B;CAK3B,IAAI,KAAK,mCAAoC,GAC3C,OAAO,EAAE,SAAS,YAAY;CAMhC,IAAI,CAAC,KAAK,SAAS,mBAA6C,GAAG,GACjE,OAAO,EAAE,SAAS,qBAAqB;CAGzC,OAAO,EACL,MAAM,mBAAmB,eAAe,IAAI,OAAO,iBACrD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildConfigurationFields.d.ts","names":[],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"buildConfigurationFields.d.ts","names":[],"sources":["../../../src/configFile/buildConfigurationFields.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;cAywBa,2BAAwB,sBACb,sBAAoB,kBAC1B,eACD,iBACd"}
|
|
@@ -7,6 +7,8 @@ declare const CACHE = true;
|
|
|
7
7
|
declare const TYPE_CHECKING = false;
|
|
8
8
|
declare const MINIFY = false;
|
|
9
9
|
declare const PURGE = false;
|
|
10
|
+
declare const CHUNK_GROUPING = true;
|
|
11
|
+
declare const DICTIONARIES_PRELOAD = true;
|
|
10
12
|
//#endregion
|
|
11
|
-
export { BUILD_MODE, CACHE, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING };
|
|
13
|
+
export { BUILD_MODE, CACHE, CHUNK_GROUPING, DICTIONARIES_PRELOAD, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING };
|
|
12
14
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","names":[],"sources":["../../../src/defaultValues/build.ts"],"mappings":";cAAa;cAEA;cAEA;cA0BA;cAEA;cAEA;cAEA;cAEA"}
|
|
1
|
+
{"version":3,"file":"build.d.ts","names":[],"sources":["../../../src/defaultValues/build.ts"],"mappings":";cAAa;cAEA;cAEA;cA0BA;cAEA;cAEA;cAEA;cAEA;cAEA;cAEA"}
|
|
@@ -4,6 +4,43 @@ declare const FILL = true;
|
|
|
4
4
|
declare const LOCATION: DictionaryLocation;
|
|
5
5
|
declare const CONTENT_AUTO_TRANSFORMATION = false;
|
|
6
6
|
declare const IMPORT_MODE = "static";
|
|
7
|
+
/**
|
|
8
|
+
* Directory the per-locale JSON chunks of `importMode: 'dynamic'` are written
|
|
9
|
+
* under, relative to `system.dynamicDictionariesDir`.
|
|
10
|
+
*
|
|
11
|
+
* Plain dictionaries land at `<subdir>/<key>/<locale>.json`, qualified ones
|
|
12
|
+
* (collections, variants) nest one directory per dimension in between. The
|
|
13
|
+
* static first segment is required by Turbopack, and build-tool plugins match
|
|
14
|
+
* module ids against this layout — hence the shared constant rather than a
|
|
15
|
+
* literal repeated on both sides.
|
|
16
|
+
*/
|
|
17
|
+
declare const DYNAMIC_DICTIONARIES_JSON_SUBDIR = "json";
|
|
18
|
+
/**
|
|
19
|
+
* Marker property carrying the ordered qualifier dimensions on a dynamic loader
|
|
20
|
+
* map. Its presence distinguishes a qualified group loader map (a nested tree
|
|
21
|
+
* of chunks) from a plain dynamic loader map (one chunk per `locale`). Prefixed
|
|
22
|
+
* and unlikely to collide with a real locale code.
|
|
23
|
+
*/
|
|
24
|
+
declare const QUALIFIER_DYNAMIC_TYPES_KEY = "__intlayerQualifierTypes";
|
|
25
|
+
/**
|
|
26
|
+
* Marker property carrying the dictionary a generated dynamic entry point
|
|
27
|
+
* already resolved for the browsing locale, before any component rendered.
|
|
28
|
+
*
|
|
29
|
+
* Build-tool plugins prepend a top-level `await` to those entry points, so the
|
|
30
|
+
* chunk that statically imports one only finishes evaluating once the awaited
|
|
31
|
+
* locale chunk has landed. A read during render then finds the content in place
|
|
32
|
+
* instead of suspending.
|
|
33
|
+
*/
|
|
34
|
+
declare const PRELOADED_DYNAMIC_KEY = "__intlayerPreloaded";
|
|
35
|
+
/**
|
|
36
|
+
* Name of the local binding a generated dynamic entry point holds its loader
|
|
37
|
+
* map in, before exporting it as default.
|
|
38
|
+
*
|
|
39
|
+
* The preload preamble is appended to that generated source and mutates the
|
|
40
|
+
* binding, so the code generator and the build plugins have to agree on the
|
|
41
|
+
* name — hence the shared constant rather than a literal repeated in both.
|
|
42
|
+
*/
|
|
43
|
+
declare const DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER = "content";
|
|
7
44
|
//#endregion
|
|
8
|
-
export { CONTENT_AUTO_TRANSFORMATION, FILL, IMPORT_MODE, LOCATION };
|
|
45
|
+
export { CONTENT_AUTO_TRANSFORMATION, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, FILL, IMPORT_MODE, LOCATION, PRELOADED_DYNAMIC_KEY, QUALIFIER_DYNAMIC_TYPES_KEY };
|
|
9
46
|
//# sourceMappingURL=dictionary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictionary.d.ts","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"mappings":";;cAEa;cACA,UAAU;cACV;cACA"}
|
|
1
|
+
{"version":3,"file":"dictionary.d.ts","names":[],"sources":["../../../src/defaultValues/dictionary.ts"],"mappings":";;cAEa;cACA,UAAU;cACV;cACA;;;;;;;;;;;cAYA;;;;;;;cAQA;;;;;;;;;;cAWA;;;;;;;;;cAUA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE } from "./analytics.js";
|
|
2
|
-
import { BUILD_MODE, CACHE, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "./build.js";
|
|
2
|
+
import { BUILD_MODE, CACHE, CHUNK_GROUPING, DICTIONARIES_PRELOAD, MINIFY, OPTIMIZE, OUTPUT_FORMAT, PURGE, TRAVERSE_PATTERN, TYPE_CHECKING } from "./build.js";
|
|
3
3
|
import { COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS } from "./compiler.js";
|
|
4
4
|
import { CODE_DIR, CONTENT_DIR, EXCLUDED_PATHS, FILE_EXTENSIONS, I18NEXT_DICTIONARIES_DIR, REACT_INTL_MESSAGES_DIR, WATCH } from "./content.js";
|
|
5
|
-
import { CONTENT_AUTO_TRANSFORMATION, FILL, IMPORT_MODE, LOCATION } from "./dictionary.js";
|
|
5
|
+
import { CONTENT_AUTO_TRANSFORMATION, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, FILL, IMPORT_MODE, LOCATION, PRELOADED_DYNAMIC_KEY, QUALIFIER_DYNAMIC_TYPES_KEY } from "./dictionary.js";
|
|
6
6
|
import { APPLICATION_URL, BACKEND_URL, CMS_URL, DICTIONARY_PRIORITY_STRATEGY, EDITOR_URL, IS_ENABLED, LIVE_SYNC, LIVE_SYNC_PORT, PORT } from "./editor.js";
|
|
7
7
|
import { DEFAULT_LOCALE, LOCALES, REQUIRED_LOCALES, STRICT_MODE } from "./internationalization.js";
|
|
8
8
|
import { MODE, PREFIX } from "./log.js";
|
|
9
9
|
import { BASE_PATH, COOKIE_NAME, ENABLE_PROXY, HEADER_NAME, LOCALE_STORAGE_NAME, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE } from "./routing.js";
|
|
10
10
|
import { CACHE_DIR, CONFIG_DIR, DICTIONARIES_DIR, DYNAMIC_DICTIONARIES_DIR, FETCH_DICTIONARIES_DIR, MAIN_DIR, MASKS_DIR, MODULE_AUGMENTATION_DIR, REMOTE_DICTIONARIES_DIR, TEMP_DIR, TYPES_DIR, UNMERGED_DICTIONARIES_DIR } from "./system.js";
|
|
11
|
-
export { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE, APPLICATION_URL, BACKEND_URL, BASE_PATH, BUILD_MODE, CACHE, CACHE_DIR, CMS_URL, CODE_DIR, COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS, CONFIG_DIR, CONTENT_AUTO_TRANSFORMATION, CONTENT_DIR, COOKIE_NAME, DEFAULT_LOCALE, DICTIONARIES_DIR, DICTIONARY_PRIORITY_STRATEGY, DYNAMIC_DICTIONARIES_DIR, EDITOR_URL, ENABLE_PROXY, EXCLUDED_PATHS, FETCH_DICTIONARIES_DIR, FILE_EXTENSIONS, FILL, HEADER_NAME, I18NEXT_DICTIONARIES_DIR, IMPORT_MODE, IS_ENABLED, LIVE_SYNC, LIVE_SYNC_PORT, LOCALES, LOCALE_STORAGE_NAME, LOCATION, MAIN_DIR, MASKS_DIR, MINIFY, MODE, MODULE_AUGMENTATION_DIR, OPTIMIZE, OUTPUT_FORMAT, PORT, PREFIX, PURGE, REACT_INTL_MESSAGES_DIR, REMOTE_DICTIONARIES_DIR, REQUIRED_LOCALES, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE, STRICT_MODE, TEMP_DIR, TRAVERSE_PATTERN, TYPES_DIR, TYPE_CHECKING, UNMERGED_DICTIONARIES_DIR, WATCH };
|
|
11
|
+
export { ANALYTICS_ENABLED, ANALYTICS_FLUSH_INTERVAL, ANALYTICS_SAMPLE_RATE, APPLICATION_URL, BACKEND_URL, BASE_PATH, BUILD_MODE, CACHE, CACHE_DIR, CHUNK_GROUPING, CMS_URL, CODE_DIR, COMPILER_DICTIONARY_KEY_PREFIX, COMPILER_ENABLED, COMPILER_NO_METADATA, COMPILER_SAVE_COMPONENTS, CONFIG_DIR, CONTENT_AUTO_TRANSFORMATION, CONTENT_DIR, COOKIE_NAME, DEFAULT_LOCALE, DICTIONARIES_DIR, DICTIONARIES_PRELOAD, DICTIONARY_PRIORITY_STRATEGY, DYNAMIC_DICTIONARIES_DIR, DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, EDITOR_URL, ENABLE_PROXY, EXCLUDED_PATHS, FETCH_DICTIONARIES_DIR, FILE_EXTENSIONS, FILL, HEADER_NAME, I18NEXT_DICTIONARIES_DIR, IMPORT_MODE, IS_ENABLED, LIVE_SYNC, LIVE_SYNC_PORT, LOCALES, LOCALE_STORAGE_NAME, LOCATION, MAIN_DIR, MASKS_DIR, MINIFY, MODE, MODULE_AUGMENTATION_DIR, OPTIMIZE, OUTPUT_FORMAT, PORT, PREFIX, PRELOADED_DYNAMIC_KEY, PURGE, QUALIFIER_DYNAMIC_TYPES_KEY, REACT_INTL_MESSAGES_DIR, REMOTE_DICTIONARIES_DIR, REQUIRED_LOCALES, ROUTING_MODE, SERVER_SET_COOKIE, STORAGE, STRICT_MODE, TEMP_DIR, TRAVERSE_PATTERN, TYPES_DIR, TYPE_CHECKING, UNMERGED_DICTIONARIES_DIR, WATCH };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/dictionaryPreload.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Matches a generated dynamic entry point, whose layout is
|
|
4
|
+
* `<dynamicDictionariesDir>/<key>.mjs`. The per-locale JSON chunks it imports
|
|
5
|
+
* live one directory deeper, under `json/`, and are deliberately excluded.
|
|
6
|
+
*/
|
|
7
|
+
declare const DYNAMIC_ENTRY_PATTERN: RegExp;
|
|
8
|
+
/**
|
|
9
|
+
* Builds a filter matching only the generated dynamic entry points, for
|
|
10
|
+
* bundlers whose load hook is selected by a regular expression over the raw
|
|
11
|
+
* file path (esbuild).
|
|
12
|
+
*
|
|
13
|
+
* A hook registered on every `.mjs` would call back into JavaScript for each
|
|
14
|
+
* such file in the build, `node_modules` included, so the filter is anchored on
|
|
15
|
+
* the dictionaries directory name. It matches both path separators because
|
|
16
|
+
* esbuild tests the platform path, which is backslash-separated on Windows —
|
|
17
|
+
* the directory name itself never contains one.
|
|
18
|
+
*
|
|
19
|
+
* The name alone is not proof of location, so the callback must still confirm
|
|
20
|
+
* the full path lies inside `dynamicDictionariesDir`.
|
|
21
|
+
*
|
|
22
|
+
* @param dynamicDictionariesDir - Absolute dictionaries root, any separator.
|
|
23
|
+
*/
|
|
24
|
+
declare const createDynamicEntryFilter: (dynamicDictionariesDir: string) => RegExp;
|
|
25
|
+
/**
|
|
26
|
+
* Specifier of the module the injected preamble reads the locale from, as the
|
|
27
|
+
* bundler plugins are expected to resolve it.
|
|
28
|
+
*
|
|
29
|
+
* Never emitted as-is: a generated entry point lives in the *application's*
|
|
30
|
+
* `.intlayer` directory, and an application depends on `intlayer` and its
|
|
31
|
+
* framework binding — not on `@intlayer/core` — so a bare specifier would
|
|
32
|
+
* resolve from a directory where the package is absent, or, worse, silently
|
|
33
|
+
* hit an unrelated copy hoisted higher up the tree.
|
|
34
|
+
*/
|
|
35
|
+
declare const PRELOAD_MODULE_SPECIFIER = "@intlayer/core/localization";
|
|
36
|
+
/**
|
|
37
|
+
* Resolves {@link PRELOAD_MODULE_SPECIFIER} to an absolute id the injected
|
|
38
|
+
* preamble can import, from a package that actually depends on it.
|
|
39
|
+
*
|
|
40
|
+
* Deliberately not `require.resolve(PRELOAD_MODULE_SPECIFIER)`: that applies
|
|
41
|
+
* the `require` condition and lands on the package's CommonJS build, which the
|
|
42
|
+
* preamble would then pull into a *browser* bundle behind a CommonJS interop
|
|
43
|
+
* wrapper — a second copy of the module alongside the ESM one the application
|
|
44
|
+
* already imports, each with its own memoized locale. The manifest is resolved
|
|
45
|
+
* instead (a condition-free subpath) and its `import` entry read directly.
|
|
46
|
+
*
|
|
47
|
+
* @param requireFn - `require`, or `createRequire(import.meta.url)`, from the
|
|
48
|
+
* plugin package.
|
|
49
|
+
* @returns Absolute path to the ESM build, falling back to whatever the
|
|
50
|
+
* standard resolution yields if the package ever stops publishing one.
|
|
51
|
+
*/
|
|
52
|
+
declare const resolvePreloadModuleId: (requireFn: NodeRequire) => string;
|
|
53
|
+
/** Why a generated entry point was left untransformed. */
|
|
54
|
+
type PreloadSkipReason = 'qualified' | 'unrecognized-shape';
|
|
55
|
+
type PreloadTransformResult = {
|
|
56
|
+
code: string;
|
|
57
|
+
skipped?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
code?: undefined;
|
|
60
|
+
skipped: PreloadSkipReason;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Adds the browsing-locale preload to a generated dynamic entry point.
|
|
64
|
+
*
|
|
65
|
+
* Bundler-agnostic on purpose: the Vite plugin and the esbuild plugin apply the
|
|
66
|
+
* identical transform, and keeping one implementation means the emitted shape
|
|
67
|
+
* cannot drift between them. The caller decides *which* modules to hand over
|
|
68
|
+
* (the id is matched against the dynamic dictionaries directory) and how to
|
|
69
|
+
* report a skip.
|
|
70
|
+
*
|
|
71
|
+
* @param code - Source of the generated `<key>.mjs` entry point.
|
|
72
|
+
* @param preloadModuleId - Specifier the preamble imports the locale resolver
|
|
73
|
+
* from, already resolved against the plugin package.
|
|
74
|
+
* @returns The transformed source, or the reason it was left alone.
|
|
75
|
+
*/
|
|
76
|
+
declare const addDynamicEntryPreload: (code: string, preloadModuleId: string) => PreloadTransformResult;
|
|
77
|
+
//#endregion
|
|
78
|
+
export { DYNAMIC_ENTRY_PATTERN, PRELOAD_MODULE_SPECIFIER, PreloadSkipReason, PreloadTransformResult, addDynamicEntryPreload, createDynamicEntryFilter, resolvePreloadModuleId };
|
|
79
|
+
//# sourceMappingURL=dictionaryPreload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaryPreload.d.ts","names":[],"sources":["../../src/dictionaryPreload.ts"],"mappings":";;;;;;cAYa,uBAAqB;;;;;;;;;;;;;;;;;cAsBrB,2BAAwB,mCAElC;;;;;;;;;;;cAmBU;;;;;;;;;;;;;;;;;cA2BA,yBAAsB,WAAe;;KAuEtC;KAEA;EACN;EAAc;;EACd;EAAkB,SAAS;;;;;;;;;;;;;;;;cAgBpB,yBAAsB,cACrB,4BAEX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/config",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Retrieve Intlayer configurations and manage environment variables for both server-side and client-side environments.",
|
|
6
6
|
"keywords": [
|
|
@@ -97,6 +97,11 @@
|
|
|
97
97
|
"require": "./dist/cjs/defaultValues/index.cjs",
|
|
98
98
|
"import": "./dist/esm/defaultValues/index.mjs"
|
|
99
99
|
},
|
|
100
|
+
"./dictionaryPreload": {
|
|
101
|
+
"types": "./dist/types/dictionaryPreload.d.ts",
|
|
102
|
+
"require": "./dist/cjs/dictionaryPreload.cjs",
|
|
103
|
+
"import": "./dist/esm/dictionaryPreload.mjs"
|
|
104
|
+
},
|
|
100
105
|
"./bundle": {
|
|
101
106
|
"types": "./dist/types/bundle/index.d.ts",
|
|
102
107
|
"require": "./dist/cjs/bundle/index.cjs",
|
|
@@ -172,7 +177,7 @@
|
|
|
172
177
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
173
178
|
},
|
|
174
179
|
"dependencies": {
|
|
175
|
-
"@intlayer/types": "9.3.
|
|
180
|
+
"@intlayer/types": "9.3.3",
|
|
176
181
|
"defu": "6.1.7",
|
|
177
182
|
"dotenv": "17.4.2",
|
|
178
183
|
"esbuild": "0.28.2",
|
|
@@ -187,7 +192,7 @@
|
|
|
187
192
|
"rimraf": "6.1.3",
|
|
188
193
|
"tsdown": "0.22.14",
|
|
189
194
|
"typescript": "7.0.2",
|
|
190
|
-
"vitest": "4.1.
|
|
195
|
+
"vitest": "4.1.11"
|
|
191
196
|
},
|
|
192
197
|
"peerDependencies": {
|
|
193
198
|
"react": ">=16.0.0"
|