j-templates 8.0.25 → 8.0.27

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/Node/vNode.js CHANGED
@@ -212,7 +212,7 @@ function ToArray(result) {
212
212
  function MapNode(vnode) {
213
213
  switch (vnode.type) {
214
214
  case FRAGMENT_NODE:
215
- return vnode.children?.flatMap(MapNode);
215
+ return vnode.children?.flatMap(MapNode) ?? null;
216
216
  default:
217
217
  return vnode.node;
218
218
  }
@@ -1,10 +1,11 @@
1
+ import { JsonDiffResult } from "../../Utils/json";
1
2
  import { DiffSpliceResult, DiffTreeProjectionMap, IDiffTree } from "./diffTree";
2
3
  /**
3
4
  * Synchronous diff implementation.
4
5
  * Computes diffs immediately without queuing or workers.
5
6
  *
6
7
  * @see StoreSync
7
- * @see DiffAsync
8
+ * @see StoreAsync
8
9
  */
9
10
  export declare class DiffSync implements IDiffTree {
10
11
  private diffTree;
@@ -22,15 +23,14 @@ export declare class DiffSync implements IDiffTree {
22
23
  * @param value - The new value to compare
23
24
  * @returns Diff results showing changes
24
25
  */
25
- DiffPath(path: string, value: any, flatten?: boolean): import("../../Utils/json").JsonDiffResult;
26
- /**
27
- * Computes diffs for a batch of path/value pairs.
28
- * @param data - Array of objects with path and value properties
29
- * @returns Combined diff results
30
- */
31
- DiffBatch(data: Array<{
32
- path: string;
33
- value: any;
34
- }>): import("../../Utils/json").JsonDiffResult;
35
- SplicePath(path: string, start: number, deleteCount: number | undefined, items: any[], flatten?: boolean): DiffSpliceResult;
26
+ DiffPath(path: string, value: any): {
27
+ path: (string | number)[];
28
+ value: unknown;
29
+ }[];
30
+ PatchPath(path: string, patch: any): {
31
+ path: (string | number)[];
32
+ value: unknown;
33
+ }[];
34
+ PushPath(path: string, items: any[]): JsonDiffResult;
35
+ SplicePath(path: string, start: number, deleteCount: number | undefined, items: any[]): DiffSpliceResult;
36
36
  }
@@ -4,7 +4,7 @@ import { DiffTree } from "./diffTree";
4
4
  * Computes diffs immediately without queuing or workers.
5
5
  *
6
6
  * @see StoreSync
7
- * @see DiffAsync
7
+ * @see StoreAsync
8
8
  */
9
9
  export class DiffSync {
10
10
  /**
@@ -21,18 +21,21 @@ export class DiffSync {
21
21
  * @param value - The new value to compare
22
22
  * @returns Diff results showing changes
23
23
  */
24
- DiffPath(path, value, flatten = true) {
25
- return this.diffTree.DiffPath(path, value, flatten);
24
+ DiffPath(path, value) {
25
+ const diff = this.diffTree.DiffPath(path, value);
26
+ return diff.concat(this.diffTree.RunProjections());
26
27
  }
27
- /**
28
- * Computes diffs for a batch of path/value pairs.
29
- * @param data - Array of objects with path and value properties
30
- * @returns Combined diff results
31
- */
32
- DiffBatch(data) {
33
- return this.diffTree.DiffBatch(data);
28
+ PatchPath(path, patch) {
29
+ const diff = this.diffTree.PatchPath(path, patch);
30
+ return diff.concat(this.diffTree.RunProjections());
31
+ }
32
+ PushPath(path, items) {
33
+ const diff = this.diffTree.PushPath(path, items);
34
+ return diff.concat(this.diffTree.RunProjections());
34
35
  }
35
- SplicePath(path, start, deleteCount, items, flatten) {
36
- return this.diffTree.SplicePath(path, start, deleteCount, items, flatten);
36
+ SplicePath(path, start, deleteCount, items) {
37
+ const spliceResult = this.diffTree.SplicePath(path, start, deleteCount, items);
38
+ spliceResult.diffResult.push(...this.diffTree.RunProjections());
39
+ return spliceResult;
37
40
  }
38
41
  }
@@ -3,23 +3,16 @@ import { type JsonDiffResult } from "../../Utils/json";
3
3
  * Interface for diff tree operations.
4
4
  */
5
5
  export interface IDiffTree {
6
- /**
7
- * Computes diffs for a batch of path/value pairs.
8
- * @param data - Array of objects with path and value properties
9
- * @returns Combined diff results
10
- */
11
- DiffBatch(data: Array<{
12
- path: string;
13
- value: any;
14
- }>): JsonDiffResult;
15
6
  /**
16
7
  * Computes the diff between a new value and the current value at a path.
17
8
  * @param path - Dot-separated path to the value
18
9
  * @param value - The new value to compare
19
10
  * @returns Diff results showing changes
20
11
  */
21
- DiffPath(path: string, value: any, flatten?: boolean): JsonDiffResult;
22
- SplicePath(path: string, start: number, deleteCount: number | undefined, items: any[], flatten?: boolean): DiffSpliceResult;
12
+ DiffPath(path: string, value: any): JsonDiffResult;
13
+ PatchPath(path: string, patch: any): JsonDiffResult;
14
+ SplicePath(path: string, start: number, deleteCount: number | undefined, items: any[]): DiffSpliceResult;
15
+ PushPath(path: string, items: any[]): JsonDiffResult;
23
16
  }
24
17
  /**
25
18
  * Constructor interface for IDiffTree.
@@ -70,12 +63,13 @@ export type DiffSpliceResult<T = unknown> = {
70
63
  /** Required by the splice operation **/
71
64
  start: number;
72
65
  deleteCount: number;
66
+ items: any[];
73
67
  spliceResult: any[];
74
68
  diffResult: JsonDiffResult;
75
69
  };
76
70
  /**
77
71
  * Diff tree implementation. Maintains root state and computes diffs for path/value updates.
78
- * Used directly by `DiffSync`, and is the building block for a `DiffAsync` worker entry
72
+ * Used directly by `DiffSync`, and is the building block for a `StoreAsync` worker entry
79
73
  * file: construct one with the desired `keyFunc`/`projections` and connect it to the worker
80
74
  * thread with `ConnectWorkerToDiffTree` (see `defaultDiffTreeWorker.ts` for the no-argument
81
75
  * case, or a custom entry file when either is needed).
@@ -94,27 +88,17 @@ export declare class DiffTree {
94
88
  constructor(keyFunc?: {
95
89
  (val: any): string;
96
90
  }, projections?: DiffTreeProjectionMap);
97
- private RunProjections;
98
- /**
99
- * Computes diffs for a batch of path/value pairs.
100
- * @param data - Array of objects with path and value properties
101
- * @returns Combined diff results
102
- */
103
- DiffBatch(data: Array<{
104
- path: string;
105
- value: any;
106
- }>): {
107
- path: (string | number)[];
108
- value: unknown;
109
- }[];
91
+ RunProjections(): JsonDiffResult;
110
92
  /**
111
93
  * Computes the diff between a new value and the current value at a path.
112
94
  * @param path - Dot-separated path to the value
113
95
  * @param value - The new value to compare
114
96
  * @returns Diff results showing changes
115
97
  */
116
- DiffPath(path: string, value: any, flatten?: boolean): JsonDiffResult;
117
- SplicePath(path: string, start: number, deleteCount: number, items: any[], flatten?: boolean): DiffSpliceResult<unknown>;
98
+ DiffPath(path: string, value: any): JsonDiffResult;
99
+ PatchPath(path: string, patch: any): JsonDiffResult;
100
+ PushPath(path: string, items: unknown[]): JsonDiffResult;
101
+ SplicePath(path: string, start: number, deleteCount: number, items: any[]): DiffSpliceResult<unknown>;
118
102
  /**
119
103
  * Retrieves the current value at a path.
120
104
  * @param path - Dot-separated path to the value
@@ -1,5 +1,5 @@
1
1
  import { ArraysEqual } from "../../Utils/array";
2
- import { JsonDeepClone, JsonDiff, JsonType } from "../../Utils/json";
2
+ import { JsonDeepClone, JsonDiff, JsonMerge, JsonType } from "../../Utils/json";
3
3
  /** Reserved key prefix a projection's result is stored under: `$projection_<id>`. */
4
4
  export const PROJECTION_PREFIX = "$projection_";
5
5
  /**
@@ -247,8 +247,8 @@ function RunProjections(source, keyFunc, projections, memo) {
247
247
  memo.set(id, values);
248
248
  // The same diff-and-apply UpdateSource uses for any other write, so a keyed entity
249
249
  // embedded in a projection's result is flattened to its own root like any other write,
250
- // and the diff reported here is unfiltered, the same as DiffPath/DiffBatch return.
251
- diffResult.push(...UpdateSource(source, PROJECTION_PREFIX + id, result, true, keyFunc));
250
+ // and the diff reported here is unfiltered, the same as DiffPath returns.
251
+ diffResult.push(...UpdateSource(source, PROJECTION_PREFIX + id, result, keyFunc));
252
252
  }
253
253
  }
254
254
  }
@@ -294,18 +294,18 @@ function ResolveKeyPath(source, path, keyFunc) {
294
294
  * @param keyFunc - Optional function to extract keys from objects
295
295
  * @returns Diff results showing all changes made
296
296
  */
297
- function UpdateSource(source, path, value, flatten, keyFunc) {
297
+ function UpdateSource(source, path, value, keyFunc) {
298
298
  const diffResult = [];
299
299
  if (keyFunc) {
300
300
  const keyPath = ResolveKeyPath(source, path, keyFunc);
301
301
  if (keyPath !== path) {
302
- const keyDiffResult = UpdateSource(source, keyPath, value, flatten, keyFunc);
302
+ const keyDiffResult = UpdateSource(source, keyPath, value, keyFunc);
303
303
  diffResult.push(...keyDiffResult);
304
304
  }
305
305
  }
306
306
  const [sourceValue] = GetPathValue(source, path);
307
307
  JsonDiff(value, sourceValue, path, diffResult);
308
- if (flatten && keyFunc) {
308
+ if (keyFunc) {
309
309
  let flattened = {};
310
310
  flattened = FlattenValue(flattened, value, keyFunc);
311
311
  flattened = JsonDeepClone(flattened);
@@ -319,7 +319,37 @@ function UpdateSource(source, path, value, flatten, keyFunc) {
319
319
  }
320
320
  return diffResult;
321
321
  }
322
- function SpliceSource(source, path, start, deleteCount, items, flatten, keyFunc) {
322
+ function PushSource(source, path, items, keyFunc) {
323
+ const [sourceValue, found] = GetPathValue(source, path);
324
+ if (!found)
325
+ throw `Value not found at path ${path}`;
326
+ if (!Array.isArray(sourceValue))
327
+ throw `Value found at path ${path} is not an array`;
328
+ const results = items.map(function (value, index) {
329
+ return {
330
+ path: `${path}.${sourceValue.length + index}`.split('.'),
331
+ value
332
+ };
333
+ });
334
+ sourceValue.push(...items);
335
+ if (items.length > 0)
336
+ results.push({
337
+ path: `${path}.length`.split('.'),
338
+ value: sourceValue.length
339
+ });
340
+ if (keyFunc) {
341
+ const flattened = JsonDeepClone(FlattenValue({}, items, keyFunc));
342
+ const keys = Object.keys(flattened);
343
+ for (let x = 0; x < keys.length; x++)
344
+ JsonDiff(flattened[keys[x]], source[keys[x]], keys[x], results);
345
+ }
346
+ const filteredDiffResult = results.filter((diff) => diff.value !== undefined);
347
+ for (let x = 0; x < filteredDiffResult.length; x++) {
348
+ SetPathValue(source, filteredDiffResult[x].path, filteredDiffResult[x].value);
349
+ }
350
+ return results;
351
+ }
352
+ function SpliceSource(source, path, start, deleteCount, items, keyFunc) {
323
353
  const [sourceValue, found] = GetPathValue(source, path);
324
354
  if (!found)
325
355
  throw `Value not found at path ${path}`;
@@ -329,13 +359,14 @@ function SpliceSource(source, path, start, deleteCount, items, flatten, keyFunc)
329
359
  const spliceResult = {
330
360
  path: path.split("."),
331
361
  start,
362
+ items,
332
363
  deleteCount,
333
364
  spliceResult: null,
334
365
  diffResult: [],
335
366
  };
336
367
  spliceResult.spliceResult = sourceValue.splice(start, deleteCount, ...items);
337
368
  InvalidateSnapshotForValue(sourceValue);
338
- if (flatten && keyFunc) {
369
+ if (keyFunc) {
339
370
  // Register the keyed entities the new items carry, diffed against the roots
340
371
  // already held: a new entity is added whole, one re-inserted unchanged (an undo)
341
372
  // produces no diff, so its readers aren't woken.
@@ -352,7 +383,7 @@ function SpliceSource(source, path, start, deleteCount, items, flatten, keyFunc)
352
383
  }
353
384
  /**
354
385
  * Diff tree implementation. Maintains root state and computes diffs for path/value updates.
355
- * Used directly by `DiffSync`, and is the building block for a `DiffAsync` worker entry
386
+ * Used directly by `DiffSync`, and is the building block for a `StoreAsync` worker entry
356
387
  * file: construct one with the desired `keyFunc`/`projections` and connect it to the worker
357
388
  * thread with `ConnectWorkerToDiffTree` (see `defaultDiffTreeWorker.ts` for the no-argument
358
389
  * case, or a custom entry file when either is needed).
@@ -375,33 +406,25 @@ export class DiffTree {
375
406
  return [];
376
407
  return RunProjections(this.rootState, this.keyFunc, this.projectionOrder, this.projectionMemo);
377
408
  }
378
- /**
379
- * Computes diffs for a batch of path/value pairs.
380
- * @param data - Array of objects with path and value properties
381
- * @returns Combined diff results
382
- */
383
- DiffBatch(data) {
384
- const results = data
385
- .map(({ path, value }) => UpdateSource(this.rootState, path, value, true, this.keyFunc))
386
- .flat(1);
387
- results.push(...this.RunProjections());
388
- return results;
389
- }
390
409
  /**
391
410
  * Computes the diff between a new value and the current value at a path.
392
411
  * @param path - Dot-separated path to the value
393
412
  * @param value - The new value to compare
394
413
  * @returns Diff results showing changes
395
414
  */
396
- DiffPath(path, value, flatten = true) {
397
- const results = UpdateSource(this.rootState, path, value, flatten, this.keyFunc);
398
- results.push(...this.RunProjections());
399
- return results;
415
+ DiffPath(path, value) {
416
+ return UpdateSource(this.rootState, path, value, this.keyFunc);
417
+ }
418
+ PatchPath(path, patch) {
419
+ const value = this.Snapshot(path);
420
+ const merged = JsonMerge(value, patch);
421
+ return UpdateSource(this.rootState, path, merged, this.keyFunc);
422
+ }
423
+ PushPath(path, items) {
424
+ return PushSource(this.rootState, path, items, this.keyFunc);
400
425
  }
401
- SplicePath(path, start, deleteCount, items, flatten = true) {
402
- const spliceResult = SpliceSource(this.rootState, path, start, deleteCount, items, flatten, this.keyFunc);
403
- spliceResult.diffResult.push(...this.RunProjections());
404
- return spliceResult;
426
+ SplicePath(path, start, deleteCount, items) {
427
+ return SpliceSource(this.rootState, path, start, deleteCount, items, this.keyFunc);
405
428
  }
406
429
  /**
407
430
  * Retrieves the current value at a path.
@@ -1,7 +1,16 @@
1
- import { DiffTree } from "./diffTree";
1
+ import { JsonDiffResult } from "../../Utils/json";
2
+ import { DiffSpliceResult, DiffTree } from "./diffTree";
3
+ export type IDiffMethodBatch = IDiffMethod[];
4
+ export type IDiffMethodBatchResult = ({
5
+ type: "diff";
6
+ result: JsonDiffResult;
7
+ } | {
8
+ type: "splice";
9
+ result: DiffSpliceResult;
10
+ })[];
2
11
  export interface IDiffMethod {
3
12
  /** The method to call */
4
- method: "create" | "diffpath" | "splicepath" | "diffbatch" | "updatepath" | "getpath";
13
+ method: "diffpath" | "splicepath" | "pushpath" | "patchpath";
5
14
  /** Arguments for the method call */
6
15
  arguments: Array<any>;
7
16
  }
@@ -1,27 +1,44 @@
1
1
  export function ConnectWorkerToDiffTree(diffTree, worker) {
2
2
  worker.onmessage = function (event) {
3
3
  const data = event.data;
4
- switch (data.method) {
5
- case "diffpath": {
6
- const diff = diffTree.DiffPath(data.arguments[0], data.arguments[1], data.arguments[2]);
7
- worker.postMessage(diff);
8
- break;
9
- }
10
- case "splicepath": {
11
- const diff = diffTree.SplicePath(data.arguments[0], data.arguments[1], data.arguments[2], data.arguments[3], data.arguments[4]);
12
- worker.postMessage(diff);
13
- break;
14
- }
15
- case "diffbatch": {
16
- const diff = diffTree.DiffBatch(data.arguments[0]);
17
- worker.postMessage(diff);
18
- break;
19
- }
20
- case "getpath": {
21
- const ret = diffTree.GetPath(data.arguments[0]);
22
- worker.postMessage(ret);
23
- break;
4
+ const result = new Array(data.length + 1);
5
+ for (let x = 0; x < data.length; x++) {
6
+ const call = data[x];
7
+ switch (call.method) {
8
+ case "diffpath": {
9
+ result[x] = {
10
+ type: "diff",
11
+ result: diffTree.DiffPath(call.arguments[0], call.arguments[1])
12
+ };
13
+ break;
14
+ }
15
+ case "splicepath": {
16
+ result[x] = {
17
+ type: "splice",
18
+ result: diffTree.SplicePath(call.arguments[0], call.arguments[1], call.arguments[2], call.arguments[3])
19
+ };
20
+ break;
21
+ }
22
+ case "pushpath": {
23
+ result[x] = {
24
+ type: "diff",
25
+ result: diffTree.PushPath(call.arguments[0], call.arguments[1])
26
+ };
27
+ break;
28
+ }
29
+ case "patchpath": {
30
+ result[x] = {
31
+ type: "diff",
32
+ result: diffTree.PatchPath(call.arguments[0], call.arguments[1])
33
+ };
34
+ break;
35
+ }
24
36
  }
25
37
  }
38
+ result[result.length - 1] = {
39
+ type: "diff",
40
+ result: diffTree.RunProjections()
41
+ };
42
+ worker.postMessage(result);
26
43
  };
27
44
  }
@@ -20,80 +20,87 @@ import { Store } from "./store";
20
20
  * await store.Patch("user", { age: 31 });
21
21
  *
22
22
  * // Pushing data into an array asynchronously
23
- * await store.Push("user.array", { id: 1 }, { id: 2 });
23
+ * await store.Write([], "users");
24
+ * await store.Push("users", { id: 1 }, { id: 2 });
24
25
  *
25
26
  * // Splicing an array asynchronously
26
- * const deletedItems = await store.Splice("user.array", 0, 1, { id: 3 });
27
+ * const deletedItems = await store.Splice("users", 0, 1, { id: 3 });
27
28
  *
28
29
  * // Cleaning up resources
29
30
  * store.Destroy();
30
31
  *
31
32
  * @see Store
32
33
  * @see StoreSync
33
- * @see DiffAsync
34
34
  */
35
35
  export declare class StoreAsync extends Store {
36
- /**
37
- * The diff instance used to compute differences between current and new data states asynchronously.
38
- * @private
39
- */
40
- private diff;
41
- /**
42
- * The async queue instance used to manage asynchronous operations in a non-blocking manner.
43
- * @private
44
- */
45
- private queue;
36
+ private writeKeySet;
37
+ private workerQueue;
38
+ private asyncQueue;
39
+ private currentBatch;
40
+ private currentBatchPromise;
46
41
  /**
47
42
  * Creates an instance of StoreAsync.
48
- * @param diffWorker A `Worker` running a `DiffTree` connected via
49
- * `ConnectWorkerToDiffTree` (e.g. a bundled `defaultDiffTreeWorker` entry). Any
50
- * `keyFunc`/projections the diff needs must be baked into that worker's own entry file,
51
- * since the worker now runs standard bundled code rather than a serialized function.
52
- * @param keyFunc Optional function to generate a key for a given data value, used locally
53
- * by this store to resolve root objects. Pass the same key logic the worker's `DiffTree`
54
- * was constructed with, if any.
43
+ * @param diffWorker A `Worker` running a `DiffTree` connected via `ConnectWorkerToDiffTree`
44
+ * (e.g. a bundled `defaultDiffTreeWorker` entry). Any `keyFunc`/projections the diff needs
45
+ * must be baked into that worker's own entry file.
46
+ * @param keyFunc Optional function to generate a key for a given data value, used locally by
47
+ * this store to resolve root objects. Pass the same key logic the worker's `DiffTree` was
48
+ * constructed with, if any.
55
49
  */
56
50
  constructor(diffWorker: Worker, keyFunc?: (value: any) => string | undefined);
57
- /**
58
- * Returns a promise that resolve once all current queued writes have completed
59
- */
60
- Flush(): Promise<void>;
61
- private nextWritePromise;
62
- private nextWriteBatch;
51
+ private Schedule;
63
52
  /**
64
53
  * Writes data to the store asynchronously.
65
- * This method ensures that write operations are queued and executed in a non-blocking manner.
54
+ * Changes made in the same tick are sent to the worker together as one batch and applied in
55
+ * the order they were made. A change to this key may be made before the returned promise
56
+ * resolves; it's applied after this write.
66
57
  * @param data The data to be written. Can be of any type.
67
58
  * @param key Optional key for the data. If not provided, the keyFunc will be used to generate a key.
68
- * @throws Will throw an error if no key is provided for the data.
59
+ * @returns A promise that resolves once the write has been applied to the store.
60
+ * @throws Will throw an error if no key is provided for the data, or reject with the original
61
+ * error if an earlier change failed.
69
62
  */
70
63
  Write(data: unknown, key?: string): Promise<void>;
71
64
  /**
72
65
  * Patches an existing value in the store with new data asynchronously.
73
- * This method ensures that patch operations are queued and executed in a non-blocking manner.
66
+ * The patch is merged with the current value in the worker, so it applies on top of any
67
+ * change made before it, including ones not yet applied to the store.
74
68
  * @param key The key of the value to be patched.
75
69
  * @param patch The patch data to be merged with the existing value.
76
- * @throws Will throw an error if the value to be patched is undefined.
70
+ * @returns A promise that resolves once the patch has been applied to the store.
71
+ * @throws Will throw if the key isn't in the store and has no pending Write, or reject with
72
+ * the original error if an earlier change failed.
77
73
  */
78
74
  Patch(key: string, patch: unknown): Promise<void>;
79
75
  /**
80
76
  * Pushes data into an array stored at the specified key asynchronously.
81
- * This method ensures that push operations are queued and executed in a non-blocking manner.
82
77
  * @param key The key of the array where data will be pushed.
83
78
  * @param data The data items to be pushed into the array.
79
+ * @returns A promise that resolves once the items have been applied to the store.
80
+ * @throws Will throw if the key isn't in the store and has no pending Write, or reject with
81
+ * the original error if an earlier change failed.
84
82
  */
85
83
  Push(key: string, ...data: unknown[]): Promise<void>;
86
84
  /**
87
85
  * Splices an array stored at the specified key with new data asynchronously.
88
- * This method ensures that splice operations are queued and executed in a non-blocking manner.
89
- * It modifies the array by deleting elements and inserting new ones at the specified position.
86
+ * This method modifies the array by deleting elements and inserting new ones at the specified position.
90
87
  * @param key The key of the array to be spliced.
91
88
  * @param start The position at which to start changing the array.
92
89
  * @param deleteCount Optional number of elements to delete. If not provided, all elements from start to end will be deleted.
93
90
  * @param items Optional elements to insert into the array.
94
- * @returns The array of deleted elements.
91
+ * @returns A promise that resolves to the array of deleted elements once the splice has been
92
+ * applied to the store.
93
+ * @throws Will throw if the key isn't in the store and has no pending Write, or reject with
94
+ * the original error if an earlier change failed.
95
95
  */
96
96
  Splice(key: string, start: number, deleteCount?: number, ...items: unknown[]): Promise<any[]>;
97
+ /**
98
+ * Returns a promise that resolves once every change made before this call has been applied
99
+ * to the store. Changes made after this call are sent in a later batch, so they aren't
100
+ * waited for and haven't been applied when the promise resolves.
101
+ * @throws Rejects with the original error if a change made before this call failed.
102
+ */
103
+ Flush(): Promise<void>;
97
104
  /**
98
105
  * Destroys the StoreAsync instance, stopping the async queue and cleaning up the diff instance.
99
106
  * This method should be called when the instance is no longer needed to free up resources.