@arcote.tech/arc 0.0.16 → 0.0.18
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/collection/collection.d.ts +16 -12
- package/dist/collection/queries/abstract-collection-query.d.ts +7 -8
- package/dist/collection/queries/one-item.d.ts +1 -1
- package/dist/collection/queries/util.d.ts +2 -2
- package/dist/context/context.d.ts +4 -2
- package/dist/context/query.d.ts +6 -3
- package/dist/data-storage/ForkStoreState.d.ts +1 -1
- package/dist/data-storage/StoreState.d.ts +37 -22
- package/dist/data-storage/data-storage-forked.d.ts +2 -2
- package/dist/data-storage/data-storage-master.d.ts +5 -3
- package/dist/data-storage/data-storage.abstract.d.ts +47 -0
- package/dist/data-storage/data-storage.interface.d.ts +14 -5
- package/dist/data-storage/deep-merge.d.ts +6 -0
- package/dist/data-storage/index.d.ts +1 -1
- package/dist/data-storage/master-store-state.d.ts +26 -13
- package/dist/data-storage/store-state-fork.d.ts +1 -1
- package/dist/data-storage/store-state-master.d.ts +1 -1
- package/dist/data-storage/store-state.abstract.d.ts +7 -3
- package/dist/data-storage/store-state.d.ts +37 -22
- package/dist/elements/date.d.ts +1 -1
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/object copy.d.ts +29 -0
- package/dist/elements/object.d.ts +15 -0
- package/dist/elements/record.d.ts +19 -0
- package/dist/elements/state.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +344 -45
- package/dist/rtc/index.d.ts +1 -0
- package/dist/rtc/messages.d.ts +3 -3
- package/dist/rtc/rtc.d.ts +4 -3
- package/dist/state/db.d.ts +1 -0
- package/dist/state/index.d.ts +1 -2
- package/dist/state/query-builder.d.ts +3 -2
- package/dist/state/query.d.ts +10 -17
- package/dist/state/state-change.d.ts +1 -0
- package/dist/state/state.d.ts +20 -16
- package/dist/state/util.d.ts +1 -0
- package/dist/utils/deep-merge.d.ts +6 -0
- package/dist/utils.d.ts +10 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,16 +3,24 @@ class ArcContextElement {
|
|
|
3
3
|
$event;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
class
|
|
8
|
-
collection;
|
|
6
|
+
// context/query.ts
|
|
7
|
+
class ArcQuery {
|
|
9
8
|
lastResult;
|
|
10
9
|
listener;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// collection/queries/abstract-collection-query.ts
|
|
13
|
+
class ArcCollectionQuery extends ArcQuery {
|
|
14
|
+
collection;
|
|
15
|
+
bindedChangeHandler = this.changeHandler.bind(this);
|
|
16
|
+
store;
|
|
11
17
|
constructor(collection) {
|
|
18
|
+
super();
|
|
12
19
|
this.collection = collection;
|
|
13
20
|
}
|
|
14
21
|
async run(dataStorage, listener) {
|
|
15
22
|
const store = dataStorage.getStore(this.collection.name);
|
|
23
|
+
this.store = store;
|
|
16
24
|
const result = await this.fetch(store);
|
|
17
25
|
this.lastResult = result;
|
|
18
26
|
if (listener)
|
|
@@ -20,16 +28,19 @@ class ArcCollectionQuery {
|
|
|
20
28
|
return result;
|
|
21
29
|
}
|
|
22
30
|
changeHandler(changes) {
|
|
31
|
+
let resultChanged = false;
|
|
23
32
|
for (const change of changes) {
|
|
24
33
|
const response = this.onChange(change);
|
|
25
|
-
if (response !== false)
|
|
34
|
+
if (response !== false) {
|
|
26
35
|
this.lastResult = response;
|
|
36
|
+
resultChanged = true;
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
|
-
if (
|
|
39
|
+
if (resultChanged)
|
|
29
40
|
this.nextResult(this.lastResult);
|
|
30
41
|
}
|
|
31
42
|
unsubscribe() {
|
|
32
|
-
|
|
43
|
+
this.store.unsubscribe(this.bindedChangeHandler);
|
|
33
44
|
}
|
|
34
45
|
nextResult(result) {
|
|
35
46
|
this.lastResult = result;
|
|
@@ -96,7 +107,7 @@ class ArcManyItemsQuery extends ArcCollectionQuery {
|
|
|
96
107
|
// collection/queries/all-items.ts
|
|
97
108
|
class ArcAllItemsQuery extends ArcManyItemsQuery {
|
|
98
109
|
async fetch(store) {
|
|
99
|
-
const results = await store.findAll(this.
|
|
110
|
+
const results = await store.findAll(this.bindedChangeHandler);
|
|
100
111
|
return this.createFiltredResult(results);
|
|
101
112
|
}
|
|
102
113
|
}
|
|
@@ -166,13 +177,13 @@ class ArcIndexedItemsQuery extends ArcManyItemsQuery {
|
|
|
166
177
|
checkItem(item) {
|
|
167
178
|
if (!super.checkItem(item))
|
|
168
179
|
return false;
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
180
|
+
const correct = Object.entries(this.data).every(([key, value]) => item[key] === value);
|
|
181
|
+
if (!correct)
|
|
171
182
|
return false;
|
|
172
183
|
return true;
|
|
173
184
|
}
|
|
174
185
|
async fetch(store) {
|
|
175
|
-
const results = await store.findByIndex(this.index, this.data, this.
|
|
186
|
+
const results = await store.findByIndex(this.index, this.data, this.bindedChangeHandler);
|
|
176
187
|
return this.createFiltredResult(results);
|
|
177
188
|
}
|
|
178
189
|
}
|
|
@@ -203,14 +214,16 @@ class ArcOneItemQuery extends ArcCollectionQuery {
|
|
|
203
214
|
this.id = id;
|
|
204
215
|
}
|
|
205
216
|
onChange(change) {
|
|
217
|
+
if (change.id !== this.id)
|
|
218
|
+
return false;
|
|
206
219
|
if (change.type === "delete")
|
|
207
|
-
return;
|
|
220
|
+
return null;
|
|
208
221
|
if (change.type === "set")
|
|
209
222
|
return change.item;
|
|
210
223
|
return false;
|
|
211
224
|
}
|
|
212
225
|
async fetch(store) {
|
|
213
|
-
const result = await store.findById(this.id, this.
|
|
226
|
+
const result = await store.findById(this.id, this.bindedChangeHandler);
|
|
214
227
|
return result;
|
|
215
228
|
}
|
|
216
229
|
}
|
|
@@ -275,6 +288,10 @@ class ArcCollection extends ArcContextElement {
|
|
|
275
288
|
...parsed
|
|
276
289
|
};
|
|
277
290
|
await store.set(body);
|
|
291
|
+
await publishEvent({
|
|
292
|
+
type: "set",
|
|
293
|
+
to: body
|
|
294
|
+
});
|
|
278
295
|
return { id };
|
|
279
296
|
},
|
|
280
297
|
remove: async (id) => {
|
|
@@ -288,6 +305,10 @@ class ArcCollection extends ArcContextElement {
|
|
|
288
305
|
...parsed
|
|
289
306
|
};
|
|
290
307
|
await store.set(body);
|
|
308
|
+
await publishEvent({
|
|
309
|
+
type: "set",
|
|
310
|
+
to: body
|
|
311
|
+
});
|
|
291
312
|
return { success: true };
|
|
292
313
|
},
|
|
293
314
|
all: async () => {
|
|
@@ -297,11 +318,19 @@ class ArcCollection extends ArcContextElement {
|
|
|
297
318
|
return store.findById(id);
|
|
298
319
|
},
|
|
299
320
|
modify: async (id, data) => {
|
|
300
|
-
const deserialized = this.schema.
|
|
321
|
+
const deserialized = this.schema.serializePartial(data);
|
|
301
322
|
const { from, to } = await store.modify(id, deserialized);
|
|
302
323
|
await publishEvent({
|
|
303
324
|
type: "modify",
|
|
304
|
-
changes:
|
|
325
|
+
changes: deserialized,
|
|
326
|
+
from,
|
|
327
|
+
to
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
edit: async (id, editCallback) => {
|
|
331
|
+
const { from, to } = await store.mutate(id, editCallback);
|
|
332
|
+
await publishEvent({
|
|
333
|
+
type: "mutate",
|
|
305
334
|
from,
|
|
306
335
|
to
|
|
307
336
|
});
|
|
@@ -376,9 +405,12 @@ class ArcContext {
|
|
|
376
405
|
}
|
|
377
406
|
});
|
|
378
407
|
}
|
|
379
|
-
commandContext(dataStorage, publishEvent) {
|
|
408
|
+
commandContext(client, dataStorage, publishEvent) {
|
|
380
409
|
return new Proxy({}, {
|
|
381
410
|
get: (target, name) => {
|
|
411
|
+
if (name === "$client") {
|
|
412
|
+
return client;
|
|
413
|
+
}
|
|
382
414
|
const element = this.elementsMap[name];
|
|
383
415
|
return element.commandContext(dataStorage, (event) => publishEvent({
|
|
384
416
|
element: name,
|
|
@@ -387,20 +419,26 @@ class ArcContext {
|
|
|
387
419
|
}
|
|
388
420
|
});
|
|
389
421
|
}
|
|
390
|
-
commandsClient(dataStorage) {
|
|
422
|
+
commandsClient(client, dataStorage, catchErrorCallback) {
|
|
391
423
|
return new Proxy({}, {
|
|
392
424
|
get: (_, name) => {
|
|
393
425
|
if (name in this.commands) {
|
|
394
426
|
return async (...args) => {
|
|
395
427
|
const forkedDataStorage = dataStorage.fork();
|
|
396
|
-
const commandContext = this.commandContext(forkedDataStorage, async (data) => {
|
|
428
|
+
const commandContext = this.commandContext(client, forkedDataStorage, async (data) => {
|
|
397
429
|
if (!this.listeners)
|
|
398
430
|
return;
|
|
399
431
|
await Promise.all(this.listeners?.map((listener) => listener(data, commandContext)));
|
|
400
432
|
});
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
433
|
+
try {
|
|
434
|
+
const result = await this.commands[name](commandContext, ...args);
|
|
435
|
+
await forkedDataStorage.merge();
|
|
436
|
+
return result;
|
|
437
|
+
} catch (error) {
|
|
438
|
+
console.log("error", error);
|
|
439
|
+
catchErrorCallback(error);
|
|
440
|
+
return error;
|
|
441
|
+
}
|
|
404
442
|
};
|
|
405
443
|
}
|
|
406
444
|
console.warn(`Command '${name}' not found in the context.`);
|
|
@@ -409,12 +447,41 @@ class ArcContext {
|
|
|
409
447
|
});
|
|
410
448
|
}
|
|
411
449
|
}
|
|
450
|
+
// data-storage/data-storage.abstract.ts
|
|
451
|
+
class DataStorage {
|
|
452
|
+
async commitChanges(changes) {
|
|
453
|
+
await Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// data-storage/store-state-fork.ts
|
|
458
|
+
import { apply } from "mutative";
|
|
459
|
+
|
|
460
|
+
// data-storage/deep-merge.ts
|
|
461
|
+
function deepMerge(target, source) {
|
|
462
|
+
const output = { ...target };
|
|
463
|
+
for (const key in source) {
|
|
464
|
+
if (source[key] === undefined)
|
|
465
|
+
continue;
|
|
466
|
+
if (isObject(source[key]) && isObject(target[key])) {
|
|
467
|
+
output[key] = deepMerge(target[key], source[key]);
|
|
468
|
+
} else {
|
|
469
|
+
output[key] = source[key];
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return output;
|
|
473
|
+
}
|
|
474
|
+
function isObject(item) {
|
|
475
|
+
return item && typeof item === "object" && !Array.isArray(item);
|
|
476
|
+
}
|
|
477
|
+
|
|
412
478
|
// data-storage/store-state.abstract.ts
|
|
479
|
+
import { create } from "mutative";
|
|
413
480
|
class StoreState {
|
|
414
481
|
storeName;
|
|
415
482
|
dataStorage;
|
|
416
483
|
deserialize;
|
|
417
|
-
listeners = new
|
|
484
|
+
listeners = new Map;
|
|
418
485
|
constructor(storeName, dataStorage, deserialize) {
|
|
419
486
|
this.storeName = storeName;
|
|
420
487
|
this.dataStorage = dataStorage;
|
|
@@ -446,11 +513,24 @@ class StoreState {
|
|
|
446
513
|
const { from, to } = await this.applyChange(change);
|
|
447
514
|
return { from, to };
|
|
448
515
|
}
|
|
516
|
+
async mutate(id, editCallback) {
|
|
517
|
+
const object = await this.findById(id);
|
|
518
|
+
const [draft, finalize] = create(object || {}, { enablePatches: true });
|
|
519
|
+
await editCallback(draft);
|
|
520
|
+
const [_, patches] = finalize();
|
|
521
|
+
const change = {
|
|
522
|
+
type: "mutate",
|
|
523
|
+
id,
|
|
524
|
+
patches
|
|
525
|
+
};
|
|
526
|
+
const { from, to } = await this.applyChange(change);
|
|
527
|
+
return { from, to };
|
|
528
|
+
}
|
|
449
529
|
unsubscribe(listener) {
|
|
450
530
|
this.listeners.delete(listener);
|
|
451
531
|
}
|
|
452
532
|
notifyListeners(events) {
|
|
453
|
-
for (const listener of this.listeners) {
|
|
533
|
+
for (const listener of this.listeners.values()) {
|
|
454
534
|
listener.callback(events);
|
|
455
535
|
}
|
|
456
536
|
}
|
|
@@ -495,7 +575,22 @@ class ForkedStoreState extends StoreState {
|
|
|
495
575
|
}
|
|
496
576
|
if (change.type === "modify") {
|
|
497
577
|
const existing = await this.findById(change.id);
|
|
498
|
-
const updated = existing ?
|
|
578
|
+
const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
|
|
579
|
+
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
580
|
+
this.changedItems.set(change.id, item);
|
|
581
|
+
return {
|
|
582
|
+
from: existing || null,
|
|
583
|
+
to: item,
|
|
584
|
+
event: {
|
|
585
|
+
type: "set",
|
|
586
|
+
item,
|
|
587
|
+
id: change.id
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
if (change.type === "mutate") {
|
|
592
|
+
const existing = await this.findById(change.id);
|
|
593
|
+
const updated = apply(existing || {}, change.patches);
|
|
499
594
|
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
500
595
|
this.changedItems.set(change.id, item);
|
|
501
596
|
return {
|
|
@@ -528,25 +623,34 @@ class ForkedStoreState extends StoreState {
|
|
|
528
623
|
}
|
|
529
624
|
async findById(id, listener) {
|
|
530
625
|
if (listener)
|
|
531
|
-
this.listeners.
|
|
626
|
+
this.listeners.set(listener, { callback: listener, id });
|
|
532
627
|
if (this.changedItems.has(id))
|
|
533
628
|
return this.changedItems.get(id);
|
|
534
629
|
return await this.master.findById(id);
|
|
535
630
|
}
|
|
536
631
|
async findByIndex(index, data, listener) {
|
|
537
632
|
if (listener)
|
|
538
|
-
this.listeners.
|
|
633
|
+
this.listeners.set(listener, { callback: listener });
|
|
539
634
|
const parentResult = await this.master.findByIndex(index, data);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
635
|
+
const results = new Map;
|
|
636
|
+
parentResult.forEach((item) => results.set(item._id, item));
|
|
637
|
+
for (const [id, changedItem] of this.changedItems) {
|
|
638
|
+
if (changedItem === null) {
|
|
639
|
+
results.delete(id);
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
const matches = Object.entries(data).every(([key, value]) => changedItem[key] === value);
|
|
643
|
+
if (matches) {
|
|
644
|
+
results.set(id, changedItem);
|
|
645
|
+
} else {
|
|
646
|
+
results.delete(id);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return Array.from(results.values());
|
|
546
650
|
}
|
|
547
651
|
async findAll(listener) {
|
|
548
652
|
if (listener)
|
|
549
|
-
this.listeners.
|
|
653
|
+
this.listeners.set(listener, { callback: listener });
|
|
550
654
|
const parentResult = await this.master.findAll();
|
|
551
655
|
return parentResult.map((item) => {
|
|
552
656
|
const id = item._id;
|
|
@@ -558,10 +662,11 @@ class ForkedStoreState extends StoreState {
|
|
|
558
662
|
}
|
|
559
663
|
|
|
560
664
|
// data-storage/data-storage-forked.ts
|
|
561
|
-
class ForkedDataStorage {
|
|
665
|
+
class ForkedDataStorage extends DataStorage {
|
|
562
666
|
master;
|
|
563
667
|
stores = new Map;
|
|
564
668
|
constructor(master) {
|
|
669
|
+
super();
|
|
565
670
|
this.master = master;
|
|
566
671
|
}
|
|
567
672
|
getReadTransaction() {
|
|
@@ -582,12 +687,15 @@ class ForkedDataStorage {
|
|
|
582
687
|
return new ForkedDataStorage(this);
|
|
583
688
|
}
|
|
584
689
|
async merge() {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
690
|
+
const changes = Array.from(this.stores.values()).filter((store) => store.changes.length > 0).map((store) => ({
|
|
691
|
+
store: store.storeName,
|
|
692
|
+
changes: store.changes
|
|
693
|
+
}));
|
|
694
|
+
await this.master.commitChanges(changes);
|
|
588
695
|
}
|
|
589
696
|
}
|
|
590
697
|
// data-storage/store-state-master.ts
|
|
698
|
+
import { apply as apply2 } from "mutative";
|
|
591
699
|
class MasterStoreState extends StoreState {
|
|
592
700
|
items = new Map;
|
|
593
701
|
isComplete = false;
|
|
@@ -624,7 +732,23 @@ class MasterStoreState extends StoreState {
|
|
|
624
732
|
}
|
|
625
733
|
if (change.type === "modify") {
|
|
626
734
|
const existing = await transaction.findById(this.storeName, change.id);
|
|
627
|
-
const updated = existing ?
|
|
735
|
+
const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
|
|
736
|
+
await transaction.set(this.storeName, updated);
|
|
737
|
+
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
738
|
+
this.items.set(change.id, item);
|
|
739
|
+
return {
|
|
740
|
+
from: null,
|
|
741
|
+
to: item,
|
|
742
|
+
event: {
|
|
743
|
+
type: "set",
|
|
744
|
+
item,
|
|
745
|
+
id: change.id
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
if (change.type === "mutate") {
|
|
750
|
+
const existing = await transaction.findById(this.storeName, change.id);
|
|
751
|
+
const updated = apply2(existing, change.patches);
|
|
628
752
|
await transaction.set(this.storeName, updated);
|
|
629
753
|
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
630
754
|
this.items.set(change.id, item);
|
|
@@ -661,20 +785,20 @@ class MasterStoreState extends StoreState {
|
|
|
661
785
|
}
|
|
662
786
|
async findById(id, listener) {
|
|
663
787
|
if (listener)
|
|
664
|
-
this.listeners.
|
|
788
|
+
this.listeners.set(listener, { callback: listener, id });
|
|
665
789
|
if (this.items.has(id))
|
|
666
790
|
return this.items.get(id);
|
|
667
791
|
const transaction = await this.dataStorage.getReadTransaction();
|
|
668
792
|
const result = await transaction.findById(this.storeName, id);
|
|
669
|
-
|
|
793
|
+
const item = result && this.deserialize ? this.deserialize(result) : result;
|
|
794
|
+
if (!item)
|
|
670
795
|
return;
|
|
671
|
-
const item = this.deserialize ? this.deserialize(result) : result;
|
|
672
796
|
this.items.set(id, item);
|
|
673
797
|
return item;
|
|
674
798
|
}
|
|
675
799
|
async findByIndex(index, data, listener) {
|
|
676
800
|
if (listener)
|
|
677
|
-
this.listeners.
|
|
801
|
+
this.listeners.set(listener, { callback: listener });
|
|
678
802
|
if (this.isComplete) {
|
|
679
803
|
const results2 = Array.from(this.items.values()).filter((item) => {
|
|
680
804
|
if (!item)
|
|
@@ -697,7 +821,7 @@ class MasterStoreState extends StoreState {
|
|
|
697
821
|
}
|
|
698
822
|
async findAll(listener) {
|
|
699
823
|
if (listener)
|
|
700
|
-
this.listeners.
|
|
824
|
+
this.listeners.set(listener, { callback: listener });
|
|
701
825
|
if (this.isComplete)
|
|
702
826
|
return Array.from(this.items.values()).filter((e) => !!e);
|
|
703
827
|
const transaction = await this.dataStorage.getReadTransaction();
|
|
@@ -716,12 +840,13 @@ class MasterStoreState extends StoreState {
|
|
|
716
840
|
}
|
|
717
841
|
|
|
718
842
|
// data-storage/data-storage-master.ts
|
|
719
|
-
class MasterDataStorage {
|
|
843
|
+
class MasterDataStorage extends DataStorage {
|
|
720
844
|
dbAdapter;
|
|
721
845
|
arcContext;
|
|
722
846
|
stores = new Map;
|
|
723
847
|
rtcAdapter;
|
|
724
848
|
constructor(dbAdapter, rtcAdapterFactory, arcContext) {
|
|
849
|
+
super();
|
|
725
850
|
this.dbAdapter = dbAdapter;
|
|
726
851
|
this.arcContext = arcContext;
|
|
727
852
|
this.rtcAdapter = rtcAdapterFactory(this);
|
|
@@ -741,6 +866,15 @@ class MasterDataStorage {
|
|
|
741
866
|
}
|
|
742
867
|
return this.stores.get(storeName);
|
|
743
868
|
}
|
|
869
|
+
async applyChanges(changes) {
|
|
870
|
+
return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
|
|
871
|
+
}
|
|
872
|
+
async commitChanges(changes) {
|
|
873
|
+
await Promise.all([
|
|
874
|
+
this.applyChanges(changes),
|
|
875
|
+
this.rtcAdapter.commitChanges(changes)
|
|
876
|
+
]);
|
|
877
|
+
}
|
|
744
878
|
fork() {
|
|
745
879
|
return new ForkedDataStorage(this);
|
|
746
880
|
}
|
|
@@ -863,7 +997,10 @@ class ArcObject extends ArcAbstract {
|
|
|
863
997
|
}, {});
|
|
864
998
|
}
|
|
865
999
|
deserialize(value) {
|
|
866
|
-
return Object.fromEntries(Object.entries(this.rawShape).
|
|
1000
|
+
return Object.fromEntries(Object.entries(this.rawShape).map(([key, element]) => [
|
|
1001
|
+
key,
|
|
1002
|
+
element.deserialize(value[key])
|
|
1003
|
+
]));
|
|
867
1004
|
}
|
|
868
1005
|
deserializePath(path, value) {
|
|
869
1006
|
if (path.length === 0) {
|
|
@@ -880,6 +1017,24 @@ class ArcObject extends ArcAbstract {
|
|
|
880
1017
|
}
|
|
881
1018
|
return element.deserialize(value);
|
|
882
1019
|
}
|
|
1020
|
+
parsePartial(value) {
|
|
1021
|
+
return Object.entries(value).reduce((acc, [key, value2]) => {
|
|
1022
|
+
acc[key] = this.rawShape[key].parse(value2);
|
|
1023
|
+
return acc;
|
|
1024
|
+
}, {});
|
|
1025
|
+
}
|
|
1026
|
+
deserializePartial(value) {
|
|
1027
|
+
return Object.entries(value).reduce((acc, [key, value2]) => {
|
|
1028
|
+
acc[key] = this.rawShape[key].deserialize(value2);
|
|
1029
|
+
return acc;
|
|
1030
|
+
}, {});
|
|
1031
|
+
}
|
|
1032
|
+
serializePartial(value) {
|
|
1033
|
+
return Object.entries(value).reduce((acc, [key, value2]) => {
|
|
1034
|
+
acc[key] = this.rawShape[key].serialize(value2);
|
|
1035
|
+
return acc;
|
|
1036
|
+
}, {});
|
|
1037
|
+
}
|
|
883
1038
|
}
|
|
884
1039
|
|
|
885
1040
|
// elements/array.ts
|
|
@@ -948,7 +1103,7 @@ class ArcDate extends ArcAbstract {
|
|
|
948
1103
|
return new Date(value);
|
|
949
1104
|
}
|
|
950
1105
|
serialize(value) {
|
|
951
|
-
return value.
|
|
1106
|
+
return value.getTime();
|
|
952
1107
|
}
|
|
953
1108
|
deserialize(value) {
|
|
954
1109
|
return new Date(value);
|
|
@@ -985,6 +1140,44 @@ function number() {
|
|
|
985
1140
|
|
|
986
1141
|
class ArcNumber extends ArcPrimitive {
|
|
987
1142
|
}
|
|
1143
|
+
// elements/record.ts
|
|
1144
|
+
function record(key, element) {
|
|
1145
|
+
return new ArcRecord(key, element);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
class ArcRecord extends ArcAbstract {
|
|
1149
|
+
key;
|
|
1150
|
+
element;
|
|
1151
|
+
constructor(key, element) {
|
|
1152
|
+
super();
|
|
1153
|
+
this.key = key;
|
|
1154
|
+
this.element = element;
|
|
1155
|
+
}
|
|
1156
|
+
parse(value) {
|
|
1157
|
+
if (!value)
|
|
1158
|
+
return {};
|
|
1159
|
+
return Object.entries(value).reduce((acc, [key, recordValue]) => {
|
|
1160
|
+
acc[key] = this.element.parse(recordValue);
|
|
1161
|
+
return acc;
|
|
1162
|
+
}, {});
|
|
1163
|
+
}
|
|
1164
|
+
serialize(value) {
|
|
1165
|
+
if (!value)
|
|
1166
|
+
return {};
|
|
1167
|
+
return Object.entries(value).reduce((acc, [key, recordValue]) => {
|
|
1168
|
+
acc[key] = this.element.serialize(recordValue);
|
|
1169
|
+
return acc;
|
|
1170
|
+
}, {});
|
|
1171
|
+
}
|
|
1172
|
+
deserialize(value) {
|
|
1173
|
+
if (!value)
|
|
1174
|
+
return {};
|
|
1175
|
+
return Object.entries(value).reduce((acc, [key, recordValue]) => {
|
|
1176
|
+
acc[key] = this.element.deserialize(recordValue);
|
|
1177
|
+
return acc;
|
|
1178
|
+
}, {});
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
988
1181
|
// elements/string-enum.ts
|
|
989
1182
|
function stringEnum(...values) {
|
|
990
1183
|
return new ArcStringEnum(values);
|
|
@@ -1113,6 +1306,7 @@ class RTCClient {
|
|
|
1113
1306
|
});
|
|
1114
1307
|
break;
|
|
1115
1308
|
case "state-changes":
|
|
1309
|
+
this.storage.applyChanges(message.changes);
|
|
1116
1310
|
break;
|
|
1117
1311
|
default:
|
|
1118
1312
|
console.warn(`Message unsupported`, message);
|
|
@@ -1126,10 +1320,111 @@ class RTCClient {
|
|
|
1126
1320
|
var rtcClientFactory = (storage) => {
|
|
1127
1321
|
return new RTCClient(storage);
|
|
1128
1322
|
};
|
|
1323
|
+
// state/query.ts
|
|
1324
|
+
class ArcStateQuery extends ArcQuery {
|
|
1325
|
+
state;
|
|
1326
|
+
bindedChangeHandler = this.changeHandler.bind(this);
|
|
1327
|
+
store;
|
|
1328
|
+
constructor(state) {
|
|
1329
|
+
super();
|
|
1330
|
+
this.state = state;
|
|
1331
|
+
}
|
|
1332
|
+
async run(dataStorage, listener) {
|
|
1333
|
+
this.store = dataStorage.getStore("state");
|
|
1334
|
+
const result = await this.store.findById(this.state.name, this.bindedChangeHandler);
|
|
1335
|
+
this.lastResult = this.state.deserialize(result);
|
|
1336
|
+
if (listener)
|
|
1337
|
+
this.listener = listener;
|
|
1338
|
+
return this.lastResult;
|
|
1339
|
+
}
|
|
1340
|
+
onChange(change) {
|
|
1341
|
+
if (change.type === "set")
|
|
1342
|
+
return change.item;
|
|
1343
|
+
return false;
|
|
1344
|
+
}
|
|
1345
|
+
changeHandler(changes) {
|
|
1346
|
+
for (const change of changes) {
|
|
1347
|
+
const response = this.onChange(change);
|
|
1348
|
+
if (response !== false)
|
|
1349
|
+
this.lastResult = this.state.deserialize(response);
|
|
1350
|
+
}
|
|
1351
|
+
if (this.lastResult)
|
|
1352
|
+
this.nextResult(this.lastResult);
|
|
1353
|
+
}
|
|
1354
|
+
unsubscribe() {
|
|
1355
|
+
this.store.unsubscribe(this.bindedChangeHandler);
|
|
1356
|
+
}
|
|
1357
|
+
nextResult(result) {
|
|
1358
|
+
this.lastResult = result;
|
|
1359
|
+
this.listener?.(result);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// state/query-builder.ts
|
|
1364
|
+
class ArcStateQueryBuilder extends ArcQueryBuilder {
|
|
1365
|
+
state;
|
|
1366
|
+
constructor(state) {
|
|
1367
|
+
super();
|
|
1368
|
+
this.state = state;
|
|
1369
|
+
}
|
|
1370
|
+
toQuery() {
|
|
1371
|
+
return new ArcStateQuery(this.state);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// state/state.ts
|
|
1376
|
+
function state(name, schema) {
|
|
1377
|
+
return new ArcState(name, schema);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
class ArcState extends ArcContextElement {
|
|
1381
|
+
name;
|
|
1382
|
+
schema;
|
|
1383
|
+
constructor(name, schema) {
|
|
1384
|
+
super();
|
|
1385
|
+
this.name = name;
|
|
1386
|
+
this.schema = schema;
|
|
1387
|
+
}
|
|
1388
|
+
serialize(data) {
|
|
1389
|
+
return {
|
|
1390
|
+
...this.schema.serialize(data),
|
|
1391
|
+
_id: this.name
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
deserialize(data) {
|
|
1395
|
+
return this.schema.deserialize(data || {});
|
|
1396
|
+
}
|
|
1397
|
+
queryBuilder() {
|
|
1398
|
+
return new ArcStateQueryBuilder(this);
|
|
1399
|
+
}
|
|
1400
|
+
commandContext(dataStorage, publishEvent) {
|
|
1401
|
+
const store = dataStorage.getStore("state");
|
|
1402
|
+
return {
|
|
1403
|
+
get: async () => {
|
|
1404
|
+
return store.findById(this.name);
|
|
1405
|
+
},
|
|
1406
|
+
modify: async (data) => {
|
|
1407
|
+
const serialized = this.serialize(data);
|
|
1408
|
+
const { from, to } = await store.modify(this.name, serialized);
|
|
1409
|
+
await publishEvent({
|
|
1410
|
+
type: "modify",
|
|
1411
|
+
changes: data,
|
|
1412
|
+
from,
|
|
1413
|
+
to
|
|
1414
|
+
});
|
|
1415
|
+
},
|
|
1416
|
+
edit: async (editCallback) => {
|
|
1417
|
+
const { from, to } = await store.mutate(this.name, editCallback);
|
|
1418
|
+
}
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1129
1422
|
export {
|
|
1130
1423
|
stringEnum,
|
|
1131
1424
|
string,
|
|
1425
|
+
state,
|
|
1132
1426
|
rtcClientFactory,
|
|
1427
|
+
record,
|
|
1133
1428
|
object,
|
|
1134
1429
|
number,
|
|
1135
1430
|
id,
|
|
@@ -1143,9 +1438,13 @@ export {
|
|
|
1143
1438
|
MasterDataStorage,
|
|
1144
1439
|
ForkedStoreState,
|
|
1145
1440
|
ForkedDataStorage,
|
|
1441
|
+
DataStorage,
|
|
1146
1442
|
ArcStringEnum,
|
|
1147
1443
|
ArcString,
|
|
1444
|
+
ArcState,
|
|
1445
|
+
ArcRecord,
|
|
1148
1446
|
ArcQueryBuilder,
|
|
1447
|
+
ArcQuery,
|
|
1149
1448
|
ArcOptional,
|
|
1150
1449
|
ArcObject,
|
|
1151
1450
|
ArcNumber,
|
package/dist/rtc/index.d.ts
CHANGED
package/dist/rtc/messages.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DataStorageChanges } from "../data-storage/data-storage.abstract";
|
|
2
2
|
export type MessageClientToHost = {
|
|
3
3
|
type: "sync";
|
|
4
4
|
lastDate: string | null;
|
|
5
5
|
} | {
|
|
6
6
|
type: "changes-executed";
|
|
7
|
-
changes:
|
|
7
|
+
changes: DataStorageChanges[];
|
|
8
8
|
};
|
|
9
9
|
export type MessageHostToClient = {
|
|
10
10
|
type: "sync-result";
|
|
@@ -12,7 +12,7 @@ export type MessageHostToClient = {
|
|
|
12
12
|
items: any[];
|
|
13
13
|
} | {
|
|
14
14
|
type: "state-changes";
|
|
15
|
-
changes:
|
|
15
|
+
changes: DataStorageChanges[];
|
|
16
16
|
} | {
|
|
17
17
|
type: "sync-done";
|
|
18
18
|
date: string;
|
package/dist/rtc/rtc.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MasterDataStorage } from "../data-storage";
|
|
2
|
+
import type { DataStorageChanges } from "../data-storage/data-storage.abstract";
|
|
2
3
|
export interface RealTimeCommunicationAdapter {
|
|
3
|
-
commitChanges(changes:
|
|
4
|
+
commitChanges(changes: DataStorageChanges[]): void;
|
|
4
5
|
sync(progressCallback: ({ store, size }: {
|
|
5
6
|
store: string;
|
|
6
7
|
size: number;
|
|
7
8
|
}) => void): Promise<void>;
|
|
8
9
|
}
|
|
9
|
-
export type RealTimeCommunicationAdapterFactory = (storage:
|
|
10
|
+
export type RealTimeCommunicationAdapterFactory = (storage: MasterDataStorage) => RealTimeCommunicationAdapter;
|
|
10
11
|
//# sourceMappingURL=rtc.d.ts.map
|