@zohodesk/client_build_tool 0.0.11-exp.26.0 → 0.0.11-exp.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,15 +15,34 @@ var _propertiesUtils = require("../I18nSplitPlugin/utils/propertiesUtils");
15
15
 
16
16
  var _I18nGroupRuntimeModule = require("./I18nGroupRuntimeModule");
17
17
 
18
- var _i18nDataLoader = require("./utils/i18nDataLoader");
18
+ var _i18nDataLoader = require("./utils/i18nDataLoader.js");
19
19
 
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
21
 
22
22
  const {
23
23
  RawSource
24
24
  } = _webpack.sources;
25
+ const assetStoreKey = Symbol.for('I18nNumericIndexPluginAssets');
25
26
  const pluginName = 'I18nNumericIndexPlugin';
26
27
 
28
+ function buildChunkMappingFromGroups(customGroups) {
29
+ if (!customGroups) {
30
+ return {};
31
+ }
32
+
33
+ const mapping = {};
34
+ Object.entries(customGroups).forEach(([groupName, config]) => {
35
+ if (config && Array.isArray(config.chunks)) {
36
+ config.chunks.forEach(chunkName => {
37
+ if (chunkName && typeof chunkName === 'string') {
38
+ mapping[chunkName] = groupName;
39
+ }
40
+ });
41
+ }
42
+ });
43
+ return mapping;
44
+ }
45
+
27
46
  class I18nNumericIndexPlugin {
28
47
  constructor(options) {
29
48
  this.options = { ...options,
@@ -33,40 +52,45 @@ class I18nNumericIndexPlugin {
33
52
  generateManifest: options.generateManifest || false,
34
53
  outputFolder: options.outputFolder || 'i18n-chunk',
35
54
  manifestPath: options.manifestPath || null,
36
- emitFiles: options.emitFiles !== undefined ? options.emitFiles : true
55
+ emitFiles: options.emitFiles !== undefined ? options.emitFiles : true,
56
+ chunkToGroupMapping: options.chunkToGroupMapping || {}
37
57
  };
38
58
  this.numericMap = {};
39
59
  this.customGroups = {};
40
60
  this.manifest = {};
61
+ this.groupAssetUrls = {};
62
+ this.preparedAssets = [];
63
+ this.assetsPrepared = false;
64
+ this.assetsEmitted = false;
65
+ this.groupChunkMapping = buildChunkMappingFromGroups(this.options.customGroups);
41
66
  }
42
67
 
43
68
  apply(compiler) {
44
- // Detect webpackI18nGroup comments in code
69
+ // Build-time validation for critical file paths
70
+ this.validateCriticalFilePaths(compiler); // Detect webpackI18nGroup comments in code
71
+
45
72
  this.detectI18nGroupComments(compiler);
46
73
  compiler.hooks.thisCompilation.tap(pluginName, compilation => {
47
- // Add runtime module for group-based loading
48
- console.log('[I18nNumericIndexPlugin] customGroups:', this.options.customGroups);
74
+ this.groupAssetUrls = {};
75
+ this.detectedGroups = {};
76
+ this.preparedAssets = [];
77
+ this.assetsPrepared = false;
78
+ this.assetsEmitted = false; // Add runtime module for group-based loading
49
79
 
50
80
  if (this.options.customGroups) {
51
81
  compilation.hooks.additionalTreeRuntimeRequirements.tap(pluginName, (chunk, set) => {
52
82
  // Only add to the main/entry chunk to avoid duplication
53
83
  if (chunk.name === 'main' || chunk.hasRuntime()) {
54
- const chunkMapping = this.getChunkIdToGroupMapping(compilation); // Only log if we have actual mappings or it's the first time
55
-
56
- const hasMapping = Object.keys(chunkMapping).length > 0;
57
-
58
- if (hasMapping || !this._hasLoggedRuntime) {
59
- console.log('[I18nNumericIndexPlugin] Adding runtime module to chunk:', chunk.name);
60
- console.log('[I18nNumericIndexPlugin] Chunk mapping for runtime:', chunkMapping);
61
- this._hasLoggedRuntime = true;
62
- }
63
-
84
+ this.ensureAssetsPrepared(compilation);
85
+ const chunkMapping = this.getChunkIdToGroupMapping(compilation);
64
86
  compilation.addRuntimeModule(chunk, new _I18nGroupRuntimeModule.I18nGroupRuntimeModule({
65
87
  customGroups: this.options.customGroups,
66
88
  chunkIdToGroupMapping: chunkMapping,
67
89
  localeVarName: this.options.localeVarName,
68
90
  jsonpFunc: this.options.jsonpFunc,
69
- i18nPublicPathVar: this.options.i18nPublicPathVar
91
+ i18nPublicPathVar: this.options.i18nPublicPathVar,
92
+ groupAssetUrls: this.groupAssetUrls,
93
+ includeContentHash: this.options.includeContentHash
70
94
  }));
71
95
  }
72
96
  });
@@ -76,49 +100,96 @@ class I18nNumericIndexPlugin {
76
100
  name: pluginName,
77
101
  stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
78
102
  }, () => {
79
- this.processI18nFiles(compilation);
103
+ this.ensureAssetsPrepared(compilation);
104
+ this.emitPreparedAssets(compilation);
80
105
  });
81
106
  });
82
107
  }
83
108
 
109
+ validateCriticalFilePaths(compiler) {
110
+ const {
111
+ jsResourcePath,
112
+ propertiesFolderPath,
113
+ numericMapPath
114
+ } = this.options;
115
+ const missingPaths = [];
116
+ const resolvedPaths = []; // Check jsResourcePath (must exist)
117
+
118
+ if (jsResourcePath) {
119
+ const resolvedJsPath = _path.default.resolve(compiler.context, jsResourcePath);
120
+
121
+ resolvedPaths.push(`jsResourcePath: ${resolvedJsPath}`);
122
+
123
+ if (!_fs.default.existsSync(resolvedJsPath)) {
124
+ missingPaths.push(`jsResourcePath: ${resolvedJsPath}`);
125
+ }
126
+ } else {
127
+ missingPaths.push('jsResourcePath: [not configured]');
128
+ } // Check propertiesFolderPath (must exist)
129
+
130
+
131
+ if (propertiesFolderPath) {
132
+ const resolvedPropsPath = _path.default.resolve(compiler.context, propertiesFolderPath);
133
+
134
+ resolvedPaths.push(`propertiesFolderPath: ${resolvedPropsPath}`);
135
+
136
+ if (!_fs.default.existsSync(resolvedPropsPath)) {
137
+ missingPaths.push(`propertiesFolderPath: ${resolvedPropsPath}`);
138
+ }
139
+ } else {
140
+ missingPaths.push('propertiesFolderPath: [not configured]');
141
+ } // Check numericMapPath (must exist)
142
+
143
+
144
+ if (numericMapPath) {
145
+ const resolvedMapPath = _path.default.resolve(compiler.context, numericMapPath);
146
+
147
+ resolvedPaths.push(`numericMapPath: ${resolvedMapPath}`);
148
+
149
+ if (!_fs.default.existsSync(resolvedMapPath)) {
150
+ missingPaths.push(`numericMapPath: ${resolvedMapPath}`);
151
+ }
152
+ } else {
153
+ missingPaths.push('numericMapPath: [not configured]');
154
+ } // If any critical files are missing, fail the build immediately
155
+
156
+
157
+ if (missingPaths.length > 0) {
158
+ const errorMessage = ['', '🚨 I18N BUILD FAILURE: Critical i18n files are missing!', '', 'The following required files could not be found:', ...missingPaths.map(path => ` ❌ ${path}`), '', 'These files are essential for i18n functionality. Please ensure they exist before building.', '', 'Resolved paths checked:', ...resolvedPaths.map(path => ` 📁 ${path}`), ''].join('\n');
159
+ throw new Error(errorMessage);
160
+ } // Log successful validation in development mode
161
+
162
+
163
+ if (compiler.options.mode === 'development') {
164
+ console.log('✅ I18n critical file validation passed:');
165
+ resolvedPaths.forEach(path => console.log(` 📁 ${path}`));
166
+ }
167
+ }
168
+
84
169
  detectI18nGroupComments(compiler) {
85
- console.log('[I18nNumericIndexPlugin] Setting up i18n group comment detection');
86
170
  compiler.hooks.normalModuleFactory.tap(pluginName, factory => {
87
171
  factory.hooks.parser.for('javascript/auto').tap(pluginName, parser => {
88
172
  parser.hooks.importCall.tap(pluginName, expr => {
89
- // Only log if comments exist to reduce noise
90
173
  const comments = expr.leadingComments || [];
91
174
 
92
175
  if (comments.length > 0) {
93
- console.log('[I18nNumericIndexPlugin] Import call with comments detected');
94
- console.log('[I18nNumericIndexPlugin] Leading comments count:', comments.length);
95
- comments.forEach((comment, index) => {
96
- console.log(`[I18nNumericIndexPlugin] Comment ${index}:`, comment.value);
97
-
176
+ comments.forEach(comment => {
98
177
  if (comment.value && comment.value.includes('webpackI18nGroup')) {
99
- console.log('[I18nNumericIndexPlugin] Found webpackI18nGroup comment:', comment.value);
100
178
  const match = comment.value.match(/webpackI18nGroup:\s*["']([^"']+)["']/);
101
179
 
102
180
  if (match) {
103
181
  const groupName = match[1];
104
- console.log('[I18nNumericIndexPlugin] Extracted group name:', groupName); // Store this information for later use
105
182
 
106
183
  if (!this.detectedGroups) {
107
184
  this.detectedGroups = {};
108
- } // Extract chunk name from webpackChunkName comment
109
-
185
+ }
110
186
 
111
187
  const chunkNameMatch = comment.value.match(/webpackChunkName:\s*["']([^"']+)["']/);
112
188
 
113
189
  if (chunkNameMatch) {
114
190
  const chunkName = chunkNameMatch[1];
115
- console.log('[I18nNumericIndexPlugin] Mapping chunk:', chunkName, '→', groupName);
116
191
  this.detectedGroups[chunkName] = groupName;
117
- } else {
118
- console.log('[I18nNumericIndexPlugin] No webpackChunkName found in comment');
119
192
  }
120
- } else {
121
- console.log('[I18nNumericIndexPlugin] webpackI18nGroup pattern did not match');
122
193
  }
123
194
  }
124
195
  });
@@ -129,53 +200,33 @@ class I18nNumericIndexPlugin {
129
200
  }
130
201
 
131
202
  getChunkIdToGroupMapping(compilation) {
132
- const chunkIdToGroup = {}; // Hardcoded chunk name to group mapping based on our setupAsync.js
133
-
134
- const hardcodedMappings = {
135
- 'SetupHome': 'setup',
136
- 'preferencePopup': 'setup',
137
- 'auditloglist': 'setup'
138
- };
139
- let foundAnyMapping = false;
140
- let hasRelevantChunks = false; // Process chunks to get their actual IDs and map to groups
203
+ const chunkIdToGroup = {};
204
+ const configuredMappings = { ...this.groupChunkMapping,
205
+ ...(this.options.chunkToGroupMapping || {})
206
+ }; // Process chunks to get their actual IDs and map to groups
141
207
 
142
208
  for (const chunk of compilation.chunks) {
143
- const chunkName = chunk.name; // Check if this chunk is relevant to setup
144
-
145
- if (chunkName && (chunkName.toLowerCase().includes('setup') || chunkName.toLowerCase().includes('preference') || chunkName.toLowerCase().includes('audit'))) {
146
- hasRelevantChunks = true;
147
- } // First try detected groups, then fallback to hardcoded mappings
148
-
209
+ const chunkName = chunk.name; // First try detected groups, then fall back to configured mappings
149
210
 
150
211
  let groupName = null;
151
212
 
152
213
  if (this.detectedGroups && this.detectedGroups[chunkName]) {
153
214
  groupName = this.detectedGroups[chunkName];
154
- console.log(`[I18nNumericIndexPlugin] Found detected mapping: ${chunkName} ${groupName} (ID: ${chunk.id})`);
155
- foundAnyMapping = true;
156
- } else if (hardcodedMappings[chunkName]) {
157
- groupName = hardcodedMappings[chunkName];
158
- console.log(`[I18nNumericIndexPlugin] Found hardcoded mapping: ${chunkName} → ${groupName} (ID: ${chunk.id})`);
159
- foundAnyMapping = true;
215
+ } else if (configuredMappings[chunkName]) {
216
+ groupName = configuredMappings[chunkName];
160
217
  }
161
218
 
162
219
  if (groupName) {
163
220
  chunkIdToGroup[chunk.id] = groupName;
164
221
  }
165
- } // Only log summary if we found mappings or relevant chunks
166
-
167
-
168
- if (foundAnyMapping || hasRelevantChunks || compilation.chunks.size > 0) {
169
- console.log('[I18nNumericIndexPlugin] Building chunk ID to group mapping');
170
- console.log('[I18nNumericIndexPlugin] Detected groups:', this.detectedGroups);
171
- console.log('[I18nNumericIndexPlugin] Total chunks in compilation:', compilation.chunks.size);
172
- console.log('[I18nNumericIndexPlugin] Final chunk ID to group mapping:', chunkIdToGroup);
173
222
  }
174
223
 
175
224
  return chunkIdToGroup;
176
225
  }
177
226
 
178
227
  processI18nFiles(compilation) {
228
+ this.preparedAssets = [];
229
+ this.groupAssetUrls = {};
179
230
  const {
180
231
  jsResourcePath,
181
232
  propertiesFolderPath,
@@ -188,14 +239,17 @@ class I18nNumericIndexPlugin {
188
239
 
189
240
  if (!jsResourcePath || !propertiesFolderPath) {
190
241
  return;
191
- } // Load existing numeric map if available
242
+ } // Reset build-scoped caches so incremental builds don't carry stale data
243
+
192
244
 
245
+ this.numericMap = {};
246
+ this.manifest = {};
247
+ this.customGroups = {}; // Load existing numeric map if available
193
248
 
194
249
  if (numericMapPath) {
195
250
  const mapData = (0, _i18nDataLoader.loadNumericMap)(numericMapPath, compilation);
196
251
 
197
252
  if (mapData && mapData.sortedKeys) {
198
- // Initialize numericMap from existing data
199
253
  mapData.sortedKeys.forEach((key, id) => {
200
254
  if (key) {
201
255
  this.numericMap[key] = id;
@@ -221,15 +275,9 @@ class I18nNumericIndexPlugin {
221
275
 
222
276
  Object.keys(allI18nObject).forEach(loc => {
223
277
  allI18nObject[loc] = this.normalizeObjectValues(allI18nObject[loc]);
224
- }); // For en_US, use only JSResources (don't merge with ApplicationResources_en_US)
225
-
226
- if (allI18nObject['en_US']) {
227
- allI18nObject['en_US'] = jsResourceKeys;
228
- } else {
229
- // If en_US doesn't exist in the folder, create it from JSResources
230
- allI18nObject['en_US'] = jsResourceKeys;
231
- } // If requested, restrict all locales to base (English) keys only
278
+ }); // For en_US, use only JSResources
232
279
 
280
+ allI18nObject['en_US'] = jsResourceKeys; // If requested, restrict all locales to base (English) keys only
233
281
 
234
282
  if (this.options.restrictToBaseKeys) {
235
283
  const baseKeys = Object.keys(jsResourceKeys);
@@ -260,8 +308,11 @@ class I18nNumericIndexPlugin {
260
308
  Object.keys(localeData).forEach(key => {
261
309
  const value = localeData[key]; // Simple logic: if has numeric ID use it, otherwise it's dynamic
262
310
 
263
- if (this.numericMap[key]) {
264
- const numericKey = String(this.numericMap[key]); // Check if belongs to a custom group
311
+ const numericId = this.numericMap[key];
312
+ const hasNumericId = numericId !== undefined && numericId !== null;
313
+
314
+ if (hasNumericId) {
315
+ const numericKey = String(numericId); // Check if belongs to a custom group
265
316
 
266
317
  const belongsToGroup = this.getKeyGroup(key);
267
318
 
@@ -271,31 +322,29 @@ class I18nNumericIndexPlugin {
271
322
  numericData[numericKey] = value;
272
323
  }
273
324
  } else {
274
- // No numeric ID = dynamic key (regardless of placeholders)
325
+ // No numeric ID = dynamic key
275
326
  dynamicData[key] = value;
276
327
  }
277
328
  }); // Handle single-file mode or separate files
278
329
 
279
330
  if (this.options.singleFile) {
280
- // Combine numeric and dynamic data into a single file
281
331
  const combinedData = { ...numericData,
282
332
  ...dynamicData
283
333
  };
284
334
 
285
335
  if (Object.keys(combinedData).length > 0) {
286
- // Use singleFileTemplate for combined file - no fileType suffix needed
287
336
  const singleFileTemplate = this.options.singleFileTemplate || '[locale].js';
288
- this.emitChunk(compilation, singleFileTemplate, locale, combinedData, jsonpFunc, null, null);
337
+ this.prepareChunkAsset(compilation, singleFileTemplate, locale, combinedData, jsonpFunc, null, null);
289
338
  }
290
339
  } else {
291
340
  // Emit numeric chunk
292
341
  if (Object.keys(numericData).length > 0) {
293
- this.emitChunk(compilation, numericFilenameTemplate, locale, numericData, jsonpFunc, null, 'numeric');
342
+ this.prepareChunkAsset(compilation, numericFilenameTemplate, locale, numericData, jsonpFunc, null, 'numeric');
294
343
  } // Emit dynamic chunk
295
344
 
296
345
 
297
346
  if (Object.keys(dynamicData).length > 0) {
298
- this.emitChunk(compilation, dynamicFilenameTemplate, locale, dynamicData, jsonpFunc, null, 'dynamic');
347
+ this.prepareChunkAsset(compilation, dynamicFilenameTemplate, locale, dynamicData, jsonpFunc, null, 'dynamic');
299
348
  }
300
349
  } // Emit custom group chunks (always separate)
301
350
 
@@ -305,7 +354,7 @@ class I18nNumericIndexPlugin {
305
354
 
306
355
  if (groupConfig && Object.keys(data).length > 0) {
307
356
  const groupTemplate = groupConfig.filenameTemplate || `[locale]/${groupName}.i18n.js`;
308
- this.emitChunk(compilation, groupTemplate, locale, data, jsonpFunc, groupName, `group-${groupName}`);
357
+ this.prepareChunkAsset(compilation, groupTemplate, locale, data, jsonpFunc, groupName, `group-${groupName}`);
309
358
  }
310
359
  });
311
360
  }); // Generate manifest file if enabled
@@ -314,9 +363,34 @@ class I18nNumericIndexPlugin {
314
363
  const manifestPath = this.options.manifestPath || _path.default.join(this.options.outputFolder, 'manifest.json');
315
364
 
316
365
  const manifestContent = JSON.stringify(this.manifest, null, 2);
317
- compilation.emitAsset(manifestPath, new RawSource(manifestContent));
318
- } // Don't save numeric map - it should only be generated by the external script
366
+ this.preparedAssets.push({
367
+ outputPath: manifestPath,
368
+ source: new RawSource(manifestContent),
369
+ shouldEmit: true
370
+ });
371
+ }
372
+ }
373
+
374
+ ensureAssetsPrepared(compilation) {
375
+ if (this.assetsPrepared) {
376
+ return;
377
+ }
378
+
379
+ this.processI18nFiles(compilation);
380
+ this.assetsPrepared = true;
381
+ }
382
+
383
+ emitPreparedAssets(compilation) {
384
+ if (this.assetsEmitted) {
385
+ return;
386
+ }
319
387
 
388
+ this.preparedAssets.forEach(asset => {
389
+ if (asset.shouldEmit !== false) {
390
+ compilation.emitAsset(asset.outputPath, asset.source);
391
+ }
392
+ });
393
+ this.assetsEmitted = true;
320
394
  }
321
395
 
322
396
  parseCustomGroups(jsResourcePath, customGroups) {
@@ -357,16 +431,6 @@ class I18nNumericIndexPlugin {
357
431
  return null;
358
432
  }
359
433
 
360
- isDynamicKey(value) {
361
- // Check if value contains placeholders like {0}, {1}, etc.
362
- return /\{\d+\}/.test(value);
363
- }
364
-
365
- getNumericKey(key) {
366
- // Return numeric ID if it exists, null otherwise
367
- return this.numericMap[key] ? String(this.numericMap[key]) : null;
368
- }
369
-
370
434
  generateContentHash(content, compilation) {
371
435
  const {
372
436
  hashFunction,
@@ -382,31 +446,22 @@ class I18nNumericIndexPlugin {
382
446
 
383
447
  constructFilePath(template, locale) {
384
448
  const {
385
- outputFolder,
386
- singleFile
387
- } = this.options; // Replace locale placeholder
388
-
389
- let filePath = template.replace(/\[locale\]/g, locale); // If template already contains outputFolder or starts with a path separator, use as-is
449
+ outputFolder
450
+ } = this.options;
451
+ const filePath = template.replace(/\[locale\]/g, locale); // If template already contains outputFolder or starts with path separator, use as-is
390
452
 
391
453
  if (filePath.includes(outputFolder) || filePath.startsWith('/')) {
392
- return filePath.replace(/\\/g, '/');
393
- } // For single-file mode with a simple template like '[locale].js',
394
- // put it directly in outputFolder without subdirectories
395
-
396
-
397
- if (singleFile && !filePath.includes('/')) {
398
- return _path.default.join(outputFolder, filePath).replace(/\\/g, '/');
399
- } // For other cases, if template contains subdirectories, preserve them
454
+ return filePath;
455
+ } // Otherwise, join with outputFolder
400
456
 
401
457
 
402
458
  return _path.default.join(outputFolder, filePath).replace(/\\/g, '/');
403
459
  }
404
460
 
405
- emitChunk(compilation, filenameTemplate, locale, data, jsonpFunc, groupName = null, fileType = null) {
461
+ prepareChunkAsset(compilation, filenameTemplate, locale, data, jsonpFunc, groupName = null, fileType = null) {
406
462
  if (!filenameTemplate || Object.keys(data).length === 0) {
407
463
  return null;
408
- } // Generate content regardless of emitFiles flag (needed for runtime)
409
-
464
+ }
410
465
 
411
466
  const content = this.generateChunkContent(data, jsonpFunc, groupName);
412
467
  let outputPath = this.constructFilePath(filenameTemplate, locale); // Handle [contenthash] placeholder in template
@@ -415,42 +470,59 @@ class I18nNumericIndexPlugin {
415
470
  const contentHash = this.generateContentHash(content, compilation);
416
471
  outputPath = outputPath.replace(/\[contenthash\]/g, contentHash);
417
472
  } else if (this.options.includeContentHash) {
418
- // Legacy: Add content hash before .js extension if includeContentHash is true
419
473
  const contentHash = this.generateContentHash(content, compilation);
420
474
  outputPath = outputPath.replace(/\.js$/, `.${contentHash}.js`);
421
475
  } // Track in manifest if enabled
422
476
 
423
477
 
424
478
  if (this.options.generateManifest) {
425
- // For single-file mode, use clean locale.js format
426
- let manifestKey;
427
-
428
- if (this.options.singleFile) {
429
- // Just use locale.js without path or type suffix
430
- manifestKey = `${locale}.js`;
431
- } else {
432
- // For multi-file mode, include the full path
433
- const cleanName = this.constructFilePath(filenameTemplate, locale);
434
- manifestKey = fileType ? cleanName.replace(/\.js$/, `.${fileType}.js`) : cleanName;
435
- }
436
-
479
+ const manifestKey = this.options.singleFile ? `${locale}.js` : outputPath;
437
480
  this.manifest[manifestKey] = _path.default.basename(outputPath);
438
- } // Only emit the file if emitFiles is true
481
+ }
439
482
 
483
+ const source = new RawSource(content);
484
+ const assetInfo = {
485
+ locale,
486
+ fileType,
487
+ outputPath,
488
+ filenameTemplate
489
+ };
490
+ this.registerEmittedAsset(compilation, assetInfo);
491
+ this.preparedAssets.push({
492
+ outputPath,
493
+ source,
494
+ shouldEmit: this.options.emitFiles,
495
+ info: assetInfo
496
+ });
497
+ return outputPath;
498
+ }
440
499
 
441
- if (this.options.emitFiles) {
442
- compilation.emitAsset(outputPath, new RawSource(content));
500
+ registerEmittedAsset(compilation, assetInfo) {
501
+ if (!Object.prototype.hasOwnProperty.call(compilation, assetStoreKey)) {
502
+ Object.defineProperty(compilation, assetStoreKey, {
503
+ configurable: true,
504
+ enumerable: false,
505
+ value: []
506
+ });
443
507
  }
444
508
 
445
- return outputPath;
509
+ compilation[assetStoreKey].push(assetInfo);
510
+
511
+ if (assetInfo.fileType && assetInfo.fileType.startsWith('group-')) {
512
+ const groupName = assetInfo.fileType.slice('group-'.length);
513
+
514
+ if (!this.groupAssetUrls[groupName]) {
515
+ this.groupAssetUrls[groupName] = {};
516
+ }
517
+
518
+ this.groupAssetUrls[groupName][assetInfo.locale] = assetInfo.outputPath;
519
+ }
446
520
  }
447
521
 
448
522
  generateChunkContent(data, jsonpFunc, groupName) {
449
- // Decode Unicode escapes to convert \uXXXX to actual characters
450
523
  const jsonString = (0, _propertiesUtils.decodeUnicodeEscapes)(JSON.stringify(data));
451
524
 
452
525
  if (groupName) {
453
- // Include group name for lazy loading identification
454
526
  return `${jsonpFunc}(${jsonString}, "${groupName}");`;
455
527
  }
456
528
 
@@ -1,21 +1,24 @@
1
1
  "use strict";
2
2
 
3
- const fs = require('fs');
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.loadAllLocaleFiles = loadAllLocaleFiles;
7
+ exports.loadI18nData = loadI18nData;
8
+ exports.loadNumericMap = loadNumericMap;
9
+ exports.loadPropertiesFile = loadPropertiesFile;
4
10
 
5
- const path = require('path');
11
+ var _fs = _interopRequireDefault(require("fs"));
6
12
 
7
- const {
8
- getPropertiesAsJSON
9
- } = require('../../I18nSplitPlugin/utils/propertiesUtils');
10
- /**
11
- * Load and parse a properties file
12
- */
13
+ var _path = _interopRequireDefault(require("path"));
13
14
 
15
+ var _propertiesUtils = require("../../I18nSplitPlugin/utils/propertiesUtils.js");
16
+
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
18
 
15
19
  function loadPropertiesFile(filePath, compilation, description) {
16
20
  try {
17
- const parsed = getPropertiesAsJSON(filePath);
18
- return parsed;
21
+ return (0, _propertiesUtils.getPropertiesAsJSON)(filePath);
19
22
  } catch (err) {
20
23
  if (compilation) {
21
24
  compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error loading ${description}: ${err.message}`));
@@ -24,30 +27,16 @@ function loadPropertiesFile(filePath, compilation, description) {
24
27
  return {};
25
28
  }
26
29
  }
27
- /**
28
- * Load numeric mapping from JSON file
29
- */
30
-
31
30
 
32
31
  function loadNumericMap(numericMapPath, compilation) {
33
32
  try {
34
- const fileContent = fs.readFileSync(numericMapPath, 'utf-8');
35
- const parsedData = JSON.parse(fileContent);
36
- let numericMap;
37
- let totalKeys; // Handle both wrapped and flat formats
38
-
39
- if (parsedData.originalKeyToNumericId) {
40
- // New format with metadata
41
- numericMap = parsedData.originalKeyToNumericId;
42
- totalKeys = parsedData.totalKeysInMap || Object.keys(numericMap).length;
43
- } else {
44
- // Flat format - use directly
45
- numericMap = parsedData;
46
- totalKeys = Object.keys(numericMap).length;
47
- } // Create sorted array for numeric ID lookups
33
+ const fileContent = _fs.default.readFileSync(numericMapPath, 'utf-8');
48
34
 
49
-
50
- const maxId = Math.max(...Object.values(numericMap));
35
+ const parsedData = JSON.parse(fileContent);
36
+ const numericMap = parsedData.originalKeyToNumericId || parsedData;
37
+ const totalKeys = parsedData.totalKeysInMap || Object.keys(numericMap).length;
38
+ const values = Object.values(numericMap);
39
+ const maxId = Math.max(...values.map(id => typeof id === 'number' ? id : Number(id)));
51
40
  const sortedKeys = new Array(maxId + 1);
52
41
  Object.entries(numericMap).forEach(([key, id]) => {
53
42
  sortedKeys[id] = key;
@@ -67,30 +56,26 @@ function loadNumericMap(numericMapPath, compilation) {
67
56
  };
68
57
  }
69
58
  }
70
- /**
71
- * Load all locale files from properties directory
72
- */
73
-
74
59
 
75
60
  function loadAllLocaleFiles(propertiesPath, compilation, jsResourceBase) {
76
- const allI18n = {};
77
- const locales = []; // Start with English base
78
-
79
- allI18n['en_US'] = jsResourceBase;
80
- locales.push('en_US');
61
+ const allI18n = {
62
+ en_US: jsResourceBase
63
+ };
64
+ const locales = ['en_US'];
81
65
 
82
66
  try {
83
- const files = fs.readdirSync(propertiesPath);
84
- files.forEach(file => {
85
- if (!file.endsWith('.properties')) return; // Match locale-specific property files
67
+ const files = _fs.default.readdirSync(propertiesPath);
86
68
 
69
+ files.forEach(file => {
70
+ if (!file.endsWith('.properties')) return;
87
71
  const match = file.match(/^ApplicationResources_([a-z]{2}_[A-Z]{2})\.properties$/);
88
72
 
89
73
  if (match) {
90
74
  const locale = match[1];
91
- const filePath = path.join(propertiesPath, file);
92
- const localeData = loadPropertiesFile(filePath, compilation, `locale ${locale}`); // Merge with base resources
93
75
 
76
+ const filePath = _path.default.join(propertiesPath, file);
77
+
78
+ const localeData = loadPropertiesFile(filePath, compilation, `locale ${locale}`);
94
79
  allI18n[locale] = { ...jsResourceBase,
95
80
  ...localeData
96
81
  };
@@ -111,17 +96,13 @@ function loadAllLocaleFiles(propertiesPath, compilation, jsResourceBase) {
111
96
  locales
112
97
  };
113
98
  }
114
- /**
115
- * Main loader function for i18n data
116
- */
117
-
118
99
 
119
100
  function loadI18nData(options, compilation) {
120
- const jsResourcePath = path.resolve(compilation.compiler.context, options.jsResourcePath);
121
- const propertiesPath = path.resolve(compilation.compiler.context, options.propertiesFolderPath); // Load base JS resources
101
+ const jsResourcePath = _path.default.resolve(compilation.compiler.context, options.jsResourcePath);
122
102
 
123
- const jsResourceBase = loadPropertiesFile(jsResourcePath, compilation, 'JS resources'); // Load all locale files
103
+ const propertiesPath = _path.default.resolve(compilation.compiler.context, options.propertiesFolderPath);
124
104
 
105
+ const jsResourceBase = loadPropertiesFile(jsResourcePath, compilation, 'JS resources');
125
106
  const {
126
107
  allI18n,
127
108
  locales
@@ -131,11 +112,4 @@ function loadI18nData(options, compilation) {
131
112
  allI18n,
132
113
  locales
133
114
  };
134
- }
135
-
136
- module.exports = {
137
- loadPropertiesFile,
138
- loadNumericMap,
139
- loadAllLocaleFiles,
140
- loadI18nData
141
- };
115
+ }