remote-state-sync 1.0.1 → 1.0.3

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/index.d.ts CHANGED
@@ -1,29 +1,33 @@
1
+ import { SuperJSONResult } from 'superjson';
1
2
  import Nanobus from 'nanobus';
2
3
  import { Ref, ShallowRef } from '@vue/reactivity';
3
4
 
4
5
  type PatchOperation = 'set' | 'delete' | 'clear' | 'add';
5
6
  interface Patch {
6
7
  op: PatchOperation;
8
+ key: string;
7
9
  path: (string | number)[];
8
10
  value?: unknown;
9
11
  }
10
12
  interface SyncOptions {
11
- snapshotGetter: (namespace: string) => Promise<Record<string, unknown>>;
13
+ snapshotGetter: (namespace: string) => Promise<SyncSnapshot>;
12
14
  }
13
15
  type SyncUpdater<T> = (state: T) => T | void;
14
16
  type SyncBusDefinition = {
15
17
  update: (namespace: string, patches: Patch[]) => void;
18
+ register: (namespace: string) => void;
16
19
  };
17
20
  type ReceiverItemBusDefinition<T> = {
18
21
  update: (newValue: T, oldValue: T, patches: Patch[]) => void;
19
22
  };
23
+ type SyncSnapshot = SuperJSONResult;
20
24
 
21
25
  declare class SyncProvider {
22
26
  private namespaces;
23
- bus: Nanobus<SyncBusDefinition>;
27
+ readonly bus: Nanobus<SyncBusDefinition>;
24
28
  constructor();
25
29
  register(namespace: string): SyncNamespaceProvider;
26
- getStateSnapshot(namespace: string): Promise<Record<string, unknown>>;
30
+ getStateSnapshot(namespace: string): SyncSnapshot;
27
31
  }
28
32
  declare class SyncNamespaceProvider {
29
33
  readonly namespace: string;
@@ -33,7 +37,7 @@ declare class SyncNamespaceProvider {
33
37
  private emitTimeout;
34
38
  constructor(namespace: string, bus: Nanobus<SyncBusDefinition>);
35
39
  sync<T>(key: string, initialValue?: T): SyncItemProvider<T>;
36
- getSnapshot(): Record<string, unknown>;
40
+ getSnapshot(): SyncSnapshot;
37
41
  private queuePatch;
38
42
  private emitPatches;
39
43
  }
@@ -58,7 +62,7 @@ declare class SyncNamespaceReceiver {
58
62
  readonly namespace: string;
59
63
  private snapshot;
60
64
  private items;
61
- constructor(namespace: string, snapshot: Record<string, unknown>);
65
+ constructor(namespace: string, snapshot: SyncSnapshot);
62
66
  sync<T>(key: string): SyncItemReceiver<T>;
63
67
  applyPatches(patches: Patch[]): void;
64
68
  private applyPatchToObject;
@@ -68,7 +72,7 @@ declare class SyncItemReceiver<T> {
68
72
  private value;
69
73
  private _ref;
70
74
  private _shallowRef;
71
- bus: Nanobus<ReceiverItemBusDefinition<T>>;
75
+ readonly bus: Nanobus<ReceiverItemBusDefinition<T>>;
72
76
  constructor(key: string, initialValue: T);
73
77
  on(event: 'update', cb: (newValue: T, oldValue: T, patches: Patch[]) => void): void;
74
78
  toValue(): T;
@@ -79,4 +83,4 @@ declare class SyncItemReceiver<T> {
79
83
  dispose(): void;
80
84
  }
81
85
 
82
- export { type Patch, type PatchOperation, type ReceiverItemBusDefinition, type SyncBusDefinition, SyncItemProvider, SyncItemReceiver, SyncNamespaceProvider, SyncNamespaceReceiver, type SyncOptions, SyncProvider, SyncReceiver, type SyncUpdater };
86
+ export { type Patch, type PatchOperation, type ReceiverItemBusDefinition, type SyncBusDefinition, SyncItemProvider, SyncItemReceiver, SyncNamespaceProvider, SyncNamespaceReceiver, type SyncOptions, SyncProvider, SyncReceiver, type SyncSnapshot, type SyncUpdater };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/provider.ts
2
2
  import Nanobus from "nanobus";
3
+ import SuperJSON from "superjson";
3
4
 
4
5
  // src/utils.ts
5
6
  function isObject(val) {
@@ -53,19 +54,19 @@ function clearValue(current) {
53
54
  }
54
55
 
55
56
  // src/proxy.ts
56
- function createDeepProxy(target, path, onPatch) {
57
+ function createDeepProxy(target, rootKey, path, onPatch) {
57
58
  if (!shouldProxy(target)) {
58
59
  return target;
59
60
  }
60
61
  if (target instanceof Map) {
61
- return createMapProxy(target, path, onPatch);
62
+ return createMapProxy(target, rootKey, path, onPatch);
62
63
  }
63
64
  if (target instanceof Set) {
64
- return createSetProxy(target, path, onPatch);
65
+ return createSetProxy(target, rootKey, path, onPatch);
65
66
  }
66
- return createObjectProxy(target, path, onPatch);
67
+ return createObjectProxy(target, rootKey, path, onPatch);
67
68
  }
68
- function createObjectProxy(target, path, onPatch) {
69
+ function createObjectProxy(target, rootKey, path, onPatch) {
69
70
  const handler = {
70
71
  get(obj, prop, receiver) {
71
72
  const value = Reflect.get(obj, prop, receiver);
@@ -73,7 +74,7 @@ function createObjectProxy(target, path, onPatch) {
73
74
  return value;
74
75
  }
75
76
  if (shouldProxy(value)) {
76
- return createDeepProxy(value, [...path, prop], onPatch);
77
+ return createDeepProxy(value, rootKey, [...path, prop], onPatch);
77
78
  }
78
79
  return value;
79
80
  },
@@ -85,6 +86,7 @@ function createObjectProxy(target, path, onPatch) {
85
86
  if (success) {
86
87
  onPatch({
87
88
  op: "set",
89
+ key: rootKey,
88
90
  path: [...path, prop],
89
91
  value
90
92
  });
@@ -99,6 +101,7 @@ function createObjectProxy(target, path, onPatch) {
99
101
  if (success) {
100
102
  onPatch({
101
103
  op: "delete",
104
+ key: rootKey,
102
105
  path: [...path, prop]
103
106
  });
104
107
  }
@@ -107,7 +110,7 @@ function createObjectProxy(target, path, onPatch) {
107
110
  };
108
111
  return new Proxy(target, handler);
109
112
  }
110
- function createMapProxy(target, path, onPatch) {
113
+ function createMapProxy(target, rootKey, path, onPatch) {
111
114
  const handler = {
112
115
  get(obj, prop) {
113
116
  const value = Reflect.get(obj, prop);
@@ -120,6 +123,7 @@ function createMapProxy(target, path, onPatch) {
120
123
  const result = obj.set(key, val);
121
124
  onPatch({
122
125
  op: "set",
126
+ key: rootKey,
123
127
  path: [...path, key],
124
128
  value: val
125
129
  });
@@ -133,6 +137,7 @@ function createMapProxy(target, path, onPatch) {
133
137
  if (hasKey) {
134
138
  onPatch({
135
139
  op: "delete",
140
+ key: rootKey,
136
141
  path: [...path, key]
137
142
  });
138
143
  }
@@ -145,6 +150,7 @@ function createMapProxy(target, path, onPatch) {
145
150
  const result = obj.clear();
146
151
  onPatch({
147
152
  op: "clear",
153
+ key: rootKey,
148
154
  path
149
155
  });
150
156
  return result;
@@ -155,7 +161,7 @@ function createMapProxy(target, path, onPatch) {
155
161
  return function(key) {
156
162
  const getVal = obj.get(key);
157
163
  if (shouldProxy(getVal)) {
158
- return createDeepProxy(getVal, [...path, key], onPatch);
164
+ return createDeepProxy(getVal, rootKey, [...path, key], onPatch);
159
165
  }
160
166
  return getVal;
161
167
  };
@@ -167,7 +173,7 @@ function createMapProxy(target, path, onPatch) {
167
173
  };
168
174
  return new Proxy(target, handler);
169
175
  }
170
- function createSetProxy(target, path, onPatch) {
176
+ function createSetProxy(target, rootKey, path, onPatch) {
171
177
  const handler = {
172
178
  get(obj, prop) {
173
179
  const value = Reflect.get(obj, prop);
@@ -182,6 +188,7 @@ function createSetProxy(target, path, onPatch) {
182
188
  if (!hasVal) {
183
189
  onPatch({
184
190
  op: "add",
191
+ key: rootKey,
185
192
  // For set, we don't have a key to navigate, but we can pass the value
186
193
  // In a true Sync scenario, Set diffing is tricky. Path is just the Set itself.
187
194
  path,
@@ -198,6 +205,7 @@ function createSetProxy(target, path, onPatch) {
198
205
  if (hasVal) {
199
206
  onPatch({
200
207
  op: "delete",
208
+ key: rootKey,
201
209
  path,
202
210
  // Similarly, deleting from set happens at Set boundary
203
211
  value: val
@@ -213,6 +221,7 @@ function createSetProxy(target, path, onPatch) {
213
221
  const result = obj.clear();
214
222
  onPatch({
215
223
  op: "clear",
224
+ key: rootKey,
216
225
  path
217
226
  });
218
227
  return result;
@@ -239,9 +248,10 @@ var SyncProvider = class {
239
248
  }
240
249
  const ns = new SyncNamespaceProvider(namespace, this.bus);
241
250
  this.namespaces.set(namespace, ns);
251
+ this.bus.emit("register", namespace);
242
252
  return ns;
243
253
  }
244
- async getStateSnapshot(namespace) {
254
+ getStateSnapshot(namespace) {
245
255
  const ns = this.namespaces.get(namespace);
246
256
  if (!ns) {
247
257
  throw new Error(`Namespace ${namespace} not found`);
@@ -272,7 +282,7 @@ var SyncNamespaceProvider = class {
272
282
  for (const [key, item] of this.items.entries()) {
273
283
  snapshot[key] = item.toValue();
274
284
  }
275
- return snapshot;
285
+ return SuperJSON.serialize(snapshot);
276
286
  }
277
287
  queuePatch(patch) {
278
288
  this.queuedPatches.push(patch);
@@ -316,16 +326,18 @@ var SyncItemProvider = class {
316
326
  setValue(newVal) {
317
327
  this.onPatch({
318
328
  op: "set",
319
- path: [this.key],
329
+ key: this.key,
330
+ path: [],
320
331
  value: newVal
321
332
  });
322
- this.value = createDeepProxy(newVal, [this.key], this.onPatch);
333
+ this.value = createDeepProxy(newVal, this.key, [], this.onPatch);
323
334
  }
324
335
  };
325
336
 
326
337
  // src/receiver.ts
327
338
  import Nanobus2 from "nanobus";
328
339
  import { shallowRef, ref, triggerRef } from "@vue/reactivity";
340
+ import SuperJSON2 from "superjson";
329
341
  var SyncReceiver = class {
330
342
  constructor(options) {
331
343
  this.options = options;
@@ -357,7 +369,8 @@ var SyncNamespaceReceiver = class {
357
369
  if (this.items.has(key)) {
358
370
  return this.items.get(key);
359
371
  }
360
- const val = this.snapshot[key];
372
+ const snapshot = SuperJSON2.deserialize(this.snapshot);
373
+ const val = snapshot[key];
361
374
  const item = new SyncItemReceiver(key, val);
362
375
  this.items.set(key, item);
363
376
  return item;
@@ -365,8 +378,7 @@ var SyncNamespaceReceiver = class {
365
378
  applyPatches(patches) {
366
379
  const affectedItems = /* @__PURE__ */ new Map();
367
380
  for (const patch of patches) {
368
- if (patch.path.length === 0) continue;
369
- const key = patch.path[0];
381
+ const key = patch.key;
370
382
  const item = this.items.get(key);
371
383
  if (item) {
372
384
  if (!affectedItems.has(item)) {
@@ -384,9 +396,9 @@ var SyncNamespaceReceiver = class {
384
396
  }
385
397
  }
386
398
  applyPatchToObject(obj, patch) {
387
- if (patch.path.length === 0) return;
399
+ const fullPath = [patch.key, ...patch.path];
388
400
  if (patch.op === "clear" || patch.op === "add") {
389
- const target = navigatePath(obj, patch.path, 0, patch.path.length);
401
+ const target = navigatePath(obj, fullPath, 0, fullPath.length);
390
402
  if (patch.op === "clear") {
391
403
  clearValue(target);
392
404
  } else {
@@ -394,8 +406,8 @@ var SyncNamespaceReceiver = class {
394
406
  }
395
407
  return;
396
408
  }
397
- const current = navigatePath(obj, patch.path, 0, patch.path.length - 1);
398
- const lastKey = patch.path[patch.path.length - 1];
409
+ const current = navigatePath(obj, fullPath, 0, fullPath.length - 1);
410
+ const lastKey = fullPath[fullPath.length - 1];
399
411
  if (patch.op === "set") {
400
412
  setValueAtPath(current, lastKey, patch.value);
401
413
  } else if (patch.op === "delete") {
@@ -431,7 +443,7 @@ var SyncItemReceiver = class {
431
443
  return this._shallowRef;
432
444
  }
433
445
  applyPatch(patch) {
434
- if (patch.path.length === 1) {
446
+ if (patch.path.length === 0) {
435
447
  if (patch.op === "set") {
436
448
  this.value = patch.value;
437
449
  if (this._ref) this._ref.value = patch.value;
@@ -441,41 +453,41 @@ var SyncItemReceiver = class {
441
453
  }
442
454
  const lastKey = patch.path[patch.path.length - 1];
443
455
  if (patch.op === "set") {
444
- const current = navigatePath(this.value, patch.path, 1, patch.path.length - 1);
456
+ const current = navigatePath(this.value, patch.path, 0, patch.path.length - 1);
445
457
  const refCurrent = navigatePath(
446
458
  this._ref ? this._ref.value : null,
447
459
  patch.path,
448
- 1,
460
+ 0,
449
461
  patch.path.length - 1
450
462
  );
451
463
  setValueAtPath(current, lastKey, patch.value);
452
464
  setValueAtPath(refCurrent, lastKey, patch.value);
453
465
  } else if (patch.op === "delete") {
454
- const current = navigatePath(this.value, patch.path, 1, patch.path.length - 1);
466
+ const current = navigatePath(this.value, patch.path, 0, patch.path.length - 1);
455
467
  const refCurrent = navigatePath(
456
468
  this._ref ? this._ref.value : null,
457
469
  patch.path,
458
- 1,
470
+ 0,
459
471
  patch.path.length - 1
460
472
  );
461
473
  deleteValueAtPath(current, lastKey);
462
474
  deleteValueAtPath(refCurrent, lastKey);
463
475
  } else if (patch.op === "add") {
464
- const target = navigatePath(this.value, patch.path, 1, patch.path.length);
476
+ const target = navigatePath(this.value, patch.path, 0, patch.path.length);
465
477
  const refTarget = navigatePath(
466
478
  this._ref ? this._ref.value : null,
467
479
  patch.path,
468
- 1,
480
+ 0,
469
481
  patch.path.length
470
482
  );
471
483
  addValueToSet(target, patch.value);
472
484
  addValueToSet(refTarget, patch.value);
473
485
  } else if (patch.op === "clear") {
474
- const target = navigatePath(this.value, patch.path, 1, patch.path.length);
486
+ const target = navigatePath(this.value, patch.path, 0, patch.path.length);
475
487
  const refTarget = navigatePath(
476
488
  this._ref ? this._ref.value : null,
477
489
  patch.path,
478
- 1,
490
+ 0,
479
491
  patch.path.length
480
492
  );
481
493
  clearValue(target);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-state-sync",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A lightweight, fully type-safe unidirectional remote state synchronization library.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,9 +26,11 @@
26
26
  "types": "./dist/index.d.ts",
27
27
  "exports": {
28
28
  ".": {
29
+ "types": "./dist/index.d.ts",
29
30
  "import": "./dist/index.js",
30
- "types": "./dist/index.d.ts"
31
- }
31
+ "default": "./dist/index.js"
32
+ },
33
+ "./package.json": "./package.json"
32
34
  },
33
35
  "files": [
34
36
  "dist"
@@ -66,6 +68,7 @@
66
68
  },
67
69
  "dependencies": {
68
70
  "@vue/reactivity": "^3.5.28",
69
- "nanobus": "^4.5.0"
71
+ "nanobus": "^4.5.0",
72
+ "superjson": "^2.2.6"
70
73
  }
71
- }
74
+ }