ducjs 3.0.3 → 3.0.5
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/ducjs_wasm.d.ts +148 -0
- package/dist/ducjs_wasm.js +850 -0
- package/dist/ducjs_wasm_bg.wasm +0 -0
- package/dist/ducjs_wasm_bg.wasm.d.ts +34 -0
- package/dist/parse.js +21 -2
- package/dist/restore/restoreDataState.js +21 -10
- package/dist/serialize.js +102 -6
- package/dist/version-control.d.ts +26 -0
- package/dist/version-control.js +33 -1
- package/dist/wasm.d.ts +3 -1
- package/dist/wasm.js +4 -2
- package/package.json +1 -2
|
Binary file
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const applyDeltaChangeset: (a: number, b: number, c: number, d: number) => [number, number, number, number];
|
|
5
|
+
export const createDeltaChangeset: (a: number, b: number, c: number, d: number) => [number, number, number, number];
|
|
6
|
+
export const getCurrentSchemaVersion: () => number;
|
|
7
|
+
export const getExternalFile: (a: number, b: number, c: number, d: number) => [number, number, number];
|
|
8
|
+
export const listExternalFiles: (a: number, b: number) => [number, number, number];
|
|
9
|
+
export const listVersions: (a: number, b: number) => [number, number, number];
|
|
10
|
+
export const parseDuc: (a: number, b: number) => [number, number, number];
|
|
11
|
+
export const parseDucLazy: (a: number, b: number) => [number, number, number];
|
|
12
|
+
export const readVersionGraph: (a: number, b: number) => [number, number, number];
|
|
13
|
+
export const restoreCheckpoint: (a: number, b: number, c: number, d: number) => [number, number, number];
|
|
14
|
+
export const restoreVersion: (a: number, b: number, c: number) => [number, number, number];
|
|
15
|
+
export const revertToVersion: (a: number, b: number, c: number) => [number, number, number];
|
|
16
|
+
export const serializeDuc: (a: any) => [number, number, number, number];
|
|
17
|
+
export const rust_sqlite_wasm_abort: () => void;
|
|
18
|
+
export const rust_sqlite_wasm_assert_fail: (a: number, b: number, c: number, d: number) => void;
|
|
19
|
+
export const rust_sqlite_wasm_calloc: (a: number, b: number) => number;
|
|
20
|
+
export const rust_sqlite_wasm_malloc: (a: number) => number;
|
|
21
|
+
export const rust_sqlite_wasm_free: (a: number) => void;
|
|
22
|
+
export const rust_sqlite_wasm_getentropy: (a: number, b: number) => number;
|
|
23
|
+
export const rust_sqlite_wasm_localtime: (a: number) => number;
|
|
24
|
+
export const rust_sqlite_wasm_realloc: (a: number, b: number) => number;
|
|
25
|
+
export const sqlite3_os_end: () => number;
|
|
26
|
+
export const sqlite3_os_init: () => number;
|
|
27
|
+
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
28
|
+
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
29
|
+
export const __wbindgen_exn_store: (a: number) => void;
|
|
30
|
+
export const __externref_table_alloc: () => number;
|
|
31
|
+
export const __wbindgen_export_4: WebAssembly.Table;
|
|
32
|
+
export const __externref_table_dealloc: (a: number) => void;
|
|
33
|
+
export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
34
|
+
export const __wbindgen_start: () => void;
|
package/dist/parse.js
CHANGED
|
@@ -40,7 +40,18 @@ export function parseDuc(blob, _fileHandle, elementsConfig, restoreConfig) {
|
|
|
40
40
|
throw new Error(`[parseDuc] wasm parse failed (size=${buffer.byteLength}, header="${header}", prefix=${prefixHex}): ${error instanceof Error ? error.message : String(error)}`);
|
|
41
41
|
}
|
|
42
42
|
const data = transformFromRust(raw);
|
|
43
|
-
|
|
43
|
+
// Preserve the original version graph from Rust before restore() can
|
|
44
|
+
// filter out entries through restoreCheckpoint/restoreDelta validation.
|
|
45
|
+
// The VG data is already validated by the Rust parser.
|
|
46
|
+
const originalVG = data.versionGraph;
|
|
47
|
+
const restored = restore(Object.assign(Object.assign({}, data), {
|
|
48
|
+
// Preserve versionGraph from Rust separately; do not run it through restore()
|
|
49
|
+
versionGraph: undefined }), elementsConfig !== null && elementsConfig !== void 0 ? elementsConfig : { syncInvalidIndices: (els) => els }, restoreConfig);
|
|
50
|
+
// Use the original version graph from Rust, bypassing restore's lossy filtering
|
|
51
|
+
if (originalVG) {
|
|
52
|
+
restored.versionGraph = originalVG;
|
|
53
|
+
}
|
|
54
|
+
return restored;
|
|
44
55
|
});
|
|
45
56
|
}
|
|
46
57
|
/**
|
|
@@ -65,10 +76,18 @@ export function parseDucLazy(buffer, elementsConfig, restoreConfig) {
|
|
|
65
76
|
throw new Error(`[parseDucLazy] wasm parse failed (size=${buffer.byteLength}, header="${header}", prefix=${prefixHex}): ${error instanceof Error ? error.message : String(error)}`);
|
|
66
77
|
}
|
|
67
78
|
const data = transformFromRust(raw);
|
|
79
|
+
// Preserve the original version graph from Rust before restore() filters
|
|
80
|
+
const originalVG = data.versionGraph;
|
|
68
81
|
const lazyFileStore = new LazyExternalFileStore(buffer);
|
|
69
82
|
const files = {};
|
|
70
|
-
const restored = restore(Object.assign(Object.assign({}, data), { files
|
|
83
|
+
const restored = restore(Object.assign(Object.assign({}, data), { files,
|
|
84
|
+
// Preserve versionGraph from Rust separately; do not run it through restore()
|
|
85
|
+
versionGraph: undefined }), elementsConfig !== null && elementsConfig !== void 0 ? elementsConfig : { syncInvalidIndices: (els) => els }, restoreConfig);
|
|
71
86
|
restored.lazyFileStore = lazyFileStore;
|
|
87
|
+
// Use the original version graph from Rust, bypassing restore's lossy filtering
|
|
88
|
+
if (originalVG) {
|
|
89
|
+
restored.versionGraph = originalVG;
|
|
90
|
+
}
|
|
72
91
|
return restored;
|
|
73
92
|
});
|
|
74
93
|
}
|
|
@@ -367,11 +367,6 @@ export const restoreVersionGraph = (importedGraph) => {
|
|
|
367
367
|
if (!importedGraph || typeof importedGraph !== "object") {
|
|
368
368
|
return undefined;
|
|
369
369
|
}
|
|
370
|
-
const userCheckpointVersionId = isValidString(importedGraph.userCheckpointVersionId);
|
|
371
|
-
const latestVersionId = isValidString(importedGraph.latestVersionId);
|
|
372
|
-
if (!userCheckpointVersionId || !latestVersionId) {
|
|
373
|
-
return undefined;
|
|
374
|
-
}
|
|
375
370
|
const checkpoints = Array.isArray(importedGraph.checkpoints)
|
|
376
371
|
? importedGraph.checkpoints
|
|
377
372
|
.map((checkpoint) => restoreCheckpoint(checkpoint))
|
|
@@ -382,6 +377,17 @@ export const restoreVersionGraph = (importedGraph) => {
|
|
|
382
377
|
.map((delta) => restoreDelta(delta))
|
|
383
378
|
.filter((delta) => Boolean(delta))
|
|
384
379
|
: [];
|
|
380
|
+
if (checkpoints.length === 0 && deltas.length === 0) {
|
|
381
|
+
return undefined;
|
|
382
|
+
}
|
|
383
|
+
// Head IDs can legitimately be empty strings (e.g. after Rust roundtrip
|
|
384
|
+
// where the DB stores NULL → unwrap_or_default → ""). Accept any string.
|
|
385
|
+
const userCheckpointVersionId = typeof importedGraph.userCheckpointVersionId === "string"
|
|
386
|
+
? importedGraph.userCheckpointVersionId
|
|
387
|
+
: "";
|
|
388
|
+
const latestVersionId = typeof importedGraph.latestVersionId === "string"
|
|
389
|
+
? importedGraph.latestVersionId
|
|
390
|
+
: "";
|
|
385
391
|
const importedMetadata = importedGraph.metadata;
|
|
386
392
|
const metadata = {
|
|
387
393
|
currentVersion: isFiniteNumber(importedMetadata === null || importedMetadata === void 0 ? void 0 : importedMetadata.currentVersion) && importedMetadata.currentVersion >= 0
|
|
@@ -411,6 +417,7 @@ export const restoreVersionGraph = (importedGraph) => {
|
|
|
411
417
|
};
|
|
412
418
|
};
|
|
413
419
|
export const restoreCheckpoint = (importedCheckpoint) => {
|
|
420
|
+
var _a, _b, _c;
|
|
414
421
|
if (!importedCheckpoint || typeof importedCheckpoint !== "object") {
|
|
415
422
|
return undefined;
|
|
416
423
|
}
|
|
@@ -419,10 +426,11 @@ export const restoreCheckpoint = (importedCheckpoint) => {
|
|
|
419
426
|
return undefined;
|
|
420
427
|
}
|
|
421
428
|
const id = isValidString(checkpoint.id);
|
|
422
|
-
|
|
423
|
-
if (!id || !data) {
|
|
429
|
+
if (!id) {
|
|
424
430
|
return undefined;
|
|
425
431
|
}
|
|
432
|
+
// Accept empty Uint8Array — shell/remote entries have byteLength === 0
|
|
433
|
+
const data = (_c = (_b = (_a = isValidUint8Array(checkpoint.data)) !== null && _a !== void 0 ? _a : (checkpoint.data instanceof Uint8Array ? checkpoint.data : undefined)) !== null && _b !== void 0 ? _b : (checkpoint.data instanceof ArrayBuffer ? new Uint8Array(checkpoint.data) : undefined)) !== null && _c !== void 0 ? _c : new Uint8Array(0);
|
|
426
434
|
return {
|
|
427
435
|
type: "checkpoint",
|
|
428
436
|
id,
|
|
@@ -443,6 +451,7 @@ export const restoreCheckpoint = (importedCheckpoint) => {
|
|
|
443
451
|
};
|
|
444
452
|
};
|
|
445
453
|
export const restoreDelta = (importedDelta) => {
|
|
454
|
+
var _a, _b, _c;
|
|
446
455
|
if (!importedDelta || typeof importedDelta !== "object") {
|
|
447
456
|
return undefined;
|
|
448
457
|
}
|
|
@@ -451,11 +460,13 @@ export const restoreDelta = (importedDelta) => {
|
|
|
451
460
|
return undefined;
|
|
452
461
|
}
|
|
453
462
|
const id = isValidString(delta.id);
|
|
454
|
-
|
|
455
|
-
const baseCheckpointId = isValidString(delta.baseCheckpointId);
|
|
456
|
-
if (!id || !payload || !baseCheckpointId) {
|
|
463
|
+
if (!id) {
|
|
457
464
|
return undefined;
|
|
458
465
|
}
|
|
466
|
+
// Accept empty Uint8Array — shell/remote entries have byteLength === 0
|
|
467
|
+
const payload = (_c = (_b = (_a = isValidUint8Array(delta.payload)) !== null && _a !== void 0 ? _a : (delta.payload instanceof Uint8Array ? delta.payload : undefined)) !== null && _b !== void 0 ? _b : (delta.payload instanceof ArrayBuffer ? new Uint8Array(delta.payload) : undefined)) !== null && _c !== void 0 ? _c : new Uint8Array(0);
|
|
468
|
+
// baseCheckpointId can be empty for shell entries or first-in-chain deltas
|
|
469
|
+
const baseCheckpointId = typeof delta.baseCheckpointId === "string" ? delta.baseCheckpointId : "";
|
|
459
470
|
return {
|
|
460
471
|
type: "delta",
|
|
461
472
|
id,
|
package/dist/serialize.js
CHANGED
|
@@ -33,15 +33,111 @@ export function serializeDuc(data, elementsConfig, restoreConfig) {
|
|
|
33
33
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
34
|
var _a, _b, _c, _d;
|
|
35
35
|
yield ensureWasm();
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const inputVG = data === null || data === void 0 ? void 0 : data.versionGraph;
|
|
37
|
+
const restored = restore(Object.assign(Object.assign({}, data), {
|
|
38
|
+
// Version graph is preserved separately — bypass restore()'s VG processing.
|
|
39
|
+
versionGraph: undefined }), elementsConfig !== null && elementsConfig !== void 0 ? elementsConfig : { syncInvalidIndices: (els) => els }, restoreConfig);
|
|
40
|
+
const shouldDropLegacyVersionGraph = hasLegacyVersionGraphShape(inputVG);
|
|
41
|
+
// Use the ORIGINAL version graph data instead of the restored one.
|
|
42
|
+
// The restore pipeline (restoreCheckpoint/restoreDelta) filters checkpoints
|
|
43
|
+
// and deltas through isValidUint8Array which can reject valid in-memory
|
|
44
|
+
// Uint8Array data (e.g. empty remote placeholders or detached buffers),
|
|
45
|
+
// silently dropping version history.
|
|
46
|
+
// hasLegacyVersionGraphShape already validates structural integrity.
|
|
47
|
+
const versionGraphForPayload = shouldDropLegacyVersionGraph
|
|
48
|
+
? undefined
|
|
49
|
+
: prepareVersionGraphForSerialization(inputVG);
|
|
50
|
+
const normalizedVersionGraphForPayload = versionGraphForPayload
|
|
51
|
+
? normalizeVersionGraphVersionNumbers(versionGraphForPayload)
|
|
52
|
+
: undefined;
|
|
53
|
+
const payloadForRust = Object.assign(Object.assign({ type: (_a = data.type) !== null && _a !== void 0 ? _a : "duc", version: (_c = (_b = data.version) !== null && _b !== void 0 ? _b : DUC_SCHEMA_VERSION) !== null && _c !== void 0 ? _c : decodeUserVersionToSemver(wasmGetCurrentSchemaVersion()), source: (_d = data.source) !== null && _d !== void 0 ? _d : "ducjs" }, restored), { versionGraph: normalizedVersionGraphForPayload });
|
|
41
54
|
const prepared = transformToRust(payloadForRust);
|
|
42
|
-
|
|
55
|
+
const serialized = wasmSerializeDuc(prepared);
|
|
56
|
+
return serialized;
|
|
43
57
|
});
|
|
44
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Ensure version numbers are unique before persistence.
|
|
61
|
+
* SQLite schema enforces UNIQUE(version_number) on both checkpoints and deltas.
|
|
62
|
+
* Collisions would otherwise cause INSERT OR REPLACE to drop historical entries.
|
|
63
|
+
*/
|
|
64
|
+
function normalizeVersionGraphVersionNumbers(vg) {
|
|
65
|
+
var _a;
|
|
66
|
+
const normalizeList = (items) => {
|
|
67
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const sorted = [...items].sort((a, b) => {
|
|
71
|
+
const aNum = Number.isFinite(a === null || a === void 0 ? void 0 : a.versionNumber) ? Number(a.versionNumber) : Number.MAX_SAFE_INTEGER;
|
|
72
|
+
const bNum = Number.isFinite(b === null || b === void 0 ? void 0 : b.versionNumber) ? Number(b.versionNumber) : Number.MAX_SAFE_INTEGER;
|
|
73
|
+
if (aNum !== bNum)
|
|
74
|
+
return aNum - bNum;
|
|
75
|
+
const aTs = Number.isFinite(a === null || a === void 0 ? void 0 : a.timestamp) ? Number(a.timestamp) : 0;
|
|
76
|
+
const bTs = Number.isFinite(b === null || b === void 0 ? void 0 : b.timestamp) ? Number(b.timestamp) : 0;
|
|
77
|
+
if (aTs !== bTs)
|
|
78
|
+
return aTs - bTs;
|
|
79
|
+
const aId = typeof (a === null || a === void 0 ? void 0 : a.id) === "string" ? a.id : "";
|
|
80
|
+
const bId = typeof (b === null || b === void 0 ? void 0 : b.id) === "string" ? b.id : "";
|
|
81
|
+
return aId.localeCompare(bId);
|
|
82
|
+
});
|
|
83
|
+
let nextVersion = 0;
|
|
84
|
+
return sorted.map((item) => {
|
|
85
|
+
const candidate = Number.isFinite(item === null || item === void 0 ? void 0 : item.versionNumber) ? Number(item.versionNumber) : nextVersion;
|
|
86
|
+
const assigned = Math.max(candidate, nextVersion);
|
|
87
|
+
nextVersion = assigned + 1;
|
|
88
|
+
return Object.assign(Object.assign({}, item), { versionNumber: assigned });
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
const checkpoints = normalizeList(Array.isArray(vg === null || vg === void 0 ? void 0 : vg.checkpoints) ? vg.checkpoints : []);
|
|
92
|
+
const deltas = normalizeList(Array.isArray(vg === null || vg === void 0 ? void 0 : vg.deltas) ? vg.deltas : []);
|
|
93
|
+
const maxCheckpointVersion = checkpoints.length
|
|
94
|
+
? Math.max(...checkpoints.map((cp) => Number(cp.versionNumber) || 0))
|
|
95
|
+
: 0;
|
|
96
|
+
const maxDeltaVersion = deltas.length
|
|
97
|
+
? Math.max(...deltas.map((d) => Number(d.versionNumber) || 0))
|
|
98
|
+
: 0;
|
|
99
|
+
const maxVersion = Math.max(maxCheckpointVersion, maxDeltaVersion, 0);
|
|
100
|
+
return Object.assign(Object.assign({}, vg), { checkpoints,
|
|
101
|
+
deltas, metadata: Object.assign(Object.assign({}, vg.metadata), { currentVersion: Number.isFinite((_a = vg === null || vg === void 0 ? void 0 : vg.metadata) === null || _a === void 0 ? void 0 : _a.currentVersion)
|
|
102
|
+
? Math.max(Number(vg.metadata.currentVersion), maxVersion)
|
|
103
|
+
: maxVersion }) });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Prepares version graph for serialization by filtering out shell entries
|
|
107
|
+
* (remote placeholders with empty data/payload) while preserving all entries
|
|
108
|
+
* with actual binary data intact.
|
|
109
|
+
*/
|
|
110
|
+
function prepareVersionGraphForSerialization(vg) {
|
|
111
|
+
if (!vg || typeof vg !== "object")
|
|
112
|
+
return undefined;
|
|
113
|
+
const checkpoints = Array.isArray(vg.checkpoints)
|
|
114
|
+
? vg.checkpoints.filter((cp) => {
|
|
115
|
+
const data = cp === null || cp === void 0 ? void 0 : cp.data;
|
|
116
|
+
if (data instanceof Uint8Array)
|
|
117
|
+
return data.byteLength > 0;
|
|
118
|
+
if (data instanceof ArrayBuffer)
|
|
119
|
+
return data.byteLength > 0;
|
|
120
|
+
// Accept base64 strings (from JSON imports)
|
|
121
|
+
if (typeof data === "string" && data.length > 0)
|
|
122
|
+
return true;
|
|
123
|
+
return false;
|
|
124
|
+
})
|
|
125
|
+
: [];
|
|
126
|
+
const deltas = Array.isArray(vg.deltas)
|
|
127
|
+
? vg.deltas.filter((d) => {
|
|
128
|
+
const payload = d === null || d === void 0 ? void 0 : d.payload;
|
|
129
|
+
if (payload instanceof Uint8Array)
|
|
130
|
+
return payload.byteLength > 0;
|
|
131
|
+
if (payload instanceof ArrayBuffer)
|
|
132
|
+
return payload.byteLength > 0;
|
|
133
|
+
if (typeof payload === "string" && payload.length > 0)
|
|
134
|
+
return true;
|
|
135
|
+
return false;
|
|
136
|
+
})
|
|
137
|
+
: [];
|
|
138
|
+
return Object.assign(Object.assign({}, vg), { checkpoints,
|
|
139
|
+
deltas });
|
|
140
|
+
}
|
|
45
141
|
function hasLegacyVersionGraphShape(versionGraph) {
|
|
46
142
|
if (!versionGraph || typeof versionGraph !== "object") {
|
|
47
143
|
return false;
|
|
@@ -59,3 +59,29 @@ export declare const revertToVersion: (ducBuffer: Uint8Array, targetVersion: num
|
|
|
59
59
|
* on the next checkpoint or delta creation.
|
|
60
60
|
*/
|
|
61
61
|
export declare const getCurrentSchemaVersion: () => Promise<number>;
|
|
62
|
+
/**
|
|
63
|
+
* Compute a checkpoint-relative binary diff changeset using bsdiff.
|
|
64
|
+
*
|
|
65
|
+
* `baseState` is the checkpoint's full data blob (the snapshot at the
|
|
66
|
+
* base checkpoint version). `currentState` is the full document state
|
|
67
|
+
* at the new version being saved as a delta.
|
|
68
|
+
*
|
|
69
|
+
* Returns an encoded changeset (`Uint8Array`) suitable for use as
|
|
70
|
+
* `Delta.payload`. bsdiff finds matching blocks even when they shift
|
|
71
|
+
* offsets, which is critical for SQLite databases where internal page
|
|
72
|
+
* reordering makes simple byte-level diffs ineffective.
|
|
73
|
+
*
|
|
74
|
+
* Use this when constructing `Delta` objects for the `VersionGraph`
|
|
75
|
+
* before calling `serializeDuc()`.
|
|
76
|
+
*/
|
|
77
|
+
export declare const createDeltaChangeset: (baseState: Uint8Array, currentState: Uint8Array) => Promise<Uint8Array>;
|
|
78
|
+
/**
|
|
79
|
+
* Apply a changeset to reconstruct document state.
|
|
80
|
+
*
|
|
81
|
+
* `baseState` must be the exact checkpoint data used when the changeset
|
|
82
|
+
* was created. Returns the full document state as `Uint8Array`.
|
|
83
|
+
*
|
|
84
|
+
* Handles all changeset formats transparently:
|
|
85
|
+
* - v3 (bsdiff), v2 (XOR diff), v1 (zlib full snapshot)
|
|
86
|
+
*/
|
|
87
|
+
export declare const applyDeltaChangeset: (baseState: Uint8Array, changeset: Uint8Array) => Promise<Uint8Array>;
|
package/dist/version-control.js
CHANGED
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { ensureWasm, wasmGetCurrentSchemaVersion, wasmListVersions, wasmReadVersionGraph, wasmRestoreCheckpoint, wasmRestoreVersion, wasmRevertToVersion, } from "./wasm";
|
|
10
|
+
import { ensureWasm, wasmApplyDeltaChangeset, wasmCreateDeltaChangeset, wasmGetCurrentSchemaVersion, wasmListVersions, wasmReadVersionGraph, wasmRestoreCheckpoint, wasmRestoreVersion, wasmRevertToVersion, } from "./wasm";
|
|
11
11
|
/**
|
|
12
12
|
* Restore the full document state at a specific version number.
|
|
13
13
|
*
|
|
@@ -82,3 +82,35 @@ export const getCurrentSchemaVersion = () => __awaiter(void 0, void 0, void 0, f
|
|
|
82
82
|
yield ensureWasm();
|
|
83
83
|
return wasmGetCurrentSchemaVersion();
|
|
84
84
|
});
|
|
85
|
+
/**
|
|
86
|
+
* Compute a checkpoint-relative binary diff changeset using bsdiff.
|
|
87
|
+
*
|
|
88
|
+
* `baseState` is the checkpoint's full data blob (the snapshot at the
|
|
89
|
+
* base checkpoint version). `currentState` is the full document state
|
|
90
|
+
* at the new version being saved as a delta.
|
|
91
|
+
*
|
|
92
|
+
* Returns an encoded changeset (`Uint8Array`) suitable for use as
|
|
93
|
+
* `Delta.payload`. bsdiff finds matching blocks even when they shift
|
|
94
|
+
* offsets, which is critical for SQLite databases where internal page
|
|
95
|
+
* reordering makes simple byte-level diffs ineffective.
|
|
96
|
+
*
|
|
97
|
+
* Use this when constructing `Delta` objects for the `VersionGraph`
|
|
98
|
+
* before calling `serializeDuc()`.
|
|
99
|
+
*/
|
|
100
|
+
export const createDeltaChangeset = (baseState, currentState) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
|
+
yield ensureWasm();
|
|
102
|
+
return wasmCreateDeltaChangeset(baseState, currentState);
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* Apply a changeset to reconstruct document state.
|
|
106
|
+
*
|
|
107
|
+
* `baseState` must be the exact checkpoint data used when the changeset
|
|
108
|
+
* was created. Returns the full document state as `Uint8Array`.
|
|
109
|
+
*
|
|
110
|
+
* Handles all changeset formats transparently:
|
|
111
|
+
* - v3 (bsdiff), v2 (XOR diff), v1 (zlib full snapshot)
|
|
112
|
+
*/
|
|
113
|
+
export const applyDeltaChangeset = (baseState, changeset) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
+
yield ensureWasm();
|
|
115
|
+
return wasmApplyDeltaChangeset(baseState, changeset);
|
|
116
|
+
});
|
package/dist/wasm.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCurrentSchemaVersion as _getCurrentSchemaVersion, getExternalFile as _getExternalFile, listExternalFiles as _listExternalFiles, listVersions as _listVersions, parseDuc as _parseDuc, parseDucLazy as _parseDucLazy, readVersionGraph as _readVersionGraph, restoreCheckpoint as _restoreCheckpoint, restoreVersion as _restoreVersion, revertToVersion as _revertToVersion, serializeDuc as _serializeDuc } from "../
|
|
1
|
+
import { applyDeltaChangeset as _applyDeltaChangeset, createDeltaChangeset as _createDeltaChangeset, getCurrentSchemaVersion as _getCurrentSchemaVersion, getExternalFile as _getExternalFile, listExternalFiles as _listExternalFiles, listVersions as _listVersions, parseDuc as _parseDuc, parseDucLazy as _parseDucLazy, readVersionGraph as _readVersionGraph, restoreCheckpoint as _restoreCheckpoint, restoreVersion as _restoreVersion, revertToVersion as _revertToVersion, serializeDuc as _serializeDuc } from "../dist/ducjs_wasm";
|
|
2
2
|
export declare function ensureWasm(wasmUrl?: string | URL | BufferSource): Promise<void>;
|
|
3
3
|
/**
|
|
4
4
|
* Fetch the raw WASM binary as an ArrayBuffer.
|
|
@@ -18,3 +18,5 @@ export declare const wasmListVersions: typeof _listVersions;
|
|
|
18
18
|
export declare const wasmReadVersionGraph: typeof _readVersionGraph;
|
|
19
19
|
export declare const wasmRevertToVersion: typeof _revertToVersion;
|
|
20
20
|
export declare const wasmGetCurrentSchemaVersion: typeof _getCurrentSchemaVersion;
|
|
21
|
+
export declare const wasmCreateDeltaChangeset: typeof _createDeltaChangeset;
|
|
22
|
+
export declare const wasmApplyDeltaChangeset: typeof _applyDeltaChangeset;
|
package/dist/wasm.js
CHANGED
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import init, { getCurrentSchemaVersion as _getCurrentSchemaVersion, getExternalFile as _getExternalFile, listExternalFiles as _listExternalFiles, listVersions as _listVersions, parseDuc as _parseDuc, parseDucLazy as _parseDucLazy, readVersionGraph as _readVersionGraph, restoreCheckpoint as _restoreCheckpoint, restoreVersion as _restoreVersion, revertToVersion as _revertToVersion, serializeDuc as _serializeDuc, } from "../
|
|
10
|
+
import init, { applyDeltaChangeset as _applyDeltaChangeset, createDeltaChangeset as _createDeltaChangeset, getCurrentSchemaVersion as _getCurrentSchemaVersion, getExternalFile as _getExternalFile, listExternalFiles as _listExternalFiles, listVersions as _listVersions, parseDuc as _parseDuc, parseDucLazy as _parseDucLazy, readVersionGraph as _readVersionGraph, restoreCheckpoint as _restoreCheckpoint, restoreVersion as _restoreVersion, revertToVersion as _revertToVersion, serializeDuc as _serializeDuc, } from "../dist/ducjs_wasm";
|
|
11
11
|
let initialized = false;
|
|
12
12
|
let initPromise = null;
|
|
13
13
|
export function ensureWasm(wasmUrl) {
|
|
@@ -31,7 +31,7 @@ export function ensureWasm(wasmUrl) {
|
|
|
31
31
|
*/
|
|
32
32
|
export function getWasmBinary() {
|
|
33
33
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
const url = new URL('../
|
|
34
|
+
const url = new URL('../dist/ducjs_wasm_bg.wasm', import.meta.url);
|
|
35
35
|
const resp = yield fetch(url);
|
|
36
36
|
if (!resp.ok) {
|
|
37
37
|
throw new Error(`Failed to fetch WASM binary: ${resp.status} ${resp.statusText}`);
|
|
@@ -50,3 +50,5 @@ export const wasmListVersions = _listVersions;
|
|
|
50
50
|
export const wasmReadVersionGraph = _readVersionGraph;
|
|
51
51
|
export const wasmRevertToVersion = _revertToVersion;
|
|
52
52
|
export const wasmGetCurrentSchemaVersion = _getCurrentSchemaVersion;
|
|
53
|
+
export const wasmCreateDeltaChangeset = _createDeltaChangeset;
|
|
54
|
+
export const wasmApplyDeltaChangeset = _applyDeltaChangeset;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ducjs",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "The duc 2D CAD file format is a cornerstone of our advanced design system, conceived to cater to professionals seeking precision and efficiency in their design work.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
},
|
|
54
54
|
"files": [
|
|
55
55
|
"dist",
|
|
56
|
-
"pkg",
|
|
57
56
|
"README.md"
|
|
58
57
|
],
|
|
59
58
|
"publishConfig": {
|