j-templates 8.1.2 → 9.0.0

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 (40) hide show
  1. package/SYNTAX_PRIMER.md +3 -4
  2. package/Store/Diff/diffTree.d.ts +39 -33
  3. package/Store/Diff/diffTree.js +147 -435
  4. package/Store/Diff/diffTree.types.d.ts +5 -79
  5. package/Store/Diff/diffTree.types.js +1 -3
  6. package/Store/Diff/diffTreeWorker.d.ts +4 -0
  7. package/Store/Diff/diffTreeWorker.js +17 -39
  8. package/Store/Diff/diffTreeWriter.d.ts +27 -38
  9. package/Store/Diff/diffTreeWriter.js +44 -95
  10. package/Store/Diff/index.d.ts +2 -0
  11. package/Store/Diff/index.js +2 -0
  12. package/Store/Diff/utils/diffTree.types.d.ts +113 -0
  13. package/Store/Diff/utils/diffTree.types.js +1 -0
  14. package/Store/Diff/utils/homes.d.ts +46 -0
  15. package/Store/Diff/utils/homes.js +213 -0
  16. package/Store/Diff/utils/paths.d.ts +42 -0
  17. package/Store/Diff/utils/paths.js +87 -0
  18. package/Store/Diff/utils/projections.d.ts +55 -0
  19. package/Store/Diff/utils/projections.js +290 -0
  20. package/Store/Diff/utils/routes.d.ts +27 -0
  21. package/Store/Diff/utils/routes.js +168 -0
  22. package/Store/Diff/utils/state.d.ts +56 -0
  23. package/Store/Diff/utils/state.js +155 -0
  24. package/Store/Store/pushStore.d.ts +1 -5
  25. package/Store/Store/pushStore.js +3 -22
  26. package/Store/Store/store.d.ts +10 -4
  27. package/Store/Store/store.js +25 -11
  28. package/Store/Store/storeAsync.d.ts +4 -5
  29. package/Store/Store/storeAsync.js +19 -36
  30. package/Store/Store/storeSync.d.ts +14 -9
  31. package/Store/Store/storeSync.js +27 -22
  32. package/Store/Tree/observableNode.d.ts +2 -23
  33. package/Store/Tree/observableNode.js +46 -183
  34. package/Store/Tree/snapshot.d.ts +68 -0
  35. package/Store/Tree/snapshot.js +147 -0
  36. package/Utils/json.d.ts +180 -10
  37. package/Utils/json.js +532 -67
  38. package/package.json +1 -1
  39. package/Store/Diff/diffSync.d.ts +0 -36
  40. package/Store/Diff/diffSync.js +0 -43
package/SYNTAX_PRIMER.md CHANGED
@@ -537,7 +537,7 @@ A store holds reactive data under string keys and diffs every write into existin
537
537
 
538
538
  | | `StoreSync` | `StoreAsync` | `PushStore` |
539
539
  | --- | --- | --- | --- |
540
- | Constructor | `new StoreSync(keyFunc?, projections?)` | `new StoreAsync(worker, keyFunc?)` | `new PushStore(source, keyFunc?, cloneData?)` |
540
+ | Constructor | `new StoreSync(keyFunc?, projections?)` | `new StoreAsync(worker, keyFunc?)` | `new PushStore(source, keyFunc?)` |
541
541
  | Diffing | main thread, synchronous | in the `Worker` you supply | in the `DiffTreeWriter` that pushes to it |
542
542
  | Writes | `void`; readable immediately | `Promise`; batched per tick, readable only after `await` | none; read-only. Changes arrive when the writer calls `Commit()` |
543
543
  | `Destroy()` | none | required; terminates the worker | required; stops listening, leaves the worker running |
@@ -652,7 +652,7 @@ store.Destroy(); // stops listening; terminate the worker yourself
652
652
  - **Create the store before the first `Commit()`.** Messages are diffs against the writer's tree, so a store created later misses the earlier changes and holds partial roots (from source). There is no catch-up message.
653
653
  - **A failed change doesn't stop either side.** After a write throws, every later write before `Commit()` throws the same error. `Commit()` still sends the writes made before the failure, skips projections, then posts `DIFF_TREE_ERROR`. The store applies the changes and sets `Error` (verified). The next commit brings projections up to date.
654
654
  - `store.Error` is reactive: the last commit's error, or `null`. It's cleared when a later commit's changes arrive (verified).
655
- - `cloneData` (default `false`): a `Worker` or `MessagePort` already delivers a structured-clone copy, so no copy is made. A same-thread `EventTarget` delivers the writer's own objects; post copies, or pass `true`. The flag only covers new roots and splices; changes to an existing root are always copied (from source).
655
+ - The store deep-clones every value it applies, so even a same-thread `EventTarget` that delivers the writer's own objects never leaves the store sharing them with the writer's tree (from source).
656
656
 
657
657
  ## ObservableScope and ObservableNode
658
658
 
@@ -707,13 +707,12 @@ ObservableNode.Unwrap(proxy) // raw underlying value
707
707
  ObservableNode.Apply(node, value) // merge a full value in place; node identity kept
708
708
  ObservableNode.Snapshot(node) // cached plain copy
709
709
  ObservableNode.Clone(value) // replaces proxies with plain data, mutating plain containers in place; returns value
710
- ObservableNode.Update(node, prop?) // force a change notification
711
710
  ObservableNode.CreateFactory(alias?) // proxy factory with aliasing (used by stores)
712
711
  ```
713
712
 
714
713
  - `Snapshot` returns the same object on repeated calls until a write. After a write, unchanged nested parts are shared (`===`) with the previous snapshot. Snapshots are **not frozen**; treat them as read-only.
715
714
  - `JSON.stringify(node)` and `node.toJSON()` use the cached snapshot.
716
- - `ApplyDiff`, `ApplySplice`, `Assign`, `Touch` and `Read` also exist; they are internal to the stores.
715
+ - `ApplyDiff`, `ApplySplice` and `Touch` also exist; they are internal to the stores. `ApplyDiff` and `ApplySplice` deep-clone what they write, so the node never shares objects with the caller.
717
716
 
718
717
  **Snapshot reads do not subscribe.** `JSON.stringify(node)`, `node.toJSON()` and `ObservableNode.Snapshot(node)` register no dependencies, so a scope that reads only through them never updates (verified). Read properties directly, or use `ObservableNode.Clone(node)`, which tracks every nested field and leaves the source untouched:
719
718
 
@@ -1,47 +1,53 @@
1
- import { type JsonDiffResult } from "../../Utils/json";
2
- import { DiffSpliceResult, DiffTreeProjectionMap } from "./diffTree.types";
1
+ import { JsonDiffResult } from '../../Utils/json';
2
+ import { IKeyFunc, IRouteDefinitions } from './utils/diffTree.types';
3
3
  /**
4
- * Diff tree implementation. Maintains root state and computes diffs for path/value updates.
5
- * Used directly by `DiffSync`, and is the building block for a `StoreAsync` worker entry
6
- * file: construct one with the desired `keyFunc`/`projections` and connect it to the worker
7
- * thread with `ConnectWorkerToDiffTree` (see `defaultDiffTreeWorker.ts` for the no-argument
8
- * case, or a custom entry file when either is needed).
4
+ * A tree of JSON state in routes, with projections, that tracks its changes as diffs. The work is
5
+ * split across `utils/`:
6
+ * - `homes`: writes, which keep every keyed value at its home
7
+ * - `state`: reading and writing route state, and snapshots of it
8
+ * - `routes`: route instances, created from the route definitions
9
+ * - `projections`: running each route instance's projections
10
+ * - `paths`: path strings
9
11
  */
10
12
  export declare class DiffTree {
11
- private keyFunc?;
12
13
  private rootState;
13
- private projectionOrder;
14
- private projectionMemo;
14
+ private snapshot;
15
+ private routes;
16
+ private projections;
17
+ /** Each root key's snapshot as of the last commit */
18
+ private commitedSnapshot;
19
+ private writeContext;
20
+ constructor(keyFunc?: IKeyFunc, routeDefinitions?: IRouteDefinitions);
21
+ WritePath(path: string, value: any): void;
22
+ PatchPath(path: string, patch: any): void;
23
+ PushPath(path: string, items: unknown[]): void;
24
+ SplicePath(path: string, start: number, deleteCount: number, items: any[]): void;
25
+ private Splice;
15
26
  /**
16
- * Creates a DiffTree instance.
17
- * @param keyFunc - Optional function to extract a key from objects
18
- * @param projections - Optional map of derived-value projections, keyed by id. Cycles
19
- * and reads of an unregistered projection id are rejected here, at construction.
27
+ * Deletes a route: its state, its child routes and projection outputs, and its route
28
+ * instances. The projection order is rebuilt on the next `RunProjections`, so deleting
29
+ * several routes in a row sorts once.
30
+ * @param routePath The route to delete, e.g. `/channel/1/`
31
+ * @throws When the path is the root route or has a property path, e.g. `/channel/1/name`
20
32
  */
21
- constructor(keyFunc?: {
22
- (val: any): string;
23
- }, projections?: DiffTreeProjectionMap);
24
- RunProjections(): JsonDiffResult;
33
+ DeleteRoute(routePath: string): void;
25
34
  /**
26
- * Computes the diff between a new value and the current value at a path.
27
- * @param path - Dot-separated path to the value
28
- * @param value - The new value to compare
29
- * @returns Diff results showing changes
35
+ * Reads the raw value at a path, root (`value.prop`) or routed (`/channel/1/value.prop`).
36
+ * @returns The value, or undefined when any segment of the path doesn't exist
30
37
  */
31
- DiffPath(path: string, value: any): JsonDiffResult;
32
- PatchPath(path: string, patch: any): JsonDiffResult;
33
- PushPath(path: string, items: unknown[]): JsonDiffResult;
34
- SplicePath(path: string, start: number, deleteCount: number, items: any[]): DiffSpliceResult;
38
+ ReadPath(path: string): any;
39
+ /** Runs every projection of every route instance; see `Projections.Run` */
40
+ RunProjections(): void;
35
41
  /**
36
- * Retrieves the current value at a path.
37
- * @param path - Dot-separated path to the value
38
- * @returns The value at the specified path
42
+ * The changes since the last commit. The root is a flat record of keys, so each key's snapshot
43
+ * is taken and compared on its own, without building a snapshot of the whole root: a key no
44
+ * write touched has the same cached snapshot as the last commit, and is skipped.
39
45
  */
40
- GetPath(path: string): any;
46
+ Commit(): JsonDiffResult;
41
47
  /**
42
- * Returns an immutable, cached snapshot of the value at a path (empty string for the
43
- * whole tree). Not part of `IDiffTree`; internal, for a future feature.
44
- * @param path - Dot-separated path to the value
48
+ * The snapshot of the value at a path. Only the path's first property is snapshotted, not
49
+ * its whole route.
50
+ * @returns The snapshot, or undefined when any segment of the path doesn't exist
45
51
  */
46
52
  Snapshot(path: string): any;
47
53
  }