@ng-org/orm 0.1.2-alpha.7 → 0.1.2-alpha.9

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.
Files changed (53) hide show
  1. package/README.md +74 -92
  2. package/dist/connector/applyPatches.d.ts +13 -4
  3. package/dist/connector/applyPatches.d.ts.map +1 -1
  4. package/dist/connector/applyPatches.js +9 -5
  5. package/dist/connector/discrete/discreteOrmSubscriptionHandler.d.ts +156 -0
  6. package/dist/connector/discrete/discreteOrmSubscriptionHandler.d.ts.map +1 -0
  7. package/dist/connector/discrete/{discreteOrmConnectionHandler.js → discreteOrmSubscriptionHandler.js} +130 -19
  8. package/dist/connector/getObjects.js +2 -2
  9. package/dist/connector/initNg.d.ts +35 -0
  10. package/dist/connector/initNg.d.ts.map +1 -1
  11. package/dist/connector/initNg.js +35 -0
  12. package/dist/connector/insertObject.js +2 -2
  13. package/dist/connector/ormSubscriptionHandler.d.ts +166 -0
  14. package/dist/connector/ormSubscriptionHandler.d.ts.map +1 -0
  15. package/dist/connector/{ormConnectionHandler.js → ormSubscriptionHandler.js} +157 -32
  16. package/dist/frontendAdapters/react/useDiscrete.d.ts +89 -69
  17. package/dist/frontendAdapters/react/useDiscrete.d.ts.map +1 -1
  18. package/dist/frontendAdapters/react/useDiscrete.js +103 -81
  19. package/dist/frontendAdapters/react/useShape.d.ts +55 -55
  20. package/dist/frontendAdapters/react/useShape.d.ts.map +1 -1
  21. package/dist/frontendAdapters/react/useShape.js +71 -73
  22. package/dist/frontendAdapters/svelte/useDiscrete.svelte.d.ts +80 -71
  23. package/dist/frontendAdapters/svelte/useDiscrete.svelte.d.ts.map +1 -1
  24. package/dist/frontendAdapters/svelte/useDiscrete.svelte.js +102 -91
  25. package/dist/frontendAdapters/svelte/useShape.svelte.d.ts +70 -64
  26. package/dist/frontendAdapters/svelte/useShape.svelte.d.ts.map +1 -1
  27. package/dist/frontendAdapters/svelte/useShape.svelte.js +73 -62
  28. package/dist/frontendAdapters/svelte4/index.d.ts +5 -0
  29. package/dist/frontendAdapters/svelte4/index.d.ts.map +1 -0
  30. package/dist/frontendAdapters/svelte4/index.js +12 -0
  31. package/dist/frontendAdapters/svelte4/useDiscrete.svelte.d.ts +85 -0
  32. package/dist/frontendAdapters/svelte4/useDiscrete.svelte.d.ts.map +1 -0
  33. package/dist/frontendAdapters/svelte4/useDiscrete.svelte.js +124 -0
  34. package/dist/frontendAdapters/svelte4/useShape.svelte.d.ts +76 -0
  35. package/dist/frontendAdapters/svelte4/useShape.svelte.d.ts.map +1 -0
  36. package/dist/frontendAdapters/svelte4/useShape.svelte.js +84 -0
  37. package/dist/frontendAdapters/vue/useDiscrete.d.ts +87 -80
  38. package/dist/frontendAdapters/vue/useDiscrete.d.ts.map +1 -1
  39. package/dist/frontendAdapters/vue/useDiscrete.js +96 -84
  40. package/dist/frontendAdapters/vue/useShape.d.ts +57 -63
  41. package/dist/frontendAdapters/vue/useShape.d.ts.map +1 -1
  42. package/dist/frontendAdapters/vue/useShape.js +59 -64
  43. package/dist/index.d.ts +6 -3
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +14 -3
  46. package/dist/types.d.ts +17 -7
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/types.js +11 -2
  49. package/package.json +7 -3
  50. package/dist/connector/discrete/discreteOrmConnectionHandler.d.ts +0 -45
  51. package/dist/connector/discrete/discreteOrmConnectionHandler.d.ts.map +0 -1
  52. package/dist/connector/ormConnectionHandler.d.ts +0 -48
  53. package/dist/connector/ormConnectionHandler.d.ts.map +0 -1
@@ -16,32 +16,48 @@ import { deepSignal, watch as watchDeepSignal, } from "@ng-org/alien-deepsignals
16
16
  * so that no new connections need to be set up.
17
17
  */
18
18
  const WAIT_BEFORE_CLOSE = 500;
19
- export class DiscreteOrmConnection {
19
+ /**
20
+ * Class for managing RDF-based ORM subscriptions with the engine.
21
+ *
22
+ * You have two options on how to interact with the ORM:
23
+ * - Use a hook for your favorite framework under `@ng-org/orm/react|vue|svelte`
24
+ * - Call {@link OrmSubscription.getOrCreate} to create a subscription manually
25
+ *
26
+ * For more information about RDF-based ORM subscriptions,
27
+ * see the [README](../../../README.md) and follow the tutorial.
28
+ */
29
+ export class DiscreteOrmSubscription {
30
+ /** Global store of all subscriptions. We use that for pooling. */
20
31
  static idToEntry = new Map();
32
+ /** The document id (IRI) of the subscribed document. */
21
33
  documentId;
22
34
  _signalObject;
23
35
  stopSignalListening;
36
+ /** The subscription id kept as an identifier for communicating with the verifier. */
24
37
  subscriptionId;
38
+ /** The number of OrmSubscriptions with the same shape and scope (for pooling). */
25
39
  refCount;
40
+ /** When true, modifications from the signalObject are not processed. */
26
41
  suspendDeepWatcher;
42
+ /** True, if a transaction is running. */
27
43
  inTransaction = false;
28
44
  /** Aggregation of patches to be sent when in transaction. */
29
45
  pendingPatches;
30
- /** Resolves once the data arrives */
46
+ /** **Await to ensure that the subscription is established and the data arrived.** */
31
47
  readyPromise;
32
- closeOrmConnection;
33
- /** Called to resolve the readyPromise. */
48
+ closeOrmSubscription;
49
+ /** Function to call once initial data has been applied. */
34
50
  resolveReady;
35
51
  constructor(documentId) {
36
52
  // @ts-expect-error
37
- window.ormDiscreteSignalConnections = DiscreteOrmConnection.idToEntry;
53
+ window.ormDiscreteSignalConnections = DiscreteOrmSubscription.idToEntry;
38
54
  // @ts-expect-error
39
- window.OrmDiscreteConnection = DiscreteOrmConnection;
55
+ window.OrmDiscreteConnection = DiscreteOrmSubscription;
40
56
  // @ts-expect-error
41
57
  window.OrmDiscreteIncomingPatches = [];
42
58
  this.documentId = documentId;
43
59
  this.refCount = 1;
44
- this.closeOrmConnection = () => { };
60
+ this.closeOrmSubscription = () => { };
45
61
  this.suspendDeepWatcher = false;
46
62
  // Initialize per-entry readiness promise that resolves in setUpConnection
47
63
  this.readyPromise = new Promise((resolve) => {
@@ -49,7 +65,7 @@ export class DiscreteOrmConnection {
49
65
  });
50
66
  ngSession.then(async ({ ng, session }) => {
51
67
  try {
52
- this.closeOrmConnection = await ng.orm_start_discrete(documentId, session.session_id, this.onBackendMessage);
68
+ this.closeOrmSubscription = await ng.orm_start_discrete(documentId, session.session_id, this.onBackendMessage);
53
69
  }
54
70
  catch (e) {
55
71
  console.error(e);
@@ -60,37 +76,119 @@ export class DiscreteOrmConnection {
60
76
  return this._signalObject;
61
77
  }
62
78
  /**
63
- * Get or create a connection which contains the ORM and lifecycle methods.
64
- * @param shapeType
65
- * @param scope
66
- * @param ng
67
- * @returns
79
+ * Returns an OrmSubscription which subscribes to the given
80
+ * document in a 2-way binding.
81
+ *
82
+ * You **find the document data** in the **`signalObject`**
83
+ * once {@link readyPromise} resolves.
84
+ * This is a {@link DeepSignal} object or array, depending on
85
+ * your CRDT document (e.g. YArray vs YMap). The signalObject
86
+ * behaves like a regular set to the outside but has a couple
87
+ * of additional features:
88
+ * - Modifications are propagated back to the document.
89
+ * Note that multiple immediate modifications in the same task,
90
+ * e.g. `obj[0] = "foo"; obj[1] = "bar"` are batched together
91
+ * and sent in a subsequent microtask.
92
+ * - External document changes are immediately reflected in the object.
93
+ * - Watch for object changes using {@link watchDeepSignal}.
94
+ *
95
+ * You can use **transactions**, to prevent excessive calls to the engine
96
+ * with {@link beginTransaction} and {@link commitTransaction}.
97
+ *
98
+ * In many cases, you are advised to use a hook for your
99
+ * favorite framework under `@ng-org/orm/react|vue|svelte`
100
+ * instead of calling `getOrCreate` directly.
101
+ *
102
+ * Call `{@link close}, to close the subscription.
103
+ *
104
+ * Note: If another call to `getOrCreate` was previously made
105
+ * and {@link close} was not called on it (or only shortly after),
106
+ * it will return the same OrmSubscription.
107
+ *
108
+ * @param documentId The document ID (IRI) of the CRDT
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * // We assume you have created a CRDT document already, as below.
113
+ * // const documentId = await ng.doc_create(
114
+ * // session_id,
115
+ * // crdt, // "Automerge" | "YMap" | "YArray". YArray is for root arrays, the other two have objects at root.
116
+ * // crdt === "Automerge" ? "data:json" : crdt === "YMap ? "data:map" : "data:array",
117
+ * // "store",
118
+ * // undefined
119
+ * // );
120
+ * const subscription = DiscreteOrmSubscription.getOrCreate(documentId);
121
+ * // Wait for data.
122
+ * await subscription.readyPromise;
123
+ *
124
+ * const document = subscription.signalObject;
125
+ * if (!document.expenses) {
126
+ * document.expenses = [];
127
+ * }
128
+ * document.expenses.push({
129
+ * name: "New Expense name",
130
+ * description: "Expense description"
131
+ * });
132
+ *
133
+ * // Await promise to run the below code in a new task.
134
+ * // That will push the changes to the database.
135
+ * await Promise.resolve();
136
+ *
137
+ * // Here, the expense modifications have been have been committed
138
+ * // (unless you had previously called subscription.beginTransaction()).
139
+ * // The data is available in subscriptions running on a different device too.
140
+ *
141
+ * subscription.close();
142
+ *
143
+ * // If you create a new subscription with the same document within a couple of 100ms,
144
+ * // The subscription hasn't been closed and the old one is returned so that the data
145
+ * // is available instantly. This is especially useful in the context of frontend frameworks.
146
+ * const subscription2 = DiscreteOrmSubscription.getOrCreate(documentId);
147
+ *
148
+ * subscription2.signalObject.expenses.push({
149
+ * name: "Second expense",
150
+ * description: "Second description"
151
+ * });
152
+ *
153
+ * subscription2.close();
154
+ * ```
68
155
  */
69
156
  static getOrCreate = (documentId) => {
70
157
  // If we already have a connection open,
71
- // return that signal object it and just increase the reference count.
158
+ // return that signal object and just increase the reference count.
72
159
  // Otherwise, open a new one.
73
- const existingConnection = DiscreteOrmConnection.idToEntry.get(documentId);
160
+ const existingConnection = DiscreteOrmSubscription.idToEntry.get(documentId);
74
161
  if (existingConnection) {
75
162
  existingConnection.refCount += 1;
76
163
  return existingConnection;
77
164
  }
78
165
  else {
79
- const newConnection = new DiscreteOrmConnection(documentId);
80
- DiscreteOrmConnection.idToEntry.set(documentId, newConnection);
166
+ const newConnection = new DiscreteOrmSubscription(documentId);
167
+ DiscreteOrmSubscription.idToEntry.set(documentId, newConnection);
81
168
  return newConnection;
82
169
  }
83
170
  };
171
+ /**
172
+ * Stop the subscription.
173
+ *
174
+ * **If there is more than one subscription with the same shape type and scope
175
+ * the orm subscription will persist.**
176
+ *
177
+ * Additionally, the closing of the subscription is delayed by a couple hundred milliseconds
178
+ * so that when frontend frameworks unmount and soon mound a component again with the same
179
+ * shape type and scope, no new orm subscription has be set up with the engine.
180
+ */
84
181
  close = () => {
85
182
  setTimeout(() => {
86
183
  if (this.refCount > 0)
87
184
  this.refCount--;
88
185
  if (this.refCount === 0) {
89
- DiscreteOrmConnection.idToEntry.delete(this.documentId);
90
- this.closeOrmConnection();
186
+ DiscreteOrmSubscription.idToEntry.delete(this.documentId);
187
+ this.closeOrmSubscription();
91
188
  }
92
189
  }, WAIT_BEFORE_CLOSE);
93
190
  };
191
+ /** Handle updates (patches) coming from signal object modifications. */
94
192
  onSignalObjectUpdate = async ({ patches, }) => {
95
193
  if (this.suspendDeepWatcher || !patches.length)
96
194
  return;
@@ -105,6 +203,7 @@ export class DiscreteOrmConnection {
105
203
  await this.readyPromise;
106
204
  ng.discrete_orm_update(this.subscriptionId, ormPatches, session.session_id);
107
205
  };
206
+ /** Handle messages coming from the engine (initial data or patches). */
108
207
  onBackendMessage = (message) => {
109
208
  const data = message?.V0;
110
209
  if (data?.DiscreteOrmInitial) {
@@ -128,6 +227,7 @@ export class DiscreteOrmConnection {
128
227
  // Resolve readiness after initial data is committed and watcher armed.
129
228
  this.resolveReady();
130
229
  };
230
+ /** Handle incoming patches from the engine */
131
231
  onBackendUpdate = (patches) => {
132
232
  // @ts-expect-error
133
233
  window.OrmDiscreteIncomingPatches.push(patches);
@@ -138,6 +238,13 @@ export class DiscreteOrmConnection {
138
238
  this.suspendDeepWatcher = false;
139
239
  });
140
240
  };
241
+ /**
242
+ * Begins a transaction that batches changes to be committed to the database.
243
+ * This is useful for performance reasons.
244
+ *
245
+ * Note that this does not disable reactivity of the `signalObject`.
246
+ * Modifications keep being rendered.
247
+ */
141
248
  beginTransaction = () => {
142
249
  this.inTransaction = true;
143
250
  this.pendingPatches = [];
@@ -149,6 +256,10 @@ export class DiscreteOrmConnection {
149
256
  this.stopSignalListening = stopListening;
150
257
  });
151
258
  };
259
+ /**
260
+ * Commits a transactions sending all modifications made during the transaction
261
+ * (started with `beginTransaction`) to the database.
262
+ */
152
263
  commitTransaction = async () => {
153
264
  if (!this.inTransaction) {
154
265
  throw new Error("No transaction is open. Call `beginTransaction` first.");
@@ -7,7 +7,7 @@
7
7
  // notice may not be copied, modified, or distributed except
8
8
  // according to those terms.
9
9
  // SPDX-License-Identifier: Apache-2.0 OR MIT
10
- import { OrmConnection } from "./ormConnectionHandler.js";
10
+ import { OrmSubscription } from "./ormSubscriptionHandler.js";
11
11
  import { deepClone } from "./utils.js";
12
12
  /**
13
13
  * Utility for retrieving objects once without establishing a two-way subscription.
@@ -16,7 +16,7 @@ import { deepClone } from "./utils.js";
16
16
  * @returns A set of all objects matching the shape and scope
17
17
  */
18
18
  export async function getObjects(shapeType, scope = {}) {
19
- const connection = OrmConnection.getOrCreate(shapeType, scope);
19
+ const connection = OrmSubscription.getOrCreate(shapeType, scope);
20
20
  await connection.readyPromise;
21
21
  setTimeout(() => {
22
22
  connection.close();
@@ -5,10 +5,45 @@ type Session = {
5
5
  private_store_id: string;
6
6
  public_store_id: string;
7
7
  };
8
+ /** Resolves to the NG session and the ng implementation. */
8
9
  export declare const ngSession: Promise<{
9
10
  ng: typeof NG;
10
11
  session: Session;
11
12
  }>;
13
+ /**
14
+ * Initialize the ORM by passing the ng implementation and session.
15
+ *
16
+ * @param ngImpl
17
+ * @param session
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { ng, init } from "@ng-org/web";
22
+ * import { initNg as initNgSignals } from "@ng-org/orm";
23
+ * let session: {
24
+ * ng: typeof NG;
25
+ * session_id: string;
26
+ * protected_store_id: string;
27
+ * private_store_id: string;
28
+ * public_store_id: string;
29
+ * [key: string]: unknown;
30
+ * };
31
+ *
32
+ * // Call as early as possible as it will redirect to the auth page.
33
+ * await init(
34
+ * async (event: any) => {
35
+ * session = event.session;
36
+ * session!.ng ??= ng;
37
+ *
38
+ * // Call initNgSignals
39
+ * initNgSignals(ng, session);
40
+ * },
41
+ * true,
42
+ * []
43
+ * );
44
+ * ```
45
+ *
46
+ */
12
47
  export declare function initNgSignals(ngImpl: typeof NG, session: Session): void;
13
48
  export {};
14
49
  //# sourceMappingURL=initNg.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initNg.d.ts","sourceRoot":"","sources":["../../src/connector/initNg.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,KAAK,OAAO,GAAG;IACX,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CAC3B,CAAC;AAIF,eAAO,MAAM,SAAS;QAAqB,OAAO,EAAE;aAAW,OAAO;EAIrE,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,QAEhE"}
1
+ {"version":3,"file":"initNg.d.ts","sourceRoot":"","sources":["../../src/connector/initNg.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,KAAK,OAAO,GAAG;IACX,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CAC3B,CAAC;AAIF,4DAA4D;AAC5D,eAAO,MAAM,SAAS;QAAqB,OAAO,EAAE;aAAW,OAAO;EAIrE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,QAEhE"}
@@ -8,9 +8,44 @@
8
8
  // according to those terms.
9
9
  // SPDX-License-Identifier: Apache-2.0 OR MIT
10
10
  let resolveNgSession;
11
+ /** Resolves to the NG session and the ng implementation. */
11
12
  export const ngSession = new Promise((resolve) => {
12
13
  resolveNgSession = resolve;
13
14
  });
15
+ /**
16
+ * Initialize the ORM by passing the ng implementation and session.
17
+ *
18
+ * @param ngImpl
19
+ * @param session
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { ng, init } from "@ng-org/web";
24
+ * import { initNg as initNgSignals } from "@ng-org/orm";
25
+ * let session: {
26
+ * ng: typeof NG;
27
+ * session_id: string;
28
+ * protected_store_id: string;
29
+ * private_store_id: string;
30
+ * public_store_id: string;
31
+ * [key: string]: unknown;
32
+ * };
33
+ *
34
+ * // Call as early as possible as it will redirect to the auth page.
35
+ * await init(
36
+ * async (event: any) => {
37
+ * session = event.session;
38
+ * session!.ng ??= ng;
39
+ *
40
+ * // Call initNgSignals
41
+ * initNgSignals(ng, session);
42
+ * },
43
+ * true,
44
+ * []
45
+ * );
46
+ * ```
47
+ *
48
+ */
14
49
  export function initNgSignals(ngImpl, session) {
15
50
  resolveNgSession({ ng: ngImpl, session });
16
51
  }
@@ -7,14 +7,14 @@
7
7
  // notice may not be copied, modified, or distributed except
8
8
  // according to those terms.
9
9
  // SPDX-License-Identifier: Apache-2.0 OR MIT
10
- import { OrmConnection } from "./ormConnectionHandler.js";
10
+ import { OrmSubscription } from "./ormSubscriptionHandler.js";
11
11
  /**
12
12
  * Utility for adding ORM-typed objects to the database without the need for subscribing to documents.
13
13
  * @param shapeType The shape type of the objects to be inserted.
14
14
  * @param object The object to be inserted.
15
15
  */
16
16
  export async function insertObject(shapeType, object) {
17
- const connection = OrmConnection.getOrCreate(shapeType, {
17
+ const connection = OrmSubscription.getOrCreate(shapeType, {
18
18
  graphs: [], // Subscribe to no documents
19
19
  });
20
20
  await connection.readyPromise;
@@ -0,0 +1,166 @@
1
+ import { type Scope } from "../types.ts";
2
+ import { Patch } from "./applyPatches.ts";
3
+ import type { DeepSignalSet } from "@ng-org/alien-deepsignals";
4
+ import type { ShapeType, 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 and follow the tutorial.
14
+ */
15
+ export declare class OrmSubscription<T extends BaseType> {
16
+ /** Global store of all subscriptions. We use that for pooling. */
17
+ private static idToEntry;
18
+ /** The shape type that is subscribed to. */
19
+ readonly shapeType: ShapeType<T>;
20
+ /** The {@link Scope} of the subscription. */
21
+ readonly scope: Scope;
22
+ /**
23
+ * The signalObject containing all data matching the shape and scope
24
+ * (once subscription is established).
25
+ * The object is of type {@link DeepSignalSet} which
26
+ * to the outside behaves like a regular set but has a couple of
27
+ * additional features:
28
+ * - Modifications are immediately propagated back to the database.
29
+ * - Database changes are immediately reflected in the object.
30
+ * - `.getBy(graphIri, subjectIri)` utility for quicker access to objects in set.
31
+ * - `.first()` utility to get the first element added to the set.
32
+ * - the iterator utilities, e.g. `.map()`, `.filter()`, ...
33
+ * - Watch for object changes using {@link watchDeepSignal}.
34
+ */
35
+ readonly signalObject: DeepSignalSet<T>;
36
+ private stopSignalListening;
37
+ /** The subscription id kept as an identifier for communicating with the verifier. */
38
+ private subscriptionId;
39
+ /** The number of OrmSubscriptions with the same shape and scope (for pooling). */
40
+ private refCount;
41
+ /** Identifier as a combination of shape type and scope. Prevents duplications. */
42
+ private identifier;
43
+ /** When true, modifications from the signalObject are not processed. */
44
+ suspendDeepWatcher: boolean;
45
+ /** True, if a transaction is running. */
46
+ inTransaction: boolean;
47
+ /** Aggregation of patches to be sent when in transaction. */
48
+ pendingPatches: Patch[] | undefined;
49
+ /** **Await to ensure that the subscription is established and the data arrived.** */
50
+ readyPromise: Promise<void>;
51
+ private closeOrmSubscription;
52
+ /** Function to call once initial data has been applied. */
53
+ private resolveReady;
54
+ private static cleanupSignalRegistry;
55
+ private constructor();
56
+ /**
57
+ * Returns an OrmSubscription which subscribes to the given
58
+ * {@link ShapeType} and {@link Scope} in a 2-way binding.
59
+ *
60
+ * You **find the data** and objects matching the shape and scope
61
+ * in the **`signalObject`** once {@link readyPromise} resolves. This is a {@link DeepSignalSet} which
62
+ * to the outside behaves like a regular set but has a couple of
63
+ * additional features:
64
+ * - Modifications are propagated back to the database.
65
+ * Note that multiple immediate modifications in the same task,
66
+ * e.g. `obj[0] = "foo"; obj[1] = "bar"` are batched together
67
+ * and sent in a subsequent microtask.
68
+ * - Database changes are immediately reflected in the object.
69
+ * - `.getBy(graphIri, subjectIri)` utility for quicker access to objects in set.
70
+ * - `.first()` utility to get the first element added to the set.
71
+ * - the iterator utilities, e.g. `.map()`, `.filter()`, ...
72
+ * - Watch for object changes using {@link watchDeepSignal}.
73
+ *
74
+ * You can use **transactions**, to prevent excessive calls to the database
75
+ * with {@link beginTransaction} and {@link commitTransaction}.
76
+ *
77
+ * In many cases, you are advised to use a hook for your
78
+ * favorite framework under `@ng-org/orm/react|vue|svelte`
79
+ * instead of calling `getOrCreate` directly.
80
+ *
81
+ * Call `{@link close}, to close the subscription.
82
+ *
83
+ * Note: If another call to `getOrCreate` was previously made
84
+ * and `close` was not called on it (or only shortly after),
85
+ * it will return the same OrmSubscription.
86
+ *
87
+ * @param shapeType The {@link ShapeType}
88
+ * @param scope The {@link Scope}. If no scope is given, the whole store is considered.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * // We assume you have created a graph document already, as below.
93
+ * // const documentId = await ng.doc_create(
94
+ * // session_id,
95
+ * // "Graph",
96
+ * // "data:graph",
97
+ * // "store",
98
+ * // undefined
99
+ * // );
100
+ * const subscription = OrmSubscription.getOrCreate(ExpenseShapeType, {graphs: [graphIri]});
101
+ * // Wait for data.
102
+ * await subscription.readyPromise;
103
+ *
104
+ * const expense = subscription.signalObject.first()
105
+ * expense.name = "updated name";
106
+ * expense.description = "updated description";
107
+ *
108
+ * // Await promise to run the below code in a new task.
109
+ * // That will push the changes to the database.
110
+ * await Promise.resolve();
111
+ *
112
+ * // Here, the expense modifications have been have been committed
113
+ * // (unless you had previously called subscription.beginTransaction()).
114
+ * // The data is available in subscriptions running on a different device too.
115
+ *
116
+ * subscription.close();
117
+ * // If you create a new subscription with the same document within a couple of 100ms,
118
+ * // The subscription hasn't been closed and the old one is returned so that the data
119
+ * // is available instantly. This is especially useful in the context of frontend frameworks.
120
+ * const subscription2 = OrmSubscription.getOrCreate(ExpenseShapeType, {graphs: [graphIri]});
121
+ *
122
+ * subscription2.signalObject.add({
123
+ * "@graph": graphIri,
124
+ * "@id": "", // Leave empty to auto-assign one.
125
+ * name": "A new expense",
126
+ * description: "A new description"
127
+ * });
128
+ *
129
+ * subscription2.close()
130
+ */
131
+ static getOrCreate: <T_1 extends BaseType>(shapeType: ShapeType<T_1>, scope: Scope) => OrmSubscription<T_1>;
132
+ /**
133
+ * Stop the subscription.
134
+ *
135
+ * **If there is more than one subscription with the same shape type and scope
136
+ * the orm subscription will persist.**
137
+ *
138
+ * Additionally, the closing of the subscription is delayed by a couple hundred milliseconds
139
+ * so that when frontend frameworks unmount and soon mound a component again with the same
140
+ * shape type and scope, no new orm subscription has be set up with the engine.
141
+ */
142
+ close: () => void;
143
+ /** Handle updates (patches) coming from signal object modifications. */
144
+ private onSignalObjectUpdate;
145
+ /** Handle messages coming from the engine (initial data or patches). */
146
+ private onBackendMessage;
147
+ private handleInitialResponse;
148
+ /** Handle incoming patches from the engine */
149
+ private onBackendUpdate;
150
+ /** Function to create random subject IRIs for newly created nested objects. */
151
+ private signalObjectPropGenerator;
152
+ /**
153
+ * Begins a transaction that batches changes to be committed to the database.
154
+ * This is useful for performance reasons.
155
+ *
156
+ * Note that this does not disable reactivity of the `signalObject`.
157
+ * Modifications keep being rendered.
158
+ */
159
+ beginTransaction: () => void;
160
+ /**
161
+ * Commits a transactions sending all modifications made during the transaction
162
+ * (started with `beginTransaction`) to the database.
163
+ */
164
+ commitTransaction: () => Promise<void>;
165
+ }
166
+ //# sourceMappingURL=ormSubscriptionHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ormSubscriptionHandler.d.ts","sourceRoot":"","sources":["../../src/connector/ormSubscriptionHandler.ts"],"names":[],"mappings":"AAUA,OAAO,EAAkB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAA4B,KAAK,EAAE,MAAM,mBAAmB,CAAC;AASpE,OAAO,KAAK,EAER,aAAa,EAEhB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAU5D;;;;;;;;;GASG;AACH,qBAAa,eAAe,CAAC,CAAC,SAAS,QAAQ;IAC3C,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,SAAS,CAA2C;IAEnE,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,mBAAmB,CAAa;IACxC,qFAAqF;IACrF,OAAO,CAAC,cAAc,CAAqB;IAC3C,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAS;IACzB,kFAAkF;IAClF,OAAO,CAAC,UAAU,CAAS;IAC3B,wEAAwE;IACxE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,yCAAyC;IACzC,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;IAGlC,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAUrB;IAEf,OAAO;IAqDP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0EG;IACH,OAAc,WAAW,GAAI,GAAC,SAAS,QAAQ,EAC3C,WAAW,SAAS,CAAC,GAAC,CAAC,EACvB,OAAO,KAAK,KACb,eAAe,CAAC,GAAC,CAAC,CAkBnB;IAEF;;;;;;;;;OASG;IACI,KAAK,aAYV;IAEF,wEAAwE;IACxE,OAAO,CAAC,oBAAoB,CAoB1B;IAEF,wEAAwE;IACxE,OAAO,CAAC,gBAAgB,CAStB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,8CAA8C;IAC9C,OAAO,CAAC,eAAe,CAOrB;IAEF,+EAA+E;IAC/E,OAAO,CAAC,yBAAyB,CAgD/B;IAEF;;;;;;OAMG;IACI,gBAAgB,aAarB;IAEF;;;OAGG;IACI,iBAAiB,sBAkCtB;CACL"}