@musnows/scriverse 0.8.7 → 0.9.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.
@@ -0,0 +1,436 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { AppError } from "./errors.js";
3
+ import { countWords } from "./utils.js";
4
+ export const SYNC_SNAPSHOT_TTL_MS = 15 * 60 * 1_000;
5
+ export const SYNC_SNAPSHOT_PAGE_BYTE_LIMIT = 4 * 1024 * 1024;
6
+ const MAX_ACTIVE_SYNC_SNAPSHOTS = 128;
7
+ function recordArray(value) {
8
+ return Array.isArray(value)
9
+ ? value.filter((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item))
10
+ : [];
11
+ }
12
+ function snapshotItem(sequence, entityType, data) {
13
+ const item = {
14
+ sequence,
15
+ entityType,
16
+ entityId: String(data.id ?? ""),
17
+ versionNo: Number(data.versionNo ?? 0),
18
+ data
19
+ };
20
+ return { ...item, byteLength: Buffer.byteLength(JSON.stringify(item), "utf8") };
21
+ }
22
+ function stableJson(value) {
23
+ if (Array.isArray(value))
24
+ return `[${value.map((item) => stableJson(item)).join(",")}]`;
25
+ if (value && typeof value === "object") {
26
+ return `{${Object.entries(value)
27
+ .filter(([, item]) => item !== undefined)
28
+ .sort(([left], [right]) => left.localeCompare(right))
29
+ .map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`)
30
+ .join(",")}}`;
31
+ }
32
+ return JSON.stringify(value) ?? "null";
33
+ }
34
+ export class OfflineSyncService {
35
+ database;
36
+ store;
37
+ snapshots = new Map();
38
+ now;
39
+ snapshotTtlMs;
40
+ constructor(database, store, options = {}) {
41
+ this.database = database;
42
+ this.store = store;
43
+ this.now = options.now ?? Date.now;
44
+ this.snapshotTtlMs = options.snapshotTtlMs ?? SYNC_SNAPSHOT_TTL_MS;
45
+ }
46
+ createSnapshot(workId, userId) {
47
+ const captured = this.database.transaction(() => {
48
+ this.assertOfflineAccessEnabled(workId);
49
+ const tree = this.store.getWorkTree(workId);
50
+ const volumes = recordArray(tree.volumes);
51
+ const { volumes: _volumes, modulePermissions: _modulePermissions, accessRole: _accessRole, ...work } = tree;
52
+ const rawItems = [
53
+ { entityType: "work", data: work }
54
+ ];
55
+ for (const volumeWithChapters of volumes) {
56
+ const chapters = recordArray(volumeWithChapters.chapters);
57
+ const { chapters: _chapters, ...volume } = volumeWithChapters;
58
+ rawItems.push({ entityType: "volume", data: volume });
59
+ for (const chapter of chapters)
60
+ rawItems.push({ entityType: "chapter", data: chapter });
61
+ }
62
+ for (const setting of this.store.listSettings(workId, true)) {
63
+ rawItems.push({ entityType: "setting", data: setting });
64
+ }
65
+ const cutoffCursor = Number(this.database.get("SELECT COALESCE(MAX(cursor), 0) AS cursor FROM sync_changes WHERE work_id = ?", workId)?.cursor ?? 0);
66
+ return {
67
+ cutoffCursor,
68
+ items: rawItems.map((item, index) => snapshotItem(index + 1, item.entityType, item.data))
69
+ };
70
+ });
71
+ const createdAtMs = this.now();
72
+ this.pruneExpired(createdAtMs);
73
+ for (const [snapshotId, snapshot] of this.snapshots) {
74
+ if (snapshot.userId === userId && snapshot.workId === workId)
75
+ this.snapshots.delete(snapshotId);
76
+ }
77
+ while (this.snapshots.size >= MAX_ACTIVE_SYNC_SNAPSHOTS) {
78
+ const oldest = [...this.snapshots.values()].sort((left, right) => left.createdAtMs - right.createdAtMs)[0];
79
+ if (!oldest)
80
+ break;
81
+ this.snapshots.delete(oldest.snapshotId);
82
+ }
83
+ const snapshot = {
84
+ snapshotId: randomUUID(),
85
+ workId,
86
+ userId,
87
+ cutoffCursor: captured.cutoffCursor,
88
+ itemCount: captured.items.length,
89
+ createdAtMs,
90
+ expiresAtMs: createdAtMs + this.snapshotTtlMs,
91
+ expiresAt: new Date(createdAtMs + this.snapshotTtlMs).toISOString(),
92
+ syncProtocol: 1,
93
+ items: captured.items
94
+ };
95
+ this.snapshots.set(snapshot.snapshotId, snapshot);
96
+ return this.descriptor(snapshot);
97
+ }
98
+ describeOwnedSnapshot(snapshotId, userId) {
99
+ return this.descriptor(this.ownedSnapshot(snapshotId, userId));
100
+ }
101
+ readSnapshotPage(snapshotId, userId, after, limit) {
102
+ const snapshot = this.ownedSnapshot(snapshotId, userId);
103
+ this.assertOfflineAccessEnabled(snapshot.workId);
104
+ const candidates = snapshot.items.filter((item) => item.sequence > after).slice(0, limit);
105
+ const selected = [];
106
+ let selectedBytes = 0;
107
+ for (const item of candidates) {
108
+ if (selected.length > 0 && selectedBytes + item.byteLength > SYNC_SNAPSHOT_PAGE_BYTE_LIMIT)
109
+ break;
110
+ selected.push(item);
111
+ selectedBytes += item.byteLength;
112
+ }
113
+ const lastSequence = selected.at(-1)?.sequence ?? after;
114
+ const hasMore = snapshot.items.some((item) => item.sequence > lastSequence);
115
+ return {
116
+ snapshotId,
117
+ workId: snapshot.workId,
118
+ cutoffCursor: snapshot.cutoffCursor,
119
+ after,
120
+ nextAfter: hasMore ? lastSequence : null,
121
+ hasMore,
122
+ items: selected.map(({ byteLength: _byteLength, ...item }) => item)
123
+ };
124
+ }
125
+ deleteSnapshot(snapshotId, userId) {
126
+ this.ownedSnapshot(snapshotId, userId);
127
+ this.snapshots.delete(snapshotId);
128
+ }
129
+ listChanges(workId, after, limit) {
130
+ return this.database.transaction(() => {
131
+ this.assertOfflineAccessEnabled(workId);
132
+ const rows = this.database.all(`SELECT cursor, entity_type, entity_id, operation, version_no, changed_by_user_id, changed_at
133
+ FROM sync_changes WHERE work_id = ? AND cursor > ? ORDER BY cursor LIMIT ?`, workId, after, limit + 1);
134
+ const hasMore = rows.length > limit;
135
+ const pageRows = rows.slice(0, limit);
136
+ const items = pageRows.map((row) => this.mapChange(row));
137
+ const latestCursor = Number(this.database.get("SELECT COALESCE(MAX(cursor), 0) AS cursor FROM sync_changes WHERE work_id = ?", workId)?.cursor ?? 0);
138
+ return {
139
+ workId,
140
+ after,
141
+ nextCursor: items.at(-1)?.cursor ?? after,
142
+ latestCursor,
143
+ hasMore,
144
+ items
145
+ };
146
+ });
147
+ }
148
+ pushMutations(workId, userId, clientId, mutations) {
149
+ this.assertOfflineAccessEnabled(workId);
150
+ const results = mutations.map((mutation) => this.processMutation(workId, userId, clientId, mutation));
151
+ return {
152
+ clientId,
153
+ results,
154
+ summary: {
155
+ applied: results.filter((result) => result.status === "applied").length,
156
+ conflict: results.filter((result) => result.status === "conflict").length,
157
+ rejected: results.filter((result) => result.status === "rejected").length,
158
+ replayed: results.filter((result) => result.replayed).length
159
+ }
160
+ };
161
+ }
162
+ getMutationResult(workId, userId, mutationId) {
163
+ this.assertOfflineAccessEnabled(workId);
164
+ const row = this.database.get(`SELECT result_json FROM sync_mutation_results
165
+ WHERE mutation_id = ? AND work_id = ? AND user_id = ?`, mutationId, workId, userId);
166
+ if (!row)
167
+ throw new AppError(404, "SYNC_MUTATION_NOT_FOUND", "同步变更结果不存在");
168
+ return this.parseMutationResult(String(row.result_json));
169
+ }
170
+ dispose() {
171
+ this.snapshots.clear();
172
+ }
173
+ ownedSnapshot(snapshotId, userId) {
174
+ const snapshot = this.snapshots.get(snapshotId);
175
+ if (!snapshot || snapshot.userId !== userId) {
176
+ throw new AppError(404, "SYNC_SNAPSHOT_NOT_FOUND", "同步快照不存在");
177
+ }
178
+ if (snapshot.expiresAtMs <= this.now()) {
179
+ this.snapshots.delete(snapshotId);
180
+ throw new AppError(410, "SYNC_SNAPSHOT_EXPIRED", "同步快照已过期,请重新创建");
181
+ }
182
+ return snapshot;
183
+ }
184
+ assertOfflineAccessEnabled(workId) {
185
+ const work = this.database.get("SELECT offline_access_enabled FROM works WHERE id = ? AND deleted_at IS NULL", workId);
186
+ if (!work)
187
+ throw new AppError(404, "WORK_NOT_FOUND", "作品不存在");
188
+ if (Number(work.offline_access_enabled) !== 1) {
189
+ throw new AppError(403, "OFFLINE_ACCESS_DISABLED", "作品所有者尚未允许 Desktop 离线访问");
190
+ }
191
+ }
192
+ mapChange(row) {
193
+ const entityType = String(row.entity_type) === "setting" ? "setting" : "chapter";
194
+ const operation = String(row.operation) === "delete" ? "delete" : "upsert";
195
+ const entityId = String(row.entity_id);
196
+ const versionNo = Number(row.version_no);
197
+ return {
198
+ cursor: Number(row.cursor),
199
+ entityType,
200
+ entityId,
201
+ operation,
202
+ versionNo,
203
+ changedByUserId: row.changed_by_user_id === null || row.changed_by_user_id === undefined
204
+ ? null
205
+ : String(row.changed_by_user_id),
206
+ changedAt: String(row.changed_at),
207
+ data: operation === "delete" ? null : entityType === "chapter"
208
+ ? this.chapterVersionData(entityId, versionNo)
209
+ : this.settingVersionData(entityId, versionNo)
210
+ };
211
+ }
212
+ processMutation(workId, userId, clientId, mutation) {
213
+ const requestHash = createHash("sha256")
214
+ .update(stableJson({ workId, userId, clientId, mutation }))
215
+ .digest("hex");
216
+ return this.database.transaction(() => {
217
+ const existing = this.database.get("SELECT request_hash, result_json FROM sync_mutation_results WHERE mutation_id = ?", mutation.mutationId);
218
+ if (existing) {
219
+ if (String(existing.request_hash) !== requestHash) {
220
+ throw new AppError(409, "MUTATION_ID_REUSED", "mutationId 已用于不同的同步请求");
221
+ }
222
+ return { ...this.parseMutationResult(String(existing.result_json)), replayed: true };
223
+ }
224
+ const result = this.applyMutation(workId, mutation);
225
+ const timestamp = new Date(this.now()).toISOString();
226
+ this.database.run(`INSERT INTO sync_mutation_results (
227
+ mutation_id, client_id, user_id, work_id, request_hash, status, applied_version_no,
228
+ conflict_version_no, error_code, result_json, created_at, updated_at
229
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, mutation.mutationId, clientId, userId, workId, requestHash, result.status, result.appliedVersionNo, result.conflictVersionNo, result.errorCode, JSON.stringify(result), timestamp, timestamp);
230
+ return result;
231
+ });
232
+ }
233
+ applyMutation(workId, mutation) {
234
+ const state = this.currentMutationEntityState(mutation.entityType, mutation.entityId);
235
+ if (!state)
236
+ return this.rejectedMutation(mutation, "SYNC_ENTITY_NOT_FOUND");
237
+ if (state.workId !== workId)
238
+ return this.rejectedMutation(mutation, "SYNC_ENTITY_NOT_FOUND");
239
+ const baseSnapshot = this.mutationVersionData(mutation.entityType, mutation.entityId, mutation.baseVersionNo);
240
+ const serverSnapshot = state.active
241
+ ? this.mutationVersionData(mutation.entityType, mutation.entityId, state.versionNo)
242
+ : { id: mutation.entityId, workId, versionNo: state.versionNo, deleted: true };
243
+ if (!baseSnapshot) {
244
+ return this.rejectedMutation(mutation, "SYNC_BASE_VERSION_MISSING", null, serverSnapshot);
245
+ }
246
+ const localSnapshot = { ...baseSnapshot, ...mutation.localSnapshot, versionNo: mutation.baseVersionNo };
247
+ if (!state.active || state.versionNo !== mutation.baseVersionNo) {
248
+ return {
249
+ mutationId: mutation.mutationId,
250
+ entityType: mutation.entityType,
251
+ entityId: mutation.entityId,
252
+ status: "conflict",
253
+ baseVersionNo: mutation.baseVersionNo,
254
+ appliedVersionNo: null,
255
+ conflictVersionNo: state.versionNo,
256
+ errorCode: "VERSION_CONFLICT",
257
+ baseSnapshot,
258
+ localSnapshot,
259
+ serverSnapshot,
260
+ replayed: false
261
+ };
262
+ }
263
+ try {
264
+ const updated = mutation.entityType === "chapter"
265
+ ? this.store.saveChapter(mutation.entityId, mutation.localSnapshot, "desktop-sync", mutation.mutationId, mutation.changeNote, mutation.baseVersionNo)
266
+ : this.store.updateSetting(mutation.entityId, mutation.localSnapshot, "desktop-sync", mutation.mutationId, mutation.changeNote, mutation.baseVersionNo);
267
+ return {
268
+ mutationId: mutation.mutationId,
269
+ entityType: mutation.entityType,
270
+ entityId: mutation.entityId,
271
+ status: "applied",
272
+ baseVersionNo: mutation.baseVersionNo,
273
+ appliedVersionNo: Number(updated.versionNo),
274
+ conflictVersionNo: null,
275
+ errorCode: null,
276
+ baseSnapshot,
277
+ localSnapshot,
278
+ serverSnapshot: updated,
279
+ replayed: false
280
+ };
281
+ }
282
+ catch (error) {
283
+ if (!(error instanceof AppError))
284
+ throw error;
285
+ const latest = this.currentMutationEntityState(mutation.entityType, mutation.entityId);
286
+ if (error.code === "VERSION_CONFLICT" && latest) {
287
+ return {
288
+ mutationId: mutation.mutationId,
289
+ entityType: mutation.entityType,
290
+ entityId: mutation.entityId,
291
+ status: "conflict",
292
+ baseVersionNo: mutation.baseVersionNo,
293
+ appliedVersionNo: null,
294
+ conflictVersionNo: latest.versionNo,
295
+ errorCode: error.code,
296
+ baseSnapshot,
297
+ localSnapshot,
298
+ serverSnapshot: latest.active
299
+ ? this.mutationVersionData(mutation.entityType, mutation.entityId, latest.versionNo)
300
+ : { id: mutation.entityId, workId, versionNo: latest.versionNo, deleted: true },
301
+ replayed: false
302
+ };
303
+ }
304
+ return this.rejectedMutation(mutation, error.code, baseSnapshot, serverSnapshot, localSnapshot);
305
+ }
306
+ }
307
+ rejectedMutation(mutation, errorCode, baseSnapshot = null, serverSnapshot = null, localSnapshot = null) {
308
+ return {
309
+ mutationId: mutation.mutationId,
310
+ entityType: mutation.entityType,
311
+ entityId: mutation.entityId,
312
+ status: "rejected",
313
+ baseVersionNo: mutation.baseVersionNo,
314
+ appliedVersionNo: null,
315
+ conflictVersionNo: null,
316
+ errorCode,
317
+ baseSnapshot,
318
+ localSnapshot,
319
+ serverSnapshot,
320
+ replayed: false
321
+ };
322
+ }
323
+ currentMutationEntityState(entityType, entityId) {
324
+ if (entityType === "chapter") {
325
+ const chapter = this.database.get("SELECT work_id, version_no, deleted_at FROM chapters WHERE id = ?", entityId);
326
+ if (chapter) {
327
+ return {
328
+ workId: String(chapter.work_id),
329
+ versionNo: Number(chapter.version_no),
330
+ active: chapter.deleted_at === null || chapter.deleted_at === undefined
331
+ };
332
+ }
333
+ const version = this.database.get("SELECT work_id, MAX(version_no) AS version_no FROM chapter_versions WHERE chapter_id = ?", entityId);
334
+ return version?.work_id
335
+ ? { workId: String(version.work_id), versionNo: Number(version.version_no), active: false }
336
+ : null;
337
+ }
338
+ const setting = this.database.get("SELECT work_id FROM settings WHERE id = ?", entityId);
339
+ const version = this.database.get(`SELECT work_id, MAX(version_no) AS version_no FROM entity_versions
340
+ WHERE entity_type = 'setting' AND entity_id = ?`, entityId);
341
+ if (!version?.work_id)
342
+ return null;
343
+ return {
344
+ workId: String(version.work_id),
345
+ versionNo: Number(version.version_no),
346
+ active: Boolean(setting)
347
+ };
348
+ }
349
+ mutationVersionData(entityType, entityId, versionNo) {
350
+ try {
351
+ return entityType === "chapter"
352
+ ? this.chapterVersionData(entityId, versionNo)
353
+ : this.settingVersionData(entityId, versionNo);
354
+ }
355
+ catch (error) {
356
+ if (error instanceof AppError && error.code === "SYNC_CHANGE_HISTORY_MISSING")
357
+ return null;
358
+ throw error;
359
+ }
360
+ }
361
+ parseMutationResult(value) {
362
+ try {
363
+ const parsed = JSON.parse(value);
364
+ if (!parsed || typeof parsed !== "object" || !parsed.mutationId || !parsed.entityId)
365
+ throw new Error("Invalid mutation result");
366
+ if (!["applied", "conflict", "rejected"].includes(parsed.status)) {
367
+ throw new Error("Invalid mutation status");
368
+ }
369
+ return { ...parsed, replayed: false };
370
+ }
371
+ catch {
372
+ throw new AppError(500, "SYNC_MUTATION_RESULT_INVALID", "同步变更结果无法解析");
373
+ }
374
+ }
375
+ chapterVersionData(chapterId, versionNo) {
376
+ const version = this.database.get(`SELECT work_id, chapter_id, version_no, title, content, volume_id, sort_order, chapter_type, created_at
377
+ FROM chapter_versions WHERE chapter_id = ? AND version_no = ?`, chapterId, versionNo);
378
+ if (!version) {
379
+ throw new AppError(500, "SYNC_CHANGE_HISTORY_MISSING", "章节同步历史不完整,请重新下载离线副本");
380
+ }
381
+ const content = String(version.content);
382
+ return {
383
+ id: String(version.chapter_id),
384
+ workId: String(version.work_id),
385
+ volumeId: version.volume_id === null || version.volume_id === undefined ? null : String(version.volume_id),
386
+ title: String(version.title),
387
+ content,
388
+ chapterType: String(version.chapter_type ?? "正文"),
389
+ sortOrder: version.sort_order === null || version.sort_order === undefined ? null : Number(version.sort_order),
390
+ wordCount: countWords(content),
391
+ versionNo: Number(version.version_no),
392
+ updatedAt: String(version.created_at)
393
+ };
394
+ }
395
+ settingVersionData(settingId, versionNo) {
396
+ const version = this.database.get(`SELECT work_id, entity_id, version_no, snapshot_json, created_at
397
+ FROM entity_versions WHERE entity_type = 'setting' AND entity_id = ? AND version_no = ?`, settingId, versionNo);
398
+ if (!version) {
399
+ throw new AppError(500, "SYNC_CHANGE_HISTORY_MISSING", "设定同步历史不完整,请重新下载离线副本");
400
+ }
401
+ let snapshot;
402
+ try {
403
+ const parsed = JSON.parse(String(version.snapshot_json));
404
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
405
+ throw new Error("Invalid setting snapshot");
406
+ snapshot = parsed;
407
+ }
408
+ catch {
409
+ throw new AppError(500, "SYNC_CHANGE_HISTORY_INVALID", "设定同步历史无法解析,请重新下载离线副本");
410
+ }
411
+ return {
412
+ id: String(version.entity_id),
413
+ workId: String(version.work_id),
414
+ ...snapshot,
415
+ versionNo: Number(version.version_no),
416
+ updatedAt: String(version.created_at)
417
+ };
418
+ }
419
+ pruneExpired(timestamp) {
420
+ for (const [snapshotId, snapshot] of this.snapshots) {
421
+ if (snapshot.expiresAtMs <= timestamp)
422
+ this.snapshots.delete(snapshotId);
423
+ }
424
+ }
425
+ descriptor(snapshot) {
426
+ return {
427
+ snapshotId: snapshot.snapshotId,
428
+ workId: snapshot.workId,
429
+ cutoffCursor: snapshot.cutoffCursor,
430
+ itemCount: snapshot.itemCount,
431
+ expiresAt: snapshot.expiresAt,
432
+ syncProtocol: 1
433
+ };
434
+ }
435
+ }
436
+ //# sourceMappingURL=offline-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offline-sync.js","sourceRoot":"","sources":["../src/offline-sync.ts"],"names":[],"mappings":"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"}
@@ -35,9 +35,12 @@ export function connectivityTestResultToast(result, objectType) {
35
35
  }
36
36
  if (source.ok === true) {
37
37
  const imageNotice = objectType === "model" && source.multimodalTested === true ? ",图片请求已验证" : "";
38
+ const privateHint = source.privateNetworkAllowed === true
39
+ ? ";当前地址指向本机或内网,已允许连接,请确认该地址可信"
40
+ : "";
38
41
  return {
39
- message: `${label}连接测试成功${imageNotice};接下来 2 分钟内不能再次测试${retryTimeText(cooldown.retryAt)}`,
40
- type: "info"
42
+ message: `${label}连接测试成功${imageNotice}${privateHint};接下来 2 分钟内不能再次测试${retryTimeText(cooldown.retryAt)}`,
43
+ type: privateHint ? "warning" : "info"
41
44
  };
42
45
  }
43
46
  const failure = typeof source.error === "string" && source.error ? source.error : "未知错误";