@arcote.tech/arc 0.0.18 → 0.0.20
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 +1 -1
- package/dist/elements/optional.d.ts +3 -3
- package/dist/index.js +55 -55
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ export type Deserialize<Id extends ArcIdAny, Schema extends ArcObjectAny> = obje
|
|
|
14
14
|
} & ReturnType<Schema["deserialize"]>>;
|
|
15
15
|
type CollectionQueryBuilder<T extends ArcCollection<any, any, any>> = {
|
|
16
16
|
all: () => ArcAllItemsQueryBuilder<T>;
|
|
17
|
-
one: (id: util.GetType<T["id"]> | undefined) => ArcOneItemQueryBuilder<T>;
|
|
17
|
+
one: (id: util.GetType<T["id"]> | undefined | null) => ArcOneItemQueryBuilder<T>;
|
|
18
18
|
};
|
|
19
19
|
type CollectionCommandContext<Id extends ArcIdAny, Schema extends ArcObjectAny> = {
|
|
20
20
|
one: (id: util.GetType<Id>) => Deserialize<Id, Schema>;
|
|
@@ -4,9 +4,9 @@ import type { ArcElement } from "./element";
|
|
|
4
4
|
export declare class ArcOptional<E extends ArcElement> implements ArcElement {
|
|
5
5
|
private parent;
|
|
6
6
|
constructor(parent: E);
|
|
7
|
-
parse(value: util.FirstArgument<E["parse"]> | undefined): ReturnType<E["parse"]> |
|
|
8
|
-
serialize(value: util.FirstArgument<E["serialize"]> | undefined): ReturnType<E["serialize"]> |
|
|
9
|
-
deserialize(value: util.FirstArgument<E["deserialize"]> | undefined): ReturnType<E["deserialize"]> |
|
|
7
|
+
parse(value: util.FirstArgument<E["parse"]> | null | undefined): ReturnType<E["parse"]> | null;
|
|
8
|
+
serialize(value: util.FirstArgument<E["serialize"]> | null | undefined): ReturnType<E["serialize"]> | null;
|
|
9
|
+
deserialize(value: util.FirstArgument<E["deserialize"]> | null | undefined): ReturnType<E["deserialize"]> | null;
|
|
10
10
|
}
|
|
11
11
|
export type ArcOptionalAny = ArcOptional<ArcAbstract>;
|
|
12
12
|
//# sourceMappingURL=optional.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -461,8 +461,10 @@ import { apply } from "mutative";
|
|
|
461
461
|
function deepMerge(target, source) {
|
|
462
462
|
const output = { ...target };
|
|
463
463
|
for (const key in source) {
|
|
464
|
-
if (source[key] === undefined)
|
|
464
|
+
if (source[key] === undefined) {
|
|
465
|
+
output[key] = undefined;
|
|
465
466
|
continue;
|
|
467
|
+
}
|
|
466
468
|
if (isObject(source[key]) && isObject(target[key])) {
|
|
467
469
|
output[key] = deepMerge(target[key], source[key]);
|
|
468
470
|
} else {
|
|
@@ -691,6 +693,7 @@ class ForkedDataStorage extends DataStorage {
|
|
|
691
693
|
store: store.storeName,
|
|
692
694
|
changes: store.changes
|
|
693
695
|
}));
|
|
696
|
+
console.log(changes);
|
|
694
697
|
await this.master.commitChanges(changes);
|
|
695
698
|
}
|
|
696
699
|
}
|
|
@@ -733,6 +736,7 @@ class MasterStoreState extends StoreState {
|
|
|
733
736
|
if (change.type === "modify") {
|
|
734
737
|
const existing = await transaction.findById(this.storeName, change.id);
|
|
735
738
|
const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
|
|
739
|
+
console.log("updated", updated);
|
|
736
740
|
await transaction.set(this.storeName, updated);
|
|
737
741
|
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
738
742
|
this.items.set(change.id, item);
|
|
@@ -890,17 +894,17 @@ class ArcOptional {
|
|
|
890
894
|
}
|
|
891
895
|
parse(value) {
|
|
892
896
|
if (!value)
|
|
893
|
-
return;
|
|
897
|
+
return null;
|
|
894
898
|
return this.parent.parse(value);
|
|
895
899
|
}
|
|
896
900
|
serialize(value) {
|
|
897
901
|
if (value)
|
|
898
902
|
return this.parent.serialize(value);
|
|
899
|
-
return;
|
|
903
|
+
return null;
|
|
900
904
|
}
|
|
901
905
|
deserialize(value) {
|
|
902
906
|
if (!value)
|
|
903
|
-
return;
|
|
907
|
+
return null;
|
|
904
908
|
return this.parent.deserialize(value);
|
|
905
909
|
}
|
|
906
910
|
}
|
|
@@ -1210,9 +1214,7 @@ class RTCClient {
|
|
|
1210
1214
|
reconnectAttempts = 0;
|
|
1211
1215
|
maxReconnectAttempts = 5;
|
|
1212
1216
|
syncProgressCallback;
|
|
1213
|
-
syncResolve;
|
|
1214
1217
|
syncPromise = null;
|
|
1215
|
-
pendingStoreChanges = [];
|
|
1216
1218
|
constructor(storage) {
|
|
1217
1219
|
this.storage = storage;
|
|
1218
1220
|
}
|
|
@@ -1220,13 +1222,54 @@ class RTCClient {
|
|
|
1220
1222
|
if (this.syncPromise)
|
|
1221
1223
|
return this.syncPromise;
|
|
1222
1224
|
this.syncProgressCallback = progressCallback;
|
|
1223
|
-
this.syncPromise =
|
|
1224
|
-
this.syncResolve = resolve;
|
|
1225
|
-
this.connect();
|
|
1226
|
-
});
|
|
1225
|
+
this.syncPromise = this.performSync();
|
|
1227
1226
|
return this.syncPromise;
|
|
1228
1227
|
}
|
|
1229
|
-
async
|
|
1228
|
+
async performSync() {
|
|
1229
|
+
this.connectWebSocket();
|
|
1230
|
+
const arcState = await this.storage.getStore("state").findById("$arc", (a) => a);
|
|
1231
|
+
const response = await fetch(`/ws/sync?lastSync=${arcState?.lastSyncDate || ""}`, {
|
|
1232
|
+
method: "GET",
|
|
1233
|
+
headers: {
|
|
1234
|
+
"Content-Type": "application/json"
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
if (!response.ok) {
|
|
1238
|
+
throw new Error("Sync failed");
|
|
1239
|
+
}
|
|
1240
|
+
const { results, syncDate } = await response.json();
|
|
1241
|
+
const pendingStoreChanges = [];
|
|
1242
|
+
for (const { store, items } of results) {
|
|
1243
|
+
this.syncProgressCallback?.({ store, size: items.length });
|
|
1244
|
+
const storeState = this.storage.getStore(store);
|
|
1245
|
+
if (!storeState) {
|
|
1246
|
+
console.error(`Store ${store} not found`);
|
|
1247
|
+
continue;
|
|
1248
|
+
}
|
|
1249
|
+
const changes = items.map((item) => {
|
|
1250
|
+
if (item.deleted) {
|
|
1251
|
+
return {
|
|
1252
|
+
type: "delete",
|
|
1253
|
+
id: item._id
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
return {
|
|
1257
|
+
type: "set",
|
|
1258
|
+
data: item
|
|
1259
|
+
};
|
|
1260
|
+
});
|
|
1261
|
+
pendingStoreChanges.push(storeState.applyChanges(changes));
|
|
1262
|
+
}
|
|
1263
|
+
await Promise.all(pendingStoreChanges);
|
|
1264
|
+
const stateStorage = this.storage.getStore("state");
|
|
1265
|
+
await stateStorage.applyChanges([
|
|
1266
|
+
{
|
|
1267
|
+
type: "set",
|
|
1268
|
+
data: { _id: "$arc", lastSyncDate: syncDate }
|
|
1269
|
+
}
|
|
1270
|
+
]);
|
|
1271
|
+
}
|
|
1272
|
+
async connectWebSocket() {
|
|
1230
1273
|
this._socket = new WebSocket(`wss://${window.location.host}/ws`);
|
|
1231
1274
|
this.openSocket = new Promise((resolve) => {
|
|
1232
1275
|
this._socket.addEventListener("open", () => {
|
|
@@ -1234,7 +1277,6 @@ class RTCClient {
|
|
|
1234
1277
|
resolve(this._socket);
|
|
1235
1278
|
});
|
|
1236
1279
|
});
|
|
1237
|
-
const arcState = await this.storage.getStore("state").findById("$arc", (a) => a);
|
|
1238
1280
|
this._socket.addEventListener("message", (e) => {
|
|
1239
1281
|
this.onMessage(JSON.parse(e.data));
|
|
1240
1282
|
});
|
|
@@ -1243,17 +1285,13 @@ class RTCClient {
|
|
|
1243
1285
|
console.error("WebSocket closed", e);
|
|
1244
1286
|
this.reconnect();
|
|
1245
1287
|
});
|
|
1246
|
-
this.sendMessage({
|
|
1247
|
-
type: "sync",
|
|
1248
|
-
lastDate: arcState?.lastSyncDate || null
|
|
1249
|
-
});
|
|
1250
1288
|
}
|
|
1251
1289
|
reconnect() {
|
|
1252
1290
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
1253
1291
|
const timeout = Math.pow(2, this.reconnectAttempts) * 1000;
|
|
1254
1292
|
setTimeout(() => {
|
|
1255
1293
|
this.reconnectAttempts++;
|
|
1256
|
-
this.
|
|
1294
|
+
this.connectWebSocket();
|
|
1257
1295
|
}, timeout);
|
|
1258
1296
|
} else {
|
|
1259
1297
|
console.error("Max reconnect attempts reached. Giving up.");
|
|
@@ -1267,44 +1305,6 @@ class RTCClient {
|
|
|
1267
1305
|
}
|
|
1268
1306
|
onMessage(message) {
|
|
1269
1307
|
switch (message.type) {
|
|
1270
|
-
case "sync-result":
|
|
1271
|
-
{
|
|
1272
|
-
const { store, items } = message;
|
|
1273
|
-
this.syncProgressCallback?.({ store, size: items.length });
|
|
1274
|
-
const storeState = this.storage.getStore(store);
|
|
1275
|
-
if (!storeState) {
|
|
1276
|
-
console.error(`Store ${store} not found`);
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
const changes = items.map((item) => {
|
|
1280
|
-
if (item.deleted) {
|
|
1281
|
-
return {
|
|
1282
|
-
type: "delete",
|
|
1283
|
-
id: item._id
|
|
1284
|
-
};
|
|
1285
|
-
}
|
|
1286
|
-
return {
|
|
1287
|
-
type: "set",
|
|
1288
|
-
data: item
|
|
1289
|
-
};
|
|
1290
|
-
});
|
|
1291
|
-
this.pendingStoreChanges.push(storeState.applyChanges(changes));
|
|
1292
|
-
}
|
|
1293
|
-
break;
|
|
1294
|
-
case "sync-done":
|
|
1295
|
-
Promise.all(this.pendingStoreChanges).then(() => {
|
|
1296
|
-
const stateStorage = this.storage.getStore("state");
|
|
1297
|
-
stateStorage.applyChanges([
|
|
1298
|
-
{
|
|
1299
|
-
type: "set",
|
|
1300
|
-
data: { _id: "$arc", lastSyncDate: message.date }
|
|
1301
|
-
}
|
|
1302
|
-
]).then(() => {
|
|
1303
|
-
this.pendingStoreChanges = [];
|
|
1304
|
-
this.syncResolve?.();
|
|
1305
|
-
});
|
|
1306
|
-
});
|
|
1307
|
-
break;
|
|
1308
1308
|
case "state-changes":
|
|
1309
1309
|
this.storage.applyChanges(message.changes);
|
|
1310
1310
|
break;
|
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.20",
|
|
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.",
|