@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.
- package/dist/{cacheEvents-CSwgzbob.d.cts → cacheEvents-BwXBBuex.d.cts} +12 -4
- package/dist/{cacheEvents-CSwgzbob.d.ts → cacheEvents-BwXBBuex.d.ts} +12 -4
- package/dist/{chunk-3ALMQ7Q5.js → chunk-FFIQQFC4.js} +91 -116
- package/dist/chunk-JOUVTRSA.cjs +61 -0
- package/dist/chunk-NEXKR7GY.js +61 -0
- package/dist/{chunk-DSK7CM4G.cjs → chunk-UMU62XLB.cjs} +110 -135
- package/dist/index.cjs +45 -22
- package/dist/index.d.cts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +42 -19
- package/dist/mp/index.cjs +31 -9
- package/dist/mp/index.d.cts +2 -2
- package/dist/mp/index.d.ts +2 -2
- package/dist/mp/index.js +29 -7
- package/dist/native/index.cjs +26 -4
- package/dist/native/index.d.cts +2 -2
- package/dist/native/index.d.ts +2 -2
- package/dist/native/index.js +24 -2
- package/dist/workers/preload-worker.cjs +90 -5
- package/dist/workers/preload-worker.js +89 -4
- package/package.json +1 -1
|
@@ -55,7 +55,6 @@ interface SSEMessage {
|
|
|
55
55
|
type: string;
|
|
56
56
|
langCode: string;
|
|
57
57
|
moduleCode: string;
|
|
58
|
-
/** SSE 消息携带的数据版本号,与本地 version 对比决定是否拉取 */
|
|
59
58
|
version: number;
|
|
60
59
|
storeName: string;
|
|
61
60
|
}
|
|
@@ -74,7 +73,6 @@ interface ResourceRecord {
|
|
|
74
73
|
key: string;
|
|
75
74
|
moduleCode: string;
|
|
76
75
|
langCode: string;
|
|
77
|
-
/** 当前已存储数据的版本号(对应旧的 toSynTime) */
|
|
78
76
|
version: number;
|
|
79
77
|
resources: Record<string, unknown>;
|
|
80
78
|
}
|
|
@@ -84,6 +82,8 @@ interface WorkerTask {
|
|
|
84
82
|
moduleCode?: string;
|
|
85
83
|
/** 全量拉取时为 0;SSE 增量拉取时为本地已有版本号 */
|
|
86
84
|
version?: number;
|
|
85
|
+
/** 唯一标识,用于主线程回传 parsedData 时关联任务(Web 模式下必须) */
|
|
86
|
+
taskId?: number;
|
|
87
87
|
trigger?: 'init-full' | 'sse';
|
|
88
88
|
/** 经 buildParams 映射后的实际请求参数;未提供时 Worker 使用内部字段名 */
|
|
89
89
|
params?: Record<string, unknown>;
|
|
@@ -93,6 +93,14 @@ interface WorkerRawDataMessage {
|
|
|
93
93
|
task: WorkerTask;
|
|
94
94
|
raw: unknown;
|
|
95
95
|
}
|
|
96
|
+
/** Worker 写入一个模块后通知主线程(Web 模式,Worker 写 IDB) */
|
|
97
|
+
interface WorkerModuleLoadedMessage {
|
|
98
|
+
type: 'moduleLoaded';
|
|
99
|
+
storeName: string;
|
|
100
|
+
moduleCode: string;
|
|
101
|
+
langCode: string;
|
|
102
|
+
version: number;
|
|
103
|
+
}
|
|
96
104
|
interface WorkerModuleErrorMessage {
|
|
97
105
|
type: 'moduleError';
|
|
98
106
|
storeName: string;
|
|
@@ -106,7 +114,7 @@ interface WorkerErrorMessage {
|
|
|
106
114
|
type: 'error';
|
|
107
115
|
message?: string;
|
|
108
116
|
}
|
|
109
|
-
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
117
|
+
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleLoadedMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
110
118
|
interface WorkerLike {
|
|
111
119
|
postMessage(data: unknown): void;
|
|
112
120
|
onMessage(handler: (data: WorkerOutMessage) => void): void;
|
|
@@ -122,4 +130,4 @@ declare function getAllRecordsByModule(moduleCode: string): Promise<ResourceReco
|
|
|
122
130
|
declare const I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
123
131
|
declare function emitI18nResourcesUpdated(): void;
|
|
124
132
|
|
|
125
|
-
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i };
|
|
133
|
+
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i, type I18nValue as j };
|
|
@@ -55,7 +55,6 @@ interface SSEMessage {
|
|
|
55
55
|
type: string;
|
|
56
56
|
langCode: string;
|
|
57
57
|
moduleCode: string;
|
|
58
|
-
/** SSE 消息携带的数据版本号,与本地 version 对比决定是否拉取 */
|
|
59
58
|
version: number;
|
|
60
59
|
storeName: string;
|
|
61
60
|
}
|
|
@@ -74,7 +73,6 @@ interface ResourceRecord {
|
|
|
74
73
|
key: string;
|
|
75
74
|
moduleCode: string;
|
|
76
75
|
langCode: string;
|
|
77
|
-
/** 当前已存储数据的版本号(对应旧的 toSynTime) */
|
|
78
76
|
version: number;
|
|
79
77
|
resources: Record<string, unknown>;
|
|
80
78
|
}
|
|
@@ -84,6 +82,8 @@ interface WorkerTask {
|
|
|
84
82
|
moduleCode?: string;
|
|
85
83
|
/** 全量拉取时为 0;SSE 增量拉取时为本地已有版本号 */
|
|
86
84
|
version?: number;
|
|
85
|
+
/** 唯一标识,用于主线程回传 parsedData 时关联任务(Web 模式下必须) */
|
|
86
|
+
taskId?: number;
|
|
87
87
|
trigger?: 'init-full' | 'sse';
|
|
88
88
|
/** 经 buildParams 映射后的实际请求参数;未提供时 Worker 使用内部字段名 */
|
|
89
89
|
params?: Record<string, unknown>;
|
|
@@ -93,6 +93,14 @@ interface WorkerRawDataMessage {
|
|
|
93
93
|
task: WorkerTask;
|
|
94
94
|
raw: unknown;
|
|
95
95
|
}
|
|
96
|
+
/** Worker 写入一个模块后通知主线程(Web 模式,Worker 写 IDB) */
|
|
97
|
+
interface WorkerModuleLoadedMessage {
|
|
98
|
+
type: 'moduleLoaded';
|
|
99
|
+
storeName: string;
|
|
100
|
+
moduleCode: string;
|
|
101
|
+
langCode: string;
|
|
102
|
+
version: number;
|
|
103
|
+
}
|
|
96
104
|
interface WorkerModuleErrorMessage {
|
|
97
105
|
type: 'moduleError';
|
|
98
106
|
storeName: string;
|
|
@@ -106,7 +114,7 @@ interface WorkerErrorMessage {
|
|
|
106
114
|
type: 'error';
|
|
107
115
|
message?: string;
|
|
108
116
|
}
|
|
109
|
-
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
117
|
+
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleLoadedMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
110
118
|
interface WorkerLike {
|
|
111
119
|
postMessage(data: unknown): void;
|
|
112
120
|
onMessage(handler: (data: WorkerOutMessage) => void): void;
|
|
@@ -122,4 +130,4 @@ declare function getAllRecordsByModule(moduleCode: string): Promise<ResourceReco
|
|
|
122
130
|
declare const I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
123
131
|
declare function emitI18nResourcesUpdated(): void;
|
|
124
132
|
|
|
125
|
-
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i };
|
|
133
|
+
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i, type I18nValue as j };
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildKey,
|
|
3
|
+
deepMerge,
|
|
4
|
+
flatToNested,
|
|
5
|
+
parseI18nValues,
|
|
6
|
+
toDefaultParams,
|
|
7
|
+
toQueryString
|
|
8
|
+
} from "./chunk-NEXKR7GY.js";
|
|
9
|
+
|
|
1
10
|
// src/core/cacheEvents.ts
|
|
2
11
|
var I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
3
12
|
function emitI18nResourcesUpdated() {
|
|
@@ -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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
callbacks.onModuleError?.(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] = langValue ?? "";
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return result;
|
|
212
|
-
}
|
|
213
|
-
function toDefaultParams(p) {
|
|
214
|
-
const result = {};
|
|
215
|
-
if (p?.storeName) result["storeName"] = p.storeName;
|
|
216
|
-
if (p?.langCode) result["langCode"] = p.langCode;
|
|
217
|
-
if (p?.moduleCode) result["moduleCode"] = p.moduleCode;
|
|
218
|
-
if (p?.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();
|
|
@@ -316,7 +290,7 @@ async function getResource(moduleCode, langCode) {
|
|
|
316
290
|
if (result.status === "rejected") continue;
|
|
317
291
|
const record = result.value;
|
|
318
292
|
if (!record?.resources) continue;
|
|
319
|
-
merged =
|
|
293
|
+
merged = deepMerge(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
|
|
381
|
-
const stored = record?.resources?.["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.
|
|
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,9 +363,8 @@ async function doUnloginPull(storage, options) {
|
|
|
398
363
|
let blocks;
|
|
399
364
|
try {
|
|
400
365
|
blocks = await doFetch(apiContext.unloginPull, options);
|
|
401
|
-
} catch {
|
|
402
|
-
|
|
403
|
-
await i18n.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
|
}
|
|
@@ -408,10 +372,10 @@ async function doUnloginPull(storage, options) {
|
|
|
408
372
|
for (const mod of block.modules ?? []) {
|
|
409
373
|
const key = buildKey(mod.moduleCode, block.langCode, baseStore);
|
|
410
374
|
const existing = await storage.getRecord(baseStore.name, key);
|
|
411
|
-
const
|
|
375
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
412
376
|
const resources = deepMerge(
|
|
413
377
|
existing?.resources ?? {},
|
|
414
|
-
flatToNested(
|
|
378
|
+
flatToNested(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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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,18 +409,43 @@ function runWorker(options, tasks, pull) {
|
|
|
448
409
|
return new Promise((resolve, reject) => {
|
|
449
410
|
const { apiContext } = options;
|
|
450
411
|
const storage = managerOptions.storage;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
412
|
+
const workerWritesDB = managerOptions.workerWritesDB ?? false;
|
|
413
|
+
const payload = {
|
|
414
|
+
baseURL: apiContext.baseURL,
|
|
415
|
+
headers: apiContext.getHeaders(),
|
|
416
|
+
pullPath: pull.path,
|
|
417
|
+
pullMethod: 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
|
-
|
|
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);
|
|
@@ -468,11 +454,8 @@ function runWorker(options, tasks, pull) {
|
|
|
468
454
|
const key = buildKey(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
|
|
472
|
-
const resources = storeIndex === 0 ? deepMerge(
|
|
473
|
-
existing?.resources ?? {},
|
|
474
|
-
flatToNested(parsed)
|
|
475
|
-
) : { ...existing?.resources ?? {}, ...parsed };
|
|
457
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
458
|
+
const resources = storeIndex === 0 ? deepMerge(existing?.resources ?? {}, flatToNested(flat)) : { ...existing?.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: (
|
|
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) {
|
|
@@ -618,16 +601,8 @@ async function pullAndStore(task, fromVersion, options) {
|
|
|
618
601
|
const key = buildKey(mod.moduleCode, block.langCode, store);
|
|
619
602
|
const existing = await storage.getRecord(store.name, key);
|
|
620
603
|
if (mod.version <= (existing?.version ?? 0)) continue;
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
if (storeIndex === 0) {
|
|
624
|
-
resources = deepMerge(
|
|
625
|
-
existing?.resources ?? {},
|
|
626
|
-
flatToNested(parsed)
|
|
627
|
-
);
|
|
628
|
-
} else {
|
|
629
|
-
resources = { ...existing?.resources ?? {}, ...parsed };
|
|
630
|
-
}
|
|
604
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
605
|
+
const resources = storeIndex === 0 ? deepMerge(existing?.resources ?? {}, flatToNested(flat)) : { ...existing?.resources ?? {}, ...flat };
|
|
631
606
|
const version = Math.max(mod.version, task.targetVersion);
|
|
632
607
|
await storage.putRecord(store.name, {
|
|
633
608
|
key,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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/utils.ts
|
|
2
|
+
function buildKey(moduleCode, langCode, store) {
|
|
3
|
+
return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
|
|
4
|
+
}
|
|
5
|
+
function parseI18nValues(values) {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const v of values) {
|
|
8
|
+
if (v.termCode) result[v.termCode] = _nullishCoalesce(v.langValue, () => ( ""));
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
function flatToNested(flat) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
15
|
+
const parts = key.split(".");
|
|
16
|
+
let cur = result;
|
|
17
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
18
|
+
const part = parts[i];
|
|
19
|
+
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
20
|
+
cur[part] = {};
|
|
21
|
+
}
|
|
22
|
+
cur = cur[part];
|
|
23
|
+
}
|
|
24
|
+
cur[parts[parts.length - 1]] = value;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function deepMerge(target, source) {
|
|
29
|
+
const result = { ...target };
|
|
30
|
+
for (const [key, sv] of Object.entries(source)) {
|
|
31
|
+
const tv = result[key];
|
|
32
|
+
if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
|
|
33
|
+
result[key] = deepMerge(tv, sv);
|
|
34
|
+
} else {
|
|
35
|
+
result[key] = sv;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function toDefaultParams(p) {
|
|
41
|
+
const result = {};
|
|
42
|
+
if (_optionalChain([p, 'optionalAccess', _ => _.storeName])) result["storeName"] = p.storeName;
|
|
43
|
+
if (_optionalChain([p, 'optionalAccess', _2 => _2.langCode])) result["langCode"] = p.langCode;
|
|
44
|
+
if (_optionalChain([p, 'optionalAccess', _3 => _3.moduleCode])) result["moduleCode"] = p.moduleCode;
|
|
45
|
+
if (_optionalChain([p, 'optionalAccess', _4 => _4.version]) != null) result["version"] = String(p.version);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function toQueryString(params) {
|
|
49
|
+
return new URLSearchParams(
|
|
50
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
51
|
+
).toString();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
exports.buildKey = buildKey; exports.parseI18nValues = parseI18nValues; exports.flatToNested = flatToNested; exports.deepMerge = deepMerge; exports.toDefaultParams = toDefaultParams; exports.toQueryString = toQueryString;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/core/utils.ts
|
|
2
|
+
function buildKey(moduleCode, langCode, store) {
|
|
3
|
+
return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
|
|
4
|
+
}
|
|
5
|
+
function parseI18nValues(values) {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const v of values) {
|
|
8
|
+
if (v.termCode) result[v.termCode] = v.langValue ?? "";
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
function flatToNested(flat) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
15
|
+
const parts = key.split(".");
|
|
16
|
+
let cur = result;
|
|
17
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
18
|
+
const part = parts[i];
|
|
19
|
+
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
20
|
+
cur[part] = {};
|
|
21
|
+
}
|
|
22
|
+
cur = cur[part];
|
|
23
|
+
}
|
|
24
|
+
cur[parts[parts.length - 1]] = value;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function deepMerge(target, source) {
|
|
29
|
+
const result = { ...target };
|
|
30
|
+
for (const [key, sv] of Object.entries(source)) {
|
|
31
|
+
const tv = result[key];
|
|
32
|
+
if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
|
|
33
|
+
result[key] = deepMerge(tv, sv);
|
|
34
|
+
} else {
|
|
35
|
+
result[key] = sv;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function toDefaultParams(p) {
|
|
41
|
+
const result = {};
|
|
42
|
+
if (p?.storeName) result["storeName"] = p.storeName;
|
|
43
|
+
if (p?.langCode) result["langCode"] = p.langCode;
|
|
44
|
+
if (p?.moduleCode) result["moduleCode"] = p.moduleCode;
|
|
45
|
+
if (p?.version != null) result["version"] = String(p.version);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function toQueryString(params) {
|
|
49
|
+
return new URLSearchParams(
|
|
50
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
51
|
+
).toString();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
buildKey,
|
|
56
|
+
parseI18nValues,
|
|
57
|
+
flatToNested,
|
|
58
|
+
deepMerge,
|
|
59
|
+
toDefaultParams,
|
|
60
|
+
toQueryString
|
|
61
|
+
};
|