@flowgram-vue/variable-core 0.2.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/LICENSE +22 -0
- package/dist/index.cjs +2630 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2293 -0
- package/dist/index.js +2592 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/src/ast/ast-node.ts +374 -0
- package/src/ast/ast-registers.ts +129 -0
- package/src/ast/common/data-node.ts +63 -0
- package/src/ast/common/index.ts +8 -0
- package/src/ast/common/list-node.ts +70 -0
- package/src/ast/common/map-node.ts +89 -0
- package/src/ast/declaration/base-variable-field.ts +184 -0
- package/src/ast/declaration/index.ts +13 -0
- package/src/ast/declaration/property.ts +19 -0
- package/src/ast/declaration/variable-declaration-list.ts +112 -0
- package/src/ast/declaration/variable-declaration.ts +78 -0
- package/src/ast/expression/base-expression.ts +117 -0
- package/src/ast/expression/enumerate-expression.ts +77 -0
- package/src/ast/expression/index.ts +10 -0
- package/src/ast/expression/keypath-expression.ts +157 -0
- package/src/ast/expression/legacy-keypath-expression.ts +119 -0
- package/src/ast/expression/wrap-array-expression.ts +96 -0
- package/src/ast/factory.ts +163 -0
- package/src/ast/flags.ts +50 -0
- package/src/ast/index.ts +26 -0
- package/src/ast/match.ts +146 -0
- package/src/ast/type/array.ts +109 -0
- package/src/ast/type/base-type.ts +49 -0
- package/src/ast/type/boolean.ts +26 -0
- package/src/ast/type/custom-type.ts +70 -0
- package/src/ast/type/index.ts +19 -0
- package/src/ast/type/integer.ts +29 -0
- package/src/ast/type/map.ts +96 -0
- package/src/ast/type/number.ts +26 -0
- package/src/ast/type/object.ts +185 -0
- package/src/ast/type/string.ts +55 -0
- package/src/ast/type/union.ts +13 -0
- package/src/ast/types.ts +188 -0
- package/src/ast/utils/expression.ts +61 -0
- package/src/ast/utils/helpers.ts +73 -0
- package/src/ast/utils/inversify.ts +42 -0
- package/src/ast/utils/observable.ts +5 -0
- package/src/ast/utils/variable-field.ts +25 -0
- package/src/composables/index.ts +9 -0
- package/src/composables/scope-provider.ts +78 -0
- package/src/composables/use-available-variables.ts +39 -0
- package/src/composables/use-output-variables.ts +36 -0
- package/src/composables/use-scope-available.ts +32 -0
- package/src/index.ts +14 -0
- package/src/providers.ts +22 -0
- package/src/scope/datas/index.ts +8 -0
- package/src/scope/datas/scope-available-data.ts +234 -0
- package/src/scope/datas/scope-event-data.ts +67 -0
- package/src/scope/datas/scope-output-data.ts +151 -0
- package/src/scope/index.ts +9 -0
- package/src/scope/scope-chain.ts +69 -0
- package/src/scope/scope.ts +200 -0
- package/src/scope/types.ts +102 -0
- package/src/scope/variable-table.ts +203 -0
- package/src/services/index.ts +6 -0
- package/src/services/variable-field-key-rename-service.ts +131 -0
- package/src/utils/memo.ts +38 -0
- package/src/utils/toDisposable.ts +16 -0
- package/src/variable-container-module.ts +28 -0
- package/src/variable-engine.ts +197 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
type KeyType = string | symbol;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create memo manager
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export const createMemo = (): {
|
|
13
|
+
<T>(key: KeyType, fn: () => T): T;
|
|
14
|
+
clear: (key?: KeyType) => void;
|
|
15
|
+
} => {
|
|
16
|
+
const _memoCache = new Map<KeyType, any>();
|
|
17
|
+
|
|
18
|
+
const memo = <T>(key: KeyType, fn: () => T): T => {
|
|
19
|
+
if (_memoCache.has(key)) {
|
|
20
|
+
return _memoCache.get(key) as T;
|
|
21
|
+
}
|
|
22
|
+
const data = fn();
|
|
23
|
+
_memoCache.set(key, data);
|
|
24
|
+
return data as T;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const clear = (key?: KeyType) => {
|
|
28
|
+
if (key) {
|
|
29
|
+
_memoCache.delete(key);
|
|
30
|
+
} else {
|
|
31
|
+
_memoCache.clear();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
memo.clear = clear;
|
|
36
|
+
|
|
37
|
+
return memo;
|
|
38
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Subscription } from 'rxjs';
|
|
7
|
+
import { Disposable } from '@flowgram-vue/utils';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Convert rxjs subscription to disposable
|
|
11
|
+
* @param subscription - The rxjs subscription
|
|
12
|
+
* @returns The disposable
|
|
13
|
+
*/
|
|
14
|
+
export function subsToDisposable(subscription: Subscription): Disposable {
|
|
15
|
+
return Disposable.create(() => subscription.unsubscribe());
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ContainerModule } from 'inversify';
|
|
7
|
+
|
|
8
|
+
import { VariableEngine } from './variable-engine';
|
|
9
|
+
import { VariableFieldKeyRenameService } from './services';
|
|
10
|
+
import { ContainerProvider, VariableEngineProvider } from './providers';
|
|
11
|
+
import { ASTRegisters } from './ast';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* An InversifyJS container module that binds all the necessary services for the variable engine.
|
|
15
|
+
* This module sets up the dependency injection for the core components of the variable engine.
|
|
16
|
+
*/
|
|
17
|
+
export const VariableContainerModule = new ContainerModule((bind) => {
|
|
18
|
+
bind(VariableEngine).toSelf().inSingletonScope();
|
|
19
|
+
bind(ASTRegisters).toSelf().inSingletonScope();
|
|
20
|
+
|
|
21
|
+
bind(VariableFieldKeyRenameService).toSelf().inSingletonScope();
|
|
22
|
+
|
|
23
|
+
// Provide a dynamic provider for VariableEngine to prevent circular dependencies.
|
|
24
|
+
bind(VariableEngineProvider).toDynamicValue((ctx) => () => ctx.container.get(VariableEngine));
|
|
25
|
+
|
|
26
|
+
// Provide a ContainerProvider to allow AST nodes and other components to access the container.
|
|
27
|
+
bind(ContainerProvider).toDynamicValue((ctx) => () => ctx.container);
|
|
28
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Subject } from 'rxjs';
|
|
7
|
+
import { inject, injectable, interfaces, preDestroy } from 'inversify';
|
|
8
|
+
import { Disposable, DisposableCollection } from '@flowgram-vue/utils';
|
|
9
|
+
import { Emitter } from '@flowgram-vue/utils';
|
|
10
|
+
|
|
11
|
+
import { subsToDisposable } from './utils/toDisposable';
|
|
12
|
+
import { createMemo } from './utils/memo';
|
|
13
|
+
import { VariableTable } from './scope/variable-table';
|
|
14
|
+
import { ScopeChangeAction } from './scope/types';
|
|
15
|
+
import { IScopeConstructor } from './scope/scope';
|
|
16
|
+
import { Scope, ScopeChain, type IVariableTable } from './scope';
|
|
17
|
+
import { ContainerProvider } from './providers';
|
|
18
|
+
import { ASTRegisters, type GlobalEventActionType } from './ast';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The core of the variable engine system.
|
|
22
|
+
* It manages scopes, variables, and events within the system.
|
|
23
|
+
*/
|
|
24
|
+
@injectable()
|
|
25
|
+
export class VariableEngine implements Disposable {
|
|
26
|
+
protected toDispose = new DisposableCollection();
|
|
27
|
+
|
|
28
|
+
protected memo = createMemo();
|
|
29
|
+
|
|
30
|
+
protected scopeMap = new Map<string | symbol, Scope>();
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A rxjs subject that emits global events occurring within the variable engine.
|
|
34
|
+
*/
|
|
35
|
+
globalEvent$: Subject<GlobalEventActionType> = new Subject<GlobalEventActionType>();
|
|
36
|
+
|
|
37
|
+
protected onScopeChangeEmitter = new Emitter<ScopeChangeAction>();
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A table containing all global variables.
|
|
41
|
+
*/
|
|
42
|
+
public globalVariableTable: IVariableTable = new VariableTable();
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* An event that fires whenever a scope is added, updated, or deleted.
|
|
46
|
+
*/
|
|
47
|
+
public onScopeChange = this.onScopeChangeEmitter.event;
|
|
48
|
+
|
|
49
|
+
@inject(ContainerProvider) private readonly containerProvider: ContainerProvider;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The Inversify container instance.
|
|
53
|
+
*/
|
|
54
|
+
get container(): interfaces.Container {
|
|
55
|
+
return this.containerProvider();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
constructor(
|
|
59
|
+
/**
|
|
60
|
+
* The scope chain, which manages the dependency relationships between scopes.
|
|
61
|
+
*/
|
|
62
|
+
@inject(ScopeChain)
|
|
63
|
+
public readonly chain: ScopeChain,
|
|
64
|
+
/**
|
|
65
|
+
* The registry for all AST node types.
|
|
66
|
+
*/
|
|
67
|
+
@inject(ASTRegisters)
|
|
68
|
+
public readonly astRegisters: ASTRegisters
|
|
69
|
+
) {
|
|
70
|
+
this.toDispose.pushAll([
|
|
71
|
+
chain,
|
|
72
|
+
Disposable.create(() => {
|
|
73
|
+
// Dispose all scopes
|
|
74
|
+
this.getAllScopes().forEach((scope) => scope.dispose());
|
|
75
|
+
this.globalVariableTable.dispose();
|
|
76
|
+
}),
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Disposes of all resources used by the variable engine.
|
|
82
|
+
*/
|
|
83
|
+
@preDestroy()
|
|
84
|
+
dispose(): void {
|
|
85
|
+
this.toDispose.dispose();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Retrieves a scope by its unique identifier.
|
|
90
|
+
* @param scopeId The ID of the scope to retrieve.
|
|
91
|
+
* @returns The scope if found, otherwise undefined.
|
|
92
|
+
*/
|
|
93
|
+
getScopeById(scopeId: string | symbol): Scope | undefined {
|
|
94
|
+
return this.scopeMap.get(scopeId);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Removes a scope by its unique identifier and disposes of it.
|
|
99
|
+
* @param scopeId The ID of the scope to remove.
|
|
100
|
+
*/
|
|
101
|
+
removeScopeById(scopeId: string | symbol): void {
|
|
102
|
+
this.getScopeById(scopeId)?.dispose();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Creates a new scope or retrieves an existing one if the ID and type match.
|
|
107
|
+
* @param id The unique identifier for the scope.
|
|
108
|
+
* @param meta Optional metadata for the scope, defined by the user.
|
|
109
|
+
* @param options Options for creating the scope.
|
|
110
|
+
* @param options.ScopeConstructor The constructor to use for creating the scope. Defaults to `Scope`.
|
|
111
|
+
* @returns The created or existing scope.
|
|
112
|
+
*/
|
|
113
|
+
createScope(
|
|
114
|
+
id: string | symbol,
|
|
115
|
+
meta?: Record<string, any>,
|
|
116
|
+
options: {
|
|
117
|
+
ScopeConstructor?: IScopeConstructor;
|
|
118
|
+
} = {}
|
|
119
|
+
): Scope {
|
|
120
|
+
const { ScopeConstructor = Scope } = options;
|
|
121
|
+
|
|
122
|
+
let scope = this.getScopeById(id);
|
|
123
|
+
|
|
124
|
+
if (!scope) {
|
|
125
|
+
scope = new ScopeConstructor({ variableEngine: this, meta, id });
|
|
126
|
+
this.scopeMap.set(id, scope);
|
|
127
|
+
this.onScopeChangeEmitter.fire({ type: 'add', scope: scope! });
|
|
128
|
+
|
|
129
|
+
scope.toDispose.pushAll([
|
|
130
|
+
scope.ast.subscribe(() => {
|
|
131
|
+
this.onScopeChangeEmitter.fire({ type: 'update', scope: scope! });
|
|
132
|
+
}),
|
|
133
|
+
// Fires when available variables change
|
|
134
|
+
scope.available.onDataChange(() => {
|
|
135
|
+
this.onScopeChangeEmitter.fire({ type: 'available', scope: scope! });
|
|
136
|
+
}),
|
|
137
|
+
]);
|
|
138
|
+
scope.onDispose(() => {
|
|
139
|
+
this.scopeMap.delete(id);
|
|
140
|
+
this.onScopeChangeEmitter.fire({ type: 'delete', scope: scope! });
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return scope;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Retrieves all scopes currently managed by the engine.
|
|
149
|
+
* @param options Options for retrieving the scopes.
|
|
150
|
+
* @param options.sort Whether to sort the scopes based on their dependency chain.
|
|
151
|
+
* @returns An array of all scopes.
|
|
152
|
+
*/
|
|
153
|
+
getAllScopes({
|
|
154
|
+
sort,
|
|
155
|
+
}: {
|
|
156
|
+
sort?: boolean;
|
|
157
|
+
} = {}): Scope[] {
|
|
158
|
+
const allScopes = Array.from(this.scopeMap.values());
|
|
159
|
+
|
|
160
|
+
if (sort) {
|
|
161
|
+
const sortScopes = this.chain.sortAll();
|
|
162
|
+
const remainScopes = new Set(allScopes);
|
|
163
|
+
sortScopes.forEach((_scope) => remainScopes.delete(_scope));
|
|
164
|
+
|
|
165
|
+
return [...sortScopes, ...Array.from(remainScopes)];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return [...allScopes];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Fires a global event to be broadcast to all listeners.
|
|
173
|
+
* @param event The global event to fire.
|
|
174
|
+
*/
|
|
175
|
+
fireGlobalEvent(event: GlobalEventActionType) {
|
|
176
|
+
this.globalEvent$.next(event);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Subscribes to a specific type of global event.
|
|
181
|
+
* @param type The type of the event to listen for.
|
|
182
|
+
* @param observer A function to be called when the event is observed.
|
|
183
|
+
* @returns A disposable object to unsubscribe from the event.
|
|
184
|
+
*/
|
|
185
|
+
onGlobalEvent<ActionType extends GlobalEventActionType = GlobalEventActionType>(
|
|
186
|
+
type: ActionType['type'],
|
|
187
|
+
observer: (action: ActionType) => void
|
|
188
|
+
): Disposable {
|
|
189
|
+
return subsToDisposable(
|
|
190
|
+
this.globalEvent$.subscribe((_action) => {
|
|
191
|
+
if (_action.type === type) {
|
|
192
|
+
observer(_action as ActionType);
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|