flow-node-variable-data.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import { BaseVariableField, VariableEngine } from '@flowgram.ai/variable-core';
  2. import { type ASTNode, ASTNodeJSON } from '@flowgram.ai/variable-core';
  3. import { FlowNodeEntity } from '@flowgram.ai/document';
  4. import { EntityData } from '@flowgram.ai/core';
  5. import { FlowNodeScope, FlowNodeScopeMeta, FlowNodeScopeTypeEnum } from './types';
  6. interface Options {
  7. variableEngine: VariableEngine;
  8. }
  9. export class FlowNodeVariableData extends EntityData {
  10. static type: string = 'FlowNodeVariableData';
  11. declare entity: FlowNodeEntity;
  12. readonly variableEngine: VariableEngine;
  13. /**
  14. * Private variables can be accessed by public ones, but not the other way around.
  15. */
  16. protected _private?: FlowNodeScope;
  17. protected _public: FlowNodeScope;
  18. get private() {
  19. return this._private;
  20. }
  21. get public() {
  22. return this._public;
  23. }
  24. /**
  25. * Sets a variable in the public AST (Abstract Syntax Tree) with the given key and JSON value.
  26. *
  27. * @param key - The key under which the variable will be stored.
  28. * @param json - The JSON value to store.
  29. * @returns The updated AST node.
  30. */
  31. public setVar(key: string, json: ASTNodeJSON): ASTNode;
  32. /**
  33. * Sets a variable in the public AST (Abstract Syntax Tree) with the default key 'outputs'.
  34. *
  35. * @param json - The JSON value to store.
  36. * @returns The updated AST node.
  37. */
  38. public setVar(json: ASTNodeJSON): ASTNode;
  39. public setVar(arg1: string | ASTNodeJSON, arg2?: ASTNodeJSON): ASTNode {
  40. if (typeof arg1 === 'string' && arg2 !== undefined) {
  41. return this.public.ast.set(arg1, arg2);
  42. }
  43. if (typeof arg1 === 'object' && arg2 === undefined) {
  44. return this.public.ast.set('outputs', arg1);
  45. }
  46. throw new Error('Invalid arguments');
  47. }
  48. /**
  49. * Retrieves a variable from the public AST (Abstract Syntax Tree) by key.
  50. *
  51. * @param key - The key of the variable to retrieve. Defaults to 'outputs'.
  52. * @returns The value of the variable, or undefined if not found.
  53. */
  54. public getVar(key: string = 'outputs') {
  55. return this.public.ast.get(key);
  56. }
  57. /**
  58. * Clears a variable from the public AST (Abstract Syntax Tree) by key.
  59. *
  60. * @param key - The key of the variable to clear. Defaults to 'outputs'.
  61. * @returns The updated AST node.
  62. */
  63. public clearVar(key: string = 'outputs') {
  64. return this.public.ast.remove(key);
  65. }
  66. /**
  67. * Sets a variable in the private AST (Abstract Syntax Tree) with the given key and JSON value.
  68. *
  69. * @param key - The key under which the variable will be stored.
  70. * @param json - The JSON value to store.
  71. * @returns The updated AST node.
  72. */
  73. public setPrivateVar(key: string, json: ASTNodeJSON): ASTNode;
  74. /**
  75. * Sets a variable in the private AST (Abstract Syntax Tree) with the default key 'outputs'.
  76. *
  77. * @param json - The JSON value to store.
  78. * @returns The updated AST node.
  79. */
  80. public setPrivateVar(json: ASTNodeJSON): ASTNode;
  81. public setPrivateVar(arg1: string | ASTNodeJSON, arg2?: ASTNodeJSON): ASTNode {
  82. if (typeof arg1 === 'string' && arg2 !== undefined) {
  83. return this.initPrivate().ast.set(arg1, arg2);
  84. }
  85. if (typeof arg1 === 'object' && arg2 === undefined) {
  86. return this.initPrivate().ast.set('outputs', arg1);
  87. }
  88. throw new Error('Invalid arguments');
  89. }
  90. /**
  91. * Retrieves a variable from the private AST (Abstract Syntax Tree) by key.
  92. *
  93. * @param key - The key of the variable to retrieve. Defaults to 'outputs'.
  94. * @returns The value of the variable, or undefined if not found.
  95. */
  96. public getPrivateVar(key: string = 'outputs') {
  97. return this.private?.ast.get(key);
  98. }
  99. /**
  100. * Clears a variable from the private AST (Abstract Syntax Tree) by key.
  101. *
  102. * @param key - The key of the variable to clear. Defaults to 'outputs'.
  103. * @returns The updated AST node.
  104. */
  105. public clearPrivateVar(key: string = 'outputs') {
  106. return this.private?.ast.remove(key);
  107. }
  108. get allScopes(): FlowNodeScope[] {
  109. const res = [];
  110. if (this._public) {
  111. res.push(this._public);
  112. }
  113. if (this._private) {
  114. res.push(this._private);
  115. }
  116. return res;
  117. }
  118. getDefaultData() {
  119. return {};
  120. }
  121. constructor(entity: FlowNodeEntity, readonly opts: Options) {
  122. super(entity);
  123. const { variableEngine } = opts || {};
  124. this.variableEngine = variableEngine;
  125. this._public = this.variableEngine.createScope(this.entity.id, {
  126. node: this.entity,
  127. type: FlowNodeScopeTypeEnum.public,
  128. } as FlowNodeScopeMeta);
  129. this.toDispose.push(this._public);
  130. }
  131. initPrivate(): FlowNodeScope {
  132. if (!this._private) {
  133. this._private = this.variableEngine.createScope(`${this.entity.id}_private`, {
  134. node: this.entity,
  135. type: FlowNodeScopeTypeEnum.private,
  136. } as FlowNodeScopeMeta);
  137. // 1. Notify the covering scopes of private to update dependencies
  138. this._private.coverScopes.forEach((_scope) => {
  139. _scope.refreshDeps();
  140. });
  141. // 2. Notify the dependent scopes of private to update their covers
  142. this._private.depScopes.forEach((_scope) => {
  143. _scope.refreshCovers();
  144. });
  145. // 3. The private scope itself needs to refresh its dependencies
  146. this._private.available.refresh();
  147. this.toDispose.push(this._private);
  148. }
  149. return this._private;
  150. }
  151. /**
  152. * Find a variable field by key path in the public scope by scope chain.
  153. * @param keyPath - The key path of the variable field.
  154. * @returns The variable field, or undefined if not found.
  155. */
  156. getByKeyPath(keyPath: string[]): BaseVariableField | undefined {
  157. return this.public.available.getByKeyPath(keyPath);
  158. }
  159. /**
  160. * Find a variable field by key path in the private scope by scope chain.
  161. * @param keyPath - The key path of the variable field.
  162. * @returns The variable field, or undefined if not found.
  163. */
  164. getByKeyPathInPrivate(keyPath: string[]): BaseVariableField | undefined {
  165. return this.private?.available.getByKeyPath(keyPath);
  166. }
  167. }