j-templates 8.0.13 → 8.0.14
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/DOM/createAssignment.js +2 -6
- package/DOM/createAttributeAssignment.js +2 -6
- package/DOM/createEventAssignment.js +2 -6
- package/DOM/createPropertyAssignment.js +10 -14
- package/DOM/domNodeConfig.js +27 -30
- package/DOM/elements.js +102 -108
- package/DOM/index.js +3 -19
- package/Node/component.js +12 -16
- package/Node/component.types.js +1 -2
- package/Node/nodeConfig.js +2 -5
- package/Node/vNode.js +64 -67
- package/Node/vNode.types.js +5 -9
- package/Store/Diff/defaultDiffTreeWorker.d.ts +1 -0
- package/Store/Diff/defaultDiffTreeWorker.js +4 -0
- package/Store/Diff/diffAsync.d.ts +2 -4
- package/Store/Diff/diffAsync.js +4 -33
- package/Store/Diff/diffSync.js +3 -10
- package/Store/Diff/diffTree.d.ts +66 -41
- package/Store/Diff/diffTree.js +357 -427
- package/Store/Diff/diffTreeWorker.d.ts +8 -0
- package/Store/Diff/diffTreeWorker.js +27 -0
- package/Store/Diff/workerQueue.js +6 -10
- package/Store/Store/store.js +10 -14
- package/Store/Store/storeAsync.d.ts +1 -2
- package/Store/Store/storeAsync.js +10 -14
- package/Store/Store/storeSync.js +10 -14
- package/Store/Tree/observableNode.js +35 -38
- package/Store/Tree/observableScope.js +35 -42
- package/Store/index.js +5 -13
- package/Utils/animation.js +7 -11
- package/Utils/array.js +2 -6
- package/Utils/asyncQueue.js +7 -11
- package/Utils/decorators.js +44 -53
- package/Utils/emitter.js +6 -9
- package/Utils/functions.js +1 -4
- package/Utils/index.js +3 -21
- package/Utils/injector.js +2 -6
- package/Utils/json.d.ts +32 -10
- package/Utils/json.js +195 -208
- package/Utils/list.js +2 -5
- package/Utils/scheduling.js +4 -7
- package/Utils/thread.js +18 -26
- package/Utils/utils.types.js +1 -2
- package/_not_used/array.js +4 -10
- package/_not_used/avlTree.js +2 -5
- package/index.js +2 -10
- package/package.json +1 -1
- package/Store/Diff/diffWorker.d.ts +0 -3
- package/Store/Diff/diffWorker.js +0 -21
package/Node/vNode.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const nodeConfig_1 = require("./nodeConfig");
|
|
12
|
-
const vNode_types_1 = require("./vNode.types");
|
|
13
|
-
var vNode;
|
|
1
|
+
import { ObservableScope } from "../Store";
|
|
2
|
+
import { InlineScope, MappedScope, } from "../Store/Tree/observableScope";
|
|
3
|
+
import { RemoveNulls } from "../Utils/array";
|
|
4
|
+
import { Emitter } from "../Utils/emitter";
|
|
5
|
+
import { IsAsync } from "../Utils/functions";
|
|
6
|
+
import { Injector } from "../Utils/injector";
|
|
7
|
+
import { Schedule, Thread } from "../Utils/thread";
|
|
8
|
+
import { NodeConfig } from "./nodeConfig";
|
|
9
|
+
import { isStringNode, TEXT_NODE, FRAGMENT_NODE, STRING_NODE, } from "./vNode.types";
|
|
10
|
+
export var vNode;
|
|
14
11
|
(function (vNode) {
|
|
15
12
|
function Create(definition) {
|
|
16
13
|
return {
|
|
17
14
|
definition,
|
|
18
15
|
type: definition.type,
|
|
19
16
|
injector: definition.componentFactory
|
|
20
|
-
? new
|
|
21
|
-
: (
|
|
17
|
+
? new Injector()
|
|
18
|
+
: (Injector.Current() ?? new Injector()),
|
|
22
19
|
parentNode: null,
|
|
23
20
|
node: definition.node ?? null,
|
|
24
21
|
children: null,
|
|
@@ -30,7 +27,7 @@ var vNode;
|
|
|
30
27
|
}
|
|
31
28
|
vNode.Create = Create;
|
|
32
29
|
function Init(vnode, parentNode = null) {
|
|
33
|
-
if (
|
|
30
|
+
if (isStringNode(vnode) || vnode.definition === null)
|
|
34
31
|
return;
|
|
35
32
|
InitNode(vnode, parentNode);
|
|
36
33
|
}
|
|
@@ -41,12 +38,12 @@ var vNode;
|
|
|
41
38
|
}
|
|
42
39
|
vNode.InitAll = InitAll;
|
|
43
40
|
function Destroy(vnode) {
|
|
44
|
-
if (
|
|
41
|
+
if (isStringNode(vnode) || vnode.destroyed)
|
|
45
42
|
return;
|
|
46
43
|
vnode.destroyed = true;
|
|
47
44
|
vnode.component?.Destroy();
|
|
48
|
-
|
|
49
|
-
vnode.onDestroyed &&
|
|
45
|
+
ObservableScope.DestroyAll(vnode.scopes);
|
|
46
|
+
vnode.onDestroyed && Emitter.Emit(vnode.onDestroyed);
|
|
50
47
|
vnode.children && DestroyAll(vnode.children);
|
|
51
48
|
}
|
|
52
49
|
vNode.Destroy = Destroy;
|
|
@@ -71,15 +68,15 @@ var vNode;
|
|
|
71
68
|
}
|
|
72
69
|
vNode.ToFunction = ToFunction;
|
|
73
70
|
function Attach(node, vnode) {
|
|
74
|
-
if (vnode.type ===
|
|
71
|
+
if (vnode.type === FRAGMENT_NODE)
|
|
75
72
|
throw new Error("Cannot attach a fragment directly. A fragment has no DOM node — " +
|
|
76
73
|
"wrap it in a real element (e.g. div) before attaching.");
|
|
77
74
|
Init(vnode);
|
|
78
|
-
|
|
75
|
+
NodeConfig.addChild(node, vnode.node);
|
|
79
76
|
return vnode;
|
|
80
77
|
}
|
|
81
78
|
vNode.Attach = Attach;
|
|
82
|
-
})(vNode || (
|
|
79
|
+
})(vNode || (vNode = {}));
|
|
83
80
|
function ComponentChildren() {
|
|
84
81
|
return this.Template();
|
|
85
82
|
}
|
|
@@ -87,52 +84,52 @@ function InitNode(vnode, parentNode) {
|
|
|
87
84
|
const { type, namespace, props, attrs, on, data, componentFactory, children, childrenArray, } = vnode.definition;
|
|
88
85
|
let node = null;
|
|
89
86
|
switch (vnode.type) {
|
|
90
|
-
case
|
|
87
|
+
case FRAGMENT_NODE:
|
|
91
88
|
break;
|
|
92
|
-
case
|
|
93
|
-
vnode.node = node = vnode.definition.node ??
|
|
89
|
+
case TEXT_NODE:
|
|
90
|
+
vnode.node = node = vnode.definition.node ?? NodeConfig.createTextNode();
|
|
94
91
|
break;
|
|
95
92
|
default:
|
|
96
|
-
vnode.node = node = vnode.definition.node ??
|
|
93
|
+
vnode.node = node = vnode.definition.node ?? NodeConfig.createNode(type, namespace);
|
|
97
94
|
break;
|
|
98
95
|
}
|
|
99
96
|
vnode.definition = null;
|
|
100
97
|
vnode.parentNode = parentNode;
|
|
101
98
|
if (props) {
|
|
102
99
|
if (typeof props === "function") {
|
|
103
|
-
const assignProperties =
|
|
104
|
-
const scope =
|
|
100
|
+
const assignProperties = NodeConfig.createPropertyAssignment(node);
|
|
101
|
+
const scope = ObservableScope.Create(props);
|
|
105
102
|
vnode.scopes.push(scope);
|
|
106
|
-
|
|
107
|
-
assignProperties(
|
|
103
|
+
ObservableScope.Watch(scope, ScheduledAssignment(assignProperties));
|
|
104
|
+
assignProperties(ObservableScope.Value(scope));
|
|
108
105
|
}
|
|
109
106
|
else
|
|
110
|
-
|
|
107
|
+
NodeConfig.propertyAssignment(node, props);
|
|
111
108
|
}
|
|
112
109
|
if (on) {
|
|
113
110
|
if (typeof on === "function") {
|
|
114
|
-
const assignEvents =
|
|
115
|
-
const scope =
|
|
111
|
+
const assignEvents = NodeConfig.createEventAssignment(node);
|
|
112
|
+
const scope = ObservableScope.Create(on);
|
|
116
113
|
vnode.scopes.push(scope);
|
|
117
|
-
|
|
118
|
-
assignEvents(
|
|
114
|
+
ObservableScope.Watch(scope, ScheduledAssignment(assignEvents));
|
|
115
|
+
assignEvents(ObservableScope.Value(scope));
|
|
119
116
|
}
|
|
120
117
|
else
|
|
121
|
-
|
|
118
|
+
NodeConfig.eventAssignment(node, on);
|
|
122
119
|
}
|
|
123
120
|
if (attrs) {
|
|
124
121
|
if (typeof attrs === "function") {
|
|
125
|
-
const assignAttributes =
|
|
126
|
-
const scope =
|
|
122
|
+
const assignAttributes = NodeConfig.createAttributeAssignment(node);
|
|
123
|
+
const scope = ObservableScope.Create(attrs);
|
|
127
124
|
vnode.scopes.push(scope);
|
|
128
|
-
|
|
129
|
-
assignAttributes(
|
|
125
|
+
ObservableScope.Watch(scope, ScheduledAssignment(assignAttributes));
|
|
126
|
+
assignAttributes(ObservableScope.Value(scope));
|
|
130
127
|
}
|
|
131
128
|
else
|
|
132
|
-
|
|
129
|
+
NodeConfig.attributeAssignment(node, attrs);
|
|
133
130
|
}
|
|
134
131
|
if (componentFactory) {
|
|
135
|
-
vnode.component =
|
|
132
|
+
vnode.component = Injector.Scope(vnode.injector, componentFactory, vnode);
|
|
136
133
|
vnode.component.Bound();
|
|
137
134
|
Children(vnode, ComponentChildren.bind(vnode.component));
|
|
138
135
|
}
|
|
@@ -148,38 +145,38 @@ function InitNode(vnode, parentNode) {
|
|
|
148
145
|
function Children(vnode, children, data) {
|
|
149
146
|
const childrenScope = CreateChildrenScope(vnode, children, data);
|
|
150
147
|
vnode.scopes.push(childrenScope);
|
|
151
|
-
|
|
148
|
+
ObservableScope.Watch(childrenScope, CreateScheduledCallback(function (scope) {
|
|
152
149
|
if (vnode.destroyed)
|
|
153
150
|
return;
|
|
154
151
|
const oldChildrenLength = vnode.children.length;
|
|
155
|
-
vnode.children =
|
|
152
|
+
vnode.children = ObservableScope.Value(scope);
|
|
156
153
|
if (oldChildrenLength !== 0 || vnode.children.length !== 0)
|
|
157
154
|
UpdateChildren(vnode);
|
|
158
155
|
}));
|
|
159
|
-
vnode.children =
|
|
156
|
+
vnode.children = ObservableScope.Value(childrenScope);
|
|
160
157
|
}
|
|
161
158
|
function CreateChildrenScope(vnode, children, data) {
|
|
162
159
|
if (data === undefined) {
|
|
163
|
-
const scope =
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
const scope = ObservableScope.Create(GetNextNodesAsArray.bind(null, vnode.injector, children));
|
|
161
|
+
ObservableScope.OnUpdated(scope, DestroyScopedVNodes);
|
|
162
|
+
ObservableScope.OnDestroyed(scope, DestroyScopedVNodes);
|
|
166
163
|
return scope;
|
|
167
164
|
}
|
|
168
|
-
if (
|
|
165
|
+
if (IsAsync(data)) {
|
|
169
166
|
const asyncData = data;
|
|
170
167
|
data = function () {
|
|
171
|
-
return
|
|
168
|
+
return InlineScope(async function () {
|
|
172
169
|
return asyncData();
|
|
173
170
|
});
|
|
174
171
|
};
|
|
175
172
|
}
|
|
176
|
-
return
|
|
173
|
+
return ObservableScope.Create(DynamicChildrenFunction.bind(null, vnode.injector, children, data));
|
|
177
174
|
}
|
|
178
175
|
function ToVNodeType(children) {
|
|
179
|
-
return typeof children === "string" ? { type:
|
|
176
|
+
return typeof children === "string" ? { type: STRING_NODE, node: children } : children;
|
|
180
177
|
}
|
|
181
178
|
function GetNextNodes(injector, children, data) {
|
|
182
|
-
return ToVNodeType(
|
|
179
|
+
return ToVNodeType(Injector.Scope(injector, children, data));
|
|
183
180
|
}
|
|
184
181
|
function GetNextNodesAsArray(injector, children, data) {
|
|
185
182
|
const nodes = GetNextNodes(injector, children, data);
|
|
@@ -193,7 +190,7 @@ function DynamicChildrenFunction(injector, children, data) {
|
|
|
193
190
|
const getNextNodes = GetNextNodes.bind(null, injector, children);
|
|
194
191
|
let results = new Array(nextData.length);
|
|
195
192
|
for (let x = 0; x < nextData.length; x++) {
|
|
196
|
-
const nodes =
|
|
193
|
+
const nodes = MappedScope(nextData[x], getNextNodes, DestroyScopedVNodes, DestroyScopedVNodes);
|
|
197
194
|
results[x] = nodes;
|
|
198
195
|
}
|
|
199
196
|
return results.flat();
|
|
@@ -207,7 +204,7 @@ function ToArray(result) {
|
|
|
207
204
|
}
|
|
208
205
|
function MapNode(vnode) {
|
|
209
206
|
switch (vnode.type) {
|
|
210
|
-
case
|
|
207
|
+
case FRAGMENT_NODE:
|
|
211
208
|
return vnode.children.flatMap(MapNode);
|
|
212
209
|
default:
|
|
213
210
|
return vnode.node;
|
|
@@ -215,47 +212,47 @@ function MapNode(vnode) {
|
|
|
215
212
|
}
|
|
216
213
|
function CleanupChildrenArray(children) {
|
|
217
214
|
const nodes = children.flatMap(MapNode);
|
|
218
|
-
|
|
215
|
+
RemoveNulls(nodes);
|
|
219
216
|
return nodes;
|
|
220
217
|
}
|
|
221
218
|
function UpdateChildren(vnode, init = false, skipInit = false) {
|
|
222
219
|
if (!vnode.children)
|
|
223
220
|
return;
|
|
224
221
|
const children = vnode.children;
|
|
225
|
-
|
|
222
|
+
Thread(function () {
|
|
226
223
|
if (vnode.destroyed || children !== vnode.children)
|
|
227
224
|
return;
|
|
228
225
|
for (let x = 0; !skipInit && x < children.length; x++) {
|
|
229
226
|
const childNode = children[x];
|
|
230
|
-
if (!
|
|
231
|
-
|
|
227
|
+
if (!isStringNode(childNode) && childNode.definition) {
|
|
228
|
+
Schedule(function () {
|
|
232
229
|
if (vnode.destroyed || children !== vnode.children)
|
|
233
230
|
return;
|
|
234
231
|
vNode.Init(childNode, vnode);
|
|
235
232
|
});
|
|
236
233
|
}
|
|
237
234
|
}
|
|
238
|
-
|
|
235
|
+
Thread(function (async) {
|
|
239
236
|
if (vnode.destroyed || children !== vnode.children)
|
|
240
237
|
return;
|
|
241
238
|
if (init) {
|
|
242
239
|
if (vnode.node !== null)
|
|
243
|
-
|
|
240
|
+
NodeConfig.reconcileChildren(vnode.node, CleanupChildrenArray(vnode.children));
|
|
244
241
|
}
|
|
245
242
|
else if (!async) {
|
|
246
243
|
let reconcileNode = vnode;
|
|
247
244
|
while (reconcileNode.node === null)
|
|
248
245
|
reconcileNode = reconcileNode.parentNode;
|
|
249
|
-
|
|
246
|
+
NodeConfig.reconcileChildren(reconcileNode.node, CleanupChildrenArray(reconcileNode.children));
|
|
250
247
|
}
|
|
251
248
|
else {
|
|
252
|
-
|
|
249
|
+
NodeConfig.scheduleUpdate(function () {
|
|
253
250
|
if (vnode.destroyed || children !== vnode.children)
|
|
254
251
|
return;
|
|
255
252
|
let reconcileNode = vnode;
|
|
256
253
|
while (reconcileNode.node === null)
|
|
257
254
|
reconcileNode = reconcileNode.parentNode;
|
|
258
|
-
|
|
255
|
+
NodeConfig.reconcileChildren(reconcileNode.node, CleanupChildrenArray(reconcileNode.children));
|
|
259
256
|
});
|
|
260
257
|
}
|
|
261
258
|
});
|
|
@@ -267,9 +264,9 @@ function ScheduledAssignment(assign) {
|
|
|
267
264
|
if (scheduled)
|
|
268
265
|
return;
|
|
269
266
|
scheduled = true;
|
|
270
|
-
|
|
267
|
+
NodeConfig.scheduleUpdate(function () {
|
|
271
268
|
scheduled = false;
|
|
272
|
-
const value =
|
|
269
|
+
const value = ObservableScope.Peek(scope);
|
|
273
270
|
assign(value);
|
|
274
271
|
});
|
|
275
272
|
};
|
|
@@ -280,7 +277,7 @@ function CreateScheduledCallback(callback) {
|
|
|
280
277
|
if (scheduled)
|
|
281
278
|
return;
|
|
282
279
|
scheduled = true;
|
|
283
|
-
|
|
280
|
+
NodeConfig.scheduleUpdate(function () {
|
|
284
281
|
scheduled = false;
|
|
285
282
|
callback(...args);
|
|
286
283
|
});
|
package/Node/vNode.types.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.TEXT_NODE = Symbol("TEXT_NODE");
|
|
7
|
-
exports.FRAGMENT_NODE = Symbol("FRAGMENT_NODE");
|
|
8
|
-
function isStringNode(vnode) {
|
|
9
|
-
return vnode.type === exports.STRING_NODE;
|
|
1
|
+
export const STRING_NODE = Symbol("STRING_NODE");
|
|
2
|
+
export const TEXT_NODE = Symbol("TEXT_NODE");
|
|
3
|
+
export const FRAGMENT_NODE = Symbol("FRAGMENT_NODE");
|
|
4
|
+
export function isStringNode(vnode) {
|
|
5
|
+
return vnode.type === STRING_NODE;
|
|
10
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DiffSpliceResult,
|
|
1
|
+
import { DiffSpliceResult, IDiffTree } from "./diffTree";
|
|
2
2
|
import { JsonDiffResult } from "../../Utils/json";
|
|
3
3
|
/**
|
|
4
4
|
* Async version of IDiffTree interface with all methods returning promises.
|
|
@@ -22,9 +22,7 @@ export declare class DiffAsync implements IDiffTreeAsync {
|
|
|
22
22
|
* projection's function is serialized with `.toString()` and `eval`'d back into a
|
|
23
23
|
* function in the worker, the same mechanic used for `keyFunc`.
|
|
24
24
|
*/
|
|
25
|
-
constructor(
|
|
26
|
-
(val: any): string;
|
|
27
|
-
}, projections?: DiffTreeProjectionMap);
|
|
25
|
+
constructor(diffWorker: Worker);
|
|
28
26
|
/**
|
|
29
27
|
* Computes the diff between a new value and the current value at a path asynchronously.
|
|
30
28
|
* @param path - Dot-separated path to the value
|
package/Store/Diff/diffAsync.js
CHANGED
|
@@ -1,25 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DiffAsync = void 0;
|
|
4
|
-
const workerQueue_1 = require("./workerQueue");
|
|
5
|
-
const diffWorker_1 = require("./diffWorker");
|
|
6
|
-
/**
|
|
7
|
-
* Serializes a `DiffTreeProjectionMap` for the worker boundary: `reads` survives structured
|
|
8
|
-
* clone as-is, and each `projection` function is serialized with `.toString()`, the same
|
|
9
|
-
* mechanic used below for `keyFunc`.
|
|
10
|
-
*/
|
|
11
|
-
function SerializeProjections(projections) {
|
|
12
|
-
const serialized = {};
|
|
13
|
-
const ids = Object.keys(projections);
|
|
14
|
-
for (let x = 0; x < ids.length; x++) {
|
|
15
|
-
const id = ids[x];
|
|
16
|
-
serialized[id] = {
|
|
17
|
-
reads: projections[id].reads,
|
|
18
|
-
projection: projections[id].projection.toString(),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
return serialized;
|
|
22
|
-
}
|
|
1
|
+
import { WorkerQueue } from "./workerQueue";
|
|
23
2
|
/**
|
|
24
3
|
* Asynchronous diff implementation using web workers.
|
|
25
4
|
* Offloads diff computation to a worker to prevent blocking the main thread.
|
|
@@ -27,7 +6,7 @@ function SerializeProjections(projections) {
|
|
|
27
6
|
* @see StoreAsync
|
|
28
7
|
* @see DiffSync
|
|
29
8
|
*/
|
|
30
|
-
class DiffAsync {
|
|
9
|
+
export class DiffAsync {
|
|
31
10
|
/**
|
|
32
11
|
* Creates a DiffAsync instance and initializes the worker.
|
|
33
12
|
* @param keyFunc - Optional function to extract a key from objects
|
|
@@ -35,15 +14,8 @@ class DiffAsync {
|
|
|
35
14
|
* projection's function is serialized with `.toString()` and `eval`'d back into a
|
|
36
15
|
* function in the worker, the same mechanic used for `keyFunc`.
|
|
37
16
|
*/
|
|
38
|
-
constructor(
|
|
39
|
-
this.workerQueue = new
|
|
40
|
-
this.workerQueue.Push({
|
|
41
|
-
method: "create",
|
|
42
|
-
arguments: [
|
|
43
|
-
keyFunc ? keyFunc.toString() : undefined,
|
|
44
|
-
projections ? SerializeProjections(projections) : undefined,
|
|
45
|
-
],
|
|
46
|
-
});
|
|
17
|
+
constructor(diffWorker) {
|
|
18
|
+
this.workerQueue = new WorkerQueue(diffWorker);
|
|
47
19
|
}
|
|
48
20
|
/**
|
|
49
21
|
* Computes the diff between a new value and the current value at a path asynchronously.
|
|
@@ -81,4 +53,3 @@ class DiffAsync {
|
|
|
81
53
|
this.workerQueue.Destroy();
|
|
82
54
|
}
|
|
83
55
|
}
|
|
84
|
-
exports.DiffAsync = DiffAsync;
|
package/Store/Diff/diffSync.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DiffSync = void 0;
|
|
4
|
-
const array_1 = require("../../Utils/array");
|
|
5
|
-
const json_1 = require("../../Utils/json");
|
|
6
|
-
const diffTree_1 = require("./diffTree");
|
|
7
|
-
const diffCnstr = (0, diffTree_1.DiffTreeFactory)(json_1.JsonDiffFactory, array_1.ArraysEqual);
|
|
1
|
+
import { DiffTree } from "./diffTree";
|
|
8
2
|
/**
|
|
9
3
|
* Synchronous diff implementation.
|
|
10
4
|
* Computes diffs immediately without queuing or workers.
|
|
@@ -12,14 +6,14 @@ const diffCnstr = (0, diffTree_1.DiffTreeFactory)(json_1.JsonDiffFactory, array_
|
|
|
12
6
|
* @see StoreSync
|
|
13
7
|
* @see DiffAsync
|
|
14
8
|
*/
|
|
15
|
-
class DiffSync {
|
|
9
|
+
export class DiffSync {
|
|
16
10
|
/**
|
|
17
11
|
* Creates a DiffSync instance.
|
|
18
12
|
* @param keyFunc - Optional function to extract a key from objects
|
|
19
13
|
* @param projections - Optional map of derived-value projections, keyed by id
|
|
20
14
|
*/
|
|
21
15
|
constructor(keyFunc, projections) {
|
|
22
|
-
this.diffTree = new
|
|
16
|
+
this.diffTree = new DiffTree(keyFunc, projections);
|
|
23
17
|
}
|
|
24
18
|
/**
|
|
25
19
|
* Computes the diff between a new value and the current value at a path.
|
|
@@ -42,4 +36,3 @@ class DiffSync {
|
|
|
42
36
|
return this.diffTree.SplicePath(path, start, deleteCount, items, flatten);
|
|
43
37
|
}
|
|
44
38
|
}
|
|
45
|
-
exports.DiffSync = DiffSync;
|
package/Store/Diff/diffTree.d.ts
CHANGED
|
@@ -1,12 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type JsonDiffResult } from "../../Utils/json";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Interface for diff tree operations.
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
+
/**
|
|
16
|
+
* Computes the diff between a new value and the current value at a path.
|
|
17
|
+
* @param path - Dot-separated path to the value
|
|
18
|
+
* @param value - The new value to compare
|
|
19
|
+
* @returns Diff results showing changes
|
|
20
|
+
*/
|
|
21
|
+
DiffPath(path: string, value: any, flatten?: boolean): JsonDiffResult;
|
|
22
|
+
SplicePath(path: string, start: number, deleteCount: number | undefined, items: any[], flatten?: boolean): DiffSpliceResult;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Constructor interface for IDiffTree.
|
|
26
|
+
*/
|
|
27
|
+
export interface IDiffTreeConstructor {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new IDiffTree instance.
|
|
30
|
+
* @param keyFunc - Optional function to extract a key from a value
|
|
31
|
+
* @param projections - Optional map of derived-value projections, keyed by id
|
|
32
|
+
*/
|
|
33
|
+
new (keyFunc?: {
|
|
34
|
+
(val: any): string;
|
|
35
|
+
}, projections?: DiffTreeProjectionMap): IDiffTree;
|
|
10
36
|
}
|
|
11
37
|
/**
|
|
12
38
|
* A pure function computing a derived value from the current values at `reads`, passed
|
|
@@ -29,17 +55,6 @@ export type DiffTreeProjectionDefinition = {
|
|
|
29
55
|
export type DiffTreeProjectionMap = {
|
|
30
56
|
[id: string]: DiffTreeProjectionDefinition;
|
|
31
57
|
};
|
|
32
|
-
/**
|
|
33
|
-
* The wire form of a `DiffTreeProjectionMap` sent to the diff worker: `reads` survives
|
|
34
|
-
* structured clone as-is, and `projection` is serialized with `.toString()`, the same
|
|
35
|
-
* mechanic `DiffAsync` already uses to send `keyFunc` across the worker boundary.
|
|
36
|
-
*/
|
|
37
|
-
export type DiffTreeSerializedProjectionMap = {
|
|
38
|
-
[id: string]: {
|
|
39
|
-
reads: string[];
|
|
40
|
-
projection: string;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
58
|
/** Reserved key prefix a projection's result is stored under: `$projection_<id>`. */
|
|
44
59
|
export declare const PROJECTION_PREFIX = "$projection_";
|
|
45
60
|
export type DiffSpliceResult<T = unknown> = {
|
|
@@ -52,9 +67,25 @@ export type DiffSpliceResult<T = unknown> = {
|
|
|
52
67
|
diffResult: JsonDiffResult;
|
|
53
68
|
};
|
|
54
69
|
/**
|
|
55
|
-
*
|
|
70
|
+
* Internal diff tree implementation.
|
|
71
|
+
* Maintains root state and computes diffs for path/value updates.
|
|
72
|
+
* @private
|
|
56
73
|
*/
|
|
57
|
-
export
|
|
74
|
+
export declare class DiffTree {
|
|
75
|
+
private keyFunc?;
|
|
76
|
+
private rootState;
|
|
77
|
+
private projectionOrder;
|
|
78
|
+
private projectionMemo;
|
|
79
|
+
/**
|
|
80
|
+
* Creates a DiffTree instance.
|
|
81
|
+
* @param keyFunc - Optional function to extract a key from objects
|
|
82
|
+
* @param projections - Optional map of derived-value projections, keyed by id. Cycles
|
|
83
|
+
* and reads of an unregistered projection id are rejected here, at construction.
|
|
84
|
+
*/
|
|
85
|
+
constructor(keyFunc?: {
|
|
86
|
+
(val: any): string;
|
|
87
|
+
}, projections?: DiffTreeProjectionMap);
|
|
88
|
+
private RunProjections;
|
|
58
89
|
/**
|
|
59
90
|
* Computes diffs for a batch of path/value pairs.
|
|
60
91
|
* @param data - Array of objects with path and value properties
|
|
@@ -63,7 +94,10 @@ export interface IDiffTree {
|
|
|
63
94
|
DiffBatch(data: Array<{
|
|
64
95
|
path: string;
|
|
65
96
|
value: any;
|
|
66
|
-
}>):
|
|
97
|
+
}>): {
|
|
98
|
+
path: (string | number)[];
|
|
99
|
+
value: unknown;
|
|
100
|
+
}[];
|
|
67
101
|
/**
|
|
68
102
|
* Computes the diff between a new value and the current value at a path.
|
|
69
103
|
* @param path - Dot-separated path to the value
|
|
@@ -71,26 +105,17 @@ export interface IDiffTree {
|
|
|
71
105
|
* @returns Diff results showing changes
|
|
72
106
|
*/
|
|
73
107
|
DiffPath(path: string, value: any, flatten?: boolean): JsonDiffResult;
|
|
74
|
-
SplicePath(path: string, start: number, deleteCount: number
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Constructor interface for IDiffTree.
|
|
78
|
-
*/
|
|
79
|
-
export interface IDiffTreeConstructor {
|
|
108
|
+
SplicePath(path: string, start: number, deleteCount: number, items: any[], flatten?: boolean): DiffSpliceResult<unknown>;
|
|
80
109
|
/**
|
|
81
|
-
*
|
|
82
|
-
* @param
|
|
83
|
-
* @
|
|
110
|
+
* Retrieves the current value at a path.
|
|
111
|
+
* @param path - Dot-separated path to the value
|
|
112
|
+
* @returns The value at the specified path
|
|
84
113
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
GetPath(path: string): any;
|
|
115
|
+
/**
|
|
116
|
+
* Returns an immutable, cached snapshot of the value at a path (empty string for the
|
|
117
|
+
* whole tree). Not part of `IDiffTree`; internal, for a future feature.
|
|
118
|
+
* @param path - Dot-separated path to the value
|
|
119
|
+
*/
|
|
120
|
+
Snapshot(path: string): any;
|
|
88
121
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Factory function that creates a DiffTree class.
|
|
91
|
-
* Can operate in worker mode for async operations.
|
|
92
|
-
* @param jsonDiffFactory - Optional factory for JSON diff utilities
|
|
93
|
-
* @param worker - If true, sets up worker message handling
|
|
94
|
-
* @returns DiffTree constructor
|
|
95
|
-
*/
|
|
96
|
-
export declare function DiffTreeFactory(jsonDiffFactory: () => JsonDiffFactoryResult, arraysEqual: (left: any[], right: any[]) => boolean, worker?: boolean): IDiffTreeConstructor;
|