vite-intlayer 7.3.11 → 7.3.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-intlayer",
3
- "version": "7.3.11",
3
+ "version": "7.3.12",
4
4
  "private": false,
5
5
  "description": "A Vite plugin for seamless internationalization (i18n), providing locale detection, redirection, and environment-based configuration",
6
6
  "keywords": [
@@ -35,17 +35,18 @@
35
35
  }
36
36
  ],
37
37
  "sideEffects": false,
38
+ "type": "module",
38
39
  "exports": {
39
40
  ".": {
40
41
  "types": "./dist/types/index.d.ts",
41
- "require": "./dist/cjs/index.cjs",
42
- "import": "./dist/esm/index.mjs"
42
+ "import": "./dist/esm/index.mjs",
43
+ "default": "./dist/esm/index.mjs"
43
44
  },
44
45
  "./package.json": "./package.json"
45
46
  },
46
- "main": "dist/cjs/index.cjs",
47
- "module": "dist/esm/index.mjs",
48
- "types": "dist/types/index.d.ts",
47
+ "main": "./dist/esm/index.mjs",
48
+ "module": "./dist/esm/index.mjs",
49
+ "types": "./dist/types/index.d.ts",
49
50
  "typesVersions": {
50
51
  "*": {
51
52
  "package.json": [
@@ -77,14 +78,14 @@
77
78
  },
78
79
  "dependencies": {
79
80
  "@babel/core": "7.28.4",
80
- "@intlayer/babel": "7.3.11",
81
- "@intlayer/chokidar": "7.3.11",
82
- "@intlayer/config": "7.3.11",
83
- "@intlayer/core": "7.3.11",
84
- "@intlayer/dictionaries-entry": "7.3.11",
85
- "@intlayer/types": "7.3.11",
81
+ "@intlayer/babel": "7.3.12",
82
+ "@intlayer/chokidar": "7.3.12",
83
+ "@intlayer/config": "7.3.12",
84
+ "@intlayer/core": "7.3.12",
85
+ "@intlayer/dictionaries-entry": "7.3.12",
86
+ "@intlayer/types": "7.3.12",
86
87
  "fast-glob": "3.3.3",
87
- "intlayer": "7.3.11"
88
+ "intlayer": "7.3.12"
88
89
  },
89
90
  "devDependencies": {
90
91
  "@types/node": "24.10.1",
@@ -98,8 +99,8 @@
98
99
  },
99
100
  "peerDependencies": {
100
101
  "@babel/core": ">=6.0.0",
101
- "@intlayer/svelte-compiler": "7.3.11",
102
- "@intlayer/vue-compiler": "7.3.11",
102
+ "@intlayer/svelte-compiler": "7.3.12",
103
+ "@intlayer/vue-compiler": "7.3.12",
103
104
  "vite": ">=4.0.0"
104
105
  },
105
106
  "peerDependenciesMeta": {
@@ -1,520 +0,0 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- let node_fs = require("node:fs");
3
- let node_fs_promises = require("node:fs/promises");
4
- let node_module = require("node:module");
5
- let node_path = require("node:path");
6
- let __intlayer_babel = require("@intlayer/babel");
7
- let __intlayer_chokidar = require("@intlayer/chokidar");
8
- let __intlayer_config = require("@intlayer/config");
9
-
10
- //#region src/IntlayerCompilerPlugin.ts
11
- /**
12
- * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer
13
- *
14
- * This autonomous compiler handles:
15
- * - Configuration loading and management
16
- * - Hot Module Replacement (HMR) for content changes
17
- * - File transformation with content extraction
18
- * - Dictionary persistence and building
19
- *
20
- * @example
21
- * ```ts
22
- * // vite.config.ts
23
- * import { defineConfig } from 'vite';
24
- * import { intlayerCompiler } from 'vite-intlayer';
25
- *
26
- * export default defineConfig({
27
- * plugins: [intlayerCompiler()],
28
- * });
29
- * ```
30
- */
31
- const intlayerCompiler = (options) => {
32
- let config;
33
- let logger;
34
- let projectRoot = "";
35
- let filesList = [];
36
- let babel = null;
37
- let pendingDictionaryWrite = null;
38
- const recentlyProcessedFiles = /* @__PURE__ */ new Map();
39
- const recentDictionaryContent = /* @__PURE__ */ new Map();
40
- const DEBOUNCE_MS = 500;
41
- const configOptions = options?.configOptions;
42
- const customCompilerConfig = options?.compilerConfig;
43
- /**
44
- * Check if a file was recently processed (within debounce window)
45
- * and should be skipped to prevent infinite loops
46
- */
47
- const wasRecentlyProcessed = (filePath) => {
48
- const lastProcessed = recentlyProcessedFiles.get(filePath);
49
- if (!lastProcessed) return false;
50
- return Date.now() - lastProcessed < DEBOUNCE_MS;
51
- };
52
- /**
53
- * Mark a file as recently processed
54
- */
55
- const markAsProcessed = (filePath) => {
56
- recentlyProcessedFiles.set(filePath, Date.now());
57
- const now = Date.now();
58
- for (const [path, timestamp] of recentlyProcessedFiles.entries()) if (now - timestamp > DEBOUNCE_MS * 2) recentlyProcessedFiles.delete(path);
59
- };
60
- /**
61
- * Create a simple hash of content for comparison
62
- * Used to detect if dictionary content has actually changed
63
- */
64
- const hashContent = (content) => {
65
- return JSON.stringify(Object.keys(content).sort().map((k) => [k, content[k]]));
66
- };
67
- /**
68
- * Check if dictionary content has changed since last write
69
- */
70
- const hasDictionaryContentChanged = (dictionaryKey, content) => {
71
- const newHash = hashContent(content);
72
- if (recentDictionaryContent.get(dictionaryKey) === newHash) return false;
73
- recentDictionaryContent.set(dictionaryKey, newHash);
74
- return true;
75
- };
76
- /**
77
- * Get compiler config from intlayer config or custom options
78
- */
79
- const getCompilerConfig = () => {
80
- const rawConfig = config;
81
- return {
82
- enabled: customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,
83
- transformPattern: customCompilerConfig?.transformPattern ?? rawConfig.compiler?.transformPattern ?? config.build.traversePattern,
84
- excludePattern: [
85
- ...customCompilerConfig?.excludePattern ?? [],
86
- "**/node_modules/**",
87
- ...config.content.fileExtensions.map((pattern) => `*${pattern}`)
88
- ],
89
- outputDir: customCompilerConfig?.outputDir ?? rawConfig.compiler?.outputDir ?? "compiler"
90
- };
91
- };
92
- /**
93
- * Get the output directory path for compiler dictionaries
94
- */
95
- const getOutputDir = () => {
96
- const { baseDir } = config.content;
97
- return (0, node_path.join)(baseDir, getCompilerConfig().outputDir);
98
- };
99
- /**
100
- * Get the file path for a dictionary
101
- */
102
- const getDictionaryFilePath = (dictionaryKey) => {
103
- return (0, node_path.join)(getOutputDir(), `${dictionaryKey}.content.json`);
104
- };
105
- /**
106
- * Read an existing dictionary file if it exists
107
- */
108
- const readExistingDictionary = async (dictionaryKey) => {
109
- const filePath = getDictionaryFilePath(dictionaryKey);
110
- if (!(0, node_fs.existsSync)(filePath)) return null;
111
- try {
112
- const content = await (0, node_fs_promises.readFile)(filePath, "utf-8");
113
- return JSON.parse(content);
114
- } catch {
115
- return null;
116
- }
117
- };
118
- /**
119
- * Merge extracted content with existing dictionary for multilingual format.
120
- * - Keys in extracted but not in existing: added with default locale only
121
- * - Keys in both: preserve existing translations, update default locale value
122
- * - Keys in existing but not in extracted: removed (no longer in source)
123
- */
124
- const mergeWithExistingMultilingualDictionary = (extractedContent, existingDictionary, defaultLocale) => {
125
- const mergedContent = {};
126
- const existingContent = existingDictionary?.content;
127
- for (const [key, value] of Object.entries(extractedContent)) {
128
- const existingEntry = existingContent?.[key];
129
- if (existingEntry && existingEntry.nodeType === "translation" && existingEntry.translation) {
130
- const oldValue = existingEntry.translation[defaultLocale];
131
- const isUpdated = oldValue !== value;
132
- mergedContent[key] = {
133
- nodeType: "translation",
134
- translation: {
135
- ...existingEntry.translation,
136
- [defaultLocale]: value
137
- }
138
- };
139
- if (isUpdated) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Updated "${key}" [${defaultLocale}]: "${oldValue?.slice(0, 30)}..." → "${value.slice(0, 30)}..."`, {
140
- level: "info",
141
- isVerbose: true
142
- });
143
- } else {
144
- mergedContent[key] = {
145
- nodeType: "translation",
146
- translation: { [defaultLocale]: value }
147
- };
148
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Added new key "${key}"`, {
149
- level: "info",
150
- isVerbose: true
151
- });
152
- }
153
- }
154
- if (existingContent) {
155
- const removedKeys = Object.keys(existingContent).filter((key) => !(key in extractedContent));
156
- for (const key of removedKeys) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Removed key "${key}" (no longer in source)`, {
157
- level: "info",
158
- isVerbose: true
159
- });
160
- }
161
- return mergedContent;
162
- };
163
- /**
164
- * Merge extracted content with existing dictionary for per-locale format.
165
- * - Keys in extracted but not in existing: added
166
- * - Keys in both: update value
167
- * - Keys in existing but not in extracted: removed (no longer in source)
168
- */
169
- const mergeWithExistingPerLocaleDictionary = (extractedContent, existingDictionary, defaultLocale) => {
170
- const mergedContent = {};
171
- const existingContent = existingDictionary?.content;
172
- for (const [key, value] of Object.entries(extractedContent)) {
173
- const existingValue = existingContent?.[key];
174
- if (existingValue && typeof existingValue === "string") {
175
- const isUpdated = existingValue !== value;
176
- mergedContent[key] = value;
177
- if (isUpdated) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Updated "${key}" [${defaultLocale}]: "${existingValue?.slice(0, 30)}..." → "${value.slice(0, 30)}..."`, {
178
- level: "info",
179
- isVerbose: true
180
- });
181
- } else {
182
- mergedContent[key] = value;
183
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Added new key "${key}"`, {
184
- level: "info",
185
- isVerbose: true
186
- });
187
- }
188
- }
189
- if (existingContent) {
190
- const removedKeys = Object.keys(existingContent).filter((key) => !(key in extractedContent));
191
- for (const key of removedKeys) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Removed key "${key}" (no longer in source)`, {
192
- level: "info",
193
- isVerbose: true
194
- });
195
- }
196
- return mergedContent;
197
- };
198
- /**
199
- * Build the list of files to transform based on configuration patterns
200
- */
201
- const buildFilesListFn = async () => {
202
- const { baseDir, fileExtensions } = config.content;
203
- const compilerConfig = getCompilerConfig();
204
- const excludePatterns = Array.isArray(compilerConfig.excludePattern) ? compilerConfig.excludePattern : [compilerConfig.excludePattern];
205
- filesList = (0, __intlayer_chokidar.buildFilesList)({
206
- transformPattern: compilerConfig.transformPattern,
207
- excludePattern: [
208
- ...excludePatterns,
209
- "**/node_modules/**",
210
- ...fileExtensions.map((pattern) => `**/*${pattern}`)
211
- ],
212
- baseDir
213
- });
214
- };
215
- /**
216
- * Initialize the compiler with the given mode
217
- */
218
- const init = async (_compilerMode) => {
219
- config = (0, __intlayer_config.getConfiguration)(configOptions);
220
- logger = (0, __intlayer_config.getAppLogger)(config);
221
- try {
222
- babel = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("@babel/core");
223
- } catch {
224
- logger("Failed to load @babel/core. Transformation will be disabled.", { level: "warn" });
225
- }
226
- await buildFilesListFn();
227
- };
228
- /**
229
- * Vite hook: config
230
- * Called before Vite config is resolved - perfect time to prepare dictionaries
231
- */
232
- const configHook = async (_config, env) => {
233
- config = (0, __intlayer_config.getConfiguration)(configOptions);
234
- logger = (0, __intlayer_config.getAppLogger)(config);
235
- const isDevCommand = env.command === "serve" && env.mode === "development";
236
- const isBuildCommand = env.command === "build";
237
- if (isDevCommand || isBuildCommand) await (0, __intlayer_chokidar.prepareIntlayer)(config, {
238
- clean: isBuildCommand,
239
- cacheTimeoutMs: isBuildCommand ? 1e3 * 30 : 1e3 * 60 * 60
240
- });
241
- };
242
- /**
243
- * Vite hook: configResolved
244
- * Called when Vite config is resolved
245
- */
246
- const configResolved = async (viteConfig) => {
247
- const compilerMode = viteConfig.env?.DEV ? "dev" : "build";
248
- projectRoot = viteConfig.root;
249
- await init(compilerMode);
250
- };
251
- /**
252
- * Build start hook - no longer needs to prepare dictionaries
253
- * The compiler is now autonomous and extracts content inline
254
- */
255
- const buildStart = async () => {
256
- logger("Intlayer compiler initialized", { level: "info" });
257
- };
258
- /**
259
- * Build end hook - wait for any pending dictionary writes
260
- */
261
- const buildEnd = async () => {
262
- if (pendingDictionaryWrite) await pendingDictionaryWrite;
263
- };
264
- /**
265
- * Configure the dev server
266
- */
267
- const configureServer = async () => {};
268
- /**
269
- * Vite hook: handleHotUpdate
270
- * Handles HMR for content files - invalidates cache and triggers re-transform
271
- */
272
- const handleHotUpdate = async (ctx) => {
273
- const { file, server, modules } = ctx;
274
- if (filesList.some((f) => f === file)) {
275
- if (wasRecentlyProcessed(file)) {
276
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Skipping re-transform of ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, file))} (recently processed)`, {
277
- level: "info",
278
- isVerbose: true
279
- });
280
- return;
281
- }
282
- markAsProcessed(file);
283
- for (const mod of modules) server.moduleGraph.invalidateModule(mod);
284
- try {
285
- await transformHandler(await (0, node_fs_promises.readFile)(file, "utf-8"), file);
286
- } catch (error) {
287
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`, { level: "error" });
288
- }
289
- server.ws.send({ type: "full-reload" });
290
- return [];
291
- }
292
- };
293
- /**
294
- * Write and build a single dictionary immediately
295
- * This is called during transform to ensure dictionaries are always up-to-date.
296
- *
297
- * The merge strategy:
298
- * - New keys are added with the default locale only
299
- * - Existing keys preserve their translations, with default locale updated
300
- * - Keys no longer in source are removed
301
- *
302
- * Dictionary format:
303
- * - Per-locale: When config.dictionary.locale is set, content is simple strings with locale property
304
- * - Multilingual: When not set, content is wrapped in translation nodes without locale property
305
- */
306
- const writeAndBuildDictionary = async (result) => {
307
- const { dictionaryKey, content } = result;
308
- if (!hasDictionaryContentChanged(dictionaryKey, content)) {
309
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Skipping dictionary ${(0, __intlayer_config.colorizeKey)(dictionaryKey)} (content unchanged)`, {
310
- level: "info",
311
- isVerbose: true
312
- });
313
- return;
314
- }
315
- const outputDir = getOutputDir();
316
- const { defaultLocale } = config.internationalization;
317
- const isPerLocaleFile = Boolean(config?.dictionary?.locale);
318
- await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
319
- const existingDictionary = await readExistingDictionary(dictionaryKey);
320
- const relativeFilePath = (0, node_path.join)((0, node_path.relative)(config.content.baseDir, outputDir), `${dictionaryKey}.content.json`);
321
- let mergedDictionary;
322
- if (isPerLocaleFile) {
323
- const mergedContent = mergeWithExistingPerLocaleDictionary(content, existingDictionary, defaultLocale);
324
- mergedDictionary = {
325
- ...existingDictionary && {
326
- $schema: existingDictionary.$schema,
327
- id: existingDictionary.id,
328
- title: existingDictionary.title,
329
- description: existingDictionary.description,
330
- tags: existingDictionary.tags,
331
- fill: existingDictionary.fill,
332
- filled: existingDictionary.filled,
333
- priority: existingDictionary.priority,
334
- version: existingDictionary.version
335
- },
336
- key: dictionaryKey,
337
- content: mergedContent,
338
- locale: defaultLocale,
339
- filePath: relativeFilePath
340
- };
341
- } else {
342
- const mergedContent = mergeWithExistingMultilingualDictionary(content, existingDictionary, defaultLocale);
343
- mergedDictionary = {
344
- ...existingDictionary && {
345
- $schema: existingDictionary.$schema,
346
- id: existingDictionary.id,
347
- title: existingDictionary.title,
348
- description: existingDictionary.description,
349
- tags: existingDictionary.tags,
350
- fill: existingDictionary.fill,
351
- filled: existingDictionary.filled,
352
- priority: existingDictionary.priority,
353
- version: existingDictionary.version
354
- },
355
- key: dictionaryKey,
356
- content: mergedContent,
357
- filePath: relativeFilePath
358
- };
359
- }
360
- try {
361
- const writeResult = await (0, __intlayer_chokidar.writeContentDeclaration)(mergedDictionary, config, { newDictionariesPath: (0, node_path.relative)(config.content.baseDir, outputDir) });
362
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} ${writeResult.status === "created" ? "Created" : writeResult.status === "updated" ? "Updated" : "Processed"} content declaration: ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, writeResult.path))}`, { level: "info" });
363
- const dictionaryToBuild = {
364
- ...mergedDictionary,
365
- filePath: (0, node_path.relative)(config.content.baseDir, writeResult.path)
366
- };
367
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Building dictionary ${(0, __intlayer_config.colorizeKey)(dictionaryKey)}`, { level: "info" });
368
- await (0, __intlayer_chokidar.buildDictionary)([dictionaryToBuild], config);
369
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Dictionary ${(0, __intlayer_config.colorizeKey)(dictionaryKey)} built successfully`, { level: "info" });
370
- } catch (error) {
371
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${(0, __intlayer_config.colorizeKey)(dictionaryKey)}: ${error}`, { level: "error" });
372
- }
373
- };
374
- /**
375
- * Callback for when content is extracted from a file
376
- * Immediately writes and builds the dictionary
377
- */
378
- const handleExtractedContent = (result) => {
379
- const contentKeys = Object.keys(result.content);
380
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, result.filePath))}`, { level: "info" });
381
- pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve()).then(() => writeAndBuildDictionary(result)).catch((error) => {
382
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`, { level: "error" });
383
- });
384
- };
385
- /**
386
- * Detect the package name to import useIntlayer from based on file extension
387
- */
388
- const detectPackageName = (filename) => {
389
- if (filename.endsWith(".vue")) return "vue-intlayer";
390
- if (filename.endsWith(".svelte")) return "svelte-intlayer";
391
- if (filename.endsWith(".tsx") || filename.endsWith(".jsx")) return "react-intlayer";
392
- return "intlayer";
393
- };
394
- /**
395
- * Transform a Vue file using the Vue extraction plugin
396
- */
397
- const transformVue = async (code, filename, defaultLocale) => {
398
- const { intlayerVueExtract } = await import("@intlayer/vue-compiler");
399
- return intlayerVueExtract(code, filename, {
400
- defaultLocale,
401
- filesList,
402
- packageName: "vue-intlayer",
403
- onExtract: handleExtractedContent
404
- });
405
- };
406
- /**
407
- * Transform a Svelte file using the Svelte extraction plugin
408
- */
409
- const transformSvelte = async (code, filename, defaultLocale) => {
410
- const { intlayerSvelteExtract } = await import("@intlayer/svelte-compiler");
411
- return await intlayerSvelteExtract(code, filename, {
412
- defaultLocale,
413
- filesList,
414
- packageName: "svelte-intlayer",
415
- onExtract: handleExtractedContent
416
- });
417
- };
418
- /**
419
- * Transform a JSX/TSX file using the Babel extraction plugin
420
- */
421
- const transformJsx = (code, filename, defaultLocale) => {
422
- if (!babel) return;
423
- const packageName = detectPackageName(filename);
424
- const result = babel.transformSync(code, {
425
- filename,
426
- plugins: [[__intlayer_babel.intlayerExtractBabelPlugin, {
427
- defaultLocale,
428
- filesList,
429
- packageName,
430
- onExtract: handleExtractedContent
431
- }]],
432
- parserOpts: {
433
- sourceType: "module",
434
- allowImportExportEverywhere: true,
435
- plugins: [
436
- "typescript",
437
- "jsx",
438
- "decorators-legacy",
439
- "classProperties",
440
- "objectRestSpread",
441
- "asyncGenerators",
442
- "functionBind",
443
- "exportDefaultFrom",
444
- "exportNamespaceFrom",
445
- "dynamicImport",
446
- "nullishCoalescingOperator",
447
- "optionalChaining"
448
- ]
449
- }
450
- });
451
- if (result?.code) return {
452
- code: result.code,
453
- map: result.map,
454
- extracted: true
455
- };
456
- };
457
- /**
458
- * Transform a file using the appropriate extraction plugin based on file type
459
- */
460
- const transformHandler = async (code, id, _options) => {
461
- if (!getCompilerConfig().enabled) return;
462
- if (id.includes("?")) return;
463
- const { defaultLocale } = config.internationalization;
464
- const filename = id;
465
- if (!filesList.includes(filename)) return;
466
- const isVue = filename.endsWith(".vue");
467
- const isSvelte = filename.endsWith(".svelte");
468
- if (!isVue && !isSvelte) {
469
- try {
470
- const result = transformJsx(code, filename, defaultLocale);
471
- if (pendingDictionaryWrite) await pendingDictionaryWrite;
472
- if (result?.code) return {
473
- code: result.code,
474
- map: result.map
475
- };
476
- } catch (error) {
477
- logger(`Failed to transform ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, filename))}: ${error}`, { level: "error" });
478
- }
479
- return;
480
- }
481
- logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Transforming ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, filename))}`, { level: "info" });
482
- try {
483
- let result;
484
- if (isVue) result = await transformVue(code, filename, defaultLocale);
485
- else if (isSvelte) result = await transformSvelte(code, filename, defaultLocale);
486
- if (pendingDictionaryWrite) await pendingDictionaryWrite;
487
- if (result?.code) return {
488
- code: result.code,
489
- map: result.map
490
- };
491
- } catch (error) {
492
- logger(`Failed to transform ${(0, node_path.relative)(projectRoot, filename)}: ${error}`, { level: "error" });
493
- }
494
- };
495
- /**
496
- * Apply hook for determining when plugin should be active
497
- */
498
- const apply = (_config, _env) => {
499
- return getCompilerConfig().enabled;
500
- };
501
- return {
502
- name: "vite-intlayer-compiler",
503
- enforce: "pre",
504
- config: configHook,
505
- configResolved,
506
- buildStart,
507
- buildEnd,
508
- configureServer,
509
- handleHotUpdate,
510
- transform: transformHandler,
511
- apply: (_viteConfig, env) => {
512
- if (!config) config = (0, __intlayer_config.getConfiguration)(configOptions);
513
- return apply(_viteConfig, env);
514
- }
515
- };
516
- };
517
-
518
- //#endregion
519
- exports.intlayerCompiler = intlayerCompiler;
520
- //# sourceMappingURL=IntlayerCompilerPlugin.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"IntlayerCompilerPlugin.cjs","names":["config: IntlayerConfig","logger: ReturnType<typeof getAppLogger>","filesList: string[]","babel: any","pendingDictionaryWrite: Promise<void> | null","mergedContent: DictionaryContentMap","ANSIColors","mergedContent: Record<string, string>","compilerMode: CompilerMode","mergedDictionary: Dictionary","dictionaryToBuild: Dictionary","intlayerExtractBabelPlugin","result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined"],"sources":["../../src/IntlayerCompilerPlugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join, relative } from 'node:path';\nimport {\n type ExtractResult,\n intlayerExtractBabelPlugin,\n} from '@intlayer/babel';\nimport {\n buildDictionary,\n buildFilesList,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n colorizePath,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type {\n CompilerConfig,\n Dictionary,\n IntlayerConfig,\n} from '@intlayer/types';\n\n/**\n * Translation node structure used in dictionaries\n */\ntype TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Dictionary content structure - map of keys to translation nodes\n */\ntype DictionaryContentMap = Record<string, TranslationNode>;\n\n/**\n * Mode of the compiler\n * - 'dev': Development mode with HMR support\n * - 'build': Production build mode\n */\nexport type CompilerMode = 'dev' | 'build';\n\n/**\n * Options for initializing the compiler\n */\nexport type IntlayerCompilerOptions = {\n /**\n * Configuration options for getting the intlayer configuration\n */\n configOptions?: GetConfigurationOptions;\n\n /**\n * Custom compiler configuration to override defaults\n */\n compilerConfig?: Partial<CompilerConfig>;\n};\n\n/**\n * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer\n *\n * This autonomous compiler handles:\n * - Configuration loading and management\n * - Hot Module Replacement (HMR) for content changes\n * - File transformation with content extraction\n * - Dictionary persistence and building\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { intlayerCompiler } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayerCompiler()],\n * });\n * ```\n */\nexport const intlayerCompiler = (options?: IntlayerCompilerOptions): any => {\n // Private state\n let config: IntlayerConfig;\n let logger: ReturnType<typeof getAppLogger>;\n let projectRoot = '';\n let filesList: string[] = [];\n let babel: any = null;\n\n // Promise to track dictionary writing (for synchronization)\n let pendingDictionaryWrite: Promise<void> | null = null;\n\n // Track recently processed files to prevent infinite loops\n // Key: file path, Value: timestamp of last processing\n const recentlyProcessedFiles = new Map<string, number>();\n // Track recently written dictionaries to prevent duplicate writes\n // Key: dictionary key, Value: hash of content that was written\n const recentDictionaryContent = new Map<string, string>();\n // Debounce window in milliseconds - skip re-processing files within this window\n const DEBOUNCE_MS = 500;\n\n const configOptions = options?.configOptions;\n const customCompilerConfig = options?.compilerConfig;\n\n /**\n * Check if a file was recently processed (within debounce window)\n * and should be skipped to prevent infinite loops\n */\n const wasRecentlyProcessed = (filePath: string): boolean => {\n const lastProcessed = recentlyProcessedFiles.get(filePath);\n if (!lastProcessed) return false;\n\n const now = Date.now();\n return now - lastProcessed < DEBOUNCE_MS;\n };\n\n /**\n * Mark a file as recently processed\n */\n const markAsProcessed = (filePath: string): void => {\n recentlyProcessedFiles.set(filePath, Date.now());\n\n // Clean up old entries to prevent memory leaks\n const now = Date.now();\n for (const [path, timestamp] of recentlyProcessedFiles.entries()) {\n if (now - timestamp > DEBOUNCE_MS * 2) {\n recentlyProcessedFiles.delete(path);\n }\n }\n };\n\n /**\n * Create a simple hash of content for comparison\n * Used to detect if dictionary content has actually changed\n */\n const hashContent = (content: Record<string, string>): string => {\n return JSON.stringify(\n Object.keys(content)\n .sort()\n .map((k) => [k, content[k]])\n );\n };\n\n /**\n * Check if dictionary content has changed since last write\n */\n const hasDictionaryContentChanged = (\n dictionaryKey: string,\n content: Record<string, string>\n ): boolean => {\n const newHash = hashContent(content);\n const previousHash = recentDictionaryContent.get(dictionaryKey);\n\n if (previousHash === newHash) {\n return false;\n }\n\n // Update the stored hash\n recentDictionaryContent.set(dictionaryKey, newHash);\n return true;\n };\n\n /**\n * Get compiler config from intlayer config or custom options\n */\n const getCompilerConfig = () => {\n // Access compiler config from the raw config (may not be in the type)\n const rawConfig = config as IntlayerConfig & {\n compiler?: Partial<CompilerConfig>;\n };\n\n return {\n enabled:\n customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,\n transformPattern:\n customCompilerConfig?.transformPattern ??\n rawConfig.compiler?.transformPattern ??\n config.build.traversePattern,\n excludePattern: [\n ...(customCompilerConfig?.excludePattern ?? []),\n '**/node_modules/**',\n ...config.content.fileExtensions.map((pattern) => `*${pattern}`),\n ],\n outputDir:\n customCompilerConfig?.outputDir ??\n rawConfig.compiler?.outputDir ??\n 'compiler',\n };\n };\n\n /**\n * Get the output directory path for compiler dictionaries\n */\n const getOutputDir = (): string => {\n const { baseDir } = config.content;\n const compilerConfig = getCompilerConfig();\n return join(baseDir, compilerConfig.outputDir);\n };\n\n /**\n * Get the file path for a dictionary\n */\n const getDictionaryFilePath = (dictionaryKey: string): string => {\n const outputDir = getOutputDir();\n return join(outputDir, `${dictionaryKey}.content.json`);\n };\n\n /**\n * Read an existing dictionary file if it exists\n */\n const readExistingDictionary = async (\n dictionaryKey: string\n ): Promise<Dictionary | null> => {\n const filePath = getDictionaryFilePath(dictionaryKey);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as Dictionary;\n } catch {\n return null;\n }\n };\n\n /**\n * Merge extracted content with existing dictionary for multilingual format.\n * - Keys in extracted but not in existing: added with default locale only\n * - Keys in both: preserve existing translations, update default locale value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\n const mergeWithExistingMultilingualDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n ): DictionaryContentMap => {\n const mergedContent: DictionaryContentMap = {};\n const existingContent = existingDictionary?.content as\n | DictionaryContentMap\n | undefined;\n\n for (const [key, value] of Object.entries(extractedContent)) {\n const existingEntry = existingContent?.[key];\n\n if (\n existingEntry &&\n existingEntry.nodeType === 'translation' &&\n existingEntry.translation\n ) {\n const oldValue = existingEntry.translation[defaultLocale];\n const isUpdated = oldValue !== value;\n\n // Key exists in both - preserve existing translations, update default locale\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n ...existingEntry.translation,\n [defaultLocale]: value,\n },\n };\n\n if (isUpdated) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated \"${key}\" [${defaultLocale}]: \"${oldValue?.slice(0, 30)}...\" → \"${value.slice(0, 30)}...\"`,\n { level: 'info', isVerbose: true }\n );\n }\n } else {\n // New key - add with default locale only\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n [defaultLocale]: value,\n },\n };\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Added new key \"${key}\"`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n // Log removed keys\n if (existingContent) {\n const removedKeys = Object.keys(existingContent).filter(\n (key) => !(key in extractedContent)\n );\n for (const key of removedKeys) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Removed key \"${key}\" (no longer in source)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n return mergedContent;\n };\n\n /**\n * Merge extracted content with existing dictionary for per-locale format.\n * - Keys in extracted but not in existing: added\n * - Keys in both: update value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\n const mergeWithExistingPerLocaleDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n ): Record<string, string> => {\n const mergedContent: Record<string, string> = {};\n const existingContent = existingDictionary?.content as\n | Record<string, string>\n | undefined;\n\n for (const [key, value] of Object.entries(extractedContent)) {\n const existingValue = existingContent?.[key];\n\n if (existingValue && typeof existingValue === 'string') {\n const isUpdated = existingValue !== value;\n\n mergedContent[key] = value;\n\n if (isUpdated) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated \"${key}\" [${defaultLocale}]: \"${existingValue?.slice(0, 30)}...\" → \"${value.slice(0, 30)}...\"`,\n { level: 'info', isVerbose: true }\n );\n }\n } else {\n // New key\n mergedContent[key] = value;\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Added new key \"${key}\"`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n // Log removed keys\n if (existingContent) {\n const removedKeys = Object.keys(existingContent).filter(\n (key) => !(key in extractedContent)\n );\n for (const key of removedKeys) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Removed key \"${key}\" (no longer in source)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n return mergedContent;\n };\n\n /**\n * Build the list of files to transform based on configuration patterns\n */\n const buildFilesListFn = async (): Promise<void> => {\n const { baseDir, fileExtensions } = config.content;\n const compilerConfig = getCompilerConfig();\n\n const excludePatterns = Array.isArray(compilerConfig.excludePattern)\n ? compilerConfig.excludePattern\n : [compilerConfig.excludePattern];\n\n filesList = buildFilesList({\n transformPattern: compilerConfig.transformPattern,\n excludePattern: [\n ...excludePatterns,\n '**/node_modules/**',\n ...fileExtensions.map((pattern) => `**/*${pattern}`),\n ],\n baseDir,\n });\n };\n\n /**\n * Initialize the compiler with the given mode\n */\n const init = async (_compilerMode: CompilerMode): Promise<void> => {\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n // Load Babel dynamically\n try {\n const localRequire = createRequire(import.meta.url);\n babel = localRequire('@babel/core');\n } catch {\n logger('Failed to load @babel/core. Transformation will be disabled.', {\n level: 'warn',\n });\n }\n\n // Build files list for transformation\n await buildFilesListFn();\n };\n\n /**\n * Vite hook: config\n * Called before Vite config is resolved - perfect time to prepare dictionaries\n */\n const configHook = async (\n _config: unknown,\n env: { command: string; mode: string }\n ): Promise<void> => {\n // Initialize config early\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n const isDevCommand = env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Prepare all existing dictionaries (builds them to .intlayer/dictionary/)\n // This ensures built dictionaries exist before the prune plugin runs\n if (isDevCommand || isBuildCommand) {\n await prepareIntlayer(config, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build\n : 1000 * 60 * 60, // 1 hour for dev\n });\n }\n };\n\n /**\n * Vite hook: configResolved\n * Called when Vite config is resolved\n */\n const configResolved = async (viteConfig: {\n env?: { DEV?: boolean };\n root: string;\n }): Promise<void> => {\n const compilerMode: CompilerMode = viteConfig.env?.DEV ? 'dev' : 'build';\n projectRoot = viteConfig.root;\n await init(compilerMode);\n };\n\n /**\n * Build start hook - no longer needs to prepare dictionaries\n * The compiler is now autonomous and extracts content inline\n */\n const buildStart = async (): Promise<void> => {\n // Autonomous compiler - no need to prepare dictionaries\n // Content is extracted inline during transformation\n logger('Intlayer compiler initialized', {\n level: 'info',\n });\n };\n\n /**\n * Build end hook - wait for any pending dictionary writes\n */\n const buildEnd = async (): Promise<void> => {\n // Wait for any pending dictionary writes to complete\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n };\n\n /**\n * Configure the dev server\n */\n const configureServer = async (): Promise<void> => {\n // In autonomous mode, we don't need file watching for dictionaries\n // Content is extracted inline during transformation\n };\n\n /**\n * Vite hook: handleHotUpdate\n * Handles HMR for content files - invalidates cache and triggers re-transform\n */\n const handleHotUpdate = async (ctx: any): Promise<unknown[] | undefined> => {\n const { file, server, modules } = ctx;\n\n // Check if this is a file we should transform\n const isTransformableFile = filesList.some((f) => f === file);\n\n if (isTransformableFile) {\n // Check if this file was recently processed to prevent infinite loops\n // When a component is transformed, it writes a dictionary, which triggers HMR,\n // which would re-transform the component - this debounce prevents that loop\n if (wasRecentlyProcessed(file)) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Skipping re-transform of ${colorizePath(relative(projectRoot, file))} (recently processed)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n return undefined;\n }\n\n // Mark file as being processed before transformation\n markAsProcessed(file);\n\n // Invalidate all affected modules to ensure re-transform\n for (const mod of modules) {\n server.moduleGraph.invalidateModule(mod);\n }\n\n // Force re-transform by reading and processing the file\n // This ensures content extraction happens on every file change\n try {\n const code = await readFile(file, 'utf-8');\n\n // Trigger the transform manually to extract content\n await transformHandler(code, file);\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n // Trigger full reload for content changes\n server.ws.send({ type: 'full-reload' });\n return [];\n }\n\n return undefined;\n };\n\n /**\n * Write and build a single dictionary immediately\n * This is called during transform to ensure dictionaries are always up-to-date.\n *\n * The merge strategy:\n * - New keys are added with the default locale only\n * - Existing keys preserve their translations, with default locale updated\n * - Keys no longer in source are removed\n *\n * Dictionary format:\n * - Per-locale: When config.dictionary.locale is set, content is simple strings with locale property\n * - Multilingual: When not set, content is wrapped in translation nodes without locale property\n */\n const writeAndBuildDictionary = async (\n result: ExtractResult\n ): Promise<void> => {\n const { dictionaryKey, content } = result;\n\n // Skip if content hasn't changed - prevents infinite loops during HMR\n if (!hasDictionaryContentChanged(dictionaryKey, content)) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Skipping dictionary ${colorizeKey(dictionaryKey)} (content unchanged)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n return;\n }\n\n const outputDir = getOutputDir();\n const { defaultLocale } = config.internationalization;\n\n // Check if per-locale format is configured\n // When config.dictionary.locale is set, use per-locale format (simple strings with locale property)\n // Otherwise, use multilingual format (content wrapped in TranslationNode objects)\n const isPerLocaleFile = Boolean(config?.dictionary?.locale);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n const existingDictionary = await readExistingDictionary(dictionaryKey);\n\n const relativeFilePath = join(\n relative(config.content.baseDir, outputDir),\n `${dictionaryKey}.content.json`\n );\n\n // Build dictionary based on format - matching transformFiles.ts behavior\n let mergedDictionary: Dictionary;\n\n if (isPerLocaleFile) {\n // Per-locale format: simple string content with locale property\n const mergedContent = mergeWithExistingPerLocaleDictionary(\n content,\n existingDictionary,\n defaultLocale\n );\n\n mergedDictionary = {\n // Preserve existing metadata (title, description, tags, etc.)\n ...(existingDictionary && {\n $schema: existingDictionary.$schema,\n id: existingDictionary.id,\n title: existingDictionary.title,\n description: existingDictionary.description,\n tags: existingDictionary.tags,\n fill: existingDictionary.fill,\n filled: existingDictionary.filled,\n priority: existingDictionary.priority,\n version: existingDictionary.version,\n }),\n // Required fields\n key: dictionaryKey,\n content: mergedContent,\n locale: defaultLocale,\n filePath: relativeFilePath,\n };\n } else {\n // Multilingual format: content wrapped in translation nodes, no locale property\n const mergedContent = mergeWithExistingMultilingualDictionary(\n content,\n existingDictionary,\n defaultLocale\n );\n\n mergedDictionary = {\n // Preserve existing metadata (title, description, tags, etc.)\n ...(existingDictionary && {\n $schema: existingDictionary.$schema,\n id: existingDictionary.id,\n title: existingDictionary.title,\n description: existingDictionary.description,\n tags: existingDictionary.tags,\n fill: existingDictionary.fill,\n filled: existingDictionary.filled,\n priority: existingDictionary.priority,\n version: existingDictionary.version,\n }),\n // Required fields\n key: dictionaryKey,\n content: mergedContent,\n filePath: relativeFilePath,\n };\n }\n\n try {\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n config,\n {\n newDictionariesPath: relative(config.content.baseDir, outputDir),\n }\n );\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} ${writeResult.status === 'created' ? 'Created' : writeResult.status === 'updated' ? 'Updated' : 'Processed'} content declaration: ${colorizePath(relative(projectRoot, writeResult.path))}`,\n {\n level: 'info',\n }\n );\n\n // Build the dictionary immediately so it's available for the prune plugin\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(config.content.baseDir, writeResult.path),\n };\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Building dictionary ${colorizeKey(dictionaryKey)}`,\n {\n level: 'info',\n }\n );\n\n await buildDictionary([dictionaryToBuild], config);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Dictionary ${colorizeKey(dictionaryKey)} built successfully`,\n {\n level: 'info',\n }\n );\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${colorizeKey(dictionaryKey)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n };\n\n /**\n * Callback for when content is extracted from a file\n * Immediately writes and builds the dictionary\n */\n const handleExtractedContent = (result: ExtractResult): void => {\n const contentKeys = Object.keys(result.content);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${colorizePath(relative(projectRoot, result.filePath))}`,\n {\n level: 'info',\n }\n );\n\n // Chain the write operation to ensure sequential writes\n pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve())\n .then(() => writeAndBuildDictionary(result))\n .catch((error) => {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`,\n {\n level: 'error',\n }\n );\n });\n };\n\n /**\n * Detect the package name to import useIntlayer from based on file extension\n */\n const detectPackageName = (filename: string): string => {\n if (filename.endsWith('.vue')) {\n return 'vue-intlayer';\n }\n if (filename.endsWith('.svelte')) {\n return 'svelte-intlayer';\n }\n if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {\n return 'react-intlayer';\n }\n // Default to react-intlayer for JSX/TSX files\n return 'intlayer';\n };\n\n /**\n * Transform a Vue file using the Vue extraction plugin\n */\n const transformVue = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerVueExtract } = await import('@intlayer/vue-compiler');\n return intlayerVueExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'vue-intlayer',\n onExtract: handleExtractedContent,\n });\n };\n\n /**\n * Transform a Svelte file using the Svelte extraction plugin\n */\n const transformSvelte = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerSvelteExtract } = await import('@intlayer/svelte-compiler');\n const result = await intlayerSvelteExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'svelte-intlayer',\n onExtract: handleExtractedContent,\n });\n\n return result;\n };\n\n /**\n * Transform a JSX/TSX file using the Babel extraction plugin\n */\n const transformJsx = (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n if (!babel) {\n return undefined;\n }\n\n const packageName = detectPackageName(filename);\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerExtractBabelPlugin,\n {\n defaultLocale,\n filesList,\n packageName,\n onExtract: handleExtractedContent,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n extracted: true,\n };\n }\n\n return undefined;\n };\n\n /**\n * Transform a file using the appropriate extraction plugin based on file type\n */\n const transformHandler = async (\n code: string,\n id: string,\n _options?: { ssr?: boolean }\n ) => {\n const compilerConfig = getCompilerConfig();\n\n // Only transform if compiler is enabled\n if (!compilerConfig.enabled) {\n return undefined;\n }\n\n // Skip virtual modules (query strings indicate compiled/virtual modules)\n // e.g., App.svelte?svelte&type=style, Component.vue?vue&type=script\n if (id.includes('?')) {\n return undefined;\n }\n\n const { defaultLocale } = config.internationalization;\n\n const filename = id;\n\n if (!filesList.includes(filename)) {\n return undefined;\n }\n\n // Only process Vue and Svelte source files with extraction\n // JSX/TSX files are handled by Babel which has its own detection\n const isVue = filename.endsWith('.vue');\n const isSvelte = filename.endsWith('.svelte');\n\n if (!isVue && !isSvelte) {\n // For non-Vue/Svelte files, use JSX transformation via Babel\n try {\n const result = transformJsx(code, filename, defaultLocale);\n\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${colorizePath(relative(projectRoot, filename))}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n return undefined;\n }\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Transforming ${colorizePath(relative(projectRoot, filename))}`,\n {\n level: 'info',\n }\n );\n\n try {\n let result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined;\n\n // Route to appropriate transformer based on file extension\n if (isVue) {\n result = await transformVue(code, filename, defaultLocale);\n } else if (isSvelte) {\n result = await transformSvelte(code, filename, defaultLocale);\n }\n\n // Wait for the dictionary to be written before returning\n // This ensures the dictionary exists before the prune plugin runs\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${relative(projectRoot, filename)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n return undefined;\n };\n\n /**\n * Apply hook for determining when plugin should be active\n */\n const apply = (_config: unknown, _env: { command: string }): boolean => {\n const compilerConfig = getCompilerConfig();\n // Apply if compiler is enabled\n return compilerConfig.enabled;\n };\n\n return {\n name: 'vite-intlayer-compiler',\n enforce: 'pre',\n config: configHook,\n configResolved,\n buildStart,\n buildEnd,\n configureServer,\n handleHotUpdate,\n transform: transformHandler,\n apply: (_viteConfig: unknown, env: { command: string }) => {\n // Initialize config if not already done\n if (!config) {\n config = getConfiguration(configOptions);\n }\n return apply(_viteConfig, env);\n },\n };\n};\n"],"mappings":"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"}
@@ -1,29 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
19
- }
20
- return to;
21
- };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
- value: mod,
24
- enumerable: true
25
- }) : target, mod));
26
-
27
- //#endregion
28
-
29
- exports.__toESM = __toESM;
@@ -1,13 +0,0 @@
1
- const require_IntlayerCompilerPlugin = require('./IntlayerCompilerPlugin.cjs');
2
- const require_intlayerPrunePlugin = require('./intlayerPrunePlugin.cjs');
3
- const require_intlayerPlugin = require('./intlayerPlugin.cjs');
4
- const require_intlayerProxyPlugin = require('./intlayerProxyPlugin.cjs');
5
-
6
- exports.intLayerMiddlewarePlugin = require_intlayerProxyPlugin.intLayerMiddlewarePlugin;
7
- exports.intLayerPlugin = require_intlayerPlugin.intLayerPlugin;
8
- exports.intlayer = require_intlayerPlugin.intlayer;
9
- exports.intlayerCompiler = require_IntlayerCompilerPlugin.intlayerCompiler;
10
- exports.intlayerMiddleware = require_intlayerProxyPlugin.intlayerMiddleware;
11
- exports.intlayerPlugin = require_intlayerPlugin.intlayerPlugin;
12
- exports.intlayerProxy = require_intlayerProxyPlugin.intlayerProxy;
13
- exports.intlayerPrune = require_intlayerPrunePlugin.intlayerPrune;
@@ -1,92 +0,0 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- const require_intlayerPrunePlugin = require('./intlayerPrunePlugin.cjs');
3
- let node_path = require("node:path");
4
- let __intlayer_chokidar = require("@intlayer/chokidar");
5
- let __intlayer_config = require("@intlayer/config");
6
-
7
- //#region src/intlayerPlugin.ts
8
- /**
9
- * @deprecated Rename to intlayer instead
10
- *
11
- * A Vite plugin that integrates Intlayer configuration into the build process
12
- *
13
- * ```ts
14
- * // Example usage of the plugin in a Vite configuration
15
- * export default defineConfig({
16
- * plugins: [ intlayer() ],
17
- * });
18
- * ```
19
- * */
20
- const intlayerPlugin = (configOptions) => {
21
- const intlayerConfig = (0, __intlayer_config.getConfiguration)(configOptions);
22
- const alias = (0, __intlayer_config.getAlias)({
23
- configuration: intlayerConfig,
24
- formatter: (value) => (0, node_path.resolve)(value)
25
- });
26
- const aliasPackages = Object.keys(alias);
27
- const plugins = [{
28
- name: "vite-intlayer-plugin",
29
- config: async (config, env) => {
30
- const isDevCommand = env.command === "serve" && env.mode === "development";
31
- const isBuildCommand = env.command === "build";
32
- if (isDevCommand || isBuildCommand) await (0, __intlayer_chokidar.prepareIntlayer)(intlayerConfig, {
33
- clean: isBuildCommand,
34
- cacheTimeoutMs: isBuildCommand ? 1e3 * 30 : 1e3 * 60 * 60
35
- });
36
- config.resolve = {
37
- ...config.resolve,
38
- alias: {
39
- ...config.resolve?.alias,
40
- ...alias
41
- }
42
- };
43
- config.optimizeDeps = {
44
- ...config.optimizeDeps,
45
- exclude: [...config.optimizeDeps?.exclude ?? [], ...aliasPackages]
46
- };
47
- if (config.ssr?.noExternal !== true) {
48
- const currentNoExternal = Array.isArray(config.ssr?.noExternal) ? config.ssr.noExternal : config.ssr?.noExternal ? [config.ssr.noExternal] : [];
49
- config.ssr = {
50
- ...config.ssr,
51
- noExternal: [...currentNoExternal, /(^@intlayer\/|intlayer$)/]
52
- };
53
- }
54
- return config;
55
- },
56
- configureServer: async (_server) => {
57
- if (intlayerConfig.content.watch) (0, __intlayer_chokidar.watch)({ configuration: intlayerConfig });
58
- }
59
- }];
60
- plugins.push(require_intlayerPrunePlugin.intlayerPrune(intlayerConfig));
61
- return plugins;
62
- };
63
- /**
64
- * A Vite plugin that integrates Intlayer configuration into the build process
65
- *
66
- * ```ts
67
- * // Example usage of the plugin in a Vite configuration
68
- * export default defineConfig({
69
- * plugins: [ intlayer() ],
70
- * });
71
- * ```
72
- */
73
- const intlayer = intlayerPlugin;
74
- /**
75
- * @deprecated Rename to intlayer instead
76
- *
77
- * A Vite plugin that integrates Intlayer configuration into the build process
78
- *
79
- * ```ts
80
- * // Example usage of the plugin in a Vite configuration
81
- * export default defineConfig({
82
- * plugins: [ intlayer() ],
83
- * });
84
- * ```
85
- */
86
- const intLayerPlugin = intlayerPlugin;
87
-
88
- //#endregion
89
- exports.intLayerPlugin = intLayerPlugin;
90
- exports.intlayer = intlayer;
91
- exports.intlayerPlugin = intlayerPlugin;
92
- //# sourceMappingURL=intlayerPlugin.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"intlayerPlugin.cjs","names":["plugins: PluginOption[]","intlayerPrune"],"sources":["../../src/intlayerPlugin.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport { prepareIntlayer, watch } from '@intlayer/chokidar';\nimport {\n type GetConfigurationOptions,\n getAlias,\n getConfiguration,\n} from '@intlayer/config';\n// @ts-ignore - Fix error Module '\"vite\"' has no exported member\nimport type { PluginOption } from 'vite';\nimport { intlayerPrune } from './intlayerPrunePlugin';\n\n/**\n * @deprecated Rename to intlayer instead\n *\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n * */\nexport const intlayerPlugin = (\n configOptions?: GetConfigurationOptions\n): PluginOption => {\n const intlayerConfig = getConfiguration(configOptions);\n\n const alias = getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value),\n });\n\n const aliasPackages = Object.keys(alias);\n\n const plugins: PluginOption[] = [\n {\n name: 'vite-intlayer-plugin',\n\n config: async (config, env) => {\n const isDevCommand =\n env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Only call prepareIntlayer during `dev` or `build` (not during `start`)\n // If prod: clean and rebuild once\n // If dev: rebuild only once if it's more than 1 hour since last rebuild\n if (isDevCommand || isBuildCommand) {\n // prepareIntlayer use runOnce to ensure to run only once because will run twice on client and server side otherwise\n await prepareIntlayer(intlayerConfig, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build (to ensure to rebuild all dictionaries)\n : 1000 * 60 * 60, // 1 hour for dev (default cache timeout)\n });\n }\n\n // Update Vite's resolve alias\n config.resolve = {\n ...config.resolve,\n alias: {\n ...config.resolve?.alias,\n ...alias,\n },\n };\n\n config.optimizeDeps = {\n ...config.optimizeDeps,\n exclude: [...(config.optimizeDeps?.exclude ?? []), ...aliasPackages],\n };\n\n // Update Vite's SSR Externalization\n // We must ensure that intlayer packages are processed by Vite (bundled)\n // so that the aliases defined above are actually applied\n if (config.ssr?.noExternal !== true) {\n const currentNoExternal = Array.isArray(config.ssr?.noExternal)\n ? config.ssr.noExternal\n : config.ssr?.noExternal\n ? [config.ssr.noExternal]\n : [];\n\n config.ssr = {\n ...config.ssr,\n noExternal: [\n ...(currentNoExternal as (string | RegExp)[]),\n // Regex to bundle all intlayer related packages\n /(^@intlayer\\/|intlayer$)/,\n ],\n };\n }\n\n return config;\n },\n\n configureServer: async (_server) => {\n if (intlayerConfig.content.watch) {\n // Start watching (assuming watch is also async)\n watch({ configuration: intlayerConfig });\n }\n },\n },\n ];\n\n // Add Babel transform plugin if enabled\n plugins.push(intlayerPrune(intlayerConfig));\n\n return plugins;\n};\n\n/**\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intlayer = intlayerPlugin;\n/**\n * @deprecated Rename to intlayer instead\n *\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intLayerPlugin = intlayerPlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuBA,MAAa,kBACX,kBACiB;CACjB,MAAM,yDAAkC,cAAc;CAEtD,MAAM,wCAAiB;EACrB,eAAe;EACf,YAAY,iCAA0B,MAAM;EAC7C,CAAC;CAEF,MAAM,gBAAgB,OAAO,KAAK,MAAM;CAExC,MAAMA,UAA0B,CAC9B;EACE,MAAM;EAEN,QAAQ,OAAO,QAAQ,QAAQ;GAC7B,MAAM,eACJ,IAAI,YAAY,WAAW,IAAI,SAAS;GAC1C,MAAM,iBAAiB,IAAI,YAAY;AAKvC,OAAI,gBAAgB,eAElB,gDAAsB,gBAAgB;IACpC,OAAO;IACP,gBAAgB,iBACZ,MAAO,KACP,MAAO,KAAK;IACjB,CAAC;AAIJ,UAAO,UAAU;IACf,GAAG,OAAO;IACV,OAAO;KACL,GAAG,OAAO,SAAS;KACnB,GAAG;KACJ;IACF;AAED,UAAO,eAAe;IACpB,GAAG,OAAO;IACV,SAAS,CAAC,GAAI,OAAO,cAAc,WAAW,EAAE,EAAG,GAAG,cAAc;IACrE;AAKD,OAAI,OAAO,KAAK,eAAe,MAAM;IACnC,MAAM,oBAAoB,MAAM,QAAQ,OAAO,KAAK,WAAW,GAC3D,OAAO,IAAI,aACX,OAAO,KAAK,aACV,CAAC,OAAO,IAAI,WAAW,GACvB,EAAE;AAER,WAAO,MAAM;KACX,GAAG,OAAO;KACV,YAAY,CACV,GAAI,mBAEJ,2BACD;KACF;;AAGH,UAAO;;EAGT,iBAAiB,OAAO,YAAY;AAClC,OAAI,eAAe,QAAQ,MAEzB,gCAAM,EAAE,eAAe,gBAAgB,CAAC;;EAG7C,CACF;AAGD,SAAQ,KAAKC,0CAAc,eAAe,CAAC;AAE3C,QAAO;;;;;;;;;;;;AAaT,MAAa,WAAW;;;;;;;;;;;;;AAaxB,MAAa,iBAAiB"}
@@ -1,238 +0,0 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- let __intlayer_config = require("@intlayer/config");
3
- let node_url = require("node:url");
4
- let __intlayer_config_client = require("@intlayer/config/client");
5
- let __intlayer_core = require("@intlayer/core");
6
-
7
- //#region src/intlayerProxyPlugin.ts
8
- /**
9
- *
10
- * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.
11
- *
12
- * // Example usage of the plugin in a Vite configuration
13
- * export default defineConfig({
14
- * plugins: [ intlayerProxyPlugin() ],
15
- * });
16
- *
17
- */
18
- const intlayerProxy = (configOptions, options) => {
19
- const { internationalization, routing } = (0, __intlayer_config.getConfiguration)(configOptions);
20
- const { locales: supportedLocales, defaultLocale } = internationalization;
21
- const { basePath = "", mode = __intlayer_config_client.DefaultValues.Routing.ROUTING_MODE } = routing;
22
- const noPrefix = mode === "no-prefix" || mode === "search-params";
23
- const prefixDefault = mode === "prefix-all";
24
- /**
25
- * Retrieves the locale from storage (cookies, localStorage, sessionStorage).
26
- */
27
- const getStorageLocale = (req) => {
28
- return (0, __intlayer_core.getLocaleFromStorage)({ getCookie: (name) => {
29
- return (req.headers.cookie ?? "").split(";").reduce((acc, cookie) => {
30
- const [key, val] = cookie.trim().split("=");
31
- acc[key] = val;
32
- return acc;
33
- }, {})[name] ?? null;
34
- } });
35
- };
36
- /**
37
- * Appends locale to search params when routing mode is 'search-params'.
38
- */
39
- const appendLocaleSearchIfNeeded = (search, locale) => {
40
- if (mode !== "search-params") return search;
41
- const params = new URLSearchParams(search ?? "");
42
- params.set("locale", locale);
43
- return `?${params.toString()}`;
44
- };
45
- /**
46
- * Extracts the locale from the URL pathname if present as the first segment.
47
- */
48
- const getPathLocale = (pathname) => {
49
- const firstSegment = pathname.split("/").filter(Boolean)[0];
50
- if (firstSegment && supportedLocales.includes(firstSegment)) return firstSegment;
51
- };
52
- /**
53
- * Writes a 301 redirect response with the given new URL.
54
- */
55
- const redirectUrl = (res, newUrl) => {
56
- res.writeHead(301, { Location: newUrl });
57
- return res.end();
58
- };
59
- /**
60
- * "Rewrite" the request internally by adjusting req.url;
61
- * we also set the locale in the response header if needed.
62
- */
63
- const rewriteUrl = (req, res, newUrl, locale) => {
64
- req.url = newUrl;
65
- if (locale) (0, __intlayer_core.setLocaleInStorage)(locale, { setHeader: (name, value) => res.setHeader(name, value) });
66
- };
67
- /**
68
- * Constructs a new path string, optionally including a locale prefix, basePath, and search parameters.
69
- * - basePath: (e.g., '/myapp')
70
- * - locale: (e.g., 'en')
71
- * - currentPath:(e.g., '/products/shoes')
72
- * - search: (e.g., '?foo=bar')
73
- */
74
- const constructPath = (locale, currentPath, search) => {
75
- const pathWithoutPrefix = currentPath.startsWith(`/${locale}`) ? currentPath.slice(`/${locale}`.length) ?? "/" : currentPath;
76
- const cleanBasePath = basePath.startsWith("/") ? basePath : `/${basePath}`;
77
- const normalizedBasePath = cleanBasePath === "/" ? "" : cleanBasePath;
78
- if (mode === "no-prefix") return search ? `${pathWithoutPrefix}${search}` : pathWithoutPrefix;
79
- if (mode === "search-params") return search ? `${pathWithoutPrefix}${search}` : pathWithoutPrefix;
80
- const pathWithLocalePrefix = currentPath.startsWith(`/${locale}`) ? currentPath : `/${locale}${currentPath}`;
81
- let newPath = `${normalizedBasePath}${basePath.endsWith("/") ? "" : ""}${pathWithLocalePrefix}`;
82
- if (!prefixDefault && locale === defaultLocale) newPath = `${normalizedBasePath}${pathWithoutPrefix}`;
83
- if (search) newPath += search;
84
- return newPath;
85
- };
86
- /**
87
- * If `noPrefix` is true, we never prefix the locale in the URL.
88
- * We simply rewrite the request to the same path, but with the best-chosen locale
89
- * in a header or search params if desired.
90
- */
91
- const handleNoPrefix = ({ req, res, next, originalPath, searchParams, storageLocale }) => {
92
- let locale = storageLocale ?? defaultLocale;
93
- if (!storageLocale) locale = (0, __intlayer_core.localeDetector)(req.headers, supportedLocales, defaultLocale);
94
- if (mode === "search-params") {
95
- if (new URLSearchParams(searchParams ?? "").get("locale") === locale) {
96
- rewriteUrl(req, res, `${`/${locale}${originalPath}`}${searchParams ?? ""}`, locale);
97
- return next();
98
- }
99
- const search$1 = appendLocaleSearchIfNeeded(searchParams, locale);
100
- return redirectUrl(res, search$1 ? `${originalPath}${search$1}` : `${originalPath}${searchParams ?? ""}`);
101
- }
102
- const internalPath = `/${locale}${originalPath}`;
103
- const search = appendLocaleSearchIfNeeded(searchParams, locale);
104
- rewriteUrl(req, res, search ? `${internalPath}${search}` : `${internalPath}${searchParams ?? ""}`, locale);
105
- return next();
106
- };
107
- /**
108
- * The main prefix logic:
109
- * - If there's no pathLocale in the URL, we might want to detect & redirect or rewrite
110
- * - If there is a pathLocale, handle storage mismatch or default locale special cases
111
- */
112
- const handlePrefix = ({ req, res, next, originalPath, searchParams, pathLocale, storageLocale }) => {
113
- if (!pathLocale) {
114
- handleMissingPathLocale({
115
- req,
116
- res,
117
- next,
118
- originalPath,
119
- searchParams,
120
- storageLocale
121
- });
122
- return;
123
- }
124
- handleExistingPathLocale({
125
- req,
126
- res,
127
- next,
128
- originalPath,
129
- searchParams,
130
- pathLocale
131
- });
132
- };
133
- /**
134
- * Handles requests where the locale is missing from the URL pathname.
135
- * We detect a locale from storage / headers / default, then either redirect or rewrite.
136
- */
137
- const handleMissingPathLocale = ({ req, res, next, originalPath, searchParams, storageLocale }) => {
138
- let locale = storageLocale ?? (0, __intlayer_core.localeDetector)(req.headers, supportedLocales, defaultLocale);
139
- if (!supportedLocales.includes(locale)) locale = defaultLocale;
140
- const search = appendLocaleSearchIfNeeded(searchParams, locale);
141
- const newPath = constructPath(locale, originalPath, search);
142
- if (prefixDefault || locale !== defaultLocale) return redirectUrl(res, newPath);
143
- rewriteUrl(req, res, newPath, locale);
144
- return next();
145
- };
146
- /**
147
- * Handles requests where the locale prefix is present in the pathname.
148
- */
149
- const handleExistingPathLocale = ({ req, res, next, originalPath, searchParams, pathLocale }) => {
150
- handleDefaultLocaleRedirect({
151
- req,
152
- res,
153
- next,
154
- originalPath,
155
- searchParams,
156
- pathLocale
157
- });
158
- };
159
- /**
160
- * If the path locale is the default locale but we don't want to prefix the default, remove it.
161
- */
162
- const handleDefaultLocaleRedirect = ({ req, res, next, originalPath, searchParams, pathLocale }) => {
163
- if (!prefixDefault && pathLocale === defaultLocale) {
164
- let newPath = originalPath.replace(`/${defaultLocale}`, "") || "/";
165
- if (searchParams) newPath += searchParams;
166
- rewriteUrl(req, res, newPath, pathLocale);
167
- return next();
168
- }
169
- rewriteUrl(req, res, searchParams ? `${originalPath}${searchParams}` : originalPath, pathLocale);
170
- return next();
171
- };
172
- return {
173
- name: "vite-intlayer-middleware-plugin",
174
- configureServer: (server) => {
175
- server.middlewares.use((req, res, next) => {
176
- if ((options?.ignore?.(req) ?? false) || req.url?.startsWith("/node_modules") || req.url?.startsWith("/@") || req.url?.startsWith("/_") || req.url?.split("?")[0].match(/\.[a-z]+$/i)) return next();
177
- const parsedUrl = (0, node_url.parse)(req.url ?? "/", true);
178
- const originalPath = parsedUrl.pathname ?? "/";
179
- const searchParams = parsedUrl.search ?? "";
180
- const pathLocale = getPathLocale(originalPath);
181
- const storageLocale = getStorageLocale(req);
182
- const effectiveStorageLocale = pathLocale && supportedLocales.includes(pathLocale) ? pathLocale : storageLocale;
183
- if (noPrefix) {
184
- handleNoPrefix({
185
- req,
186
- res,
187
- next,
188
- originalPath,
189
- searchParams,
190
- storageLocale: effectiveStorageLocale
191
- });
192
- return;
193
- }
194
- handlePrefix({
195
- req,
196
- res,
197
- next,
198
- originalPath,
199
- searchParams,
200
- pathLocale,
201
- storageLocale: effectiveStorageLocale
202
- });
203
- });
204
- }
205
- };
206
- };
207
- /**
208
- * @deprecated Rename to intlayerProxy instead
209
- *
210
- * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.
211
- *
212
- * ```ts
213
- * // Example usage of the plugin in a Vite configuration
214
- * export default defineConfig({
215
- * plugins: [ intlayerMiddleware() ],
216
- * });
217
- * ```
218
- */
219
- const intlayerMiddleware = intlayerProxy;
220
- /**
221
- * @deprecated Rename to intlayerProxy instead
222
- *
223
- * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.
224
-
225
- * ```ts
226
- * // Example usage of the plugin in a Vite configuration
227
- * export default defineConfig({
228
- * plugins: [ intlayerMiddleware() ],
229
- * });
230
- * ```
231
- */
232
- const intLayerMiddlewarePlugin = intlayerProxy;
233
-
234
- //#endregion
235
- exports.intLayerMiddlewarePlugin = intLayerMiddlewarePlugin;
236
- exports.intlayerMiddleware = intlayerMiddleware;
237
- exports.intlayerProxy = intlayerProxy;
238
- //# sourceMappingURL=intlayerProxyPlugin.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"intlayerProxyPlugin.cjs","names":["DefaultValues","search"],"sources":["../../src/intlayerProxyPlugin.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { parse } from 'node:url';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config';\nimport { DefaultValues } from '@intlayer/config/client';\nimport {\n getLocaleFromStorage,\n localeDetector,\n setLocaleInStorage,\n} from '@intlayer/core';\nimport type { Locale } from '@intlayer/types';\n/* @ts-ignore - Vite types error */\nimport type { Connect, Plugin } from 'vite';\n\ntype IntlayerProxyPluginOptions = {\n /**\n * A function that allows you to ignore specific requests from the intlayer proxy.\n *\n * @example\n * ```ts\n * export default defineConfig({\n * plugins: [ intlayerProxyPlugin({ ignore: (req) => req.url?.startsWith('/api') }) ],\n * });\n * ```\n *\n * @param req - The incoming request.\n * @returns A boolean value indicating whether to ignore the request.\n */\n ignore?: (req: IncomingMessage) => boolean;\n};\n\n/**\n *\n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n *\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerProxyPlugin() ],\n * });\n *\n */\nexport const intlayerProxy = (\n configOptions?: GetConfigurationOptions,\n options?: IntlayerProxyPluginOptions\n): Plugin => {\n const intlayerConfig = getConfiguration(configOptions);\n\n const { internationalization, routing } = intlayerConfig;\n const { locales: supportedLocales, defaultLocale } = internationalization;\n\n const { basePath = '', mode = DefaultValues.Routing.ROUTING_MODE } = routing;\n\n // Derived flags from routing.mode\n const noPrefix = mode === 'no-prefix' || mode === 'search-params';\n const prefixDefault = mode === 'prefix-all';\n\n /* --------------------------------------------------------------------\n * Helper & Utility Functions\n * --------------------------------------------------------------------\n */\n\n /**\n * Retrieves the locale from storage (cookies, localStorage, sessionStorage).\n */\n const getStorageLocale = (req: IncomingMessage): Locale | undefined => {\n const locale = getLocaleFromStorage({\n getCookie: (name: string) => {\n const cookieHeader = req.headers.cookie ?? '';\n const cookies = cookieHeader.split(';').reduce(\n (acc, cookie) => {\n const [key, val] = cookie.trim().split('=');\n acc[key] = val;\n return acc;\n },\n {} as Record<string, string>\n );\n return cookies[name] ?? null;\n },\n });\n return locale;\n };\n\n /**\n * Appends locale to search params when routing mode is 'search-params'.\n */\n const appendLocaleSearchIfNeeded = (\n search: string | undefined,\n locale: Locale\n ): string | undefined => {\n if (mode !== 'search-params') return search;\n\n const params = new URLSearchParams(search ?? '');\n params.set('locale', locale);\n return `?${params.toString()}`;\n };\n\n /**\n * Extracts the locale from the URL pathname if present as the first segment.\n */\n const getPathLocale = (pathname: string): Locale | undefined => {\n // e.g. if pathname is /en/some/page or /en\n // we check if \"en\" is in your supportedLocales\n const segments = pathname.split('/').filter(Boolean);\n const firstSegment = segments[0];\n if (firstSegment && supportedLocales.includes(firstSegment as Locale)) {\n return firstSegment as Locale;\n }\n return undefined;\n };\n\n /**\n * Writes a 301 redirect response with the given new URL.\n */\n const redirectUrl = (\n res: ServerResponse<IncomingMessage>,\n newUrl: string\n ) => {\n res.writeHead(301, { Location: newUrl });\n return res.end();\n };\n\n /**\n * \"Rewrite\" the request internally by adjusting req.url;\n * we also set the locale in the response header if needed.\n */\n const rewriteUrl = (\n req: Connect.IncomingMessage,\n res: ServerResponse<IncomingMessage>,\n newUrl: string,\n locale?: Locale\n ) => {\n req.url = newUrl;\n // If you want to mimic Next.js's behavior of setting a header for the locale:\n if (locale) {\n setLocaleInStorage(locale, {\n setHeader: (name: string, value: string) => res.setHeader(name, value),\n });\n }\n };\n\n /**\n * Constructs a new path string, optionally including a locale prefix, basePath, and search parameters.\n * - basePath: (e.g., '/myapp')\n * - locale: (e.g., 'en')\n * - currentPath:(e.g., '/products/shoes')\n * - search: (e.g., '?foo=bar')\n */\n const constructPath = (\n locale: Locale,\n currentPath: string,\n search?: string\n ) => {\n // Strip any incoming locale prefix if present\n const pathWithoutPrefix = currentPath.startsWith(`/${locale}`)\n ? (currentPath.slice(`/${locale}`.length) ?? '/')\n : currentPath;\n\n // Ensure basePath always starts with '/', and remove trailing slash if needed\n const cleanBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`;\n // If basePath is '/', no trailing slash is needed\n const normalizedBasePath = cleanBasePath === '/' ? '' : cleanBasePath;\n\n // In 'search-params' and 'no-prefix' modes, do not prefix the path with the locale\n if (mode === 'no-prefix') {\n const newPath = search\n ? `${pathWithoutPrefix}${search}`\n : pathWithoutPrefix;\n return newPath;\n }\n\n if (mode === 'search-params') {\n const newPath = search\n ? `${pathWithoutPrefix}${search}`\n : pathWithoutPrefix;\n return newPath;\n }\n\n // Check if path already starts with locale to avoid double-prefixing\n const pathWithLocalePrefix = currentPath.startsWith(`/${locale}`)\n ? currentPath\n : `/${locale}${currentPath}`;\n\n const basePathTrailingSlash = basePath.endsWith('/');\n\n let newPath = `${normalizedBasePath}${basePathTrailingSlash ? '' : ''}${pathWithLocalePrefix}`;\n\n // Special case: if prefixDefault is false and locale is defaultLocale, remove the locale prefix\n if (!prefixDefault && locale === defaultLocale) {\n newPath = `${normalizedBasePath}${pathWithoutPrefix}`;\n }\n\n // Append search parameters if provided\n if (search) {\n newPath += search;\n }\n\n return newPath;\n };\n\n /* --------------------------------------------------------------------\n * Handlers that mirror Next.js style logic\n * --------------------------------------------------------------------\n */\n\n /**\n * If `noPrefix` is true, we never prefix the locale in the URL.\n * We simply rewrite the request to the same path, but with the best-chosen locale\n * in a header or search params if desired.\n */\n const handleNoPrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n }) => {\n // Determine the best locale\n let locale = storageLocale ?? defaultLocale;\n\n // Use fallback to localeDetector if no storage locale\n if (!storageLocale) {\n const detectedLocale = localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n );\n locale = detectedLocale as Locale;\n }\n\n // In search-params mode, we need to redirect to add the locale search param\n if (mode === 'search-params') {\n // Check if locale search param already exists and matches the detected locale\n const existingSearchParams = new URLSearchParams(searchParams ?? '');\n const existingLocale = existingSearchParams.get('locale');\n\n // If the existing locale matches the detected locale, no redirect needed\n if (existingLocale === locale) {\n // For internal routing, we need to add the locale prefix so the framework can match [locale] param\n const internalPath = `/${locale}${originalPath}`;\n const rewritePath = `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n return next();\n }\n\n // Locale param missing or doesn't match - redirect to add/update it\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const redirectPath = search\n ? `${originalPath}${search}`\n : `${originalPath}${searchParams ?? ''}`;\n\n // Redirect to add/update the locale search param (URL changes in browser)\n return redirectUrl(res, redirectPath);\n }\n\n // For no-prefix mode (not search-params), add locale prefix internally for routing\n const internalPath = `/${locale}${originalPath}`;\n\n // Add search params if needed\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const rewritePath = search\n ? `${internalPath}${search}`\n : `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n\n return next();\n };\n\n /**\n * The main prefix logic:\n * - If there's no pathLocale in the URL, we might want to detect & redirect or rewrite\n * - If there is a pathLocale, handle storage mismatch or default locale special cases\n */\n const handlePrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale?: Locale;\n storageLocale?: Locale;\n }) => {\n // 1. If pathLocale is missing, handle\n if (!pathLocale) {\n handleMissingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n });\n return;\n }\n\n // 2. If pathLocale exists, handle it\n handleExistingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n });\n };\n\n /**\n * Handles requests where the locale is missing from the URL pathname.\n * We detect a locale from storage / headers / default, then either redirect or rewrite.\n */\n const handleMissingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n }) => {\n // 1. Choose the best locale\n let locale = (storageLocale ??\n localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n )) as Locale;\n\n // 2. If still invalid, fallback\n if (!supportedLocales.includes(locale)) {\n locale = defaultLocale;\n }\n\n // 3. Construct new path - preserving original search params\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const newPath = constructPath(locale, originalPath, search);\n\n // If we always prefix default or if this is not the default locale, do a 301 redirect\n // so that the user sees the locale in the URL.\n if (prefixDefault || locale !== defaultLocale) {\n return redirectUrl(res, newPath);\n }\n\n // If we do NOT prefix the default locale, just rewrite in place\n rewriteUrl(req, res, newPath, locale);\n return next();\n };\n\n /**\n * Handles requests where the locale prefix is present in the pathname.\n */\n const handleExistingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale: Locale;\n }) => {\n // In prefix modes, respect the URL path locale\n // The path locale takes precedence, and we'll update storage to match\n handleDefaultLocaleRedirect({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n });\n };\n\n /**\n * If the path locale is the default locale but we don't want to prefix the default, remove it.\n */\n const handleDefaultLocaleRedirect = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale: Locale;\n }) => {\n // If we don't prefix default AND the path locale is the default locale -> remove it\n if (!prefixDefault && pathLocale === defaultLocale) {\n // Remove the default locale part from the path\n let newPath = originalPath.replace(`/${defaultLocale}`, '') || '/';\n // In prefix modes, don't add locale to search params\n // Just preserve the original search params if they exist\n if (searchParams) {\n newPath += searchParams;\n }\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n }\n\n // If we do prefix default or pathLocale != default, keep as is, but rewrite headers\n // Preserve original search params without adding locale\n const newPath = searchParams\n ? `${originalPath}${searchParams}`\n : originalPath;\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n };\n\n return {\n name: 'vite-intlayer-middleware-plugin',\n configureServer: (server) => {\n server.middlewares.use((req, res, next) => {\n // Bypass assets and special Vite endpoints\n if (\n // Custom ignore function\n (options?.ignore?.(req) ?? false) ||\n req.url?.startsWith('/node_modules') ||\n /**\n * /^@vite/ # HMR client and helpers\n * /^@fs/ # file-system import serving\n * /^@id/ # virtual module ids\n * /^@tanstack/start-router-manifest # Tanstack Start Router manifest\n */\n req.url?.startsWith('/@') ||\n /**\n * /^__vite_ping$ # health ping\n * /^__open-in-editor$\n * /^__manifest$ # Remix/RR7 lazyRouteDiscovery\n */\n req.url?.startsWith('/_') ||\n /**\n * ./myFile.js\n */\n req.url\n ?.split('?')[0]\n .match(/\\.[a-z]+$/i) // checks for file extensions\n ) {\n return next();\n }\n\n // Parse original URL for path and query\n const parsedUrl = parse(req.url ?? '/', true);\n const originalPath = parsedUrl.pathname ?? '/';\n const searchParams = parsedUrl.search ?? '';\n\n // Check if there's a locale prefix in the path FIRST\n const pathLocale = getPathLocale(originalPath);\n\n // Attempt to read the locale from storage (cookies, localStorage, etc.)\n const storageLocale = getStorageLocale(req);\n\n // CRITICAL FIX: If there's a valid pathLocale, it takes precedence over storage\n // This prevents race conditions when cookies are stale during locale switches\n const effectiveStorageLocale =\n pathLocale && supportedLocales.includes(pathLocale)\n ? pathLocale\n : storageLocale;\n\n // If noPrefix is true, we skip prefix logic altogether\n if (noPrefix) {\n handleNoPrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale: effectiveStorageLocale,\n });\n return;\n }\n\n // Otherwise, handle prefix logic\n handlePrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale: effectiveStorageLocale,\n });\n });\n },\n };\n};\n\n/**\n * @deprecated Rename to intlayerProxy instead\n *\n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intlayerMiddleware = intlayerProxy;\n\n/**\n * @deprecated Rename to intlayerProxy instead\n * \n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intLayerMiddlewarePlugin = intlayerProxy;\n"],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- let node_module = require("node:module");
3
- let node_path = require("node:path");
4
- let __intlayer_babel = require("@intlayer/babel");
5
- let __intlayer_chokidar = require("@intlayer/chokidar");
6
- let __intlayer_config = require("@intlayer/config");
7
- let __intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
8
- let fast_glob = require("fast-glob");
9
- fast_glob = require_rolldown_runtime.__toESM(fast_glob);
10
-
11
- //#region src/intlayerPrunePlugin.ts
12
- const intlayerPrune = (intlayerConfig) => {
13
- try {
14
- const babel = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("@babel/core");
15
- const logger = (0, __intlayer_config.getAppLogger)(intlayerConfig);
16
- const { importMode, traversePattern, optimize } = intlayerConfig.build;
17
- const { dictionariesDir, dynamicDictionariesDir, unmergedDictionariesDir, fetchDictionariesDir, mainDir, baseDir } = intlayerConfig.content;
18
- const filesListPattern = fast_glob.default.sync(traversePattern, { cwd: baseDir }).map((file) => {
19
- if ((0, node_path.isAbsolute)(file)) return file;
20
- return (0, node_path.join)(baseDir, file);
21
- });
22
- const dictionariesEntryPath = (0, node_path.join)(mainDir, "dictionaries.mjs");
23
- const unmergedDictionariesEntryPath = (0, node_path.join)(mainDir, "unmerged_dictionaries.mjs");
24
- const dynamicDictionariesEntryPath = (0, node_path.join)(mainDir, "dynamic_dictionaries.mjs");
25
- const filesList = [
26
- ...filesListPattern,
27
- dictionariesEntryPath,
28
- unmergedDictionariesEntryPath
29
- ];
30
- const dictionaries = (0, __intlayer_dictionaries_entry.getDictionaries)(intlayerConfig);
31
- const liveSyncKeys = Object.values(dictionaries).filter((dictionary) => dictionary.live).map((dictionary) => dictionary.key);
32
- return [{
33
- name: "vite-intlayer-simple-transform",
34
- enforce: "pre",
35
- apply: (_config, env) => {
36
- const isBuild = env.command === "build";
37
- return (optimize === void 0 && isBuild || optimize === true) && (importMode === "dynamic" || importMode === "live");
38
- },
39
- transform(code, id) {
40
- if (!id.endsWith(".vue")) return null;
41
- if (!code.includes("useIntlayer")) return null;
42
- return {
43
- code: code.replace(/(\s+|=\s*)useIntlayer\s*\(/g, "$1await useIntlayer("),
44
- map: null
45
- };
46
- }
47
- }, {
48
- name: "vite-intlayer-babel-transform",
49
- enforce: "post",
50
- apply: (_config, env) => {
51
- const isBuild = env.command === "build";
52
- const isEnabled = optimize === void 0 && isBuild || optimize === true;
53
- if (isEnabled) (0, __intlayer_chokidar.runOnce)((0, node_path.join)(baseDir, ".intlayer", "cache", "intlayer-prune-plugin-enabled.lock"), () => logger("Build optimization enabled"), { cacheTimeoutMs: 1e3 * 10 });
54
- return isEnabled;
55
- },
56
- transform(code, id) {
57
- /**
58
- * Transform file as
59
- * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts
60
- * Into
61
- * .../HelloWorld.vue
62
- *
63
- * Prevention for virtual file
64
- */
65
- const filename = id.split("?", 1)[0];
66
- if (!filesList.includes(filename)) return null;
67
- const result = babel.transformSync(code, {
68
- filename,
69
- plugins: [[__intlayer_babel.intlayerOptimizeBabelPlugin, {
70
- optimize,
71
- dictionariesDir,
72
- dictionariesEntryPath,
73
- unmergedDictionariesEntryPath,
74
- unmergedDictionariesDir,
75
- dynamicDictionariesDir,
76
- dynamicDictionariesEntryPath,
77
- fetchDictionariesDir,
78
- importMode,
79
- filesList,
80
- replaceDictionaryEntry: true,
81
- liveSyncKeys
82
- }]],
83
- parserOpts: {
84
- sourceType: "module",
85
- allowImportExportEverywhere: true,
86
- plugins: [
87
- "typescript",
88
- "jsx",
89
- "decorators-legacy",
90
- "classProperties",
91
- "objectRestSpread",
92
- "asyncGenerators",
93
- "functionBind",
94
- "exportDefaultFrom",
95
- "exportNamespaceFrom",
96
- "dynamicImport",
97
- "nullishCoalescingOperator",
98
- "optionalChaining"
99
- ]
100
- }
101
- });
102
- if (result?.code) return {
103
- code: result.code,
104
- map: result.map
105
- };
106
- }
107
- }];
108
- } catch (error) {
109
- console.warn("Failed to transform with Babel plugin:", error);
110
- return [];
111
- }
112
- };
113
-
114
- //#endregion
115
- exports.intlayerPrune = intlayerPrune;
116
- //# sourceMappingURL=intlayerPrunePlugin.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"intlayerPrunePlugin.cjs","names":["fg","intlayerOptimizeBabelPlugin"],"sources":["../../src/intlayerPrunePlugin.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { isAbsolute, join } from 'node:path';\nimport { intlayerOptimizeBabelPlugin } from '@intlayer/babel';\nimport { runOnce } from '@intlayer/chokidar';\nimport { getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport type { PluginOption } from 'vite';\n\nexport const intlayerPrune = (\n intlayerConfig: IntlayerConfig\n): PluginOption[] => {\n try {\n const localeRequire = createRequire(import.meta.url);\n const babel = localeRequire('@babel/core');\n const logger = getAppLogger(intlayerConfig);\n\n const { importMode, traversePattern, optimize } = intlayerConfig.build;\n\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n unmergedDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n baseDir,\n } = intlayerConfig.content;\n\n const filesListPattern = fg\n .sync(traversePattern, {\n cwd: baseDir,\n })\n .map((file) => {\n if (isAbsolute(file)) {\n return file;\n }\n return join(baseDir, file);\n });\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries(intlayerConfig);\n const liveSyncKeys = Object.values(dictionaries)\n .filter((dictionary) => dictionary.live)\n .map((dictionary) => dictionary.key);\n\n return [\n {\n /**\n * On vue, we pre-insert the 'await' to the useIntlayer call\n * It will trigger the transformation of the async call by the vue compiler\n *\n * Then the second plugin will make the second transformation to replace the useIntlayer call by the useDictionaryDynamic call\n */\n name: 'vite-intlayer-simple-transform',\n enforce: 'pre', // Run before Vue so Vue sees the 'await'\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled =\n (optimize === undefined && isBuild) || optimize === true;\n const isAsync = importMode === 'dynamic' || importMode === 'live';\n\n return isEnabled && isAsync;\n },\n\n transform(code, id) {\n // 1. Only process .vue files\n // The await injection is only needed for Vue to trigger async component compilation\n if (!id.endsWith('.vue')) return null;\n\n // 2. Check if the file actually uses the composable to avoid unnecessary work\n if (!code.includes('useIntlayer')) return null;\n\n // B. Add 'await' to the function call\n // Matches: useIntlayer(args) -> await useIntlayer(args)\n // Note: Since we aliased the import above, 'useIntlayer' now refers to 'useDictionaryAsync'\n const transformedCode = code.replace(\n /(\\s+|=\\s*)useIntlayer\\s*\\(/g,\n '$1await useIntlayer('\n );\n\n return {\n code: transformedCode,\n map: null, // Simple string replace doesn't strictly need a sourcemap for this case\n };\n },\n },\n {\n name: 'vite-intlayer-babel-transform',\n enforce: 'post', // Run after other transformations as vue\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled =\n (optimize === undefined && isBuild) || optimize === true;\n\n if (isEnabled) {\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-prune-plugin-enabled.lock'\n ),\n () => logger('Build optimization enabled'),\n {\n cacheTimeoutMs: 1000 * 10, // 10 seconds\n }\n );\n }\n\n return isEnabled;\n },\n transform(code, id) {\n /**\n * Transform file as\n * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts\n * Into\n * .../HelloWorld.vue\n *\n * Prevention for virtual file\n */\n const filename = id.split('?', 1)[0];\n\n if (!filesList.includes(filename)) return null;\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerOptimizeBabelPlugin,\n {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n liveSyncKeys,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n },\n },\n ];\n } catch (error) {\n console.warn('Failed to transform with Babel plugin:', error);\n\n return [];\n }\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,iBACX,mBACmB;AACnB,KAAI;EAEF,MAAM,qFAD8C,CACxB,cAAc;EAC1C,MAAM,6CAAsB,eAAe;EAE3C,MAAM,EAAE,YAAY,iBAAiB,aAAa,eAAe;EAEjE,MAAM,EACJ,iBACA,wBACA,yBACA,sBACA,SACA,YACE,eAAe;EAEnB,MAAM,mBAAmBA,kBACtB,KAAK,iBAAiB,EACrB,KAAK,SACN,CAAC,CACD,KAAK,SAAS;AACb,iCAAe,KAAK,CAClB,QAAO;AAET,8BAAY,SAAS,KAAK;IAC1B;EAEJ,MAAM,4CAA6B,SAAS,mBAAmB;EAC/D,MAAM,oDACJ,SACA,4BACD;EACD,MAAM,mDACJ,SACA,2BACD;EAED,MAAM,YAAY;GAChB,GAAG;GACH;GACA;GACD;EAED,MAAM,kEAA+B,eAAe;EACpD,MAAM,eAAe,OAAO,OAAO,aAAa,CAC7C,QAAQ,eAAe,WAAW,KAAK,CACvC,KAAK,eAAe,WAAW,IAAI;AAEtC,SAAO,CACL;GAOE,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;AAKhC,YAHG,aAAa,UAAa,WAAY,aAAa,UACtC,eAAe,aAAa,eAAe;;GAK7D,UAAU,MAAM,IAAI;AAGlB,QAAI,CAAC,GAAG,SAAS,OAAO,CAAE,QAAO;AAGjC,QAAI,CAAC,KAAK,SAAS,cAAc,CAAE,QAAO;AAU1C,WAAO;KACL,MANsB,KAAK,QAC3B,+BACA,uBACD;KAIC,KAAK;KACN;;GAEJ,EACD;GACE,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;IAChC,MAAM,YACH,aAAa,UAAa,WAAY,aAAa;AAEtD,QAAI,UACF,sDAEI,SACA,aACA,SACA,qCACD,QACK,OAAO,6BAA6B,EAC1C,EACE,gBAAgB,MAAO,IACxB,CACF;AAGH,WAAO;;GAET,UAAU,MAAM,IAAI;;;;;;;;;IASlB,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,CAAC;AAElC,QAAI,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;IAE1C,MAAM,SAAS,MAAM,cAAc,MAAM;KACvC;KACA,SAAS,CACP,CACEC,8CACA;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,wBAAwB;MACxB;MACD,CACF,CACF;KACD,YAAY;MACV,YAAY;MACZ,6BAA6B;MAC7B,SAAS;OACP;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF,CAAC;AAEF,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;;GAGN,CACF;UACM,OAAO;AACd,UAAQ,KAAK,0CAA0C,MAAM;AAE7D,SAAO,EAAE"}