@prestizni-software/server-dem 0.6.5 → 0.6.7
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/AutoUpdateServerManagerClass.d.ts +6 -1
- package/dist/AutoUpdateServerManagerClass.js +120 -1
- package/dist/AutoUpdateServerManagerClass.js.map +1 -1
- package/dist/AutoUpdatedServerObjectClass.d.ts +8 -0
- package/dist/AutoUpdatedServerObjectClass.js +31 -0
- package/dist/AutoUpdatedServerObjectClass.js.map +1 -1
- package/dist/CommonTypes.d.ts +7 -1
- package/dist/CommonTypes.js +7 -0
- package/dist/CommonTypes.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/sync/ClientStateReconciler.d.ts +41 -0
- package/dist/sync/ClientStateReconciler.js +162 -0
- package/dist/sync/ClientStateReconciler.js.map +1 -0
- package/dist/sync/ServerChangeTracker.d.ts +50 -0
- package/dist/sync/ServerChangeTracker.js +181 -0
- package/dist/sync/ServerChangeTracker.js.map +1 -0
- package/dist/sync/index.d.ts +7 -0
- package/dist/sync/index.js +8 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/storage/IClientStorageAdapter.d.ts +23 -0
- package/dist/sync/storage/IClientStorageAdapter.js +2 -0
- package/dist/sync/storage/IClientStorageAdapter.js.map +1 -0
- package/dist/sync/storage/IndexedDbStorageAdapter.d.ts +22 -0
- package/dist/sync/storage/IndexedDbStorageAdapter.js +125 -0
- package/dist/sync/storage/IndexedDbStorageAdapter.js.map +1 -0
- package/dist/sync/storage/LocalStorageAdapter.d.ts +27 -0
- package/dist/sync/storage/LocalStorageAdapter.js +85 -0
- package/dist/sync/storage/LocalStorageAdapter.js.map +1 -0
- package/dist/sync/storage/MemoryStorageAdapter.d.ts +13 -0
- package/dist/sync/storage/MemoryStorageAdapter.js +25 -0
- package/dist/sync/storage/MemoryStorageAdapter.js.map +1 -0
- package/dist/sync/types.d.ts +67 -0
- package/dist/sync/types.js +5 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { globalCache } from "../CommonTypes.js";
|
|
2
|
+
export class ClientStateReconciler {
|
|
3
|
+
/**
|
|
4
|
+
* Restores client manager objects in-memory from a persistent storage adapter.
|
|
5
|
+
*/
|
|
6
|
+
static async restoreFromStorage(manager, storageAdapter) {
|
|
7
|
+
try {
|
|
8
|
+
const state = await storageAdapter.loadManagerState(manager.className);
|
|
9
|
+
if (!state || !Array.isArray(state.ids) || state.ids.length === 0) {
|
|
10
|
+
return { restored: false, revision: state?.revision ?? 0, count: 0 };
|
|
11
|
+
}
|
|
12
|
+
// Clear existing in-memory objects for this manager
|
|
13
|
+
for (const oldId of Object.keys(manager.objects_)) {
|
|
14
|
+
delete globalCache.objects[oldId];
|
|
15
|
+
}
|
|
16
|
+
manager.objects_ = {};
|
|
17
|
+
const objectMap = new Map();
|
|
18
|
+
if (state.objects) {
|
|
19
|
+
for (const objData of state.objects) {
|
|
20
|
+
if (objData?._id) {
|
|
21
|
+
objectMap.set(objData._id.toString(), objData);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (const id of state.ids) {
|
|
26
|
+
const objData = objectMap.get(id);
|
|
27
|
+
const instance = new manager.classParam(manager.classParam, manager.socket, objData || id, manager.loggers, manager.className, manager, manager.callbacks, manager.emitter);
|
|
28
|
+
manager.objects_[id] = instance;
|
|
29
|
+
globalCache.objects[id] = {
|
|
30
|
+
className: manager.className,
|
|
31
|
+
object: instance,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
manager.totalObjects = state.ids.length;
|
|
35
|
+
manager.loadedObjects = state.ids.length;
|
|
36
|
+
manager.isLoaded_ = true;
|
|
37
|
+
if ("_cachedObjectsArray" in manager) {
|
|
38
|
+
manager._cachedObjectsArray = null;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
restored: true,
|
|
42
|
+
revision: state.revision,
|
|
43
|
+
count: state.ids.length,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
manager.loggers?.warn?.(`Failed to restore ${manager.className} from storage: ${err instanceof Error ? err.message : String(err)}`);
|
|
48
|
+
return { restored: false, revision: 0, count: 0 };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Persists current manager in-memory state to storage adapter.
|
|
53
|
+
*/
|
|
54
|
+
static async persistToStorage(manager, revision, storageAdapter) {
|
|
55
|
+
try {
|
|
56
|
+
const objectsAsArray = manager.objectsAsArray;
|
|
57
|
+
const ids = objectsAsArray.map((o) => (o._id ? o._id.toString() : o.data?._id?.toString())).filter(Boolean);
|
|
58
|
+
const objects = objectsAsArray.map((o) => {
|
|
59
|
+
if (typeof o.extractedData !== "undefined") {
|
|
60
|
+
return o.extractedData;
|
|
61
|
+
}
|
|
62
|
+
return o.data || { _id: o._id ? o._id.toString() : "unknown" };
|
|
63
|
+
});
|
|
64
|
+
const state = {
|
|
65
|
+
className: manager.className,
|
|
66
|
+
revision,
|
|
67
|
+
ids,
|
|
68
|
+
objects,
|
|
69
|
+
properties: manager.properties || [],
|
|
70
|
+
savedAt: Date.now(),
|
|
71
|
+
};
|
|
72
|
+
await storageAdapter.saveManagerState(manager.className, state);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
manager.loggers?.warn?.(`Failed to persist ${manager.className} to storage: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Applies a delta changes payload to the in-memory client manager.
|
|
80
|
+
*/
|
|
81
|
+
static async applyDelta(manager, payload, storageAdapter) {
|
|
82
|
+
const changes = payload.changes ?? [];
|
|
83
|
+
for (const change of changes) {
|
|
84
|
+
const id = change.id;
|
|
85
|
+
if (change.type === "delete") {
|
|
86
|
+
const existing = manager.getObject(id);
|
|
87
|
+
if (existing) {
|
|
88
|
+
await manager.deleteObject(id);
|
|
89
|
+
manager.totalObjects = Math.max(0, manager.totalObjects - 1);
|
|
90
|
+
manager.loadedObjects = Math.max(0, manager.loadedObjects - 1);
|
|
91
|
+
if ("_cachedObjectsArray" in manager) {
|
|
92
|
+
manager._cachedObjectsArray = null;
|
|
93
|
+
}
|
|
94
|
+
manager.callbacks?.delete?.(existing);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (change.type === "create") {
|
|
98
|
+
let existing = manager.getObject(id);
|
|
99
|
+
if (!existing) {
|
|
100
|
+
const instance = new manager.classParam(manager.classParam, manager.socket, change.data || id, manager.loggers, manager.className, manager, manager.callbacks, manager.emitter);
|
|
101
|
+
manager.objects_[id] = instance;
|
|
102
|
+
if ("_cachedObjectsArray" in manager) {
|
|
103
|
+
manager._cachedObjectsArray = null;
|
|
104
|
+
}
|
|
105
|
+
globalCache.objects[id] = {
|
|
106
|
+
className: manager.className,
|
|
107
|
+
object: instance,
|
|
108
|
+
};
|
|
109
|
+
manager.totalObjects += 1;
|
|
110
|
+
manager.loadedObjects += 1;
|
|
111
|
+
manager.callbacks?.new?.(instance);
|
|
112
|
+
}
|
|
113
|
+
else if (change.data) {
|
|
114
|
+
// Object already exists, apply properties
|
|
115
|
+
await this.patchObjectProperties(existing, change.data, manager.callbacks);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (change.type === "update") {
|
|
119
|
+
let existing = manager.getObject(id);
|
|
120
|
+
if (existing && change.data) {
|
|
121
|
+
await this.patchObjectProperties(existing, change.data, manager.callbacks);
|
|
122
|
+
}
|
|
123
|
+
else if (!existing && change.data) {
|
|
124
|
+
// Object was updated but client did not have it, create it
|
|
125
|
+
const instance = new manager.classParam(manager.classParam, manager.socket, change.data, manager.loggers, manager.className, manager, manager.callbacks, manager.emitter);
|
|
126
|
+
manager.objects_[id] = instance;
|
|
127
|
+
if ("_cachedObjectsArray" in manager) {
|
|
128
|
+
manager._cachedObjectsArray = null;
|
|
129
|
+
}
|
|
130
|
+
globalCache.objects[id] = {
|
|
131
|
+
className: manager.className,
|
|
132
|
+
object: instance,
|
|
133
|
+
};
|
|
134
|
+
manager.totalObjects += 1;
|
|
135
|
+
manager.loadedObjects += 1;
|
|
136
|
+
manager.callbacks?.new?.(instance);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (storageAdapter) {
|
|
141
|
+
await this.persistToStorage(manager, payload.revision, storageAdapter);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
static async patchObjectProperties(targetObj, patchData, callbacks) {
|
|
145
|
+
for (const key of Object.keys(patchData)) {
|
|
146
|
+
if (key === "_id")
|
|
147
|
+
continue;
|
|
148
|
+
const val = patchData[key];
|
|
149
|
+
if (targetObj.data) {
|
|
150
|
+
targetObj.data[key] = val;
|
|
151
|
+
}
|
|
152
|
+
if (typeof targetObj.setValue__ === "function") {
|
|
153
|
+
await targetObj.setValue__(key, val, true);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
targetObj[key] = val;
|
|
157
|
+
}
|
|
158
|
+
callbacks?.update?.(targetObj, key);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ClientStateReconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientStateReconciler.js","sourceRoot":"","sources":["../../sync/ClientStateReconciler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ChangeEntry, ChangeLogOptions, ChangeType, PruneMode } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates a fast approximation of the memory/JSON byte footprint of a JavaScript object/value.
|
|
4
|
+
*/
|
|
5
|
+
export declare function estimateObjectSizeBytes(obj: unknown): number;
|
|
6
|
+
export declare class ServerChangeTracker<T = unknown> {
|
|
7
|
+
readonly className: string;
|
|
8
|
+
private currentRevision;
|
|
9
|
+
private lowestRetainedRevision;
|
|
10
|
+
private entries;
|
|
11
|
+
private totalEstimatedBytes;
|
|
12
|
+
maxAgeMs?: number;
|
|
13
|
+
maxSizeBytes?: number;
|
|
14
|
+
maxEntries?: number;
|
|
15
|
+
pruneMode: PruneMode;
|
|
16
|
+
constructor(className: string, options?: ChangeLogOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Dynamically updates limits (MB size, TTL age, entries, pruneMode) mid-run and triggers pruning.
|
|
19
|
+
*/
|
|
20
|
+
updateOptions(options: Partial<ChangeLogOptions>): void;
|
|
21
|
+
getCurrentRevision(): number;
|
|
22
|
+
getLowestRetainedRevision(): number;
|
|
23
|
+
getEstimatedSizeBytes(): number;
|
|
24
|
+
getEntryCount(): number;
|
|
25
|
+
/**
|
|
26
|
+
* Records a mutation and assigns a new monotonic revision number.
|
|
27
|
+
*/
|
|
28
|
+
recordChange(type: ChangeType, id: string, data?: Partial<T>): number;
|
|
29
|
+
/**
|
|
30
|
+
* Records a mutation with an explicit timestamp (useful for testing or replay).
|
|
31
|
+
*/
|
|
32
|
+
recordChangeWithTimestamp(type: ChangeType, id: string, data: Partial<T> | undefined, timestamp: number): number;
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves all mutations occurring strictly after `clientRevision`.
|
|
35
|
+
* If `clientRevision` is older than the lowest retained revision in history,
|
|
36
|
+
* returns `isExpired: true` indicating a full sync is necessary.
|
|
37
|
+
*/
|
|
38
|
+
getChangesSince(clientRevision: number, allowedIds?: Set<string>): {
|
|
39
|
+
isExpired: boolean;
|
|
40
|
+
changes: ChangeEntry<T>[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Prunes entries based on configured maxAgeMs, maxSizeBytes, maxEntries, and pruneMode.
|
|
44
|
+
*/
|
|
45
|
+
prune(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Clears all recorded entries and resets tracking state.
|
|
48
|
+
*/
|
|
49
|
+
clear(): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculates a fast approximation of the memory/JSON byte footprint of a JavaScript object/value.
|
|
3
|
+
*/
|
|
4
|
+
export function estimateObjectSizeBytes(obj) {
|
|
5
|
+
if (obj === null || obj === undefined)
|
|
6
|
+
return 8;
|
|
7
|
+
const type = typeof obj;
|
|
8
|
+
if (type === "boolean")
|
|
9
|
+
return 4;
|
|
10
|
+
if (type === "number")
|
|
11
|
+
return 8;
|
|
12
|
+
if (type === "string")
|
|
13
|
+
return obj.length * 2;
|
|
14
|
+
if (type === "object") {
|
|
15
|
+
let size = 16;
|
|
16
|
+
if (Array.isArray(obj)) {
|
|
17
|
+
for (let i = 0; i < obj.length; i++) {
|
|
18
|
+
size += estimateObjectSizeBytes(obj[i]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
for (const key in obj) {
|
|
23
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
24
|
+
size += key.length * 2 + estimateObjectSizeBytes(obj[key]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return size;
|
|
29
|
+
}
|
|
30
|
+
return 16;
|
|
31
|
+
}
|
|
32
|
+
export class ServerChangeTracker {
|
|
33
|
+
className;
|
|
34
|
+
currentRevision = 0;
|
|
35
|
+
lowestRetainedRevision = 1;
|
|
36
|
+
entries = [];
|
|
37
|
+
totalEstimatedBytes = 0;
|
|
38
|
+
maxAgeMs;
|
|
39
|
+
maxSizeBytes;
|
|
40
|
+
maxEntries;
|
|
41
|
+
pruneMode;
|
|
42
|
+
constructor(className, options) {
|
|
43
|
+
this.className = className;
|
|
44
|
+
this.maxAgeMs = options?.maxAgeMs;
|
|
45
|
+
this.maxSizeBytes = options?.maxSizeBytes;
|
|
46
|
+
this.maxEntries = options?.maxEntries;
|
|
47
|
+
this.pruneMode = options?.pruneMode ?? "either";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Dynamically updates limits (MB size, TTL age, entries, pruneMode) mid-run and triggers pruning.
|
|
51
|
+
*/
|
|
52
|
+
updateOptions(options) {
|
|
53
|
+
if (options.maxAgeMs !== undefined)
|
|
54
|
+
this.maxAgeMs = options.maxAgeMs;
|
|
55
|
+
if (options.maxSizeBytes !== undefined)
|
|
56
|
+
this.maxSizeBytes = options.maxSizeBytes;
|
|
57
|
+
if (options.maxEntries !== undefined)
|
|
58
|
+
this.maxEntries = options.maxEntries;
|
|
59
|
+
if (options.pruneMode !== undefined)
|
|
60
|
+
this.pruneMode = options.pruneMode;
|
|
61
|
+
this.prune();
|
|
62
|
+
}
|
|
63
|
+
getCurrentRevision() {
|
|
64
|
+
return this.currentRevision;
|
|
65
|
+
}
|
|
66
|
+
getLowestRetainedRevision() {
|
|
67
|
+
return this.lowestRetainedRevision;
|
|
68
|
+
}
|
|
69
|
+
getEstimatedSizeBytes() {
|
|
70
|
+
return this.totalEstimatedBytes;
|
|
71
|
+
}
|
|
72
|
+
getEntryCount() {
|
|
73
|
+
return this.entries.length;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Records a mutation and assigns a new monotonic revision number.
|
|
77
|
+
*/
|
|
78
|
+
recordChange(type, id, data) {
|
|
79
|
+
return this.recordChangeWithTimestamp(type, id, data, Date.now());
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Records a mutation with an explicit timestamp (useful for testing or replay).
|
|
83
|
+
*/
|
|
84
|
+
recordChangeWithTimestamp(type, id, data, timestamp) {
|
|
85
|
+
this.currentRevision += 1;
|
|
86
|
+
const rev = this.currentRevision;
|
|
87
|
+
const estimatedBytes = 40 + // metadata overhead (revision, type, id, timestamp)
|
|
88
|
+
id.length * 2 +
|
|
89
|
+
(data ? estimateObjectSizeBytes(data) : 0);
|
|
90
|
+
const entry = {
|
|
91
|
+
revision: rev,
|
|
92
|
+
type,
|
|
93
|
+
id,
|
|
94
|
+
data,
|
|
95
|
+
timestamp,
|
|
96
|
+
estimatedBytes,
|
|
97
|
+
};
|
|
98
|
+
this.entries.push(entry);
|
|
99
|
+
this.totalEstimatedBytes += estimatedBytes;
|
|
100
|
+
this.prune();
|
|
101
|
+
return rev;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Retrieves all mutations occurring strictly after `clientRevision`.
|
|
105
|
+
* If `clientRevision` is older than the lowest retained revision in history,
|
|
106
|
+
* returns `isExpired: true` indicating a full sync is necessary.
|
|
107
|
+
*/
|
|
108
|
+
getChangesSince(clientRevision, allowedIds) {
|
|
109
|
+
if (clientRevision >= this.currentRevision) {
|
|
110
|
+
return { isExpired: false, changes: [] };
|
|
111
|
+
}
|
|
112
|
+
if (this.entries.length === 0 || clientRevision < this.lowestRetainedRevision - 1) {
|
|
113
|
+
return { isExpired: true, changes: [] };
|
|
114
|
+
}
|
|
115
|
+
let filtered = this.entries.filter((e) => e.revision > clientRevision);
|
|
116
|
+
if (allowedIds) {
|
|
117
|
+
filtered = filtered.filter((e) => allowedIds.has(e.id));
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
isExpired: false,
|
|
121
|
+
changes: filtered,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Prunes entries based on configured maxAgeMs, maxSizeBytes, maxEntries, and pruneMode.
|
|
126
|
+
*/
|
|
127
|
+
prune() {
|
|
128
|
+
if (this.entries.length === 0)
|
|
129
|
+
return;
|
|
130
|
+
const now = Date.now();
|
|
131
|
+
let deleteCount = 0;
|
|
132
|
+
for (let i = 0; i < this.entries.length; i++) {
|
|
133
|
+
const entry = this.entries[i];
|
|
134
|
+
const isAgeViolated = this.maxAgeMs != null && now - entry.timestamp > this.maxAgeMs;
|
|
135
|
+
const isSizeViolated = this.maxSizeBytes != null && this.totalEstimatedBytes > this.maxSizeBytes;
|
|
136
|
+
const isCountViolated = this.maxEntries != null && this.entries.length - deleteCount > this.maxEntries;
|
|
137
|
+
let shouldPrune = false;
|
|
138
|
+
if (this.pruneMode === "both") {
|
|
139
|
+
const hasAgeConstraint = this.maxAgeMs != null;
|
|
140
|
+
const hasSizeConstraint = this.maxSizeBytes != null;
|
|
141
|
+
if (hasAgeConstraint && hasSizeConstraint) {
|
|
142
|
+
shouldPrune = (isAgeViolated && isSizeViolated) || isCountViolated;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
shouldPrune = isAgeViolated || isSizeViolated || isCountViolated;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// "either" mode
|
|
150
|
+
shouldPrune = isAgeViolated || isSizeViolated || isCountViolated;
|
|
151
|
+
}
|
|
152
|
+
if (shouldPrune) {
|
|
153
|
+
this.totalEstimatedBytes -= entry.estimatedBytes;
|
|
154
|
+
deleteCount++;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (deleteCount > 0) {
|
|
161
|
+
this.entries.splice(0, deleteCount);
|
|
162
|
+
if (this.entries.length > 0) {
|
|
163
|
+
this.lowestRetainedRevision = this.entries[0].revision;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
this.lowestRetainedRevision = this.currentRevision + 1;
|
|
167
|
+
this.totalEstimatedBytes = 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Clears all recorded entries and resets tracking state.
|
|
173
|
+
*/
|
|
174
|
+
clear() {
|
|
175
|
+
this.entries = [];
|
|
176
|
+
this.totalEstimatedBytes = 0;
|
|
177
|
+
this.currentRevision = 0;
|
|
178
|
+
this.lowestRetainedRevision = 1;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=ServerChangeTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServerChangeTracker.js","sourceRoot":"","sources":["../../sync/ServerChangeTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./ServerChangeTracker.js";
|
|
3
|
+
export * from "./ClientStateReconciler.js";
|
|
4
|
+
export * from "./storage/IClientStorageAdapter.js";
|
|
5
|
+
export * from "./storage/MemoryStorageAdapter.js";
|
|
6
|
+
export * from "./storage/LocalStorageAdapter.js";
|
|
7
|
+
export * from "./storage/IndexedDbStorageAdapter.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./ServerChangeTracker.js";
|
|
3
|
+
export * from "./ClientStateReconciler.js";
|
|
4
|
+
export * from "./storage/IClientStorageAdapter.js";
|
|
5
|
+
export * from "./storage/MemoryStorageAdapter.js";
|
|
6
|
+
export * from "./storage/LocalStorageAdapter.js";
|
|
7
|
+
export * from "./storage/IndexedDbStorageAdapter.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { StoredManagerState } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Interface for pluggable client-side persistent storage adapters in DEM.
|
|
4
|
+
*/
|
|
5
|
+
export interface IClientStorageAdapter {
|
|
6
|
+
/**
|
|
7
|
+
* Save complete manager state to persistent storage.
|
|
8
|
+
*/
|
|
9
|
+
saveManagerState<T = unknown>(className: string, state: StoredManagerState<T>): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Retrieve saved manager state from storage.
|
|
12
|
+
* Returns null if no state exists or if stored data is corrupted.
|
|
13
|
+
*/
|
|
14
|
+
loadManagerState<T = unknown>(className: string): Promise<StoredManagerState<T> | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Clear saved state for a specific manager class.
|
|
17
|
+
*/
|
|
18
|
+
clearManagerState(className: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Clear all stored DEM manager states across all classes.
|
|
21
|
+
*/
|
|
22
|
+
clearAll(): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IClientStorageAdapter.js","sourceRoot":"","sources":["../../../sync/storage/IClientStorageAdapter.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StoredManagerState } from "../types.js";
|
|
2
|
+
import { IClientStorageAdapter } from "./IClientStorageAdapter.js";
|
|
3
|
+
export interface IndexedDbStorageAdapterOptions {
|
|
4
|
+
dbName?: string;
|
|
5
|
+
storeName?: string;
|
|
6
|
+
idbFactory?: IDBFactory;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* IndexedDB storage adapter for client-side DEM caching in browsers.
|
|
10
|
+
*/
|
|
11
|
+
export declare class IndexedDbStorageAdapter implements IClientStorageAdapter {
|
|
12
|
+
private dbName;
|
|
13
|
+
private storeName;
|
|
14
|
+
private idbFactory;
|
|
15
|
+
private dbPromise;
|
|
16
|
+
constructor(options?: IndexedDbStorageAdapterOptions);
|
|
17
|
+
private getDb;
|
|
18
|
+
saveManagerState<T = unknown>(className: string, state: StoredManagerState<T>): Promise<void>;
|
|
19
|
+
loadManagerState<T = unknown>(className: string): Promise<StoredManagerState<T> | null>;
|
|
20
|
+
clearManagerState(className: string): Promise<void>;
|
|
21
|
+
clearAll(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IndexedDB storage adapter for client-side DEM caching in browsers.
|
|
3
|
+
*/
|
|
4
|
+
export class IndexedDbStorageAdapter {
|
|
5
|
+
dbName;
|
|
6
|
+
storeName;
|
|
7
|
+
idbFactory = null;
|
|
8
|
+
dbPromise = null;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.dbName = options?.dbName ?? "dem_offline_store";
|
|
11
|
+
this.storeName = options?.storeName ?? "manager_states";
|
|
12
|
+
if (options?.idbFactory) {
|
|
13
|
+
this.idbFactory = options.idbFactory;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof indexedDB !== "undefined") {
|
|
16
|
+
this.idbFactory = indexedDB;
|
|
17
|
+
}
|
|
18
|
+
else if (typeof window !== "undefined" && window.indexedDB) {
|
|
19
|
+
this.idbFactory = window.indexedDB;
|
|
20
|
+
}
|
|
21
|
+
else if (typeof globalThis !== "undefined" && globalThis.indexedDB) {
|
|
22
|
+
this.idbFactory = globalThis.indexedDB;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async getDb() {
|
|
26
|
+
if (this.dbPromise)
|
|
27
|
+
return this.dbPromise;
|
|
28
|
+
if (!this.idbFactory) {
|
|
29
|
+
throw new Error("IndexedDB is not supported in the current environment.");
|
|
30
|
+
}
|
|
31
|
+
this.dbPromise = new Promise((resolve, reject) => {
|
|
32
|
+
const request = this.idbFactory.open(this.dbName, 1);
|
|
33
|
+
request.onupgradeneeded = () => {
|
|
34
|
+
const db = request.result;
|
|
35
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
36
|
+
db.createObjectStore(this.storeName, { keyPath: "className" });
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
request.onsuccess = () => {
|
|
40
|
+
resolve(request.result);
|
|
41
|
+
};
|
|
42
|
+
request.onerror = () => {
|
|
43
|
+
reject(request.error || new Error("Failed to open IndexedDB"));
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
return this.dbPromise;
|
|
47
|
+
}
|
|
48
|
+
async saveManagerState(className, state) {
|
|
49
|
+
if (!this.idbFactory)
|
|
50
|
+
return;
|
|
51
|
+
try {
|
|
52
|
+
const db = await this.getDb();
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const tx = db.transaction(this.storeName, "readwrite");
|
|
55
|
+
const store = tx.objectStore(this.storeName);
|
|
56
|
+
const record = { ...state, className };
|
|
57
|
+
const req = store.put(record);
|
|
58
|
+
req.onsuccess = () => resolve();
|
|
59
|
+
req.onerror = () => reject(req.error);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Graceful error fallback
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async loadManagerState(className) {
|
|
67
|
+
if (!this.idbFactory)
|
|
68
|
+
return null;
|
|
69
|
+
try {
|
|
70
|
+
const db = await this.getDb();
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
const tx = db.transaction(this.storeName, "readonly");
|
|
73
|
+
const store = tx.objectStore(this.storeName);
|
|
74
|
+
const req = store.get(className);
|
|
75
|
+
req.onsuccess = () => {
|
|
76
|
+
if (req.result && typeof req.result.revision === "number") {
|
|
77
|
+
resolve(req.result);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
resolve(null);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
req.onerror = () => reject(req.error);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async clearManagerState(className) {
|
|
91
|
+
if (!this.idbFactory)
|
|
92
|
+
return;
|
|
93
|
+
try {
|
|
94
|
+
const db = await this.getDb();
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
const tx = db.transaction(this.storeName, "readwrite");
|
|
97
|
+
const store = tx.objectStore(this.storeName);
|
|
98
|
+
const req = store.delete(className);
|
|
99
|
+
req.onsuccess = () => resolve();
|
|
100
|
+
req.onerror = () => reject(req.error);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Ignore
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async clearAll() {
|
|
108
|
+
if (!this.idbFactory)
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
const db = await this.getDb();
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
const tx = db.transaction(this.storeName, "readwrite");
|
|
114
|
+
const store = tx.objectStore(this.storeName);
|
|
115
|
+
const req = store.clear();
|
|
116
|
+
req.onsuccess = () => resolve();
|
|
117
|
+
req.onerror = () => reject(req.error);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Ignore
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=IndexedDbStorageAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexedDbStorageAdapter.js","sourceRoot":"","sources":["../../../sync/storage/IndexedDbStorageAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StoredManagerState } from "../types.js";
|
|
2
|
+
import { IClientStorageAdapter } from "./IClientStorageAdapter.js";
|
|
3
|
+
export interface LocalStorageAdapterOptions {
|
|
4
|
+
prefix?: string;
|
|
5
|
+
storage?: {
|
|
6
|
+
getItem(key: string): string | null;
|
|
7
|
+
setItem(key: string, value: string): void;
|
|
8
|
+
removeItem(key: string): void;
|
|
9
|
+
clear?(): void;
|
|
10
|
+
key?(index: number): string | null;
|
|
11
|
+
length?: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* LocalStorage client storage adapter.
|
|
16
|
+
* Works with browser window.localStorage or mock storage in tests/Node.js.
|
|
17
|
+
*/
|
|
18
|
+
export declare class LocalStorageAdapter implements IClientStorageAdapter {
|
|
19
|
+
private prefix;
|
|
20
|
+
private storageBackend;
|
|
21
|
+
constructor(options?: LocalStorageAdapterOptions);
|
|
22
|
+
private getKey;
|
|
23
|
+
saveManagerState<T = unknown>(className: string, state: StoredManagerState<T>): Promise<void>;
|
|
24
|
+
loadManagerState<T = unknown>(className: string): Promise<StoredManagerState<T> | null>;
|
|
25
|
+
clearManagerState(className: string): Promise<void>;
|
|
26
|
+
clearAll(): Promise<void>;
|
|
27
|
+
}
|