@shuo-li/i18n 1.0.9 → 1.2.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.
@@ -1,4 +1,13 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/core/cacheEvents.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+ var _chunkJOUVTRSAcjs = require('./chunk-JOUVTRSA.cjs');
9
+
10
+ // src/core/cacheEvents.ts
2
11
  var I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
3
12
  function emitI18nResourcesUpdated() {
4
13
  if (typeof window === "undefined") return;
@@ -136,12 +145,31 @@ var WorkerManager = class {
136
145
  }
137
146
  const worker = createWorker();
138
147
  this.worker = worker;
148
+ const workerWritesDB = typeof callbacks.transformRaw === "function";
139
149
  worker.onMessage((msg) => {
140
150
  if (msg.type === "rawData") {
141
- const p = callbacks.onRawData(msg.task, msg.raw).catch(() => {
142
- });
143
- this.pendingCallbacks.add(p);
144
- p.finally(() => this.pendingCallbacks.delete(p));
151
+ if (workerWritesDB && callbacks.transformRaw) {
152
+ let blocks;
153
+ try {
154
+ blocks = callbacks.transformRaw(msg.task, msg.raw);
155
+ } catch (err) {
156
+ console.error("[i18n] transform failed", msg.task, err);
157
+ blocks = [];
158
+ }
159
+ worker.postMessage({ type: "parsedData", taskId: msg.task.taskId, blocks });
160
+ } else if (callbacks.onRawData) {
161
+ const p = callbacks.onRawData(msg.task, msg.raw).catch(() => {
162
+ });
163
+ this.pendingCallbacks.add(p);
164
+ p.finally(() => this.pendingCallbacks.delete(p));
165
+ }
166
+ } else if (msg.type === "moduleLoaded") {
167
+ if (callbacks.onModuleLoaded) {
168
+ const p = callbacks.onModuleLoaded(msg).catch(() => {
169
+ });
170
+ this.pendingCallbacks.add(p);
171
+ p.finally(() => this.pendingCallbacks.delete(p));
172
+ }
145
173
  } else if (msg.type === "moduleError") {
146
174
  _optionalChain([callbacks, 'access', _7 => _7.onModuleError, 'optionalCall', _8 => _8(msg)]);
147
175
  } else if (msg.type === "done" || msg.type === "error") {
@@ -169,61 +197,6 @@ var WorkerManager = class {
169
197
  }
170
198
  };
171
199
 
172
- // src/core/utils.ts
173
- function buildKey(moduleCode, langCode, store) {
174
- return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
175
- }
176
- function flatToNested(flat) {
177
- const result = {};
178
- for (const [key, value] of Object.entries(flat)) {
179
- const parts = key.split(".");
180
- let cur = result;
181
- for (let i = 0; i < parts.length - 1; i++) {
182
- const part = parts[i];
183
- if (typeof cur[part] !== "object" || cur[part] === null) {
184
- cur[part] = {};
185
- }
186
- cur = cur[part];
187
- }
188
- cur[parts[parts.length - 1]] = value;
189
- }
190
- return result;
191
- }
192
- function deepMerge(target, source) {
193
- const result = { ...target };
194
- for (const [key, sv] of Object.entries(source)) {
195
- const tv = result[key];
196
- if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
197
- result[key] = deepMerge(tv, sv);
198
- } else {
199
- result[key] = sv;
200
- }
201
- }
202
- return result;
203
- }
204
- function parseI18nValues(values) {
205
- const result = {};
206
- for (const { termCode, langValue } of values) {
207
- if (termCode && langValue !== void 0) {
208
- result[termCode] = _nullishCoalesce(langValue, () => ( ""));
209
- }
210
- }
211
- return result;
212
- }
213
- function toDefaultParams(p) {
214
- const result = {};
215
- if (_optionalChain([p, 'optionalAccess', _14 => _14.storeName])) result["storeName"] = p.storeName;
216
- if (_optionalChain([p, 'optionalAccess', _15 => _15.langCode])) result["langCode"] = p.langCode;
217
- if (_optionalChain([p, 'optionalAccess', _16 => _16.moduleCode])) result["moduleCode"] = p.moduleCode;
218
- if (_optionalChain([p, 'optionalAccess', _17 => _17.version]) != null) result["version"] = String(p.version);
219
- return result;
220
- }
221
- function toQueryString(params) {
222
- return new URLSearchParams(
223
- Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
224
- ).toString();
225
- }
226
-
227
200
  // src/core/manager.ts
228
201
  var PRIORITY_MODULES = ["ENUMS", "CUSTOMER"];
229
202
  var currentLang = "zh_CN";
@@ -236,6 +209,7 @@ var resolvedLanguages = [];
236
209
  var unloginPullStarted = false;
237
210
  var managerOptions = null;
238
211
  var initOptions = null;
212
+ var taskIdCounter = 0;
239
213
  var loadedModules = /* @__PURE__ */ new Set();
240
214
  var loadingModules = /* @__PURE__ */ new Set();
241
215
  var sseClient = new SSEClient();
@@ -308,15 +282,15 @@ async function getResource(moduleCode, langCode) {
308
282
  let merged = { ...getStaticLocale(moduleCode, langCode) };
309
283
  const results = await Promise.allSettled(
310
284
  resolvedStores.map(
311
- (store) => storage.getRecord(store.name, buildKey(moduleCode, langCode, store))
285
+ (store) => storage.getRecord(store.name, _chunkJOUVTRSAcjs.buildKey.call(void 0, moduleCode, langCode, store))
312
286
  )
313
287
  );
314
288
  for (let i = 0; i < resolvedStores.length; i++) {
315
289
  const result = results[i];
316
290
  if (result.status === "rejected") continue;
317
291
  const record = result.value;
318
- if (!_optionalChain([record, 'optionalAccess', _18 => _18.resources])) continue;
319
- merged = i === 0 ? deepMerge(merged, record.resources) : deepMerge(merged, flatToNested(record.resources));
292
+ if (!_optionalChain([record, 'optionalAccess', _14 => _14.resources])) continue;
293
+ merged = _chunkJOUVTRSAcjs.deepMerge.call(void 0, merged, record.resources);
320
294
  }
321
295
  return merged;
322
296
  }
@@ -372,24 +346,15 @@ async function _initI18n(options) {
372
346
  startSSE(options);
373
347
  }
374
348
  }
375
- var CACHE_VERSION_KEY = "__meta__:cache_version";
376
349
  async function checkCacheVersion(storage, options) {
377
350
  if (options.version == null) return;
378
- const baseStoreName = resolvedStores[0].name;
379
351
  const current = String(options.version);
380
- const record = await storage.getRecord(baseStoreName, CACHE_VERSION_KEY).catch(() => void 0);
381
- const stored = _optionalChain([record, 'optionalAccess', _19 => _19.resources, 'optionalAccess', _20 => _20["value"]]);
352
+ const stored = await storage.getMeta("cache_version").catch(() => null);
382
353
  if (stored === current) return;
383
354
  for (const store of options.stores) {
384
355
  await storage.clearStore(store.name);
385
356
  }
386
- await storage.putRecord(baseStoreName, {
387
- key: CACHE_VERSION_KEY,
388
- moduleCode: "__meta__",
389
- langCode: "__meta__",
390
- version: 0,
391
- resources: { value: current }
392
- });
357
+ await storage.setMeta("cache_version", current);
393
358
  }
394
359
  async function doUnloginPull(storage, options) {
395
360
  const { apiContext } = options;
@@ -398,20 +363,19 @@ async function doUnloginPull(storage, options) {
398
363
  let blocks;
399
364
  try {
400
365
  blocks = await doFetch(apiContext.unloginPull, options);
401
- } catch (e4) {
402
- await injectCurrentLanguageModules(currentLang);
403
- await _i18next2.default.changeLanguage(currentLang);
366
+ } catch (err) {
367
+ console.error("[i18n] unloginPull \u8BF7\u6C42\u5931\u8D25\uFF0C\u964D\u7EA7\u9759\u6001\u515C\u5E95", err);
404
368
  emitI18nResourcesUpdated();
405
369
  return;
406
370
  }
407
371
  for (const block of blocks) {
408
372
  for (const mod of _nullishCoalesce(block.modules, () => ( []))) {
409
- const key = buildKey(mod.moduleCode, block.langCode, baseStore);
373
+ const key = _chunkJOUVTRSAcjs.buildKey.call(void 0, mod.moduleCode, block.langCode, baseStore);
410
374
  const existing = await storage.getRecord(baseStore.name, key);
411
- const parsed = parseI18nValues(_nullishCoalesce(mod.i18nValues, () => ( [])));
412
- const resources = deepMerge(
413
- _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _21 => _21.resources]), () => ( {})),
414
- flatToNested(parsed)
375
+ const flat = _chunkJOUVTRSAcjs.parseI18nValues.call(void 0, mod.i18nValues);
376
+ const resources = _chunkJOUVTRSAcjs.deepMerge.call(void 0,
377
+ _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _15 => _15.resources]), () => ( {})),
378
+ _chunkJOUVTRSAcjs.flatToNested.call(void 0, flat)
415
379
  );
416
380
  await storage.putRecord(baseStore.name, {
417
381
  key,
@@ -431,16 +395,13 @@ async function startWorkerFull(options) {
431
395
  const pull = apiContext.pull;
432
396
  const tasks = [];
433
397
  for (const store of resolvedStores) {
434
- for (const lang of resolvedLanguages) {
435
- for (const module of sortedModules()) {
436
- const internal = { storeName: store.name, langCode: lang, moduleCode: module, version: 0 };
437
- tasks.push({
438
- ...internal,
439
- trigger: "init-full",
440
- params: pull.buildParams ? pull.buildParams(internal) : void 0
441
- });
442
- }
443
- }
398
+ const internal = { storeName: store.name };
399
+ tasks.push({
400
+ storeName: store.name,
401
+ taskId: ++taskIdCounter,
402
+ trigger: "init-full",
403
+ params: pull.buildParams ? pull.buildParams(internal) : void 0
404
+ });
444
405
  }
445
406
  await runWorker(options, tasks, pull);
446
407
  }
@@ -448,31 +409,53 @@ function runWorker(options, tasks, pull) {
448
409
  return new Promise((resolve, reject) => {
449
410
  const { apiContext } = options;
450
411
  const storage = managerOptions.storage;
451
- workerManager.start(
452
- managerOptions.createWorker,
453
- {
454
- baseURL: apiContext.baseURL,
455
- headers: apiContext.getHeaders(),
456
- pullPath: pull.path,
457
- pullMethod: _nullishCoalesce(pull.method, () => ( "GET")),
458
- tasks
459
- },
460
- {
412
+ const workerWritesDB = _nullishCoalesce(managerOptions.workerWritesDB, () => ( false));
413
+ const payload = {
414
+ baseURL: apiContext.baseURL,
415
+ headers: apiContext.getHeaders(),
416
+ pullPath: pull.path,
417
+ pullMethod: _nullishCoalesce(pull.method, () => ( "GET")),
418
+ tasks,
419
+ ...workerWritesDB ? { storeConfigs: resolvedStores } : {}
420
+ };
421
+ if (workerWritesDB) {
422
+ workerManager.start(managerOptions.createWorker, payload, {
423
+ transformRaw: (task, raw) => {
424
+ try {
425
+ return pull.transform ? pull.transform(raw) : raw;
426
+ } catch (err) {
427
+ console.error("[i18n] pull transform \u5931\u8D25", task, err);
428
+ return [];
429
+ }
430
+ },
431
+ onModuleLoaded: async (info) => {
432
+ await onModuleLoaded(info);
433
+ },
434
+ onModuleError: () => {
435
+ },
436
+ onDone: resolve,
437
+ onError: () => reject(new Error("[i18n] Worker fatal error"))
438
+ });
439
+ } else {
440
+ workerManager.start(managerOptions.createWorker, payload, {
461
441
  onRawData: async (task, raw) => {
462
- const blocks = pull.transform ? pull.transform(raw) : raw;
442
+ let blocks;
443
+ try {
444
+ blocks = pull.transform ? pull.transform(raw) : raw;
445
+ } catch (err) {
446
+ console.error("[i18n] pull transform \u5931\u8D25", task, err);
447
+ return;
448
+ }
463
449
  const store = resolvedStores.find((s) => s.name === task.storeName);
464
450
  if (!store) return;
465
451
  const storeIndex = resolvedStores.indexOf(store);
466
452
  for (const block of blocks) {
467
453
  for (const mod of _nullishCoalesce(block.modules, () => ( []))) {
468
- const key = buildKey(mod.moduleCode, block.langCode, store);
454
+ const key = _chunkJOUVTRSAcjs.buildKey.call(void 0, mod.moduleCode, block.langCode, store);
469
455
  const existing = await storage.getRecord(store.name, key);
470
456
  if (existing && mod.version <= existing.version) continue;
471
- const parsed = parseI18nValues(_nullishCoalesce(mod.i18nValues, () => ( [])));
472
- const resources = storeIndex === 0 ? deepMerge(
473
- _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _22 => _22.resources]), () => ( {})),
474
- flatToNested(parsed)
475
- ) : { ..._nullishCoalesce(_optionalChain([existing, 'optionalAccess', _23 => _23.resources]), () => ( {})), ...parsed };
457
+ const flat = _chunkJOUVTRSAcjs.parseI18nValues.call(void 0, mod.i18nValues);
458
+ const resources = storeIndex === 0 ? _chunkJOUVTRSAcjs.deepMerge.call(void 0, _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _16 => _16.resources]), () => ( {})), _chunkJOUVTRSAcjs.flatToNested.call(void 0, flat)) : { ..._nullishCoalesce(_optionalChain([existing, 'optionalAccess', _17 => _17.resources]), () => ( {})), ...flat };
476
459
  await storage.putRecord(store.name, {
477
460
  key,
478
461
  moduleCode: mod.moduleCode,
@@ -482,19 +465,19 @@ function runWorker(options, tasks, pull) {
482
465
  });
483
466
  await onModuleLoaded({
484
467
  storeName: task.storeName,
485
- langCode: block.langCode,
486
468
  moduleCode: mod.moduleCode,
469
+ langCode: block.langCode,
487
470
  version: mod.version
488
471
  });
489
472
  }
490
473
  }
491
474
  },
492
- onModuleError: (_data) => {
475
+ onModuleError: () => {
493
476
  },
494
477
  onDone: resolve,
495
478
  onError: () => reject(new Error("[i18n] Worker fatal error"))
496
- }
497
- );
479
+ });
480
+ }
498
481
  });
499
482
  }
500
483
  async function onModuleLoaded(data) {
@@ -508,9 +491,9 @@ async function injectFromDB(moduleCode, langCode) {
508
491
  const storage = managerOptions.storage;
509
492
  for (let i = 0; i < resolvedStores.length; i++) {
510
493
  const store = resolvedStores[i];
511
- const key = buildKey(moduleCode, langCode, store);
494
+ const key = _chunkJOUVTRSAcjs.buildKey.call(void 0, moduleCode, langCode, store);
512
495
  const record = await storage.getRecord(store.name, key);
513
- if (!_optionalChain([record, 'optionalAccess', _24 => _24.resources])) continue;
496
+ if (!_optionalChain([record, 'optionalAccess', _18 => _18.resources])) continue;
514
497
  if (i === 0) {
515
498
  _i18next2.default.addResourceBundle(langCode, moduleCode, record.resources, true, true);
516
499
  } else {
@@ -532,7 +515,7 @@ function startSSE(options) {
532
515
  if (!apiContext.sse) return;
533
516
  sseClient.start(
534
517
  (raw) => {
535
- const msg = _optionalChain([apiContext, 'access', _25 => _25.sse, 'optionalAccess', _26 => _26.transformMessage]) ? apiContext.sse.transformMessage(raw) : raw;
518
+ const msg = _optionalChain([apiContext, 'access', _19 => _19.sse, 'optionalAccess', _20 => _20.transformMessage]) ? apiContext.sse.transformMessage(raw) : raw;
536
519
  void handleSSEMessage(msg, options);
537
520
  },
538
521
  {
@@ -582,7 +565,7 @@ async function flushPendingSSESyncs(options) {
582
565
  task.moduleCode,
583
566
  task.langCode
584
567
  );
585
- } catch (e5) {
568
+ } catch (e4) {
586
569
  localVersion = 0;
587
570
  }
588
571
  if (task.targetVersion <= localVersion) continue;
@@ -593,7 +576,7 @@ async function flushPendingSSESyncs(options) {
593
576
  await _i18next2.default.changeLanguage(currentLang);
594
577
  emitI18nResourcesUpdated();
595
578
  }
596
- } catch (e6) {
579
+ } catch (e5) {
597
580
  }
598
581
  }
599
582
  } finally {
@@ -615,19 +598,11 @@ async function pullAndStore(task, fromVersion, options) {
615
598
  const store = resolvedStores.find((s) => s.name === task.storeName);
616
599
  if (!store) continue;
617
600
  const storeIndex = resolvedStores.indexOf(store);
618
- const key = buildKey(mod.moduleCode, block.langCode, store);
601
+ const key = _chunkJOUVTRSAcjs.buildKey.call(void 0, mod.moduleCode, block.langCode, store);
619
602
  const existing = await storage.getRecord(store.name, key);
620
- if (mod.version <= (_nullishCoalesce(_optionalChain([existing, 'optionalAccess', _27 => _27.version]), () => ( 0)))) continue;
621
- let resources;
622
- const parsed = parseI18nValues(_nullishCoalesce(mod.i18nValues, () => ( [])));
623
- if (storeIndex === 0) {
624
- resources = deepMerge(
625
- _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _28 => _28.resources]), () => ( {})),
626
- flatToNested(parsed)
627
- );
628
- } else {
629
- resources = { ..._nullishCoalesce(_optionalChain([existing, 'optionalAccess', _29 => _29.resources]), () => ( {})), ...parsed };
630
- }
603
+ if (mod.version <= (_nullishCoalesce(_optionalChain([existing, 'optionalAccess', _21 => _21.version]), () => ( 0)))) continue;
604
+ const flat = _chunkJOUVTRSAcjs.parseI18nValues.call(void 0, mod.i18nValues);
605
+ const resources = storeIndex === 0 ? _chunkJOUVTRSAcjs.deepMerge.call(void 0, _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _22 => _22.resources]), () => ( {})), _chunkJOUVTRSAcjs.flatToNested.call(void 0, flat)) : { ..._nullishCoalesce(_optionalChain([existing, 'optionalAccess', _23 => _23.resources]), () => ( {})), ...flat };
631
606
  const version = Math.max(mod.version, task.targetVersion);
632
607
  await storage.putRecord(store.name, {
633
608
  key,
@@ -643,7 +618,7 @@ async function doFetch(config, options, internalParams) {
643
618
  const fetchFn = _nullishCoalesce(managerOptions.fetchFn, () => ( globalThis.fetch.bind(globalThis)));
644
619
  const headers = options.apiContext.getHeaders();
645
620
  const url = options.apiContext.baseURL + config.path;
646
- const params = "buildParams" in config && config.buildParams ? config.buildParams(internalParams) : toDefaultParams(internalParams);
621
+ const params = "buildParams" in config && config.buildParams ? config.buildParams(internalParams) : _chunkJOUVTRSAcjs.toDefaultParams.call(void 0, internalParams);
647
622
  const method = "method" in config ? config.method : void 0;
648
623
  let res;
649
624
  if (method === "POST") {
@@ -653,7 +628,7 @@ async function doFetch(config, options, internalParams) {
653
628
  body: JSON.stringify(params)
654
629
  });
655
630
  } else {
656
- const qs = toQueryString(params);
631
+ const qs = _chunkJOUVTRSAcjs.toQueryString.call(void 0, params);
657
632
  res = await fetchFn(qs ? `${url}?${qs}` : url, { headers });
658
633
  }
659
634
  if (!res.ok) throw new Error(`[i18n] fetch failed: ${res.status} ${url}`);
@@ -671,13 +646,13 @@ function sortedModules() {
671
646
  return [...priority, ...rest];
672
647
  }
673
648
  function getStaticLocale(moduleCode, langCode) {
674
- return _nullishCoalesce(_optionalChain([initOptions, 'optionalAccess', _30 => _30.staticLocales, 'optionalAccess', _31 => _31[langCode], 'optionalAccess', _32 => _32[moduleCode]]), () => ( {}));
649
+ return _nullishCoalesce(_optionalChain([initOptions, 'optionalAccess', _24 => _24.staticLocales, 'optionalAccess', _25 => _25[langCode], 'optionalAccess', _26 => _26[moduleCode]]), () => ( {}));
675
650
  }
676
651
  async function getStoredVersion(store, moduleCode, langCode) {
677
652
  const storage = managerOptions.storage;
678
- const key = buildKey(moduleCode, langCode, store);
653
+ const key = _chunkJOUVTRSAcjs.buildKey.call(void 0, moduleCode, langCode, store);
679
654
  const record = await storage.getRecord(store.name, key);
680
- return _nullishCoalesce(_optionalChain([record, 'optionalAccess', _33 => _33.version]), () => ( 0));
655
+ return _nullishCoalesce(_optionalChain([record, 'optionalAccess', _27 => _27.version]), () => ( 0));
681
656
  }
682
657
 
683
658
 
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
4
 
@@ -7,7 +7,11 @@ var _chunkAJJKJPNBcjs = require('./chunk-AJJKJPNB.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkDSK7CM4Gcjs = require('./chunk-DSK7CM4G.cjs');
10
+ var _chunkUMU62XLBcjs = require('./chunk-UMU62XLB.cjs');
11
+
12
+
13
+
14
+ var _chunkJOUVTRSAcjs = require('./chunk-JOUVTRSA.cjs');
11
15
 
12
16
  // src/index.ts
13
17
  var _i18next = require('i18next'); var _i18next2 = _interopRequireDefault(_i18next);
@@ -15,6 +19,7 @@ var _reacti18next = require('react-i18next');
15
19
 
16
20
  // src/storage/indexeddb.ts
17
21
  var DB_NAME = "i18n_cache";
22
+ var META_STORE = "i18n_meta";
18
23
  function resourceStoreName(name) {
19
24
  return `i18n_resources_${name}`;
20
25
  }
@@ -25,10 +30,13 @@ function openDB(storeNames, idbVersion) {
25
30
  const request = indexedDB.open(DB_NAME, idbVersion);
26
31
  request.onupgradeneeded = (event) => {
27
32
  const db = event.target.result;
33
+ if (!db.objectStoreNames.contains(META_STORE)) {
34
+ db.createObjectStore(META_STORE, { keyPath: "key" });
35
+ }
28
36
  for (const name of storeNames) {
29
- const storeName = resourceStoreName(name);
30
- if (!db.objectStoreNames.contains(storeName)) {
31
- const s = db.createObjectStore(storeName, { keyPath: "key" });
37
+ const sName = resourceStoreName(name);
38
+ if (!db.objectStoreNames.contains(sName)) {
39
+ const s = db.createObjectStore(sName, { keyPath: "key" });
32
40
  s.createIndex("by_module", "moduleCode");
33
41
  s.createIndex("by_language", "langCode");
34
42
  }
@@ -72,18 +80,16 @@ async function withRetry(fn) {
72
80
  }
73
81
  var IndexedDBAdapter = class {
74
82
  /**
75
- * schemaVersion 来自外部传入的 options.version。
76
- * IDB 版本 = schemaVersion * 100 + stores.length,保证:
77
- * - options.version 变化 → IDB 版本变化 → onupgradeneeded → 触发 checkCacheVersion 的数据清理
78
- * - store 数量变化(未登录→登录)→ IDB 版本变化 → onupgradeneeded → 新增 store
83
+ * idbVersion = schemaVersion * 100 + stores.length + 1
84
+ * +1 确保升级时创建 i18n_meta objectStore(新用户自动建,老用户触发 onupgradeneeded)
79
85
  */
80
86
  async ensureStores(stores, schemaVersion = 1) {
81
87
  const storeNames = stores.map((s) => s.name);
82
- const idbVersion = schemaVersion * 100 + storeNames.length;
88
+ const idbVersion = schemaVersion * 100 + storeNames.length + 1;
83
89
  if (dbInstance) {
84
90
  const allExist = storeNames.every(
85
91
  (n) => dbInstance.objectStoreNames.contains(resourceStoreName(n))
86
- );
92
+ ) && dbInstance.objectStoreNames.contains(META_STORE);
87
93
  if (allExist && dbInstance.version === idbVersion) return;
88
94
  dbInstance.close();
89
95
  dbInstance = null;
@@ -105,16 +111,14 @@ var IndexedDBAdapter = class {
105
111
  return withRetry(async () => {
106
112
  const db = await getDB();
107
113
  const tx = db.transaction(resourceStoreName(storeName), "readonly");
108
- const store = tx.objectStore(resourceStoreName(storeName));
109
- return idbRequest(store.get(key));
114
+ return idbRequest(tx.objectStore(resourceStoreName(storeName)).get(key));
110
115
  });
111
116
  }
112
117
  async putRecord(storeName, record) {
113
118
  await withRetry(async () => {
114
119
  const db = await getDB();
115
120
  const tx = db.transaction(resourceStoreName(storeName), "readwrite");
116
- const store = tx.objectStore(resourceStoreName(storeName));
117
- await idbRequest(store.put(record));
121
+ await idbRequest(tx.objectStore(resourceStoreName(storeName)).put(record));
118
122
  });
119
123
  }
120
124
  async getAllByModule(storeName, moduleCode) {
@@ -136,10 +140,10 @@ var IndexedDBAdapter = class {
136
140
  return withRetry(async () => {
137
141
  const db = await getDB();
138
142
  for (const store of stores) {
139
- const tx = db.transaction(resourceStoreName(store.name), "readonly");
140
- const objStore = tx.objectStore(resourceStoreName(store.name));
143
+ const sName = resourceStoreName(store.name);
144
+ const tx = db.transaction(sName, "readonly");
141
145
  const found = await new Promise((resolve, reject) => {
142
- const req = objStore.openCursor();
146
+ const req = tx.objectStore(sName).openCursor();
143
147
  req.onerror = () => reject(req.error);
144
148
  req.onsuccess = () => {
145
149
  const cursor = req.result;
@@ -147,8 +151,7 @@ var IndexedDBAdapter = class {
147
151
  resolve(false);
148
152
  return;
149
153
  }
150
- const record = cursor.value;
151
- if (!record.key.startsWith("UNLOGIN_") && !record.key.startsWith("__meta__:")) {
154
+ if (!cursor.value.key.startsWith("UNLOGIN_")) {
152
155
  resolve(true);
153
156
  return;
154
157
  }
@@ -160,6 +163,23 @@ var IndexedDBAdapter = class {
160
163
  return true;
161
164
  });
162
165
  }
166
+ async getMeta(key) {
167
+ return withRetry(async () => {
168
+ const db = await getDB();
169
+ const tx = db.transaction(META_STORE, "readonly");
170
+ const record = await idbRequest(
171
+ tx.objectStore(META_STORE).get(key)
172
+ );
173
+ return _nullishCoalesce(_optionalChain([record, 'optionalAccess', _ => _.value]), () => ( null));
174
+ });
175
+ }
176
+ async setMeta(key, value) {
177
+ await withRetry(async () => {
178
+ const db = await getDB();
179
+ const tx = db.transaction(META_STORE, "readwrite");
180
+ await idbRequest(tx.objectStore(META_STORE).put({ key, value }));
181
+ });
182
+ }
163
183
  };
164
184
 
165
185
  // src/index.ts
@@ -180,8 +200,9 @@ if (!_i18next2.default.isInitialized) {
180
200
  }
181
201
  });
182
202
  }
183
- var { initI18n, closeSSE, ensureModules, getResource, getAllRecordsByModule } = _chunkDSK7CM4Gcjs.createI18nManager.call(void 0, {
203
+ var { initI18n, closeSSE, ensureModules, getResource, getAllRecordsByModule } = _chunkUMU62XLBcjs.createI18nManager.call(void 0, {
184
204
  storage: new IndexedDBAdapter(),
205
+ workerWritesDB: true,
185
206
  createWorker: () => new (0, _chunkAJJKJPNBcjs.WebWorkerAdapter)(
186
207
  new Worker(new URL("./workers/preload-worker.js", import.meta.url), { type: "module" })
187
208
  )
@@ -196,4 +217,6 @@ var { initI18n, closeSSE, ensureModules, getResource, getAllRecordsByModule } =
196
217
 
197
218
 
198
219
 
199
- exports.I18N_RESOURCES_UPDATED_EVENT = _chunkDSK7CM4Gcjs.I18N_RESOURCES_UPDATED_EVENT; exports.closeSSE = closeSSE; exports.emitI18nResourcesUpdated = _chunkDSK7CM4Gcjs.emitI18nResourcesUpdated; exports.ensureModules = ensureModules; exports.getAllRecordsByModule = getAllRecordsByModule; exports.getResource = getResource; exports.initI18n = initI18n; exports.useDict = _chunkAJJKJPNBcjs.useDict; exports.useTranslation = _chunkAJJKJPNBcjs.useTranslation;
220
+
221
+
222
+ exports.I18N_RESOURCES_UPDATED_EVENT = _chunkUMU62XLBcjs.I18N_RESOURCES_UPDATED_EVENT; exports.closeSSE = closeSSE; exports.deepMerge = _chunkJOUVTRSAcjs.deepMerge; exports.emitI18nResourcesUpdated = _chunkUMU62XLBcjs.emitI18nResourcesUpdated; exports.ensureModules = ensureModules; exports.flatToNested = _chunkJOUVTRSAcjs.flatToNested; exports.getAllRecordsByModule = getAllRecordsByModule; exports.getResource = getResource; exports.initI18n = initI18n; exports.useDict = _chunkAJJKJPNBcjs.useDict; exports.useTranslation = _chunkAJJKJPNBcjs.useTranslation;
package/dist/index.d.cts CHANGED
@@ -1,12 +1,22 @@
1
- import { c as closeSSE$1, e as ensureModules$1, g as getAllRecordsByModule$1, a as getResource$1, i as initI18n$1 } from './cacheEvents-CSwgzbob.cjs';
2
- export { I as I18N_RESOURCES_UPDATED_EVENT, b as I18nInitOptions, P as PullLangBlock, R as ResourceRecord, S as SSEMessage, d as StandardPullParams, f as StoreConfig, W as WorkerLike, h as emitI18nResourcesUpdated } from './cacheEvents-CSwgzbob.cjs';
1
+ import { c as closeSSE$1, e as ensureModules$1, g as getAllRecordsByModule$1, a as getResource$1, i as initI18n$1 } from './cacheEvents-BwXBBuex.cjs';
2
+ export { I as I18N_RESOURCES_UPDATED_EVENT, b as I18nInitOptions, j as I18nValue, P as PullLangBlock, R as ResourceRecord, S as SSEMessage, d as StandardPullParams, f as StoreConfig, W as WorkerLike, h as emitI18nResourcesUpdated } from './cacheEvents-BwXBBuex.cjs';
3
3
  export { u as useDict } from './hooks-ClO29Chr.cjs';
4
4
  export { useTranslation } from 'react-i18next';
5
5
 
6
+ /**
7
+ * dot-notation 平铺 key → 嵌套对象
8
+ * "a.b.c" → { a: { b: { c: value } } }
9
+ */
10
+ declare function flatToNested(flat: Record<string, unknown>): Record<string, unknown>;
11
+ /**
12
+ * 深度合并,source 叶节点覆盖 target,数组直接覆盖
13
+ */
14
+ declare function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown>;
15
+
6
16
  declare const initI18n: typeof initI18n$1;
7
17
  declare const closeSSE: typeof closeSSE$1;
8
18
  declare const ensureModules: typeof ensureModules$1;
9
19
  declare const getResource: typeof getResource$1;
10
20
  declare const getAllRecordsByModule: typeof getAllRecordsByModule$1;
11
21
 
12
- export { closeSSE, ensureModules, getAllRecordsByModule, getResource, initI18n };
22
+ export { closeSSE, deepMerge, ensureModules, flatToNested, getAllRecordsByModule, getResource, initI18n };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,22 @@
1
- import { c as closeSSE$1, e as ensureModules$1, g as getAllRecordsByModule$1, a as getResource$1, i as initI18n$1 } from './cacheEvents-CSwgzbob.js';
2
- export { I as I18N_RESOURCES_UPDATED_EVENT, b as I18nInitOptions, P as PullLangBlock, R as ResourceRecord, S as SSEMessage, d as StandardPullParams, f as StoreConfig, W as WorkerLike, h as emitI18nResourcesUpdated } from './cacheEvents-CSwgzbob.js';
1
+ import { c as closeSSE$1, e as ensureModules$1, g as getAllRecordsByModule$1, a as getResource$1, i as initI18n$1 } from './cacheEvents-BwXBBuex.js';
2
+ export { I as I18N_RESOURCES_UPDATED_EVENT, b as I18nInitOptions, j as I18nValue, P as PullLangBlock, R as ResourceRecord, S as SSEMessage, d as StandardPullParams, f as StoreConfig, W as WorkerLike, h as emitI18nResourcesUpdated } from './cacheEvents-BwXBBuex.js';
3
3
  export { u as useDict } from './hooks-ClO29Chr.js';
4
4
  export { useTranslation } from 'react-i18next';
5
5
 
6
+ /**
7
+ * dot-notation 平铺 key → 嵌套对象
8
+ * "a.b.c" → { a: { b: { c: value } } }
9
+ */
10
+ declare function flatToNested(flat: Record<string, unknown>): Record<string, unknown>;
11
+ /**
12
+ * 深度合并,source 叶节点覆盖 target,数组直接覆盖
13
+ */
14
+ declare function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown>;
15
+
6
16
  declare const initI18n: typeof initI18n$1;
7
17
  declare const closeSSE: typeof closeSSE$1;
8
18
  declare const ensureModules: typeof ensureModules$1;
9
19
  declare const getResource: typeof getResource$1;
10
20
  declare const getAllRecordsByModule: typeof getAllRecordsByModule$1;
11
21
 
12
- export { closeSSE, ensureModules, getAllRecordsByModule, getResource, initI18n };
22
+ export { closeSSE, deepMerge, ensureModules, flatToNested, getAllRecordsByModule, getResource, initI18n };