@flowgram.ai/variable-core 0.1.0-alpha.3 → 0.1.0-alpha.31
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 +1086 -425
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +1783 -529
- package/dist/index.d.ts +1783 -529
- package/dist/index.js +1152 -485
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- 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) => {
|
|
@@ -109,7 +270,7 @@ var ASTKind = /* @__PURE__ */ ((ASTKind2) => {
|
|
|
109
270
|
ASTKind2["VariableDeclarationList"] = "VariableDeclarationList";
|
|
110
271
|
ASTKind2["KeyPathExpression"] = "KeyPathExpression";
|
|
111
272
|
ASTKind2["EnumerateExpression"] = "EnumerateExpression";
|
|
112
|
-
ASTKind2["
|
|
273
|
+
ASTKind2["WrapArrayExpression"] = "WrapArrayExpression";
|
|
113
274
|
ASTKind2["ListNode"] = "ListNode";
|
|
114
275
|
ASTKind2["DataNode"] = "DataNode";
|
|
115
276
|
ASTKind2["MapNode"] = "MapNode";
|
|
@@ -117,7 +278,7 @@ var ASTKind = /* @__PURE__ */ ((ASTKind2) => {
|
|
|
117
278
|
})(ASTKind || {});
|
|
118
279
|
|
|
119
280
|
// src/ast/ast-registers.ts
|
|
120
|
-
import { omit } from "lodash";
|
|
281
|
+
import { omit } from "lodash-es";
|
|
121
282
|
import { injectable as injectable2 } from "inversify";
|
|
122
283
|
|
|
123
284
|
// src/ast/utils/inversify.ts
|
|
@@ -148,6 +309,43 @@ var postConstructAST = () => (target, propertyKey) => {
|
|
|
148
309
|
}
|
|
149
310
|
};
|
|
150
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
|
+
|
|
151
349
|
// src/ast/utils/helpers.ts
|
|
152
350
|
function updateChildNodeHelper({
|
|
153
351
|
getChildNode,
|
|
@@ -183,22 +381,9 @@ function getAllChildren(ast) {
|
|
|
183
381
|
return [...ast.children, ...ast.children.map((_child) => getAllChildren(_child)).flat()];
|
|
184
382
|
}
|
|
185
383
|
function isMatchAST(node, targetType) {
|
|
186
|
-
return node
|
|
384
|
+
return ASTMatch.is(node, targetType);
|
|
187
385
|
}
|
|
188
386
|
|
|
189
|
-
// src/ast/flags.ts
|
|
190
|
-
var ASTNodeFlags = /* @__PURE__ */ ((ASTNodeFlags2) => {
|
|
191
|
-
ASTNodeFlags2[ASTNodeFlags2["None"] = 0] = "None";
|
|
192
|
-
ASTNodeFlags2[ASTNodeFlags2["VariableField"] = 1] = "VariableField";
|
|
193
|
-
ASTNodeFlags2[ASTNodeFlags2["Expression"] = 4] = "Expression";
|
|
194
|
-
ASTNodeFlags2[ASTNodeFlags2["BasicType"] = 8] = "BasicType";
|
|
195
|
-
ASTNodeFlags2[ASTNodeFlags2["DrilldownType"] = 16] = "DrilldownType";
|
|
196
|
-
ASTNodeFlags2[ASTNodeFlags2["EnumerateType"] = 32] = "EnumerateType";
|
|
197
|
-
ASTNodeFlags2[ASTNodeFlags2["UnionType"] = 64] = "UnionType";
|
|
198
|
-
ASTNodeFlags2[ASTNodeFlags2["VariableType"] = 120] = "VariableType";
|
|
199
|
-
return ASTNodeFlags2;
|
|
200
|
-
})(ASTNodeFlags || {});
|
|
201
|
-
|
|
202
387
|
// src/ast/ast-node.ts
|
|
203
388
|
import {
|
|
204
389
|
BehaviorSubject,
|
|
@@ -206,58 +391,62 @@ import {
|
|
|
206
391
|
debounceTime,
|
|
207
392
|
distinctUntilChanged,
|
|
208
393
|
map,
|
|
209
|
-
skip,
|
|
394
|
+
skip as skip2,
|
|
210
395
|
tap
|
|
211
396
|
} from "rxjs";
|
|
212
397
|
import { nanoid } from "nanoid";
|
|
398
|
+
import { isNil, omitBy } from "lodash-es";
|
|
213
399
|
import { shallowEqual } from "fast-equals";
|
|
214
|
-
import { Disposable as Disposable2, DisposableCollection as
|
|
400
|
+
import { Disposable as Disposable2, DisposableCollection as DisposableCollection3 } from "@flowgram.ai/utils";
|
|
215
401
|
var ASTNode = class _ASTNode {
|
|
216
402
|
/**
|
|
217
|
-
*
|
|
218
|
-
* @param createParams
|
|
219
|
-
* @param injectOptions
|
|
403
|
+
* Constructor.
|
|
404
|
+
* @param createParams Necessary parameters for creating an ASTNode.
|
|
405
|
+
* @param injectOptions Dependency injection for various modules.
|
|
220
406
|
*/
|
|
221
407
|
constructor({ key, parent, scope }, opts) {
|
|
222
408
|
/**
|
|
223
|
-
*
|
|
409
|
+
* Node flags, used to record some flag information.
|
|
224
410
|
*/
|
|
225
411
|
this.flags = 0 /* None */;
|
|
226
412
|
/**
|
|
227
|
-
*
|
|
413
|
+
* The version number of the ASTNode, which increments by 1 each time `fireChange` is called.
|
|
228
414
|
*/
|
|
229
415
|
this._version = 0;
|
|
230
416
|
/**
|
|
231
|
-
*
|
|
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.
|
|
232
420
|
*/
|
|
233
421
|
this.changeLocked = false;
|
|
234
422
|
/**
|
|
235
|
-
*
|
|
423
|
+
* Parameters related to batch updates.
|
|
236
424
|
*/
|
|
237
425
|
this._batch = {
|
|
238
426
|
batching: false,
|
|
239
427
|
hasChangesInBatch: false
|
|
240
428
|
};
|
|
241
429
|
/**
|
|
242
|
-
* AST
|
|
243
|
-
* -
|
|
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.
|
|
244
433
|
*/
|
|
245
434
|
this.value$ = new BehaviorSubject(this);
|
|
246
435
|
/**
|
|
247
|
-
*
|
|
436
|
+
* Child ASTNodes.
|
|
248
437
|
*/
|
|
249
438
|
this._children = /* @__PURE__ */ new Set();
|
|
250
439
|
/**
|
|
251
|
-
*
|
|
440
|
+
* List of disposal handlers for the ASTNode.
|
|
252
441
|
*/
|
|
253
|
-
this.toDispose = new
|
|
442
|
+
this.toDispose = new DisposableCollection3(
|
|
254
443
|
Disposable2.create(() => {
|
|
255
444
|
this.parent?.fireChange();
|
|
256
445
|
this.children.forEach((child) => child.dispose());
|
|
257
446
|
})
|
|
258
447
|
);
|
|
259
448
|
/**
|
|
260
|
-
*
|
|
449
|
+
* Callback triggered upon disposal.
|
|
261
450
|
*/
|
|
262
451
|
this.onDispose = this.toDispose.onDispose;
|
|
263
452
|
this.scope = scope;
|
|
@@ -265,10 +454,19 @@ var ASTNode = class _ASTNode {
|
|
|
265
454
|
this.opts = opts;
|
|
266
455
|
this.key = key || nanoid();
|
|
267
456
|
this.fromJSON = this.withBatchUpdate(this.fromJSON.bind(this));
|
|
268
|
-
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
|
+
);
|
|
269
467
|
}
|
|
270
468
|
/**
|
|
271
|
-
*
|
|
469
|
+
* The type of the ASTNode.
|
|
272
470
|
*/
|
|
273
471
|
get kind() {
|
|
274
472
|
if (!this.constructor.kind) {
|
|
@@ -277,24 +475,14 @@ var ASTNode = class _ASTNode {
|
|
|
277
475
|
return this.constructor.kind;
|
|
278
476
|
}
|
|
279
477
|
/**
|
|
280
|
-
*
|
|
478
|
+
* Gets all child ASTNodes of the current ASTNode.
|
|
281
479
|
*/
|
|
282
480
|
get children() {
|
|
283
481
|
return Array.from(this._children);
|
|
284
482
|
}
|
|
285
483
|
/**
|
|
286
|
-
*
|
|
287
|
-
* @
|
|
288
|
-
*/
|
|
289
|
-
toJSON() {
|
|
290
|
-
console.warn("[VariableEngine] Please Implement toJSON method for " + this.kind);
|
|
291
|
-
return {
|
|
292
|
-
kind: this.kind
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* 创建子节点
|
|
297
|
-
* @param json 子节点的 AST JSON
|
|
484
|
+
* Creates a child ASTNode.
|
|
485
|
+
* @param json The AST JSON of the child ASTNode.
|
|
298
486
|
* @returns
|
|
299
487
|
*/
|
|
300
488
|
createChildNode(json) {
|
|
@@ -312,8 +500,8 @@ var ASTNode = class _ASTNode {
|
|
|
312
500
|
return child;
|
|
313
501
|
}
|
|
314
502
|
/**
|
|
315
|
-
*
|
|
316
|
-
* @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.
|
|
317
505
|
*/
|
|
318
506
|
updateChildNodeByKey(keyInThis, nextJSON) {
|
|
319
507
|
this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
@@ -324,8 +512,8 @@ var ASTNode = class _ASTNode {
|
|
|
324
512
|
});
|
|
325
513
|
}
|
|
326
514
|
/**
|
|
327
|
-
*
|
|
328
|
-
* @param updater
|
|
515
|
+
* Batch updates the ASTNode, merging all `fireChange` calls within the batch function into one.
|
|
516
|
+
* @param updater The batch function.
|
|
329
517
|
* @returns
|
|
330
518
|
*/
|
|
331
519
|
withBatchUpdate(updater) {
|
|
@@ -345,7 +533,7 @@ var ASTNode = class _ASTNode {
|
|
|
345
533
|
};
|
|
346
534
|
}
|
|
347
535
|
/**
|
|
348
|
-
*
|
|
536
|
+
* Triggers an update for the current node.
|
|
349
537
|
*/
|
|
350
538
|
fireChange() {
|
|
351
539
|
if (this.changeLocked || this.disposed) {
|
|
@@ -361,22 +549,24 @@ var ASTNode = class _ASTNode {
|
|
|
361
549
|
this.parent?.fireChange();
|
|
362
550
|
}
|
|
363
551
|
/**
|
|
364
|
-
*
|
|
365
|
-
* -
|
|
552
|
+
* The version value of the ASTNode.
|
|
553
|
+
* - You can used to check whether ASTNode are updated.
|
|
366
554
|
*/
|
|
367
555
|
get version() {
|
|
368
556
|
return this._version;
|
|
369
557
|
}
|
|
370
558
|
/**
|
|
371
|
-
*
|
|
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.
|
|
372
562
|
*/
|
|
373
563
|
get hash() {
|
|
374
564
|
return `${this._version}${this.kind}${this.key}`;
|
|
375
565
|
}
|
|
376
566
|
/**
|
|
377
|
-
*
|
|
378
|
-
* @param observer
|
|
379
|
-
* @param selector
|
|
567
|
+
* Listens for changes to the ASTNode.
|
|
568
|
+
* @param observer The listener callback.
|
|
569
|
+
* @param selector Listens for specified data.
|
|
380
570
|
* @returns
|
|
381
571
|
*/
|
|
382
572
|
subscribe(observer, { selector, debounceAnimation, triggerOnInit } = {}) {
|
|
@@ -392,13 +582,17 @@ var ASTNode = class _ASTNode {
|
|
|
392
582
|
return value;
|
|
393
583
|
}
|
|
394
584
|
),
|
|
395
|
-
//
|
|
396
|
-
triggerOnInit ? tap(() => null) :
|
|
397
|
-
//
|
|
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.
|
|
398
588
|
debounceAnimation ? debounceTime(0, animationFrameScheduler) : tap(() => null)
|
|
399
589
|
).subscribe(observer)
|
|
400
590
|
);
|
|
401
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Dispatches a global event for the current ASTNode.
|
|
594
|
+
* @param event The global event.
|
|
595
|
+
*/
|
|
402
596
|
dispatchGlobalEvent(event) {
|
|
403
597
|
this.scope.event.dispatch({
|
|
404
598
|
...event,
|
|
@@ -406,7 +600,7 @@ var ASTNode = class _ASTNode {
|
|
|
406
600
|
});
|
|
407
601
|
}
|
|
408
602
|
/**
|
|
409
|
-
*
|
|
603
|
+
* Disposes the ASTNode.
|
|
410
604
|
*/
|
|
411
605
|
dispose() {
|
|
412
606
|
if (this.toDispose.disposed) {
|
|
@@ -429,8 +623,9 @@ var BaseType = class extends ASTNode {
|
|
|
429
623
|
this.flags = 8 /* BasicType */;
|
|
430
624
|
}
|
|
431
625
|
/**
|
|
432
|
-
*
|
|
433
|
-
* @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.
|
|
434
629
|
*/
|
|
435
630
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
436
631
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
@@ -442,17 +637,15 @@ var BaseType = class extends ASTNode {
|
|
|
442
637
|
return this.kind === targetTypeJSON?.kind;
|
|
443
638
|
}
|
|
444
639
|
/**
|
|
445
|
-
*
|
|
446
|
-
*
|
|
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`.
|
|
447
645
|
*/
|
|
448
646
|
getByKeyPath(keyPath = []) {
|
|
449
647
|
throw new Error(`Get By Key Path is not implemented for Type: ${this.kind}`);
|
|
450
648
|
}
|
|
451
|
-
toJSON() {
|
|
452
|
-
return {
|
|
453
|
-
kind: this.kind
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
649
|
};
|
|
457
650
|
|
|
458
651
|
// src/ast/type/array.ts
|
|
@@ -461,13 +654,24 @@ var ArrayType = class extends BaseType {
|
|
|
461
654
|
super(...arguments);
|
|
462
655
|
this.flags = 16 /* DrilldownType */ | 32 /* EnumerateType */;
|
|
463
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Deserializes the `ArrayJSON` to the `ArrayType`.
|
|
659
|
+
* @param json The `ArrayJSON` to deserialize.
|
|
660
|
+
*/
|
|
464
661
|
fromJSON({ items }) {
|
|
465
662
|
this.updateChildNodeByKey("items", parseTypeJsonOrKind(items));
|
|
466
663
|
}
|
|
467
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Whether the items type can be drilled down.
|
|
666
|
+
*/
|
|
468
667
|
get canDrilldownItems() {
|
|
469
668
|
return !!(this.items?.flags & 16 /* DrilldownType */);
|
|
470
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
|
+
*/
|
|
471
675
|
getByKeyPath(keyPath) {
|
|
472
676
|
const [curr, ...rest] = keyPath || [];
|
|
473
677
|
if (curr === "0" && this.canDrilldownItems) {
|
|
@@ -475,19 +679,24 @@ var ArrayType = class extends BaseType {
|
|
|
475
679
|
}
|
|
476
680
|
return void 0;
|
|
477
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
|
+
*/
|
|
478
687
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
479
688
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
480
689
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
481
690
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
482
691
|
return isSuperEqual;
|
|
483
692
|
}
|
|
484
|
-
return targetTypeJSON && isSuperEqual && //
|
|
693
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
485
694
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
486
695
|
}
|
|
487
696
|
/**
|
|
488
|
-
* Array
|
|
489
|
-
* @param targetTypeJSON
|
|
490
|
-
* @returns
|
|
697
|
+
* Array strong comparison.
|
|
698
|
+
* @param targetTypeJSON The type to compare with.
|
|
699
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
491
700
|
*/
|
|
492
701
|
customStrongEqual(targetTypeJSON) {
|
|
493
702
|
if (!this.items) {
|
|
@@ -495,6 +704,10 @@ var ArrayType = class extends BaseType {
|
|
|
495
704
|
}
|
|
496
705
|
return this.items?.isTypeEqual(targetTypeJSON.items);
|
|
497
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Serialize the `ArrayType` to `ArrayJSON`
|
|
709
|
+
* @returns The JSON representation of `ArrayType`.
|
|
710
|
+
*/
|
|
498
711
|
toJSON() {
|
|
499
712
|
return {
|
|
500
713
|
kind: "Array" /* Array */,
|
|
@@ -510,7 +723,31 @@ var StringType = class extends BaseType {
|
|
|
510
723
|
super(...arguments);
|
|
511
724
|
this.flags = 8 /* BasicType */;
|
|
512
725
|
}
|
|
513
|
-
|
|
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
|
+
};
|
|
514
751
|
}
|
|
515
752
|
};
|
|
516
753
|
StringType.kind = "String" /* String */;
|
|
@@ -521,61 +758,84 @@ var IntegerType = class extends BaseType {
|
|
|
521
758
|
super(...arguments);
|
|
522
759
|
this.flags = 8 /* BasicType */;
|
|
523
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* Deserializes the `IntegerJSON` to the `IntegerType`.
|
|
763
|
+
* @param json The `IntegerJSON` to deserialize.
|
|
764
|
+
*/
|
|
524
765
|
fromJSON() {
|
|
525
766
|
}
|
|
767
|
+
toJSON() {
|
|
768
|
+
return {};
|
|
769
|
+
}
|
|
526
770
|
};
|
|
527
771
|
IntegerType.kind = "Integer" /* Integer */;
|
|
528
772
|
|
|
529
773
|
// src/ast/type/boolean.ts
|
|
530
774
|
var BooleanType = class extends BaseType {
|
|
775
|
+
/**
|
|
776
|
+
* Deserializes the `BooleanJSON` to the `BooleanType`.
|
|
777
|
+
* @param json The `BooleanJSON` to deserialize.
|
|
778
|
+
*/
|
|
531
779
|
fromJSON() {
|
|
532
780
|
}
|
|
781
|
+
toJSON() {
|
|
782
|
+
return {};
|
|
783
|
+
}
|
|
533
784
|
};
|
|
534
785
|
BooleanType.kind = "Boolean" /* Boolean */;
|
|
535
786
|
|
|
536
787
|
// src/ast/type/number.ts
|
|
537
788
|
var NumberType = class extends BaseType {
|
|
789
|
+
/**
|
|
790
|
+
* Deserializes the `NumberJSON` to the `NumberType`.
|
|
791
|
+
* @param json The `NumberJSON` to deserialize.
|
|
792
|
+
*/
|
|
538
793
|
fromJSON() {
|
|
539
794
|
}
|
|
795
|
+
toJSON() {
|
|
796
|
+
return {};
|
|
797
|
+
}
|
|
540
798
|
};
|
|
541
799
|
NumberType.kind = "Number" /* Number */;
|
|
542
800
|
|
|
543
801
|
// src/ast/type/map.ts
|
|
544
802
|
var MapType = class extends BaseType {
|
|
803
|
+
/**
|
|
804
|
+
* Deserializes the `MapJSON` to the `MapType`.
|
|
805
|
+
* @param json The `MapJSON` to deserialize.
|
|
806
|
+
*/
|
|
545
807
|
fromJSON({ keyType = "String" /* String */, valueType }) {
|
|
546
808
|
this.updateChildNodeByKey("keyType", parseTypeJsonOrKind(keyType));
|
|
547
809
|
this.updateChildNodeByKey("valueType", parseTypeJsonOrKind(valueType));
|
|
548
810
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
// const [curr, ...rest] = keyPath || [];
|
|
555
|
-
// if (curr === '*' && this.canDrilldownValue) {
|
|
556
|
-
// return this.valueType.getByKeyPath(rest);
|
|
557
|
-
// }
|
|
558
|
-
// return undefined;
|
|
559
|
-
// }
|
|
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
|
+
*/
|
|
560
816
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
561
817
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
562
818
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
563
819
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
564
820
|
return isSuperEqual;
|
|
565
821
|
}
|
|
566
|
-
return targetTypeJSON && isSuperEqual && //
|
|
822
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
567
823
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
568
824
|
}
|
|
569
825
|
/**
|
|
570
|
-
* Map
|
|
571
|
-
* @param targetTypeJSON
|
|
572
|
-
* @returns
|
|
826
|
+
* Map strong comparison.
|
|
827
|
+
* @param targetTypeJSON The type to compare with.
|
|
828
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
573
829
|
*/
|
|
574
830
|
customStrongEqual(targetTypeJSON) {
|
|
575
831
|
const { keyType = "String" /* String */, valueType } = targetTypeJSON;
|
|
576
832
|
const isValueTypeEqual = !valueType && !this.valueType || this.valueType?.isTypeEqual(valueType);
|
|
577
833
|
return isValueTypeEqual && this.keyType?.isTypeEqual(keyType);
|
|
578
834
|
}
|
|
835
|
+
/**
|
|
836
|
+
* Serialize the node to a JSON object.
|
|
837
|
+
* @returns The JSON representation of the node.
|
|
838
|
+
*/
|
|
579
839
|
toJSON() {
|
|
580
840
|
return {
|
|
581
841
|
kind: "Map" /* Map */,
|
|
@@ -584,17 +844,23 @@ var MapType = class extends BaseType {
|
|
|
584
844
|
};
|
|
585
845
|
}
|
|
586
846
|
};
|
|
587
|
-
// public flags: ASTNodeFlags = ASTNodeFlags.DrilldownType | ASTNodeFlags.EnumerateType;
|
|
588
847
|
MapType.kind = "Map" /* Map */;
|
|
589
848
|
|
|
590
849
|
// src/ast/type/object.ts
|
|
591
|
-
import { xor } from "lodash";
|
|
850
|
+
import { xor } from "lodash-es";
|
|
592
851
|
var ObjectType = class extends BaseType {
|
|
593
852
|
constructor() {
|
|
594
853
|
super(...arguments);
|
|
595
854
|
this.flags = 16 /* DrilldownType */;
|
|
855
|
+
/**
|
|
856
|
+
* A map of property keys to `Property` instances.
|
|
857
|
+
*/
|
|
596
858
|
this.propertyTable = /* @__PURE__ */ new Map();
|
|
597
859
|
}
|
|
860
|
+
/**
|
|
861
|
+
* Deserializes the `ObjectJSON` to the `ObjectType`.
|
|
862
|
+
* @param json The `ObjectJSON` to deserialize.
|
|
863
|
+
*/
|
|
598
864
|
fromJSON({ properties }) {
|
|
599
865
|
const removedKeys = new Set(this.propertyTable.keys());
|
|
600
866
|
const prev = [...this.properties || []];
|
|
@@ -628,16 +894,19 @@ var ObjectType = class extends BaseType {
|
|
|
628
894
|
}
|
|
629
895
|
});
|
|
630
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Serialize the `ObjectType` to `ObjectJSON`.
|
|
899
|
+
* @returns The JSON representation of `ObjectType`.
|
|
900
|
+
*/
|
|
631
901
|
toJSON() {
|
|
632
902
|
return {
|
|
633
|
-
kind: "Object" /* Object */,
|
|
634
903
|
properties: this.properties.map((_property) => _property.toJSON())
|
|
635
904
|
};
|
|
636
905
|
}
|
|
637
906
|
/**
|
|
638
|
-
*
|
|
639
|
-
* @param keyPath
|
|
640
|
-
* @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`.
|
|
641
910
|
*/
|
|
642
911
|
getByKeyPath(keyPath) {
|
|
643
912
|
const [curr, ...restKeyPath] = keyPath;
|
|
@@ -650,19 +919,24 @@ var ObjectType = class extends BaseType {
|
|
|
650
919
|
}
|
|
651
920
|
return void 0;
|
|
652
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
|
+
*/
|
|
653
927
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
654
928
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
655
929
|
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
656
930
|
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
657
931
|
return isSuperEqual;
|
|
658
932
|
}
|
|
659
|
-
return targetTypeJSON && isSuperEqual && //
|
|
933
|
+
return targetTypeJSON && isSuperEqual && // Weak comparison, only need to compare the Kind.
|
|
660
934
|
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
661
935
|
}
|
|
662
936
|
/**
|
|
663
|
-
* Object
|
|
664
|
-
* @param targetTypeJSON
|
|
665
|
-
* @returns
|
|
937
|
+
* Object type strong comparison.
|
|
938
|
+
* @param targetTypeJSON The type to compare with.
|
|
939
|
+
* @returns `true` if the types are equal, `false` otherwise.
|
|
666
940
|
*/
|
|
667
941
|
customStrongEqual(targetTypeJSON) {
|
|
668
942
|
const targetProperties = targetTypeJSON.properties || [];
|
|
@@ -679,15 +953,27 @@ ObjectType.kind = "Object" /* Object */;
|
|
|
679
953
|
|
|
680
954
|
// src/ast/type/custom-type.ts
|
|
681
955
|
var CustomType = class extends BaseType {
|
|
956
|
+
/**
|
|
957
|
+
* The name of the custom type.
|
|
958
|
+
*/
|
|
682
959
|
get typeName() {
|
|
683
960
|
return this._typeName;
|
|
684
961
|
}
|
|
962
|
+
/**
|
|
963
|
+
* Deserializes the `CustomTypeJSON` to the `CustomType`.
|
|
964
|
+
* @param json The `CustomTypeJSON` to deserialize.
|
|
965
|
+
*/
|
|
685
966
|
fromJSON(json) {
|
|
686
967
|
if (this._typeName !== json.typeName) {
|
|
687
968
|
this._typeName = json.typeName;
|
|
688
969
|
this.fireChange();
|
|
689
970
|
}
|
|
690
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
|
+
*/
|
|
691
977
|
isTypeEqual(targetTypeJSONOrKind) {
|
|
692
978
|
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
693
979
|
if (targetTypeJSON?.kind === "Union" /* Union */) {
|
|
@@ -697,6 +983,11 @@ var CustomType = class extends BaseType {
|
|
|
697
983
|
}
|
|
698
984
|
return targetTypeJSON?.kind === this.kind && targetTypeJSON?.typeName === this.typeName;
|
|
699
985
|
}
|
|
986
|
+
toJSON() {
|
|
987
|
+
return {
|
|
988
|
+
typeName: this.typeName
|
|
989
|
+
};
|
|
990
|
+
}
|
|
700
991
|
};
|
|
701
992
|
CustomType.kind = "CustomType" /* CustomType */;
|
|
702
993
|
|
|
@@ -704,11 +995,11 @@ CustomType.kind = "CustomType" /* CustomType */;
|
|
|
704
995
|
import {
|
|
705
996
|
distinctUntilChanged as distinctUntilChanged2,
|
|
706
997
|
map as map2,
|
|
707
|
-
switchMap,
|
|
998
|
+
switchMap as switchMap2,
|
|
708
999
|
combineLatest,
|
|
709
1000
|
of,
|
|
710
|
-
Subject,
|
|
711
|
-
share
|
|
1001
|
+
Subject as Subject2,
|
|
1002
|
+
share as share2
|
|
712
1003
|
} from "rxjs";
|
|
713
1004
|
import { shallowEqual as shallowEqual2 } from "fast-equals";
|
|
714
1005
|
|
|
@@ -731,25 +1022,24 @@ var BaseExpression = class extends ASTNode {
|
|
|
731
1022
|
super(params, opts);
|
|
732
1023
|
this.flags = 4 /* Expression */;
|
|
733
1024
|
/**
|
|
734
|
-
*
|
|
1025
|
+
* The variable fields referenced by the expression.
|
|
735
1026
|
*/
|
|
736
1027
|
this._refs = [];
|
|
737
|
-
this.refreshRefs$ = new
|
|
1028
|
+
this.refreshRefs$ = new Subject2();
|
|
738
1029
|
/**
|
|
739
|
-
*
|
|
740
|
-
* 监听 [a.b.c] -> [a.b]
|
|
1030
|
+
* An observable that emits the referenced variable fields when they change.
|
|
741
1031
|
*/
|
|
742
1032
|
this.refs$ = this.refreshRefs$.pipe(
|
|
743
1033
|
map2(() => this.getRefFields()),
|
|
744
1034
|
distinctUntilChanged2(shallowEqual2),
|
|
745
|
-
|
|
1035
|
+
switchMap2(
|
|
746
1036
|
(refs) => !refs?.length ? of([]) : combineLatest(
|
|
747
1037
|
refs.map(
|
|
748
1038
|
(ref) => ref ? ref.value$ : of(void 0)
|
|
749
1039
|
)
|
|
750
1040
|
)
|
|
751
1041
|
),
|
|
752
|
-
|
|
1042
|
+
share2()
|
|
753
1043
|
);
|
|
754
1044
|
this.toDispose.push(
|
|
755
1045
|
subsToDisposable(
|
|
@@ -761,114 +1051,42 @@ var BaseExpression = class extends ASTNode {
|
|
|
761
1051
|
);
|
|
762
1052
|
}
|
|
763
1053
|
/**
|
|
764
|
-
*
|
|
1054
|
+
* Get the global variable table, which is used to access referenced variables.
|
|
765
1055
|
*/
|
|
766
1056
|
get globalVariableTable() {
|
|
767
1057
|
return this.scope.variableEngine.globalVariableTable;
|
|
768
1058
|
}
|
|
769
1059
|
/**
|
|
770
|
-
*
|
|
1060
|
+
* Parent variable fields, sorted from closest to farthest.
|
|
771
1061
|
*/
|
|
772
1062
|
get parentFields() {
|
|
773
1063
|
return getParentFields(this);
|
|
774
1064
|
}
|
|
1065
|
+
/**
|
|
1066
|
+
* The variable fields referenced by the expression.
|
|
1067
|
+
*/
|
|
775
1068
|
get refs() {
|
|
776
1069
|
return this._refs;
|
|
777
1070
|
}
|
|
778
1071
|
/**
|
|
779
|
-
*
|
|
1072
|
+
* Refresh the variable references.
|
|
780
1073
|
*/
|
|
781
1074
|
refreshRefs() {
|
|
782
1075
|
this.refreshRefs$.next();
|
|
783
1076
|
}
|
|
784
1077
|
};
|
|
785
1078
|
|
|
786
|
-
// src/ast/expression/expression-list.ts
|
|
787
|
-
var ExpressionList = class extends ASTNode {
|
|
788
|
-
fromJSON({ expressions }) {
|
|
789
|
-
this.expressions = expressions.map((_expression, idx) => {
|
|
790
|
-
const prevExpression = this.expressions[idx];
|
|
791
|
-
if (prevExpression.kind !== _expression.kind) {
|
|
792
|
-
prevExpression.dispose();
|
|
793
|
-
this.fireChange();
|
|
794
|
-
return this.createChildNode(_expression);
|
|
795
|
-
}
|
|
796
|
-
prevExpression.fromJSON(_expression);
|
|
797
|
-
return prevExpression;
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
toJSON() {
|
|
801
|
-
return {
|
|
802
|
-
kind: "ExpressionList" /* ExpressionList */,
|
|
803
|
-
properties: this.expressions.map((_expression) => _expression.toJSON())
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
ExpressionList.kind = "ExpressionList" /* ExpressionList */;
|
|
808
|
-
|
|
809
|
-
// src/ast/expression/keypath-expression.ts
|
|
810
|
-
import { shallowEqual as shallowEqual3 } from "fast-equals";
|
|
811
|
-
var KeyPathExpression = class extends BaseExpression {
|
|
812
|
-
constructor(params, opts) {
|
|
813
|
-
super(params, opts);
|
|
814
|
-
this._keyPath = [];
|
|
815
|
-
this.toDispose.pushAll([
|
|
816
|
-
// 可以用变量列表变化时候 (有新增或者删除时)
|
|
817
|
-
this.scope.available.onVariableListChange(() => {
|
|
818
|
-
this.refreshRefs();
|
|
819
|
-
}),
|
|
820
|
-
// this._keyPath 指向的可引用变量发生变化时,刷新引用数据
|
|
821
|
-
this.scope.available.onAnyVariableChange((_v) => {
|
|
822
|
-
if (_v.key === this._keyPath[0]) {
|
|
823
|
-
this.refreshRefs();
|
|
824
|
-
}
|
|
825
|
-
})
|
|
826
|
-
]);
|
|
827
|
-
}
|
|
828
|
-
get keyPath() {
|
|
829
|
-
return this._keyPath;
|
|
830
|
-
}
|
|
831
|
-
getRefFields() {
|
|
832
|
-
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
833
|
-
return ref ? [ref] : [];
|
|
834
|
-
}
|
|
835
|
-
get returnType() {
|
|
836
|
-
const [refNode] = this._refs || [];
|
|
837
|
-
if (refNode && refNode.flags & 1 /* VariableField */) {
|
|
838
|
-
return refNode.type;
|
|
839
|
-
}
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
/**
|
|
843
|
-
* 业务重改该方法可快速定制自己的 Path 表达式
|
|
844
|
-
* - 只需要将业务的 Path 解析为变量系统的 KeyPath 即可
|
|
845
|
-
* @param json 业务定义的 Path 表达式
|
|
846
|
-
* @returns
|
|
847
|
-
*/
|
|
848
|
-
parseToKeyPath(json) {
|
|
849
|
-
return json.keyPath;
|
|
850
|
-
}
|
|
851
|
-
fromJSON(json) {
|
|
852
|
-
const keyPath = this.parseToKeyPath(json);
|
|
853
|
-
if (!shallowEqual3(keyPath, this._keyPath)) {
|
|
854
|
-
this._keyPath = keyPath;
|
|
855
|
-
this.refreshRefs();
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
toJSON() {
|
|
859
|
-
return {
|
|
860
|
-
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
861
|
-
keyPath: this._keyPath
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
};
|
|
865
|
-
KeyPathExpression.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
866
|
-
|
|
867
1079
|
// src/ast/expression/enumerate-expression.ts
|
|
868
1080
|
var EnumerateExpression = class extends BaseExpression {
|
|
1081
|
+
/**
|
|
1082
|
+
* The expression to be enumerated.
|
|
1083
|
+
*/
|
|
869
1084
|
get enumerateFor() {
|
|
870
1085
|
return this._enumerateFor;
|
|
871
1086
|
}
|
|
1087
|
+
/**
|
|
1088
|
+
* The return type of the expression.
|
|
1089
|
+
*/
|
|
872
1090
|
get returnType() {
|
|
873
1091
|
const childReturnType = this.enumerateFor?.returnType;
|
|
874
1092
|
if (childReturnType?.kind === "Array" /* Array */) {
|
|
@@ -876,12 +1094,24 @@ var EnumerateExpression = class extends BaseExpression {
|
|
|
876
1094
|
}
|
|
877
1095
|
return void 0;
|
|
878
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
|
+
*/
|
|
879
1101
|
getRefFields() {
|
|
880
1102
|
return [];
|
|
881
1103
|
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Deserializes the `EnumerateExpressionJSON` to the `EnumerateExpression`.
|
|
1106
|
+
* @param json The `EnumerateExpressionJSON` to deserialize.
|
|
1107
|
+
*/
|
|
882
1108
|
fromJSON({ enumerateFor: expression }) {
|
|
883
1109
|
this.updateChildNodeByKey("_enumerateFor", expression);
|
|
884
1110
|
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Serialize the `EnumerateExpression` to `EnumerateExpressionJSON`.
|
|
1113
|
+
* @returns The JSON representation of `EnumerateExpression`.
|
|
1114
|
+
*/
|
|
885
1115
|
toJSON() {
|
|
886
1116
|
return {
|
|
887
1117
|
kind: "EnumerateExpression" /* EnumerateExpression */,
|
|
@@ -891,11 +1121,12 @@ var EnumerateExpression = class extends BaseExpression {
|
|
|
891
1121
|
};
|
|
892
1122
|
EnumerateExpression.kind = "EnumerateExpression" /* EnumerateExpression */;
|
|
893
1123
|
|
|
894
|
-
// src/ast/expression/keypath-expression
|
|
895
|
-
import {
|
|
1124
|
+
// src/ast/expression/keypath-expression.ts
|
|
1125
|
+
import { distinctUntilChanged as distinctUntilChanged3 } from "rxjs";
|
|
1126
|
+
import { shallowEqual as shallowEqual3 } from "fast-equals";
|
|
896
1127
|
|
|
897
1128
|
// src/ast/utils/expression.ts
|
|
898
|
-
import { intersection } from "lodash";
|
|
1129
|
+
import { intersection } from "lodash-es";
|
|
899
1130
|
function getAllRefs(ast) {
|
|
900
1131
|
return getAllChildren(ast).filter((_child) => _child.flags & 4 /* Expression */).map((_child) => _child.refs).flat().filter(Boolean);
|
|
901
1132
|
}
|
|
@@ -915,36 +1146,45 @@ function checkRefCycle(curr, refNodes) {
|
|
|
915
1146
|
return intersection(Array.from(visited), getParentFields(curr)).length > 0;
|
|
916
1147
|
}
|
|
917
1148
|
|
|
918
|
-
// src/ast/expression/keypath-expression
|
|
919
|
-
var
|
|
1149
|
+
// src/ast/expression/keypath-expression.ts
|
|
1150
|
+
var KeyPathExpression = class extends BaseExpression {
|
|
920
1151
|
constructor(params, opts) {
|
|
921
1152
|
super(params, opts);
|
|
922
1153
|
this._keyPath = [];
|
|
923
1154
|
this.toDispose.pushAll([
|
|
924
|
-
//
|
|
1155
|
+
// Can be used when the variable list changes (when there are additions or deletions).
|
|
925
1156
|
this.scope.available.onVariableListChange(() => {
|
|
926
1157
|
this.refreshRefs();
|
|
927
1158
|
}),
|
|
928
|
-
// this._keyPath
|
|
1159
|
+
// When the referable variable pointed to by this._keyPath changes, refresh the reference data.
|
|
929
1160
|
this.scope.available.onAnyVariableChange((_v) => {
|
|
930
1161
|
if (_v.key === this._keyPath[0]) {
|
|
931
1162
|
this.refreshRefs();
|
|
932
1163
|
}
|
|
933
1164
|
}),
|
|
934
1165
|
subsToDisposable(
|
|
935
|
-
this.refs$.
|
|
1166
|
+
this.refs$.pipe(
|
|
1167
|
+
distinctUntilChanged3(
|
|
1168
|
+
(prev, next) => prev === next,
|
|
1169
|
+
(_refs) => _refs?.[0]?.type?.hash
|
|
1170
|
+
)
|
|
1171
|
+
).subscribe((_type) => {
|
|
936
1172
|
const [ref] = this._refs;
|
|
937
|
-
|
|
938
|
-
this.prevRefTypeHash = ref?.type?.hash;
|
|
939
|
-
this.updateChildNodeByKey("_returnType", this.getReturnTypeJSONByRef(ref));
|
|
940
|
-
}
|
|
1173
|
+
this.updateChildNodeByKey("_returnType", this.getReturnTypeJSONByRef(ref));
|
|
941
1174
|
})
|
|
942
1175
|
)
|
|
943
1176
|
]);
|
|
944
1177
|
}
|
|
1178
|
+
/**
|
|
1179
|
+
* The key path of the variable.
|
|
1180
|
+
*/
|
|
945
1181
|
get keyPath() {
|
|
946
1182
|
return this._keyPath;
|
|
947
1183
|
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Get the variable fields referenced by the expression.
|
|
1186
|
+
* @returns An array of referenced variable fields.
|
|
1187
|
+
*/
|
|
948
1188
|
getRefFields() {
|
|
949
1189
|
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
950
1190
|
if (checkRefCycle(this, [ref])) {
|
|
@@ -956,39 +1196,189 @@ var KeyPathExpressionV2 = class extends BaseExpression {
|
|
|
956
1196
|
}
|
|
957
1197
|
return ref ? [ref] : [];
|
|
958
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* The return type of the expression.
|
|
1201
|
+
*/
|
|
959
1202
|
get returnType() {
|
|
960
1203
|
return this._returnType;
|
|
961
1204
|
}
|
|
962
1205
|
/**
|
|
963
|
-
*
|
|
964
|
-
*
|
|
965
|
-
*
|
|
966
|
-
* @
|
|
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.
|
|
967
1211
|
*/
|
|
968
1212
|
parseToKeyPath(json) {
|
|
969
1213
|
return json.keyPath;
|
|
970
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Deserializes the `KeyPathExpressionJSON` to the `KeyPathExpression`.
|
|
1217
|
+
* @param json The `KeyPathExpressionJSON` to deserialize.
|
|
1218
|
+
*/
|
|
971
1219
|
fromJSON(json) {
|
|
972
1220
|
const keyPath = this.parseToKeyPath(json);
|
|
973
|
-
if (!
|
|
1221
|
+
if (!shallowEqual3(keyPath, this._keyPath)) {
|
|
974
1222
|
this._keyPath = keyPath;
|
|
1223
|
+
this._rawPathJson = json;
|
|
975
1224
|
this.refreshRefs();
|
|
976
1225
|
}
|
|
977
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
|
+
*/
|
|
978
1232
|
getReturnTypeJSONByRef(_ref) {
|
|
979
1233
|
return _ref?.type?.toJSON();
|
|
980
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
|
+
*/
|
|
981
1362
|
toJSON() {
|
|
982
1363
|
return {
|
|
983
|
-
kind: "
|
|
984
|
-
|
|
1364
|
+
kind: "WrapArrayExpression" /* WrapArrayExpression */,
|
|
1365
|
+
wrapFor: this.wrapFor?.toJSON()
|
|
985
1366
|
};
|
|
986
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
|
+
}
|
|
987
1377
|
};
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1378
|
+
WrapArrayExpression.kind = "WrapArrayExpression" /* WrapArrayExpression */;
|
|
1379
|
+
__decorateClass([
|
|
1380
|
+
postConstructAST()
|
|
1381
|
+
], WrapArrayExpression.prototype, "init", 1);
|
|
992
1382
|
|
|
993
1383
|
// src/ast/declaration/base-variable-field.ts
|
|
994
1384
|
import { shallowEqual as shallowEqual5 } from "fast-equals";
|
|
@@ -999,35 +1389,73 @@ var BaseVariableField = class extends ASTNode {
|
|
|
999
1389
|
this._meta = {};
|
|
1000
1390
|
}
|
|
1001
1391
|
/**
|
|
1002
|
-
*
|
|
1392
|
+
* Parent variable fields, sorted from closest to farthest
|
|
1003
1393
|
*/
|
|
1004
1394
|
get parentFields() {
|
|
1005
1395
|
return getParentFields(this);
|
|
1006
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
|
+
*/
|
|
1007
1406
|
get meta() {
|
|
1008
1407
|
return this._meta;
|
|
1009
1408
|
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Type of the variable field, similar to js code:
|
|
1411
|
+
* `const v: string`
|
|
1412
|
+
*/
|
|
1010
1413
|
get type() {
|
|
1011
1414
|
return this._initializer?.returnType || this._type;
|
|
1012
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
|
+
*/
|
|
1013
1422
|
get initializer() {
|
|
1014
1423
|
return this._initializer;
|
|
1015
1424
|
}
|
|
1016
1425
|
/**
|
|
1017
|
-
*
|
|
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`
|
|
1018
1434
|
*/
|
|
1019
1435
|
fromJSON({ type, initializer, meta }) {
|
|
1020
1436
|
this.updateType(type);
|
|
1021
1437
|
this.updateInitializer(initializer);
|
|
1022
1438
|
this.updateMeta(meta);
|
|
1023
1439
|
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Update the type of the variable field
|
|
1442
|
+
* @param type type ASTJSON representation of Type
|
|
1443
|
+
*/
|
|
1024
1444
|
updateType(type) {
|
|
1025
1445
|
const nextTypeJson = typeof type === "string" ? { kind: type } : type;
|
|
1026
1446
|
this.updateChildNodeByKey("_type", nextTypeJson);
|
|
1027
1447
|
}
|
|
1448
|
+
/**
|
|
1449
|
+
* Update the initializer of the variable field
|
|
1450
|
+
* @param nextInitializer initializer ASTJSON representation of Expression
|
|
1451
|
+
*/
|
|
1028
1452
|
updateInitializer(nextInitializer) {
|
|
1029
1453
|
this.updateChildNodeByKey("_initializer", nextInitializer);
|
|
1030
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Update the meta data of the variable field
|
|
1457
|
+
* @param nextMeta meta data of the variable field
|
|
1458
|
+
*/
|
|
1031
1459
|
updateMeta(nextMeta) {
|
|
1032
1460
|
if (!shallowEqual5(nextMeta, this._meta)) {
|
|
1033
1461
|
this._meta = nextMeta;
|
|
@@ -1035,7 +1463,8 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1035
1463
|
}
|
|
1036
1464
|
}
|
|
1037
1465
|
/**
|
|
1038
|
-
*
|
|
1466
|
+
* Get the variable field by keyPath, similar to js code:
|
|
1467
|
+
* `v.a.b`
|
|
1039
1468
|
* @param keyPath
|
|
1040
1469
|
* @returns
|
|
1041
1470
|
*/
|
|
@@ -1046,7 +1475,7 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1046
1475
|
return void 0;
|
|
1047
1476
|
}
|
|
1048
1477
|
/**
|
|
1049
|
-
*
|
|
1478
|
+
* Subscribe to type change of the variable field
|
|
1050
1479
|
* @param observer
|
|
1051
1480
|
* @returns
|
|
1052
1481
|
*/
|
|
@@ -1054,12 +1483,11 @@ var BaseVariableField = class extends ASTNode {
|
|
|
1054
1483
|
return this.subscribe(observer, { selector: (curr) => curr.type });
|
|
1055
1484
|
}
|
|
1056
1485
|
/**
|
|
1057
|
-
*
|
|
1058
|
-
* @returns
|
|
1486
|
+
* Serialize the variable field to JSON
|
|
1487
|
+
* @returns ASTNodeJSON representation of `BaseVariableField`
|
|
1059
1488
|
*/
|
|
1060
1489
|
toJSON() {
|
|
1061
1490
|
return {
|
|
1062
|
-
kind: this.kind,
|
|
1063
1491
|
key: this.key,
|
|
1064
1492
|
type: this.type?.toJSON(),
|
|
1065
1493
|
initializer: this.initializer?.toJSON(),
|
|
@@ -1073,34 +1501,42 @@ var VariableDeclaration = class extends BaseVariableField {
|
|
|
1073
1501
|
constructor(params) {
|
|
1074
1502
|
super(params);
|
|
1075
1503
|
this._order = 0;
|
|
1076
|
-
this.scope.output.addVariableToTable(this);
|
|
1077
|
-
this.toDispose.push(
|
|
1078
|
-
Disposable3.create(() => {
|
|
1079
|
-
this.scope.output.setHasChanges();
|
|
1080
|
-
this.scope.output.removeVariableFromTable(this.key);
|
|
1081
|
-
})
|
|
1082
|
-
);
|
|
1083
1504
|
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Variable sorting order, which is used to sort variables in `scope.outputs.variables`
|
|
1507
|
+
*/
|
|
1084
1508
|
get order() {
|
|
1085
1509
|
return this._order;
|
|
1086
1510
|
}
|
|
1087
1511
|
/**
|
|
1088
|
-
*
|
|
1512
|
+
* Deserialize the `VariableDeclarationJSON` to the `VariableDeclaration`.
|
|
1089
1513
|
*/
|
|
1090
1514
|
fromJSON({ order, ...rest }) {
|
|
1091
1515
|
this.updateOrder(order);
|
|
1092
1516
|
super.fromJSON(rest);
|
|
1093
1517
|
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Update the sorting order of the variable declaration.
|
|
1520
|
+
* @param order Variable sorting order. Default is 0.
|
|
1521
|
+
*/
|
|
1094
1522
|
updateOrder(order = 0) {
|
|
1095
1523
|
if (order !== this._order) {
|
|
1096
1524
|
this._order = order;
|
|
1097
|
-
this.
|
|
1525
|
+
this.dispatchGlobalEvent({
|
|
1526
|
+
type: "ReSortVariableDeclarations"
|
|
1527
|
+
});
|
|
1098
1528
|
this.fireChange();
|
|
1099
1529
|
}
|
|
1100
1530
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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
|
+
};
|
|
1104
1540
|
}
|
|
1105
1541
|
};
|
|
1106
1542
|
VariableDeclaration.kind = "VariableDeclaration" /* VariableDeclaration */;
|
|
@@ -1109,8 +1545,18 @@ VariableDeclaration.kind = "VariableDeclaration" /* VariableDeclaration */;
|
|
|
1109
1545
|
var VariableDeclarationList = class extends ASTNode {
|
|
1110
1546
|
constructor() {
|
|
1111
1547
|
super(...arguments);
|
|
1548
|
+
/**
|
|
1549
|
+
* Map of variable declarations, keyed by variable name.
|
|
1550
|
+
*/
|
|
1112
1551
|
this.declarationTable = /* @__PURE__ */ new Map();
|
|
1113
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
|
+
*/
|
|
1114
1560
|
fromJSON({ declarations, startOrder }) {
|
|
1115
1561
|
const removedKeys = new Set(this.declarationTable.keys());
|
|
1116
1562
|
const prev = [...this.declarations || []];
|
|
@@ -1150,10 +1596,14 @@ var VariableDeclarationList = class extends ASTNode {
|
|
|
1150
1596
|
}
|
|
1151
1597
|
});
|
|
1152
1598
|
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Serialize the `VariableDeclarationList` to the `VariableDeclarationListJSON`.
|
|
1601
|
+
* @returns ASTJSON representation of `VariableDeclarationList`
|
|
1602
|
+
*/
|
|
1153
1603
|
toJSON() {
|
|
1154
1604
|
return {
|
|
1155
1605
|
kind: "VariableDeclarationList" /* VariableDeclarationList */,
|
|
1156
|
-
|
|
1606
|
+
declarations: this.declarations.map((_declaration) => _declaration.toJSON())
|
|
1157
1607
|
};
|
|
1158
1608
|
}
|
|
1159
1609
|
};
|
|
@@ -1167,9 +1617,16 @@ Property.kind = "Property" /* Property */;
|
|
|
1167
1617
|
// src/ast/common/data-node.ts
|
|
1168
1618
|
import { shallowEqual as shallowEqual6 } from "fast-equals";
|
|
1169
1619
|
var DataNode = class extends ASTNode {
|
|
1620
|
+
/**
|
|
1621
|
+
* The data of the node.
|
|
1622
|
+
*/
|
|
1170
1623
|
get data() {
|
|
1171
1624
|
return this._data;
|
|
1172
1625
|
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Deserializes the `DataNodeJSON` to the `DataNode`.
|
|
1628
|
+
* @param json The `DataNodeJSON` to deserialize.
|
|
1629
|
+
*/
|
|
1173
1630
|
fromJSON(json) {
|
|
1174
1631
|
const { kind, ...restData } = json;
|
|
1175
1632
|
if (!shallowEqual6(restData, this._data)) {
|
|
@@ -1177,12 +1634,20 @@ var DataNode = class extends ASTNode {
|
|
|
1177
1634
|
this.fireChange();
|
|
1178
1635
|
}
|
|
1179
1636
|
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Serialize the `DataNode` to `DataNodeJSON`.
|
|
1639
|
+
* @returns The JSON representation of `DataNode`.
|
|
1640
|
+
*/
|
|
1180
1641
|
toJSON() {
|
|
1181
1642
|
return {
|
|
1182
1643
|
kind: "DataNode" /* DataNode */,
|
|
1183
1644
|
...this._data
|
|
1184
1645
|
};
|
|
1185
1646
|
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Partially update the data of the node.
|
|
1649
|
+
* @param nextData The data to be updated.
|
|
1650
|
+
*/
|
|
1186
1651
|
partialUpdate(nextData) {
|
|
1187
1652
|
if (!shallowEqual6(nextData, this._data)) {
|
|
1188
1653
|
this._data = {
|
|
@@ -1197,9 +1662,16 @@ DataNode.kind = "DataNode" /* DataNode */;
|
|
|
1197
1662
|
|
|
1198
1663
|
// src/ast/common/list-node.ts
|
|
1199
1664
|
var ListNode = class extends ASTNode {
|
|
1665
|
+
/**
|
|
1666
|
+
* The list of nodes.
|
|
1667
|
+
*/
|
|
1200
1668
|
get list() {
|
|
1201
1669
|
return this._list;
|
|
1202
1670
|
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Deserializes the `ListNodeJSON` to the `ListNode`.
|
|
1673
|
+
* @param json The `ListNodeJSON` to deserialize.
|
|
1674
|
+
*/
|
|
1203
1675
|
fromJSON({ list }) {
|
|
1204
1676
|
this._list.slice(list.length).forEach((_item) => {
|
|
1205
1677
|
_item.dispose();
|
|
@@ -1216,6 +1688,10 @@ var ListNode = class extends ASTNode {
|
|
|
1216
1688
|
return prevItem;
|
|
1217
1689
|
});
|
|
1218
1690
|
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Serialize the `ListNode` to `ListNodeJSON`.
|
|
1693
|
+
* @returns The JSON representation of `ListNode`.
|
|
1694
|
+
*/
|
|
1219
1695
|
toJSON() {
|
|
1220
1696
|
return {
|
|
1221
1697
|
kind: "ListNode" /* ListNode */,
|
|
@@ -1231,6 +1707,10 @@ var MapNode = class extends ASTNode {
|
|
|
1231
1707
|
super(...arguments);
|
|
1232
1708
|
this.map = /* @__PURE__ */ new Map();
|
|
1233
1709
|
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Deserializes the `MapNodeJSON` to the `MapNode`.
|
|
1712
|
+
* @param json The `MapNodeJSON` to deserialize.
|
|
1713
|
+
*/
|
|
1234
1714
|
fromJSON({ map: map4 }) {
|
|
1235
1715
|
const removedKeys = new Set(this.map.keys());
|
|
1236
1716
|
for (const [key, item] of map4 || []) {
|
|
@@ -1241,6 +1721,10 @@ var MapNode = class extends ASTNode {
|
|
|
1241
1721
|
this.remove(removeKey);
|
|
1242
1722
|
}
|
|
1243
1723
|
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Serialize the `MapNode` to `MapNodeJSON`.
|
|
1726
|
+
* @returns The JSON representation of `MapNode`.
|
|
1727
|
+
*/
|
|
1244
1728
|
toJSON() {
|
|
1245
1729
|
return {
|
|
1246
1730
|
kind: "MapNode" /* MapNode */,
|
|
@@ -1248,9 +1732,10 @@ var MapNode = class extends ASTNode {
|
|
|
1248
1732
|
};
|
|
1249
1733
|
}
|
|
1250
1734
|
/**
|
|
1251
|
-
*
|
|
1252
|
-
* @param key
|
|
1253
|
-
* @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.
|
|
1254
1739
|
*/
|
|
1255
1740
|
set(key, nextJSON) {
|
|
1256
1741
|
return this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
@@ -1261,8 +1746,8 @@ var MapNode = class extends ASTNode {
|
|
|
1261
1746
|
});
|
|
1262
1747
|
}
|
|
1263
1748
|
/**
|
|
1264
|
-
*
|
|
1265
|
-
* @param key
|
|
1749
|
+
* Remove a node from the map.
|
|
1750
|
+
* @param key The key of the node.
|
|
1266
1751
|
*/
|
|
1267
1752
|
remove(key) {
|
|
1268
1753
|
this.get(key)?.dispose();
|
|
@@ -1270,9 +1755,9 @@ var MapNode = class extends ASTNode {
|
|
|
1270
1755
|
this.fireChange();
|
|
1271
1756
|
}
|
|
1272
1757
|
/**
|
|
1273
|
-
*
|
|
1274
|
-
* @param key
|
|
1275
|
-
* @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`.
|
|
1276
1761
|
*/
|
|
1277
1762
|
get(key) {
|
|
1278
1763
|
return this.map.get(key);
|
|
@@ -1283,9 +1768,12 @@ MapNode.kind = "MapNode" /* MapNode */;
|
|
|
1283
1768
|
// src/ast/ast-registers.ts
|
|
1284
1769
|
var ASTRegisters = class {
|
|
1285
1770
|
/**
|
|
1286
|
-
*
|
|
1771
|
+
* Core AST node registration.
|
|
1287
1772
|
*/
|
|
1288
1773
|
constructor() {
|
|
1774
|
+
/**
|
|
1775
|
+
* @deprecated Please use `@injectToAst(XXXService) declare xxxService: XXXService` to achieve external dependency injection.
|
|
1776
|
+
*/
|
|
1289
1777
|
this.injectors = /* @__PURE__ */ new Map();
|
|
1290
1778
|
this.astMap = /* @__PURE__ */ new Map();
|
|
1291
1779
|
this.registerAST(StringType);
|
|
@@ -1301,13 +1789,13 @@ var ASTRegisters = class {
|
|
|
1301
1789
|
this.registerAST(VariableDeclarationList);
|
|
1302
1790
|
this.registerAST(KeyPathExpression);
|
|
1303
1791
|
this.registerAST(EnumerateExpression);
|
|
1304
|
-
this.registerAST(
|
|
1792
|
+
this.registerAST(WrapArrayExpression);
|
|
1305
1793
|
this.registerAST(MapNode);
|
|
1306
1794
|
this.registerAST(DataNode);
|
|
1307
1795
|
}
|
|
1308
1796
|
/**
|
|
1309
|
-
*
|
|
1310
|
-
* @param param
|
|
1797
|
+
* Creates an AST node.
|
|
1798
|
+
* @param param Creation parameters.
|
|
1311
1799
|
* @returns
|
|
1312
1800
|
*/
|
|
1313
1801
|
createAST(json, { parent, scope }) {
|
|
@@ -1327,6 +1815,7 @@ var ASTRegisters = class {
|
|
|
1327
1815
|
node.changeLocked = true;
|
|
1328
1816
|
node.fromJSON(omit(json, ["key", "kind"]));
|
|
1329
1817
|
node.changeLocked = false;
|
|
1818
|
+
node.dispatchGlobalEvent({ type: "NewAST" });
|
|
1330
1819
|
if (Reflect.hasMetadata(POST_CONSTRUCT_AST_SYMBOL, node)) {
|
|
1331
1820
|
const postConstructKey = Reflect.getMetadata(POST_CONSTRUCT_AST_SYMBOL, node);
|
|
1332
1821
|
node[postConstructKey]?.();
|
|
@@ -1334,7 +1823,7 @@ var ASTRegisters = class {
|
|
|
1334
1823
|
return node;
|
|
1335
1824
|
}
|
|
1336
1825
|
/**
|
|
1337
|
-
*
|
|
1826
|
+
* Gets the node Registry by AST node type.
|
|
1338
1827
|
* @param kind
|
|
1339
1828
|
* @returns
|
|
1340
1829
|
*/
|
|
@@ -1342,9 +1831,8 @@ var ASTRegisters = class {
|
|
|
1342
1831
|
return this.astMap.get(kind);
|
|
1343
1832
|
}
|
|
1344
1833
|
/**
|
|
1345
|
-
*
|
|
1834
|
+
* Registers an AST node.
|
|
1346
1835
|
* @param ASTNode
|
|
1347
|
-
* @param injector
|
|
1348
1836
|
*/
|
|
1349
1837
|
registerAST(ASTNode2, injector) {
|
|
1350
1838
|
this.astMap.set(ASTNode2.kind, ASTNode2);
|
|
@@ -1360,7 +1848,10 @@ ASTRegisters = __decorateClass([
|
|
|
1360
1848
|
// src/ast/factory.ts
|
|
1361
1849
|
var ASTFactory;
|
|
1362
1850
|
((ASTFactory2) => {
|
|
1363
|
-
ASTFactory2.createString = () => ({
|
|
1851
|
+
ASTFactory2.createString = (json) => ({
|
|
1852
|
+
kind: "String" /* String */,
|
|
1853
|
+
...json || {}
|
|
1854
|
+
});
|
|
1364
1855
|
ASTFactory2.createNumber = () => ({ kind: "Number" /* Number */ });
|
|
1365
1856
|
ASTFactory2.createBoolean = () => ({ kind: "Boolean" /* Boolean */ });
|
|
1366
1857
|
ASTFactory2.createInteger = () => ({ kind: "Integer" /* Integer */ });
|
|
@@ -1404,116 +1895,13 @@ var ASTFactory;
|
|
|
1404
1895
|
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
1405
1896
|
...json
|
|
1406
1897
|
});
|
|
1898
|
+
ASTFactory2.createWrapArrayExpression = (json) => ({
|
|
1899
|
+
kind: "WrapArrayExpression" /* WrapArrayExpression */,
|
|
1900
|
+
...json
|
|
1901
|
+
});
|
|
1407
1902
|
ASTFactory2.create = (targetType, json) => ({ kind: targetType.kind, ...json });
|
|
1408
1903
|
})(ASTFactory || (ASTFactory = {}));
|
|
1409
1904
|
|
|
1410
|
-
// src/scope/variable-table.ts
|
|
1411
|
-
import { Subject as Subject2, merge, share as share2, skip as skip2, switchMap as switchMap2 } from "rxjs";
|
|
1412
|
-
import { Emitter } from "@flowgram.ai/utils";
|
|
1413
|
-
import { DisposableCollection as DisposableCollection3 } from "@flowgram.ai/utils";
|
|
1414
|
-
var VariableTable = class {
|
|
1415
|
-
constructor(parentTable) {
|
|
1416
|
-
this.parentTable = parentTable;
|
|
1417
|
-
this.table = /* @__PURE__ */ new Map();
|
|
1418
|
-
this.onDataChangeEmitter = new Emitter();
|
|
1419
|
-
this.variables$ = new Subject2();
|
|
1420
|
-
// 监听变量列表中的单个变量变化
|
|
1421
|
-
this.anyVariableChange$ = this.variables$.pipe(
|
|
1422
|
-
switchMap2(
|
|
1423
|
-
(_variables) => merge(
|
|
1424
|
-
..._variables.map(
|
|
1425
|
-
(_v) => _v.value$.pipe(
|
|
1426
|
-
// 跳过 BehaviorSubject 第一个
|
|
1427
|
-
skip2(1)
|
|
1428
|
-
)
|
|
1429
|
-
)
|
|
1430
|
-
)
|
|
1431
|
-
),
|
|
1432
|
-
share2()
|
|
1433
|
-
);
|
|
1434
|
-
this.onDataChange = this.onDataChangeEmitter.event;
|
|
1435
|
-
this._version = 0;
|
|
1436
|
-
}
|
|
1437
|
-
/**
|
|
1438
|
-
* 监听任意变量变化
|
|
1439
|
-
* @param observer 监听器,变量变化时会吐出值
|
|
1440
|
-
* @returns
|
|
1441
|
-
*/
|
|
1442
|
-
onAnyVariableChange(observer) {
|
|
1443
|
-
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1444
|
-
}
|
|
1445
|
-
/**
|
|
1446
|
-
* 列表或者任意变量变化
|
|
1447
|
-
* @param observer
|
|
1448
|
-
*/
|
|
1449
|
-
onAnyChange(observer) {
|
|
1450
|
-
const disposables = new DisposableCollection3();
|
|
1451
|
-
disposables.pushAll([this.onDataChange(observer), this.onAnyVariableChange(observer)]);
|
|
1452
|
-
return disposables;
|
|
1453
|
-
}
|
|
1454
|
-
fireChange() {
|
|
1455
|
-
this._version++;
|
|
1456
|
-
this.onDataChangeEmitter.fire();
|
|
1457
|
-
this.parentTable?.fireChange();
|
|
1458
|
-
}
|
|
1459
|
-
get version() {
|
|
1460
|
-
return this._version;
|
|
1461
|
-
}
|
|
1462
|
-
get variables() {
|
|
1463
|
-
return Array.from(this.table.values());
|
|
1464
|
-
}
|
|
1465
|
-
get variableKeys() {
|
|
1466
|
-
return Array.from(this.table.keys());
|
|
1467
|
-
}
|
|
1468
|
-
/**
|
|
1469
|
-
* 根据 keyPath 找到对应的变量,或 Property 节点
|
|
1470
|
-
* @param keyPath
|
|
1471
|
-
* @returns
|
|
1472
|
-
*/
|
|
1473
|
-
getByKeyPath(keyPath) {
|
|
1474
|
-
const [variableKey, ...propertyKeys] = keyPath || [];
|
|
1475
|
-
if (!variableKey) {
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1478
|
-
const variable = this.getVariableByKey(variableKey);
|
|
1479
|
-
return propertyKeys.length ? variable?.getByKeyPath(propertyKeys) : variable;
|
|
1480
|
-
}
|
|
1481
|
-
/**
|
|
1482
|
-
* 根据 key 值找到相应的变量
|
|
1483
|
-
* @param key
|
|
1484
|
-
* @returns
|
|
1485
|
-
*/
|
|
1486
|
-
getVariableByKey(key) {
|
|
1487
|
-
return this.table.get(key);
|
|
1488
|
-
}
|
|
1489
|
-
/**
|
|
1490
|
-
* 往 variableTable 添加输出变量
|
|
1491
|
-
* @param variable
|
|
1492
|
-
*/
|
|
1493
|
-
addVariableToTable(variable) {
|
|
1494
|
-
this.table.set(variable.key, variable);
|
|
1495
|
-
if (this.parentTable) {
|
|
1496
|
-
this.parentTable.addVariableToTable(variable);
|
|
1497
|
-
}
|
|
1498
|
-
this.variables$.next(this.variables);
|
|
1499
|
-
}
|
|
1500
|
-
/**
|
|
1501
|
-
* 从 variableTable 中移除变量
|
|
1502
|
-
* @param key
|
|
1503
|
-
*/
|
|
1504
|
-
removeVariableFromTable(key) {
|
|
1505
|
-
this.table.delete(key);
|
|
1506
|
-
if (this.parentTable) {
|
|
1507
|
-
this.parentTable.removeVariableFromTable(key);
|
|
1508
|
-
}
|
|
1509
|
-
this.variables$.next(this.variables);
|
|
1510
|
-
}
|
|
1511
|
-
dispose() {
|
|
1512
|
-
this.variableKeys.forEach((_key) => this.parentTable?.removeVariableFromTable(_key));
|
|
1513
|
-
this.onDataChangeEmitter.dispose();
|
|
1514
|
-
}
|
|
1515
|
-
};
|
|
1516
|
-
|
|
1517
1905
|
// src/scope/datas/scope-output-data.ts
|
|
1518
1906
|
var ScopeOutputData = class {
|
|
1519
1907
|
constructor(scope) {
|
|
@@ -1522,7 +1910,7 @@ var ScopeOutputData = class {
|
|
|
1522
1910
|
this._hasChanges = false;
|
|
1523
1911
|
this.variableTable = new VariableTable(scope.variableEngine.globalVariableTable);
|
|
1524
1912
|
this.scope.toDispose.pushAll([
|
|
1525
|
-
//
|
|
1913
|
+
// When the root AST node is updated, check if there are any changes.
|
|
1526
1914
|
this.scope.ast.subscribe(() => {
|
|
1527
1915
|
if (this._hasChanges) {
|
|
1528
1916
|
this.memo.clear();
|
|
@@ -1531,23 +1919,66 @@ var ScopeOutputData = class {
|
|
|
1531
1919
|
this._hasChanges = false;
|
|
1532
1920
|
}
|
|
1533
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
|
+
}),
|
|
1534
1935
|
this.variableTable
|
|
1535
1936
|
]);
|
|
1536
1937
|
}
|
|
1938
|
+
/**
|
|
1939
|
+
* The variable engine instance.
|
|
1940
|
+
*/
|
|
1537
1941
|
get variableEngine() {
|
|
1538
1942
|
return this.scope.variableEngine;
|
|
1539
1943
|
}
|
|
1944
|
+
/**
|
|
1945
|
+
* The global variable table from the variable engine.
|
|
1946
|
+
*/
|
|
1540
1947
|
get globalVariableTable() {
|
|
1541
1948
|
return this.scope.variableEngine.globalVariableTable;
|
|
1542
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
|
+
*/
|
|
1543
1959
|
get onDataChange() {
|
|
1544
1960
|
return this.variableTable.onDataChange.bind(this.variableTable);
|
|
1545
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
|
+
*/
|
|
1546
1971
|
get onAnyVariableChange() {
|
|
1547
1972
|
return this.variableTable.onAnyVariableChange.bind(this.variableTable);
|
|
1548
1973
|
}
|
|
1549
1974
|
/**
|
|
1550
|
-
*
|
|
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.
|
|
1551
1982
|
*/
|
|
1552
1983
|
get variables() {
|
|
1553
1984
|
return this.memo(
|
|
@@ -1556,7 +1987,7 @@ var ScopeOutputData = class {
|
|
|
1556
1987
|
);
|
|
1557
1988
|
}
|
|
1558
1989
|
/**
|
|
1559
|
-
*
|
|
1990
|
+
* The keys of the output variables.
|
|
1560
1991
|
*/
|
|
1561
1992
|
get variableKeys() {
|
|
1562
1993
|
return this.memo("variableKeys", () => this.variableTable.variableKeys);
|
|
@@ -1568,18 +1999,21 @@ var ScopeOutputData = class {
|
|
|
1568
1999
|
this.variableTable.addVariableToTable(variable);
|
|
1569
2000
|
this._hasChanges = true;
|
|
1570
2001
|
}
|
|
1571
|
-
// 标记为发生了变化,用于变量排序变化的场景
|
|
1572
|
-
setHasChanges() {
|
|
1573
|
-
this._hasChanges = true;
|
|
1574
|
-
}
|
|
1575
2002
|
removeVariableFromTable(key) {
|
|
1576
2003
|
this.variableTable.removeVariableFromTable(key);
|
|
1577
2004
|
this._hasChanges = true;
|
|
1578
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
|
+
*/
|
|
1579
2011
|
getVariableByKey(key) {
|
|
1580
2012
|
return this.variableTable.getVariableByKey(key);
|
|
1581
2013
|
}
|
|
1582
|
-
|
|
2014
|
+
/**
|
|
2015
|
+
* Notifies the covering scopes that the available variables have changed.
|
|
2016
|
+
*/
|
|
1583
2017
|
notifyCoversChange() {
|
|
1584
2018
|
this.scope.coverScopes.forEach((scope) => scope.available.refresh());
|
|
1585
2019
|
}
|
|
@@ -1588,40 +2022,47 @@ var ScopeOutputData = class {
|
|
|
1588
2022
|
// src/scope/datas/scope-available-data.ts
|
|
1589
2023
|
import {
|
|
1590
2024
|
Subject as Subject3,
|
|
1591
|
-
|
|
2025
|
+
animationFrameScheduler as animationFrameScheduler2,
|
|
2026
|
+
debounceTime as debounceTime2,
|
|
2027
|
+
distinctUntilChanged as distinctUntilChanged4,
|
|
1592
2028
|
map as map3,
|
|
1593
2029
|
merge as merge2,
|
|
1594
2030
|
share as share3,
|
|
1595
2031
|
skip as skip3,
|
|
1596
|
-
|
|
2032
|
+
startWith,
|
|
2033
|
+
switchMap as switchMap3,
|
|
2034
|
+
tap as tap2
|
|
1597
2035
|
} from "rxjs";
|
|
1598
|
-
import { flatten } from "lodash";
|
|
2036
|
+
import { flatten } from "lodash-es";
|
|
1599
2037
|
import { shallowEqual as shallowEqual7 } from "fast-equals";
|
|
1600
|
-
import { Disposable as
|
|
2038
|
+
import { Disposable as Disposable3 } from "@flowgram.ai/utils";
|
|
1601
2039
|
import { Emitter as Emitter2 } from "@flowgram.ai/utils";
|
|
1602
2040
|
var ScopeAvailableData = class {
|
|
1603
2041
|
constructor(scope) {
|
|
1604
2042
|
this.scope = scope;
|
|
1605
2043
|
this.memo = createMemo();
|
|
2044
|
+
this._version = 0;
|
|
1606
2045
|
this.refresh$ = new Subject3();
|
|
1607
2046
|
this._variables = [];
|
|
1608
2047
|
/**
|
|
1609
|
-
*
|
|
2048
|
+
* An observable that emits when the list of available variables changes.
|
|
1610
2049
|
*/
|
|
1611
2050
|
this.variables$ = this.refresh$.pipe(
|
|
1612
|
-
//
|
|
2051
|
+
// Map to the flattened list of variables from all dependency scopes.
|
|
1613
2052
|
map3(() => flatten(this.depScopes.map((scope) => scope.output.variables || []))),
|
|
1614
|
-
//
|
|
1615
|
-
|
|
2053
|
+
// Use shallow equality to check if the variable list has changed.
|
|
2054
|
+
distinctUntilChanged4(shallowEqual7),
|
|
1616
2055
|
share3()
|
|
1617
2056
|
);
|
|
1618
|
-
|
|
2057
|
+
/**
|
|
2058
|
+
* An observable that emits when any variable in the available list changes its value.
|
|
2059
|
+
*/
|
|
1619
2060
|
this.anyVariableChange$ = this.variables$.pipe(
|
|
1620
2061
|
switchMap3(
|
|
1621
2062
|
(_variables) => merge2(
|
|
1622
2063
|
..._variables.map(
|
|
1623
2064
|
(_v) => _v.value$.pipe(
|
|
1624
|
-
//
|
|
2065
|
+
// Skip the initial value of the BehaviorSubject.
|
|
1625
2066
|
skip3(1)
|
|
1626
2067
|
)
|
|
1627
2068
|
)
|
|
@@ -1629,30 +2070,60 @@ var ScopeAvailableData = class {
|
|
|
1629
2070
|
),
|
|
1630
2071
|
share3()
|
|
1631
2072
|
);
|
|
2073
|
+
/**
|
|
2074
|
+
* @deprecated
|
|
2075
|
+
*/
|
|
1632
2076
|
this.onDataChangeEmitter = new Emitter2();
|
|
2077
|
+
this.onListOrAnyVarChangeEmitter = new Emitter2();
|
|
1633
2078
|
/**
|
|
1634
|
-
*
|
|
2079
|
+
* @deprecated use available.onListOrAnyVarChange instead
|
|
1635
2080
|
*/
|
|
1636
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;
|
|
1637
2086
|
this.scope.toDispose.pushAll([
|
|
1638
2087
|
this.onVariableListChange((_variables) => {
|
|
1639
2088
|
this._variables = _variables;
|
|
1640
2089
|
this.memo.clear();
|
|
1641
2090
|
this.onDataChangeEmitter.fire(this._variables);
|
|
2091
|
+
this.bumpVersion();
|
|
2092
|
+
this.onListOrAnyVarChangeEmitter.fire(this._variables);
|
|
1642
2093
|
}),
|
|
1643
2094
|
this.onAnyVariableChange(() => {
|
|
1644
2095
|
this.onDataChangeEmitter.fire(this._variables);
|
|
2096
|
+
this.bumpVersion();
|
|
2097
|
+
this.onListOrAnyVarChangeEmitter.fire(this._variables);
|
|
1645
2098
|
}),
|
|
1646
|
-
|
|
2099
|
+
Disposable3.create(() => {
|
|
1647
2100
|
this.refresh$.complete();
|
|
1648
2101
|
this.refresh$.unsubscribe();
|
|
1649
2102
|
})
|
|
1650
2103
|
]);
|
|
1651
2104
|
}
|
|
2105
|
+
/**
|
|
2106
|
+
* The global variable table from the variable engine.
|
|
2107
|
+
*/
|
|
1652
2108
|
get globalVariableTable() {
|
|
1653
2109
|
return this.scope.variableEngine.globalVariableTable;
|
|
1654
2110
|
}
|
|
1655
|
-
|
|
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
|
+
*/
|
|
1656
2127
|
refresh() {
|
|
1657
2128
|
if (this.scope.disposed) {
|
|
1658
2129
|
return;
|
|
@@ -1660,43 +2131,43 @@ var ScopeAvailableData = class {
|
|
|
1660
2131
|
this.refresh$.next();
|
|
1661
2132
|
}
|
|
1662
2133
|
/**
|
|
1663
|
-
*
|
|
1664
|
-
* @param observer
|
|
1665
|
-
* @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.
|
|
1666
2137
|
*/
|
|
1667
2138
|
onAnyVariableChange(observer) {
|
|
1668
2139
|
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1669
2140
|
}
|
|
1670
2141
|
/**
|
|
1671
|
-
*
|
|
1672
|
-
* @param observer
|
|
1673
|
-
* @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.
|
|
1674
2145
|
*/
|
|
1675
2146
|
onVariableListChange(observer) {
|
|
1676
2147
|
return subsToDisposable(this.variables$.subscribe(observer));
|
|
1677
2148
|
}
|
|
1678
2149
|
/**
|
|
1679
|
-
*
|
|
2150
|
+
* Gets the list of available variables.
|
|
1680
2151
|
*/
|
|
1681
2152
|
get variables() {
|
|
1682
2153
|
return this._variables;
|
|
1683
2154
|
}
|
|
1684
2155
|
/**
|
|
1685
|
-
*
|
|
2156
|
+
* Gets the keys of the available variables.
|
|
1686
2157
|
*/
|
|
1687
2158
|
get variableKeys() {
|
|
1688
2159
|
return this.memo("availableKeys", () => this._variables.map((_v) => _v.key));
|
|
1689
2160
|
}
|
|
1690
2161
|
/**
|
|
1691
|
-
*
|
|
2162
|
+
* Gets the dependency scopes.
|
|
1692
2163
|
*/
|
|
1693
2164
|
get depScopes() {
|
|
1694
2165
|
return this.scope.depScopes;
|
|
1695
2166
|
}
|
|
1696
2167
|
/**
|
|
1697
|
-
*
|
|
1698
|
-
* @param keyPath
|
|
1699
|
-
* @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`.
|
|
1700
2171
|
*/
|
|
1701
2172
|
getByKeyPath(keyPath = []) {
|
|
1702
2173
|
if (!this.variableKeys.includes(keyPath[0])) {
|
|
@@ -1704,6 +2175,37 @@ var ScopeAvailableData = class {
|
|
|
1704
2175
|
}
|
|
1705
2176
|
return this.globalVariableTable.getByKeyPath(keyPath);
|
|
1706
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
|
+
}
|
|
1707
2209
|
};
|
|
1708
2210
|
|
|
1709
2211
|
// src/scope/datas/scope-event-data.ts
|
|
@@ -1718,15 +2220,30 @@ var ScopeEventData = class {
|
|
|
1718
2220
|
})
|
|
1719
2221
|
]);
|
|
1720
2222
|
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Dispatches a global event.
|
|
2225
|
+
* @param action The event action to dispatch.
|
|
2226
|
+
*/
|
|
1721
2227
|
dispatch(action) {
|
|
1722
2228
|
if (this.scope.disposed) {
|
|
1723
2229
|
return;
|
|
1724
2230
|
}
|
|
1725
2231
|
this.event$.next(action);
|
|
1726
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
|
+
*/
|
|
1727
2238
|
subscribe(observer) {
|
|
1728
2239
|
return subsToDisposable(this.event$.subscribe(observer));
|
|
1729
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
|
+
*/
|
|
1730
2247
|
on(type, observer) {
|
|
1731
2248
|
return subsToDisposable(
|
|
1732
2249
|
this.event$.pipe(filter((_action) => _action.type === type)).subscribe(observer)
|
|
@@ -1738,7 +2255,7 @@ var ScopeEventData = class {
|
|
|
1738
2255
|
var Scope = class {
|
|
1739
2256
|
constructor(options) {
|
|
1740
2257
|
/**
|
|
1741
|
-
*
|
|
2258
|
+
* A memoization utility for caching computed values.
|
|
1742
2259
|
*/
|
|
1743
2260
|
this.memo = createMemo();
|
|
1744
2261
|
this.toDispose = new DisposableCollection4();
|
|
@@ -1750,7 +2267,7 @@ var Scope = class {
|
|
|
1750
2267
|
this.ast = this.variableEngine.astRegisters.createAST(
|
|
1751
2268
|
{
|
|
1752
2269
|
kind: "MapNode" /* MapNode */,
|
|
1753
|
-
key: this.id
|
|
2270
|
+
key: String(this.id)
|
|
1754
2271
|
},
|
|
1755
2272
|
{
|
|
1756
2273
|
scope: this
|
|
@@ -1759,25 +2276,41 @@ var Scope = class {
|
|
|
1759
2276
|
this.output = new ScopeOutputData(this);
|
|
1760
2277
|
this.available = new ScopeAvailableData(this);
|
|
1761
2278
|
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Refreshes the covering scopes.
|
|
2281
|
+
*/
|
|
1762
2282
|
refreshCovers() {
|
|
1763
2283
|
this.memo.clear("covers");
|
|
1764
2284
|
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Refreshes the dependency scopes and the available variables.
|
|
2287
|
+
*/
|
|
1765
2288
|
refreshDeps() {
|
|
1766
2289
|
this.memo.clear("deps");
|
|
1767
2290
|
this.available.refresh();
|
|
1768
2291
|
}
|
|
2292
|
+
/**
|
|
2293
|
+
* Gets the scopes that this scope depends on.
|
|
2294
|
+
*/
|
|
1769
2295
|
get depScopes() {
|
|
1770
2296
|
return this.memo(
|
|
1771
2297
|
"deps",
|
|
1772
2298
|
() => this.variableEngine.chain.getDeps(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1773
2299
|
);
|
|
1774
2300
|
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Gets the scopes that are covered by this scope.
|
|
2303
|
+
*/
|
|
1775
2304
|
get coverScopes() {
|
|
1776
2305
|
return this.memo(
|
|
1777
2306
|
"covers",
|
|
1778
2307
|
() => this.variableEngine.chain.getCovers(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1779
2308
|
);
|
|
1780
2309
|
}
|
|
2310
|
+
/**
|
|
2311
|
+
* Disposes of the scope and its resources.
|
|
2312
|
+
* This will also trigger updates in dependent and covering scopes.
|
|
2313
|
+
*/
|
|
1781
2314
|
dispose() {
|
|
1782
2315
|
this.ast.dispose();
|
|
1783
2316
|
this.toDispose.dispose();
|
|
@@ -1787,6 +2320,32 @@ var Scope = class {
|
|
|
1787
2320
|
get disposed() {
|
|
1788
2321
|
return this.toDispose.disposed;
|
|
1789
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
|
+
}
|
|
1790
2349
|
};
|
|
1791
2350
|
|
|
1792
2351
|
// src/variable-engine.ts
|
|
@@ -1797,44 +2356,71 @@ var VariableEngine = class {
|
|
|
1797
2356
|
this.toDispose = new DisposableCollection5();
|
|
1798
2357
|
this.memo = createMemo();
|
|
1799
2358
|
this.scopeMap = /* @__PURE__ */ new Map();
|
|
2359
|
+
/**
|
|
2360
|
+
* A rxjs subject that emits global events occurring within the variable engine.
|
|
2361
|
+
*/
|
|
1800
2362
|
this.globalEvent$ = new Subject5();
|
|
1801
2363
|
this.onScopeChangeEmitter = new Emitter3();
|
|
2364
|
+
/**
|
|
2365
|
+
* A table containing all global variables.
|
|
2366
|
+
*/
|
|
1802
2367
|
this.globalVariableTable = new VariableTable();
|
|
2368
|
+
/**
|
|
2369
|
+
* An event that fires whenever a scope is added, updated, or deleted.
|
|
2370
|
+
*/
|
|
1803
2371
|
this.onScopeChange = this.onScopeChangeEmitter.event;
|
|
1804
2372
|
this.toDispose.pushAll([
|
|
1805
2373
|
chain,
|
|
1806
|
-
|
|
2374
|
+
Disposable4.create(() => {
|
|
1807
2375
|
this.getAllScopes().forEach((scope) => scope.dispose());
|
|
1808
2376
|
this.globalVariableTable.dispose();
|
|
1809
2377
|
})
|
|
1810
2378
|
]);
|
|
1811
2379
|
}
|
|
2380
|
+
/**
|
|
2381
|
+
* The Inversify container instance.
|
|
2382
|
+
*/
|
|
1812
2383
|
get container() {
|
|
1813
2384
|
return this.containerProvider();
|
|
1814
2385
|
}
|
|
1815
2386
|
dispose() {
|
|
1816
2387
|
this.toDispose.dispose();
|
|
1817
2388
|
}
|
|
1818
|
-
|
|
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
|
+
*/
|
|
1819
2394
|
getScopeById(scopeId) {
|
|
1820
2395
|
return this.scopeMap.get(scopeId);
|
|
1821
2396
|
}
|
|
1822
|
-
|
|
2397
|
+
/**
|
|
2398
|
+
* Removes a scope by its unique identifier and disposes of it.
|
|
2399
|
+
* @param scopeId The ID of the scope to remove.
|
|
2400
|
+
*/
|
|
1823
2401
|
removeScopeById(scopeId) {
|
|
1824
2402
|
this.getScopeById(scopeId)?.dispose();
|
|
1825
2403
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
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;
|
|
1828
2414
|
let scope = this.getScopeById(id);
|
|
1829
2415
|
if (!scope) {
|
|
1830
|
-
scope = new
|
|
2416
|
+
scope = new ScopeConstructor({ variableEngine: this, meta, id });
|
|
1831
2417
|
this.scopeMap.set(id, scope);
|
|
1832
2418
|
this.onScopeChangeEmitter.fire({ type: "add", scope });
|
|
1833
2419
|
scope.toDispose.pushAll([
|
|
1834
2420
|
scope.ast.subscribe(() => {
|
|
1835
2421
|
this.onScopeChangeEmitter.fire({ type: "update", scope });
|
|
1836
2422
|
}),
|
|
1837
|
-
//
|
|
2423
|
+
// Fires when available variables change
|
|
1838
2424
|
scope.available.onDataChange(() => {
|
|
1839
2425
|
this.onScopeChangeEmitter.fire({ type: "available", scope });
|
|
1840
2426
|
})
|
|
@@ -1846,7 +2432,12 @@ var VariableEngine = class {
|
|
|
1846
2432
|
}
|
|
1847
2433
|
return scope;
|
|
1848
2434
|
}
|
|
1849
|
-
|
|
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
|
+
*/
|
|
1850
2441
|
getAllScopes({
|
|
1851
2442
|
sort
|
|
1852
2443
|
} = {}) {
|
|
@@ -1859,9 +2450,19 @@ var VariableEngine = class {
|
|
|
1859
2450
|
}
|
|
1860
2451
|
return [...allScopes];
|
|
1861
2452
|
}
|
|
2453
|
+
/**
|
|
2454
|
+
* Fires a global event to be broadcast to all listeners.
|
|
2455
|
+
* @param event The global event to fire.
|
|
2456
|
+
*/
|
|
1862
2457
|
fireGlobalEvent(event) {
|
|
1863
2458
|
this.globalEvent$.next(event);
|
|
1864
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
|
+
*/
|
|
1865
2466
|
onGlobalEvent(type, observer) {
|
|
1866
2467
|
return subsToDisposable(
|
|
1867
2468
|
this.globalEvent$.subscribe((_action) => {
|
|
@@ -1885,18 +2486,33 @@ VariableEngine = __decorateClass([
|
|
|
1885
2486
|
], VariableEngine);
|
|
1886
2487
|
|
|
1887
2488
|
// src/services/variable-field-key-rename-service.ts
|
|
1888
|
-
import { difference } from "lodash";
|
|
2489
|
+
import { difference } from "lodash-es";
|
|
1889
2490
|
import { inject as inject3, injectable as injectable4, postConstruct, preDestroy as preDestroy2 } from "inversify";
|
|
1890
2491
|
import { DisposableCollection as DisposableCollection6, Emitter as Emitter4 } from "@flowgram.ai/utils";
|
|
1891
2492
|
var VariableFieldKeyRenameService = class {
|
|
1892
2493
|
constructor() {
|
|
1893
2494
|
this.toDispose = new DisposableCollection6();
|
|
1894
2495
|
this.renameEmitter = new Emitter4();
|
|
1895
|
-
|
|
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
|
+
*/
|
|
1896
2500
|
this.disposeInListEmitter = new Emitter4();
|
|
2501
|
+
/**
|
|
2502
|
+
* An event that fires when a variable field key is successfully renamed.
|
|
2503
|
+
*/
|
|
1897
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
|
+
*/
|
|
1898
2508
|
this.onDisposeInList = this.disposeInListEmitter.event;
|
|
1899
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
|
+
*/
|
|
1900
2516
|
handleFieldListChange(ast, prev, next) {
|
|
1901
2517
|
if (!ast || !prev?.length || !next?.length) {
|
|
1902
2518
|
this.notifyFieldsDispose(prev, next);
|
|
@@ -1927,6 +2543,11 @@ var VariableFieldKeyRenameService = class {
|
|
|
1927
2543
|
}
|
|
1928
2544
|
this.renameEmitter.fire(renameNodeInfo);
|
|
1929
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
|
+
*/
|
|
1930
2551
|
notifyFieldsDispose(prev, next) {
|
|
1931
2552
|
const removedFields = difference(prev || [], next || []);
|
|
1932
2553
|
removedFields.forEach((_field) => this.disposeInListEmitter.fire(_field));
|
|
@@ -1974,28 +2595,48 @@ var VariableContainerModule = new ContainerModule((bind) => {
|
|
|
1974
2595
|
});
|
|
1975
2596
|
|
|
1976
2597
|
// src/react/context.tsx
|
|
1977
|
-
import { createContext, useContext } from "react";
|
|
2598
|
+
import React, { createContext, useContext } from "react";
|
|
1978
2599
|
var ScopeContext = createContext(null);
|
|
1979
|
-
var ScopeProvider =
|
|
1980
|
-
|
|
1981
|
-
|
|
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
|
+
};
|
|
1982
2619
|
|
|
1983
|
-
// src/react/hooks/
|
|
2620
|
+
// src/react/hooks/use-scope-available.ts
|
|
1984
2621
|
import { useEffect } from "react";
|
|
1985
2622
|
import { useRefresh } from "@flowgram.ai/core";
|
|
1986
|
-
function useScopeAvailable() {
|
|
1987
|
-
const
|
|
2623
|
+
function useScopeAvailable(params) {
|
|
2624
|
+
const { autoRefresh = true } = params || {};
|
|
2625
|
+
const scope = useCurrentScope({ strict: true });
|
|
1988
2626
|
const refresh = useRefresh();
|
|
1989
2627
|
useEffect(() => {
|
|
1990
|
-
|
|
2628
|
+
if (!autoRefresh) {
|
|
2629
|
+
return () => null;
|
|
2630
|
+
}
|
|
2631
|
+
const disposable = scope.available.onListOrAnyVarChange(() => {
|
|
1991
2632
|
refresh();
|
|
1992
2633
|
});
|
|
1993
2634
|
return () => disposable.dispose();
|
|
1994
|
-
}, []);
|
|
2635
|
+
}, [autoRefresh]);
|
|
1995
2636
|
return scope.available;
|
|
1996
2637
|
}
|
|
1997
2638
|
|
|
1998
|
-
// src/react/hooks/
|
|
2639
|
+
// src/react/hooks/use-available-variables.ts
|
|
1999
2640
|
import { useEffect as useEffect2 } from "react";
|
|
2000
2641
|
import { useRefresh as useRefresh2, useService } from "@flowgram.ai/core";
|
|
2001
2642
|
function useAvailableVariables() {
|
|
@@ -2004,7 +2645,7 @@ function useAvailableVariables() {
|
|
|
2004
2645
|
const refresh = useRefresh2();
|
|
2005
2646
|
useEffect2(() => {
|
|
2006
2647
|
if (!scope) {
|
|
2007
|
-
const disposable2 = variableEngine.globalVariableTable.
|
|
2648
|
+
const disposable2 = variableEngine.globalVariableTable.onListOrAnyVarChange(() => {
|
|
2008
2649
|
refresh();
|
|
2009
2650
|
});
|
|
2010
2651
|
return () => disposable2.dispose();
|
|
@@ -2016,9 +2657,30 @@ function useAvailableVariables() {
|
|
|
2016
2657
|
}, []);
|
|
2017
2658
|
return scope ? scope.available.variables : variableEngine.globalVariableTable.variables;
|
|
2018
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
|
+
}
|
|
2019
2680
|
export {
|
|
2020
2681
|
ASTFactory,
|
|
2021
2682
|
ASTKind,
|
|
2683
|
+
ASTMatch,
|
|
2022
2684
|
ASTNode,
|
|
2023
2685
|
ASTNodeFlags,
|
|
2024
2686
|
ASTRegisters,
|
|
@@ -2030,10 +2692,9 @@ export {
|
|
|
2030
2692
|
CustomType,
|
|
2031
2693
|
DataNode,
|
|
2032
2694
|
EnumerateExpression,
|
|
2033
|
-
ExpressionList,
|
|
2034
2695
|
IntegerType,
|
|
2035
2696
|
KeyPathExpression,
|
|
2036
|
-
|
|
2697
|
+
LegacyKeyPathExpression,
|
|
2037
2698
|
ListNode,
|
|
2038
2699
|
MapNode,
|
|
2039
2700
|
MapType,
|
|
@@ -2051,13 +2712,13 @@ export {
|
|
|
2051
2712
|
VariableEngine,
|
|
2052
2713
|
VariableEngineProvider,
|
|
2053
2714
|
VariableFieldKeyRenameService,
|
|
2054
|
-
|
|
2715
|
+
WrapArrayExpression,
|
|
2055
2716
|
injectToAST,
|
|
2056
2717
|
isMatchAST,
|
|
2057
2718
|
postConstructAST,
|
|
2058
2719
|
useAvailableVariables,
|
|
2059
2720
|
useCurrentScope,
|
|
2060
|
-
|
|
2061
|
-
|
|
2721
|
+
useOutputVariables,
|
|
2722
|
+
useScopeAvailable
|
|
2062
2723
|
};
|
|
2063
2724
|
//# sourceMappingURL=index.js.map
|