@ng-org/orm 0.1.2-alpha.1 → 0.1.2-alpha.10
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/README.md +151 -230
- package/dist/connector/applyPatches.d.ts +19 -49
- package/dist/connector/applyPatches.d.ts.map +1 -1
- package/dist/connector/applyPatches.js +57 -58
- package/dist/connector/discrete/discreteOrmSubscriptionHandler.d.ts +168 -0
- package/dist/connector/discrete/discreteOrmSubscriptionHandler.d.ts.map +1 -0
- package/dist/connector/discrete/discreteOrmSubscriptionHandler.js +309 -0
- package/dist/connector/getObjects.d.ts +11 -0
- package/dist/connector/getObjects.d.ts.map +1 -0
- package/dist/connector/getObjects.js +26 -0
- package/dist/connector/initNg.d.ts +33 -2
- package/dist/connector/initNg.d.ts.map +1 -1
- package/dist/connector/initNg.js +30 -0
- package/dist/connector/insertObject.d.ts +9 -0
- package/dist/connector/insertObject.d.ts.map +1 -0
- package/dist/connector/insertObject.js +24 -0
- package/dist/connector/ormSubscriptionHandler.d.ts +167 -0
- package/dist/connector/ormSubscriptionHandler.d.ts.map +1 -0
- package/dist/connector/ormSubscriptionHandler.js +400 -0
- package/dist/connector/utils.d.ts +17 -0
- package/dist/connector/utils.d.ts.map +1 -0
- package/dist/connector/utils.js +68 -0
- package/dist/frontendAdapters/react/index.d.ts +2 -1
- package/dist/frontendAdapters/react/index.d.ts.map +1 -1
- package/dist/frontendAdapters/react/index.js +2 -1
- package/dist/frontendAdapters/react/useDiscrete.d.ts +104 -0
- package/dist/frontendAdapters/react/useDiscrete.d.ts.map +1 -0
- package/dist/frontendAdapters/react/useDiscrete.js +151 -0
- package/dist/frontendAdapters/react/useShape.d.ts +69 -2
- package/dist/frontendAdapters/react/useShape.d.ts.map +1 -1
- package/dist/frontendAdapters/react/useShape.js +89 -8
- package/dist/frontendAdapters/svelte/index.d.ts +2 -1
- package/dist/frontendAdapters/svelte/index.d.ts.map +1 -1
- package/dist/frontendAdapters/svelte/index.js +2 -1
- package/dist/frontendAdapters/svelte/useDiscrete.svelte.d.ts +94 -0
- package/dist/frontendAdapters/svelte/useDiscrete.svelte.d.ts.map +1 -0
- package/dist/frontendAdapters/svelte/useDiscrete.svelte.js +137 -0
- package/dist/frontendAdapters/svelte/useShape.svelte.d.ts +79 -10
- package/dist/frontendAdapters/svelte/useShape.svelte.d.ts.map +1 -1
- package/dist/frontendAdapters/svelte/useShape.svelte.js +88 -9
- package/dist/frontendAdapters/svelte4/index.d.ts +5 -0
- package/dist/frontendAdapters/svelte4/index.d.ts.map +1 -0
- package/dist/{connector/createSignalObjectForShape.js → frontendAdapters/svelte4/index.js} +3 -15
- package/dist/frontendAdapters/svelte4/useDiscrete.svelte.d.ts +84 -0
- package/dist/frontendAdapters/svelte4/useDiscrete.svelte.d.ts.map +1 -0
- package/dist/frontendAdapters/svelte4/useDiscrete.svelte.js +126 -0
- package/dist/frontendAdapters/svelte4/useShape.svelte.d.ts +77 -0
- package/dist/frontendAdapters/svelte4/useShape.svelte.d.ts.map +1 -0
- package/dist/frontendAdapters/svelte4/useShape.svelte.js +91 -0
- package/dist/frontendAdapters/utils.d.ts +2 -0
- package/dist/frontendAdapters/utils.d.ts.map +1 -0
- package/dist/frontendAdapters/utils.js +14 -0
- package/dist/frontendAdapters/vue/index.d.ts +2 -1
- package/dist/frontendAdapters/vue/index.d.ts.map +1 -1
- package/dist/frontendAdapters/vue/index.js +2 -1
- package/dist/frontendAdapters/vue/useDiscrete.d.ts +99 -0
- package/dist/frontendAdapters/vue/useDiscrete.d.ts.map +1 -0
- package/dist/frontendAdapters/vue/useDiscrete.js +123 -0
- package/dist/frontendAdapters/vue/useShape.d.ts +73 -2
- package/dist/frontendAdapters/vue/useShape.d.ts.map +1 -1
- package/dist/frontendAdapters/vue/useShape.js +79 -4
- package/dist/index.d.ts +13 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -6
- package/dist/types.d.ts +63 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -1
- package/package.json +37 -48
- package/dist/connector/applyPatches.test.d.ts +0 -2
- package/dist/connector/applyPatches.test.d.ts.map +0 -1
- package/dist/connector/applyPatches.test.js +0 -772
- package/dist/connector/createSignalObjectForShape.d.ts +0 -14
- package/dist/connector/createSignalObjectForShape.d.ts.map +0 -1
- package/dist/connector/ormConnectionHandler.d.ts +0 -47
- package/dist/connector/ormConnectionHandler.d.ts.map +0 -1
- package/dist/connector/ormConnectionHandler.js +0 -240
- package/src/connector/applyPatches.test.ts +0 -842
- package/src/connector/applyPatches.ts +0 -404
- package/src/connector/createSignalObjectForShape.ts +0 -35
- package/src/connector/initNg.ts +0 -30
- package/src/connector/ormConnectionHandler.ts +0 -300
- package/src/frontendAdapters/react/index.ts +0 -2
- package/src/frontendAdapters/react/useShape.ts +0 -36
- package/src/frontendAdapters/svelte/index.ts +0 -2
- package/src/frontendAdapters/svelte/useShape.svelte.ts +0 -46
- package/src/frontendAdapters/vue/index.ts +0 -2
- package/src/frontendAdapters/vue/useShape.ts +0 -33
- package/src/index.ts +0 -14
- package/src/types.ts +0 -26
|
@@ -26,7 +26,7 @@ function parseGraphId(input) {
|
|
|
26
26
|
return { graph, id };
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* Find an object in a Set by its
|
|
29
|
+
* Find an object in a Set by its `@id` property.
|
|
30
30
|
* Returns the object if found, otherwise undefined.
|
|
31
31
|
*/
|
|
32
32
|
function findInSetBySegment(set, seg) {
|
|
@@ -45,63 +45,31 @@ function findInSetBySegment(set, seg) {
|
|
|
45
45
|
return undefined;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
+
* @ignore
|
|
49
|
+
*
|
|
48
50
|
* Apply a diff to an object.
|
|
49
51
|
*
|
|
50
52
|
* The syntax is inspired by RFC 6902 but it is not compatible.
|
|
51
53
|
*
|
|
52
54
|
* It supports Sets for multi-valued properties:
|
|
53
55
|
* - Primitive values are added as Sets (Set<string | number | boolean>)
|
|
54
|
-
* - Multi-valued objects are stored in Sets, accessed by their
|
|
55
|
-
* - Single objects are plain objects with an
|
|
56
|
+
* - Multi-valued objects are stored in Sets, accessed by their `@id` property
|
|
57
|
+
* - Single objects are plain objects with an `@id` property
|
|
56
58
|
*
|
|
57
59
|
* Path traversal:
|
|
58
|
-
* - When traversing through a Set, the path segment is treated as an
|
|
60
|
+
* - When traversing through a Set, the path segment is treated as an `@id` to find the object
|
|
59
61
|
* - When traversing through a plain object, the path segment is a property name
|
|
60
62
|
*
|
|
61
|
-
* @example operations
|
|
62
|
-
* ```jsonc
|
|
63
|
-
* // === SINGLE OBJECT ===
|
|
64
|
-
* // Creating a single object (has @id at same level)
|
|
65
|
-
* { "op": "add", "path": "/urn:example:person1/address", "valType": "object" }
|
|
66
|
-
* { "op": "add", "path": "/urn:example:person1/address/@id", "value": "urn:test:address1" }
|
|
67
|
-
* // Adding primitives to single object
|
|
68
|
-
* { "op": "add", "path": "/urn:example:person1/address/street", "value": "1st street" }
|
|
69
|
-
* { "op": "add", "path": "/urn:example:person1/address/country", "value": "Greece" }
|
|
70
|
-
* // Remove a primitive from object
|
|
71
|
-
* { "op": "remove", "path": "/urn:example:person1/address/street" }
|
|
72
|
-
* // Remove the entire object
|
|
73
|
-
* { "op": "remove", "path": "/urn:example:person1/address" }
|
|
74
|
-
*
|
|
75
|
-
* // === MULTI-VALUED OBJECTS (Set) ===
|
|
76
|
-
* // Creating a multi-object container (NO @id at this level -> creates Set)
|
|
77
|
-
* { "op": "add", "path": "/urn:example:person1/children", "valType": "object" }
|
|
78
|
-
* // Adding an object to the Set (path includes object's @id)
|
|
79
|
-
* { "op": "add", "path": "/urn:example:person1/children/urn:example:child1", "valType": "object" }
|
|
80
|
-
* { "op": "add", "path": "/urn:example:person1/children/urn:example:child1/@id", "value": "urn:example:child1" }
|
|
81
|
-
* // Adding properties to object in Set
|
|
82
|
-
* { "op": "add", "path": "/urn:example:person1/children/urn:example:child1/name", "value": "Alice" }
|
|
83
|
-
* // Remove an object from Set
|
|
84
|
-
* { "op": "remove", "path": "/urn:example:person1/children/urn:example:child1" }
|
|
85
|
-
* // Remove all objects (the Set itself)
|
|
86
|
-
* { "op": "remove", "path": "/urn:example:person1/children" }
|
|
87
|
-
*
|
|
88
|
-
* // === PRIMITIVE SETS ===
|
|
89
|
-
* // Add primitive types to Sets
|
|
90
|
-
* { "op": "add", "valType": "set", "path": "/urn:example:person1/tags", "value": [1,2,3] }
|
|
91
|
-
* // Remove primitive types from a Set
|
|
92
|
-
* { "op": "remove", "valType": "set", "path": "/urn:example:person1/tags", "value": [1,2] }
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
63
|
* @param currentState The object before the patch
|
|
96
64
|
* @param patches An array of patches to apply to the object.
|
|
97
65
|
* @param ensurePathExists If true, create nested objects along the path if the path does not exist.
|
|
98
66
|
*
|
|
99
|
-
*
|
|
67
|
+
* Note: When creating new objects, this function pre-scans upcoming patches to find `@id` and `@graph`
|
|
100
68
|
* values that will be assigned to the object. This prevents the signal library's propGenerator
|
|
101
69
|
* from being triggered before these identity fields are set, which would cause it to generate
|
|
102
70
|
* random IDs unnecessarily.
|
|
103
71
|
*/
|
|
104
|
-
export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
72
|
+
export function applyPatches(currentState, patches, ormType, ensurePathExists = false) {
|
|
105
73
|
for (let patchIndex = 0; patchIndex < patches.length; patchIndex++) {
|
|
106
74
|
const patch = patches[patchIndex];
|
|
107
75
|
if (!patch.path.startsWith("/"))
|
|
@@ -112,7 +80,8 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
112
80
|
.filter(Boolean)
|
|
113
81
|
.map(decodePathSegment);
|
|
114
82
|
if (pathParts.length === 0) {
|
|
115
|
-
|
|
83
|
+
// Actually, this should mean replace..
|
|
84
|
+
console.warn("[applyPatches] No path specified for patch", patch);
|
|
116
85
|
continue;
|
|
117
86
|
}
|
|
118
87
|
const lastKey = pathParts[pathParts.length - 1];
|
|
@@ -149,7 +118,7 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
149
118
|
if (ensurePathExists) {
|
|
150
119
|
if (parentVal != null && typeof parentVal === "object") {
|
|
151
120
|
// Check if we need to create an object or a set:
|
|
152
|
-
if (pathParts[i + 1]?.includes("|")) {
|
|
121
|
+
if (pathParts[i + 1]?.includes("|") && ormType === "set") {
|
|
153
122
|
// The next path segment is an IRI, that means the new element must be a set of objects. Create a set.
|
|
154
123
|
parentVal[seg] = new Set();
|
|
155
124
|
}
|
|
@@ -170,13 +139,12 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
170
139
|
}
|
|
171
140
|
}
|
|
172
141
|
if (parentMissing) {
|
|
173
|
-
console.warn(`[
|
|
142
|
+
console.warn(`[applyPatches] Skipping patch due to missing parent path segment(s): ${patch.path}`);
|
|
174
143
|
continue;
|
|
175
144
|
}
|
|
176
|
-
// parentVal now should be an object or
|
|
177
|
-
if (parentVal == null ||
|
|
178
|
-
(
|
|
179
|
-
console.warn(`[applyDiff] Skipping patch because parent is not an object or Set: ${patch.path}`);
|
|
145
|
+
// parentVal now should be an object, array, or set into which we apply lastKey
|
|
146
|
+
if (parentVal == null || typeof parentVal !== "object") {
|
|
147
|
+
console.warn(`[applyPatches] Skipping patch because parent is not an object or Set: ${patch.path}`);
|
|
180
148
|
continue;
|
|
181
149
|
}
|
|
182
150
|
const key = lastKey;
|
|
@@ -185,7 +153,9 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
185
153
|
// The key represents the identifier of an object within the Set
|
|
186
154
|
const targetObj = findInSetBySegment(parentVal, key);
|
|
187
155
|
// Handle object creation in a Set
|
|
188
|
-
if (patch.op === "add" &&
|
|
156
|
+
if (patch.op === "add" &&
|
|
157
|
+
typeof patch.value === "object" &&
|
|
158
|
+
patch.value !== null) {
|
|
189
159
|
if (!targetObj) {
|
|
190
160
|
// Determine if this will be a single object or nested Set
|
|
191
161
|
const hasId = patches[patchIndex + 2]?.path.endsWith("@id");
|
|
@@ -203,6 +173,8 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
203
173
|
}
|
|
204
174
|
}
|
|
205
175
|
parentVal.add(newLeaf);
|
|
176
|
+
// Skip the next two add (@id + @graph) patches.
|
|
177
|
+
patchIndex += 2;
|
|
206
178
|
}
|
|
207
179
|
continue;
|
|
208
180
|
}
|
|
@@ -215,14 +187,13 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
215
187
|
}
|
|
216
188
|
// All other operations require the target object to exist
|
|
217
189
|
if (!targetObj) {
|
|
218
|
-
console.warn(`[
|
|
190
|
+
console.warn(`[applyPatches] Target object with @id=${key} not found in Set for path: ${patch.path}`);
|
|
219
191
|
continue;
|
|
220
192
|
}
|
|
221
193
|
// This shouldn't happen - we handle all intermediate segments in the traversal loop
|
|
222
|
-
console.warn(`[
|
|
194
|
+
console.warn(`[applyPatches] Unexpected: reached end of path with Set as parent: ${patch.path}`);
|
|
223
195
|
continue;
|
|
224
196
|
}
|
|
225
|
-
// Regular object handling (parentVal is a plain object, not a Set)
|
|
226
197
|
// Handle primitive set additions
|
|
227
198
|
if (patch.op === "add" && patch.valType === "set") {
|
|
228
199
|
const existing = parentVal[key];
|
|
@@ -267,7 +238,11 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
267
238
|
// Distinguish between single objects and multi-object containers:
|
|
268
239
|
// - If an @id patch follows for this path, it's a single object -> create {}
|
|
269
240
|
// - If no @id patch follows, it's a container for multi-valued objects -> create set.
|
|
270
|
-
if (patch.op === "add" &&
|
|
241
|
+
if (patch.op === "add" &&
|
|
242
|
+
typeof patch.value === "object" &&
|
|
243
|
+
patch.value !== null &&
|
|
244
|
+
ormType === "set" // TODO: The engine should preferably add valType: "set" here (we don't need ormType then).
|
|
245
|
+
) {
|
|
271
246
|
const leafVal = parentVal[key];
|
|
272
247
|
const hasId = patches.at(patchIndex + 2)?.path.endsWith("@id");
|
|
273
248
|
// If the leafVal does not exist and it should be a set, create.
|
|
@@ -286,12 +261,34 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
286
261
|
newLeaf["@id"] = idPatch.value;
|
|
287
262
|
}
|
|
288
263
|
parentVal[key] = newLeaf;
|
|
264
|
+
// Skip the next two add (@id + @graph) patches.
|
|
265
|
+
patchIndex += 2;
|
|
289
266
|
}
|
|
290
267
|
continue;
|
|
291
268
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
269
|
+
if (Array.isArray(parentVal)) {
|
|
270
|
+
if (key === "-") {
|
|
271
|
+
if (patch.op == "add") {
|
|
272
|
+
parentVal.push(patch.value);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
parentVal.pop();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
else if (patch.op == "add") {
|
|
279
|
+
let keyNum = Number(key);
|
|
280
|
+
parentVal.splice(keyNum, 0, patch.value);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// patch.op == remove
|
|
284
|
+
let keyNum = Number(key);
|
|
285
|
+
// Remove element at position from array in-place (will resize).
|
|
286
|
+
parentVal.splice(keyNum, 1);
|
|
287
|
+
}
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
// Basic add
|
|
291
|
+
if (patch.op === "add") {
|
|
295
292
|
parentVal[key] = patch.value;
|
|
296
293
|
continue;
|
|
297
294
|
}
|
|
@@ -305,11 +302,13 @@ export function applyPatches(currentState, patches, ensurePathExists = false) {
|
|
|
305
302
|
}
|
|
306
303
|
}
|
|
307
304
|
/**
|
|
308
|
-
*
|
|
305
|
+
* @ignore
|
|
306
|
+
*
|
|
307
|
+
* See documentation for applyPatches
|
|
309
308
|
*/
|
|
310
|
-
export function applyPatchesToDeepSignal(currentState, patch) {
|
|
309
|
+
export function applyPatchesToDeepSignal(currentState, patch, ormType) {
|
|
311
310
|
batch(() => {
|
|
312
|
-
applyPatches(currentState, patch,
|
|
311
|
+
applyPatches(currentState, patch, ormType, false);
|
|
313
312
|
});
|
|
314
313
|
}
|
|
315
314
|
function decodePathSegment(segment) {
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { DiscreteArray, DiscreteObject } from "../../types.ts";
|
|
2
|
+
import { Patch } from "../applyPatches.ts";
|
|
3
|
+
import type { DeepPatch, DeepSignal } from "@ng-org/alien-deepsignals";
|
|
4
|
+
import type { BaseType } from "@ng-org/shex-orm";
|
|
5
|
+
/**
|
|
6
|
+
* Class for managing RDF-based ORM subscriptions with the engine.
|
|
7
|
+
*
|
|
8
|
+
* You have two options on how to interact with the ORM:
|
|
9
|
+
* - Use a hook for your favorite framework under `@ng-org/orm/react|vue|svelte`
|
|
10
|
+
* - Call {@link OrmSubscription.getOrCreate} to create a subscription manually
|
|
11
|
+
*
|
|
12
|
+
* For more information about RDF-based ORM subscriptions,
|
|
13
|
+
* see the [README](../../../README.md) and follow the tutorial.
|
|
14
|
+
*/
|
|
15
|
+
export declare class DiscreteOrmSubscription {
|
|
16
|
+
/** Global store of all subscriptions. We use that for pooling. */
|
|
17
|
+
private static idToEntry;
|
|
18
|
+
/** The document ID (NURI) of the subscribed document. */
|
|
19
|
+
readonly documentId: string;
|
|
20
|
+
private _signalObject;
|
|
21
|
+
private stopSignalListening;
|
|
22
|
+
/** The subscription ID kept as an identifier for communicating with the verifier. */
|
|
23
|
+
private subscriptionId;
|
|
24
|
+
/** The number of OrmSubscriptions with the same shape and scope (for pooling). */
|
|
25
|
+
private refCount;
|
|
26
|
+
/** When true, modifications from the signalObject are not processed. */
|
|
27
|
+
private suspendDeepWatcher;
|
|
28
|
+
/** @readonly True, if a transaction is running. */
|
|
29
|
+
inTransaction: boolean;
|
|
30
|
+
/** Aggregation of patches to be sent when in transaction. */
|
|
31
|
+
pendingPatches: Patch[] | undefined;
|
|
32
|
+
/** **Await to ensure that the subscription is established and the data arrived.** */
|
|
33
|
+
readyPromise: Promise<void>;
|
|
34
|
+
private closeOrmSubscription;
|
|
35
|
+
/** Function to call once initial data has been applied. */
|
|
36
|
+
private resolveReady;
|
|
37
|
+
private constructor();
|
|
38
|
+
/**
|
|
39
|
+
* The signalObject containing all data of the document
|
|
40
|
+
* (once subscription is established).
|
|
41
|
+
* The object behaves like a regular object or array with a couple of additions:
|
|
42
|
+
* - Modifications are immediately propagated back to the database.
|
|
43
|
+
* - Database changes are immediately reflected in the object.
|
|
44
|
+
* - Watch for object changes using {@link watchDeepSignal}.
|
|
45
|
+
* - Objects in arrays receive a unique `@id` property.
|
|
46
|
+
*/
|
|
47
|
+
get signalObject(): DeepSignal<DiscreteArray | DiscreteObject> | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Returns an OrmSubscription which subscribes to the given
|
|
50
|
+
* document in a 2-way binding.
|
|
51
|
+
*
|
|
52
|
+
* You **find the document data** in the **`signalObject`**,
|
|
53
|
+
* once {@link readyPromise} resolves.
|
|
54
|
+
* This is a {@link DeepSignal} object or array, depending on
|
|
55
|
+
* your CRDT document (e.g. YArray vs YMap). The signalObject
|
|
56
|
+
* behaves like a regular set to the outside but has a couple
|
|
57
|
+
* of additional features:
|
|
58
|
+
* - Modifications are propagated back to the document.
|
|
59
|
+
* Note that multiple immediate modifications in the same task,
|
|
60
|
+
* e.g. `obj[0] = "foo"; obj[1] = "bar"` are batched together
|
|
61
|
+
* and sent in a subsequent microtask.
|
|
62
|
+
* - External document changes are immediately reflected in the object.
|
|
63
|
+
* - Watch for object changes using {@link watchDeepSignal}.
|
|
64
|
+
*
|
|
65
|
+
* You can use **transactions**, to prevent excessive calls to the engine
|
|
66
|
+
* with {@link beginTransaction} and {@link commitTransaction}.
|
|
67
|
+
*
|
|
68
|
+
* In many cases, you are advised to use a hook for your
|
|
69
|
+
* favorite framework under `@ng-org/orm/react|vue|svelte`
|
|
70
|
+
* instead of calling `getOrCreate` directly.
|
|
71
|
+
*
|
|
72
|
+
* Call `{@link close}, to close the subscription.
|
|
73
|
+
*
|
|
74
|
+
* Note: If another call to `getOrCreate` was previously made
|
|
75
|
+
* and {@link close} was not called on it (or only shortly after),
|
|
76
|
+
* it will return the same OrmSubscription (pooling).
|
|
77
|
+
*
|
|
78
|
+
* @param documentId The document ID (NURI) of the CRDT
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* // We assume you have created a CRDT document already, as below.
|
|
83
|
+
* // const documentId = await ng.doc_create(
|
|
84
|
+
* // session_id,
|
|
85
|
+
* // crdt, // "Automerge" | "YMap" | "YArray". YArray is for root arrays, the other two have objects at root.
|
|
86
|
+
* // crdt === "Automerge" ? "data:json" : crdt === "YMap ? "data:map" : "data:array",
|
|
87
|
+
* // "store",
|
|
88
|
+
* // undefined
|
|
89
|
+
* // );
|
|
90
|
+
* const subscription = DiscreteOrmSubscription.getOrCreate(documentId);
|
|
91
|
+
* // Wait for data.
|
|
92
|
+
* await subscription.readyPromise;
|
|
93
|
+
*
|
|
94
|
+
* const document = subscription.signalObject;
|
|
95
|
+
* if (!document.expenses) {
|
|
96
|
+
* document.expenses = [];
|
|
97
|
+
* }
|
|
98
|
+
* document.expenses.push({
|
|
99
|
+
* name: "New Expense name",
|
|
100
|
+
* description: "Expense description"
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* // Await promise to run the below code in a new task.
|
|
104
|
+
* // That will have push the changes to the database.
|
|
105
|
+
* await Promise.resolve();
|
|
106
|
+
*
|
|
107
|
+
* // Here, the expense modifications have been committed
|
|
108
|
+
* // (unless you had previously called subscription.beginTransaction()).
|
|
109
|
+
* // The data is available in subscriptions running on a different device too.
|
|
110
|
+
*
|
|
111
|
+
* subscription.close();
|
|
112
|
+
*
|
|
113
|
+
* // If you create a new subscription with the same document within a couple of 100ms,
|
|
114
|
+
* // The subscription hasn't been closed and the old one is returned so that the data
|
|
115
|
+
* // is available instantly. This is especially useful in the context of unmounting and remounting frontend frameworks.
|
|
116
|
+
* const subscription2 = DiscreteOrmSubscription.getOrCreate(documentId);
|
|
117
|
+
*
|
|
118
|
+
* subscription2.signalObject.expenses.push({
|
|
119
|
+
* name: "Second expense",
|
|
120
|
+
* description: "Second description"
|
|
121
|
+
* });
|
|
122
|
+
*
|
|
123
|
+
* subscription2.close();
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
static getOrCreate: <T extends BaseType>(documentId: string) => DiscreteOrmSubscription;
|
|
127
|
+
/**
|
|
128
|
+
* Stop the subscription.
|
|
129
|
+
*
|
|
130
|
+
* **If there is more than one subscription with the document ID,
|
|
131
|
+
* the orm subscription won't close yet.**
|
|
132
|
+
*
|
|
133
|
+
* Additionally, the closing of the subscription is delayed by a couple hundred milliseconds
|
|
134
|
+
* so that when frontend frameworks unmount and soon mount a component again with the same
|
|
135
|
+
* document ID, we reuse the same orm subscription.
|
|
136
|
+
*/
|
|
137
|
+
close: () => void;
|
|
138
|
+
/** Handle updates (patches) coming from signal object modifications. */
|
|
139
|
+
private onSignalObjectUpdate;
|
|
140
|
+
/** Handle messages coming from the engine (initial data or patches). */
|
|
141
|
+
private onBackendMessage;
|
|
142
|
+
private handleInitialResponse;
|
|
143
|
+
/** Handle incoming patches from the engine */
|
|
144
|
+
private onBackendUpdate;
|
|
145
|
+
/**
|
|
146
|
+
* Begins a transaction that batches changes to be committed to the database.
|
|
147
|
+
* This is useful for performance reasons.
|
|
148
|
+
*
|
|
149
|
+
* Note that this does not disable reactivity of the `signalObject`.
|
|
150
|
+
* Modifications keep being rendered instantly.
|
|
151
|
+
*/
|
|
152
|
+
beginTransaction: () => void;
|
|
153
|
+
/**
|
|
154
|
+
* Commits a transactions sending all modifications made during the transaction
|
|
155
|
+
* (started with `beginTransaction`) to the database.
|
|
156
|
+
* @throws if no transaction is open.
|
|
157
|
+
*/
|
|
158
|
+
commitTransaction: () => Promise<void>;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Converts DeepSignal patches to ORM Wasm-compatible patches
|
|
162
|
+
* @param patches DeepSignal patches
|
|
163
|
+
* @returns Patches with stringified path
|
|
164
|
+
*
|
|
165
|
+
* @ignore
|
|
166
|
+
*/
|
|
167
|
+
export declare function deepPatchesToWasm(patches: DeepPatch[]): Patch[];
|
|
168
|
+
//# sourceMappingURL=discreteOrmSubscriptionHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discreteOrmSubscriptionHandler.d.ts","sourceRoot":"","sources":["../../../src/connector/discrete/discreteOrmSubscriptionHandler.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAA4B,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAQrE,OAAO,KAAK,EACR,SAAS,EACT,UAAU,EAEb,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AASjD;;;;;;;;;GASG;AACH,qBAAa,uBAAuB;IAChC,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,SAAS,CAA8C;IAEtE,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,aAAa,CAEL;IAChB,OAAO,CAAC,mBAAmB,CAA2B;IACtD,qFAAqF;IACrF,OAAO,CAAC,cAAc,CAAqB;IAC3C,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAS;IACzB,wEAAwE;IACxE,OAAO,CAAC,kBAAkB,CAAU;IACpC,mDAAmD;IACnD,aAAa,EAAE,OAAO,CAAS;IAC/B,6DAA6D;IAC7D,cAAc,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACpC,qFAAqF;IACrF,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,CAAC,oBAAoB,CAAa;IACzC,2DAA2D;IAC3D,OAAO,CAAC,YAAY,CAAc;IAElC,OAAO;IA+BP;;;;;;;;OAQG;IACH,IAAW,YAAY,2DAEtB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6EG;IACH,OAAc,WAAW,GAAI,CAAC,SAAS,QAAQ,EAC3C,YAAY,MAAM,KACnB,uBAAuB,CAcxB;IAEF;;;;;;;;;OASG;IACI,KAAK,aASV;IAEF,wEAAwE;IACxE,OAAO,CAAC,oBAAoB,CAsB1B;IAEF,wEAAwE;IACxE,OAAO,CAAC,gBAAgB,CAStB;IAEF,OAAO,CAAC,qBAAqB,CAiB3B;IAEF,8CAA8C;IAC9C,OAAO,CAAC,eAAe,CAUrB;IAEF;;;;;;OAMG;IACI,gBAAgB,aAerB;IAEF;;;;OAIG;IACI,iBAAiB,sBAiCtB;CACL;AAED;;;;;;GAMG;AAEH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,CAO/D"}
|