@arcote.tech/arc 0.0.11 → 0.0.13
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 +10 -4
- package/dist/collection/db.d.ts +1 -1
- package/dist/collection/in-memory-db-proxy.d.ts +10 -0
- package/dist/collection/queries/abstract-collection-query.d.ts +1 -1
- package/dist/collection/queries/one-item.d.ts +1 -1
- package/dist/collection/query-builders/abstract-many-items.d.ts +3 -1
- package/dist/elements/instanceOf.d.ts +19 -0
- package/dist/elements/or.d.ts +11 -0
- package/dist/elements/recurent.d.ts +20 -0
- package/dist/index.js +176 -12
- package/dist/model/index.d.ts +1 -0
- package/dist/model/model.d.ts +14 -6
- package/dist/model/rtc.d.ts +1 -1
- package/dist/model/submodel.d.ts +23 -0
- package/dist/rtc/messages.d.ts +1 -2
- package/package.json +1 -2
|
@@ -15,7 +15,8 @@ declare class ArcCollection<Name extends string, Id extends ArcIdAny, Schema ext
|
|
|
15
15
|
readonly name: Name;
|
|
16
16
|
readonly id: Id;
|
|
17
17
|
readonly schema: Schema;
|
|
18
|
-
|
|
18
|
+
readonly options: ArcCollectionOptions<Id, Schema>;
|
|
19
|
+
constructor(name: Name, id: Id, schema: Schema, options: ArcCollectionOptions<Id, Schema>);
|
|
19
20
|
serialize(data: objectUtil.simplify<{
|
|
20
21
|
_id: util.FirstArgument<Id["serialize"]>;
|
|
21
22
|
} & objectUtil.addQuestionMarks<util.FirstArgument<Schema["serialize"]>>>): objectUtil.simplify<{
|
|
@@ -31,7 +32,9 @@ declare class ArcCollection<Name extends string, Id extends ArcIdAny, Schema ext
|
|
|
31
32
|
commandContext(transaction: ReadTransaction, changes: CollectionChange[], getDraft: GetDraft<any>): {
|
|
32
33
|
one: (id: util.GetType<Id>) => Deserialize<Id, Schema>;
|
|
33
34
|
remove: (id: util.GetType<Id>) => Promise<any>;
|
|
34
|
-
add: (data: objectUtil.addQuestionMarks<util.FirstArgument<Schema["serialize"]>>) => Promise<
|
|
35
|
+
add: (data: objectUtil.addQuestionMarks<util.FirstArgument<Schema["serialize"]>>) => Promise<{
|
|
36
|
+
id: util.GetType<Id>;
|
|
37
|
+
}>;
|
|
35
38
|
set: (id: util.GetType<Id>, data: util.FirstArgument<Schema["serialize"]>) => Promise<any>;
|
|
36
39
|
};
|
|
37
40
|
applyChange(transaction: ReadWriteTransaction, change: CollectionChange, events: CollectionChange[]): Promise<void>;
|
|
@@ -43,7 +46,7 @@ export declare class ArcIndexedCollection<Name extends string, Id extends ArcIdA
|
|
|
43
46
|
[name: string]: Indexes[];
|
|
44
47
|
}> extends ArcCollection<Name, Id, Schema> implements ArcContextElement {
|
|
45
48
|
readonly indexes: I;
|
|
46
|
-
constructor(name: Name, id: Id, schema: Schema, indexes: I);
|
|
49
|
+
constructor(name: Name, id: Id, schema: Schema, options: ArcCollectionOptions<Id, Schema>, indexes: I);
|
|
47
50
|
queryBuilder(): {
|
|
48
51
|
all: () => ArcAllItemsQueryBuilder<ArcCollection<Name, Id, Schema>>;
|
|
49
52
|
one: (id: util.GetType<Id> | undefined) => ArcOneItemQueryBuilder<ArcCollection<Name, Id, Schema>>;
|
|
@@ -55,5 +58,8 @@ export declare class ArcIndexedCollection<Name extends string, Id extends ArcIdA
|
|
|
55
58
|
}
|
|
56
59
|
export type ArcCollectionAny = ArcCollection<any, any, any>;
|
|
57
60
|
export type ArcIndexedCollectionAny = ArcIndexedCollection<any, any, any, any, any>;
|
|
58
|
-
|
|
61
|
+
type ArcCollectionOptions<Id extends ArcIdAny, Schema extends ArcObjectAny> = {
|
|
62
|
+
sort?: (a: Deserialize<Id, Schema>, b: Deserialize<Id, Schema>) => number;
|
|
63
|
+
};
|
|
64
|
+
export declare function collection<Name extends string, Id extends ArcIdAny, Schema extends ArcObjectAny>(name: Name, id: Id, schema: Schema, options?: ArcCollectionOptions<Id, Schema>): ArcCollection<Name, Id, Schema>;
|
|
59
65
|
export {};
|
package/dist/collection/db.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface ReadWriteTransaction extends ReadTransaction {
|
|
|
7
7
|
commit(): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
export interface ReadTransaction {
|
|
10
|
-
findById<C extends ArcCollectionAny>(collection: C, id: util.GetType<C["id"]>): Promise<util.CollectionItemWithId<C
|
|
10
|
+
findById<C extends ArcCollectionAny>(collection: C, id: util.GetType<C["id"]>): Promise<util.CollectionItemWithId<C> | undefined>;
|
|
11
11
|
findByIndex<C extends ArcIndexedCollectionAny>(collection: C, index: string, data: any): Promise<util.CollectionItemWithId<C>[]>;
|
|
12
12
|
findAll<C extends ArcCollectionAny>(collection: C): Promise<util.CollectionItemWithId<C>[]>;
|
|
13
13
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ArcCollectionAny } from "../collection";
|
|
2
|
+
import type { DatabaseAdapter, ReadTransaction, ReadWriteTransaction } from "../collection/db";
|
|
3
|
+
export declare class InMemoryDatabaseProxyAdapter implements DatabaseAdapter {
|
|
4
|
+
private parentAdapter;
|
|
5
|
+
private local;
|
|
6
|
+
constructor(parentAdapter: DatabaseAdapter);
|
|
7
|
+
readWriteTransaction(collections: ArcCollectionAny[]): ReadWriteTransaction;
|
|
8
|
+
readTransaction(collections: ArcCollectionAny[]): ReadTransaction;
|
|
9
|
+
clearLocal(): void;
|
|
10
|
+
}
|
|
@@ -12,7 +12,7 @@ export declare abstract class ArcCollectionQuery<Collection extends ArcCollectio
|
|
|
12
12
|
getLastResult(): Response;
|
|
13
13
|
run(db: DatabaseAdapter, changes$: Subject<CollectionChange>): Promise<void>;
|
|
14
14
|
protected abstract onChange(change: CollectionChange): Response | false;
|
|
15
|
-
protected abstract fetch(transaction: ReadTransaction): Promise<Response> | undefined;
|
|
15
|
+
protected abstract fetch(transaction: ReadTransaction): Promise<Response | undefined> | undefined;
|
|
16
16
|
private changeHandler;
|
|
17
17
|
unsubscribe(): void;
|
|
18
18
|
private nextResult;
|
|
@@ -7,5 +7,5 @@ export declare class ArcOneItemQuery<Collection extends ArcCollectionAny> extend
|
|
|
7
7
|
private id;
|
|
8
8
|
constructor(collection: Collection, id: util.GetType<Collection["id"]>);
|
|
9
9
|
protected onChange(change: CollectionChange): any;
|
|
10
|
-
protected fetch(transaction: ReadTransaction): Promise<ReturnType<Collection["deserialize"]
|
|
10
|
+
protected fetch(transaction: ReadTransaction): Promise<ReturnType<Collection["deserialize"]> | undefined> | undefined;
|
|
11
11
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ArcQueryBuilder } from "../../context/query-builders";
|
|
2
2
|
import type { util } from "../../utils";
|
|
3
3
|
import { type ArcCollectionAny } from "../collection";
|
|
4
|
+
type SortComparator<C extends ArcCollectionAny> = ((a: util.CollectionItemWithId<C>, b: util.CollectionItemWithId<C>) => number) | Array<[keyof util.CollectionItemWithId<C>, "ASC" | "DESC"]>;
|
|
4
5
|
export declare abstract class ArcManyItemsQueryBuilder<C extends ArcCollectionAny> extends ArcQueryBuilder {
|
|
5
6
|
protected filterFn?: (item: util.CollectionItemWithId<C>) => boolean;
|
|
6
7
|
protected sortFn?: (a: util.CollectionItemWithId<C>, b: util.CollectionItemWithId<C>) => number;
|
|
7
8
|
filter(callback: (item: util.CollectionItemWithId<C>) => boolean): this;
|
|
8
|
-
sort(
|
|
9
|
+
sort(comparator: SortComparator<C>): this;
|
|
9
10
|
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ArcElement } from "./element";
|
|
2
|
+
import type { ArcRawShape } from "./object";
|
|
3
|
+
import { ArcOptional } from "./optional";
|
|
4
|
+
export declare function ArcClass<E extends ArcRawShape>(shape: E): {
|
|
5
|
+
new (): { [key in keyof E]: ReturnType<E[key]["deserialize"]>; };
|
|
6
|
+
};
|
|
7
|
+
export declare class ArcInstanceOf<E> implements ArcElement {
|
|
8
|
+
private Class;
|
|
9
|
+
constructor(Class: {
|
|
10
|
+
new (): E;
|
|
11
|
+
});
|
|
12
|
+
serialize(value: unknown): unknown;
|
|
13
|
+
deserialize(value: unknown): E;
|
|
14
|
+
parse(value: unknown): unknown;
|
|
15
|
+
optional(): ArcOptional<this>;
|
|
16
|
+
}
|
|
17
|
+
export declare function instanceOf<E>(element: {
|
|
18
|
+
new (): E;
|
|
19
|
+
}): ArcInstanceOf<E>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { util } from "../utils";
|
|
2
|
+
import type { ArcElement } from "./element";
|
|
3
|
+
export declare class ArcOr<T extends ArcElement[]> implements ArcElement {
|
|
4
|
+
private elements;
|
|
5
|
+
constructor(elements: T);
|
|
6
|
+
serialize(value: util.FirstArgument<T[number]["serialize"]>): ReturnType<T[number]["serialize"]>;
|
|
7
|
+
deserialize(value: util.FirstArgument<T[number]["deserialize"]>): ReturnType<T[number]["deserialize"]>;
|
|
8
|
+
parse(value: util.FirstArgument<T[number]["parse"]>): ReturnType<T[number]["parse"]>;
|
|
9
|
+
private isTypeOf;
|
|
10
|
+
}
|
|
11
|
+
export declare function or<T extends ArcElement[]>(...elements: T): ArcOr<T>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type util } from "../utils";
|
|
2
|
+
import { ArcAbstract } from "./abstract";
|
|
3
|
+
import type { ArcElement } from "./element";
|
|
4
|
+
import { ArcOptional } from "./optional";
|
|
5
|
+
export declare class ArcRecurent<E extends ArcElement, Brand extends string | symbol> implements ArcElement {
|
|
6
|
+
private parent;
|
|
7
|
+
constructor(parent: E);
|
|
8
|
+
serialize(value: util.FirstArgument<E["serialize"]> & {
|
|
9
|
+
__brand: Brand;
|
|
10
|
+
}): ReturnType<E["serialize"]>;
|
|
11
|
+
deserialize(value: util.FirstArgument<E["deserialize"]>): ReturnType<E["deserialize"]> & {
|
|
12
|
+
__brand: Brand;
|
|
13
|
+
};
|
|
14
|
+
parse(value: util.FirstArgument<E["parse"]>): ReturnType<E["parse"]> & {
|
|
15
|
+
__brand: Brand;
|
|
16
|
+
};
|
|
17
|
+
optional(): ArcOptional<this>;
|
|
18
|
+
}
|
|
19
|
+
export type ArcRecurentAny = ArcRecurent<ArcAbstract, any>;
|
|
20
|
+
export declare function recurent<E extends () => ArcElement>(element: E): ArcRecurent<ArcElement, string | symbol>;
|
package/dist/index.js
CHANGED
|
@@ -114,6 +114,23 @@ class ArcQueryBuilder {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
// collection/query-builders/abstract-many-items.ts
|
|
117
|
+
function sortComparatorBuilder(comparator) {
|
|
118
|
+
if (typeof comparator === "function") {
|
|
119
|
+
return comparator;
|
|
120
|
+
} else if (Array.isArray(comparator)) {
|
|
121
|
+
return (a, b) => {
|
|
122
|
+
for (const [key, order] of comparator) {
|
|
123
|
+
if (a[key] < b[key])
|
|
124
|
+
return order === "ASC" ? -1 : 1;
|
|
125
|
+
if (a[key] > b[key])
|
|
126
|
+
return order === "ASC" ? 1 : -1;
|
|
127
|
+
}
|
|
128
|
+
return 0;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
throw new Error("Invalid comparator type");
|
|
132
|
+
}
|
|
133
|
+
|
|
117
134
|
class ArcManyItemsQueryBuilder extends ArcQueryBuilder {
|
|
118
135
|
filterFn;
|
|
119
136
|
sortFn;
|
|
@@ -121,8 +138,8 @@ class ArcManyItemsQueryBuilder extends ArcQueryBuilder {
|
|
|
121
138
|
this.filterFn = callback;
|
|
122
139
|
return this;
|
|
123
140
|
}
|
|
124
|
-
sort(
|
|
125
|
-
this.sortFn =
|
|
141
|
+
sort(comparator) {
|
|
142
|
+
this.sortFn = sortComparatorBuilder(comparator);
|
|
126
143
|
return this;
|
|
127
144
|
}
|
|
128
145
|
}
|
|
@@ -133,6 +150,8 @@ class ArcAllItemsQueryBuilder extends ArcManyItemsQueryBuilder {
|
|
|
133
150
|
constructor(collection) {
|
|
134
151
|
super();
|
|
135
152
|
this.collection = collection;
|
|
153
|
+
if (collection.options.sort)
|
|
154
|
+
this.sortFn = collection.options.sort;
|
|
136
155
|
}
|
|
137
156
|
toQuery() {
|
|
138
157
|
return new ArcAllItemsQuery(this.collection, this.filterFn, this.sortFn);
|
|
@@ -175,6 +194,8 @@ class ArcIndexedItemsQueryBuilder extends ArcManyItemsQueryBuilder {
|
|
|
175
194
|
this.collection = collection;
|
|
176
195
|
this.index = index;
|
|
177
196
|
this.data = data;
|
|
197
|
+
if (collection.options.sort)
|
|
198
|
+
this.sortFn = collection.options.sort;
|
|
178
199
|
}
|
|
179
200
|
toQuery() {
|
|
180
201
|
return new ArcIndexedItemsQuery(this.collection, this.index, this.data, this.filterFn, this.sortFn);
|
|
@@ -217,18 +238,20 @@ class ArcOneItemQueryBuilder extends ArcQueryBuilder {
|
|
|
217
238
|
}
|
|
218
239
|
|
|
219
240
|
// collection/collection.ts
|
|
220
|
-
function collection(name, id, schema) {
|
|
221
|
-
return new ArcCollection(name, id, schema);
|
|
241
|
+
function collection(name, id, schema, options = {}) {
|
|
242
|
+
return new ArcCollection(name, id, schema, options);
|
|
222
243
|
}
|
|
223
244
|
|
|
224
245
|
class ArcCollection {
|
|
225
246
|
name;
|
|
226
247
|
id;
|
|
227
248
|
schema;
|
|
228
|
-
|
|
249
|
+
options;
|
|
250
|
+
constructor(name, id, schema, options) {
|
|
229
251
|
this.name = name;
|
|
230
252
|
this.id = id;
|
|
231
253
|
this.schema = schema;
|
|
254
|
+
this.options = options;
|
|
232
255
|
}
|
|
233
256
|
serialize(data) {
|
|
234
257
|
return {
|
|
@@ -304,14 +327,14 @@ class ArcCollection {
|
|
|
304
327
|
}
|
|
305
328
|
}
|
|
306
329
|
indexBy(indexes) {
|
|
307
|
-
return new ArcIndexedCollection(this.name, this.id, this.schema, indexes);
|
|
330
|
+
return new ArcIndexedCollection(this.name, this.id, this.schema, this.options, indexes);
|
|
308
331
|
}
|
|
309
332
|
}
|
|
310
333
|
|
|
311
334
|
class ArcIndexedCollection extends ArcCollection {
|
|
312
335
|
indexes;
|
|
313
|
-
constructor(name, id, schema, indexes) {
|
|
314
|
-
super(name, id, schema);
|
|
336
|
+
constructor(name, id, schema, options, indexes) {
|
|
337
|
+
super(name, id, schema, options);
|
|
315
338
|
this.indexes = indexes;
|
|
316
339
|
}
|
|
317
340
|
queryBuilder() {
|
|
@@ -713,7 +736,7 @@ class ArcModel {
|
|
|
713
736
|
const result = await command(context3, ...args);
|
|
714
737
|
const changes = await finalize();
|
|
715
738
|
await this.applyChangesForTransaction(transaction, changes);
|
|
716
|
-
this.rtc.
|
|
739
|
+
this.rtc.changesExecuted(changes);
|
|
717
740
|
return { changes, result };
|
|
718
741
|
}
|
|
719
742
|
async applyChangesForTransaction(transaction, changes) {
|
|
@@ -736,6 +759,147 @@ class ArcModel {
|
|
|
736
759
|
return this.context.collectionsMap[name];
|
|
737
760
|
}
|
|
738
761
|
}
|
|
762
|
+
// model/submodel.ts
|
|
763
|
+
import { Subject as Subject3 } from "rxjs";
|
|
764
|
+
|
|
765
|
+
// collection/in-memory-db-proxy.ts
|
|
766
|
+
class InMemoryTransaction {
|
|
767
|
+
parentTransaction;
|
|
768
|
+
local;
|
|
769
|
+
constructor(parentTransaction, local) {
|
|
770
|
+
this.parentTransaction = parentTransaction;
|
|
771
|
+
this.local = local;
|
|
772
|
+
}
|
|
773
|
+
async set(collection3, data) {
|
|
774
|
+
let collectionLocal = this.local.get(collection3.name);
|
|
775
|
+
if (!collectionLocal) {
|
|
776
|
+
collectionLocal = new Map;
|
|
777
|
+
this.local.set(collection3.name, collectionLocal);
|
|
778
|
+
}
|
|
779
|
+
collectionLocal.set(data._id, data);
|
|
780
|
+
}
|
|
781
|
+
async remove(collection3, id3) {
|
|
782
|
+
let collectionLocal = this.local.get(collection3.name);
|
|
783
|
+
if (!collectionLocal) {
|
|
784
|
+
collectionLocal = new Map;
|
|
785
|
+
this.local.set(collection3.name, collectionLocal);
|
|
786
|
+
}
|
|
787
|
+
collectionLocal.set(id3, null);
|
|
788
|
+
}
|
|
789
|
+
async findById(collection3, id3) {
|
|
790
|
+
const localItem = this.local.get(collection3.name)?.get(id3);
|
|
791
|
+
if (localItem !== undefined) {
|
|
792
|
+
return localItem === null ? undefined : localItem;
|
|
793
|
+
}
|
|
794
|
+
return this.parentTransaction.findById(collection3, id3);
|
|
795
|
+
}
|
|
796
|
+
async findByIndex(collection3, index, data) {
|
|
797
|
+
const parentResults = await this.parentTransaction.findByIndex(collection3, index, data);
|
|
798
|
+
const localResults = Array.from(this.local.get(collection3.name)?.values() || []).filter((item) => item !== null && this.matchesIndex(item, index, data));
|
|
799
|
+
return this.mergeResults(parentResults, localResults);
|
|
800
|
+
}
|
|
801
|
+
async findAll(collection3) {
|
|
802
|
+
const parentResults = await this.parentTransaction.findAll(collection3);
|
|
803
|
+
const localResults = Array.from(this.local.get(collection3.name)?.values() || []).filter((item) => item !== null);
|
|
804
|
+
return this.mergeResults(parentResults, localResults);
|
|
805
|
+
}
|
|
806
|
+
async commit() {
|
|
807
|
+
}
|
|
808
|
+
matchesIndex(item, index, data) {
|
|
809
|
+
return Object.entries(data).every(([key, value]) => item[key] === value);
|
|
810
|
+
}
|
|
811
|
+
mergeResults(parentResults, localResults) {
|
|
812
|
+
const mergedMap = new Map;
|
|
813
|
+
parentResults.forEach((item) => mergedMap.set(item._id, item));
|
|
814
|
+
localResults.forEach((item) => mergedMap.set(item._id, item));
|
|
815
|
+
return Array.from(mergedMap.values());
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
class InMemoryDatabaseProxyAdapter {
|
|
820
|
+
parentAdapter;
|
|
821
|
+
local = new Map;
|
|
822
|
+
constructor(parentAdapter) {
|
|
823
|
+
this.parentAdapter = parentAdapter;
|
|
824
|
+
}
|
|
825
|
+
readWriteTransaction(collections) {
|
|
826
|
+
const parentTransaction = this.parentAdapter.readWriteTransaction(collections);
|
|
827
|
+
return new InMemoryTransaction(parentTransaction, this.local);
|
|
828
|
+
}
|
|
829
|
+
readTransaction(collections) {
|
|
830
|
+
const parentTransaction = this.parentAdapter.readTransaction(collections);
|
|
831
|
+
return new InMemoryTransaction(parentTransaction, this.local);
|
|
832
|
+
}
|
|
833
|
+
clearLocal() {
|
|
834
|
+
this.local.clear();
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// model/submodel.ts
|
|
839
|
+
class ArcSubModel {
|
|
840
|
+
parentModel;
|
|
841
|
+
changes$ = new Subject3;
|
|
842
|
+
proxyAdapterPromise;
|
|
843
|
+
uncommitedChanges = [];
|
|
844
|
+
constructor(parentModel) {
|
|
845
|
+
this.parentModel = parentModel;
|
|
846
|
+
this.parentModel.changes$.subscribe(this.changes$);
|
|
847
|
+
this.proxyAdapterPromise = this.parentModel.dbAdapterPromise.then((dbAdapter) => new InMemoryDatabaseProxyAdapter(dbAdapter));
|
|
848
|
+
}
|
|
849
|
+
query(queryFactory) {
|
|
850
|
+
const queryBuilder = this.context.queryBuilder();
|
|
851
|
+
const query = queryFactory(queryBuilder).toQuery();
|
|
852
|
+
this.runQuery(query);
|
|
853
|
+
return query;
|
|
854
|
+
}
|
|
855
|
+
async runQuery(query) {
|
|
856
|
+
const proxyAdapter = await this.proxyAdapterPromise;
|
|
857
|
+
query.run(proxyAdapter, this.changes$);
|
|
858
|
+
}
|
|
859
|
+
commands() {
|
|
860
|
+
return new Proxy({}, {
|
|
861
|
+
get: (target, name) => {
|
|
862
|
+
if (name in this.parentModel.context.commands) {
|
|
863
|
+
return async (...args) => {
|
|
864
|
+
const { result } = await this.executeCommand(this.parentModel.context.commands[name], ...args);
|
|
865
|
+
return result;
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
console.warn(`Command '${name}' not found in the context.`);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
async executeCommand(command, ...args) {
|
|
874
|
+
const proxyAdapter = await this.proxyAdapterPromise;
|
|
875
|
+
const transaction = proxyAdapter.readWriteTransaction(this.parentModel.context.collections);
|
|
876
|
+
const { context: context3, finalize } = await this.parentModel.context.commandContext(transaction);
|
|
877
|
+
const result = await command(context3, ...args);
|
|
878
|
+
const changes = await finalize();
|
|
879
|
+
const events = [];
|
|
880
|
+
for (const change of changes) {
|
|
881
|
+
await this.context.applyChange(transaction, change, events);
|
|
882
|
+
}
|
|
883
|
+
this.uncommitedChanges.push(...changes);
|
|
884
|
+
events.forEach((change) => this.changes$.next(change));
|
|
885
|
+
return { changes, result };
|
|
886
|
+
}
|
|
887
|
+
getCollection(name) {
|
|
888
|
+
return this.parentModel.getCollection(name);
|
|
889
|
+
}
|
|
890
|
+
async applyChanges(changes) {
|
|
891
|
+
const proxyAdapter = await this.proxyAdapterPromise;
|
|
892
|
+
const transaction = proxyAdapter.readWriteTransaction(this.parentModel.context.collections);
|
|
893
|
+
await this.parentModel.applyChangesForTransaction(transaction, changes);
|
|
894
|
+
}
|
|
895
|
+
get context() {
|
|
896
|
+
return this.parentModel.context;
|
|
897
|
+
}
|
|
898
|
+
async commitChanges() {
|
|
899
|
+
this.parentModel.applyChanges(this.uncommitedChanges);
|
|
900
|
+
this.parentModel.rtc.changesExecuted(this.uncommitedChanges);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
739
903
|
// rtc/deserializeChanges.ts
|
|
740
904
|
function deserializeChanges(changes, getCollection) {
|
|
741
905
|
return changes.map((change) => {
|
|
@@ -807,10 +971,9 @@ class RTCClient {
|
|
|
807
971
|
console.error("Max reconnect attempts reached. Giving up.");
|
|
808
972
|
}
|
|
809
973
|
}
|
|
810
|
-
|
|
974
|
+
changesExecuted(changes) {
|
|
811
975
|
return this.sendMessage({
|
|
812
|
-
type: "
|
|
813
|
-
command,
|
|
976
|
+
type: "changes-executed",
|
|
814
977
|
changes
|
|
815
978
|
});
|
|
816
979
|
}
|
|
@@ -874,6 +1037,7 @@ export {
|
|
|
874
1037
|
collection,
|
|
875
1038
|
boolean,
|
|
876
1039
|
array,
|
|
1040
|
+
ArcSubModel,
|
|
877
1041
|
ArcStringEnum,
|
|
878
1042
|
ArcString,
|
|
879
1043
|
ArcOptional,
|
package/dist/model/index.d.ts
CHANGED
package/dist/model/model.d.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { Subject } from "rxjs";
|
|
2
2
|
import type { ArcCollectionAny, ArcIndexedCollectionAny } from "../collection";
|
|
3
3
|
import type { CollectionChange } from "../collection/collection-change";
|
|
4
|
-
import type { DBAdapterFactory } from "../collection/db";
|
|
4
|
+
import type { DatabaseAdapter, DBAdapterFactory, ReadWriteTransaction } from "../collection/db";
|
|
5
5
|
import type { CommandsClient } from "../context/commands";
|
|
6
6
|
import { type ArcContextAny, type ArcContextWithCommandsAny } from "../context/context";
|
|
7
7
|
import type { ArcQuery } from "../context/query";
|
|
8
8
|
import type { QueryFactoryFunction } from "./query-builder";
|
|
9
|
-
import type { RealTimeCommunicationAdapterFactory } from "./rtc";
|
|
10
|
-
export
|
|
9
|
+
import type { RealTimeCommunicationAdapter, RealTimeCommunicationAdapterFactory } from "./rtc";
|
|
10
|
+
export interface IArcModel<C extends ArcContextWithCommandsAny> {
|
|
11
11
|
readonly context: C;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
changes$: Subject<CollectionChange>;
|
|
13
|
+
query(queryFactory: QueryFactoryFunction<C>): ArcQuery;
|
|
14
|
+
commands(): CommandsClient<C["commands"]>;
|
|
15
|
+
getCollection(name: string): ArcCollectionAny | ArcIndexedCollectionAny;
|
|
16
|
+
applyChanges(changes: CollectionChange[]): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare class ArcModel<C extends ArcContextWithCommandsAny> implements IArcModel<C> {
|
|
19
|
+
readonly context: C;
|
|
20
|
+
rtc: RealTimeCommunicationAdapter;
|
|
21
|
+
dbAdapterPromise: Promise<DatabaseAdapter>;
|
|
14
22
|
changes$: Subject<CollectionChange>;
|
|
15
23
|
constructor(context: C, dbAdapterFactory: DBAdapterFactory, rtcAdapterFactory: RealTimeCommunicationAdapterFactory);
|
|
16
24
|
query(queryFactory: QueryFactoryFunction<C>): ArcQuery;
|
|
@@ -20,7 +28,7 @@ export declare class ArcModel<C extends ArcContextWithCommandsAny> {
|
|
|
20
28
|
changes: CollectionChange[];
|
|
21
29
|
result: any;
|
|
22
30
|
}>;
|
|
23
|
-
|
|
31
|
+
applyChangesForTransaction(transaction: ReadWriteTransaction, changes: CollectionChange[]): Promise<void>;
|
|
24
32
|
private notifyChange;
|
|
25
33
|
applyChanges(changes: CollectionChange[]): Promise<void>;
|
|
26
34
|
getCollection(name: string): ArcCollectionAny | ArcIndexedCollectionAny;
|
package/dist/model/rtc.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CollectionChange } from "../collection/collection-change";
|
|
2
2
|
import type { ArcModelAny } from "./model";
|
|
3
3
|
export interface RealTimeCommunicationAdapter {
|
|
4
|
-
|
|
4
|
+
changesExecuted(changes: CollectionChange[]): void;
|
|
5
5
|
}
|
|
6
6
|
export type RealTimeCommunicationAdapterFactory = (model: ArcModelAny) => RealTimeCommunicationAdapter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Subject } from "rxjs";
|
|
2
|
+
import type { ArcCollectionAny, ArcIndexedCollectionAny } from "../collection";
|
|
3
|
+
import type { CollectionChange } from "../collection/collection-change";
|
|
4
|
+
import type { CommandsClient } from "../context/commands";
|
|
5
|
+
import type { ArcContextWithCommandsAny } from "../context/context";
|
|
6
|
+
import type { ArcQuery } from "../context/query";
|
|
7
|
+
import { ArcModel, type IArcModel } from "./model";
|
|
8
|
+
import type { QueryFactoryFunction } from "./query-builder";
|
|
9
|
+
export declare class ArcSubModel<C extends ArcContextWithCommandsAny> implements IArcModel<C> {
|
|
10
|
+
private parentModel;
|
|
11
|
+
changes$: Subject<CollectionChange>;
|
|
12
|
+
private proxyAdapterPromise;
|
|
13
|
+
private uncommitedChanges;
|
|
14
|
+
constructor(parentModel: ArcModel<C>);
|
|
15
|
+
query(queryFactory: QueryFactoryFunction<C>): ArcQuery;
|
|
16
|
+
private runQuery;
|
|
17
|
+
commands(): CommandsClient<C["commands"]>;
|
|
18
|
+
private executeCommand;
|
|
19
|
+
getCollection(name: string): ArcCollectionAny | ArcIndexedCollectionAny;
|
|
20
|
+
applyChanges(changes: CollectionChange[]): Promise<void>;
|
|
21
|
+
get context(): C;
|
|
22
|
+
commitChanges(): Promise<void>;
|
|
23
|
+
}
|
package/dist/rtc/messages.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "0.0.
|
|
7
|
+
"version": "0.0.13",
|
|
8
8
|
"private": false,
|
|
9
9
|
"author": "Przemysław Krasiński [arcote.tech]",
|
|
10
10
|
"description": "Arc is a framework designed to align code closely with business logic, streamlining development and enhancing productivity.",
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"build:declaration": "tsc --emitDeclarationOnly --project tsconfig.types.json",
|
|
14
14
|
"postbuild": "rimraf tsconfig.types.tsbuildinfo",
|
|
15
15
|
"type-check": "tsc",
|
|
16
|
-
"publish": "bun run build && npm publish --access=public",
|
|
17
16
|
"dev": "nodemon --ignore dist -e ts,tsx --exec 'bun run build'"
|
|
18
17
|
},
|
|
19
18
|
"dependencies": {
|