wuchale 0.23.4 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/adapter-utils/mixed-visitor.d.ts +21 -14
  2. package/dist/adapter-utils/mixed-visitor.js +110 -101
  3. package/dist/adapter-vanilla/index.js +8 -6
  4. package/dist/adapter-vanilla/inertvisitors.d.ts +31 -0
  5. package/dist/adapter-vanilla/inertvisitors.js +86 -0
  6. package/dist/adapter-vanilla/transformer.d.ts +67 -95
  7. package/dist/adapter-vanilla/transformer.js +288 -241
  8. package/dist/adapters.d.ts +16 -12
  9. package/dist/adapters.js +33 -13
  10. package/dist/ai/gemini.js +1 -1
  11. package/dist/ai/index.js +3 -1
  12. package/dist/bundlers/vite.d.ts +1 -1
  13. package/dist/bundlers/vite.js +3 -3
  14. package/dist/cli/check.js +1 -1
  15. package/dist/cli/index.js +12 -5
  16. package/dist/cli/status.js +1 -1
  17. package/dist/config.d.ts +2 -1
  18. package/dist/config.js +2 -2
  19. package/dist/handler/files.d.ts +11 -13
  20. package/dist/handler/files.js +37 -44
  21. package/dist/handler/index.d.ts +7 -4
  22. package/dist/handler/index.js +85 -62
  23. package/dist/handler/state.d.ts +10 -11
  24. package/dist/handler/state.js +40 -28
  25. package/dist/handler/url.d.ts +10 -13
  26. package/dist/handler/url.js +51 -80
  27. package/dist/hub.d.ts +1 -1
  28. package/dist/hub.js +16 -14
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +2 -2
  31. package/dist/load-utils/index.d.ts +6 -8
  32. package/dist/load-utils/index.js +11 -11
  33. package/dist/load-utils/pure.d.ts +2 -2
  34. package/dist/load-utils/server.d.ts +3 -3
  35. package/dist/load-utils/server.js +4 -7
  36. package/dist/pofile.d.ts +5 -5
  37. package/dist/pofile.js +23 -35
  38. package/dist/storage.d.ts +6 -3
  39. package/dist/storage.js +98 -0
  40. package/dist/url.d.ts +12 -10
  41. package/dist/url.js +206 -31
  42. package/package.json +4 -5
  43. package/src/adapter-vanilla/loaders/bundle.js +1 -1
  44. package/src/adapter-vanilla/loaders/server.js +3 -3
  45. package/src/adapter-vanilla/loaders/vite.js +2 -2
  46. package/src/adapter-vanilla/loaders/vite.ssr.js +3 -3
@@ -1,3 +1,4 @@
1
+ import { writeFile } from 'node:fs/promises';
1
2
  import { resolve } from 'node:path';
2
3
  import { isDeepStrictEqual } from 'node:util';
3
4
  import pm, {} from 'picomatch';
@@ -6,7 +7,7 @@ import { getKey } from '../adapters.js';
6
7
  import AIQueue from '../ai/index.js';
7
8
  import { compileTranslation } from '../compile.js';
8
9
  import { itemIsUrl, newItem } from '../storage.js';
9
- import { Files, globConfToArgs, normalizeSep, objKeyLocale, } from './files.js';
10
+ import { defaultLoadID, Files, globConfToArgs, normalizeSep, objKeyLocale, } from './files.js';
10
11
  import { State } from './state.js';
11
12
  import { URLHandler } from './url.js';
12
13
  const loaderImportGetRuntime = 'getRuntime';
@@ -15,19 +16,45 @@ const getFuncPlainDefault = '_w_load_';
15
16
  const urlLocalizeUdfName = 'localize';
16
17
  const getFuncReactiveDefault = `${getFuncPlainDefault}rx_`;
17
18
  const bundleCatalogsVarName = '_w_catalogs_';
18
- /** return two arrays: the corresponding one, and the one to import from in the case of shared catalogs */
19
- export function getLoadIDs(adapter, key, ownerKey, granularStates, sourceLocale) {
20
- const loadIDs = [];
21
- if (!adapter.granularLoad) {
22
- return [[key], [ownerKey]];
19
+ export function getLoadIDs(adapter, granularStates, sourceLocale) {
20
+ if (!adapter.loading.granular) {
21
+ return [defaultLoadID];
23
22
  }
23
+ const loadIDs = [];
24
24
  for (const state of granularStates) {
25
25
  // only the ones with ready messages
26
26
  if (state.compiled.get(sourceLocale).items.length) {
27
27
  loadIDs.push(state.id);
28
28
  }
29
29
  }
30
- return [loadIDs, loadIDs];
30
+ return loadIDs;
31
+ }
32
+ export const newItemsAllowed = (mode, devMode) => mode !== 'dev' || devMode === 'add' || devMode === 'refs' || devMode === 'clean';
33
+ function getFallback(fbConf, loc, sourceLocale, locales, chain) {
34
+ let fallback = fbConf[loc];
35
+ if (!fallback) {
36
+ if (loc.includes('-')) {
37
+ fallback = new Intl.Locale(loc).language;
38
+ }
39
+ if (!fallback || !locales.includes(fallback)) {
40
+ chain.push(sourceLocale);
41
+ return;
42
+ }
43
+ }
44
+ chain.push(fallback);
45
+ getFallback(fbConf, fallback, sourceLocale, locales, chain);
46
+ }
47
+ export function getFallbackChains(fallbackConf, locales, sourceLocale) {
48
+ const chains = new Map([[sourceLocale, [sourceLocale]]]);
49
+ for (const loc of locales) {
50
+ if (loc === sourceLocale) {
51
+ continue;
52
+ }
53
+ const chain = [loc];
54
+ chains.set(loc, chain);
55
+ getFallback(fallbackConf, loc, sourceLocale, locales, chain);
56
+ }
57
+ return chains;
31
58
  }
32
59
  export class AdapterHandler {
33
60
  key;
@@ -41,15 +68,19 @@ export class AdapterHandler {
41
68
  url;
42
69
  aiQueue;
43
70
  onBeforeSave;
71
+ #fallbackChains;
72
+ #newKeys = new Set(); // keys added during dev
44
73
  constructor(opts) {
45
74
  this.#opts = opts;
46
75
  this.key = opts.key;
47
76
  this.adapter = opts.adapter;
48
77
  this.granularState = opts.granularState;
49
78
  this.sharedState = opts.sharedState;
50
- this.fileMatches = pm(...globConfToArgs(opts.adapter.files, opts.root, opts.config.localesDir, opts.adapter.outDir));
79
+ const [patterns, ignore] = globConfToArgs(opts.adapter.files, opts.config.localesDir);
80
+ this.fileMatches = pm(patterns, { ignore });
51
81
  this.sourceLocale = opts.sourceLocale;
52
82
  this.url = new URLHandler(opts.config.locales, this.sourceLocale, opts.adapter.url);
83
+ this.#fallbackChains = getFallbackChains(opts.config.fallback, opts.config.locales, this.sourceLocale);
53
84
  this.files = opts.files;
54
85
  if (opts.config.ai) {
55
86
  this.aiQueue = new AIQueue(opts.sourceLocale, opts.config.ai, opts.mode === 'cli' ? this.saveStorage : this.saveStorageCompile, opts.log);
@@ -65,16 +96,16 @@ export class AdapterHandler {
65
96
  fs,
66
97
  root,
67
98
  });
68
- const writeProxies = states => files.writeProxies(config.locales, ...getLoadIDs(adapter, key, sharedState.ownerKey, states, opts.sourceLocale));
69
- const granularState = new State(writeProxies, adapter.generateLoadID);
99
+ const writeProxies = groupPatts => files.writeProxies(config.locales, groupPatts);
100
+ const granularState = new State(writeProxies, adapter.loading.group);
70
101
  const handler = new AdapterHandler({ ...opts, granularState, files });
71
102
  await handler.loadStorage();
72
- if (await handler.url.initPatterns(key, sharedState.catalog, handler.aiQueue)) {
103
+ if (await handler.url.initPatterns(key, sharedState.catalog, handler.#fallbackChains, handler.aiQueue)) {
73
104
  await handler.saveStorage();
74
105
  }
75
106
  await handler.compile();
76
- await writeProxies(granularState.byID.values());
77
- await files.writeUrlFiles(handler.url.buildManifest(sharedState.catalog), config.locales[0]);
107
+ await writeProxies(granularState.groupPatterns);
108
+ await files.writeUrlFiles(handler.url.buildManifest(), config.locales[0]);
78
109
  return handler;
79
110
  };
80
111
  loadStorage = async () => {
@@ -84,7 +115,7 @@ export class AdapterHandler {
84
115
  };
85
116
  saveStorage = async () => {
86
117
  this.onBeforeSave?.();
87
- await this.sharedState.save();
118
+ await this.sharedState.save(this.#opts.mode === 'dev' && this.#opts.devMode === 'clean');
88
119
  };
89
120
  compile = async (hmrVersion = -1) => {
90
121
  // for proper fallback
@@ -116,10 +147,10 @@ export class AdapterHandler {
116
147
  return manifest;
117
148
  };
118
149
  #writeManifests = async () => {
119
- const promises = [this.files.writeManifest(this.#buildManifest(this.sharedState.indexTracker.indices), null)];
120
- if (this.adapter.granularLoad) {
150
+ const promises = [this.files.writeManifest(this.#buildManifest(this.sharedState.indexTracker.getAll()), null)];
151
+ if (this.adapter.loading.granular) {
121
152
  for (const state of this.granularState.byID.values()) {
122
- promises.push(this.files.writeManifest(this.#buildManifest(state.indexTracker.indices), state.id));
153
+ promises.push(this.files.writeManifest(this.#buildManifest(state.indexTracker.getAll()), state.id));
123
154
  }
124
155
  }
125
156
  await Promise.all(promises);
@@ -135,7 +166,7 @@ export class AdapterHandler {
135
166
  const promises = [
136
167
  this.files.writeCatalogModule(compiledData.items, compiledData.hasPlurals ? pluralRule : null, loc, hmrVersionMode, null),
137
168
  ];
138
- if (this.adapter.granularLoad) {
169
+ if (this.adapter.loading.granular) {
139
170
  for (const state of this.granularState.byID.values()) {
140
171
  compiledData = state.compiled?.get(loc) || {
141
172
  hasPlurals: false,
@@ -146,25 +177,12 @@ export class AdapterHandler {
146
177
  }
147
178
  await Promise.all(promises);
148
179
  };
149
- getCompiledFallback(index, loc) {
150
- for (let _ = 0; _ < 100; _++) {
151
- // just to be sure
152
- let fallbackLoc = this.#opts.config.fallback[loc];
153
- if (fallbackLoc == null) {
154
- if (loc.includes('-')) {
155
- fallbackLoc = new Intl.Locale(loc).language;
156
- }
157
- if (fallbackLoc == null || !this.#opts.config.locales.includes(fallbackLoc)) {
158
- fallbackLoc = this.sourceLocale;
159
- }
160
- }
161
- const catalog = this.sharedState.compiled.get(fallbackLoc).items;
162
- const compiled = catalog[index];
163
- if (compiled || fallbackLoc === this.sourceLocale) {
164
- // last try
180
+ getCompiledFallback(index, locale) {
181
+ for (const loc of this.#fallbackChains.get(locale) ?? [locale, this.sourceLocale]) {
182
+ const compiled = this.sharedState.compiled.get(loc).items[index];
183
+ if (compiled || loc === this.sourceLocale) {
165
184
  return compiled || '';
166
185
  }
167
- loc = fallbackLoc;
168
186
  }
169
187
  return '';
170
188
  }
@@ -207,16 +225,16 @@ export class AdapterHandler {
207
225
  else {
208
226
  let toCompile = transl[0];
209
227
  if (itemIsUrl(item)) {
210
- toCompile = this.url.matchToCompile(key, this.sharedState.catalog, loc);
228
+ toCompile = this.url.matchToCompile(key, loc);
211
229
  }
212
230
  compiled = compileTranslation(toCompile, fallback);
213
231
  }
214
232
  sharedCompiledLoc.items[index] = compiled;
215
- if (!this.adapter.granularLoad) {
233
+ if (!this.adapter.loading.granular) {
216
234
  continue;
217
235
  }
218
236
  for (const ref of item.references) {
219
- const state = await this.granularState.byFileCreate(ref.file, this.#opts.config.locales);
237
+ const state = await this.granularState.byFileCreate(ref.file, this.#opts.config.locales, newItemsAllowed(this.#opts.mode, this.#opts.devMode));
220
238
  const compiledLoc = state.compiled.get(loc);
221
239
  compiledLoc.hasPlurals = sharedCompiledLoc.hasPlurals;
222
240
  compiledLoc.items[state.indexTracker.get(key)] = compiled;
@@ -261,24 +279,20 @@ export class AdapterHandler {
261
279
  getRuntimeReactive += 'hmr_';
262
280
  head.push(this.#hmrUpdateFunc(getRuntimeVars.plain, getRuntimePlain), this.#hmrUpdateFunc(getRuntimeVars.reactive, getRuntimeReactive));
263
281
  }
264
- let loaderRelTo = filename;
265
- if (this.adapter.outDir) {
266
- loaderRelTo = resolve(`${this.adapter.outDir}/${filename}`);
267
- }
268
- const loaderPath = this.files.getImportLoaderPath(forServer, loaderRelTo);
282
+ const loaderPath = this.files.getImportLoaderPath(forServer, filename);
269
283
  const importsFuncs = [
270
284
  `${loaderImportGetRuntime} as ${getRuntimePlain}`,
271
285
  `${loaderImportGetRuntimeRx} as ${getRuntimeReactive}`,
272
286
  ];
273
287
  head = [`import {${importsFuncs.join(', ')}} from "${loaderPath}"`, ...head];
274
- if (!this.adapter.bundleLoad) {
288
+ if (!this.adapter.loading.direct) {
275
289
  return head.join('\n');
276
290
  }
277
291
  const imports = [];
278
292
  const objElms = [];
279
293
  for (const [i, loc] of this.#opts.config.locales.entries()) {
280
294
  const locKW = `_w_c_${i}_`;
281
- const importFrom = this.files.getImportPath(this.files.getCompiledFilePath(loc, loadID), loaderRelTo);
295
+ const importFrom = this.files.getImportPath(this.files.getCompiledFilePath(loc, loadID), filename);
282
296
  imports.push(`import * as ${locKW} from '${importFrom}'`);
283
297
  objElms.push(`${objKeyLocale(loc)}: ${locKW}`);
284
298
  }
@@ -286,15 +300,17 @@ export class AdapterHandler {
286
300
  };
287
301
  #prepareRuntimeExpr = (loadID) => {
288
302
  const importLoaderVars = this.#getRuntimeVars();
289
- if (this.adapter.bundleLoad) {
303
+ if (this.adapter.loading.direct) {
290
304
  return {
291
305
  plain: `${importLoaderVars.plain}(${bundleCatalogsVarName})`,
292
306
  reactive: `${importLoaderVars.reactive}(${bundleCatalogsVarName})`,
293
307
  };
294
308
  }
309
+ // default is always 0 unless loading.granular is true
310
+ const loadIDParam = loadID === 0 ? '' : loadID;
295
311
  return {
296
- plain: `${importLoaderVars.plain}('${loadID}')`,
297
- reactive: `${importLoaderVars.reactive}('${loadID}')`,
312
+ plain: `${importLoaderVars.plain}(${loadIDParam})`,
313
+ reactive: `${importLoaderVars.reactive}(${loadIDParam})`,
298
314
  };
299
315
  };
300
316
  popTrackedRefs = (filename) => {
@@ -367,6 +383,7 @@ export class AdapterHandler {
367
383
  let compileUpdated = false;
368
384
  const hmrKeys = [];
369
385
  const toTranslate = [];
386
+ const modifyExistingRefs = this.#opts.mode !== 'dev' || this.#opts.devMode === 'refs' || this.#opts.devMode === 'clean';
370
387
  for (const msgInfo of msgs) {
371
388
  let key = getKey(msgInfo.msgStr, msgInfo.context);
372
389
  hmrKeys.push(key);
@@ -377,16 +394,18 @@ export class AdapterHandler {
377
394
  err.id = filename;
378
395
  throw err;
379
396
  }
380
- key = this.url.patternKeys.get(matched); // ! because already checked at extraction
397
+ key = getKey([this.url.patterns[matched[0]]]);
381
398
  }
382
399
  let item = this.sharedState.catalog.get(key);
383
400
  if (!item) {
384
401
  item = newItem({ id: msgInfo.msgStr }, this.#opts.config.locales);
385
402
  this.sharedState.catalog.set(key, item);
403
+ this.#newKeys.add(key);
386
404
  storageUpdated = true;
387
405
  compileUpdated = true;
388
406
  }
389
- if (this.updateRef(item, key, filename, msgInfo, previousReferences)) {
407
+ const modifyRefs = modifyExistingRefs || (this.#opts.devMode === 'add' && this.#newKeys.has(key));
408
+ if (modifyRefs && this.updateRef(item, key, filename, msgInfo, previousReferences)) {
390
409
  storageUpdated = true;
391
410
  if (msgInfo.type === 'url') {
392
411
  compileUpdated = true;
@@ -416,16 +435,18 @@ export class AdapterHandler {
416
435
  this.aiQueue.add(toTranslate);
417
436
  await this.aiQueue.running;
418
437
  }
419
- const { cleaned, cleanedUrls } = this.cleanTrackedRefs(previousReferences);
420
- if (cleaned) {
421
- storageUpdated = true;
422
- }
423
- if (cleanedUrls) {
424
- compileUpdated = true;
438
+ if (modifyExistingRefs) {
439
+ const { cleaned, cleanedUrls } = this.cleanTrackedRefs(previousReferences);
440
+ if (cleaned) {
441
+ storageUpdated = true;
442
+ }
443
+ if (cleanedUrls) {
444
+ compileUpdated = true;
445
+ }
425
446
  }
447
+ // cli saves and compiles at the end
426
448
  if (storageUpdated && this.#opts.mode !== 'cli') {
427
- // cli saves and compiles at the end
428
- await this.saveStorage();
449
+ this.#opts.devMode && (await this.saveStorage());
429
450
  if (compileUpdated) {
430
451
  await this.compile();
431
452
  }
@@ -435,10 +456,10 @@ export class AdapterHandler {
435
456
  transform = async (content, filename, hmrVersion = -1, forServer = false) => {
436
457
  filename = normalizeSep(filename);
437
458
  let indexTracker = this.sharedState.indexTracker;
438
- let loadID = this.key;
459
+ let loadID = defaultLoadID;
439
460
  let compiled = this.sharedState.compiled;
440
- if (this.adapter.granularLoad) {
441
- const state = await this.granularState.byFileCreate(filename, this.#opts.config.locales);
461
+ if (this.adapter.loading.granular) {
462
+ const state = await this.granularState.byFileCreate(filename, this.#opts.config.locales, newItemsAllowed(this.#opts.mode, this.#opts.devMode));
442
463
  indexTracker = state.indexTracker;
443
464
  loadID = state.id;
444
465
  compiled = state.compiled;
@@ -481,7 +502,9 @@ export class AdapterHandler {
481
502
  if (msgs.length) {
482
503
  output = result.output(this.#prepareHeader(filename, loadID, hmrData, msgs.some(m => m.type === 'url'), forServer));
483
504
  }
484
- await this.files.writeTransformed(filename, output.code ?? content);
505
+ if (this.#opts.modifyInplace && output.code) {
506
+ await writeFile(filename, output.code);
507
+ }
485
508
  return [output, updated];
486
509
  };
487
510
  }
@@ -1,4 +1,4 @@
1
- import { IndexTracker } from '../adapters.js';
1
+ import { IndexTracker, type LoadGroupPatt } from '../adapters.js';
2
2
  import type { CompiledElement } from '../compile.js';
3
3
  import { type Catalog, type CatalogStorage, type PluralRules } from '../storage.js';
4
4
  export type Compiled = {
@@ -15,21 +15,20 @@ export declare class SharedState {
15
15
  storage: CatalogStorage;
16
16
  catalog: Catalog;
17
17
  pluralRules: PluralRules;
18
- constructor(storage: CatalogStorage, ownerKey: string, sourceLocale: string);
18
+ constructor(storage: CatalogStorage, ownerKey: string, sourceLocale: string, allowNewItems: boolean);
19
19
  load(locales: string[]): Promise<void>;
20
- save(): Promise<void>;
20
+ save(onlyReferenced: boolean): Promise<void>;
21
21
  }
22
22
  export type GranularState = {
23
- id: string;
23
+ id: number;
24
24
  compiled: CompiledCatalogs;
25
25
  indexTracker: IndexTracker;
26
26
  };
27
- export type WriteProxies = (states: Iterable<GranularState>) => Promise<void>;
27
+ export type WriteProxies = (groupPatterns: LoadGroupPatt[]) => Promise<void>;
28
28
  export declare class State {
29
- byFile: Map<string, GranularState>;
30
- byID: Map<string, GranularState>;
31
- writeProxies: WriteProxies;
32
- generateLoadID: (filename: string) => string;
33
- constructor(writeProxies: WriteProxies, generateLoadID: (filename: string) => string);
34
- byFileCreate(filename: string, locales: string[]): Promise<GranularState>;
29
+ #private;
30
+ readonly byID: Map<number, GranularState>;
31
+ readonly groupPatterns: LoadGroupPatt[];
32
+ constructor(writeProxies: WriteProxies, groupPatterns: LoadGroupPatt[]);
33
+ byFileCreate(filename: string, locales: string[], allowNewItems: boolean): Promise<GranularState>;
35
34
  }
@@ -1,5 +1,6 @@
1
+ import pm from 'picomatch';
1
2
  import { getKey, IndexTracker } from '../adapters.js';
2
- import { defaultPluralRule, fillTranslations } from '../storage.js';
3
+ import { defaultPluralRule, fillTranslations, itemIsObsolete, } from '../storage.js';
3
4
  /**
4
5
  * plural rule expressions should be
5
6
  * - made of ternary and binary expressions
@@ -25,15 +26,16 @@ export class SharedState {
25
26
  ownerKey;
26
27
  sourceLocale;
27
28
  compiled = new Map();
28
- indexTracker = new IndexTracker();
29
+ indexTracker;
29
30
  // storage
30
31
  storage;
31
32
  catalog = new Map();
32
33
  pluralRules = new Map();
33
- constructor(storage, ownerKey, sourceLocale) {
34
+ constructor(storage, ownerKey, sourceLocale, allowNewItems) {
34
35
  this.ownerKey = ownerKey;
35
36
  this.sourceLocale = sourceLocale;
36
37
  this.storage = storage;
38
+ this.indexTracker = new IndexTracker(allowNewItems);
37
39
  }
38
40
  async load(locales) {
39
41
  const loaded = await this.storage.load();
@@ -54,50 +56,60 @@ export class SharedState {
54
56
  this.catalog.set(getKey(id, item.context), item);
55
57
  }
56
58
  }
57
- async save() {
59
+ async save(onlyReferenced) {
60
+ const items = Array.from(this.catalog.values());
58
61
  await this.storage.save({
59
62
  pluralRules: this.pluralRules,
60
- // Array important, cannot loop over map values multiple times!
61
- items: Array.from(this.catalog.values()),
63
+ items: onlyReferenced ? items.filter(i => !itemIsObsolete(i)) : items,
62
64
  });
63
65
  }
64
66
  }
65
67
  export class State {
66
- byFile = new Map();
68
+ #byFile = new Map();
67
69
  byID = new Map();
68
- writeProxies;
69
- generateLoadID;
70
- constructor(writeProxies, generateLoadID) {
71
- this.writeProxies = writeProxies;
72
- this.generateLoadID = generateLoadID;
70
+ #writeProxies;
71
+ groupPatterns = [];
72
+ #groupMatches = [];
73
+ constructor(writeProxies, groupPatterns) {
74
+ this.#writeProxies = writeProxies;
75
+ this.groupPatterns = groupPatterns;
76
+ this.#groupMatches = groupPatterns.map(p => pm(p));
73
77
  }
74
- async byFileCreate(filename, locales) {
75
- let state = this.byFile.get(filename);
78
+ #getLoadID(filename) {
79
+ let id = -1;
80
+ for (const [i, match] of this.#groupMatches.entries()) {
81
+ if (!match(filename)) {
82
+ continue;
83
+ }
84
+ id = i;
85
+ }
86
+ if (id === -1) {
87
+ id = this.groupPatterns.length;
88
+ this.groupPatterns.push(filename);
89
+ this.#groupMatches.push(f => f === filename);
90
+ }
91
+ return id + 1; // not to start from 0 which is reserved for the shared
92
+ }
93
+ async byFileCreate(filename, locales, allowNewItems) {
94
+ let state = this.#byFile.get(filename);
76
95
  if (state != null) {
77
96
  return state;
78
97
  }
79
- const id = this.generateLoadID(filename);
80
- const stateG = this.byID.get(id);
81
- if (stateG) {
82
- state = stateG;
83
- }
84
- else {
85
- const compiledLoaded = new Map();
98
+ const id = this.#getLoadID(filename);
99
+ state = this.byID.get(id);
100
+ if (!state) {
86
101
  state = {
87
102
  id,
88
103
  compiled: new Map(),
89
- indexTracker: new IndexTracker(),
104
+ indexTracker: new IndexTracker(allowNewItems),
90
105
  };
91
106
  for (const loc of locales) {
92
- state.compiled.set(loc, compiledLoaded.get(loc) ?? {
93
- hasPlurals: false,
94
- items: [],
95
- });
107
+ state.compiled.set(loc, { hasPlurals: false, items: [] });
96
108
  }
97
109
  this.byID.set(id, state);
98
- await this.writeProxies(this.byID.values());
110
+ await this.#writeProxies(this.groupPatterns);
99
111
  }
100
- this.byFile.set(filename, state);
112
+ this.#byFile.set(filename, state);
101
113
  return state;
102
114
  }
103
115
  }
@@ -1,18 +1,15 @@
1
- import { type Token } from 'path-to-regexp';
2
- import { type URLConf } from '../adapters.js';
1
+ import { type URLConf, type UrlMatcher } from '../adapters.js';
3
2
  import type AIQueue from '../ai/index.js';
4
3
  import { type Catalog } from '../storage.js';
5
- import type { URLManifest } from '../url.js';
6
- export declare function patternFromTranslate(patternTranslated: string, keys: Token[]): string;
7
- export declare function patternToTranslate(pattern: string): string;
4
+ import { type Pattern, type URLManifest } from '../url.js';
8
5
  export declare class URLHandler {
9
- patternKeys: Map<string, string>;
10
- locales: string[];
11
- sourceLocale: string;
12
- patterns: string[];
6
+ readonly locales: string[];
7
+ readonly sourceLocale: string;
8
+ readonly patterns: string[];
9
+ readonly compiledPatterns: Map<string, Pattern>[];
13
10
  constructor(locales: string[], sourceLocale: string, urlConf?: URLConf);
14
- buildManifest: (catalog: Catalog) => URLManifest;
15
- initPatterns: (adapterKey: string, catalog: Catalog, aiQueue?: AIQueue) => Promise<boolean>;
16
- match: (url: string) => string | null;
17
- matchToCompile: (key: string, catalog: Catalog, locale: string) => string;
11
+ buildManifest: () => URLManifest;
12
+ initPatterns: (adapterKey: string, catalog: Catalog, fallbackChains: Map<string, string[]>, aiQueue?: AIQueue) => Promise<boolean>;
13
+ match: UrlMatcher;
14
+ matchToCompile: (key: string, locale: string) => string;
18
15
  }