@flowgram.ai/variable-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/esm/index.js +2028 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +996 -0
- package/dist/index.d.ts +996 -0
- package/dist/index.js +2067 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,2028 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
12
|
+
|
|
13
|
+
// src/variable-container-module.ts
|
|
14
|
+
import { ContainerModule } from "inversify";
|
|
15
|
+
|
|
16
|
+
// src/variable-engine.ts
|
|
17
|
+
import { Subject as Subject5 } from "rxjs";
|
|
18
|
+
import { inject as inject2, injectable as injectable3, preDestroy } from "inversify";
|
|
19
|
+
import { Disposable as Disposable6, DisposableCollection as DisposableCollection5 } from "@flowgram.ai/utils";
|
|
20
|
+
import { Emitter as Emitter3 } from "@flowgram.ai/utils";
|
|
21
|
+
|
|
22
|
+
// src/utils/toDisposable.tsx
|
|
23
|
+
import { Disposable } from "@flowgram.ai/utils";
|
|
24
|
+
function subsToDisposable(subscription) {
|
|
25
|
+
return Disposable.create(() => subscription.unsubscribe());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/utils/memo.ts
|
|
29
|
+
var createMemo = () => {
|
|
30
|
+
const _memoCache = /* @__PURE__ */ new Map();
|
|
31
|
+
const memo = (key, fn) => {
|
|
32
|
+
if (_memoCache.has(key)) {
|
|
33
|
+
return _memoCache.get(key);
|
|
34
|
+
}
|
|
35
|
+
const data = fn();
|
|
36
|
+
_memoCache.set(key, data);
|
|
37
|
+
return data;
|
|
38
|
+
};
|
|
39
|
+
const clear = (key) => {
|
|
40
|
+
if (key) {
|
|
41
|
+
_memoCache.delete(key);
|
|
42
|
+
} else {
|
|
43
|
+
_memoCache.clear();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
memo.clear = clear;
|
|
47
|
+
return memo;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/scope/scope-chain.ts
|
|
51
|
+
import { inject, injectable } from "inversify";
|
|
52
|
+
import { DisposableCollection } from "@flowgram.ai/utils";
|
|
53
|
+
|
|
54
|
+
// src/providers.ts
|
|
55
|
+
var VariableEngineProvider = Symbol("DynamicVariableEngine");
|
|
56
|
+
var ContainerProvider = Symbol("ContainerProvider");
|
|
57
|
+
|
|
58
|
+
// src/scope/scope-chain.ts
|
|
59
|
+
var ScopeChain = class {
|
|
60
|
+
constructor() {
|
|
61
|
+
this.toDispose = new DisposableCollection();
|
|
62
|
+
}
|
|
63
|
+
get variableEngine() {
|
|
64
|
+
return this.variableEngineProvider();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 所有作用域依赖关系刷新
|
|
68
|
+
*/
|
|
69
|
+
refreshAllChange() {
|
|
70
|
+
this.variableEngine.getAllScopes().forEach((_scope) => {
|
|
71
|
+
_scope.refreshCovers();
|
|
72
|
+
_scope.refreshDeps();
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
dispose() {
|
|
76
|
+
this.toDispose.dispose();
|
|
77
|
+
}
|
|
78
|
+
get disposed() {
|
|
79
|
+
return this.toDispose.disposed;
|
|
80
|
+
}
|
|
81
|
+
get onDispose() {
|
|
82
|
+
return this.toDispose.onDispose;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
__decorateClass([
|
|
86
|
+
inject(VariableEngineProvider)
|
|
87
|
+
], ScopeChain.prototype, "variableEngineProvider", 2);
|
|
88
|
+
ScopeChain = __decorateClass([
|
|
89
|
+
injectable()
|
|
90
|
+
], ScopeChain);
|
|
91
|
+
|
|
92
|
+
// src/scope/scope.ts
|
|
93
|
+
import { DisposableCollection as DisposableCollection4 } from "@flowgram.ai/utils";
|
|
94
|
+
|
|
95
|
+
// src/ast/types.ts
|
|
96
|
+
var ASTKind = /* @__PURE__ */ ((ASTKind2) => {
|
|
97
|
+
ASTKind2["String"] = "String";
|
|
98
|
+
ASTKind2["Number"] = "Number";
|
|
99
|
+
ASTKind2["Integer"] = "Integer";
|
|
100
|
+
ASTKind2["Boolean"] = "Boolean";
|
|
101
|
+
ASTKind2["Object"] = "Object";
|
|
102
|
+
ASTKind2["Array"] = "Array";
|
|
103
|
+
ASTKind2["Map"] = "Map";
|
|
104
|
+
ASTKind2["Union"] = "Union";
|
|
105
|
+
ASTKind2["Any"] = "Any";
|
|
106
|
+
ASTKind2["Property"] = "Property";
|
|
107
|
+
ASTKind2["VariableDeclaration"] = "VariableDeclaration";
|
|
108
|
+
ASTKind2["VariableDeclarationList"] = "VariableDeclarationList";
|
|
109
|
+
ASTKind2["KeyPathExpression"] = "KeyPathExpression";
|
|
110
|
+
ASTKind2["EnumerateExpression"] = "EnumerateExpression";
|
|
111
|
+
ASTKind2["ExpressionList"] = "ExpressionList";
|
|
112
|
+
ASTKind2["ListNode"] = "ListNode";
|
|
113
|
+
ASTKind2["DataNode"] = "DataNode";
|
|
114
|
+
ASTKind2["MapNode"] = "MapNode";
|
|
115
|
+
return ASTKind2;
|
|
116
|
+
})(ASTKind || {});
|
|
117
|
+
|
|
118
|
+
// src/ast/ast-registers.ts
|
|
119
|
+
import { omit } from "lodash";
|
|
120
|
+
import { injectable as injectable2 } from "inversify";
|
|
121
|
+
|
|
122
|
+
// src/ast/utils/inversify.ts
|
|
123
|
+
var injectToAST = (serviceIdentifier) => function(target, propertyKey) {
|
|
124
|
+
if (!serviceIdentifier) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`ServiceIdentifier ${serviceIdentifier} in @lazyInject is Empty, it might be caused by file circular dependency, please check it.`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const descriptor = {
|
|
130
|
+
get() {
|
|
131
|
+
const container = this.scope.variableEngine.container;
|
|
132
|
+
return container.get(serviceIdentifier);
|
|
133
|
+
},
|
|
134
|
+
set() {
|
|
135
|
+
},
|
|
136
|
+
configurable: true,
|
|
137
|
+
enumerable: true
|
|
138
|
+
};
|
|
139
|
+
return descriptor;
|
|
140
|
+
};
|
|
141
|
+
var POST_CONSTRUCT_AST_SYMBOL = Symbol("post_construct_ast");
|
|
142
|
+
var postConstructAST = () => (target, propertyKey) => {
|
|
143
|
+
if (!Reflect.hasMetadata(POST_CONSTRUCT_AST_SYMBOL, target)) {
|
|
144
|
+
Reflect.defineMetadata(POST_CONSTRUCT_AST_SYMBOL, propertyKey, target);
|
|
145
|
+
} else {
|
|
146
|
+
throw Error("Duplication Post Construct AST");
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// src/ast/utils/helpers.ts
|
|
151
|
+
function updateChildNodeHelper({
|
|
152
|
+
getChildNode,
|
|
153
|
+
updateChildNode,
|
|
154
|
+
removeChildNode,
|
|
155
|
+
nextJSON
|
|
156
|
+
}) {
|
|
157
|
+
const currNode = getChildNode();
|
|
158
|
+
const isNewKind = currNode?.kind !== nextJSON?.kind;
|
|
159
|
+
const isNewKey = nextJSON?.key && nextJSON?.key !== currNode?.key;
|
|
160
|
+
if (isNewKind || isNewKey) {
|
|
161
|
+
if (currNode) {
|
|
162
|
+
currNode.dispose();
|
|
163
|
+
removeChildNode();
|
|
164
|
+
}
|
|
165
|
+
if (nextJSON) {
|
|
166
|
+
const newNode = this.createChildNode(nextJSON);
|
|
167
|
+
updateChildNode(newNode);
|
|
168
|
+
this.fireChange();
|
|
169
|
+
return newNode;
|
|
170
|
+
} else {
|
|
171
|
+
this.fireChange();
|
|
172
|
+
}
|
|
173
|
+
} else if (nextJSON) {
|
|
174
|
+
currNode?.fromJSON(nextJSON);
|
|
175
|
+
}
|
|
176
|
+
return currNode;
|
|
177
|
+
}
|
|
178
|
+
function parseTypeJsonOrKind(typeJSONOrKind) {
|
|
179
|
+
return typeof typeJSONOrKind === "string" ? { kind: typeJSONOrKind } : typeJSONOrKind;
|
|
180
|
+
}
|
|
181
|
+
function getAllChildren(ast) {
|
|
182
|
+
return [...ast.children, ...ast.children.map((_child) => getAllChildren(_child)).flat()];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/ast/flags.ts
|
|
186
|
+
var ASTNodeFlags = /* @__PURE__ */ ((ASTNodeFlags2) => {
|
|
187
|
+
ASTNodeFlags2[ASTNodeFlags2["None"] = 0] = "None";
|
|
188
|
+
ASTNodeFlags2[ASTNodeFlags2["VariableField"] = 1] = "VariableField";
|
|
189
|
+
ASTNodeFlags2[ASTNodeFlags2["Expression"] = 4] = "Expression";
|
|
190
|
+
ASTNodeFlags2[ASTNodeFlags2["BasicType"] = 8] = "BasicType";
|
|
191
|
+
ASTNodeFlags2[ASTNodeFlags2["DrilldownType"] = 16] = "DrilldownType";
|
|
192
|
+
ASTNodeFlags2[ASTNodeFlags2["EnumerateType"] = 32] = "EnumerateType";
|
|
193
|
+
ASTNodeFlags2[ASTNodeFlags2["UnionType"] = 64] = "UnionType";
|
|
194
|
+
ASTNodeFlags2[ASTNodeFlags2["VariableType"] = 120] = "VariableType";
|
|
195
|
+
return ASTNodeFlags2;
|
|
196
|
+
})(ASTNodeFlags || {});
|
|
197
|
+
|
|
198
|
+
// src/ast/ast-node.ts
|
|
199
|
+
import {
|
|
200
|
+
BehaviorSubject,
|
|
201
|
+
animationFrameScheduler,
|
|
202
|
+
debounceTime,
|
|
203
|
+
distinctUntilChanged,
|
|
204
|
+
map,
|
|
205
|
+
skip,
|
|
206
|
+
tap
|
|
207
|
+
} from "rxjs";
|
|
208
|
+
import { nanoid } from "nanoid";
|
|
209
|
+
import { shallowEqual } from "fast-equals";
|
|
210
|
+
import { Disposable as Disposable2, DisposableCollection as DisposableCollection2 } from "@flowgram.ai/utils";
|
|
211
|
+
var ASTNode = class _ASTNode {
|
|
212
|
+
/**
|
|
213
|
+
* 构造函数
|
|
214
|
+
* @param createParams 创建 ASTNode 的必要参数
|
|
215
|
+
* @param injectOptions 依赖注入各种模块
|
|
216
|
+
*/
|
|
217
|
+
constructor({ key, parent, scope }, opts) {
|
|
218
|
+
/**
|
|
219
|
+
* 节点 Flags,记录一些 Flag 信息
|
|
220
|
+
*/
|
|
221
|
+
this.flags = 0 /* None */;
|
|
222
|
+
/**
|
|
223
|
+
* 节点的版本号,每 fireChange 一次 version + 1
|
|
224
|
+
*/
|
|
225
|
+
this._version = 0;
|
|
226
|
+
/**
|
|
227
|
+
* 更新锁
|
|
228
|
+
*/
|
|
229
|
+
this.changeLocked = false;
|
|
230
|
+
/**
|
|
231
|
+
* Batch Update 相关参数
|
|
232
|
+
*/
|
|
233
|
+
this._batch = {
|
|
234
|
+
batching: false,
|
|
235
|
+
hasChangesInBatch: false
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* AST 节点变化事件,基于 Rxjs 实现
|
|
239
|
+
* - 使用了 BehaviorSubject, 在订阅时会自动触发一次事件,事件为当前值
|
|
240
|
+
*/
|
|
241
|
+
this.value$ = new BehaviorSubject(this);
|
|
242
|
+
/**
|
|
243
|
+
* 子节点
|
|
244
|
+
*/
|
|
245
|
+
this._children = /* @__PURE__ */ new Set();
|
|
246
|
+
/**
|
|
247
|
+
* 删除节点处理事件列表
|
|
248
|
+
*/
|
|
249
|
+
this.toDispose = new DisposableCollection2(
|
|
250
|
+
Disposable2.create(() => {
|
|
251
|
+
this.parent?.fireChange();
|
|
252
|
+
this.children.forEach((child) => child.dispose());
|
|
253
|
+
})
|
|
254
|
+
);
|
|
255
|
+
/**
|
|
256
|
+
* 销毁时触发的回调
|
|
257
|
+
*/
|
|
258
|
+
this.onDispose = this.toDispose.onDispose;
|
|
259
|
+
this.scope = scope;
|
|
260
|
+
this.parent = parent;
|
|
261
|
+
this.opts = opts;
|
|
262
|
+
this.key = key || nanoid();
|
|
263
|
+
this.fromJSON = this.withBatchUpdate(this.fromJSON.bind(this));
|
|
264
|
+
this.dispatchGlobalEvent({ type: "NewAST" });
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* AST 节点的类型
|
|
268
|
+
*/
|
|
269
|
+
get kind() {
|
|
270
|
+
if (!this.constructor.kind) {
|
|
271
|
+
throw new Error(`ASTNode Registry need a kind: ${this.constructor.name}`);
|
|
272
|
+
}
|
|
273
|
+
return this.constructor.kind;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* 获取当前节点所有子节点
|
|
277
|
+
*/
|
|
278
|
+
get children() {
|
|
279
|
+
return Array.from(this._children);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* 转化为 ASTNodeJSON
|
|
283
|
+
* @returns
|
|
284
|
+
*/
|
|
285
|
+
toJSON() {
|
|
286
|
+
console.warn("[VariableEngine] Please Implement toJSON method for " + this.kind);
|
|
287
|
+
return {
|
|
288
|
+
kind: this.kind
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* 创建子节点
|
|
293
|
+
* @param json 子节点的 AST JSON
|
|
294
|
+
* @returns
|
|
295
|
+
*/
|
|
296
|
+
createChildNode(json) {
|
|
297
|
+
const astRegisters = this.scope.variableEngine.astRegisters;
|
|
298
|
+
const child = astRegisters.createAST(json, {
|
|
299
|
+
parent: this,
|
|
300
|
+
scope: this.scope
|
|
301
|
+
});
|
|
302
|
+
this._children.add(child);
|
|
303
|
+
child.toDispose.push(
|
|
304
|
+
Disposable2.create(() => {
|
|
305
|
+
this._children.delete(child);
|
|
306
|
+
})
|
|
307
|
+
);
|
|
308
|
+
return child;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* 更新子节点,快速实现子节点更新消费逻辑
|
|
312
|
+
* @param keyInThis 当前对象上的指定 key
|
|
313
|
+
*/
|
|
314
|
+
updateChildNodeByKey(keyInThis, nextJSON) {
|
|
315
|
+
this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
316
|
+
getChildNode: () => this[keyInThis],
|
|
317
|
+
updateChildNode: (_node) => this[keyInThis] = _node,
|
|
318
|
+
removeChildNode: () => this[keyInThis] = void 0,
|
|
319
|
+
nextJSON
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* 批处理更新,批处理函数内所有的 fireChange 都合并成一个
|
|
324
|
+
* @param updater 批处理函数
|
|
325
|
+
* @returns
|
|
326
|
+
*/
|
|
327
|
+
withBatchUpdate(updater) {
|
|
328
|
+
return (...args) => {
|
|
329
|
+
if (this._batch.batching) {
|
|
330
|
+
return updater.call(this, ...args);
|
|
331
|
+
}
|
|
332
|
+
this._batch.hasChangesInBatch = false;
|
|
333
|
+
this._batch.batching = true;
|
|
334
|
+
const res = updater.call(this, ...args);
|
|
335
|
+
this._batch.batching = false;
|
|
336
|
+
if (this._batch.hasChangesInBatch) {
|
|
337
|
+
this.fireChange();
|
|
338
|
+
}
|
|
339
|
+
this._batch.hasChangesInBatch = false;
|
|
340
|
+
return res;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* 触发当前节点更新
|
|
345
|
+
*/
|
|
346
|
+
fireChange() {
|
|
347
|
+
if (this.changeLocked || this.disposed) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (this._batch.batching) {
|
|
351
|
+
this._batch.hasChangesInBatch = true;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this._version++;
|
|
355
|
+
this.value$.next(this);
|
|
356
|
+
this.dispatchGlobalEvent({ type: "UpdateAST" });
|
|
357
|
+
this.parent?.fireChange();
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* 节点的版本值
|
|
361
|
+
* - 通过 NodeA === NodeB && versionA === versionB 可以比较两者是否相等
|
|
362
|
+
*/
|
|
363
|
+
get version() {
|
|
364
|
+
return this._version;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* 节点唯一 hash 值
|
|
368
|
+
*/
|
|
369
|
+
get hash() {
|
|
370
|
+
return `${this._version}${this.kind}${this.key}`;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* 监听 AST 节点的变化
|
|
374
|
+
* @param observer 监听回调
|
|
375
|
+
* @param selector 监听指定数据
|
|
376
|
+
* @returns
|
|
377
|
+
*/
|
|
378
|
+
subscribe(observer, { selector, debounceAnimation, triggerOnInit } = {}) {
|
|
379
|
+
return subsToDisposable(
|
|
380
|
+
this.value$.pipe(
|
|
381
|
+
map(() => selector ? selector(this) : this),
|
|
382
|
+
distinctUntilChanged(
|
|
383
|
+
(a, b) => shallowEqual(a, b),
|
|
384
|
+
(value) => {
|
|
385
|
+
if (value instanceof _ASTNode) {
|
|
386
|
+
return value.hash;
|
|
387
|
+
}
|
|
388
|
+
return value;
|
|
389
|
+
}
|
|
390
|
+
),
|
|
391
|
+
// 默认跳过 BehaviorSubject 第一次触发
|
|
392
|
+
triggerOnInit ? tap(() => null) : skip(1),
|
|
393
|
+
// 每个 animationFrame 内所有更新合并成一个
|
|
394
|
+
debounceAnimation ? debounceTime(0, animationFrameScheduler) : tap(() => null)
|
|
395
|
+
).subscribe(observer)
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
dispatchGlobalEvent(event) {
|
|
399
|
+
this.scope.event.dispatch({
|
|
400
|
+
...event,
|
|
401
|
+
ast: this
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* 销毁
|
|
406
|
+
*/
|
|
407
|
+
dispose() {
|
|
408
|
+
if (this.toDispose.disposed) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
this.toDispose.dispose();
|
|
412
|
+
this.dispatchGlobalEvent({ type: "DisposeAST" });
|
|
413
|
+
this.value$.complete();
|
|
414
|
+
this.value$.unsubscribe();
|
|
415
|
+
}
|
|
416
|
+
get disposed() {
|
|
417
|
+
return this.toDispose.disposed;
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/ast/type/base-type.ts
|
|
422
|
+
var BaseType = class extends ASTNode {
|
|
423
|
+
constructor() {
|
|
424
|
+
super(...arguments);
|
|
425
|
+
this.flags = 8 /* BasicType */;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* 类型是否一致,节点有额外信息判断,请参考 extraTypeInfoEqual
|
|
429
|
+
* @param targetTypeJSON
|
|
430
|
+
*/
|
|
431
|
+
isTypeEqual(targetTypeJSONOrKind) {
|
|
432
|
+
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
433
|
+
if (targetTypeJSON?.kind === "Union" /* Union */) {
|
|
434
|
+
return (targetTypeJSON?.types || [])?.some(
|
|
435
|
+
(_subType) => this.isTypeEqual(_subType)
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
return this.kind === targetTypeJSON?.kind;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 可下钻类型需实现
|
|
442
|
+
* @param keyPath
|
|
443
|
+
*/
|
|
444
|
+
getByKeyPath(keyPath = []) {
|
|
445
|
+
throw new Error(`Get By Key Path is not implemented for Type: ${this.kind}`);
|
|
446
|
+
}
|
|
447
|
+
toJSON() {
|
|
448
|
+
return {
|
|
449
|
+
kind: this.kind
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// src/ast/type/array.ts
|
|
455
|
+
var ArrayType = class extends BaseType {
|
|
456
|
+
constructor() {
|
|
457
|
+
super(...arguments);
|
|
458
|
+
this.flags = 16 /* DrilldownType */ | 32 /* EnumerateType */;
|
|
459
|
+
}
|
|
460
|
+
fromJSON({ items }) {
|
|
461
|
+
this.updateChildNodeByKey("items", parseTypeJsonOrKind(items));
|
|
462
|
+
}
|
|
463
|
+
// items 类型是否可下钻
|
|
464
|
+
get canDrilldownItems() {
|
|
465
|
+
return !!(this.items?.flags & 16 /* DrilldownType */);
|
|
466
|
+
}
|
|
467
|
+
getByKeyPath(keyPath) {
|
|
468
|
+
const [curr, ...rest] = keyPath || [];
|
|
469
|
+
if (curr === "0" && this.canDrilldownItems) {
|
|
470
|
+
return this.items.getByKeyPath(rest);
|
|
471
|
+
}
|
|
472
|
+
return void 0;
|
|
473
|
+
}
|
|
474
|
+
isTypeEqual(targetTypeJSONOrKind) {
|
|
475
|
+
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
476
|
+
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
477
|
+
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
478
|
+
return isSuperEqual;
|
|
479
|
+
}
|
|
480
|
+
return targetTypeJSON && isSuperEqual && // 弱比较,只需要比较 Kind 即可
|
|
481
|
+
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Array 强比较
|
|
485
|
+
* @param targetTypeJSON
|
|
486
|
+
* @returns
|
|
487
|
+
*/
|
|
488
|
+
customStrongEqual(targetTypeJSON) {
|
|
489
|
+
if (!this.items) {
|
|
490
|
+
return !targetTypeJSON?.items;
|
|
491
|
+
}
|
|
492
|
+
return this.items?.isTypeEqual(targetTypeJSON.items);
|
|
493
|
+
}
|
|
494
|
+
toJSON() {
|
|
495
|
+
return {
|
|
496
|
+
kind: "Array" /* Array */,
|
|
497
|
+
items: this.items?.toJSON()
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
ArrayType.kind = "Array" /* Array */;
|
|
502
|
+
|
|
503
|
+
// src/ast/type/string.ts
|
|
504
|
+
var StringType = class extends BaseType {
|
|
505
|
+
constructor() {
|
|
506
|
+
super(...arguments);
|
|
507
|
+
this.flags = 8 /* BasicType */;
|
|
508
|
+
}
|
|
509
|
+
fromJSON() {
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
StringType.kind = "String" /* String */;
|
|
513
|
+
|
|
514
|
+
// src/ast/type/integer.ts
|
|
515
|
+
var IntegerType = class extends BaseType {
|
|
516
|
+
constructor() {
|
|
517
|
+
super(...arguments);
|
|
518
|
+
this.flags = 8 /* BasicType */;
|
|
519
|
+
}
|
|
520
|
+
fromJSON() {
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
IntegerType.kind = "Integer" /* Integer */;
|
|
524
|
+
|
|
525
|
+
// src/ast/type/boolean.ts
|
|
526
|
+
var BooleanType = class extends BaseType {
|
|
527
|
+
fromJSON() {
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
BooleanType.kind = "Boolean" /* Boolean */;
|
|
531
|
+
|
|
532
|
+
// src/ast/type/number.ts
|
|
533
|
+
var NumberType = class extends BaseType {
|
|
534
|
+
fromJSON() {
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
NumberType.kind = "Number" /* Number */;
|
|
538
|
+
|
|
539
|
+
// src/ast/type/map.ts
|
|
540
|
+
var MapType = class extends BaseType {
|
|
541
|
+
fromJSON({ keyType = "String" /* String */, valueType }) {
|
|
542
|
+
this.updateChildNodeByKey("keyType", parseTypeJsonOrKind(keyType));
|
|
543
|
+
this.updateChildNodeByKey("valueType", parseTypeJsonOrKind(valueType));
|
|
544
|
+
}
|
|
545
|
+
// Value 类型是否可下钻,后续实现
|
|
546
|
+
// get canDrilldownValue(): boolean {
|
|
547
|
+
// return !!(this.valueType.flags & ASTNodeFlags.DrilldownType);
|
|
548
|
+
// }
|
|
549
|
+
// getByKeyPath(keyPath: string[]): BaseVariableField | undefined {
|
|
550
|
+
// const [curr, ...rest] = keyPath || [];
|
|
551
|
+
// if (curr === '*' && this.canDrilldownValue) {
|
|
552
|
+
// return this.valueType.getByKeyPath(rest);
|
|
553
|
+
// }
|
|
554
|
+
// return undefined;
|
|
555
|
+
// }
|
|
556
|
+
isTypeEqual(targetTypeJSONOrKind) {
|
|
557
|
+
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
558
|
+
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
559
|
+
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
560
|
+
return isSuperEqual;
|
|
561
|
+
}
|
|
562
|
+
return targetTypeJSON && isSuperEqual && // 弱比较,只需要比较 Kind 即可
|
|
563
|
+
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Map 强比较
|
|
567
|
+
* @param targetTypeJSON
|
|
568
|
+
* @returns
|
|
569
|
+
*/
|
|
570
|
+
customStrongEqual(targetTypeJSON) {
|
|
571
|
+
const { keyType = "String" /* String */, valueType } = targetTypeJSON;
|
|
572
|
+
const isValueTypeEqual = !valueType && !this.valueType || this.valueType?.isTypeEqual(valueType);
|
|
573
|
+
return isValueTypeEqual && this.keyType?.isTypeEqual(keyType);
|
|
574
|
+
}
|
|
575
|
+
toJSON() {
|
|
576
|
+
return {
|
|
577
|
+
kind: "Map" /* Map */,
|
|
578
|
+
keyType: this.keyType?.toJSON(),
|
|
579
|
+
valueType: this.valueType?.toJSON()
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
// public flags: ASTNodeFlags = ASTNodeFlags.DrilldownType | ASTNodeFlags.EnumerateType;
|
|
584
|
+
MapType.kind = "Map" /* Map */;
|
|
585
|
+
|
|
586
|
+
// src/ast/type/object.ts
|
|
587
|
+
import { xor } from "lodash";
|
|
588
|
+
var ObjectType = class extends BaseType {
|
|
589
|
+
constructor() {
|
|
590
|
+
super(...arguments);
|
|
591
|
+
this.flags = 16 /* DrilldownType */;
|
|
592
|
+
this.propertyTable = /* @__PURE__ */ new Map();
|
|
593
|
+
}
|
|
594
|
+
fromJSON({ properties }) {
|
|
595
|
+
const removedKeys = new Set(this.propertyTable.keys());
|
|
596
|
+
const prev = [...this.properties || []];
|
|
597
|
+
this.properties = (properties || []).map((property) => {
|
|
598
|
+
const existProperty = this.propertyTable.get(property.key);
|
|
599
|
+
removedKeys.delete(property.key);
|
|
600
|
+
if (existProperty) {
|
|
601
|
+
existProperty.fromJSON(property);
|
|
602
|
+
return existProperty;
|
|
603
|
+
} else {
|
|
604
|
+
const newProperty = this.createChildNode({
|
|
605
|
+
...property,
|
|
606
|
+
kind: "Property" /* Property */
|
|
607
|
+
});
|
|
608
|
+
this.fireChange();
|
|
609
|
+
this.propertyTable.set(property.key, newProperty);
|
|
610
|
+
return newProperty;
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
removedKeys.forEach((key) => {
|
|
614
|
+
const property = this.propertyTable.get(key);
|
|
615
|
+
property?.dispose();
|
|
616
|
+
this.propertyTable.delete(key);
|
|
617
|
+
this.fireChange();
|
|
618
|
+
});
|
|
619
|
+
this.dispatchGlobalEvent({
|
|
620
|
+
type: "ObjectPropertiesChange",
|
|
621
|
+
payload: {
|
|
622
|
+
prev,
|
|
623
|
+
next: [...this.properties]
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
toJSON() {
|
|
628
|
+
return {
|
|
629
|
+
kind: "Object" /* Object */,
|
|
630
|
+
properties: this.properties.map((_property) => _property.toJSON())
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* 根据 KeyPath 找到对应的变量
|
|
635
|
+
* @param keyPath 变量路径
|
|
636
|
+
* @returns
|
|
637
|
+
*/
|
|
638
|
+
getByKeyPath(keyPath) {
|
|
639
|
+
const [curr, ...restKeyPath] = keyPath;
|
|
640
|
+
const property = this.propertyTable.get(curr);
|
|
641
|
+
if (!restKeyPath.length) {
|
|
642
|
+
return property;
|
|
643
|
+
}
|
|
644
|
+
if (property?.type && property?.type?.flags & 16 /* DrilldownType */) {
|
|
645
|
+
return property.type.getByKeyPath(restKeyPath);
|
|
646
|
+
}
|
|
647
|
+
return void 0;
|
|
648
|
+
}
|
|
649
|
+
isTypeEqual(targetTypeJSONOrKind) {
|
|
650
|
+
const targetTypeJSON = parseTypeJsonOrKind(targetTypeJSONOrKind);
|
|
651
|
+
const isSuperEqual = super.isTypeEqual(targetTypeJSONOrKind);
|
|
652
|
+
if (targetTypeJSON?.weak || targetTypeJSON?.kind === "Union" /* Union */) {
|
|
653
|
+
return isSuperEqual;
|
|
654
|
+
}
|
|
655
|
+
return targetTypeJSON && isSuperEqual && // 弱比较,只需要比较 Kind 即可
|
|
656
|
+
(targetTypeJSON?.weak || this.customStrongEqual(targetTypeJSON));
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Object 类型强比较
|
|
660
|
+
* @param targetTypeJSON
|
|
661
|
+
* @returns
|
|
662
|
+
*/
|
|
663
|
+
customStrongEqual(targetTypeJSON) {
|
|
664
|
+
const targetProperties = targetTypeJSON.properties || [];
|
|
665
|
+
const sourcePropertyKeys = Array.from(this.propertyTable.keys());
|
|
666
|
+
const targetPropertyKeys = targetProperties.map((_target) => _target.key);
|
|
667
|
+
const isKeyStrongEqual = !xor(sourcePropertyKeys, targetPropertyKeys).length;
|
|
668
|
+
return isKeyStrongEqual && targetProperties.every((targetProperty) => {
|
|
669
|
+
const sourceProperty = this.propertyTable.get(targetProperty.key);
|
|
670
|
+
return sourceProperty && sourceProperty.key === targetProperty.key && sourceProperty.type?.isTypeEqual(targetProperty?.type);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
ObjectType.kind = "Object" /* Object */;
|
|
675
|
+
|
|
676
|
+
// src/ast/expression/base-expression.ts
|
|
677
|
+
import {
|
|
678
|
+
distinctUntilChanged as distinctUntilChanged2,
|
|
679
|
+
map as map2,
|
|
680
|
+
switchMap,
|
|
681
|
+
combineLatest,
|
|
682
|
+
of,
|
|
683
|
+
Subject,
|
|
684
|
+
share
|
|
685
|
+
} from "rxjs";
|
|
686
|
+
import { shallowEqual as shallowEqual2 } from "fast-equals";
|
|
687
|
+
|
|
688
|
+
// src/ast/utils/variable-field.ts
|
|
689
|
+
function getParentFields(ast) {
|
|
690
|
+
let curr = ast.parent;
|
|
691
|
+
const res = [];
|
|
692
|
+
while (curr) {
|
|
693
|
+
if (curr.flags & 1 /* VariableField */) {
|
|
694
|
+
res.push(curr);
|
|
695
|
+
}
|
|
696
|
+
curr = curr.parent;
|
|
697
|
+
}
|
|
698
|
+
return res;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/ast/expression/base-expression.ts
|
|
702
|
+
var BaseExpression = class extends ASTNode {
|
|
703
|
+
constructor(params, opts) {
|
|
704
|
+
super(params, opts);
|
|
705
|
+
this.flags = 4 /* Expression */;
|
|
706
|
+
/**
|
|
707
|
+
* 引用变量
|
|
708
|
+
*/
|
|
709
|
+
this._refs = [];
|
|
710
|
+
this.refreshRefs$ = new Subject();
|
|
711
|
+
/**
|
|
712
|
+
* 监听引用变量变化
|
|
713
|
+
* 监听 [a.b.c] -> [a.b]
|
|
714
|
+
*/
|
|
715
|
+
this.refs$ = this.refreshRefs$.pipe(
|
|
716
|
+
map2(() => this.getRefFields()),
|
|
717
|
+
distinctUntilChanged2(shallowEqual2),
|
|
718
|
+
switchMap(
|
|
719
|
+
(refs) => !refs?.length ? of([]) : combineLatest(
|
|
720
|
+
refs.map(
|
|
721
|
+
(ref) => ref ? ref.value$ : of(void 0)
|
|
722
|
+
)
|
|
723
|
+
)
|
|
724
|
+
),
|
|
725
|
+
share()
|
|
726
|
+
);
|
|
727
|
+
this.toDispose.push(
|
|
728
|
+
subsToDisposable(
|
|
729
|
+
this.refs$.subscribe((_refs) => {
|
|
730
|
+
this._refs = _refs;
|
|
731
|
+
this.fireChange();
|
|
732
|
+
})
|
|
733
|
+
)
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* 获取全局变量表,方便表达式获取引用变量
|
|
738
|
+
*/
|
|
739
|
+
get globalVariableTable() {
|
|
740
|
+
return this.scope.variableEngine.globalVariableTable;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* 父变量字段,通过由近而远的方式进行排序
|
|
744
|
+
*/
|
|
745
|
+
get parentFields() {
|
|
746
|
+
return getParentFields(this);
|
|
747
|
+
}
|
|
748
|
+
get refs() {
|
|
749
|
+
return this._refs;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* 刷新变量引用
|
|
753
|
+
*/
|
|
754
|
+
refreshRefs() {
|
|
755
|
+
this.refreshRefs$.next();
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
// src/ast/expression/expression-list.ts
|
|
760
|
+
var ExpressionList = class extends ASTNode {
|
|
761
|
+
fromJSON({ expressions }) {
|
|
762
|
+
this.expressions = expressions.map((_expression, idx) => {
|
|
763
|
+
const prevExpression = this.expressions[idx];
|
|
764
|
+
if (prevExpression.kind !== _expression.kind) {
|
|
765
|
+
prevExpression.dispose();
|
|
766
|
+
this.fireChange();
|
|
767
|
+
return this.createChildNode(_expression);
|
|
768
|
+
}
|
|
769
|
+
prevExpression.fromJSON(_expression);
|
|
770
|
+
return prevExpression;
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
toJSON() {
|
|
774
|
+
return {
|
|
775
|
+
kind: "ExpressionList" /* ExpressionList */,
|
|
776
|
+
properties: this.expressions.map((_expression) => _expression.toJSON())
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
ExpressionList.kind = "ExpressionList" /* ExpressionList */;
|
|
781
|
+
|
|
782
|
+
// src/ast/expression/keypath-expression.ts
|
|
783
|
+
import { shallowEqual as shallowEqual3 } from "fast-equals";
|
|
784
|
+
var KeyPathExpression = class extends BaseExpression {
|
|
785
|
+
constructor(params, opts) {
|
|
786
|
+
super(params, opts);
|
|
787
|
+
this._keyPath = [];
|
|
788
|
+
this.toDispose.pushAll([
|
|
789
|
+
// 可以用变量列表变化时候 (有新增或者删除时)
|
|
790
|
+
this.scope.available.onVariableListChange(() => {
|
|
791
|
+
this.refreshRefs();
|
|
792
|
+
}),
|
|
793
|
+
// this._keyPath 指向的可引用变量发生变化时,刷新引用数据
|
|
794
|
+
this.scope.available.onAnyVariableChange((_v) => {
|
|
795
|
+
if (_v.key === this._keyPath[0]) {
|
|
796
|
+
this.refreshRefs();
|
|
797
|
+
}
|
|
798
|
+
})
|
|
799
|
+
]);
|
|
800
|
+
}
|
|
801
|
+
get keyPath() {
|
|
802
|
+
return this._keyPath;
|
|
803
|
+
}
|
|
804
|
+
getRefFields() {
|
|
805
|
+
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
806
|
+
return ref ? [ref] : [];
|
|
807
|
+
}
|
|
808
|
+
get returnType() {
|
|
809
|
+
const [refNode] = this._refs || [];
|
|
810
|
+
if (refNode && refNode.flags & 1 /* VariableField */) {
|
|
811
|
+
return refNode.type;
|
|
812
|
+
}
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* 业务重改该方法可快速定制自己的 Path 表达式
|
|
817
|
+
* - 只需要将业务的 Path 解析为变量系统的 KeyPath 即可
|
|
818
|
+
* @param json 业务定义的 Path 表达式
|
|
819
|
+
* @returns
|
|
820
|
+
*/
|
|
821
|
+
parseToKeyPath(json) {
|
|
822
|
+
return json.keyPath;
|
|
823
|
+
}
|
|
824
|
+
fromJSON(json) {
|
|
825
|
+
const keyPath = this.parseToKeyPath(json);
|
|
826
|
+
if (!shallowEqual3(keyPath, this._keyPath)) {
|
|
827
|
+
this._keyPath = keyPath;
|
|
828
|
+
this.refreshRefs();
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
toJSON() {
|
|
832
|
+
return {
|
|
833
|
+
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
834
|
+
keyPath: this._keyPath
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
KeyPathExpression.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
839
|
+
|
|
840
|
+
// src/ast/expression/enumerate-expression.ts
|
|
841
|
+
var EnumerateExpression = class extends BaseExpression {
|
|
842
|
+
get enumerateFor() {
|
|
843
|
+
return this._enumerateFor;
|
|
844
|
+
}
|
|
845
|
+
get returnType() {
|
|
846
|
+
const childReturnType = this.enumerateFor?.returnType;
|
|
847
|
+
if (childReturnType?.kind === "Array" /* Array */) {
|
|
848
|
+
return childReturnType.items;
|
|
849
|
+
}
|
|
850
|
+
return void 0;
|
|
851
|
+
}
|
|
852
|
+
getRefFields() {
|
|
853
|
+
return [];
|
|
854
|
+
}
|
|
855
|
+
fromJSON({ enumerateFor: expression }) {
|
|
856
|
+
this.updateChildNodeByKey("_enumerateFor", expression);
|
|
857
|
+
}
|
|
858
|
+
toJSON() {
|
|
859
|
+
return {
|
|
860
|
+
kind: "EnumerateExpression" /* EnumerateExpression */,
|
|
861
|
+
enumerateFor: this.enumerateFor?.toJSON()
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
EnumerateExpression.kind = "EnumerateExpression" /* EnumerateExpression */;
|
|
866
|
+
|
|
867
|
+
// src/ast/expression/keypath-expression-v2.ts
|
|
868
|
+
import { shallowEqual as shallowEqual4 } from "fast-equals";
|
|
869
|
+
|
|
870
|
+
// src/ast/utils/expression.ts
|
|
871
|
+
import { intersection } from "lodash";
|
|
872
|
+
function getAllRefs(ast) {
|
|
873
|
+
return getAllChildren(ast).filter((_child) => _child.flags & 4 /* Expression */).map((_child) => _child.refs).flat().filter(Boolean);
|
|
874
|
+
}
|
|
875
|
+
function checkRefCycle(curr, refNodes) {
|
|
876
|
+
if (intersection(curr.scope.coverScopes, refNodes.map((_ref) => _ref?.scope).filter(Boolean)).length === 0) {
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
879
|
+
const visited = /* @__PURE__ */ new Set();
|
|
880
|
+
const queue = [...refNodes];
|
|
881
|
+
while (queue.length) {
|
|
882
|
+
const currNode = queue.shift();
|
|
883
|
+
visited.add(currNode);
|
|
884
|
+
for (const ref of getAllRefs(currNode).filter((_ref) => !visited.has(_ref))) {
|
|
885
|
+
queue.push(ref);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return intersection(Array.from(visited), getParentFields(curr)).length > 0;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// src/ast/expression/keypath-expression-v2.ts
|
|
892
|
+
var KeyPathExpressionV2 = class extends BaseExpression {
|
|
893
|
+
constructor(params, opts) {
|
|
894
|
+
super(params, opts);
|
|
895
|
+
this._keyPath = [];
|
|
896
|
+
this.toDispose.pushAll([
|
|
897
|
+
// 可以用变量列表变化时候 (有新增或者删除时)
|
|
898
|
+
this.scope.available.onVariableListChange(() => {
|
|
899
|
+
this.refreshRefs();
|
|
900
|
+
}),
|
|
901
|
+
// this._keyPath 指向的可引用变量发生变化时,刷新引用数据
|
|
902
|
+
this.scope.available.onAnyVariableChange((_v) => {
|
|
903
|
+
if (_v.key === this._keyPath[0]) {
|
|
904
|
+
this.refreshRefs();
|
|
905
|
+
}
|
|
906
|
+
}),
|
|
907
|
+
subsToDisposable(
|
|
908
|
+
this.refs$.subscribe((_type) => {
|
|
909
|
+
const [ref] = this._refs;
|
|
910
|
+
if (this.prevRefTypeHash !== ref?.type?.hash) {
|
|
911
|
+
this.prevRefTypeHash = ref?.type?.hash;
|
|
912
|
+
this.updateChildNodeByKey("_returnType", this.getReturnTypeJSONByRef(ref));
|
|
913
|
+
}
|
|
914
|
+
})
|
|
915
|
+
)
|
|
916
|
+
]);
|
|
917
|
+
}
|
|
918
|
+
get keyPath() {
|
|
919
|
+
return this._keyPath;
|
|
920
|
+
}
|
|
921
|
+
getRefFields() {
|
|
922
|
+
const ref = this.scope.available.getByKeyPath(this._keyPath);
|
|
923
|
+
if (checkRefCycle(this, [ref])) {
|
|
924
|
+
console.warn(
|
|
925
|
+
"[CustomKeyPathExpression] checkRefCycle: Reference Cycle Existed",
|
|
926
|
+
this.parentFields.map((_field) => _field.key).reverse()
|
|
927
|
+
);
|
|
928
|
+
return [];
|
|
929
|
+
}
|
|
930
|
+
return ref ? [ref] : [];
|
|
931
|
+
}
|
|
932
|
+
get returnType() {
|
|
933
|
+
return this._returnType;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* 业务重改该方法可快速定制自己的 Path 表达式
|
|
937
|
+
* - 只需要将业务的 Path 解析为变量系统的 KeyPath 即可
|
|
938
|
+
* @param json 业务定义的 Path 表达式
|
|
939
|
+
* @returns
|
|
940
|
+
*/
|
|
941
|
+
parseToKeyPath(json) {
|
|
942
|
+
return json.keyPath;
|
|
943
|
+
}
|
|
944
|
+
fromJSON(json) {
|
|
945
|
+
const keyPath = this.parseToKeyPath(json);
|
|
946
|
+
if (!shallowEqual4(keyPath, this._keyPath)) {
|
|
947
|
+
this._keyPath = keyPath;
|
|
948
|
+
this.refreshRefs();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
getReturnTypeJSONByRef(_ref) {
|
|
952
|
+
return _ref?.type?.toJSON();
|
|
953
|
+
}
|
|
954
|
+
toJSON() {
|
|
955
|
+
return {
|
|
956
|
+
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
957
|
+
keyPath: this._keyPath
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
KeyPathExpressionV2.kind = "KeyPathExpression" /* KeyPathExpression */;
|
|
962
|
+
|
|
963
|
+
// src/ast/declaration/variable-declaration.ts
|
|
964
|
+
import { Disposable as Disposable3 } from "@flowgram.ai/utils";
|
|
965
|
+
|
|
966
|
+
// src/ast/declaration/base-variable-field.ts
|
|
967
|
+
import { shallowEqual as shallowEqual5 } from "fast-equals";
|
|
968
|
+
var BaseVariableField = class extends ASTNode {
|
|
969
|
+
constructor() {
|
|
970
|
+
super(...arguments);
|
|
971
|
+
this.flags = 1 /* VariableField */;
|
|
972
|
+
this._meta = {};
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* 父变量字段,通过由近而远的方式进行排序
|
|
976
|
+
*/
|
|
977
|
+
get parentFields() {
|
|
978
|
+
return getParentFields(this);
|
|
979
|
+
}
|
|
980
|
+
get meta() {
|
|
981
|
+
return this._meta;
|
|
982
|
+
}
|
|
983
|
+
get type() {
|
|
984
|
+
return this._initializer?.returnType || this._type;
|
|
985
|
+
}
|
|
986
|
+
get initializer() {
|
|
987
|
+
return this._initializer;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* 解析 VariableDeclarationJSON 从而生成变量声明节点
|
|
991
|
+
*/
|
|
992
|
+
fromJSON({ type, initializer, meta }) {
|
|
993
|
+
this.updateType(type);
|
|
994
|
+
this.updateInitializer(initializer);
|
|
995
|
+
this.updateMeta(meta);
|
|
996
|
+
}
|
|
997
|
+
updateType(type) {
|
|
998
|
+
const nextTypeJson = typeof type === "string" ? { kind: type } : type;
|
|
999
|
+
this.updateChildNodeByKey("_type", nextTypeJson);
|
|
1000
|
+
}
|
|
1001
|
+
updateInitializer(nextInitializer) {
|
|
1002
|
+
this.updateChildNodeByKey("_initializer", nextInitializer);
|
|
1003
|
+
}
|
|
1004
|
+
updateMeta(nextMeta) {
|
|
1005
|
+
if (!shallowEqual5(nextMeta, this._meta)) {
|
|
1006
|
+
this._meta = nextMeta;
|
|
1007
|
+
this.fireChange();
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* 根据 keyPath 去找下钻的变量字段
|
|
1012
|
+
* @param keyPath
|
|
1013
|
+
* @returns
|
|
1014
|
+
*/
|
|
1015
|
+
getByKeyPath(keyPath) {
|
|
1016
|
+
if (this.type?.flags & 16 /* DrilldownType */) {
|
|
1017
|
+
return this.type.getByKeyPath(keyPath);
|
|
1018
|
+
}
|
|
1019
|
+
return void 0;
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* 监听类型变化
|
|
1023
|
+
* @param observer
|
|
1024
|
+
* @returns
|
|
1025
|
+
*/
|
|
1026
|
+
onTypeChange(observer) {
|
|
1027
|
+
return this.subscribe(observer, { selector: (curr) => curr.type });
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* 转换为 JSON
|
|
1031
|
+
* @returns
|
|
1032
|
+
*/
|
|
1033
|
+
toJSON() {
|
|
1034
|
+
return {
|
|
1035
|
+
kind: this.kind,
|
|
1036
|
+
key: this.key,
|
|
1037
|
+
type: this.type?.toJSON(),
|
|
1038
|
+
initializer: this.initializer?.toJSON(),
|
|
1039
|
+
meta: this._meta
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
// src/ast/declaration/variable-declaration.ts
|
|
1045
|
+
var VariableDeclaration = class extends BaseVariableField {
|
|
1046
|
+
constructor(params) {
|
|
1047
|
+
super(params);
|
|
1048
|
+
this._order = 0;
|
|
1049
|
+
this.scope.output.addVariableToTable(this);
|
|
1050
|
+
this.toDispose.push(
|
|
1051
|
+
Disposable3.create(() => {
|
|
1052
|
+
this.scope.output.setHasChanges();
|
|
1053
|
+
this.scope.output.removeVariableFromTable(this.key);
|
|
1054
|
+
})
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
get order() {
|
|
1058
|
+
return this._order;
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* 解析 VariableDeclarationJSON 从而生成变量声明节点
|
|
1062
|
+
*/
|
|
1063
|
+
fromJSON({ order, ...rest }) {
|
|
1064
|
+
this.updateOrder(order);
|
|
1065
|
+
super.fromJSON(rest);
|
|
1066
|
+
}
|
|
1067
|
+
updateOrder(order = 0) {
|
|
1068
|
+
if (order !== this._order) {
|
|
1069
|
+
this._order = order;
|
|
1070
|
+
this.scope.output.setHasChanges();
|
|
1071
|
+
this.fireChange();
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
// 监听类型变化
|
|
1075
|
+
onTypeChange(observer) {
|
|
1076
|
+
return this.subscribe(observer, { selector: (curr) => curr.type });
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
VariableDeclaration.kind = "VariableDeclaration" /* VariableDeclaration */;
|
|
1080
|
+
|
|
1081
|
+
// src/ast/declaration/variable-declaration-list.ts
|
|
1082
|
+
var VariableDeclarationList = class extends ASTNode {
|
|
1083
|
+
constructor() {
|
|
1084
|
+
super(...arguments);
|
|
1085
|
+
this.declarationTable = /* @__PURE__ */ new Map();
|
|
1086
|
+
}
|
|
1087
|
+
fromJSON({ declarations, startOrder }) {
|
|
1088
|
+
const removedKeys = new Set(this.declarationTable.keys());
|
|
1089
|
+
const prev = [...this.declarations || []];
|
|
1090
|
+
this.declarations = (declarations || []).map(
|
|
1091
|
+
(declaration, idx) => {
|
|
1092
|
+
const order = (startOrder || 0) + idx;
|
|
1093
|
+
const declarationKey = declaration.key || this.declarations?.[idx]?.key;
|
|
1094
|
+
const existDeclaration = this.declarationTable.get(declarationKey);
|
|
1095
|
+
if (declarationKey) {
|
|
1096
|
+
removedKeys.delete(declarationKey);
|
|
1097
|
+
}
|
|
1098
|
+
if (existDeclaration) {
|
|
1099
|
+
existDeclaration.fromJSON({ order, ...declaration });
|
|
1100
|
+
return existDeclaration;
|
|
1101
|
+
} else {
|
|
1102
|
+
const newDeclaration = this.createChildNode({
|
|
1103
|
+
order,
|
|
1104
|
+
...declaration,
|
|
1105
|
+
kind: "VariableDeclaration" /* VariableDeclaration */
|
|
1106
|
+
});
|
|
1107
|
+
this.fireChange();
|
|
1108
|
+
this.declarationTable.set(newDeclaration.key, newDeclaration);
|
|
1109
|
+
return newDeclaration;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
);
|
|
1113
|
+
removedKeys.forEach((key) => {
|
|
1114
|
+
const declaration = this.declarationTable.get(key);
|
|
1115
|
+
declaration?.dispose();
|
|
1116
|
+
this.declarationTable.delete(key);
|
|
1117
|
+
});
|
|
1118
|
+
this.dispatchGlobalEvent({
|
|
1119
|
+
type: "VariableListChange",
|
|
1120
|
+
payload: {
|
|
1121
|
+
prev,
|
|
1122
|
+
next: [...this.declarations]
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
toJSON() {
|
|
1127
|
+
return {
|
|
1128
|
+
kind: "VariableDeclarationList" /* VariableDeclarationList */,
|
|
1129
|
+
properties: this.declarations.map((_declaration) => _declaration.toJSON())
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
VariableDeclarationList.kind = "VariableDeclarationList" /* VariableDeclarationList */;
|
|
1134
|
+
|
|
1135
|
+
// src/ast/declaration/property.ts
|
|
1136
|
+
var Property = class extends BaseVariableField {
|
|
1137
|
+
};
|
|
1138
|
+
Property.kind = "Property" /* Property */;
|
|
1139
|
+
|
|
1140
|
+
// src/ast/common/data-node.ts
|
|
1141
|
+
import { shallowEqual as shallowEqual6 } from "fast-equals";
|
|
1142
|
+
var DataNode = class extends ASTNode {
|
|
1143
|
+
get data() {
|
|
1144
|
+
return this._data;
|
|
1145
|
+
}
|
|
1146
|
+
fromJSON(json) {
|
|
1147
|
+
const { kind, ...restData } = json;
|
|
1148
|
+
if (!shallowEqual6(restData, this._data)) {
|
|
1149
|
+
this._data = restData;
|
|
1150
|
+
this.fireChange();
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
toJSON() {
|
|
1154
|
+
return {
|
|
1155
|
+
kind: "DataNode" /* DataNode */,
|
|
1156
|
+
...this._data
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
partialUpdate(nextData) {
|
|
1160
|
+
if (!shallowEqual6(nextData, this._data)) {
|
|
1161
|
+
this._data = {
|
|
1162
|
+
...this._data,
|
|
1163
|
+
...nextData
|
|
1164
|
+
};
|
|
1165
|
+
this.fireChange();
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
DataNode.kind = "DataNode" /* DataNode */;
|
|
1170
|
+
|
|
1171
|
+
// src/ast/common/list-node.ts
|
|
1172
|
+
var ListNode = class extends ASTNode {
|
|
1173
|
+
get list() {
|
|
1174
|
+
return this._list;
|
|
1175
|
+
}
|
|
1176
|
+
fromJSON({ list }) {
|
|
1177
|
+
this._list.slice(list.length).forEach((_item) => {
|
|
1178
|
+
_item.dispose();
|
|
1179
|
+
this.fireChange();
|
|
1180
|
+
});
|
|
1181
|
+
this._list = list.map((_item, idx) => {
|
|
1182
|
+
const prevItem = this._list[idx];
|
|
1183
|
+
if (prevItem.kind !== _item.kind) {
|
|
1184
|
+
prevItem.dispose();
|
|
1185
|
+
this.fireChange();
|
|
1186
|
+
return this.createChildNode(_item);
|
|
1187
|
+
}
|
|
1188
|
+
prevItem.fromJSON(_item);
|
|
1189
|
+
return prevItem;
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
toJSON() {
|
|
1193
|
+
return {
|
|
1194
|
+
kind: "ListNode" /* ListNode */,
|
|
1195
|
+
list: this._list.map((item) => item.toJSON())
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
ListNode.kind = "ListNode" /* ListNode */;
|
|
1200
|
+
|
|
1201
|
+
// src/ast/common/map-node.ts
|
|
1202
|
+
var MapNode = class extends ASTNode {
|
|
1203
|
+
constructor() {
|
|
1204
|
+
super(...arguments);
|
|
1205
|
+
this.map = /* @__PURE__ */ new Map();
|
|
1206
|
+
}
|
|
1207
|
+
fromJSON({ map: map4 }) {
|
|
1208
|
+
const removedKeys = new Set(this.map.keys());
|
|
1209
|
+
for (const [key, item] of map4 || []) {
|
|
1210
|
+
removedKeys.delete(key);
|
|
1211
|
+
this.set(key, item);
|
|
1212
|
+
}
|
|
1213
|
+
for (const removeKey of Array.from(removedKeys)) {
|
|
1214
|
+
this.remove(removeKey);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
toJSON() {
|
|
1218
|
+
return {
|
|
1219
|
+
kind: "MapNode" /* MapNode */,
|
|
1220
|
+
map: Array.from(this.map.entries())
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* 往 Map 中设置 ASTNode
|
|
1225
|
+
* @param key ASTNode 的索引,
|
|
1226
|
+
* @param json
|
|
1227
|
+
*/
|
|
1228
|
+
set(key, nextJSON) {
|
|
1229
|
+
return this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
1230
|
+
getChildNode: () => this.get(key),
|
|
1231
|
+
removeChildNode: () => this.map.delete(key),
|
|
1232
|
+
updateChildNode: (nextNode) => this.map.set(key, nextNode),
|
|
1233
|
+
nextJSON
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* 移除指定 ASTNode
|
|
1238
|
+
* @param key
|
|
1239
|
+
*/
|
|
1240
|
+
remove(key) {
|
|
1241
|
+
this.get(key)?.dispose();
|
|
1242
|
+
this.map.delete(key);
|
|
1243
|
+
this.fireChange();
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* 获取 ASTNode
|
|
1247
|
+
* @param key
|
|
1248
|
+
* @returns
|
|
1249
|
+
*/
|
|
1250
|
+
get(key) {
|
|
1251
|
+
return this.map.get(key);
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
MapNode.kind = "MapNode" /* MapNode */;
|
|
1255
|
+
|
|
1256
|
+
// src/ast/ast-registers.ts
|
|
1257
|
+
var ASTRegisters = class {
|
|
1258
|
+
/**
|
|
1259
|
+
* 核心 AST 节点注册
|
|
1260
|
+
*/
|
|
1261
|
+
constructor() {
|
|
1262
|
+
this.injectors = /* @__PURE__ */ new Map();
|
|
1263
|
+
this.astMap = /* @__PURE__ */ new Map();
|
|
1264
|
+
this.registerAST(StringType);
|
|
1265
|
+
this.registerAST(NumberType);
|
|
1266
|
+
this.registerAST(BooleanType);
|
|
1267
|
+
this.registerAST(IntegerType);
|
|
1268
|
+
this.registerAST(ObjectType);
|
|
1269
|
+
this.registerAST(ArrayType);
|
|
1270
|
+
this.registerAST(MapType);
|
|
1271
|
+
this.registerAST(Property);
|
|
1272
|
+
this.registerAST(VariableDeclaration);
|
|
1273
|
+
this.registerAST(VariableDeclarationList);
|
|
1274
|
+
this.registerAST(KeyPathExpression);
|
|
1275
|
+
this.registerAST(EnumerateExpression);
|
|
1276
|
+
this.registerAST(ExpressionList);
|
|
1277
|
+
this.registerAST(MapNode);
|
|
1278
|
+
this.registerAST(DataNode);
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* 创建 AST 节点
|
|
1282
|
+
* @param param 创建参数
|
|
1283
|
+
* @returns
|
|
1284
|
+
*/
|
|
1285
|
+
createAST(json, { parent, scope }) {
|
|
1286
|
+
const Registry = this.astMap.get(json.kind);
|
|
1287
|
+
if (!Registry) {
|
|
1288
|
+
throw Error(`ASTKind: ${String(json.kind)} can not find its ASTNode Registry`);
|
|
1289
|
+
}
|
|
1290
|
+
const injector = this.injectors.get(json.kind);
|
|
1291
|
+
const node = new Registry(
|
|
1292
|
+
{
|
|
1293
|
+
key: json.key,
|
|
1294
|
+
scope,
|
|
1295
|
+
parent
|
|
1296
|
+
},
|
|
1297
|
+
injector?.() || {}
|
|
1298
|
+
);
|
|
1299
|
+
node.changeLocked = true;
|
|
1300
|
+
node.fromJSON(omit(json, ["key", "kind"]));
|
|
1301
|
+
node.changeLocked = false;
|
|
1302
|
+
if (Reflect.hasMetadata(POST_CONSTRUCT_AST_SYMBOL, node)) {
|
|
1303
|
+
const postConstructKey = Reflect.getMetadata(POST_CONSTRUCT_AST_SYMBOL, node);
|
|
1304
|
+
node[postConstructKey]?.();
|
|
1305
|
+
}
|
|
1306
|
+
return node;
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* 根据 AST 节点类型获取节点 Registry
|
|
1310
|
+
* @param kind
|
|
1311
|
+
* @returns
|
|
1312
|
+
*/
|
|
1313
|
+
getASTRegistryByKind(kind) {
|
|
1314
|
+
return this.astMap.get(kind);
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* 注册 AST 节点
|
|
1318
|
+
* @param ASTNode
|
|
1319
|
+
* @param injector
|
|
1320
|
+
*/
|
|
1321
|
+
registerAST(ASTNode2, injector) {
|
|
1322
|
+
this.astMap.set(ASTNode2.kind, ASTNode2);
|
|
1323
|
+
if (injector) {
|
|
1324
|
+
this.injectors.set(ASTNode2.kind, injector);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
ASTRegisters = __decorateClass([
|
|
1329
|
+
injectable2()
|
|
1330
|
+
], ASTRegisters);
|
|
1331
|
+
|
|
1332
|
+
// src/ast/factory.ts
|
|
1333
|
+
var ASTFactory;
|
|
1334
|
+
((ASTFactory2) => {
|
|
1335
|
+
ASTFactory2.createString = () => ({ kind: "String" /* String */ });
|
|
1336
|
+
ASTFactory2.createNumber = () => ({ kind: "Number" /* Number */ });
|
|
1337
|
+
ASTFactory2.createBoolean = () => ({ kind: "Boolean" /* Boolean */ });
|
|
1338
|
+
ASTFactory2.createInteger = () => ({ kind: "Integer" /* Integer */ });
|
|
1339
|
+
ASTFactory2.createObject = (json) => ({
|
|
1340
|
+
kind: "Object" /* Object */,
|
|
1341
|
+
...json
|
|
1342
|
+
});
|
|
1343
|
+
ASTFactory2.createArray = (json) => ({
|
|
1344
|
+
kind: "Array" /* Array */,
|
|
1345
|
+
...json
|
|
1346
|
+
});
|
|
1347
|
+
ASTFactory2.createMap = (json) => ({
|
|
1348
|
+
kind: "Map" /* Map */,
|
|
1349
|
+
...json
|
|
1350
|
+
});
|
|
1351
|
+
ASTFactory2.createUnion = (json) => ({
|
|
1352
|
+
kind: "Union" /* Union */,
|
|
1353
|
+
...json
|
|
1354
|
+
});
|
|
1355
|
+
ASTFactory2.createVariableDeclaration = (json) => ({
|
|
1356
|
+
kind: "VariableDeclaration" /* VariableDeclaration */,
|
|
1357
|
+
...json
|
|
1358
|
+
});
|
|
1359
|
+
ASTFactory2.createProperty = (json) => ({
|
|
1360
|
+
kind: "Property" /* Property */,
|
|
1361
|
+
...json
|
|
1362
|
+
});
|
|
1363
|
+
ASTFactory2.createVariableDeclarationList = (json) => ({
|
|
1364
|
+
kind: "VariableDeclarationList" /* VariableDeclarationList */,
|
|
1365
|
+
...json
|
|
1366
|
+
});
|
|
1367
|
+
ASTFactory2.createEnumerateExpression = (json) => ({
|
|
1368
|
+
kind: "EnumerateExpression" /* EnumerateExpression */,
|
|
1369
|
+
...json
|
|
1370
|
+
});
|
|
1371
|
+
ASTFactory2.createKeyPathExpression = (json) => ({
|
|
1372
|
+
kind: "KeyPathExpression" /* KeyPathExpression */,
|
|
1373
|
+
...json
|
|
1374
|
+
});
|
|
1375
|
+
})(ASTFactory || (ASTFactory = {}));
|
|
1376
|
+
|
|
1377
|
+
// src/scope/variable-table.ts
|
|
1378
|
+
import { Subject as Subject2, merge, share as share2, skip as skip2, switchMap as switchMap2 } from "rxjs";
|
|
1379
|
+
import { Emitter } from "@flowgram.ai/utils";
|
|
1380
|
+
import { DisposableCollection as DisposableCollection3 } from "@flowgram.ai/utils";
|
|
1381
|
+
var VariableTable = class {
|
|
1382
|
+
constructor(parentTable) {
|
|
1383
|
+
this.parentTable = parentTable;
|
|
1384
|
+
this.table = /* @__PURE__ */ new Map();
|
|
1385
|
+
this.onDataChangeEmitter = new Emitter();
|
|
1386
|
+
this.variables$ = new Subject2();
|
|
1387
|
+
// 监听变量列表中的单个变量变化
|
|
1388
|
+
this.anyVariableChange$ = this.variables$.pipe(
|
|
1389
|
+
switchMap2(
|
|
1390
|
+
(_variables) => merge(
|
|
1391
|
+
..._variables.map(
|
|
1392
|
+
(_v) => _v.value$.pipe(
|
|
1393
|
+
// 跳过 BehaviorSubject 第一个
|
|
1394
|
+
skip2(1)
|
|
1395
|
+
)
|
|
1396
|
+
)
|
|
1397
|
+
)
|
|
1398
|
+
),
|
|
1399
|
+
share2()
|
|
1400
|
+
);
|
|
1401
|
+
this.onDataChange = this.onDataChangeEmitter.event;
|
|
1402
|
+
this._version = 0;
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* 监听任意变量变化
|
|
1406
|
+
* @param observer 监听器,变量变化时会吐出值
|
|
1407
|
+
* @returns
|
|
1408
|
+
*/
|
|
1409
|
+
onAnyVariableChange(observer) {
|
|
1410
|
+
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* 列表或者任意变量变化
|
|
1414
|
+
* @param observer
|
|
1415
|
+
*/
|
|
1416
|
+
onAnyChange(observer) {
|
|
1417
|
+
const disposables = new DisposableCollection3();
|
|
1418
|
+
disposables.pushAll([this.onDataChange(observer), this.onAnyVariableChange(observer)]);
|
|
1419
|
+
return disposables;
|
|
1420
|
+
}
|
|
1421
|
+
fireChange() {
|
|
1422
|
+
this._version++;
|
|
1423
|
+
this.onDataChangeEmitter.fire();
|
|
1424
|
+
this.parentTable?.fireChange();
|
|
1425
|
+
}
|
|
1426
|
+
get version() {
|
|
1427
|
+
return this._version;
|
|
1428
|
+
}
|
|
1429
|
+
get variables() {
|
|
1430
|
+
return Array.from(this.table.values());
|
|
1431
|
+
}
|
|
1432
|
+
get variableKeys() {
|
|
1433
|
+
return Array.from(this.table.keys());
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* 根据 keyPath 找到对应的变量,或 Property 节点
|
|
1437
|
+
* @param keyPath
|
|
1438
|
+
* @returns
|
|
1439
|
+
*/
|
|
1440
|
+
getByKeyPath(keyPath) {
|
|
1441
|
+
const [variableKey, ...propertyKeys] = keyPath || [];
|
|
1442
|
+
if (!variableKey) {
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1445
|
+
const variable = this.getVariableByKey(variableKey);
|
|
1446
|
+
return propertyKeys.length ? variable?.getByKeyPath(propertyKeys) : variable;
|
|
1447
|
+
}
|
|
1448
|
+
/**
|
|
1449
|
+
* 根据 key 值找到相应的变量
|
|
1450
|
+
* @param key
|
|
1451
|
+
* @returns
|
|
1452
|
+
*/
|
|
1453
|
+
getVariableByKey(key) {
|
|
1454
|
+
return this.table.get(key);
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* 往 variableTable 添加输出变量
|
|
1458
|
+
* @param variable
|
|
1459
|
+
*/
|
|
1460
|
+
addVariableToTable(variable) {
|
|
1461
|
+
this.table.set(variable.key, variable);
|
|
1462
|
+
if (this.parentTable) {
|
|
1463
|
+
this.parentTable.addVariableToTable(variable);
|
|
1464
|
+
}
|
|
1465
|
+
this.variables$.next(this.variables);
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* 从 variableTable 中移除变量
|
|
1469
|
+
* @param key
|
|
1470
|
+
*/
|
|
1471
|
+
removeVariableFromTable(key) {
|
|
1472
|
+
this.table.delete(key);
|
|
1473
|
+
if (this.parentTable) {
|
|
1474
|
+
this.parentTable.removeVariableFromTable(key);
|
|
1475
|
+
}
|
|
1476
|
+
this.variables$.next(this.variables);
|
|
1477
|
+
}
|
|
1478
|
+
dispose() {
|
|
1479
|
+
this.variableKeys.forEach((_key) => this.parentTable?.removeVariableFromTable(_key));
|
|
1480
|
+
this.onDataChangeEmitter.dispose();
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
// src/scope/datas/scope-output-data.ts
|
|
1485
|
+
var ScopeOutputData = class {
|
|
1486
|
+
constructor(scope) {
|
|
1487
|
+
this.scope = scope;
|
|
1488
|
+
this.memo = createMemo();
|
|
1489
|
+
this._hasChanges = false;
|
|
1490
|
+
this.variableTable = new VariableTable(scope.variableEngine.globalVariableTable);
|
|
1491
|
+
this.scope.toDispose.pushAll([
|
|
1492
|
+
// AST 根节点更新时,检查在这次 AST 变化期间节点是否有变化
|
|
1493
|
+
this.scope.ast.subscribe(() => {
|
|
1494
|
+
if (this._hasChanges) {
|
|
1495
|
+
this.memo.clear();
|
|
1496
|
+
this.notifyCoversChange();
|
|
1497
|
+
this.variableTable.fireChange();
|
|
1498
|
+
this._hasChanges = false;
|
|
1499
|
+
}
|
|
1500
|
+
}),
|
|
1501
|
+
this.variableTable
|
|
1502
|
+
]);
|
|
1503
|
+
}
|
|
1504
|
+
get variableEngine() {
|
|
1505
|
+
return this.scope.variableEngine;
|
|
1506
|
+
}
|
|
1507
|
+
get globalVariableTable() {
|
|
1508
|
+
return this.scope.variableEngine.globalVariableTable;
|
|
1509
|
+
}
|
|
1510
|
+
get onDataChange() {
|
|
1511
|
+
return this.variableTable.onDataChange.bind(this.variableTable);
|
|
1512
|
+
}
|
|
1513
|
+
get onAnyVariableChange() {
|
|
1514
|
+
return this.variableTable.onAnyVariableChange.bind(this.variableTable);
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* 作用域输出变量
|
|
1518
|
+
*/
|
|
1519
|
+
get variables() {
|
|
1520
|
+
return this.memo(
|
|
1521
|
+
"variables",
|
|
1522
|
+
() => this.variableTable.variables.sort((a, b) => a.order - b.order)
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* 输出的变量 keys
|
|
1527
|
+
*/
|
|
1528
|
+
get variableKeys() {
|
|
1529
|
+
return this.memo("variableKeys", () => this.variableTable.variableKeys);
|
|
1530
|
+
}
|
|
1531
|
+
addVariableToTable(variable) {
|
|
1532
|
+
if (variable.scope !== this.scope) {
|
|
1533
|
+
throw Error("VariableDeclaration must be a ast node in scope");
|
|
1534
|
+
}
|
|
1535
|
+
this.variableTable.addVariableToTable(variable);
|
|
1536
|
+
this._hasChanges = true;
|
|
1537
|
+
}
|
|
1538
|
+
// 标记为发生了变化,用于变量排序变化的场景
|
|
1539
|
+
setHasChanges() {
|
|
1540
|
+
this._hasChanges = true;
|
|
1541
|
+
}
|
|
1542
|
+
removeVariableFromTable(key) {
|
|
1543
|
+
this.variableTable.removeVariableFromTable(key);
|
|
1544
|
+
this._hasChanges = true;
|
|
1545
|
+
}
|
|
1546
|
+
getVariableByKey(key) {
|
|
1547
|
+
return this.variableTable.getVariableByKey(key);
|
|
1548
|
+
}
|
|
1549
|
+
// 通知覆盖作用域更新可用变量
|
|
1550
|
+
notifyCoversChange() {
|
|
1551
|
+
this.scope.coverScopes.forEach((scope) => scope.available.refresh());
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// src/scope/datas/scope-available-data.ts
|
|
1556
|
+
import {
|
|
1557
|
+
Subject as Subject3,
|
|
1558
|
+
distinctUntilChanged as distinctUntilChanged3,
|
|
1559
|
+
map as map3,
|
|
1560
|
+
merge as merge2,
|
|
1561
|
+
share as share3,
|
|
1562
|
+
skip as skip3,
|
|
1563
|
+
switchMap as switchMap3
|
|
1564
|
+
} from "rxjs";
|
|
1565
|
+
import { flatten } from "lodash";
|
|
1566
|
+
import { shallowEqual as shallowEqual7 } from "fast-equals";
|
|
1567
|
+
import { Disposable as Disposable5 } from "@flowgram.ai/utils";
|
|
1568
|
+
import { Emitter as Emitter2 } from "@flowgram.ai/utils";
|
|
1569
|
+
var ScopeAvailableData = class {
|
|
1570
|
+
constructor(scope) {
|
|
1571
|
+
this.scope = scope;
|
|
1572
|
+
this.memo = createMemo();
|
|
1573
|
+
this.refresh$ = new Subject3();
|
|
1574
|
+
this._variables = [];
|
|
1575
|
+
/**
|
|
1576
|
+
* 监听
|
|
1577
|
+
*/
|
|
1578
|
+
this.variables$ = this.refresh$.pipe(
|
|
1579
|
+
// 输出变量是否 version 发生变化
|
|
1580
|
+
map3(() => flatten(this.depScopes.map((scope) => scope.output.variables || []))),
|
|
1581
|
+
// 变量列表浅比较
|
|
1582
|
+
distinctUntilChanged3(shallowEqual7),
|
|
1583
|
+
share3()
|
|
1584
|
+
);
|
|
1585
|
+
// 监听变量列表中的单个变量变化
|
|
1586
|
+
this.anyVariableChange$ = this.variables$.pipe(
|
|
1587
|
+
switchMap3(
|
|
1588
|
+
(_variables) => merge2(
|
|
1589
|
+
..._variables.map(
|
|
1590
|
+
(_v) => _v.value$.pipe(
|
|
1591
|
+
// 跳过 BehaviorSubject 第一个
|
|
1592
|
+
skip3(1)
|
|
1593
|
+
)
|
|
1594
|
+
)
|
|
1595
|
+
)
|
|
1596
|
+
),
|
|
1597
|
+
share3()
|
|
1598
|
+
);
|
|
1599
|
+
this.onDataChangeEmitter = new Emitter2();
|
|
1600
|
+
/**
|
|
1601
|
+
* 监听变量列表变化 + 任意子变量变化
|
|
1602
|
+
*/
|
|
1603
|
+
this.onDataChange = this.onDataChangeEmitter.event;
|
|
1604
|
+
this.scope.toDispose.pushAll([
|
|
1605
|
+
this.onVariableListChange((_variables) => {
|
|
1606
|
+
this._variables = _variables;
|
|
1607
|
+
this.memo.clear();
|
|
1608
|
+
this.onDataChangeEmitter.fire(this._variables);
|
|
1609
|
+
}),
|
|
1610
|
+
this.onAnyVariableChange(() => {
|
|
1611
|
+
this.onDataChangeEmitter.fire(this._variables);
|
|
1612
|
+
}),
|
|
1613
|
+
Disposable5.create(() => {
|
|
1614
|
+
this.refresh$.complete();
|
|
1615
|
+
this.refresh$.unsubscribe();
|
|
1616
|
+
})
|
|
1617
|
+
]);
|
|
1618
|
+
}
|
|
1619
|
+
get globalVariableTable() {
|
|
1620
|
+
return this.scope.variableEngine.globalVariableTable;
|
|
1621
|
+
}
|
|
1622
|
+
// 刷新可访问变量列表
|
|
1623
|
+
refresh() {
|
|
1624
|
+
if (this.scope.disposed) {
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
this.refresh$.next();
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* 监听任意变量变化
|
|
1631
|
+
* @param observer 监听器,变量变化时会吐出值
|
|
1632
|
+
* @returns
|
|
1633
|
+
*/
|
|
1634
|
+
onAnyVariableChange(observer) {
|
|
1635
|
+
return subsToDisposable(this.anyVariableChange$.subscribe(observer));
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* 监听变量列表变化
|
|
1639
|
+
* @param observer
|
|
1640
|
+
* @returns
|
|
1641
|
+
*/
|
|
1642
|
+
onVariableListChange(observer) {
|
|
1643
|
+
return subsToDisposable(this.variables$.subscribe(observer));
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* 获取可消费变量
|
|
1647
|
+
*/
|
|
1648
|
+
get variables() {
|
|
1649
|
+
return this._variables;
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* 获取可访问的变量 keys
|
|
1653
|
+
*/
|
|
1654
|
+
get variableKeys() {
|
|
1655
|
+
return this.memo("availableKeys", () => this._variables.map((_v) => _v.key));
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* 返回依赖的作用域
|
|
1659
|
+
*/
|
|
1660
|
+
get depScopes() {
|
|
1661
|
+
return this.scope.depScopes;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* 通过 keyPath 找到可用变量
|
|
1665
|
+
* @param keyPath
|
|
1666
|
+
* @returns
|
|
1667
|
+
*/
|
|
1668
|
+
getByKeyPath(keyPath = []) {
|
|
1669
|
+
if (!this.variableKeys.includes(keyPath[0])) {
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
return this.globalVariableTable.getByKeyPath(keyPath);
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
|
|
1676
|
+
// src/scope/datas/scope-event-data.ts
|
|
1677
|
+
import { Subject as Subject4, filter } from "rxjs";
|
|
1678
|
+
var ScopeEventData = class {
|
|
1679
|
+
constructor(scope) {
|
|
1680
|
+
this.scope = scope;
|
|
1681
|
+
this.event$ = new Subject4();
|
|
1682
|
+
scope.toDispose.pushAll([
|
|
1683
|
+
this.subscribe((_action) => {
|
|
1684
|
+
scope.variableEngine.fireGlobalEvent(_action);
|
|
1685
|
+
})
|
|
1686
|
+
]);
|
|
1687
|
+
}
|
|
1688
|
+
dispatch(action) {
|
|
1689
|
+
if (this.scope.disposed) {
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
this.event$.next(action);
|
|
1693
|
+
}
|
|
1694
|
+
subscribe(observer) {
|
|
1695
|
+
return subsToDisposable(this.event$.subscribe(observer));
|
|
1696
|
+
}
|
|
1697
|
+
on(type, observer) {
|
|
1698
|
+
return subsToDisposable(
|
|
1699
|
+
this.event$.pipe(filter((_action) => _action.type === type)).subscribe(observer)
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
};
|
|
1703
|
+
|
|
1704
|
+
// src/scope/scope.ts
|
|
1705
|
+
var Scope = class {
|
|
1706
|
+
constructor(options) {
|
|
1707
|
+
/**
|
|
1708
|
+
* 数据缓存
|
|
1709
|
+
*/
|
|
1710
|
+
this.memo = createMemo();
|
|
1711
|
+
this.toDispose = new DisposableCollection4();
|
|
1712
|
+
this.onDispose = this.toDispose.onDispose;
|
|
1713
|
+
this.id = options.id;
|
|
1714
|
+
this.meta = options.meta || {};
|
|
1715
|
+
this.variableEngine = options.variableEngine;
|
|
1716
|
+
this.event = new ScopeEventData(this);
|
|
1717
|
+
this.ast = this.variableEngine.astRegisters.createAST(
|
|
1718
|
+
{
|
|
1719
|
+
kind: "MapNode" /* MapNode */,
|
|
1720
|
+
key: this.id
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
scope: this
|
|
1724
|
+
}
|
|
1725
|
+
);
|
|
1726
|
+
this.output = new ScopeOutputData(this);
|
|
1727
|
+
this.available = new ScopeAvailableData(this);
|
|
1728
|
+
}
|
|
1729
|
+
refreshCovers() {
|
|
1730
|
+
this.memo.clear("covers");
|
|
1731
|
+
}
|
|
1732
|
+
refreshDeps() {
|
|
1733
|
+
this.memo.clear("deps");
|
|
1734
|
+
this.available.refresh();
|
|
1735
|
+
}
|
|
1736
|
+
get depScopes() {
|
|
1737
|
+
return this.memo(
|
|
1738
|
+
"deps",
|
|
1739
|
+
() => this.variableEngine.chain.getDeps(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
get coverScopes() {
|
|
1743
|
+
return this.memo(
|
|
1744
|
+
"covers",
|
|
1745
|
+
() => this.variableEngine.chain.getCovers(this).filter((_scope) => Boolean(_scope) && !_scope?.disposed)
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
dispose() {
|
|
1749
|
+
this.ast.dispose();
|
|
1750
|
+
this.toDispose.dispose();
|
|
1751
|
+
this.coverScopes.forEach((_scope) => _scope.refreshDeps());
|
|
1752
|
+
this.depScopes.forEach((_scope) => _scope.refreshCovers());
|
|
1753
|
+
}
|
|
1754
|
+
get disposed() {
|
|
1755
|
+
return this.toDispose.disposed;
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
// src/variable-engine.ts
|
|
1760
|
+
var VariableEngine = class {
|
|
1761
|
+
constructor(chain, astRegisters) {
|
|
1762
|
+
this.chain = chain;
|
|
1763
|
+
this.astRegisters = astRegisters;
|
|
1764
|
+
this.toDispose = new DisposableCollection5();
|
|
1765
|
+
this.memo = createMemo();
|
|
1766
|
+
this.scopeMap = /* @__PURE__ */ new Map();
|
|
1767
|
+
this.globalEvent$ = new Subject5();
|
|
1768
|
+
this.onScopeChangeEmitter = new Emitter3();
|
|
1769
|
+
this.globalVariableTable = new VariableTable();
|
|
1770
|
+
this.onScopeChange = this.onScopeChangeEmitter.event;
|
|
1771
|
+
this.toDispose.pushAll([
|
|
1772
|
+
chain,
|
|
1773
|
+
Disposable6.create(() => {
|
|
1774
|
+
this.getAllScopes().forEach((scope) => scope.dispose());
|
|
1775
|
+
this.globalVariableTable.dispose();
|
|
1776
|
+
})
|
|
1777
|
+
]);
|
|
1778
|
+
}
|
|
1779
|
+
get container() {
|
|
1780
|
+
return this.containerProvider();
|
|
1781
|
+
}
|
|
1782
|
+
dispose() {
|
|
1783
|
+
this.toDispose.dispose();
|
|
1784
|
+
}
|
|
1785
|
+
// 根据 scopeId 找到作用域
|
|
1786
|
+
getScopeById(scopeId) {
|
|
1787
|
+
return this.scopeMap.get(scopeId);
|
|
1788
|
+
}
|
|
1789
|
+
// 移除作用域
|
|
1790
|
+
removeScopeById(scopeId) {
|
|
1791
|
+
this.getScopeById(scopeId)?.dispose();
|
|
1792
|
+
}
|
|
1793
|
+
// 获取 Scope,如果 Scope 存在且类型相同,则会直接使用
|
|
1794
|
+
createScope(id, meta) {
|
|
1795
|
+
let scope = this.getScopeById(id);
|
|
1796
|
+
if (!scope) {
|
|
1797
|
+
scope = new Scope({ variableEngine: this, meta, id });
|
|
1798
|
+
this.scopeMap.set(id, scope);
|
|
1799
|
+
this.onScopeChangeEmitter.fire({ type: "add", scope });
|
|
1800
|
+
scope.toDispose.pushAll([
|
|
1801
|
+
scope.ast.subscribe(() => {
|
|
1802
|
+
this.onScopeChangeEmitter.fire({ type: "update", scope });
|
|
1803
|
+
}),
|
|
1804
|
+
// 可用变量发生变化
|
|
1805
|
+
scope.available.onDataChange(() => {
|
|
1806
|
+
this.onScopeChangeEmitter.fire({ type: "available", scope });
|
|
1807
|
+
})
|
|
1808
|
+
]);
|
|
1809
|
+
scope.onDispose(() => {
|
|
1810
|
+
this.scopeMap.delete(id);
|
|
1811
|
+
this.onScopeChangeEmitter.fire({ type: "delete", scope });
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
return scope;
|
|
1815
|
+
}
|
|
1816
|
+
// 获取系统中所有的作用域
|
|
1817
|
+
getAllScopes({
|
|
1818
|
+
sort
|
|
1819
|
+
} = {}) {
|
|
1820
|
+
const allScopes = Array.from(this.scopeMap.values());
|
|
1821
|
+
if (sort) {
|
|
1822
|
+
const sortScopes = this.chain.sortAll();
|
|
1823
|
+
const remainScopes = new Set(allScopes);
|
|
1824
|
+
sortScopes.forEach((_scope) => remainScopes.delete(_scope));
|
|
1825
|
+
return [...sortScopes, ...Array.from(remainScopes)];
|
|
1826
|
+
}
|
|
1827
|
+
return [...allScopes];
|
|
1828
|
+
}
|
|
1829
|
+
fireGlobalEvent(event) {
|
|
1830
|
+
this.globalEvent$.next(event);
|
|
1831
|
+
}
|
|
1832
|
+
onGlobalEvent(type, observer) {
|
|
1833
|
+
return subsToDisposable(
|
|
1834
|
+
this.globalEvent$.subscribe((_action) => {
|
|
1835
|
+
if (_action.type === type) {
|
|
1836
|
+
observer(_action);
|
|
1837
|
+
}
|
|
1838
|
+
})
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
__decorateClass([
|
|
1843
|
+
inject2(ContainerProvider)
|
|
1844
|
+
], VariableEngine.prototype, "containerProvider", 2);
|
|
1845
|
+
__decorateClass([
|
|
1846
|
+
preDestroy()
|
|
1847
|
+
], VariableEngine.prototype, "dispose", 1);
|
|
1848
|
+
VariableEngine = __decorateClass([
|
|
1849
|
+
injectable3(),
|
|
1850
|
+
__decorateParam(0, inject2(ScopeChain)),
|
|
1851
|
+
__decorateParam(1, inject2(ASTRegisters))
|
|
1852
|
+
], VariableEngine);
|
|
1853
|
+
|
|
1854
|
+
// src/services/variable-field-key-rename-service.ts
|
|
1855
|
+
import { difference } from "lodash";
|
|
1856
|
+
import { inject as inject3, injectable as injectable4, postConstruct, preDestroy as preDestroy2 } from "inversify";
|
|
1857
|
+
import { DisposableCollection as DisposableCollection6, Emitter as Emitter4 } from "@flowgram.ai/utils";
|
|
1858
|
+
var VariableFieldKeyRenameService = class {
|
|
1859
|
+
constructor() {
|
|
1860
|
+
this.toDispose = new DisposableCollection6();
|
|
1861
|
+
this.renameEmitter = new Emitter4();
|
|
1862
|
+
// 没有被 rename 的字段通过 disposeInList 透出,让业务区分变量是 rename 删除的,还是真正从列表中删除的
|
|
1863
|
+
this.disposeInListEmitter = new Emitter4();
|
|
1864
|
+
this.onRename = this.renameEmitter.event;
|
|
1865
|
+
this.onDisposeInList = this.disposeInListEmitter.event;
|
|
1866
|
+
}
|
|
1867
|
+
handleFieldListChange(ast, prev, next) {
|
|
1868
|
+
if (!ast || !prev?.length || !next?.length) {
|
|
1869
|
+
this.notifyFieldsDispose(prev, next);
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
if (prev.length !== next.length) {
|
|
1873
|
+
this.notifyFieldsDispose(prev, next);
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
let renameNodeInfo = null;
|
|
1877
|
+
let existFieldChanged = false;
|
|
1878
|
+
for (const [index, prevField] of prev.entries()) {
|
|
1879
|
+
const nextField = next[index];
|
|
1880
|
+
if (prevField.key !== nextField.key) {
|
|
1881
|
+
if (existFieldChanged) {
|
|
1882
|
+
this.notifyFieldsDispose(prev, next);
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
existFieldChanged = true;
|
|
1886
|
+
if (prevField.type?.kind === nextField.type?.kind) {
|
|
1887
|
+
renameNodeInfo = { before: prevField, after: nextField };
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
if (!renameNodeInfo) {
|
|
1892
|
+
this.notifyFieldsDispose(prev, next);
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
this.renameEmitter.fire(renameNodeInfo);
|
|
1896
|
+
}
|
|
1897
|
+
notifyFieldsDispose(prev, next) {
|
|
1898
|
+
const removedFields = difference(prev || [], next || []);
|
|
1899
|
+
removedFields.forEach((_field) => this.disposeInListEmitter.fire(_field));
|
|
1900
|
+
}
|
|
1901
|
+
init() {
|
|
1902
|
+
this.toDispose.pushAll([
|
|
1903
|
+
this.variableEngine.onGlobalEvent(
|
|
1904
|
+
"VariableListChange",
|
|
1905
|
+
(_action) => {
|
|
1906
|
+
this.handleFieldListChange(_action.ast, _action.payload?.prev, _action.payload?.next);
|
|
1907
|
+
}
|
|
1908
|
+
),
|
|
1909
|
+
this.variableEngine.onGlobalEvent(
|
|
1910
|
+
"ObjectPropertiesChange",
|
|
1911
|
+
(_action) => {
|
|
1912
|
+
this.handleFieldListChange(_action.ast, _action.payload?.prev, _action.payload?.next);
|
|
1913
|
+
}
|
|
1914
|
+
)
|
|
1915
|
+
]);
|
|
1916
|
+
}
|
|
1917
|
+
dispose() {
|
|
1918
|
+
this.toDispose.dispose();
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
__decorateClass([
|
|
1922
|
+
inject3(VariableEngine)
|
|
1923
|
+
], VariableFieldKeyRenameService.prototype, "variableEngine", 2);
|
|
1924
|
+
__decorateClass([
|
|
1925
|
+
postConstruct()
|
|
1926
|
+
], VariableFieldKeyRenameService.prototype, "init", 1);
|
|
1927
|
+
__decorateClass([
|
|
1928
|
+
preDestroy2()
|
|
1929
|
+
], VariableFieldKeyRenameService.prototype, "dispose", 1);
|
|
1930
|
+
VariableFieldKeyRenameService = __decorateClass([
|
|
1931
|
+
injectable4()
|
|
1932
|
+
], VariableFieldKeyRenameService);
|
|
1933
|
+
|
|
1934
|
+
// src/variable-container-module.ts
|
|
1935
|
+
var VariableContainerModule = new ContainerModule((bind) => {
|
|
1936
|
+
bind(VariableEngine).toSelf().inSingletonScope();
|
|
1937
|
+
bind(ASTRegisters).toSelf().inSingletonScope();
|
|
1938
|
+
bind(VariableFieldKeyRenameService).toSelf().inSingletonScope();
|
|
1939
|
+
bind(VariableEngineProvider).toDynamicValue((ctx) => () => ctx.container.get(VariableEngine));
|
|
1940
|
+
bind(ContainerProvider).toDynamicValue((ctx) => () => ctx.container);
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1943
|
+
// src/react/context.tsx
|
|
1944
|
+
import { createContext, useContext } from "react";
|
|
1945
|
+
var ScopeContext = createContext(null);
|
|
1946
|
+
var ScopeProvider = ScopeContext.Provider;
|
|
1947
|
+
var useScopeContext = () => useContext(ScopeContext);
|
|
1948
|
+
var useCurrentScope = () => useContext(ScopeContext)?.scope;
|
|
1949
|
+
|
|
1950
|
+
// src/react/hooks/useScopeAvailable.ts
|
|
1951
|
+
import { useEffect } from "react";
|
|
1952
|
+
import { useRefresh } from "@flowgram.ai/core";
|
|
1953
|
+
function useScopeAvailable() {
|
|
1954
|
+
const scope = useCurrentScope();
|
|
1955
|
+
const refresh = useRefresh();
|
|
1956
|
+
useEffect(() => {
|
|
1957
|
+
const disposable = scope.available.onDataChange(() => {
|
|
1958
|
+
refresh();
|
|
1959
|
+
});
|
|
1960
|
+
return () => disposable.dispose();
|
|
1961
|
+
}, []);
|
|
1962
|
+
return scope.available;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
// src/react/hooks/useAvailableVariables.ts
|
|
1966
|
+
import { useEffect as useEffect2 } from "react";
|
|
1967
|
+
import { useRefresh as useRefresh2, useService } from "@flowgram.ai/core";
|
|
1968
|
+
function useAvailableVariables() {
|
|
1969
|
+
const scope = useCurrentScope();
|
|
1970
|
+
const variableEngine = useService(VariableEngine);
|
|
1971
|
+
const refresh = useRefresh2();
|
|
1972
|
+
useEffect2(() => {
|
|
1973
|
+
if (!scope) {
|
|
1974
|
+
const disposable2 = variableEngine.globalVariableTable.onAnyChange(() => {
|
|
1975
|
+
refresh();
|
|
1976
|
+
});
|
|
1977
|
+
return () => disposable2.dispose();
|
|
1978
|
+
}
|
|
1979
|
+
const disposable = scope.available.onDataChange(() => {
|
|
1980
|
+
refresh();
|
|
1981
|
+
});
|
|
1982
|
+
return () => disposable.dispose();
|
|
1983
|
+
}, []);
|
|
1984
|
+
return scope ? scope.available.variables : variableEngine.globalVariableTable.variables;
|
|
1985
|
+
}
|
|
1986
|
+
export {
|
|
1987
|
+
ASTFactory,
|
|
1988
|
+
ASTKind,
|
|
1989
|
+
ASTNode,
|
|
1990
|
+
ASTNodeFlags,
|
|
1991
|
+
ASTRegisters,
|
|
1992
|
+
ArrayType,
|
|
1993
|
+
BaseExpression,
|
|
1994
|
+
BaseType,
|
|
1995
|
+
BaseVariableField,
|
|
1996
|
+
BooleanType,
|
|
1997
|
+
DataNode,
|
|
1998
|
+
EnumerateExpression,
|
|
1999
|
+
ExpressionList,
|
|
2000
|
+
IntegerType,
|
|
2001
|
+
KeyPathExpression,
|
|
2002
|
+
KeyPathExpressionV2,
|
|
2003
|
+
ListNode,
|
|
2004
|
+
MapNode,
|
|
2005
|
+
MapType,
|
|
2006
|
+
NumberType,
|
|
2007
|
+
ObjectType,
|
|
2008
|
+
Property,
|
|
2009
|
+
Scope,
|
|
2010
|
+
ScopeChain,
|
|
2011
|
+
ScopeOutputData,
|
|
2012
|
+
ScopeProvider,
|
|
2013
|
+
StringType,
|
|
2014
|
+
VariableContainerModule,
|
|
2015
|
+
VariableDeclaration,
|
|
2016
|
+
VariableDeclarationList,
|
|
2017
|
+
VariableEngine,
|
|
2018
|
+
VariableEngineProvider,
|
|
2019
|
+
VariableFieldKeyRenameService,
|
|
2020
|
+
VariableTable,
|
|
2021
|
+
injectToAST,
|
|
2022
|
+
postConstructAST,
|
|
2023
|
+
useAvailableVariables,
|
|
2024
|
+
useCurrentScope,
|
|
2025
|
+
useScopeAvailable,
|
|
2026
|
+
useScopeContext
|
|
2027
|
+
};
|
|
2028
|
+
//# sourceMappingURL=index.js.map
|