@flowgram.ai/variable-core 0.1.0-alpha.2 → 0.1.0-alpha.21
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/dist/esm/index.js +1117 -425
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +1799 -520
- package/dist/index.d.ts +1799 -520
- package/dist/index.js +1182 -483
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
- package/README.md +0 -24
package/dist/esm/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { ContainerModule } from "inversify";
|
|
|
16
16
|
// src/variable-engine.ts
|
|
17
17
|
import { Subject as Subject5 } from "rxjs";
|
|
18
18
|
import { inject as inject2, injectable as injectable3, preDestroy } from "inversify";
|
|
19
|
-
import { Disposable as
|
|
19
|
+
import { Disposable as Disposable4, DisposableCollection as DisposableCollection5 } from "@flowgram.ai/utils";
|
|
20
20
|
import { Emitter as Emitter3 } from "@flowgram.ai/utils";
|
|
21
21
|
|
|
22
22
|
// src/utils/toDisposable.tsx
|
|
@@ -47,9 +47,170 @@ var createMemo = () => {
|
|
|
47
47
|
return memo;
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
// src/scope/variable-table.ts
|
|
51
|
+
import { Subject, merge, share, skip, switchMap } from "rxjs";
|
|
52
|
+
import { DisposableCollection, Emitter } from "@flowgram.ai/utils";
|
|
53
|
+
var VariableTable = class {
|
|
54
|
+
constructor(parentTable) {
|
|
55
|
+
this.parentTable = parentTable;
|
|
56
|
+
this.table = /* @__PURE__ */ new Map();
|
|
57
|
+
this.toDispose = new DisposableCollection();
|
|
58
|
+
/**
|
|
59
|
+
* @deprecated
|
|
60
|
+
*/
|
|
61
|
+
this.onDataChangeEmitter = new Emitter();
|
|
62
|
+
this.variables$ = new Subject();
|
|
63
|
+
/**
|
|
64
|
+
* An observable that listens for value changes on any variable within the table.
|
|
65
|
+
*/
|
|
66
|
+
this.anyVariableChange$ = this.variables$.pipe(
|
|
67
|
+
switchMap(
|
|
68
|
+
(_variables) => merge(
|
|
69
|
+
..._variables.map(
|
|
70
|
+
(_v) => _v.value$.pipe(
|
|
71
|
+
// Skip the initial value of the BehaviorSubject
|
|
72
|
+
skip(1)
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
),
|
|
77
|
+
share()
|
|
78
|
+
);
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated Use onListOrAnyVarChange instead.
|
|
81
|
+
*/
|
|
82
|
+
this.onDataChange = this.onDataChangeEmitter.event;
|
|
83
|
+
this._version = 0;
|
|
84
|
+
this.toDispose.pushAll([
|
|
85
|
+
this.onDataChangeEmitter,
|
|
86
|
+
// Activate the share() operator
|
|
87
|
+
this.onAnyVariableChange(() => {
|
|
88
|
+
this.bumpVersion();
|
|
89
|
+
})
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Subscribes to updates on any variable in the list.
|
|
94
|
+
* @param observer A function to be called when any variable's value changes.
|
|
95
|
+
* @returns A disposable object to unsubscribe from the updates.
|
|
96
|
+
*/
|
|
97
|
+
onAnyVariableChange(observer) {
|
|
98
|
+
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Subscribes to changes in the variable list (additions or removals).
|
|
102
|
+
* @param observer A function to be called when the list of variables changes.
|
|
103
|
+
* @returns A disposable object to unsubscribe from the updates.
|
|
104
|
+
*/
|
|
105
|
+
onVariableListChange(observer) {
|
|
106
|
+
return subsToDisposable(this.variables$.subscribe(observer));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Subscribes to both variable list changes and updates to any variable in the list.
|
|
110
|
+
* @param observer A function to be called when either the list or a variable in it changes.
|
|
111
|
+
* @returns A disposable collection to unsubscribe from both events.
|
|
112
|
+
*/
|
|
113
|
+
onListOrAnyVarChange(observer) {
|
|
114
|
+
const disposables = new DisposableCollection();
|
|
115
|
+
disposables.pushAll([this.onVariableListChange(observer), this.onAnyVariableChange(observer)]);
|
|
116
|
+
return disposables;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Fires change events to notify listeners that the data has been updated.
|
|
120
|
+
*/
|
|
121
|
+
fireChange() {
|
|
122
|
+
this.bumpVersion();
|
|
123
|
+
this.onDataChangeEmitter.fire();
|
|
124
|
+
this.variables$.next(this.variables);
|
|
125
|
+
this.parentTable?.fireChange();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The current version of the variable table, incremented on each change.
|
|
129
|
+
*/
|
|
130
|
+
get version() {
|
|
131
|
+
return this._version;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Increments the version number, resetting to 0 if it reaches MAX_SAFE_INTEGER.
|
|
135
|
+
*/
|
|
136
|
+
bumpVersion() {
|
|
137
|
+
this._version = this._version + 1;
|
|
138
|
+
if (this._version === Number.MAX_SAFE_INTEGER) {
|
|
139
|
+
this._version = 0;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* An array of all variables in the table.
|
|
144
|
+
*/
|
|
145
|
+
get variables() {
|
|
146
|
+
return Array.from(this.table.values());
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* An array of all variable keys in the table.
|
|
150
|
+
*/
|
|
151
|
+
get variableKeys() {
|
|
152
|
+
return Array.from(this.table.keys());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Retrieves a variable or a nested property field by its key path.
|
|
156
|
+
* @param keyPath An array of keys representing the path to the desired field.
|
|
157
|
+
* @returns The found variable or property field, or undefined if not found.
|
|
158
|
+
*/
|
|
159
|
+
getByKeyPath(keyPath) {
|
|
160
|
+
const [variableKey, ...propertyKeys] = keyPath || [];
|
|
161
|
+
if (!variableKey) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const variable = this.getVariableByKey(variableKey);
|
|
165
|
+
return propertyKeys.length ? variable?.getByKeyPath(propertyKeys) : variable;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Retrieves a variable by its key.
|
|
169
|
+
* @param key The key of the variable to retrieve.
|
|
170
|
+
* @returns The variable declaration if found, otherwise undefined.
|
|
171
|
+
*/
|
|
172
|
+
getVariableByKey(key) {
|
|
173
|
+
return this.table.get(key);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Adds a variable to the table.
|
|
177
|
+
* If a parent table exists, the variable is also added to the parent.
|
|
178
|
+
* @param variable The variable declaration to add.
|
|
179
|
+
*/
|
|
180
|
+
addVariableToTable(variable) {
|
|
181
|
+
this.table.set(variable.key, variable);
|
|
182
|
+
if (this.parentTable) {
|
|
183
|
+
this.parentTable.addVariableToTable(variable);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Removes a variable from the table.
|
|
188
|
+
* If a parent table exists, the variable is also removed from the parent.
|
|
189
|
+
* @param key The key of the variable to remove.
|
|
190
|
+
*/
|
|
191
|
+
removeVariableFromTable(key) {
|
|
192
|
+
this.table.delete(key);
|
|
193
|
+
if (this.parentTable) {
|
|
194
|
+
this.parentTable.removeVariableFromTable(key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Disposes of all resources used by the variable table.
|
|
199
|
+
*/
|
|
200
|
+
dispose() {
|
|
201
|
+
this.variableKeys.forEach(
|
|
202
|
+
(_key) => this.parentTable?.removeVariableFromTable(_key)
|
|
203
|
+
);
|
|
204
|
+
this.parentTable?.fireChange();
|
|
205
|
+
this.variables$.complete();
|
|
206
|
+
this.variables$.unsubscribe();
|
|
207
|
+
this.toDispose.dispose();
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
50
211
|
// src/scope/scope-chain.ts
|
|
51
212
|
import { inject, injectable } from "inversify";
|
|
52
|
-
import { DisposableCollection } from "@flowgram.ai/utils";
|
|
213
|
+
import { DisposableCollection as DisposableCollection2 } from "@flowgram.ai/utils";
|
|
53
214
|
|
|
54
215
|
// src/providers.ts
|
|
55
216
|
var VariableEngineProvider = Symbol("DynamicVariableEngine");
|
|
@@ -58,13 +219,13 @@ var ContainerProvider = Symbol("ContainerProvider");
|
|
|
58
219
|
// src/scope/scope-chain.ts
|
|
59
220
|
var ScopeChain = class {
|
|
60
221
|
constructor() {
|
|
61
|
-
this.toDispose = new
|
|
222
|
+
this.toDispose = new DisposableCollection2();
|
|
62
223
|
}
|
|
63
224
|
get variableEngine() {
|
|
64
225
|
return this.variableEngineProvider();
|
|
65
226
|
}
|
|
66
227
|
/**
|
|
67
|
-
*
|
|
228
|
+
* Refreshes the dependency and coverage relationships for all scopes.
|
|
68
229
|
*/
|
|
69
230
|
refreshAllChange() {
|
|
70
231
|
this.variableEngine.getAllScopes().forEach((_scope) => {
|
|
@@ -103,12 +264,13 @@ var ASTKind = /* @__PURE__ */ ((ASTKind2) => {
|
|
|
103
264
|
ASTKind2["Map"] = "Map";
|
|
104
265
|
ASTKind2["Union"] = "Union";
|
|
105
266
|
ASTKind2["Any"] = "Any";
|
|
267
|
+
ASTKind2["CustomType"] = "CustomType";
|
|
106
268
|
ASTKind2["Property"] = "Property";
|
|
107
269
|
ASTKind2["VariableDeclaration"] = "VariableDeclaration";
|
|
108
270
|
ASTKind2["VariableDeclarationList"] = "VariableDeclarationList";
|
|
109
271
|
ASTKind2["KeyPathExpression"] = "KeyPathExpression";
|
|
110
272
|
ASTKind2["EnumerateExpression"] = "EnumerateExpression";
|
|
111
|
-
ASTKind2["
|
|
273
|
+
ASTKind2["WrapArrayExpression"] = "WrapArrayExpression";
|
|
112
274
|
ASTKind2["ListNode"] = "ListNode";
|
|
113
275
|
ASTKind2["DataNode"] = "DataNode";
|
|
114
276
|
ASTKind2["MapNode"] = "MapNode";
|
|
@@ -116,7 +278,7 @@ var ASTKind = /* @__PURE__ */ ((ASTKind2) => {
|
|
|
116
278
|
})(ASTKind || {});
|
|
117
279
|
|
|
118
280
|
// src/ast/ast-registers.ts
|
|
119
|
-
import { omit } from "lodash";
|
|
281
|
+
import { omit } from "lodash-es";
|
|
120
282
|
import { injectable as injectable2 } from "inversify";
|
|
121
283
|
|
|
122
284
|
// src/ast/utils/inversify.ts
|
|
@@ -147,6 +309,43 @@ var postConstructAST = () => (target, propertyKey) => {
|
|
|
147
309
|
}
|
|
148
310
|
};
|
|
149
311
|
|
|
312
|
+
// src/ast/flags.ts
|
|
313
|
+
var ASTNodeFlags = /* @__PURE__ */ ((ASTNodeFlags2) => {
|
|
314
|
+
ASTNodeFlags2[ASTNodeFlags2["None"] = 0] = "None";
|
|
315
|
+
ASTNodeFlags2[ASTNodeFlags2["VariableField"] = 1] = "VariableField";
|
|
316
|
+
ASTNodeFlags2[ASTNodeFlags2["Expression"] = 4] = "Expression";
|
|
317
|
+
ASTNodeFlags2[ASTNodeFlags2["BasicType"] = 8] = "BasicType";
|
|
318
|
+
ASTNodeFlags2[ASTNodeFlags2["DrilldownType"] = 16] = "DrilldownType";
|
|
319
|
+
ASTNodeFlags2[ASTNodeFlags2["EnumerateType"] = 32] = "EnumerateType";
|
|
320
|
+
ASTNodeFlags2[ASTNodeFlags2["UnionType"] = 64] = "UnionType";
|
|
321
|
+
ASTNodeFlags2[ASTNodeFlags2["VariableType"] = 120] = "VariableType";
|
|
322
|
+
return ASTNodeFlags2;
|
|
323
|
+
})(ASTNodeFlags || {});
|
|
324
|
+
|
|
325
|
+
// src/ast/match.ts
|
|
326
|
+
var ASTMatch;
|
|
327
|
+
((ASTMatch2) => {
|
|
328
|
+
ASTMatch2.isString = (node) => node?.kind === "String" /* String */;
|
|
329
|
+
ASTMatch2.isNumber = (node) => node?.kind === "Number" /* Number */;
|
|
330
|
+
ASTMatch2.isBoolean = (node) => node?.kind === "Boolean" /* Boolean */;
|
|
331
|
+
ASTMatch2.isInteger = (node) => node?.kind === "Integer" /* Integer */;
|
|
332
|
+
ASTMatch2.isObject = (node) => node?.kind === "Object" /* Object */;
|
|
333
|
+
ASTMatch2.isArray = (node) => node?.kind === "Array" /* Array */;
|
|
334
|
+
ASTMatch2.isMap = (node) => node?.kind === "Map" /* Map */;
|
|
335
|
+
ASTMatch2.isCustomType = (node) => node?.kind === "CustomType" /* CustomType */;
|
|
336
|
+
ASTMatch2.isVariableDeclaration = (node) => node?.kind === "VariableDeclaration" /* VariableDeclaration */;
|
|
337
|
+
ASTMatch2.isProperty = (node) => node?.kind === "Property" /* Property */;
|
|
338
|
+
ASTMatch2.isBaseVariableField = (node) => !!(node?.flags || 0 & 1 /* VariableField */);
|
|
339
|
+
ASTMatch2.isVariableDeclarationList = (node) => node?.kind === "VariableDeclarationList" /* VariableDeclarationList */;
|
|
340
|
+
ASTMatch2.isEnumerateExpression = (node) => node?.kind === "EnumerateExpression" /* EnumerateExpression */;
|
|
341
|
+
ASTMatch2.isWrapArrayExpression = (node) => node?.kind === "WrapArrayExpression" /* WrapArrayExpression */;
|
|
342
|
+
ASTMatch2.isKeyPathExpression = (node) => node?.kind === "KeyPathExpression" /* KeyPathExpression */;
|
|
343
|
+
function is(node, targetType) {
|
|
344
|
+
return node?.kind === targetType?.kind;
|
|
345
|
+
}
|
|
346
|
+
ASTMatch2.is = is;
|
|
347
|
+
})(ASTMatch || (ASTMatch = {}));
|
|
348
|
+
|
|
150
349
|
// src/ast/utils/helpers.ts
|
|
151
350
|
function updateChildNodeHelper({
|
|
152
351
|
getChildNode,
|
|
@@ -182,22 +381,9 @@ function getAllChildren(ast) {
|
|
|
182
381
|
return [...ast.children, ...ast.children.map((_child) => getAllChildren(_child)).flat()];
|
|
183
382
|
}
|
|
184
383
|
function isMatchAST(node, targetType) {
|
|
185
|
-
return node
|
|
384
|
+
return ASTMatch.is(node, targetType);
|
|
186
385
|
}
|
|
187
386
|
|
|
188
|
-
// src/ast/flags.ts
|
|
189
|
-
var ASTNodeFlags = /* @__PURE__ */ ((ASTNodeFlags2) => {
|
|
190
|
-
ASTNodeFlags2[ASTNodeFlags2["None"] = 0] = "None";
|
|
191
|
-
ASTNodeFlags2[ASTNodeFlags2["VariableField"] = 1] = "VariableField";
|
|
192
|
-
ASTNodeFlags2[ASTNodeFlags2["Expression"] = 4] = "Expression";
|
|
193
|
-
ASTNodeFlags2[ASTNodeFlags2["BasicType"] = 8] = "BasicType";
|
|
194
|
-
ASTNodeFlags2[ASTNodeFlags2["DrilldownType"] = 16] = "DrilldownType";
|
|
195
|
-
ASTNodeFlags2[ASTNodeFlags2["EnumerateType"] = 32] = "EnumerateType";
|
|
196
|
-
ASTNodeFlags2[ASTNodeFlags2["UnionType"] = 64] = "UnionType";
|
|
197
|
-
ASTNodeFlags2[ASTNodeFlags2["VariableType"] = 120] = "VariableType";
|
|
198
|
-
return ASTNodeFlags2;
|
|
199
|
-
})(ASTNodeFlags || {});
|
|
200
|
-
|
|
201
387
|
// src/ast/ast-node.ts
|
|
202
388
|
import {
|
|
203
389
|
BehaviorSubject,
|
|
@@ -205,58 +391,62 @@ import {
|
|
|
205
391
|
debounceTime,
|
|
206
392
|
distinctUntilChanged,
|
|
207
393
|
map,
|
|
208
|
-
skip,
|
|
394
|
+
skip as skip2,
|
|
209
395
|
tap
|
|
210
396
|
} from "rxjs";
|
|
211
397
|
import { nanoid } from "nanoid";
|
|
398
|
+
import { isNil, omitBy } from "lodash-es";
|
|
212
399
|
import { shallowEqual } from "fast-equals";
|
|
213
|
-
import { Disposable as Disposable2, DisposableCollection as
|
|
400
|
+
import { Disposable as Disposable2, DisposableCollection as DisposableCollection3 } from "@flowgram.ai/utils";
|
|
214
401
|
var ASTNode = class _ASTNode {
|
|
215
402
|
/**
|
|
216
|
-
*
|
|
217
|
-
* @param createParams
|
|
218
|
-
* @param injectOptions
|
|
403
|
+
* Constructor.
|
|
404
|
+
* @param createParams Necessary parameters for creating an ASTNode.
|
|
405
|
+
* @param injectOptions Dependency injection for various modules.
|
|
219
406
|
*/
|
|
220
407
|
constructor({ key, parent, scope }, opts) {
|
|
221
408
|
/**
|
|
222
|
-
*
|
|
409
|
+
* Node flags, used to record some flag information.
|
|
223
410
|
*/
|
|
224
411
|
this.flags = 0 /* None */;
|
|
225
412
|
/**
|
|
226
|
-
*
|
|
413
|
+
* The version number of the ASTNode, which increments by 1 each time `fireChange` is called.
|
|
227
414
|
*/
|
|
228
415
|
this._version = 0;
|
|
229
416
|
/**
|
|
230
|
-
*
|
|
417
|
+
* Update lock.
|
|
418
|
+
* - When set to `true`, `fireChange` will not trigger any events.
|
|
419
|
+
* - This is useful when multiple updates are needed, and you want to avoid multiple triggers.
|
|
231
420
|
*/
|
|
232
421
|
this.changeLocked = false;
|
|
233
422
|
/**
|
|
234
|
-
*
|
|
423
|
+
* Parameters related to batch updates.
|
|
235
424
|
*/
|
|
236
425
|
this._batch = {
|
|
237
426
|
batching: false,
|
|
238
427
|
hasChangesInBatch: false
|
|
239
428
|
};
|
|
240
429
|
/**
|
|
241
|
-
* AST
|
|
242
|
-
* -
|
|
430
|
+
* AST node change Observable events, implemented based on RxJS.
|
|
431
|
+
* - Emits the current ASTNode value upon subscription.
|
|
432
|
+
* - Emits a new value whenever `fireChange` is called.
|
|
243
433
|
*/
|
|
244
434
|
this.value$ = new BehaviorSubject(this);
|
|
245
435
|
/**
|
|
246
|
-
*
|
|
436
|
+
* Child ASTNodes.
|
|
247
437
|
*/
|
|
248
438
|
this._children = /* @__PURE__ */ new Set();
|
|
249
439
|
/**
|
|
250
|
-
*
|
|
440
|
+
* List of disposal handlers for the ASTNode.
|
|
251
441
|
*/
|
|
252
|
-
this.toDispose = new
|
|
442
|
+
this.toDispose = new DisposableCollection3(
|
|
253
443
|
Disposable2.create(() => {
|
|
254
444
|
this.parent?.fireChange();
|
|
255
445
|
this.children.forEach((child) => child.dispose());
|
|
256
446
|
})
|
|
257
447
|
);
|
|
258
448
|
/**
|
|
259
|
-
*
|
|
449
|
+
* Callback triggered upon disposal.
|
|
260
450
|
*/
|
|
261
451
|
this.onDispose = this.toDispose.onDispose;
|
|
262
452
|
this.scope = scope;
|
|
@@ -264,10 +454,19 @@ var ASTNode = class _ASTNode {
|
|
|
264
454
|
this.opts = opts;
|
|
265
455
|
this.key = key || nanoid();
|
|
266
456
|
this.fromJSON = this.withBatchUpdate(this.fromJSON.bind(this));
|
|
267
|
-
this.
|
|
457
|
+
const rawToJSON = this.toJSON?.bind(this);
|
|
458
|
+
this.toJSON = () => omitBy(
|
|
459
|
+
{
|
|
460
|
+
// always include kind
|
|
461
|
+
kind: this.kind,
|
|
462
|
+
...rawToJSON?.() || {}
|
|
463
|
+
},
|
|
464
|
+
// remove undefined fields
|
|
465
|
+
isNil
|
|
466
|
+
);
|
|
268
467
|
}
|
|
269
468
|
/**
|
|
270
|
-
*
|
|
469
|
+
* The type of the ASTNode.
|
|
271
470
|
*/
|
|
272
471
|
get kind() {
|
|
273
472
|
if (!this.constructor.kind) {
|
|
@@ -276,24 +475,14 @@ var ASTNode = class _ASTNode {
|
|
|
276
475
|
return this.constructor.kind;
|
|
277
476
|
}
|
|
278
477
|
/**
|
|
279
|
-
*
|
|
478
|
+
* Gets all child ASTNodes of the current ASTNode.
|
|
280
479
|
*/
|
|
281
480
|
get children() {
|
|
282
481
|
return Array.from(this._children);
|
|
283
482
|
}
|
|
284
483
|
/**
|
|
285
|
-
*
|
|
286
|
-
* @
|
|
287
|
-
*/
|
|
288
|
-
toJSON() {
|
|
289
|
-
console.warn("[VariableEngine] Please Implement toJSON method for " + this.kind);
|
|
290
|
-
return {
|
|
291
|
-
kind: this.kind
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* 创建子节点
|
|
296
|
-
* @param json 子节点的 AST JSON
|
|
484
|
+
* Creates a child ASTNode.
|
|
485
|
+
* @param json The AST JSON of the child ASTNode.
|
|
297
486
|
* @returns
|
|
298
487
|
*/
|
|
299
488
|
createChildNode(json) {
|
|
@@ -311,8 +500,8 @@ var ASTNode = class _ASTNode {
|
|
|
311
500
|
return child;
|
|
312
501
|
}
|
|
313
502
|
/**
|
|
314
|
-
*
|
|
315
|
-
* @param keyInThis
|
|
503
|
+
* Updates a child ASTNode, quickly implementing the consumption logic for child ASTNode updates.
|
|
504
|
+
* @param keyInThis The specified key on the current object.
|
|
316
505
|
*/
|
|
317
506
|
updateChildNodeByKey(keyInThis, nextJSON) {
|
|
318
507
|
this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
@@ -323,8 +512,8 @@ var ASTNode = class _ASTNode {
|
|
|
323
512
|
});
|
|
324
513
|
}
|
|
325
514
|
/**
|
|
326
|
-
*
|
|
327
|
-
* @param updater
|
|
515
|
+
* Batch updates the ASTNode, merging all `fireChange` calls within the batch function into one.
|
|
516
|
+
* @param updater The batch function.
|
|
328
517
|
* @returns
|
|
329
518
|
*/
|
|
330
519
|
withBatchUpdate(updater) {
|
|
@@ -344,7 +533,7 @@ var ASTNode = class _ASTNode {
|
|
|
344
533
|
};
|
|
345
534
|
}
|
|
346
535
|
/**
|
|
347
|
-
*
|
|
536
|
+
* Triggers an update for the current node.
|
|
348
537
|
*/
|
|
349
538
|
fireChange() {
|
|
350
539
|
if (this.changeLocked || this.disposed) {
|
|
@@ -360,22 +549,24 @@ var ASTNode = class _ASTNode {
|
|
|
360
549
|
this.parent?.fireChange();
|
|
361
550
|
}
|
|
362
551
|
/**
|
|
363
|
-
*
|
|
364
|
-
* -
|
|
552
|
+
* The version value of the ASTNode.
|
|
553
|
+
* - You can used to check whether ASTNode are updated.
|
|
365
554
|
*/
|
|
366
555
|
get version() {
|
|
367
556
|
return this._version;
|
|
368
557
|
}
|
|
369
558
|
/**
|
|
370
|
-
*
|
|
559
|
+
* The unique hash value of the ASTNode.
|
|
560
|
+
* - It will update when the ASTNode is updated.
|
|
561
|
+
* - You can used to check two ASTNode are equal.
|
|
371
562
|
*/
|
|
372
563
|
get hash() {
|
|
373
564
|
return `${this._version}${this.kind}${this.key}`;
|
|
374
565
|
}
|
|
375
566
|
/**
|
|
376
|
-
*
|
|
377
|
-
* @param observer
|
|
378
|
-
* @param selector
|
|
567
|
+
* Listens for changes to the ASTNode.
|
|
568
|
+
* @param observer The listener callback.
|
|
569
|
+
* @param selector Listens for specified data.
|
|
379
570
|
* @returns
|
|
380
571
|
*/
|
|
381
572
|
subscribe(observer, { selector, debounceAnimation, triggerOnInit } = {}) {
|
|
@@ -391,13 +582,17 @@ var ASTNode = class _ASTNode {
|
|
|
391
582
|
return value;
|
|
392
583
|
}
|
|
393
584
|
),
|
|
394
|
-
//
|
|
395
|
-
triggerOnInit ? tap(() => null) :
|
|
396
|
-
//
|
|
585
|
+
// By default, skip the first trigger of BehaviorSubject.
|
|
586
|
+
triggerOnInit ? tap(() => null) : skip2(1),
|
|
587
|
+
// All updates within each animationFrame are merged into one.
|
|
397
588
|
debounceAnimation ? debounceTime(0, animationFrameScheduler) : tap(() => null)
|
|
398
589
|
).subscribe(observer)
|
|
399
590
|
);
|
|
400
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Dispatches a global event for the current ASTNode.
|
|
594
|
+
* @param event The global event.
|
|
595
|
+
*/
|
|
401
596
|
dispatchGlobalEvent(event) {
|
|
402
597
|
this.scope.event.dispatch({
|
|
403
598
|
...event,
|
|
@@ -405,7 +600,7 @@ var ASTNode = class _ASTNode {
|
|
|
405
600
|
});
|
|
406
601
|
}
|
|
407
602
|
/**
|
|
408
|
-
*
|
|
603
|
+
* Disposes the ASTNode.
|
|
409
604
|
*/
|
|
410
605
|
dispose() {
|
|
411
606
|
if (this.toDispose.disposed) {
|
|
@@ -428,8 +623,9 @@ var BaseType = class extends ASTNode {
|
|
|
428
623
|
this.flags = 8 /* BasicType */;
|
|
429
624
|
}
|
|
430
625
|
/**
|
|
431
|
-
*
|
|
432
|
-
* @param
|
|
626
|
+
* Check if the current type is equal to the target type.
|
|
627
|
+
* @param targetTypeJSONOrKind The type to compare with.
|
|
628
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
433
629
|
*/
|
|
434
630
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
435
631
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
@@ -441,17 +637,15 @@ var BaseType = class extends ASTNode {
|
|
|
441
637
|
return this.kind === targetTypeJSON?.kind;
|
|
442
638
|
}
|
|
443
639
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
640
|
+
* Get a variable field by key path.
|
|
641
|
+
*
|
|
642
|
+
* This method should be implemented by drillable types.
|
|
643
|
+
* @param keyPath The key path to search for.
|
|
644
|
+
* @returns The variable field if found, otherwise `undefined`.
|
|
446
645
|
*/
|
|
447
646
|
getByKeyPath(keyPath = []) {
|
|
448
647
|
throw new Error(`Get By Key Path is not implemented for Type: ${this.kind}`);
|
|
449
648
|
}
|
|
450
|
-
toJSON() {
|
|
451
|
-
return {
|
|
452
|
-
kind: this.kind
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
649
|
};
|
|
456
650
|
|
|
457
651
|
// src/ast/type/array.ts
|
|
@@ -460,13 +654,24 @@ var ArrayType = class extends BaseType {
|
|
|
460
654
|
super(...arguments);
|
|
461
655
|
this.flags = 16 /* DrilldownType */ | 32 /* EnumerateType */;
|
|
462
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Deserializes the `ArrayJSON` to the `ArrayType`.
|
|
659
|
+
* @param json The `ArrayJSON` to deserialize.
|
|
660
|
+
*/
|
|
463
661
|
fromJSON({ items }) {
|
|
464
662
|
this.updateChildNodeByKey("items", parseTypeJsonOrKind(items));
|
|
465
663
|
}
|
|
466
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Whether the items type can be drilled down.
|
|
666
|
+
*/
|
|
467
667
|
get canDrilldownItems() {
|
|
468
668
|
return !!(this.items?.flags & 16 /* DrilldownType */);
|
|
469
669
|
}
|
|
670
|
+
/**
|
|
671
|
+
* Get a variable field by key path.
|
|
672
|
+
* @param keyPath The key path to search for.
|
|
673
|
+
* @returns The variable field if found, otherwise `undefined`.
|
|
674
|
+
*/
|
|
470
675
|
getByKeyPath(keyPath) {
|
|
471
676
|
const [curr, ...rest] = keyPath || [];
|
|
472
677
|
if (curr === "0" && this.canDrilldownItems) {
|
|
@@ -474,19 +679,24 @@ var ArrayType = class extends BaseType {
|
|
|
474
679
|
}
|
|
475
680
|
return void 0;
|
|
476
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* Check if the current type is equal to the target type.
|
|
684
|
+
* @param targetTypeJSONOrKind The type to compare with.
|
|
685
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
686
|
+
*/
|
|
477
687
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
478
688
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
479
689
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
480
690
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
481
691
|
return isSuperEqual;
|
|
482
692
|
}
|
|
483
|
-
return targetTypeJSON && isSuperEqual && //
|
|
693
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
484
694
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
485
695
|
}
|
|
486
696
|
/**
|
|
487
|
-
* Array
|
|
488
|
-
* @param targetTypeJSON
|
|
489
|
-
* @returns
|
|
697
|
+
* Array strong comparison.
|
|
698
|
+
* @param targetTypeJSON The type to compare with.
|
|
699
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
490
700
|
*/
|
|
491
701
|
customStrongEqual(targetTypeJSON) {
|
|
492
702
|
if (!this.items) {
|
|
@@ -494,6 +704,10 @@ var ArrayType = class extends BaseType {
|
|
|
494
704
|
}
|
|
495
705
|
return this.items?.isTypeEqual(targetTypeJSON.items);
|
|
496
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Serialize the `ArrayType` to `ArrayJSON`
|
|
709
|
+
* @returns The JSON representation of `ArrayType`.
|
|
710
|
+
*/
|
|
497
711
|
toJSON() {
|
|
498
712
|
return {
|
|
499
713
|
kind: "Array" /* Array */,
|
|
@@ -509,7 +723,31 @@ var StringType = class extends BaseType {
|
|
|
509
723
|
super(...arguments);
|
|
510
724
|
this.flags = 8 /* BasicType */;
|
|
511
725
|
}
|
|
512
|
-
|
|
726
|
+
/**
|
|
727
|
+
* see https://json-schema.org/understanding-json-schema/reference/string#format
|
|
728
|
+
*/
|
|
729
|
+
get format() {
|
|
730
|
+
return this._format;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Deserialize the `StringJSON` to the `StringType`.
|
|
734
|
+
*
|
|
735
|
+
* @param json StringJSON representation of the `StringType`.
|
|
736
|
+
*/
|
|
737
|
+
fromJSON(json) {
|
|
738
|
+
if (json?.format !== this._format) {
|
|
739
|
+
this._format = json?.format;
|
|
740
|
+
this.fireChange();
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Serialize the `StringType` to `StringJSON`.
|
|
745
|
+
* @returns The JSON representation of `StringType`.
|
|
746
|
+
*/
|
|
747
|
+
toJSON() {
|
|
748
|
+
return {
|
|
749
|
+
format: this._format
|
|
750
|
+
};
|
|
513
751
|
}
|
|
514
752
|
};
|
|
515
753
|
StringType.kind = "String" /* String */;
|
|
@@ -520,61 +758,84 @@ var IntegerType = class extends BaseType {
|
|
|
520
758
|
super(...arguments);
|
|
521
759
|
this.flags = 8 /* BasicType */;
|
|
522
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* Deserializes the `IntegerJSON` to the `IntegerType`.
|
|
763
|
+
* @param json The `IntegerJSON` to deserialize.
|
|
764
|
+
*/
|
|
523
765
|
fromJSON() {
|
|
524
766
|
}
|
|
767
|
+
toJSON() {
|
|
768
|
+
return {};
|
|
769
|
+
}
|
|
525
770
|
};
|
|
526
771
|
IntegerType.kind = "Integer" /* Integer */;
|
|
527
772
|
|
|
528
773
|
// src/ast/type/boolean.ts
|
|
529
774
|
var BooleanType = class extends BaseType {
|
|
775
|
+
/**
|
|
776
|
+
* Deserializes the `BooleanJSON` to the `BooleanType`.
|
|
777
|
+
* @param json The `BooleanJSON` to deserialize.
|
|
778
|
+
*/
|
|
530
779
|
fromJSON() {
|
|
531
780
|
}
|
|
781
|
+
toJSON() {
|
|
782
|
+
return {};
|
|
783
|
+
}
|
|
532
784
|
};
|
|
533
785
|
BooleanType.kind = "Boolean" /* Boolean */;
|
|
534
786
|
|
|
535
787
|
// src/ast/type/number.ts
|
|
536
788
|
var NumberType = class extends BaseType {
|
|
789
|
+
/**
|
|
790
|
+
* Deserializes the `NumberJSON` to the `NumberType`.
|
|
791
|
+
* @param json The `NumberJSON` to deserialize.
|
|
792
|
+
*/
|
|
537
793
|
fromJSON() {
|
|
538
794
|
}
|
|
795
|
+
toJSON() {
|
|
796
|
+
return {};
|
|
797
|
+
}
|
|
539
798
|
};
|
|
540
799
|
NumberType.kind = "Number" /* Number */;
|
|
541
800
|
|
|
542
801
|
// src/ast/type/map.ts
|
|
543
802
|
var MapType = class extends BaseType {
|
|
803
|
+
/**
|
|
804
|
+
* Deserializes the `MapJSON` to the `MapType`.
|
|
805
|
+
* @param json The `MapJSON` to deserialize.
|
|
806
|
+
*/
|
|
544
807
|
fromJSON({ keyType = "String" /* String */, valueType }) {
|
|
545
808
|
this.updateChildNodeByKey("keyType", parseTypeJsonOrKind(keyType));
|
|
546
809
|
this.updateChildNodeByKey("valueType", parseTypeJsonOrKind(valueType));
|
|
547
810
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
// const [curr, ...rest] = keyPath || [];
|
|
554
|
-
// if (curr === '*' && this.canDrilldownValue) {
|
|
555
|
-
// return this.valueType.getByKeyPath(rest);
|
|
556
|
-
// }
|
|
557
|
-
// return undefined;
|
|
558
|
-
// }
|
|
811
|
+
/**
|
|
812
|
+
* Check if the current type is equal to the target type.
|
|
813
|
+
* @param targetTypeJSONOrKind The type to compare with.
|
|
814
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
815
|
+
*/
|
|
559
816
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
560
817
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
561
818
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
562
819
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
563
820
|
return isSuperEqual;
|
|
564
821
|
}
|
|
565
|
-
return targetTypeJSON && isSuperEqual && //
|
|
822
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
566
823
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
567
824
|
}
|
|
568
825
|
/**
|
|
569
|
-
* Map
|
|
570
|
-
* @param targetTypeJSON
|
|
571
|
-
* @returns
|
|
826
|
+
* Map strong comparison.
|
|
827
|
+
* @param targetTypeJSON The type to compare with.
|
|
828
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
572
829
|
*/
|
|
573
830
|
customStrongEqual(targetTypeJSON) {
|
|
574
831
|
const { keyType = "String" /* String */, valueType } = targetTypeJSON;
|
|
575
832
|
const isValueTypeEqual = !valueType && !this.valueType || this.valueType?.isTypeEqual(valueType);
|
|
576
833
|
return isValueTypeEqual && this.keyType?.isTypeEqual(keyType);
|
|
577
834
|
}
|
|
835
|
+
/**
|
|
836
|
+
* Serialize the node to a JSON object.
|
|
837
|
+
* @returns The JSON representation of the node.
|
|
838
|
+
*/
|
|
578
839
|
toJSON() {
|
|
579
840
|
return {
|
|
580
841
|
kind: "Map" /* Map */,
|
|
@@ -583,17 +844,23 @@ var MapType = class extends BaseType {
|
|
|
583
844
|
};
|
|
584
845
|
}
|
|
585
846
|
};
|
|
586
|
-
// public flags: ASTNodeFlags = ASTNodeFlags.DrilldownType | ASTNodeFlags.EnumerateType;
|
|
587
847
|
MapType.kind = "Map" /* Map */;
|
|
588
848
|
|
|
589
849
|
// src/ast/type/object.ts
|
|
590
|
-
import { xor } from "lodash";
|
|
850
|
+
import { xor } from "lodash-es";
|
|
591
851
|
var ObjectType = class extends BaseType {
|
|
592
852
|
constructor() {
|
|
593
853
|
super(...arguments);
|
|
594
854
|
this.flags = 16 /* DrilldownType */;
|
|
855
|
+
/**
|
|
856
|
+
* A map of property keys to `Property` instances.
|
|
857
|
+
*/
|
|
595
858
|
this.propertyTable = /* @__PURE__ */ new Map();
|
|
596
859
|
}
|
|
860
|
+
/**
|
|
861
|
+
* Deserializes the `ObjectJSON` to the `ObjectType`.
|
|
862
|
+
* @param json The `ObjectJSON` to deserialize.
|
|
863
|
+
*/
|
|
597
864
|
fromJSON({ properties }) {
|
|
598
865
|
const removedKeys = new Set(this.propertyTable.keys());
|
|
599
866
|
const prev = [...this.properties || []];
|
|
@@ -627,16 +894,19 @@ var ObjectType = class extends BaseType {
|
|
|
627
894
|
}
|
|
628
895
|
});
|
|
629
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Serialize the `ObjectType` to `ObjectJSON`.
|
|
899
|
+
* @returns The JSON representation of `ObjectType`.
|
|
900
|
+
*/
|
|
630
901
|
toJSON() {
|
|
631
902
|
return {
|
|
632
|
-
kind: "Object" /* Object */,
|
|
633
903
|
properties: this.properties.map((_property) => _property.toJSON())
|
|
634
904
|
};
|
|
635
905
|
}
|
|
636
906
|
/**
|
|
637
|
-
*
|
|
638
|
-
* @param keyPath
|
|
639
|
-
* @returns
|
|
907
|
+
* Get a variable field by key path.
|
|
908
|
+
* @param keyPath The key path to search for.
|
|
909
|
+
* @returns The variable field if found, otherwise `undefined`.
|
|
640
910
|
*/
|
|
641
911
|
getByKeyPath(keyPath) {
|
|
642
912
|
const [curr, ...restKeyPath] = keyPath;
|
|
@@ -649,19 +919,24 @@ var ObjectType = class extends BaseType {
|
|
|
649
919
|
}
|
|
650
920
|
return void 0;
|
|
651
921
|
}
|
|
922
|
+
/**
|
|
923
|
+
* Check if the current type is equal to the target type.
|
|
924
|
+
* @param targetTypeJSONOrKind The type to compare with.
|
|
925
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
926
|
+
*/
|
|
652
927
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
653
928
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
654
929
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
655
930
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
656
931
|
return isSuperEqual;
|
|
657
932
|
}
|
|
658
|
-
return targetTypeJSON && isSuperEqual && //
|
|
933
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
659
934
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
660
935
|
}
|
|
661
936
|
/**
|
|
662
|
-
* Object
|
|
663
|
-
* @param targetTypeJSON
|
|
664
|
-
* @returns
|
|
937
|
+
* Object type strong comparison.
|
|
938
|
+
* @param targetTypeJSON The type to compare with.
|
|
939
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
665
940
|
*/
|
|
666
941
|
customStrongEqual(targetTypeJSON) {
|
|
667
942
|
const targetProperties = targetTypeJSON.properties || [];
|
|
@@ -676,15 +951,55 @@ var ObjectType = class extends BaseType {
|
|
|
676
951
|
};
|
|
677
952
|
ObjectType.kind = "Object" /* Object */;
|
|
678
953
|
|
|
954
|
+
// src/ast/type/custom-type.ts
|
|
955
|
+
var CustomType = class extends BaseType {
|
|
956
|
+
/**
|
|
957
|
+
* The name of the custom type.
|
|
958
|
+
*/
|
|
959
|
+
get typeName() {
|
|
960
|
+
return this._typeName;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Deserializes the `CustomTypeJSON` to the `CustomType`.
|
|
964
|
+
* @param json The `CustomTypeJSON` to deserialize.
|
|
965
|
+
*/
|
|
966
|
+
fromJSON(json) {
|
|
967
|
+
if (this._typeName !== json.typeName) {
|
|
968
|
+
this._typeName = json.typeName;
|
|
969
|
+
this.fireChange();
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Check if the current type is equal to the target type.
|
|
974
|
+
* @param targetTypeJSONOrKind The type to compare with.
|
|
975
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
976
|
+
*/
|
|
977
|
+
isTypeEqual(targetTypeJSONOrKind) {
|
|
978
|
+
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
979
|
+
if (targetTypeJSON?.kind === "Union" /* Union */) {
|
|
980
|
+
return (targetTypeJSON?.types || [])?.some(
|
|
981
|
+
(_subType) => this.isTypeEqual(_subType)
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
return targetTypeJSON?.kind === this.kind && targetTypeJSON?.typeName === this.typeName;
|
|
985
|
+
}
|
|
986
|
+
toJSON() {
|
|
987
|
+
return {
|
|
988
|
+
typeName: this.typeName
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
CustomType.kind = "CustomType" /* CustomType */;
|
|
993
|
+
|
|
679
994
|
// src/ast/expression/base-expression.ts
|
|
680
995
|
import {
|
|
681
996
|
distinctUntilChanged as distinctUntilChanged2,
|
|
682
997
|
map as map2,
|
|
683
|
-
switchMap,
|
|
998
|
+
switchMap as switchMap2,
|
|
684
999
|
combineLatest,
|
|
685
1000
|
of,
|
|
686
|
-
Subject,
|
|
687
|
-
share
|
|
1001
|
+
Subject as Subject2,
|
|
1002
|
+
share as share2
|
|
688
1003
|
} from "rxjs";
|
|
689
1004
|
import { shallowEqual as shallowEqual2 } from "fast-equals";
|
|
690
1005
|
|
|
@@ -707,25 +1022,24 @@ var BaseExpression = class extends ASTNode {
|
|
|
707
1022
|
super(params, opts);
|
|
708
1023
|
this.flags = 4 /* Expression */;
|
|
709
1024
|
/**
|
|
710
|
-
*
|
|
1025
|
+
* The variable fields referenced by the expression.
|
|
711
1026
|
*/
|
|
712
1027
|
this._refs = [];
|
|
713
|
-
this.refreshRefs$ = new
|
|
1028
|
+
this.refreshRefs$ = new Subject2();
|
|
714
1029
|
/**
|
|
715
|
-
*
|
|
716
|
-
* 监听 [a.b.c] -> [a.b]
|
|
1030
|
+
* An observable that emits the referenced variable fields when they change.
|
|
717
1031
|
*/
|
|
718
1032
|
this.refs$ = this.refreshRefs$.pipe(
|
|
719
1033
|
map2(() => this.getRefFields()),
|
|
720
1034
|
distinctUntilChanged2(shallowEqual2),
|
|
721
|
-
|
|
1035
|
+
switchMap2(
|
|
722
1036
|
(refs) => !refs?.length ? of([]) : combineLatest(
|
|
723
1037
|
refs.map(
|
|
724
1038
|
(ref) => ref ? ref.value$ : of(void 0)
|
|
725
1039
|
)
|
|
726
1040
|
)
|
|
727
1041
|
),
|
|
728
|
-
|
|
1042
|
+
share2()
|
|
729
1043
|
);
|
|
730
1044
|
this.toDispose.push(
|
|
731
1045
|
subsToDisposable(
|
|
@@ -737,114 +1051,42 @@ var BaseExpression = class extends ASTNode {
|
|
|
737
1051
|
);
|
|
738
1052
|
}
|
|
739
1053
|
/**
|
|
740
|
-
*
|
|
1054
|
+
* Get the global variable table, which is used to access referenced variables.
|
|
741
1055
|
*/
|
|
742
1056
|
get globalVariableTable() {
|
|
743
1057
|
return this.scope.variableEngine.globalVariableTable;
|
|
744
1058
|
}
|
|
745
1059
|
/**
|
|
746
|
-
*
|
|
1060
|
+
* Parent variable fields, sorted from closest to farthest.
|
|
747
1061
|
*/
|
|
748
1062
|
get parentFields() {
|
|
749
1063
|
return getParentFields(this);
|
|
750
1064
|
}
|
|
1065
|
+
/**
|
|
1066
|
+
* The variable fields referenced by the expression.
|
|
1067
|
+
*/
|
|
751
1068
|
get refs() {
|
|
752
1069
|
return this._refs;
|
|
753
1070
|
}
|
|
754
1071
|
/**
|
|
755
|
-
*
|
|
1072
|
+
* Refresh the variable references.
|
|
756
1073
|
*/
|
|
757
1074
|
refreshRefs() {
|
|
758
1075
|
this.refreshRefs$.next();
|
|
759
1076
|
}
|
|
760
1077
|
};
|
|
761
1078
|
|
|
762
|
-
// src/ast/expression/expression-list.ts
|
|
763
|
-
var ExpressionList = class extends ASTNode {
|
|
764
|
-
fromJSON({ expressions }) {
|
|
765
|
-
this.expressions = expressions.map((_expression, idx) => {
|
|
766
|
-
const prevExpression = this.expressions[idx];
|
|
767
|
-
if (prevExpression.kind !== _expression.kind) {
|
|
768
|
-
prevExpression.dispose();
|
|
769
|
-
this.fireChange();
|
|
770
|
-
return this.createChildNode(_expression);
|
|
771
|
-
}
|
|
772
|
-
prevExpression.fromJSON(_expression);
|
|
773
|
-
return prevExpression;
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
toJSON() {
|
|
777
|
-
return {
|
|
778
|
-
kind: "ExpressionList" /* ExpressionList */,
|
|
779
|
-
properties: this.expressions.map((_expression) => _expression.toJSON())
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
ExpressionList.kind = "ExpressionList" /* ExpressionList */;
|
|
784
|
-
|
|
785
|
-
// src/ast/expression/keypath-expression.ts
|
|
786
|
-
import { shallowEqual as shallowEqual3 } from "fast-equals";
|
|
787
|
-
var KeyPathExpression = class extends BaseExpression {
|
|
788
|
-
constructor(params, opts) {
|
|
789
|
-
super(params, opts);
|
|
790
|
-
this._keyPath = [];
|
|
791
|
-
this.toDispose.pushAll([
|
|
792
|
-
// 可以用变量列表变化时候 (有新增或者删除时)
|
|
793
|
-
this.scope.available.onVariableListChange(() => {
|
|
794
|
-
this.refreshRefs();
|
|
795
|
-
}),
|
|
796
|
-
// this._keyPath 指向的可引用变量发生变化时,刷新引用数据
|
|
797
|
-
this.scope.available.onAnyVariableChange((_v) => {
|
|
798
|
-
if (_v.key === this._keyPath[0]) {
|
|
799
|
-
this.refreshRefs();
|
|
800
|
-
}
|
|
801
|
-
})
|
|
802
|
-
]);
|
|
803
|
-
}
|
|
804
|
-
get keyPath() {
|
|
805
|
-
return this._keyPath;
|
|
806
|
-
}
|
|
807
|
-
getRefFields() {
|
|
808
|
-
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
809
|
-
return ref ? [ref] : [];
|
|
810
|
-
}
|
|
811
|
-
get returnType() {
|
|
812
|
-
const [refNode] = this._refs || [];
|
|
813
|
-
if (refNode && refNode.flags & 1 /* VariableField */) {
|
|
814
|
-
return refNode.type;
|
|
815
|
-
}
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* 业务重改该方法可快速定制自己的 Path 表达式
|
|
820
|
-
* - 只需要将业务的 Path 解析为变量系统的 KeyPath 即可
|
|
821
|
-
* @param json 业务定义的 Path 表达式
|
|
822
|
-
* @returns
|
|
823
|
-
*/
|
|
824
|
-
parseToKeyPath(json) {
|
|
825
|
-
return json.keyPath;
|
|
826
|
-
}
|
|
827
|
-
fromJSON(json) {
|
|
828
|
-
const keyPath = this.parseToKeyPath(json);
|
|
829
|
-
if (!shallowEqual3(keyPath, this._keyPath)) {
|
|
830
|
-
this._keyPath = keyPath;
|
|
831
|
-
this.refreshRefs();
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
toJSON() {
|
|
835
|
-
return {
|
|
836
|
-
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
837
|
-
keyPath: this._keyPath
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
};
|
|
841
|
-
KeyPathExpression.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
842
|
-
|
|
843
1079
|
// src/ast/expression/enumerate-expression.ts
|
|
844
1080
|
var EnumerateExpression = class extends BaseExpression {
|
|
1081
|
+
/**
|
|
1082
|
+
* The expression to be enumerated.
|
|
1083
|
+
*/
|
|
845
1084
|
get enumerateFor() {
|
|
846
1085
|
return this._enumerateFor;
|
|
847
1086
|
}
|
|
1087
|
+
/**
|
|
1088
|
+
* The return type of the expression.
|
|
1089
|
+
*/
|
|
848
1090
|
get returnType() {
|
|
849
1091
|
const childReturnType = this.enumerateFor?.returnType;
|
|
850
1092
|
if (childReturnType?.kind === "Array" /* Array */) {
|
|
@@ -852,12 +1094,24 @@ var EnumerateExpression = class extends BaseExpression {
|
|
|
852
1094
|
}
|
|
853
1095
|
return void 0;
|
|
854
1096
|
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Get the variable fields referenced by the expression.
|
|
1099
|
+
* @returns An empty array, as this expression does not reference any variables.
|
|
1100
|
+
*/
|
|
855
1101
|
getRefFields() {
|
|
856
1102
|
return [];
|
|
857
1103
|
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Deserializes the `EnumerateExpressionJSON` to the `EnumerateExpression`.
|
|
1106
|
+
* @param json The `EnumerateExpressionJSON` to deserialize.
|
|
1107
|
+
*/
|
|
858
1108
|
fromJSON({ enumerateFor: expression }) {
|
|
859
1109
|
this.updateChildNodeByKey("_enumerateFor", expression);
|
|
860
1110
|
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Serialize the `EnumerateExpression` to `EnumerateExpressionJSON`.
|
|
1113
|
+
* @returns The JSON representation of `EnumerateExpression`.
|
|
1114
|
+
*/
|
|
861
1115
|
toJSON() {
|
|
862
1116
|
return {
|
|
863
1117
|
kind: "EnumerateExpression" /* EnumerateExpression */,
|
|
@@ -867,11 +1121,12 @@ var EnumerateExpression = class extends BaseExpression {
|
|
|
867
1121
|
};
|
|
868
1122
|
EnumerateExpression.kind = "EnumerateExpression" /* EnumerateExpression */;
|
|
869
1123
|
|
|
870
|
-
// src/ast/expression/keypath-expression
|
|
871
|
-
import {
|
|
1124
|
+
// src/ast/expression/keypath-expression.ts
|
|
1125
|
+
import { distinctUntilChanged as distinctUntilChanged3 } from "rxjs";
|
|
1126
|
+
import { shallowEqual as shallowEqual3 } from "fast-equals";
|
|
872
1127
|
|
|
873
1128
|
// src/ast/utils/expression.ts
|
|
874
|
-
import { intersection } from "lodash";
|
|
1129
|
+
import { intersection } from "lodash-es";
|
|
875
1130
|
function getAllRefs(ast) {
|
|
876
1131
|
return getAllChildren(ast).filter((_child) => _child.flags & 4 /* Expression */).map((_child) => _child.refs).flat().filter(Boolean);
|
|
877
1132
|
}
|
|
@@ -891,36 +1146,45 @@ function checkRefCycle(curr, refNodes) {
|
|
|
891
1146
|
return intersection(Array.from(visited), getParentFields(curr)).length > 0;
|
|
892
1147
|
}
|
|
893
1148
|
|
|
894
|
-
// src/ast/expression/keypath-expression
|
|
895
|
-
var
|
|
1149
|
+
// src/ast/expression/keypath-expression.ts
|
|
1150
|
+
var KeyPathExpression = class extends BaseExpression {
|
|
896
1151
|
constructor(params, opts) {
|
|
897
1152
|
super(params, opts);
|
|
898
1153
|
this._keyPath = [];
|
|
899
1154
|
this.toDispose.pushAll([
|
|
900
|
-
//
|
|
1155
|
+
// Can be used when the variable list changes (when there are additions or deletions).
|
|
901
1156
|
this.scope.available.onVariableListChange(() => {
|
|
902
1157
|
this.refreshRefs();
|
|
903
1158
|
}),
|
|
904
|
-
// this._keyPath
|
|
1159
|
+
// When the referable variable pointed to by this._keyPath changes, refresh the reference data.
|
|
905
1160
|
this.scope.available.onAnyVariableChange((_v) => {
|
|
906
1161
|
if (_v.key === this._keyPath[0]) {
|
|
907
1162
|
this.refreshRefs();
|
|
908
1163
|
}
|
|
909
1164
|
}),
|
|
910
1165
|
subsToDisposable(
|
|
911
|
-
this.refs$.
|
|
1166
|
+
this.refs$.pipe(
|
|
1167
|
+
distinctUntilChanged3(
|
|
1168
|
+
(prev, next) => prev === next,
|
|
1169
|
+
(_refs) => _refs?.[0]?.type?.hash
|
|
1170
|
+
)
|
|
1171
|
+
).subscribe((_type) => {
|
|
912
1172
|
const [ref] = this._refs;
|
|
913
|
-
|
|
914
|
-
this.prevRefTypeHash = ref?.type?.hash;
|
|
915
|
-
this.updateChildNodeByKey("_returnType", this.getReturnTypeJSONByRef(ref));
|
|
916
|
-
}
|
|
1173
|
+
this.updateChildNodeByKey("_returnType", this.getReturnTypeJSONByRef(ref));
|
|
917
1174
|
})
|
|
918
1175
|
)
|
|
919
1176
|
]);
|
|
920
1177
|
}
|
|
1178
|
+
/**
|
|
1179
|
+
* The key path of the variable.
|
|
1180
|
+
*/
|
|
921
1181
|
get keyPath() {
|
|
922
1182
|
return this._keyPath;
|
|
923
1183
|
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Get the variable fields referenced by the expression.
|
|
1186
|
+
* @returns An array of referenced variable fields.
|
|
1187
|
+
*/
|
|
924
1188
|
getRefFields() {
|
|
925
1189
|
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
926
1190
|
if (checkRefCycle(this, [ref])) {
|
|
@@ -932,39 +1196,189 @@ var KeyPathExpressionV2 = class extends BaseExpression {
|
|
|
932
1196
|
}
|
|
933
1197
|
return ref ? [ref] : [];
|
|
934
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* The return type of the expression.
|
|
1201
|
+
*/
|
|
935
1202
|
get returnType() {
|
|
936
1203
|
return this._returnType;
|
|
937
1204
|
}
|
|
938
1205
|
/**
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
*
|
|
942
|
-
* @
|
|
1206
|
+
* Parse the business-defined path expression into a key path.
|
|
1207
|
+
*
|
|
1208
|
+
* Businesses can quickly customize their own path expressions by modifying this method.
|
|
1209
|
+
* @param json The path expression defined by the business.
|
|
1210
|
+
* @returns The key path.
|
|
943
1211
|
*/
|
|
944
1212
|
parseToKeyPath(json) {
|
|
945
1213
|
return json.keyPath;
|
|
946
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Deserializes the `KeyPathExpressionJSON` to the `KeyPathExpression`.
|
|
1217
|
+
* @param json The `KeyPathExpressionJSON` to deserialize.
|
|
1218
|
+
*/
|
|
947
1219
|
fromJSON(json) {
|
|
948
1220
|
const keyPath = this.parseToKeyPath(json);
|
|
949
|
-
if (!
|
|
1221
|
+
if (!shallowEqual3(keyPath, this._keyPath)) {
|
|
950
1222
|
this._keyPath = keyPath;
|
|
1223
|
+
this._rawPathJson = json;
|
|
951
1224
|
this.refreshRefs();
|
|
952
1225
|
}
|
|
953
1226
|
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Get the return type JSON by reference.
|
|
1229
|
+
* @param _ref The referenced variable field.
|
|
1230
|
+
* @returns The JSON representation of the return type.
|
|
1231
|
+
*/
|
|
954
1232
|
getReturnTypeJSONByRef(_ref) {
|
|
955
1233
|
return _ref?.type?.toJSON();
|
|
956
1234
|
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Serialize the `KeyPathExpression` to `KeyPathExpressionJSON`.
|
|
1237
|
+
* @returns The JSON representation of `KeyPathExpression`.
|
|
1238
|
+
*/
|
|
1239
|
+
toJSON() {
|
|
1240
|
+
return this._rawPathJson;
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
KeyPathExpression.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
1244
|
+
|
|
1245
|
+
// src/ast/expression/legacy-keypath-expression.ts
|
|
1246
|
+
import { shallowEqual as shallowEqual4 } from "fast-equals";
|
|
1247
|
+
var LegacyKeyPathExpression = class extends BaseExpression {
|
|
1248
|
+
constructor(params, opts) {
|
|
1249
|
+
super(params, opts);
|
|
1250
|
+
this._keyPath = [];
|
|
1251
|
+
this.toDispose.pushAll([
|
|
1252
|
+
// Can be used when the variable list changes (when there are additions or deletions).
|
|
1253
|
+
this.scope.available.onVariableListChange(() => {
|
|
1254
|
+
this.refreshRefs();
|
|
1255
|
+
}),
|
|
1256
|
+
// When the referable variable pointed to by this._keyPath changes, refresh the reference data.
|
|
1257
|
+
this.scope.available.onAnyVariableChange((_v) => {
|
|
1258
|
+
if (_v.key === this._keyPath[0]) {
|
|
1259
|
+
this.refreshRefs();
|
|
1260
|
+
}
|
|
1261
|
+
})
|
|
1262
|
+
]);
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* The key path of the variable.
|
|
1266
|
+
*/
|
|
1267
|
+
get keyPath() {
|
|
1268
|
+
return this._keyPath;
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Get the variable fields referenced by the expression.
|
|
1272
|
+
* @returns An array of referenced variable fields.
|
|
1273
|
+
*/
|
|
1274
|
+
getRefFields() {
|
|
1275
|
+
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
1276
|
+
return ref ? [ref] : [];
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* The return type of the expression.
|
|
1280
|
+
*/
|
|
1281
|
+
get returnType() {
|
|
1282
|
+
const [refNode] = this._refs || [];
|
|
1283
|
+
if (refNode && refNode.flags & 1 /* VariableField */) {
|
|
1284
|
+
return refNode.type;
|
|
1285
|
+
}
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Parse the business-defined path expression into a key path.
|
|
1290
|
+
*
|
|
1291
|
+
* Businesses can quickly customize their own path expressions by modifying this method.
|
|
1292
|
+
* @param json The path expression defined by the business.
|
|
1293
|
+
* @returns The key path.
|
|
1294
|
+
*/
|
|
1295
|
+
parseToKeyPath(json) {
|
|
1296
|
+
return json.keyPath;
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Deserializes the `KeyPathExpressionJSON` to the `KeyPathExpression`.
|
|
1300
|
+
* @param json The `KeyPathExpressionJSON` to deserialize.
|
|
1301
|
+
*/
|
|
1302
|
+
fromJSON(json) {
|
|
1303
|
+
const keyPath = this.parseToKeyPath(json);
|
|
1304
|
+
if (!shallowEqual4(keyPath, this._keyPath)) {
|
|
1305
|
+
this._keyPath = keyPath;
|
|
1306
|
+
this._rawPathJson = json;
|
|
1307
|
+
this.refreshRefs();
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Serialize the `KeyPathExpression` to `KeyPathExpressionJSON`.
|
|
1312
|
+
* @returns The JSON representation of `KeyPathExpression`.
|
|
1313
|
+
*/
|
|
1314
|
+
toJSON() {
|
|
1315
|
+
return this._rawPathJson;
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
LegacyKeyPathExpression.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
1319
|
+
|
|
1320
|
+
// src/ast/expression/wrap-array-expression.ts
|
|
1321
|
+
var WrapArrayExpression = class extends BaseExpression {
|
|
1322
|
+
/**
|
|
1323
|
+
* The expression to be wrapped.
|
|
1324
|
+
*/
|
|
1325
|
+
get wrapFor() {
|
|
1326
|
+
return this._wrapFor;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* The return type of the expression.
|
|
1330
|
+
*/
|
|
1331
|
+
get returnType() {
|
|
1332
|
+
return this._returnType;
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Refresh the return type of the expression.
|
|
1336
|
+
*/
|
|
1337
|
+
refreshReturnType() {
|
|
1338
|
+
const childReturnTypeJSON = this.wrapFor?.returnType?.toJSON();
|
|
1339
|
+
this.updateChildNodeByKey("_returnType", {
|
|
1340
|
+
kind: "Array" /* Array */,
|
|
1341
|
+
items: childReturnTypeJSON
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Get the variable fields referenced by the expression.
|
|
1346
|
+
* @returns An empty array, as this expression does not reference any variables.
|
|
1347
|
+
*/
|
|
1348
|
+
getRefFields() {
|
|
1349
|
+
return [];
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Deserializes the `WrapArrayExpressionJSON` to the `WrapArrayExpression`.
|
|
1353
|
+
* @param json The `WrapArrayExpressionJSON` to deserialize.
|
|
1354
|
+
*/
|
|
1355
|
+
fromJSON({ wrapFor: expression }) {
|
|
1356
|
+
this.updateChildNodeByKey("_wrapFor", expression);
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Serialize the `WrapArrayExpression` to `WrapArrayExpressionJSON`.
|
|
1360
|
+
* @returns The JSON representation of `WrapArrayExpression`.
|
|
1361
|
+
*/
|
|
957
1362
|
toJSON() {
|
|
958
1363
|
return {
|
|
959
|
-
kind: "
|
|
960
|
-
|
|
1364
|
+
kind: "WrapArrayExpression" /* WrapArrayExpression */,
|
|
1365
|
+
wrapFor: this.wrapFor?.toJSON()
|
|
961
1366
|
};
|
|
962
1367
|
}
|
|
1368
|
+
init() {
|
|
1369
|
+
this.refreshReturnType = this.refreshReturnType.bind(this);
|
|
1370
|
+
this.toDispose.push(
|
|
1371
|
+
this.subscribe(this.refreshReturnType, {
|
|
1372
|
+
selector: (curr) => curr.wrapFor?.returnType,
|
|
1373
|
+
triggerOnInit: true
|
|
1374
|
+
})
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
963
1377
|
};
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1378
|
+
WrapArrayExpression.kind = "WrapArrayExpression" /* WrapArrayExpression */;
|
|
1379
|
+
__decorateClass([
|
|
1380
|
+
postConstructAST()
|
|
1381
|
+
], WrapArrayExpression.prototype, "init", 1);
|
|
968
1382
|
|
|
969
1383
|
// src/ast/declaration/base-variable-field.ts
|
|
970
1384
|
import { shallowEqual as shallowEqual5 } from "fast-equals";
|
|
@@ -975,35 +1389,73 @@ var BaseVariableField = class extends ASTNode {
|
|
|
975
1389
|
this._meta = {};
|
|
976
1390
|
}
|
|
977
1391
|
/**
|
|
978
|
-
*
|
|
1392
|
+
* Parent variable fields, sorted from closest to farthest
|
|
979
1393
|
*/
|
|
980
1394
|
get parentFields() {
|
|
981
1395
|
return getParentFields(this);
|
|
982
1396
|
}
|
|
1397
|
+
/**
|
|
1398
|
+
* KeyPath of the variable field, sorted from farthest to closest
|
|
1399
|
+
*/
|
|
1400
|
+
get keyPath() {
|
|
1401
|
+
return [...this.parentFields.reverse().map((_field) => _field.key), this.key];
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Metadata of the variable field, you cans store information like `title`, `icon`, etc.
|
|
1405
|
+
*/
|
|
983
1406
|
get meta() {
|
|
984
1407
|
return this._meta;
|
|
985
1408
|
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Type of the variable field, similar to js code:
|
|
1411
|
+
* `const v: string`
|
|
1412
|
+
*/
|
|
986
1413
|
get type() {
|
|
987
1414
|
return this._initializer?.returnType || this._type;
|
|
988
1415
|
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Initializer of the variable field, similar to js code:
|
|
1418
|
+
* `const v = 'hello'`
|
|
1419
|
+
*
|
|
1420
|
+
* with initializer, the type of field will be inferred from the initializer.
|
|
1421
|
+
*/
|
|
989
1422
|
get initializer() {
|
|
990
1423
|
return this._initializer;
|
|
991
1424
|
}
|
|
992
1425
|
/**
|
|
993
|
-
*
|
|
1426
|
+
* The global unique hash of the field, and will be changed when the field is updated.
|
|
1427
|
+
*/
|
|
1428
|
+
get hash() {
|
|
1429
|
+
return `[${this._version}]${this.keyPath.join(".")}`;
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* Deserialize the `BaseVariableFieldJSON` to the `BaseVariableField`.
|
|
1433
|
+
* @param json ASTJSON representation of `BaseVariableField`
|
|
994
1434
|
*/
|
|
995
1435
|
fromJSON({ type, initializer, meta }) {
|
|
996
1436
|
this.updateType(type);
|
|
997
1437
|
this.updateInitializer(initializer);
|
|
998
1438
|
this.updateMeta(meta);
|
|
999
1439
|
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Update the type of the variable field
|
|
1442
|
+
* @param type type ASTJSON representation of Type
|
|
1443
|
+
*/
|
|
1000
1444
|
updateType(type) {
|
|
1001
1445
|
const nextTypeJson = typeof type === "string" ? { kind: type } : type;
|
|
1002
1446
|
this.updateChildNodeByKey("_type", nextTypeJson);
|
|
1003
1447
|
}
|
|
1448
|
+
/**
|
|
1449
|
+
* Update the initializer of the variable field
|
|
1450
|
+
* @param nextInitializer initializer ASTJSON representation of Expression
|
|
1451
|
+
*/
|
|
1004
1452
|
updateInitializer(nextInitializer) {
|
|
1005
1453
|
this.updateChildNodeByKey("_initializer", nextInitializer);
|
|
1006
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Update the meta data of the variable field
|
|
1457
|
+
* @param nextMeta meta data of the variable field
|
|
1458
|
+
*/
|
|
1007
1459
|
updateMeta(nextMeta) {
|
|
1008
1460
|
if (!shallowEqual5(nextMeta, this._meta)) {
|
|
1009
1461
|
this._meta = nextMeta;
|
|
@@ -1011,7 +1463,8 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1011
1463
|
}
|
|
1012
1464
|
}
|
|
1013
1465
|
/**
|
|
1014
|
-
*
|
|
1466
|
+
* Get the variable field by keyPath, similar to js code:
|
|
1467
|
+
* `v.a.b`
|
|
1015
1468
|
* @param keyPath
|
|
1016
1469
|
* @returns
|
|
1017
1470
|
*/
|
|
@@ -1022,7 +1475,7 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1022
1475
|
return void 0;
|
|
1023
1476
|
}
|
|
1024
1477
|
/**
|
|
1025
|
-
*
|
|
1478
|
+
* Subscribe to type change of the variable field
|
|
1026
1479
|
* @param observer
|
|
1027
1480
|
* @returns
|
|
1028
1481
|
*/
|
|
@@ -1030,12 +1483,11 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1030
1483
|
return this.subscribe(observer, { selector: (curr) => curr.type });
|
|
1031
1484
|
}
|
|
1032
1485
|
/**
|
|
1033
|
-
*
|
|
1034
|
-
* @returns
|
|
1486
|
+
* Serialize the variable field to JSON
|
|
1487
|
+
* @returns ASTNodeJSON representation of `BaseVariableField`
|
|
1035
1488
|
*/
|
|
1036
1489
|
toJSON() {
|
|
1037
1490
|
return {
|
|
1038
|
-
kind: this.kind,
|
|
1039
1491
|
key: this.key,
|
|
1040
1492
|
type: this.type?.toJSON(),
|
|
1041
1493
|
initializer: this.initializer?.toJSON(),
|
|
@@ -1049,34 +1501,42 @@ var VariableDeclaration = class extends BaseVariableField {
|
|
|
1049
1501
|
constructor(params) {
|
|
1050
1502
|
super(params);
|
|
1051
1503
|
this._order = 0;
|
|
1052
|
-
this.scope.output.addVariableToTable(this);
|
|
1053
|
-
this.toDispose.push(
|
|
1054
|
-
Disposable3.create(() => {
|
|
1055
|
-
this.scope.output.setHasChanges();
|
|
1056
|
-
this.scope.output.removeVariableFromTable(this.key);
|
|
1057
|
-
})
|
|
1058
|
-
);
|
|
1059
1504
|
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Variable sorting order, which is used to sort variables in `scope.outputs.variables`
|
|
1507
|
+
*/
|
|
1060
1508
|
get order() {
|
|
1061
1509
|
return this._order;
|
|
1062
1510
|
}
|
|
1063
1511
|
/**
|
|
1064
|
-
*
|
|
1512
|
+
* Deserialize the `VariableDeclarationJSON` to the `VariableDeclaration`.
|
|
1065
1513
|
*/
|
|
1066
1514
|
fromJSON({ order, ...rest }) {
|
|
1067
1515
|
this.updateOrder(order);
|
|
1068
1516
|
super.fromJSON(rest);
|
|
1069
1517
|
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Update the sorting order of the variable declaration.
|
|
1520
|
+
* @param order Variable sorting order. Default is 0.
|
|
1521
|
+
*/
|
|
1070
1522
|
updateOrder(order = 0) {
|
|
1071
1523
|
if (order !== this._order) {
|
|
1072
1524
|
this._order = order;
|
|
1073
|
-
this.
|
|
1525
|
+
this.dispatchGlobalEvent({
|
|
1526
|
+
type: "ReSortVariableDeclarations"
|
|
1527
|
+
});
|
|
1074
1528
|
this.fireChange();
|
|
1075
1529
|
}
|
|
1076
1530
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1531
|
+
/**
|
|
1532
|
+
* Serialize the `VariableDeclaration` to `VariableDeclarationJSON`.
|
|
1533
|
+
* @returns The JSON representation of `VariableDeclaration`.
|
|
1534
|
+
*/
|
|
1535
|
+
toJSON() {
|
|
1536
|
+
return {
|
|
1537
|
+
...super.toJSON(),
|
|
1538
|
+
order: this.order
|
|
1539
|
+
};
|
|
1080
1540
|
}
|
|
1081
1541
|
};
|
|
1082
1542
|
VariableDeclaration.kind = "VariableDeclaration" /* VariableDeclaration */;
|
|
@@ -1085,8 +1545,18 @@ VariableDeclaration.kind = "VariableDeclaration" /* VariableDeclaration */;
|
|
|
1085
1545
|
var VariableDeclarationList = class extends ASTNode {
|
|
1086
1546
|
constructor() {
|
|
1087
1547
|
super(...arguments);
|
|
1548
|
+
/**
|
|
1549
|
+
* Map of variable declarations, keyed by variable name.
|
|
1550
|
+
*/
|
|
1088
1551
|
this.declarationTable = /* @__PURE__ */ new Map();
|
|
1089
1552
|
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Deserialize the `VariableDeclarationListJSON` to the `VariableDeclarationList`.
|
|
1555
|
+
* - VariableDeclarationListChangeAction will be dispatched after deserialization.
|
|
1556
|
+
*
|
|
1557
|
+
* @param declarations Variable declarations.
|
|
1558
|
+
* @param startOrder The starting order number for variables. Default is 0.
|
|
1559
|
+
*/
|
|
1090
1560
|
fromJSON({ declarations, startOrder }) {
|
|
1091
1561
|
const removedKeys = new Set(this.declarationTable.keys());
|
|
1092
1562
|
const prev = [...this.declarations || []];
|
|
@@ -1126,10 +1596,14 @@ var VariableDeclarationList = class extends ASTNode {
|
|
|
1126
1596
|
}
|
|
1127
1597
|
});
|
|
1128
1598
|
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Serialize the `VariableDeclarationList` to the `VariableDeclarationListJSON`.
|
|
1601
|
+
* @returns ASTJSON representation of `VariableDeclarationList`
|
|
1602
|
+
*/
|
|
1129
1603
|
toJSON() {
|
|
1130
1604
|
return {
|
|
1131
1605
|
kind: "VariableDeclarationList" /* VariableDeclarationList */,
|
|
1132
|
-
|
|
1606
|
+
declarations: this.declarations.map((_declaration) => _declaration.toJSON())
|
|
1133
1607
|
};
|
|
1134
1608
|
}
|
|
1135
1609
|
};
|
|
@@ -1143,9 +1617,16 @@ Property.kind = "Property" /* Property */;
|
|
|
1143
1617
|
// src/ast/common/data-node.ts
|
|
1144
1618
|
import { shallowEqual as shallowEqual6 } from "fast-equals";
|
|
1145
1619
|
var DataNode = class extends ASTNode {
|
|
1620
|
+
/**
|
|
1621
|
+
* The data of the node.
|
|
1622
|
+
*/
|
|
1146
1623
|
get data() {
|
|
1147
1624
|
return this._data;
|
|
1148
1625
|
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Deserializes the `DataNodeJSON` to the `DataNode`.
|
|
1628
|
+
* @param json The `DataNodeJSON` to deserialize.
|
|
1629
|
+
*/
|
|
1149
1630
|
fromJSON(json) {
|
|
1150
1631
|
const { kind, ...restData } = json;
|
|
1151
1632
|
if (!shallowEqual6(restData, this._data)) {
|
|
@@ -1153,12 +1634,20 @@ var DataNode = class extends ASTNode {
|
|
|
1153
1634
|
this.fireChange();
|
|
1154
1635
|
}
|
|
1155
1636
|
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Serialize the `DataNode` to `DataNodeJSON`.
|
|
1639
|
+
* @returns The JSON representation of `DataNode`.
|
|
1640
|
+
*/
|
|
1156
1641
|
toJSON() {
|
|
1157
1642
|
return {
|
|
1158
1643
|
kind: "DataNode" /* DataNode */,
|
|
1159
1644
|
...this._data
|
|
1160
1645
|
};
|
|
1161
1646
|
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Partially update the data of the node.
|
|
1649
|
+
* @param nextData The data to be updated.
|
|
1650
|
+
*/
|
|
1162
1651
|
partialUpdate(nextData) {
|
|
1163
1652
|
if (!shallowEqual6(nextData, this._data)) {
|
|
1164
1653
|
this._data = {
|
|
@@ -1173,9 +1662,16 @@ DataNode.kind = "DataNode" /* DataNode */;
|
|
|
1173
1662
|
|
|
1174
1663
|
// src/ast/common/list-node.ts
|
|
1175
1664
|
var ListNode = class extends ASTNode {
|
|
1665
|
+
/**
|
|
1666
|
+
* The list of nodes.
|
|
1667
|
+
*/
|
|
1176
1668
|
get list() {
|
|
1177
1669
|
return this._list;
|
|
1178
1670
|
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Deserializes the `ListNodeJSON` to the `ListNode`.
|
|
1673
|
+
* @param json The `ListNodeJSON` to deserialize.
|
|
1674
|
+
*/
|
|
1179
1675
|
fromJSON({ list }) {
|
|
1180
1676
|
this._list.slice(list.length).forEach((_item) => {
|
|
1181
1677
|
_item.dispose();
|
|
@@ -1192,6 +1688,10 @@ var ListNode = class extends ASTNode {
|
|
|
1192
1688
|
return prevItem;
|
|
1193
1689
|
});
|
|
1194
1690
|
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Serialize the `ListNode` to `ListNodeJSON`.
|
|
1693
|
+
* @returns The JSON representation of `ListNode`.
|
|
1694
|
+
*/
|
|
1195
1695
|
toJSON() {
|
|
1196
1696
|
return {
|
|
1197
1697
|
kind: "ListNode" /* ListNode */,
|
|
@@ -1207,6 +1707,10 @@ var MapNode = class extends ASTNode {
|
|
|
1207
1707
|
super(...arguments);
|
|
1208
1708
|
this.map = /* @__PURE__ */ new Map();
|
|
1209
1709
|
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Deserializes the `MapNodeJSON` to the `MapNode`.
|
|
1712
|
+
* @param json The `MapNodeJSON` to deserialize.
|
|
1713
|
+
*/
|
|
1210
1714
|
fromJSON({ map: map4 }) {
|
|
1211
1715
|
const removedKeys = new Set(this.map.keys());
|
|
1212
1716
|
for (const [key, item] of map4 || []) {
|
|
@@ -1217,6 +1721,10 @@ var MapNode = class extends ASTNode {
|
|
|
1217
1721
|
this.remove(removeKey);
|
|
1218
1722
|
}
|
|
1219
1723
|
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Serialize the `MapNode` to `MapNodeJSON`.
|
|
1726
|
+
* @returns The JSON representation of `MapNode`.
|
|
1727
|
+
*/
|
|
1220
1728
|
toJSON() {
|
|
1221
1729
|
return {
|
|
1222
1730
|
kind: "MapNode" /* MapNode */,
|
|
@@ -1224,9 +1732,10 @@ var MapNode = class extends ASTNode {
|
|
|
1224
1732
|
};
|
|
1225
1733
|
}
|
|
1226
1734
|
/**
|
|
1227
|
-
*
|
|
1228
|
-
* @param key
|
|
1229
|
-
* @param
|
|
1735
|
+
* Set a node in the map.
|
|
1736
|
+
* @param key The key of the node.
|
|
1737
|
+
* @param nextJSON The JSON representation of the node.
|
|
1738
|
+
* @returns The node instance.
|
|
1230
1739
|
*/
|
|
1231
1740
|
set(key, nextJSON) {
|
|
1232
1741
|
return this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
@@ -1237,8 +1746,8 @@ var MapNode = class extends ASTNode {
|
|
|
1237
1746
|
});
|
|
1238
1747
|
}
|
|
1239
1748
|
/**
|
|
1240
|
-
*
|
|
1241
|
-
* @param key
|
|
1749
|
+
* Remove a node from the map.
|
|
1750
|
+
* @param key The key of the node.
|
|
1242
1751
|
*/
|
|
1243
1752
|
remove(key) {
|
|
1244
1753
|
this.get(key)?.dispose();
|
|
@@ -1246,9 +1755,9 @@ var MapNode = class extends ASTNode {
|
|
|
1246
1755
|
this.fireChange();
|
|
1247
1756
|
}
|
|
1248
1757
|
/**
|
|
1249
|
-
*
|
|
1250
|
-
* @param key
|
|
1251
|
-
* @returns
|
|
1758
|
+
* Get a node from the map.
|
|
1759
|
+
* @param key The key of the node.
|
|
1760
|
+
* @returns The node instance if found, otherwise `undefined`.
|
|
1252
1761
|
*/
|
|
1253
1762
|
get(key) {
|
|
1254
1763
|
return this.map.get(key);
|
|
@@ -1259,9 +1768,12 @@ MapNode.kind = "MapNode" /* MapNode */;
|
|
|
1259
1768
|
// src/ast/ast-registers.ts
|
|
1260
1769
|
var ASTRegisters = class {
|
|
1261
1770
|
/**
|
|
1262
|
-
*
|
|
1771
|
+
* Core AST node registration.
|
|
1263
1772
|
*/
|
|
1264
1773
|
constructor() {
|
|
1774
|
+
/**
|
|
1775
|
+
* @deprecated Please use `@injectToAst(XXXService) declare xxxService: XXXService` to achieve external dependency injection.
|
|
1776
|
+
*/
|
|
1265
1777
|
this.injectors = /* @__PURE__ */ new Map();
|
|
1266
1778
|
this.astMap = /* @__PURE__ */ new Map();
|
|
1267
1779
|
this.registerAST(StringType);
|
|
@@ -1271,18 +1783,19 @@ var ASTRegisters = class {
|
|
|
1271
1783
|
this.registerAST(ObjectType);
|
|
1272
1784
|
this.registerAST(ArrayType);
|
|
1273
1785
|
this.registerAST(MapType);
|
|
1786
|
+
this.registerAST(CustomType);
|
|
1274
1787
|
this.registerAST(Property);
|
|
1275
1788
|
this.registerAST(VariableDeclaration);
|
|
1276
1789
|
this.registerAST(VariableDeclarationList);
|
|
1277
1790
|
this.registerAST(KeyPathExpression);
|
|
1278
1791
|
this.registerAST(EnumerateExpression);
|
|
1279
|
-
this.registerAST(
|
|
1792
|
+
this.registerAST(WrapArrayExpression);
|
|
1280
1793
|
this.registerAST(MapNode);
|
|
1281
1794
|
this.registerAST(DataNode);
|
|
1282
1795
|
}
|
|
1283
1796
|
/**
|
|
1284
|
-
*
|
|
1285
|
-
* @param param
|
|
1797
|
+
* Creates an AST node.
|
|
1798
|
+
* @param param Creation parameters.
|
|
1286
1799
|
* @returns
|
|
1287
1800
|
*/
|
|
1288
1801
|
createAST(json, { parent, scope }) {
|
|
@@ -1302,6 +1815,7 @@ var ASTRegisters = class {
|
|
|
1302
1815
|
node.changeLocked = true;
|
|
1303
1816
|
node.fromJSON(omit(json, ["key", "kind"]));
|
|
1304
1817
|
node.changeLocked = false;
|
|
1818
|
+
node.dispatchGlobalEvent({ type: "NewAST" });
|
|
1305
1819
|
if (Reflect.hasMetadata(POST_CONSTRUCT_AST_SYMBOL, node)) {
|
|
1306
1820
|
const postConstructKey = Reflect.getMetadata(POST_CONSTRUCT_AST_SYMBOL, node);
|
|
1307
1821
|
node[postConstructKey]?.();
|
|
@@ -1309,7 +1823,7 @@ var ASTRegisters = class {
|
|
|
1309
1823
|
return node;
|
|
1310
1824
|
}
|
|
1311
1825
|
/**
|
|
1312
|
-
*
|
|
1826
|
+
* Gets the node Registry by AST node type.
|
|
1313
1827
|
* @param kind
|
|
1314
1828
|
* @returns
|
|
1315
1829
|
*/
|
|
@@ -1317,9 +1831,8 @@ var ASTRegisters = class {
|
|
|
1317
1831
|
return this.astMap.get(kind);
|
|
1318
1832
|
}
|
|
1319
1833
|
/**
|
|
1320
|
-
*
|
|
1834
|
+
* Registers an AST node.
|
|
1321
1835
|
* @param ASTNode
|
|
1322
|
-
* @param injector
|
|
1323
1836
|
*/
|
|
1324
1837
|
registerAST(ASTNode2, injector) {
|
|
1325
1838
|
this.astMap.set(ASTNode2.kind, ASTNode2);
|
|
@@ -1335,7 +1848,10 @@ ASTRegisters = __decorateClass([
|
|
|
1335
1848
|
// src/ast/factory.ts
|
|
1336
1849
|
var ASTFactory;
|
|
1337
1850
|
((ASTFactory2) => {
|
|
1338
|
-
ASTFactory2.createString = () => ({
|
|
1851
|
+
ASTFactory2.createString = (json) => ({
|
|
1852
|
+
kind: "String" /* String */,
|
|
1853
|
+
...json || {}
|
|
1854
|
+
});
|
|
1339
1855
|
ASTFactory2.createNumber = () => ({ kind: "Number" /* Number */ });
|
|
1340
1856
|
ASTFactory2.createBoolean = () => ({ kind: "Boolean" /* Boolean */ });
|
|
1341
1857
|
ASTFactory2.createInteger = () => ({ kind: "Integer" /* Integer */ });
|
|
@@ -1355,6 +1871,10 @@ var ASTFactory;
|
|
|
1355
1871
|
kind: "Union" /* Union */,
|
|
1356
1872
|
...json
|
|
1357
1873
|
});
|
|
1874
|
+
ASTFactory2.createCustomType = (json) => ({
|
|
1875
|
+
kind: "CustomType" /* CustomType */,
|
|
1876
|
+
...json
|
|
1877
|
+
});
|
|
1358
1878
|
ASTFactory2.createVariableDeclaration = (json) => ({
|
|
1359
1879
|
kind: "VariableDeclaration" /* VariableDeclaration */,
|
|
1360
1880
|
...json
|
|
@@ -1375,115 +1895,13 @@ var ASTFactory;
|
|
|
1375
1895
|
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
1376
1896
|
...json
|
|
1377
1897
|
});
|
|
1898
|
+
ASTFactory2.createWrapArrayExpression = (json) => ({
|
|
1899
|
+
kind: "WrapArrayExpression" /* WrapArrayExpression */,
|
|
1900
|
+
...json
|
|
1901
|
+
});
|
|
1902
|
+
ASTFactory2.create = (targetType, json) => ({ kind: targetType.kind, ...json });
|
|
1378
1903
|
})(ASTFactory || (ASTFactory = {}));
|
|
1379
1904
|
|
|
1380
|
-
// src/scope/variable-table.ts
|
|
1381
|
-
import { Subject as Subject2, merge, share as share2, skip as skip2, switchMap as switchMap2 } from "rxjs";
|
|
1382
|
-
import { Emitter } from "@flowgram.ai/utils";
|
|
1383
|
-
import { DisposableCollection as DisposableCollection3 } from "@flowgram.ai/utils";
|
|
1384
|
-
var VariableTable = class {
|
|
1385
|
-
constructor(parentTable) {
|
|
1386
|
-
this.parentTable = parentTable;
|
|
1387
|
-
this.table = /* @__PURE__ */ new Map();
|
|
1388
|
-
this.onDataChangeEmitter = new Emitter();
|
|
1389
|
-
this.variables$ = new Subject2();
|
|
1390
|
-
// 监听变量列表中的单个变量变化
|
|
1391
|
-
this.anyVariableChange$ = this.variables$.pipe(
|
|
1392
|
-
switchMap2(
|
|
1393
|
-
(_variables) => merge(
|
|
1394
|
-
..._variables.map(
|
|
1395
|
-
(_v) => _v.value$.pipe(
|
|
1396
|
-
// 跳过 BehaviorSubject 第一个
|
|
1397
|
-
skip2(1)
|
|
1398
|
-
)
|
|
1399
|
-
)
|
|
1400
|
-
)
|
|
1401
|
-
),
|
|
1402
|
-
share2()
|
|
1403
|
-
);
|
|
1404
|
-
this.onDataChange = this.onDataChangeEmitter.event;
|
|
1405
|
-
this._version = 0;
|
|
1406
|
-
}
|
|
1407
|
-
/**
|
|
1408
|
-
* 监听任意变量变化
|
|
1409
|
-
* @param observer 监听器,变量变化时会吐出值
|
|
1410
|
-
* @returns
|
|
1411
|
-
*/
|
|
1412
|
-
onAnyVariableChange(observer) {
|
|
1413
|
-
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1414
|
-
}
|
|
1415
|
-
/**
|
|
1416
|
-
* 列表或者任意变量变化
|
|
1417
|
-
* @param observer
|
|
1418
|
-
*/
|
|
1419
|
-
onAnyChange(observer) {
|
|
1420
|
-
const disposables = new DisposableCollection3();
|
|
1421
|
-
disposables.pushAll([this.onDataChange(observer), this.onAnyVariableChange(observer)]);
|
|
1422
|
-
return disposables;
|
|
1423
|
-
}
|
|
1424
|
-
fireChange() {
|
|
1425
|
-
this._version++;
|
|
1426
|
-
this.onDataChangeEmitter.fire();
|
|
1427
|
-
this.parentTable?.fireChange();
|
|
1428
|
-
}
|
|
1429
|
-
get version() {
|
|
1430
|
-
return this._version;
|
|
1431
|
-
}
|
|
1432
|
-
get variables() {
|
|
1433
|
-
return Array.from(this.table.values());
|
|
1434
|
-
}
|
|
1435
|
-
get variableKeys() {
|
|
1436
|
-
return Array.from(this.table.keys());
|
|
1437
|
-
}
|
|
1438
|
-
/**
|
|
1439
|
-
* 根据 keyPath 找到对应的变量,或 Property 节点
|
|
1440
|
-
* @param keyPath
|
|
1441
|
-
* @returns
|
|
1442
|
-
*/
|
|
1443
|
-
getByKeyPath(keyPath) {
|
|
1444
|
-
const [variableKey, ...propertyKeys] = keyPath || [];
|
|
1445
|
-
if (!variableKey) {
|
|
1446
|
-
return;
|
|
1447
|
-
}
|
|
1448
|
-
const variable = this.getVariableByKey(variableKey);
|
|
1449
|
-
return propertyKeys.length ? variable?.getByKeyPath(propertyKeys) : variable;
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* 根据 key 值找到相应的变量
|
|
1453
|
-
* @param key
|
|
1454
|
-
* @returns
|
|
1455
|
-
*/
|
|
1456
|
-
getVariableByKey(key) {
|
|
1457
|
-
return this.table.get(key);
|
|
1458
|
-
}
|
|
1459
|
-
/**
|
|
1460
|
-
* 往 variableTable 添加输出变量
|
|
1461
|
-
* @param variable
|
|
1462
|
-
*/
|
|
1463
|
-
addVariableToTable(variable) {
|
|
1464
|
-
this.table.set(variable.key, variable);
|
|
1465
|
-
if (this.parentTable) {
|
|
1466
|
-
this.parentTable.addVariableToTable(variable);
|
|
1467
|
-
}
|
|
1468
|
-
this.variables$.next(this.variables);
|
|
1469
|
-
}
|
|
1470
|
-
/**
|
|
1471
|
-
* 从 variableTable 中移除变量
|
|
1472
|
-
* @param key
|
|
1473
|
-
*/
|
|
1474
|
-
removeVariableFromTable(key) {
|
|
1475
|
-
this.table.delete(key);
|
|
1476
|
-
if (this.parentTable) {
|
|
1477
|
-
this.parentTable.removeVariableFromTable(key);
|
|
1478
|
-
}
|
|
1479
|
-
this.variables$.next(this.variables);
|
|
1480
|
-
}
|
|
1481
|
-
dispose() {
|
|
1482
|
-
this.variableKeys.forEach((_key) => this.parentTable?.removeVariableFromTable(_key));
|
|
1483
|
-
this.onDataChangeEmitter.dispose();
|
|
1484
|
-
}
|
|
1485
|
-
};
|
|
1486
|
-
|
|
1487
1905
|
// src/scope/datas/scope-output-data.ts
|
|
1488
1906
|
var ScopeOutputData = class {
|
|
1489
1907
|
constructor(scope) {
|
|
@@ -1492,7 +1910,7 @@ var ScopeOutputData = class {
|
|
|
1492
1910
|
this._hasChanges = false;
|
|
1493
1911
|
this.variableTable = new VariableTable(scope.variableEngine.globalVariableTable);
|
|
1494
1912
|
this.scope.toDispose.pushAll([
|
|
1495
|
-
//
|
|
1913
|
+
// When the root AST node is updated, check if there are any changes.
|
|
1496
1914
|
this.scope.ast.subscribe(() => {
|
|
1497
1915
|
if (this._hasChanges) {
|
|
1498
1916
|
this.memo.clear();
|
|
@@ -1501,23 +1919,66 @@ var ScopeOutputData = class {
|
|
|
1501
1919
|
this._hasChanges = false;
|
|
1502
1920
|
}
|
|
1503
1921
|
}),
|
|
1922
|
+
this.scope.event.on("DisposeAST", (_action) => {
|
|
1923
|
+
if (_action.ast?.kind === "VariableDeclaration" /* VariableDeclaration */) {
|
|
1924
|
+
this.removeVariableFromTable(_action.ast.key);
|
|
1925
|
+
}
|
|
1926
|
+
}),
|
|
1927
|
+
this.scope.event.on("NewAST", (_action) => {
|
|
1928
|
+
if (_action.ast?.kind === "VariableDeclaration" /* VariableDeclaration */) {
|
|
1929
|
+
this.addVariableToTable(_action.ast);
|
|
1930
|
+
}
|
|
1931
|
+
}),
|
|
1932
|
+
this.scope.event.on("ReSortVariableDeclarations", () => {
|
|
1933
|
+
this._hasChanges = true;
|
|
1934
|
+
}),
|
|
1504
1935
|
this.variableTable
|
|
1505
1936
|
]);
|
|
1506
1937
|
}
|
|
1938
|
+
/**
|
|
1939
|
+
* The variable engine instance.
|
|
1940
|
+
*/
|
|
1507
1941
|
get variableEngine() {
|
|
1508
1942
|
return this.scope.variableEngine;
|
|
1509
1943
|
}
|
|
1944
|
+
/**
|
|
1945
|
+
* The global variable table from the variable engine.
|
|
1946
|
+
*/
|
|
1510
1947
|
get globalVariableTable() {
|
|
1511
1948
|
return this.scope.variableEngine.globalVariableTable;
|
|
1512
1949
|
}
|
|
1950
|
+
/**
|
|
1951
|
+
* The current version of the output data, which increments on each change.
|
|
1952
|
+
*/
|
|
1953
|
+
get version() {
|
|
1954
|
+
return this.variableTable.version;
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
* @deprecated use onListOrAnyVarChange instead
|
|
1958
|
+
*/
|
|
1513
1959
|
get onDataChange() {
|
|
1514
1960
|
return this.variableTable.onDataChange.bind(this.variableTable);
|
|
1515
1961
|
}
|
|
1962
|
+
/**
|
|
1963
|
+
* An event that fires when the list of output variables changes.
|
|
1964
|
+
*/
|
|
1965
|
+
get onVariableListChange() {
|
|
1966
|
+
return this.variableTable.onVariableListChange.bind(this.variableTable);
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* An event that fires when any output variable's value changes.
|
|
1970
|
+
*/
|
|
1516
1971
|
get onAnyVariableChange() {
|
|
1517
1972
|
return this.variableTable.onAnyVariableChange.bind(this.variableTable);
|
|
1518
1973
|
}
|
|
1519
1974
|
/**
|
|
1520
|
-
*
|
|
1975
|
+
* An event that fires when the output variable list changes or any variable's value is updated.
|
|
1976
|
+
*/
|
|
1977
|
+
get onListOrAnyVarChange() {
|
|
1978
|
+
return this.variableTable.onListOrAnyVarChange.bind(this.variableTable);
|
|
1979
|
+
}
|
|
1980
|
+
/**
|
|
1981
|
+
* The output variable declarations of the scope, sorted by order.
|
|
1521
1982
|
*/
|
|
1522
1983
|
get variables() {
|
|
1523
1984
|
return this.memo(
|
|
@@ -1526,7 +1987,7 @@ var ScopeOutputData = class {
|
|
|
1526
1987
|
);
|
|
1527
1988
|
}
|
|
1528
1989
|
/**
|
|
1529
|
-
*
|
|
1990
|
+
* The keys of the output variables.
|
|
1530
1991
|
*/
|
|
1531
1992
|
get variableKeys() {
|
|
1532
1993
|
return this.memo("variableKeys", () => this.variableTable.variableKeys);
|
|
@@ -1538,18 +1999,21 @@ var ScopeOutputData = class {
|
|
|
1538
1999
|
this.variableTable.addVariableToTable(variable);
|
|
1539
2000
|
this._hasChanges = true;
|
|
1540
2001
|
}
|
|
1541
|
-
// 标记为发生了变化,用于变量排序变化的场景
|
|
1542
|
-
setHasChanges() {
|
|
1543
|
-
this._hasChanges = true;
|
|
1544
|
-
}
|
|
1545
2002
|
removeVariableFromTable(key) {
|
|
1546
2003
|
this.variableTable.removeVariableFromTable(key);
|
|
1547
2004
|
this._hasChanges = true;
|
|
1548
2005
|
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Retrieves a variable declaration by its key.
|
|
2008
|
+
* @param key The key of the variable.
|
|
2009
|
+
* @returns The `VariableDeclaration` or `undefined` if not found.
|
|
2010
|
+
*/
|
|
1549
2011
|
getVariableByKey(key) {
|
|
1550
2012
|
return this.variableTable.getVariableByKey(key);
|
|
1551
2013
|
}
|
|
1552
|
-
|
|
2014
|
+
/**
|
|
2015
|
+
* Notifies the covering scopes that the available variables have changed.
|
|
2016
|
+
*/
|
|
1553
2017
|
notifyCoversChange() {
|
|
1554
2018
|
this.scope.coverScopes.forEach((scope) => scope.available.refresh());
|
|
1555
2019
|
}
|
|
@@ -1558,40 +2022,47 @@ var ScopeOutputData = class {
|
|
|
1558
2022
|
// src/scope/datas/scope-available-data.ts
|
|
1559
2023
|
import {
|
|
1560
2024
|
Subject as Subject3,
|
|
1561
|
-
|
|
2025
|
+
animationFrameScheduler as animationFrameScheduler2,
|
|
2026
|
+
debounceTime as debounceTime2,
|
|
2027
|
+
distinctUntilChanged as distinctUntilChanged4,
|
|
1562
2028
|
map as map3,
|
|
1563
2029
|
merge as merge2,
|
|
1564
2030
|
share as share3,
|
|
1565
2031
|
skip as skip3,
|
|
1566
|
-
|
|
2032
|
+
startWith,
|
|
2033
|
+
switchMap as switchMap3,
|
|
2034
|
+
tap as tap2
|
|
1567
2035
|
} from "rxjs";
|
|
1568
|
-
import { flatten } from "lodash";
|
|
2036
|
+
import { flatten } from "lodash-es";
|
|
1569
2037
|
import { shallowEqual as shallowEqual7 } from "fast-equals";
|
|
1570
|
-
import { Disposable as
|
|
2038
|
+
import { Disposable as Disposable3 } from "@flowgram.ai/utils";
|
|
1571
2039
|
import { Emitter as Emitter2 } from "@flowgram.ai/utils";
|
|
1572
2040
|
var ScopeAvailableData = class {
|
|
1573
2041
|
constructor(scope) {
|
|
1574
2042
|
this.scope = scope;
|
|
1575
2043
|
this.memo = createMemo();
|
|
2044
|
+
this._version = 0;
|
|
1576
2045
|
this.refresh$ = new Subject3();
|
|
1577
2046
|
this._variables = [];
|
|
1578
2047
|
/**
|
|
1579
|
-
*
|
|
2048
|
+
* An observable that emits when the list of available variables changes.
|
|
1580
2049
|
*/
|
|
1581
2050
|
this.variables$ = this.refresh$.pipe(
|
|
1582
|
-
//
|
|
2051
|
+
// Map to the flattened list of variables from all dependency scopes.
|
|
1583
2052
|
map3(() => flatten(this.depScopes.map((scope) => scope.output.variables || []))),
|
|
1584
|
-
//
|
|
1585
|
-
|
|
2053
|
+
// Use shallow equality to check if the variable list has changed.
|
|
2054
|
+
distinctUntilChanged4(shallowEqual7),
|
|
1586
2055
|
share3()
|
|
1587
2056
|
);
|
|
1588
|
-
|
|
2057
|
+
/**
|
|
2058
|
+
* An observable that emits when any variable in the available list changes its value.
|
|
2059
|
+
*/
|
|
1589
2060
|
this.anyVariableChange$ = this.variables$.pipe(
|
|
1590
2061
|
switchMap3(
|
|
1591
2062
|
(_variables) => merge2(
|
|
1592
2063
|
..._variables.map(
|
|
1593
2064
|
(_v) => _v.value$.pipe(
|
|
1594
|
-
//
|
|
2065
|
+
// Skip the initial value of the BehaviorSubject.
|
|
1595
2066
|
skip3(1)
|
|
1596
2067
|
)
|
|
1597
2068
|
)
|
|
@@ -1599,30 +2070,60 @@ var ScopeAvailableData = class {
|
|
|
1599
2070
|
),
|
|
1600
2071
|
share3()
|
|
1601
2072
|
);
|
|
2073
|
+
/**
|
|
2074
|
+
* @deprecated
|
|
2075
|
+
*/
|
|
1602
2076
|
this.onDataChangeEmitter = new Emitter2();
|
|
2077
|
+
this.onListOrAnyVarChangeEmitter = new Emitter2();
|
|
1603
2078
|
/**
|
|
1604
|
-
*
|
|
2079
|
+
* @deprecated use available.onListOrAnyVarChange instead
|
|
1605
2080
|
*/
|
|
1606
2081
|
this.onDataChange = this.onDataChangeEmitter.event;
|
|
2082
|
+
/**
|
|
2083
|
+
* An event that fires when the variable list changes or any variable's value is updated.
|
|
2084
|
+
*/
|
|
2085
|
+
this.onListOrAnyVarChange = this.onListOrAnyVarChangeEmitter.event;
|
|
1607
2086
|
this.scope.toDispose.pushAll([
|
|
1608
2087
|
this.onVariableListChange((_variables) => {
|
|
1609
2088
|
this._variables = _variables;
|
|
1610
2089
|
this.memo.clear();
|
|
1611
2090
|
this.onDataChangeEmitter.fire(this._variables);
|
|
2091
|
+
this.bumpVersion();
|
|
2092
|
+
this.onListOrAnyVarChangeEmitter.fire(this._variables);
|
|
1612
2093
|
}),
|
|
1613
2094
|
this.onAnyVariableChange(() => {
|
|
1614
2095
|
this.onDataChangeEmitter.fire(this._variables);
|
|
2096
|
+
this.bumpVersion();
|
|
2097
|
+
this.onListOrAnyVarChangeEmitter.fire(this._variables);
|
|
1615
2098
|
}),
|
|
1616
|
-
|
|
2099
|
+
Disposable3.create(() => {
|
|
1617
2100
|
this.refresh$.complete();
|
|
1618
2101
|
this.refresh$.unsubscribe();
|
|
1619
2102
|
})
|
|
1620
2103
|
]);
|
|
1621
2104
|
}
|
|
2105
|
+
/**
|
|
2106
|
+
* The global variable table from the variable engine.
|
|
2107
|
+
*/
|
|
1622
2108
|
get globalVariableTable() {
|
|
1623
2109
|
return this.scope.variableEngine.globalVariableTable;
|
|
1624
2110
|
}
|
|
1625
|
-
|
|
2111
|
+
/**
|
|
2112
|
+
* The current version of the available data, which increments on each change.
|
|
2113
|
+
*/
|
|
2114
|
+
get version() {
|
|
2115
|
+
return this._version;
|
|
2116
|
+
}
|
|
2117
|
+
bumpVersion() {
|
|
2118
|
+
this._version = this._version + 1;
|
|
2119
|
+
if (this._version === Number.MAX_SAFE_INTEGER) {
|
|
2120
|
+
this._version = 0;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
/**
|
|
2124
|
+
* Refreshes the list of available variables.
|
|
2125
|
+
* This should be called when the dependencies of the scope change.
|
|
2126
|
+
*/
|
|
1626
2127
|
refresh() {
|
|
1627
2128
|
if (this.scope.disposed) {
|
|
1628
2129
|
return;
|
|
@@ -1630,43 +2131,43 @@ var ScopeAvailableData = class {
|
|
|
1630
2131
|
this.refresh$.next();
|
|
1631
2132
|
}
|
|
1632
2133
|
/**
|
|
1633
|
-
*
|
|
1634
|
-
* @param observer
|
|
1635
|
-
* @returns
|
|
2134
|
+
* Subscribes to changes in any variable's value in the available list.
|
|
2135
|
+
* @param observer A function to be called with the changed variable.
|
|
2136
|
+
* @returns A disposable to unsubscribe from the changes.
|
|
1636
2137
|
*/
|
|
1637
2138
|
onAnyVariableChange(observer) {
|
|
1638
2139
|
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1639
2140
|
}
|
|
1640
2141
|
/**
|
|
1641
|
-
*
|
|
1642
|
-
* @param observer
|
|
1643
|
-
* @returns
|
|
2142
|
+
* Subscribes to changes in the list of available variables.
|
|
2143
|
+
* @param observer A function to be called with the new list of variables.
|
|
2144
|
+
* @returns A disposable to unsubscribe from the changes.
|
|
1644
2145
|
*/
|
|
1645
2146
|
onVariableListChange(observer) {
|
|
1646
2147
|
return subsToDisposable(this.variables$.subscribe(observer));
|
|
1647
2148
|
}
|
|
1648
2149
|
/**
|
|
1649
|
-
*
|
|
2150
|
+
* Gets the list of available variables.
|
|
1650
2151
|
*/
|
|
1651
2152
|
get variables() {
|
|
1652
2153
|
return this._variables;
|
|
1653
2154
|
}
|
|
1654
2155
|
/**
|
|
1655
|
-
*
|
|
2156
|
+
* Gets the keys of the available variables.
|
|
1656
2157
|
*/
|
|
1657
2158
|
get variableKeys() {
|
|
1658
2159
|
return this.memo("availableKeys", () => this._variables.map((_v) => _v.key));
|
|
1659
2160
|
}
|
|
1660
2161
|
/**
|
|
1661
|
-
*
|
|
2162
|
+
* Gets the dependency scopes.
|
|
1662
2163
|
*/
|
|
1663
2164
|
get depScopes() {
|
|
1664
2165
|
return this.scope.depScopes;
|
|
1665
2166
|
}
|
|
1666
2167
|
/**
|
|
1667
|
-
*
|
|
1668
|
-
* @param keyPath
|
|
1669
|
-
* @returns
|
|
2168
|
+
* Retrieves a variable field by its key path from the available variables.
|
|
2169
|
+
* @param keyPath The key path to the variable field.
|
|
2170
|
+
* @returns The found `BaseVariableField` or `undefined`.
|
|
1670
2171
|
*/
|
|
1671
2172
|
getByKeyPath(keyPath = []) {
|
|
1672
2173
|
if (!this.variableKeys.includes(keyPath[0])) {
|
|
@@ -1674,6 +2175,37 @@ var ScopeAvailableData = class {
|
|
|
1674
2175
|
}
|
|
1675
2176
|
return this.globalVariableTable.getByKeyPath(keyPath);
|
|
1676
2177
|
}
|
|
2178
|
+
/**
|
|
2179
|
+
* Tracks changes to a variable field by its key path.
|
|
2180
|
+
* This includes changes to its type, value, or any nested properties.
|
|
2181
|
+
* @param keyPath The key path to the variable field to track.
|
|
2182
|
+
* @param cb The callback to execute when the variable changes.
|
|
2183
|
+
* @param opts Configuration options for the subscription.
|
|
2184
|
+
* @returns A disposable to unsubscribe from the tracking.
|
|
2185
|
+
*/
|
|
2186
|
+
trackByKeyPath(keyPath = [], cb, opts) {
|
|
2187
|
+
const { triggerOnInit = true, debounceAnimation, selector } = opts || {};
|
|
2188
|
+
return subsToDisposable(
|
|
2189
|
+
merge2(this.anyVariableChange$, this.variables$).pipe(
|
|
2190
|
+
triggerOnInit ? startWith() : tap2(() => null),
|
|
2191
|
+
map3(() => {
|
|
2192
|
+
const v = this.getByKeyPath(keyPath);
|
|
2193
|
+
return selector ? selector(v) : v;
|
|
2194
|
+
}),
|
|
2195
|
+
distinctUntilChanged4(
|
|
2196
|
+
(a, b) => shallowEqual7(a, b),
|
|
2197
|
+
(value) => {
|
|
2198
|
+
if (value instanceof ASTNode) {
|
|
2199
|
+
return value.hash;
|
|
2200
|
+
}
|
|
2201
|
+
return value;
|
|
2202
|
+
}
|
|
2203
|
+
),
|
|
2204
|
+
// Debounce updates to a single emission per animation frame.
|
|
2205
|
+
debounceAnimation ? debounceTime2(0, animationFrameScheduler2) : tap2(() => null)
|
|
2206
|
+
).subscribe(cb)
|
|
2207
|
+
);
|
|
2208
|
+
}
|
|
1677
2209
|
};
|
|
1678
2210
|
|
|
1679
2211
|
// src/scope/datas/scope-event-data.ts
|
|
@@ -1688,15 +2220,30 @@ var ScopeEventData = class {
|
|
|
1688
2220
|
})
|
|
1689
2221
|
]);
|
|
1690
2222
|
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Dispatches a global event.
|
|
2225
|
+
* @param action The event action to dispatch.
|
|
2226
|
+
*/
|
|
1691
2227
|
dispatch(action) {
|
|
1692
2228
|
if (this.scope.disposed) {
|
|
1693
2229
|
return;
|
|
1694
2230
|
}
|
|
1695
2231
|
this.event$.next(action);
|
|
1696
2232
|
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Subscribes to all global events.
|
|
2235
|
+
* @param observer The observer function to call with the event action.
|
|
2236
|
+
* @returns A disposable to unsubscribe from the events.
|
|
2237
|
+
*/
|
|
1697
2238
|
subscribe(observer) {
|
|
1698
2239
|
return subsToDisposable(this.event$.subscribe(observer));
|
|
1699
2240
|
}
|
|
2241
|
+
/**
|
|
2242
|
+
* Subscribes to a specific type of global event.
|
|
2243
|
+
* @param type The type of the event to subscribe to.
|
|
2244
|
+
* @param observer The observer function to call with the event action.
|
|
2245
|
+
* @returns A disposable to unsubscribe from the event.
|
|
2246
|
+
*/
|
|
1700
2247
|
on(type, observer) {
|
|
1701
2248
|
return subsToDisposable(
|
|
1702
2249
|
this.event$.pipe(filter((_action) => _action.type === type)).subscribe(observer)
|
|
@@ -1708,7 +2255,7 @@ var ScopeEventData = class {
|
|
|
1708
2255
|
var Scope = class {
|
|
1709
2256
|
constructor(options) {
|
|
1710
2257
|
/**
|
|
1711
|
-
*
|
|
2258
|
+
* A memoization utility for caching computed values.
|
|
1712
2259
|
*/
|
|
1713
2260
|
this.memo = createMemo();
|
|
1714
2261
|
this.toDispose = new DisposableCollection4();
|
|
@@ -1720,7 +2267,7 @@ var Scope = class {
|
|
|
1720
2267
|
this.ast = this.variableEngine.astRegisters.createAST(
|
|
1721
2268
|
{
|
|
1722
2269
|
kind: "MapNode" /* MapNode */,
|
|
1723
|
-
key: this.id
|
|
2270
|
+
key: String(this.id)
|
|
1724
2271
|
},
|
|
1725
2272
|
{
|
|
1726
2273
|
scope: this
|
|
@@ -1729,25 +2276,41 @@ var Scope = class {
|
|
|
1729
2276
|
this.output = new ScopeOutputData(this);
|
|
1730
2277
|
this.available = new ScopeAvailableData(this);
|
|
1731
2278
|
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Refreshes the covering scopes.
|
|
2281
|
+
*/
|
|
1732
2282
|
refreshCovers() {
|
|
1733
2283
|
this.memo.clear("covers");
|
|
1734
2284
|
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Refreshes the dependency scopes and the available variables.
|
|
2287
|
+
*/
|
|
1735
2288
|
refreshDeps() {
|
|
1736
2289
|
this.memo.clear("deps");
|
|
1737
2290
|
this.available.refresh();
|
|
1738
2291
|
}
|
|
2292
|
+
/**
|
|
2293
|
+
* Gets the scopes that this scope depends on.
|
|
2294
|
+
*/
|
|
1739
2295
|
get depScopes() {
|
|
1740
2296
|
return this.memo(
|
|
1741
2297
|
"deps",
|
|
1742
2298
|
() => this.variableEngine.chain.getDeps(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1743
2299
|
);
|
|
1744
2300
|
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Gets the scopes that are covered by this scope.
|
|
2303
|
+
*/
|
|
1745
2304
|
get coverScopes() {
|
|
1746
2305
|
return this.memo(
|
|
1747
2306
|
"covers",
|
|
1748
2307
|
() => this.variableEngine.chain.getCovers(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1749
2308
|
);
|
|
1750
2309
|
}
|
|
2310
|
+
/**
|
|
2311
|
+
* Disposes of the scope and its resources.
|
|
2312
|
+
* This will also trigger updates in dependent and covering scopes.
|
|
2313
|
+
*/
|
|
1751
2314
|
dispose() {
|
|
1752
2315
|
this.ast.dispose();
|
|
1753
2316
|
this.toDispose.dispose();
|
|
@@ -1757,6 +2320,32 @@ var Scope = class {
|
|
|
1757
2320
|
get disposed() {
|
|
1758
2321
|
return this.toDispose.disposed;
|
|
1759
2322
|
}
|
|
2323
|
+
setVar(arg1, arg2) {
|
|
2324
|
+
if (typeof arg1 === "string" && arg2 !== void 0) {
|
|
2325
|
+
return this.ast.set(arg1, arg2);
|
|
2326
|
+
}
|
|
2327
|
+
if (typeof arg1 === "object" && arg2 === void 0) {
|
|
2328
|
+
return this.ast.set("outputs", arg1);
|
|
2329
|
+
}
|
|
2330
|
+
throw new Error("Invalid arguments");
|
|
2331
|
+
}
|
|
2332
|
+
/**
|
|
2333
|
+
* Retrieves a variable from the scope by its key.
|
|
2334
|
+
*
|
|
2335
|
+
* @param key The key of the variable to retrieve. Defaults to 'outputs'.
|
|
2336
|
+
* @returns The AST node for the variable, or `undefined` if not found.
|
|
2337
|
+
*/
|
|
2338
|
+
getVar(key = "outputs") {
|
|
2339
|
+
return this.ast.get(key);
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Clears a variable from the scope by its key.
|
|
2343
|
+
*
|
|
2344
|
+
* @param key The key of the variable to clear. Defaults to 'outputs'.
|
|
2345
|
+
*/
|
|
2346
|
+
clearVar(key = "outputs") {
|
|
2347
|
+
return this.ast.remove(key);
|
|
2348
|
+
}
|
|
1760
2349
|
};
|
|
1761
2350
|
|
|
1762
2351
|
// src/variable-engine.ts
|
|
@@ -1767,44 +2356,71 @@ var VariableEngine = class {
|
|
|
1767
2356
|
this.toDispose = new DisposableCollection5();
|
|
1768
2357
|
this.memo = createMemo();
|
|
1769
2358
|
this.scopeMap = /* @__PURE__ */ new Map();
|
|
2359
|
+
/**
|
|
2360
|
+
* A rxjs subject that emits global events occurring within the variable engine.
|
|
2361
|
+
*/
|
|
1770
2362
|
this.globalEvent$ = new Subject5();
|
|
1771
2363
|
this.onScopeChangeEmitter = new Emitter3();
|
|
2364
|
+
/**
|
|
2365
|
+
* A table containing all global variables.
|
|
2366
|
+
*/
|
|
1772
2367
|
this.globalVariableTable = new VariableTable();
|
|
2368
|
+
/**
|
|
2369
|
+
* An event that fires whenever a scope is added, updated, or deleted.
|
|
2370
|
+
*/
|
|
1773
2371
|
this.onScopeChange = this.onScopeChangeEmitter.event;
|
|
1774
2372
|
this.toDispose.pushAll([
|
|
1775
2373
|
chain,
|
|
1776
|
-
|
|
2374
|
+
Disposable4.create(() => {
|
|
1777
2375
|
this.getAllScopes().forEach((scope) => scope.dispose());
|
|
1778
2376
|
this.globalVariableTable.dispose();
|
|
1779
2377
|
})
|
|
1780
2378
|
]);
|
|
1781
2379
|
}
|
|
2380
|
+
/**
|
|
2381
|
+
* The Inversify container instance.
|
|
2382
|
+
*/
|
|
1782
2383
|
get container() {
|
|
1783
2384
|
return this.containerProvider();
|
|
1784
2385
|
}
|
|
1785
2386
|
dispose() {
|
|
1786
2387
|
this.toDispose.dispose();
|
|
1787
2388
|
}
|
|
1788
|
-
|
|
2389
|
+
/**
|
|
2390
|
+
* Retrieves a scope by its unique identifier.
|
|
2391
|
+
* @param scopeId The ID of the scope to retrieve.
|
|
2392
|
+
* @returns The scope if found, otherwise undefined.
|
|
2393
|
+
*/
|
|
1789
2394
|
getScopeById(scopeId) {
|
|
1790
2395
|
return this.scopeMap.get(scopeId);
|
|
1791
2396
|
}
|
|
1792
|
-
|
|
2397
|
+
/**
|
|
2398
|
+
* Removes a scope by its unique identifier and disposes of it.
|
|
2399
|
+
* @param scopeId The ID of the scope to remove.
|
|
2400
|
+
*/
|
|
1793
2401
|
removeScopeById(scopeId) {
|
|
1794
2402
|
this.getScopeById(scopeId)?.dispose();
|
|
1795
2403
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
2404
|
+
/**
|
|
2405
|
+
* Creates a new scope or retrieves an existing one if the ID and type match.
|
|
2406
|
+
* @param id The unique identifier for the scope.
|
|
2407
|
+
* @param meta Optional metadata for the scope, defined by the user.
|
|
2408
|
+
* @param options Options for creating the scope.
|
|
2409
|
+
* @param options.ScopeConstructor The constructor to use for creating the scope. Defaults to `Scope`.
|
|
2410
|
+
* @returns The created or existing scope.
|
|
2411
|
+
*/
|
|
2412
|
+
createScope(id, meta, options = {}) {
|
|
2413
|
+
const { ScopeConstructor = Scope } = options;
|
|
1798
2414
|
let scope = this.getScopeById(id);
|
|
1799
2415
|
if (!scope) {
|
|
1800
|
-
scope = new
|
|
2416
|
+
scope = new ScopeConstructor({ variableEngine: this, meta, id });
|
|
1801
2417
|
this.scopeMap.set(id, scope);
|
|
1802
2418
|
this.onScopeChangeEmitter.fire({ type: "add", scope });
|
|
1803
2419
|
scope.toDispose.pushAll([
|
|
1804
2420
|
scope.ast.subscribe(() => {
|
|
1805
2421
|
this.onScopeChangeEmitter.fire({ type: "update", scope });
|
|
1806
2422
|
}),
|
|
1807
|
-
//
|
|
2423
|
+
// Fires when available variables change
|
|
1808
2424
|
scope.available.onDataChange(() => {
|
|
1809
2425
|
this.onScopeChangeEmitter.fire({ type: "available", scope });
|
|
1810
2426
|
})
|
|
@@ -1816,7 +2432,12 @@ var VariableEngine = class {
|
|
|
1816
2432
|
}
|
|
1817
2433
|
return scope;
|
|
1818
2434
|
}
|
|
1819
|
-
|
|
2435
|
+
/**
|
|
2436
|
+
* Retrieves all scopes currently managed by the engine.
|
|
2437
|
+
* @param options Options for retrieving the scopes.
|
|
2438
|
+
* @param options.sort Whether to sort the scopes based on their dependency chain.
|
|
2439
|
+
* @returns An array of all scopes.
|
|
2440
|
+
*/
|
|
1820
2441
|
getAllScopes({
|
|
1821
2442
|
sort
|
|
1822
2443
|
} = {}) {
|
|
@@ -1829,9 +2450,19 @@ var VariableEngine = class {
|
|
|
1829
2450
|
}
|
|
1830
2451
|
return [...allScopes];
|
|
1831
2452
|
}
|
|
2453
|
+
/**
|
|
2454
|
+
* Fires a global event to be broadcast to all listeners.
|
|
2455
|
+
* @param event The global event to fire.
|
|
2456
|
+
*/
|
|
1832
2457
|
fireGlobalEvent(event) {
|
|
1833
2458
|
this.globalEvent$.next(event);
|
|
1834
2459
|
}
|
|
2460
|
+
/**
|
|
2461
|
+
* Subscribes to a specific type of global event.
|
|
2462
|
+
* @param type The type of the event to listen for.
|
|
2463
|
+
* @param observer A function to be called when the event is observed.
|
|
2464
|
+
* @returns A disposable object to unsubscribe from the event.
|
|
2465
|
+
*/
|
|
1835
2466
|
onGlobalEvent(type, observer) {
|
|
1836
2467
|
return subsToDisposable(
|
|
1837
2468
|
this.globalEvent$.subscribe((_action) => {
|
|
@@ -1855,18 +2486,33 @@ VariableEngine = __decorateClass([
|
|
|
1855
2486
|
], VariableEngine);
|
|
1856
2487
|
|
|
1857
2488
|
// src/services/variable-field-key-rename-service.ts
|
|
1858
|
-
import { difference } from "lodash";
|
|
2489
|
+
import { difference } from "lodash-es";
|
|
1859
2490
|
import { inject as inject3, injectable as injectable4, postConstruct, preDestroy as preDestroy2 } from "inversify";
|
|
1860
2491
|
import { DisposableCollection as DisposableCollection6, Emitter as Emitter4 } from "@flowgram.ai/utils";
|
|
1861
2492
|
var VariableFieldKeyRenameService = class {
|
|
1862
2493
|
constructor() {
|
|
1863
2494
|
this.toDispose = new DisposableCollection6();
|
|
1864
2495
|
this.renameEmitter = new Emitter4();
|
|
1865
|
-
|
|
2496
|
+
/**
|
|
2497
|
+
* Emits events for fields that are disposed of during a list change, but not renamed.
|
|
2498
|
+
* This helps distinguish between a field that was truly removed and one that was renamed.
|
|
2499
|
+
*/
|
|
1866
2500
|
this.disposeInListEmitter = new Emitter4();
|
|
2501
|
+
/**
|
|
2502
|
+
* An event that fires when a variable field key is successfully renamed.
|
|
2503
|
+
*/
|
|
1867
2504
|
this.onRename = this.renameEmitter.event;
|
|
2505
|
+
/**
|
|
2506
|
+
* An event that fires when a field is removed from a list (and not part of a rename).
|
|
2507
|
+
*/
|
|
1868
2508
|
this.onDisposeInList = this.disposeInListEmitter.event;
|
|
1869
2509
|
}
|
|
2510
|
+
/**
|
|
2511
|
+
* Handles changes in a list of fields to detect rename operations.
|
|
2512
|
+
* @param ast The AST node where the change occurred.
|
|
2513
|
+
* @param prev The list of fields before the change.
|
|
2514
|
+
* @param next The list of fields after the change.
|
|
2515
|
+
*/
|
|
1870
2516
|
handleFieldListChange(ast, prev, next) {
|
|
1871
2517
|
if (!ast || !prev?.length || !next?.length) {
|
|
1872
2518
|
this.notifyFieldsDispose(prev, next);
|
|
@@ -1897,6 +2543,11 @@ var VariableFieldKeyRenameService = class {
|
|
|
1897
2543
|
}
|
|
1898
2544
|
this.renameEmitter.fire(renameNodeInfo);
|
|
1899
2545
|
}
|
|
2546
|
+
/**
|
|
2547
|
+
* Notifies listeners about fields that were removed from a list.
|
|
2548
|
+
* @param prev The list of fields before the change.
|
|
2549
|
+
* @param next The list of fields after the change.
|
|
2550
|
+
*/
|
|
1900
2551
|
notifyFieldsDispose(prev, next) {
|
|
1901
2552
|
const removedFields = difference(prev || [], next || []);
|
|
1902
2553
|
removedFields.forEach((_field) => this.disposeInListEmitter.fire(_field));
|
|
@@ -1944,28 +2595,48 @@ var VariableContainerModule = new ContainerModule((bind) => {
|
|
|
1944
2595
|
});
|
|
1945
2596
|
|
|
1946
2597
|
// src/react/context.tsx
|
|
1947
|
-
import { createContext, useContext } from "react";
|
|
2598
|
+
import React, { createContext, useContext } from "react";
|
|
1948
2599
|
var ScopeContext = createContext(null);
|
|
1949
|
-
var ScopeProvider =
|
|
1950
|
-
|
|
1951
|
-
|
|
2600
|
+
var ScopeProvider = (props) => {
|
|
2601
|
+
const { scope, value, children } = props;
|
|
2602
|
+
const scopeToUse = scope || value?.scope;
|
|
2603
|
+
if (!scopeToUse) {
|
|
2604
|
+
throw new Error("[ScopeProvider] scope is required");
|
|
2605
|
+
}
|
|
2606
|
+
return /* @__PURE__ */ React.createElement(ScopeContext.Provider, { value: { scope: scopeToUse } }, children);
|
|
2607
|
+
};
|
|
2608
|
+
var useCurrentScope = (params) => {
|
|
2609
|
+
const { strict = false } = params || {};
|
|
2610
|
+
const context = useContext(ScopeContext);
|
|
2611
|
+
if (!context) {
|
|
2612
|
+
if (strict) {
|
|
2613
|
+
throw new Error("useCurrentScope must be used within a <ScopeProvider scope={scope}>");
|
|
2614
|
+
}
|
|
2615
|
+
console.warn("useCurrentScope should be used within a <ScopeProvider scope={scope}>");
|
|
2616
|
+
}
|
|
2617
|
+
return context?.scope;
|
|
2618
|
+
};
|
|
1952
2619
|
|
|
1953
|
-
// src/react/hooks/
|
|
2620
|
+
// src/react/hooks/use-scope-available.ts
|
|
1954
2621
|
import { useEffect } from "react";
|
|
1955
2622
|
import { useRefresh } from "@flowgram.ai/core";
|
|
1956
|
-
function useScopeAvailable() {
|
|
1957
|
-
const
|
|
2623
|
+
function useScopeAvailable(params) {
|
|
2624
|
+
const { autoRefresh = true } = params || {};
|
|
2625
|
+
const scope = useCurrentScope({ strict: true });
|
|
1958
2626
|
const refresh = useRefresh();
|
|
1959
2627
|
useEffect(() => {
|
|
1960
|
-
|
|
2628
|
+
if (!autoRefresh) {
|
|
2629
|
+
return () => null;
|
|
2630
|
+
}
|
|
2631
|
+
const disposable = scope.available.onListOrAnyVarChange(() => {
|
|
1961
2632
|
refresh();
|
|
1962
2633
|
});
|
|
1963
2634
|
return () => disposable.dispose();
|
|
1964
|
-
}, []);
|
|
2635
|
+
}, [autoRefresh]);
|
|
1965
2636
|
return scope.available;
|
|
1966
2637
|
}
|
|
1967
2638
|
|
|
1968
|
-
// src/react/hooks/
|
|
2639
|
+
// src/react/hooks/use-available-variables.ts
|
|
1969
2640
|
import { useEffect as useEffect2 } from "react";
|
|
1970
2641
|
import { useRefresh as useRefresh2, useService } from "@flowgram.ai/core";
|
|
1971
2642
|
function useAvailableVariables() {
|
|
@@ -1974,7 +2645,7 @@ function useAvailableVariables() {
|
|
|
1974
2645
|
const refresh = useRefresh2();
|
|
1975
2646
|
useEffect2(() => {
|
|
1976
2647
|
if (!scope) {
|
|
1977
|
-
const disposable2 = variableEngine.globalVariableTable.
|
|
2648
|
+
const disposable2 = variableEngine.globalVariableTable.onListOrAnyVarChange(() => {
|
|
1978
2649
|
refresh();
|
|
1979
2650
|
});
|
|
1980
2651
|
return () => disposable2.dispose();
|
|
@@ -1986,9 +2657,30 @@ function useAvailableVariables() {
|
|
|
1986
2657
|
}, []);
|
|
1987
2658
|
return scope ? scope.available.variables : variableEngine.globalVariableTable.variables;
|
|
1988
2659
|
}
|
|
2660
|
+
|
|
2661
|
+
// src/react/hooks/use-output-variables.ts
|
|
2662
|
+
import { useEffect as useEffect3 } from "react";
|
|
2663
|
+
import { useRefresh as useRefresh3 } from "@flowgram.ai/core";
|
|
2664
|
+
function useOutputVariables() {
|
|
2665
|
+
const scope = useCurrentScope();
|
|
2666
|
+
const refresh = useRefresh3();
|
|
2667
|
+
useEffect3(() => {
|
|
2668
|
+
if (!scope) {
|
|
2669
|
+
throw new Error(
|
|
2670
|
+
"[useOutputVariables]: No scope found, useOutputVariables must be used in <ScopeProvider>"
|
|
2671
|
+
);
|
|
2672
|
+
}
|
|
2673
|
+
const disposable = scope.output.onListOrAnyVarChange(() => {
|
|
2674
|
+
refresh();
|
|
2675
|
+
});
|
|
2676
|
+
return () => disposable.dispose();
|
|
2677
|
+
}, []);
|
|
2678
|
+
return scope?.output.variables || [];
|
|
2679
|
+
}
|
|
1989
2680
|
export {
|
|
1990
2681
|
ASTFactory,
|
|
1991
2682
|
ASTKind,
|
|
2683
|
+
ASTMatch,
|
|
1992
2684
|
ASTNode,
|
|
1993
2685
|
ASTNodeFlags,
|
|
1994
2686
|
ASTRegisters,
|
|
@@ -1997,12 +2689,12 @@ export {
|
|
|
1997
2689
|
BaseType,
|
|
1998
2690
|
BaseVariableField,
|
|
1999
2691
|
BooleanType,
|
|
2692
|
+
CustomType,
|
|
2000
2693
|
DataNode,
|
|
2001
2694
|
EnumerateExpression,
|
|
2002
|
-
ExpressionList,
|
|
2003
2695
|
IntegerType,
|
|
2004
2696
|
KeyPathExpression,
|
|
2005
|
-
|
|
2697
|
+
LegacyKeyPathExpression,
|
|
2006
2698
|
ListNode,
|
|
2007
2699
|
MapNode,
|
|
2008
2700
|
MapType,
|
|
@@ -2020,13 +2712,13 @@ export {
|
|
|
2020
2712
|
VariableEngine,
|
|
2021
2713
|
VariableEngineProvider,
|
|
2022
2714
|
VariableFieldKeyRenameService,
|
|
2023
|
-
|
|
2715
|
+
WrapArrayExpression,
|
|
2024
2716
|
injectToAST,
|
|
2025
2717
|
isMatchAST,
|
|
2026
2718
|
postConstructAST,
|
|
2027
2719
|
useAvailableVariables,
|
|
2028
2720
|
useCurrentScope,
|
|
2029
|
-
|
|
2030
|
-
|
|
2721
|
+
useOutputVariables,
|
|
2722
|
+
useScopeAvailable
|
|
2031
2723
|
};
|
|
2032
2724
|
//# sourceMappingURL=index.js.map
|