mirror of
				https://github.com/Tencent/tmagic-editor.git
				synced 2025-11-04 02:28:04 +08:00 
			
		
		
		
	refactor: 依赖收集相关代码抽出独立成库
This commit is contained in:
		
							parent
							
								
									2b10e7eda9
								
							
						
					
					
						commit
						94641bad76
					
				@ -54,6 +54,7 @@
 | 
				
			|||||||
    "chalk": "^4.1.0",
 | 
					    "chalk": "^4.1.0",
 | 
				
			||||||
    "commitizen": "^4.3.0",
 | 
					    "commitizen": "^4.3.0",
 | 
				
			||||||
    "conventional-changelog-cli": "^4.1.0",
 | 
					    "conventional-changelog-cli": "^4.1.0",
 | 
				
			||||||
 | 
					    "cosmiconfig": "^8.3.6",
 | 
				
			||||||
    "cz-conventional-changelog": "^3.3.0",
 | 
					    "cz-conventional-changelog": "^3.3.0",
 | 
				
			||||||
    "element-plus": "^2.2.32",
 | 
					    "element-plus": "^2.2.32",
 | 
				
			||||||
    "enquirer": "^2.3.6",
 | 
					    "enquirer": "^2.3.6",
 | 
				
			||||||
@ -79,7 +80,7 @@
 | 
				
			|||||||
    "vite": "^4.4.4",
 | 
					    "vite": "^4.4.4",
 | 
				
			||||||
    "vitepress": "1.0.0-rc.24",
 | 
					    "vitepress": "1.0.0-rc.24",
 | 
				
			||||||
    "vitest": "^0.31.1",
 | 
					    "vitest": "^0.31.1",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "config": {
 | 
					  "config": {
 | 
				
			||||||
    "commitizen": {
 | 
					    "commitizen": {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										42
									
								
								packages/dep/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								packages/dep/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "version": "1.3.1",
 | 
				
			||||||
 | 
					  "name": "@tmagic/dep",
 | 
				
			||||||
 | 
					  "type": "module",
 | 
				
			||||||
 | 
					  "sideEffects": [
 | 
				
			||||||
 | 
					    "dist/*"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "main": "dist/tmagic-dep.umd.cjs",
 | 
				
			||||||
 | 
					  "module": "dist/tmagic-dep.js",
 | 
				
			||||||
 | 
					  "types": "types/index.d.ts",
 | 
				
			||||||
 | 
					  "exports": {
 | 
				
			||||||
 | 
					    ".": {
 | 
				
			||||||
 | 
					      "types": "./types/index.d.ts",
 | 
				
			||||||
 | 
					      "import": "./dist/tmagic-dep.js",
 | 
				
			||||||
 | 
					      "require": "./dist/tmagic-dep.umd.cjs"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "./*": "./*"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "build": "npm run build:type && vite build",
 | 
				
			||||||
 | 
					    "build:type": "npm run clear:type && tsc --declaration --emitDeclarationOnly --project tsconfig.build.json",
 | 
				
			||||||
 | 
					    "clear:type": "rimraf ./types"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "engines": {
 | 
				
			||||||
 | 
					    "node": ">=14"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "repository": {
 | 
				
			||||||
 | 
					    "type": "git",
 | 
				
			||||||
 | 
					    "url": "https://github.com/Tencent/tmagic-editor.git"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@tmagic/schema": "1.3.1",
 | 
				
			||||||
 | 
					    "@tmagic/utils": "1.3.1"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
 | 
					    "typescript": "^5.0.4",
 | 
				
			||||||
 | 
					    "vite": "^4.4.4"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										112
									
								
								packages/dep/src/Target.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								packages/dep/src/Target.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					import type { DepData } from '@tmagic/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { DepTargetType, type IsTarget, type TargetOptions } from './types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 需要收集依赖的目标
 | 
				
			||||||
 | 
					 * 例如:一个代码块可以为一个目标
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export default class Target {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 如何识别目标
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public isTarget: IsTarget;
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 目标id,不可重复
 | 
				
			||||||
 | 
					   * 例如目标是代码块,则为代码块id
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public id: string | number;
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 目标名称,用于显示在依赖列表中
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public name?: string;
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public type: string = DepTargetType.DEFAULT;
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 依赖详情
 | 
				
			||||||
 | 
					   * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public deps: DepData = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(options: TargetOptions) {
 | 
				
			||||||
 | 
					    this.isTarget = options.isTarget;
 | 
				
			||||||
 | 
					    this.id = options.id;
 | 
				
			||||||
 | 
					    this.name = options.name;
 | 
				
			||||||
 | 
					    if (options.type) {
 | 
				
			||||||
 | 
					      this.type = options.type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (options.initialDeps) {
 | 
				
			||||||
 | 
					      this.deps = options.initialDeps;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 更新依赖
 | 
				
			||||||
 | 
					   * @param node 节点配置
 | 
				
			||||||
 | 
					   * @param key 哪个key配置了这个目标的id
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public updateDep(node: Record<string | number, any>, key: string | number) {
 | 
				
			||||||
 | 
					    const dep = this.deps[node.id] || {
 | 
				
			||||||
 | 
					      name: node.name,
 | 
				
			||||||
 | 
					      keys: [],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (node.name) {
 | 
				
			||||||
 | 
					      dep.name = node.name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.deps[node.id] = dep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dep.keys.indexOf(key) === -1) {
 | 
				
			||||||
 | 
					      dep.keys.push(key);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 删除依赖
 | 
				
			||||||
 | 
					   * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖
 | 
				
			||||||
 | 
					   * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key
 | 
				
			||||||
 | 
					   * @returns void
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public removeDep(node?: Record<string | number, any>, key?: string | number) {
 | 
				
			||||||
 | 
					    if (!node) {
 | 
				
			||||||
 | 
					      Object.keys(this.deps).forEach((depKey) => {
 | 
				
			||||||
 | 
					        delete this.deps[depKey];
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dep = this.deps[node.id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!dep) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (key) {
 | 
				
			||||||
 | 
					      const index = dep.keys.indexOf(key);
 | 
				
			||||||
 | 
					      dep.keys.splice(index, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (dep.keys.length === 0) {
 | 
				
			||||||
 | 
					        delete this.deps[node.id];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      delete this.deps[node.id];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 判断指定节点下的指定key是否存在在依赖列表中
 | 
				
			||||||
 | 
					   * @param node 哪个节点
 | 
				
			||||||
 | 
					   * @param key 哪个key
 | 
				
			||||||
 | 
					   * @returns boolean
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public hasDep(node: Record<string | number, any>, key: string | number) {
 | 
				
			||||||
 | 
					    const dep = this.deps[node.id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Boolean(dep?.keys.find((d) => d === key));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public destroy() {
 | 
				
			||||||
 | 
					    this.deps = {};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										175
									
								
								packages/dep/src/Watcher.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								packages/dep/src/Watcher.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					import { isObject } from '@tmagic/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type Target from './Target';
 | 
				
			||||||
 | 
					import { DepTargetType, type TargetList } from './types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Watcher {
 | 
				
			||||||
 | 
					  private targetsList: TargetList = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(options?: { initialTargets?: TargetList }) {
 | 
				
			||||||
 | 
					    if (options?.initialTargets) {
 | 
				
			||||||
 | 
					      this.targetsList = options.initialTargets;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public getTargetsList() {
 | 
				
			||||||
 | 
					    return this.targetsList;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 获取指定类型中的所有target
 | 
				
			||||||
 | 
					   * @param type 分类
 | 
				
			||||||
 | 
					   * @returns Target[]
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public getTargets(type: string = DepTargetType.DEFAULT) {
 | 
				
			||||||
 | 
					    return this.targetsList[type] || {};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 添加新的目标
 | 
				
			||||||
 | 
					   * @param target Target
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public addTarget(target: Target) {
 | 
				
			||||||
 | 
					    const targets = this.getTargets(target.type) || {};
 | 
				
			||||||
 | 
					    this.targetsList[target.type] = targets;
 | 
				
			||||||
 | 
					    targets[target.id] = target;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 获取指定id的target
 | 
				
			||||||
 | 
					   * @param id target id
 | 
				
			||||||
 | 
					   * @returns Target
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public getTarget(id: string | number) {
 | 
				
			||||||
 | 
					    const allTargets = Object.values(this.targetsList);
 | 
				
			||||||
 | 
					    for (const targets of allTargets) {
 | 
				
			||||||
 | 
					      if (targets[id]) {
 | 
				
			||||||
 | 
					        return targets[id];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 判断是否存在指定id的target
 | 
				
			||||||
 | 
					   * @param id target id
 | 
				
			||||||
 | 
					   * @returns boolean
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public hasTarget(id: string | number) {
 | 
				
			||||||
 | 
					    return Boolean(this.getTarget(id));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 删除指定id的target
 | 
				
			||||||
 | 
					   * @param id target id
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public removeTarget(id: string | number) {
 | 
				
			||||||
 | 
					    const allTargets = Object.values(this.targetsList);
 | 
				
			||||||
 | 
					    for (const targets of allTargets) {
 | 
				
			||||||
 | 
					      if (targets[id]) {
 | 
				
			||||||
 | 
					        targets[id].destroy();
 | 
				
			||||||
 | 
					        delete targets[id];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 删除指定分类的所有target
 | 
				
			||||||
 | 
					   * @param type 分类
 | 
				
			||||||
 | 
					   * @returns void
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public removeTargets(type: string = DepTargetType.DEFAULT) {
 | 
				
			||||||
 | 
					    const targets = this.targetsList[type];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!targets) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const target of Object.values(targets)) {
 | 
				
			||||||
 | 
					      target.destroy();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete this.targetsList[type];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 删除所有target
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public clearTargets() {
 | 
				
			||||||
 | 
					    Object.keys(this.targetsList).forEach((key) => {
 | 
				
			||||||
 | 
					      delete this.targetsList[key];
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 收集依赖
 | 
				
			||||||
 | 
					   * @param nodes 需要收集的节点
 | 
				
			||||||
 | 
					   * @param deep 是否需要收集子节点
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public collect(nodes: Record<string | number, any>[], deep = false) {
 | 
				
			||||||
 | 
					    Object.values(this.targetsList).forEach((targets) => {
 | 
				
			||||||
 | 
					      Object.values(targets).forEach((target) => {
 | 
				
			||||||
 | 
					        nodes.forEach((node) => {
 | 
				
			||||||
 | 
					          // 先删除原有依赖,重新收集
 | 
				
			||||||
 | 
					          target.removeDep(node);
 | 
				
			||||||
 | 
					          this.collectItem(node, target, deep);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 清除依赖
 | 
				
			||||||
 | 
					   * @param nodes 需要清除依赖的节点
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public clear(nodes?: Record<string | number, any>[]) {
 | 
				
			||||||
 | 
					    const clearedItemsNodeIds: (string | number)[] = [];
 | 
				
			||||||
 | 
					    Object.values(this.targetsList).forEach((targets) => {
 | 
				
			||||||
 | 
					      Object.values(targets).forEach((target) => {
 | 
				
			||||||
 | 
					        if (nodes) {
 | 
				
			||||||
 | 
					          nodes.forEach((node) => {
 | 
				
			||||||
 | 
					            target.removeDep(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Array.isArray(node.items) && node.items.length && !clearedItemsNodeIds.includes(node.id)) {
 | 
				
			||||||
 | 
					              clearedItemsNodeIds.push(node.id);
 | 
				
			||||||
 | 
					              this.clear(node.items);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          target.removeDep();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private collectItem(node: Record<string | number, any>, target: Target, deep = false) {
 | 
				
			||||||
 | 
					    const collectTarget = (config: Record<string | number, any>, prop = '') => {
 | 
				
			||||||
 | 
					      const doCollect = (key: string, value: any) => {
 | 
				
			||||||
 | 
					        const keyIsItems = key === 'items';
 | 
				
			||||||
 | 
					        const fullKey = prop ? `${prop}.${key}` : key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (target.isTarget(fullKey, value)) {
 | 
				
			||||||
 | 
					          target.updateDep(node, fullKey);
 | 
				
			||||||
 | 
					        } else if (!keyIsItems && Array.isArray(value)) {
 | 
				
			||||||
 | 
					          value.forEach((item, index) => {
 | 
				
			||||||
 | 
					            if (isObject(item)) {
 | 
				
			||||||
 | 
					              collectTarget(item, `${fullKey}.${index}`);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        } else if (isObject(value)) {
 | 
				
			||||||
 | 
					          collectTarget(value, fullKey);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (keyIsItems && deep && Array.isArray(value)) {
 | 
				
			||||||
 | 
					          value.forEach((child) => {
 | 
				
			||||||
 | 
					            this.collectItem(child, target, deep);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Object.entries(config).forEach(([key, value]) => {
 | 
				
			||||||
 | 
					        if (typeof value === 'undefined' || value === '') return;
 | 
				
			||||||
 | 
					        doCollect(key, value);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    collectTarget(node);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								packages/dep/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/dep/src/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					export { default as Target } from './Target';
 | 
				
			||||||
 | 
					export { default as Watcher } from './Watcher';
 | 
				
			||||||
 | 
					export * from './utils';
 | 
				
			||||||
 | 
					export * from './types';
 | 
				
			||||||
							
								
								
									
										33
									
								
								packages/dep/src/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								packages/dep/src/types.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					import { DepData } from '@tmagic/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type Target from './Target';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 依赖收集的目标类型 */
 | 
				
			||||||
 | 
					export enum DepTargetType {
 | 
				
			||||||
 | 
					  DEFAULT = 'default',
 | 
				
			||||||
 | 
					  /** 代码块 */
 | 
				
			||||||
 | 
					  CODE_BLOCK = 'code-block',
 | 
				
			||||||
 | 
					  /** 数据源 */
 | 
				
			||||||
 | 
					  DATA_SOURCE = 'data-source',
 | 
				
			||||||
 | 
					  /** 数据源方法 */
 | 
				
			||||||
 | 
					  DATA_SOURCE_METHOD = 'data-source-method',
 | 
				
			||||||
 | 
					  /** 数据源条件 */
 | 
				
			||||||
 | 
					  DATA_SOURCE_COND = 'data-source-cond',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type IsTarget = (key: string | number, value: any) => boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface TargetOptions {
 | 
				
			||||||
 | 
					  isTarget: IsTarget;
 | 
				
			||||||
 | 
					  id: string | number;
 | 
				
			||||||
 | 
					  /** 类型,数据源、代码块或其他 */
 | 
				
			||||||
 | 
					  type?: string;
 | 
				
			||||||
 | 
					  name?: string;
 | 
				
			||||||
 | 
					  initialDeps?: DepData;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface TargetList {
 | 
				
			||||||
 | 
					  [type: string]: {
 | 
				
			||||||
 | 
					    [targetId: string | number]: Target;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,23 +1,28 @@
 | 
				
			|||||||
import { isEmpty } from 'lodash-es';
 | 
					import {
 | 
				
			||||||
 | 
					  type CodeBlockContent,
 | 
				
			||||||
import { type CodeBlockContent, HookType, type Id } from '@tmagic/schema';
 | 
					  type DataSourceSchema,
 | 
				
			||||||
 | 
					  type DepData,
 | 
				
			||||||
 | 
					  type HookData,
 | 
				
			||||||
 | 
					  HookType,
 | 
				
			||||||
 | 
					  type Id,
 | 
				
			||||||
 | 
					} from '@tmagic/schema';
 | 
				
			||||||
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
 | 
					import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dataSourceService from '@editor/services/dataSource';
 | 
					import Target from './Target';
 | 
				
			||||||
import { Target } from '@editor/services/dep';
 | 
					import { DepTargetType } from './types';
 | 
				
			||||||
import { DepTargetType, type HookData } from '@editor/type';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent) =>
 | 
					export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent, initialDeps: DepData = {}) =>
 | 
				
			||||||
  new Target({
 | 
					  new Target({
 | 
				
			||||||
    type: DepTargetType.CODE_BLOCK,
 | 
					    type: DepTargetType.CODE_BLOCK,
 | 
				
			||||||
    id,
 | 
					    id,
 | 
				
			||||||
 | 
					    initialDeps,
 | 
				
			||||||
    name: codeBlock.name,
 | 
					    name: codeBlock.name,
 | 
				
			||||||
    isTarget: (key: string | number, value: any) => {
 | 
					    isTarget: (key: string | number, value: any) => {
 | 
				
			||||||
      if (id === value) {
 | 
					      if (id === value) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (value?.hookType === HookType.CODE && !isEmpty(value.hookData)) {
 | 
					      if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) {
 | 
				
			||||||
        const index = value.hookData.findIndex((item: HookData) => item.codeId === id);
 | 
					        const index = value.hookData.findIndex((item: HookData) => item.codeId === id);
 | 
				
			||||||
        return Boolean(index > -1);
 | 
					        return Boolean(index > -1);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -26,13 +31,23 @@ export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent) =>
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createDataSourceTarget = (id: Id) =>
 | 
					export const createDataSourceTarget = (ds: DataSourceSchema, initialDeps: DepData = {}) =>
 | 
				
			||||||
  new Target({
 | 
					  new Target({
 | 
				
			||||||
    type: DepTargetType.DATA_SOURCE,
 | 
					    type: DepTargetType.DATA_SOURCE,
 | 
				
			||||||
    id,
 | 
					    id: ds.id,
 | 
				
			||||||
 | 
					    initialDeps,
 | 
				
			||||||
    isTarget: (key: string | number, value: any) => {
 | 
					    isTarget: (key: string | number, value: any) => {
 | 
				
			||||||
      // 关联数据源对象或者在模板在使用数据源
 | 
					      // 关联数据源对象,如:{ isBindDataSource: true, dataSourceId: 'xxx'}
 | 
				
			||||||
      if ((value?.isBindDataSource && value.dataSourceId) || (typeof value === 'string' && value.includes(`${id}`))) {
 | 
					      // 或者在模板在使用数据源,如:`xxx${id.field}xxx`
 | 
				
			||||||
 | 
					      if (
 | 
				
			||||||
 | 
					        (value?.isBindDataSource && value.dataSourceId) ||
 | 
				
			||||||
 | 
					        (typeof value === 'string' && value.includes(`${ds.id}`))
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}
 | 
				
			||||||
 | 
					      if (value?.isBindDataSourceField && value.dataSourceId && typeof value.template === 'string') {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,31 +65,28 @@ export const createDataSourceTarget = (id: Id) =>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      const dsId = prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length);
 | 
					      const dsId = prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return dsId === id && Boolean(dataSourceService.getDataSourceById(id));
 | 
					      return dsId === ds.id;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createDataSourceCondTarget = (id: string) =>
 | 
					export const createDataSourceCondTarget = (ds: DataSourceSchema, initialDeps: DepData = {}) =>
 | 
				
			||||||
  new Target({
 | 
					  new Target({
 | 
				
			||||||
    type: DepTargetType.DATA_SOURCE_COND,
 | 
					    type: DepTargetType.DATA_SOURCE_COND,
 | 
				
			||||||
    id,
 | 
					    id: ds.id,
 | 
				
			||||||
 | 
					    initialDeps,
 | 
				
			||||||
    isTarget: (key: string | number, value: any) => {
 | 
					    isTarget: (key: string | number, value: any) => {
 | 
				
			||||||
      if (!Array.isArray(value) || value[0] !== id || !`${key}`.startsWith('displayConds')) return false;
 | 
					      if (!Array.isArray(value) || value[0] !== ds.id || !`${key}`.startsWith('displayConds')) return false;
 | 
				
			||||||
 | 
					 | 
				
			||||||
      const ds = dataSourceService.getDataSourceById(id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return Boolean(ds?.fields?.find((field) => field.name === value[1]));
 | 
					      return Boolean(ds?.fields?.find((field) => field.name === value[1]));
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const createDataSourceMethodTarget = (id: string) =>
 | 
					export const createDataSourceMethodTarget = (ds: DataSourceSchema, initialDeps: DepData = {}) =>
 | 
				
			||||||
  new Target({
 | 
					  new Target({
 | 
				
			||||||
    type: DepTargetType.DATA_SOURCE_METHOD,
 | 
					    type: DepTargetType.DATA_SOURCE_METHOD,
 | 
				
			||||||
    id,
 | 
					    id: ds.id,
 | 
				
			||||||
 | 
					    initialDeps,
 | 
				
			||||||
    isTarget: (key: string | number, value: any) => {
 | 
					    isTarget: (key: string | number, value: any) => {
 | 
				
			||||||
      if (!Array.isArray(value) || value[0] !== id) return false;
 | 
					      if (!Array.isArray(value) || value[0] !== ds.id) return false;
 | 
				
			||||||
 | 
					 | 
				
			||||||
      const ds = dataSourceService.getDataSourceById(id);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return Boolean(ds?.methods?.find((method) => method.name === value[1]));
 | 
					      return Boolean(ds?.methods?.find((method) => method.name === value[1]));
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
							
								
								
									
										28
									
								
								packages/dep/tests/Target.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/dep/tests/Target.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					import { describe, expect, test } from 'vitest';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Target from '../src/Target';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Target', () => {
 | 
				
			||||||
 | 
					  test('instance', () => {
 | 
				
			||||||
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    expect(target).toBeInstanceOf(Target);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  test('default target type', () => {
 | 
				
			||||||
 | 
					    const defaultTarget = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'default',
 | 
				
			||||||
 | 
					      type: 'default',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					      type: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    expect(defaultTarget.type).toBe('default');
 | 
				
			||||||
 | 
					    expect(target.type).toBe('target');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -1,88 +1,110 @@
 | 
				
			|||||||
import { describe, expect, test } from 'vitest';
 | 
					import { describe, expect, test } from 'vitest';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import depService, { Target, Watcher } from '@editor/services/dep';
 | 
					import Target from '../src/Target';
 | 
				
			||||||
 | 
					import Watcher from '../src/Watcher';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('Watcher', () => {
 | 
					describe('Watcher', () => {
 | 
				
			||||||
  test('instance', () => {
 | 
					  test('instance', () => {
 | 
				
			||||||
    const watcher = new Watcher();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
    expect(watcher).toBeInstanceOf(Watcher);
 | 
					    expect(watcher).toBeInstanceOf(Watcher);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe('depService', () => {
 | 
					 | 
				
			||||||
  const defaultTarget = new Target({
 | 
					 | 
				
			||||||
    id: 1,
 | 
					 | 
				
			||||||
    name: 'test',
 | 
					 | 
				
			||||||
    isTarget: () => true,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const target = new Target({
 | 
					 | 
				
			||||||
    type: 'target',
 | 
					 | 
				
			||||||
    id: 2,
 | 
					 | 
				
			||||||
    name: 'test',
 | 
					 | 
				
			||||||
    isTarget: () => true,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  test('default target type', () => {
 | 
					 | 
				
			||||||
    expect(defaultTarget.type).toBe('default');
 | 
					 | 
				
			||||||
    expect(target.type).toBe('target');
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('addTarget', () => {
 | 
					  test('addTarget', () => {
 | 
				
			||||||
    depService.addTarget(target);
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					      type: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(depService.getTarget(1)).toBeUndefined();
 | 
					    watcher.addTarget(target);
 | 
				
			||||||
    expect(depService.getTarget(2)?.id).toBe(2);
 | 
					
 | 
				
			||||||
    expect(Object.keys(depService.getTargets())).toHaveLength(0);
 | 
					    expect(watcher.getTarget(1)).toBeUndefined();
 | 
				
			||||||
    expect(Object.keys(depService.getTargets('target'))).toHaveLength(1);
 | 
					    expect(watcher.getTarget('target')?.id).toBe('target');
 | 
				
			||||||
 | 
					    expect(Object.keys(watcher.getTargets())).toHaveLength(0);
 | 
				
			||||||
 | 
					    expect(Object.keys(watcher.getTargets('target'))).toHaveLength(1);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('clearTargets', () => {
 | 
					  test('clearTargets', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.addTarget(target);
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeTruthy();
 | 
					    watcher.addTarget(target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.clearTargets();
 | 
					    expect(watcher.hasTarget('target')).toBeTruthy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeFalsy();
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeFalsy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('hasTarget', () => {
 | 
					  test('hasTarget', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.addTarget(target);
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'target2',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(depService.hasTarget(1)).toBeFalsy();
 | 
					    watcher.clearTargets();
 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeTruthy();
 | 
					
 | 
				
			||||||
 | 
					    watcher.addTarget(target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeFalsy();
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target2')).toBeTruthy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('removeTarget', () => {
 | 
					  test('removeTarget', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
    depService.addTarget(target);
 | 
					
 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeTruthy();
 | 
					    const target = new Target({
 | 
				
			||||||
    depService.removeTarget(2);
 | 
					      isTarget: () => true,
 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeFalsy();
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					    watcher.addTarget(target);
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeTruthy();
 | 
				
			||||||
 | 
					    watcher.removeTarget('target');
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeFalsy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('removeTargets', () => {
 | 
					  test('removeTargets', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
    depService.addTarget(defaultTarget);
 | 
					 | 
				
			||||||
    depService.addTarget(target);
 | 
					 | 
				
			||||||
    expect(depService.hasTarget(1)).toBeTruthy();
 | 
					 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeTruthy();
 | 
					 | 
				
			||||||
    depService.removeTargets('target');
 | 
					 | 
				
			||||||
    expect(depService.hasTarget(1)).toBeTruthy();
 | 
					 | 
				
			||||||
    expect(depService.hasTarget(2)).toBeFalsy();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.removeTargets('target1');
 | 
					    const defaultTarget = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      id: 'defaultTarget',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const target = new Target({
 | 
				
			||||||
 | 
					      isTarget: () => true,
 | 
				
			||||||
 | 
					      type: 'targetType',
 | 
				
			||||||
 | 
					      id: 'target',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					    watcher.addTarget(defaultTarget);
 | 
				
			||||||
 | 
					    watcher.addTarget(target);
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('defaultTarget')).toBeTruthy();
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeTruthy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watcher.removeTargets('targetType');
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('defaultTarget')).toBeTruthy();
 | 
				
			||||||
 | 
					    expect(watcher.hasTarget('target')).toBeFalsy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('collect', () => {
 | 
					  test('collect', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.addTarget(
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watcher.addTarget(
 | 
				
			||||||
      new Target({
 | 
					      new Target({
 | 
				
			||||||
        type: 'target',
 | 
					        type: 'target',
 | 
				
			||||||
        id: 'collect_1',
 | 
					        id: 'collect_1',
 | 
				
			||||||
@ -91,7 +113,7 @@ describe('depService', () => {
 | 
				
			|||||||
      }),
 | 
					      }),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.addTarget(
 | 
					    watcher.addTarget(
 | 
				
			||||||
      new Target({
 | 
					      new Target({
 | 
				
			||||||
        type: 'target',
 | 
					        type: 'target',
 | 
				
			||||||
        id: 'collect_2',
 | 
					        id: 'collect_2',
 | 
				
			||||||
@ -100,7 +122,7 @@ describe('depService', () => {
 | 
				
			|||||||
      }),
 | 
					      }),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.collect([
 | 
					    watcher.collect([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        id: 'node_1',
 | 
					        id: 'node_1',
 | 
				
			||||||
        name: 'node',
 | 
					        name: 'node',
 | 
				
			||||||
@ -119,15 +141,15 @@ describe('depService', () => {
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const target1 = depService.getTarget('collect_1');
 | 
					    const target1 = watcher.getTarget('collect_1');
 | 
				
			||||||
    const target2 = depService.getTarget('collect_2');
 | 
					    const target2 = watcher.getTarget('collect_2');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(target1?.deps?.node_1.name).toBe('node');
 | 
					    expect(target1?.deps?.node_1.name).toBe('node');
 | 
				
			||||||
    expect(target2?.deps?.node_1.name).toBe('node');
 | 
					    expect(target2?.deps?.node_1.name).toBe('node');
 | 
				
			||||||
    expect(target1?.deps?.node_1.keys).toHaveLength(1);
 | 
					    expect(target1?.deps?.node_1.keys).toHaveLength(1);
 | 
				
			||||||
    expect(target2?.deps?.node_1.keys).toHaveLength(3);
 | 
					    expect(target2?.deps?.node_1.keys).toHaveLength(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.collect([
 | 
					    watcher.collect([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        id: 'node_1',
 | 
					        id: 'node_1',
 | 
				
			||||||
        name: 'node',
 | 
					        name: 'node',
 | 
				
			||||||
@ -149,7 +171,7 @@ describe('depService', () => {
 | 
				
			|||||||
    expect(target1?.deps?.node_1).toBeUndefined();
 | 
					    expect(target1?.deps?.node_1).toBeUndefined();
 | 
				
			||||||
    expect(target2?.deps?.node_1.keys).toHaveLength(1);
 | 
					    expect(target2?.deps?.node_1.keys).toHaveLength(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.collect([
 | 
					    watcher.collect([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        id: 'node_1',
 | 
					        id: 'node_1',
 | 
				
			||||||
        name: 'node',
 | 
					        name: 'node',
 | 
				
			||||||
@ -161,7 +183,7 @@ describe('depService', () => {
 | 
				
			|||||||
    expect(target1?.deps?.node_1).toBeUndefined();
 | 
					    expect(target1?.deps?.node_1).toBeUndefined();
 | 
				
			||||||
    expect(target2?.deps?.node_1.keys[0]).toBe('text1');
 | 
					    expect(target2?.deps?.node_1.keys[0]).toBe('text1');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.clear([
 | 
					    watcher.clear([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        id: 'node_1',
 | 
					        id: 'node_1',
 | 
				
			||||||
        name: 'node',
 | 
					        name: 'node',
 | 
				
			||||||
@ -173,9 +195,11 @@ describe('depService', () => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('collect deep', () => {
 | 
					  test('collect deep', () => {
 | 
				
			||||||
    depService.clearTargets();
 | 
					    const watcher = new Watcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.addTarget(
 | 
					    watcher.clearTargets();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watcher.addTarget(
 | 
				
			||||||
      new Target({
 | 
					      new Target({
 | 
				
			||||||
        type: 'target',
 | 
					        type: 'target',
 | 
				
			||||||
        id: 'collect_1',
 | 
					        id: 'collect_1',
 | 
				
			||||||
@ -184,7 +208,7 @@ describe('depService', () => {
 | 
				
			|||||||
      }),
 | 
					      }),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.collect(
 | 
					    watcher.collect(
 | 
				
			||||||
      [
 | 
					      [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          id: 'node_1',
 | 
					          id: 'node_1',
 | 
				
			||||||
@ -202,12 +226,12 @@ describe('depService', () => {
 | 
				
			|||||||
      true,
 | 
					      true,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const target1 = depService.getTarget('collect_1');
 | 
					    const target1 = watcher.getTarget('collect_1');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(target1?.deps?.node_1.name).toBe('node');
 | 
					    expect(target1?.deps?.node_1.name).toBe('node');
 | 
				
			||||||
    expect(target1?.deps?.node_2.name).toBe('node2');
 | 
					    expect(target1?.deps?.node_2.name).toBe('node2');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depService.clear([
 | 
					    watcher.clear([
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        id: 'node_1',
 | 
					        id: 'node_1',
 | 
				
			||||||
        name: 'node',
 | 
					        name: 'node',
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
import { describe, expect, test } from 'vitest';
 | 
					import { describe, expect, test } from 'vitest';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as dep from '@editor/utils/dep';
 | 
					import * as utils from '../src/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('dep', () => {
 | 
					describe('utils', () => {
 | 
				
			||||||
  test('createCodeBlockTarget', () => {
 | 
					  test('createCodeBlockTarget', () => {
 | 
				
			||||||
    const target = dep.createCodeBlockTarget('code_5316', {
 | 
					    const target = utils.createCodeBlockTarget('code_5316', {
 | 
				
			||||||
      name: 'code',
 | 
					      name: 'code',
 | 
				
			||||||
      content: () => false,
 | 
					      content: () => false,
 | 
				
			||||||
      params: [],
 | 
					      params: [],
 | 
				
			||||||
@ -33,7 +33,7 @@ describe('dep', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    expect(isTarget).toBeTruthy();
 | 
					    expect(isTarget).toBeTruthy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const target1 = dep.createCodeBlockTarget('1', {
 | 
					    const target1 = utils.createCodeBlockTarget('1', {
 | 
				
			||||||
      name: 'code',
 | 
					      name: 'code',
 | 
				
			||||||
      content: () => false,
 | 
					      content: () => false,
 | 
				
			||||||
      params: [],
 | 
					      params: [],
 | 
				
			||||||
							
								
								
									
										13
									
								
								packages/dep/tsconfig.build.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								packages/dep/tsconfig.build.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": "../../tsconfig.json",
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "baseUrl": ".",
 | 
				
			||||||
 | 
					    "declaration": true,
 | 
				
			||||||
 | 
					    "declarationDir": "types",
 | 
				
			||||||
 | 
					    "forceConsistentCasingInFileNames": true,
 | 
				
			||||||
 | 
					    "paths": {},
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "include": [
 | 
				
			||||||
 | 
							"src"
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								packages/dep/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								packages/dep/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": "../../tsconfig.json",
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "baseUrl": "../..",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								packages/dep/vite.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								packages/dep/vite.config.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Tencent is pleased to support the open source community by making TMagicEditor available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2023 THL A29 Limited, a Tencent company.  All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { defineConfig } from 'vite';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pkg from './package.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default defineConfig({
 | 
				
			||||||
 | 
					  resolve: {
 | 
				
			||||||
 | 
					    alias:
 | 
				
			||||||
 | 
					      process.env.NODE_ENV === 'production'
 | 
				
			||||||
 | 
					        ? []
 | 
				
			||||||
 | 
					        : [{ find: /^@tmagic\/schema/, replacement: path.join(__dirname, '../schema/src/index.ts') }],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build: {
 | 
				
			||||||
 | 
					    sourcemap: true,
 | 
				
			||||||
 | 
					    minify: false,
 | 
				
			||||||
 | 
					    target: 'esnext',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lib: {
 | 
				
			||||||
 | 
					      entry: 'src/index.ts',
 | 
				
			||||||
 | 
					      name: 'TMagicDep',
 | 
				
			||||||
 | 
					      fileName: 'tmagic-dep',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rollupOptions: {
 | 
				
			||||||
 | 
					      // 确保外部化处理那些你不想打包进库的依赖
 | 
				
			||||||
 | 
					      external(id: string) {
 | 
				
			||||||
 | 
					        return Object.keys(pkg.dependencies).some((k) => new RegExp(`^${k}`).test(id));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -37,15 +37,15 @@
 | 
				
			|||||||
    "typescript"
 | 
					    "typescript"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2",
 | 
					    "@vue/test-utils": "^2.3.2",
 | 
				
			||||||
    "rimraf": "^3.0.2",
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
    "typescript": "^5.0.4",
 | 
					    "typescript": "^5.0.4",
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,7 @@
 | 
				
			|||||||
    "@babel/core": "^7.18.0",
 | 
					    "@babel/core": "^7.18.0",
 | 
				
			||||||
    "@element-plus/icons-vue": "^2.0.9",
 | 
					    "@element-plus/icons-vue": "^2.0.9",
 | 
				
			||||||
    "@tmagic/core": "1.3.1",
 | 
					    "@tmagic/core": "1.3.1",
 | 
				
			||||||
 | 
					    "@tmagic/dep": "1.3.1",
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "@tmagic/form": "1.3.1",
 | 
					    "@tmagic/form": "1.3.1",
 | 
				
			||||||
    "@tmagic/schema": "1.3.1",
 | 
					    "@tmagic/schema": "1.3.1",
 | 
				
			||||||
@ -63,13 +64,13 @@
 | 
				
			|||||||
    "monaco-editor": "^0.41.0",
 | 
					    "monaco-editor": "^0.41.0",
 | 
				
			||||||
    "moveable": "^0.51.1",
 | 
					    "moveable": "^0.51.1",
 | 
				
			||||||
    "serialize-javascript": "^6.0.0",
 | 
					    "serialize-javascript": "^6.0.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "@tmagic/form": "1.3.1",
 | 
					    "@tmagic/form": "1.3.1",
 | 
				
			||||||
    "monaco-editor": "^0.41.0",
 | 
					    "monaco-editor": "^0.41.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/events": "^3.0.0",
 | 
					    "@types/events": "^3.0.0",
 | 
				
			||||||
@ -77,7 +78,7 @@
 | 
				
			|||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
    "@types/serialize-javascript": "^5.0.1",
 | 
					    "@types/serialize-javascript": "^5.0.1",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2",
 | 
					    "@vue/test-utils": "^2.3.2",
 | 
				
			||||||
    "rimraf": "^3.0.2",
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
    "sass": "^1.35.1",
 | 
					    "sass": "^1.35.1",
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,7 @@ import './theme/index.scss';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type { OnDrag } from 'gesto';
 | 
					export type { OnDrag } from 'gesto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type { DepTargetType } from '@tmagic/dep';
 | 
				
			||||||
export type { MoveableOptions } from '@tmagic/stage';
 | 
					export type { MoveableOptions } from '@tmagic/stage';
 | 
				
			||||||
export * from './type';
 | 
					export * from './type';
 | 
				
			||||||
export * from './hooks';
 | 
					export * from './hooks';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,21 @@
 | 
				
			|||||||
import { onUnmounted, toRaw, watch } from 'vue';
 | 
					import { onUnmounted, reactive, toRaw, watch } from 'vue';
 | 
				
			||||||
import { cloneDeep } from 'lodash-es';
 | 
					import { cloneDeep } from 'lodash-es';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { EventOption } from '@tmagic/core';
 | 
					import type { EventOption } from '@tmagic/core';
 | 
				
			||||||
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from '@tmagic/schema';
 | 
					import type { Target } from '@tmagic/dep';
 | 
				
			||||||
import { getNodes } from '@tmagic/utils';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import PropsPanel from './layouts/PropsPanel.vue';
 | 
					 | 
				
			||||||
import type { Target } from './services/dep';
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  createCodeBlockTarget,
 | 
					  createCodeBlockTarget,
 | 
				
			||||||
  createDataSourceCondTarget,
 | 
					  createDataSourceCondTarget,
 | 
				
			||||||
  createDataSourceMethodTarget,
 | 
					  createDataSourceMethodTarget,
 | 
				
			||||||
  createDataSourceTarget,
 | 
					  createDataSourceTarget,
 | 
				
			||||||
} from './utils/dep';
 | 
					  DepTargetType,
 | 
				
			||||||
 | 
					} from '@tmagic/dep';
 | 
				
			||||||
 | 
					import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from '@tmagic/schema';
 | 
				
			||||||
 | 
					import { getNodes } from '@tmagic/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import PropsPanel from './layouts/PropsPanel.vue';
 | 
				
			||||||
import { EditorProps } from './editorProps';
 | 
					import { EditorProps } from './editorProps';
 | 
				
			||||||
import { DepTargetType, Services } from './type';
 | 
					import { Services } from './type';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export declare type LooseRequired<T> = {
 | 
					export declare type LooseRequired<T> = {
 | 
				
			||||||
  [P in string & keyof T]: T[P];
 | 
					  [P in string & keyof T]: T[P];
 | 
				
			||||||
@ -270,9 +271,9 @@ export const initServiceEvents = (
 | 
				
			|||||||
  depService.on('collected', collectedHandler);
 | 
					  depService.on('collected', collectedHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const initDataSourceDepTarget = (ds: DataSourceSchema) => {
 | 
					  const initDataSourceDepTarget = (ds: DataSourceSchema) => {
 | 
				
			||||||
    depService.addTarget(createDataSourceTarget(ds.id));
 | 
					    depService.addTarget(createDataSourceTarget(ds, reactive({})));
 | 
				
			||||||
    depService.addTarget(createDataSourceMethodTarget(ds.id));
 | 
					    depService.addTarget(createDataSourceMethodTarget(ds, reactive({})));
 | 
				
			||||||
    depService.addTarget(createDataSourceCondTarget(ds.id));
 | 
					    depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const rootChangeHandler = async (value: MApp | null, preValue?: MApp | null) => {
 | 
					  const rootChangeHandler = async (value: MApp | null, preValue?: MApp | null) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -44,13 +44,14 @@
 | 
				
			|||||||
import { computed, inject, ref } from 'vue';
 | 
					import { computed, inject, ref } from 'vue';
 | 
				
			||||||
import { Close, Edit, View } from '@element-plus/icons-vue';
 | 
					import { Close, Edit, View } from '@element-plus/icons-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { DepTargetType } from '@tmagic/dep';
 | 
				
			||||||
import { tMagicMessage, tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
 | 
					import { tMagicMessage, tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
 | 
				
			||||||
import type { Id } from '@tmagic/schema';
 | 
					import type { Id } from '@tmagic/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Icon from '@editor/components/Icon.vue';
 | 
					import Icon from '@editor/components/Icon.vue';
 | 
				
			||||||
import AppManageIcon from '@editor/icons/AppManageIcon.vue';
 | 
					import AppManageIcon from '@editor/icons/AppManageIcon.vue';
 | 
				
			||||||
import CodeIcon from '@editor/icons/CodeIcon.vue';
 | 
					import CodeIcon from '@editor/icons/CodeIcon.vue';
 | 
				
			||||||
import { CodeBlockListSlots, CodeDeleteErrorType, CodeDslItem, DepTargetType, Services } from '@editor/type';
 | 
					import { type CodeBlockListSlots, CodeDeleteErrorType, type CodeDslItem, type Services } from '@editor/type';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineSlots<CodeBlockListSlots>();
 | 
					defineSlots<CodeBlockListSlots>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -38,11 +38,12 @@
 | 
				
			|||||||
import { computed, inject, ref } from 'vue';
 | 
					import { computed, inject, ref } from 'vue';
 | 
				
			||||||
import { Aim, Close, Coin, Edit, View } from '@element-plus/icons-vue';
 | 
					import { Aim, Close, Coin, Edit, View } from '@element-plus/icons-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { DepTargetType } from '@tmagic/dep';
 | 
				
			||||||
import { tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
 | 
					import { tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
 | 
				
			||||||
import { Dep, Id } from '@tmagic/schema';
 | 
					import { DepData, Id } from '@tmagic/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Icon from '@editor/components/Icon.vue';
 | 
					import Icon from '@editor/components/Icon.vue';
 | 
				
			||||||
import { type DataSourceListSlots, DepTargetType, type Services } from '@editor/type';
 | 
					import type { DataSourceListSlots, Services } from '@editor/type';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineSlots<DataSourceListSlots>();
 | 
					defineSlots<DataSourceListSlots>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,10 +66,10 @@ const dsDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE) |
 | 
				
			|||||||
const dsMethodDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_METHOD) || {});
 | 
					const dsMethodDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_METHOD) || {});
 | 
				
			||||||
const dsCondDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_COND) || {});
 | 
					const dsCondDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_COND) || {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getKeyTreeConfig = (dep: Dep[string], type?: string) =>
 | 
					const getKeyTreeConfig = (dep: DepData[string], type?: string) =>
 | 
				
			||||||
  dep.keys.map((key) => ({ name: key, id: key, type: 'key', isMethod: type === 'method', isCond: type === 'cond' }));
 | 
					  dep.keys.map((key) => ({ name: key, id: key, type: 'key', isMethod: type === 'method', isCond: type === 'cond' }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getNodeTreeConfig = (id: string, dep: Dep[string], type?: string) => ({
 | 
					const getNodeTreeConfig = (id: string, dep: DepData[string], type?: string) => ({
 | 
				
			||||||
  name: dep.name,
 | 
					  name: dep.name,
 | 
				
			||||||
  type: 'node',
 | 
					  type: 'node',
 | 
				
			||||||
  id,
 | 
					  id,
 | 
				
			||||||
@ -81,7 +82,7 @@ const getNodeTreeConfig = (id: string, dep: Dep[string], type?: string) => ({
 | 
				
			|||||||
 * @param deps 依赖
 | 
					 * @param deps 依赖
 | 
				
			||||||
 * @param type 依赖类型
 | 
					 * @param type 依赖类型
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const mergeChildren = (children: any[], deps: Dep, type?: string) => {
 | 
					const mergeChildren = (children: any[], deps: DepData, type?: string) => {
 | 
				
			||||||
  Object.entries(deps).forEach(([id, dep]) => {
 | 
					  Object.entries(deps).forEach(([id, dep]) => {
 | 
				
			||||||
    // 已经生成过的节点
 | 
					    // 已经生成过的节点
 | 
				
			||||||
    const nodeItem = children.find((item) => item.id === id);
 | 
					    const nodeItem = children.find((item) => item.id === id);
 | 
				
			||||||
@ -97,9 +98,9 @@ const mergeChildren = (children: any[], deps: Dep, type?: string) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const list = computed(() =>
 | 
					const list = computed(() =>
 | 
				
			||||||
  dataSources.value.map((ds) => {
 | 
					  dataSources.value.map((ds) => {
 | 
				
			||||||
    const dsDeps = dsDep.value[ds.id].deps;
 | 
					    const dsDeps = dsDep.value[ds.id]?.deps || {};
 | 
				
			||||||
    const dsMethodDeps = dsMethodDep.value[ds.id].deps;
 | 
					    const dsMethodDeps = dsMethodDep.value[ds.id]?.deps || {};
 | 
				
			||||||
    const dsCondDeps = dsCondDep.value[ds.id].deps;
 | 
					    const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const children: any[] = [];
 | 
					    const children: any[] = [];
 | 
				
			||||||
    // 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
 | 
					    // 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
 | 
				
			||||||
 | 
				
			|||||||
@ -15,320 +15,58 @@
 | 
				
			|||||||
 * See the License for the specific language governing permissions and
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import { EventEmitter } from 'events';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { reactive } from 'vue';
 | 
					import { reactive } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { Dep, Id, MNode } from '@tmagic/schema';
 | 
					import { DepTargetType, type Target, Watcher } from '@tmagic/dep';
 | 
				
			||||||
import { isObject } from '@tmagic/utils';
 | 
					import type { Id, MNode } from '@tmagic/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { DepTargetType } from '@editor/type';
 | 
					import BaseService from './BaseService';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IsTarget = (key: string | number, value: any) => boolean;
 | 
					class Dep extends BaseService {
 | 
				
			||||||
 | 
					  private watcher = new Watcher({ initialTargets: reactive({}) });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface TargetOptions {
 | 
					  public removeTargets(type: string = DepTargetType.DEFAULT) {
 | 
				
			||||||
  isTarget: IsTarget;
 | 
					    this.watcher.removeTargets(type);
 | 
				
			||||||
  id: string | number;
 | 
					 | 
				
			||||||
  /** 类型,数据源、代码块或其他 */
 | 
					 | 
				
			||||||
  type?: DepTargetType | string;
 | 
					 | 
				
			||||||
  name?: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface TargetList {
 | 
					    this.emit('remove-target');
 | 
				
			||||||
  [type: DepTargetType | string]: {
 | 
					 | 
				
			||||||
    [targetId: string | number]: Target;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 需要收集依赖的目标
 | 
					 | 
				
			||||||
 * 例如:一个代码块可以为一个目标
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export class Target extends EventEmitter {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 如何识别目标
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public isTarget: IsTarget;
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 目标id,不可重复
 | 
					 | 
				
			||||||
   * 例如目标是代码块,则为代码块id
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public id: string | number;
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 目标名称,用于显示在依赖列表中
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public name?: string;
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public type: DepTargetType | string = DepTargetType.DEFAULT;
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 依赖详情
 | 
					 | 
				
			||||||
   * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public deps = reactive<Dep>({});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  constructor(options: TargetOptions) {
 | 
					 | 
				
			||||||
    super();
 | 
					 | 
				
			||||||
    this.isTarget = options.isTarget;
 | 
					 | 
				
			||||||
    this.id = options.id;
 | 
					 | 
				
			||||||
    this.name = options.name;
 | 
					 | 
				
			||||||
    if (options.type) {
 | 
					 | 
				
			||||||
      this.type = options.type;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  public getTargets(type: string = DepTargetType.DEFAULT) {
 | 
				
			||||||
   * 更新依赖
 | 
					    return this.watcher.getTargets(type);
 | 
				
			||||||
   * @param node 节点配置
 | 
					 | 
				
			||||||
   * @param key 哪个key配置了这个目标的id
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public updateDep(node: MNode, key: string | number) {
 | 
					 | 
				
			||||||
    const dep = this.deps[node.id] || {
 | 
					 | 
				
			||||||
      name: node.name,
 | 
					 | 
				
			||||||
      keys: [],
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (node.name) {
 | 
					 | 
				
			||||||
      dep.name = node.name;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.deps[node.id] = dep;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (dep.keys.indexOf(key) === -1) {
 | 
					 | 
				
			||||||
      dep.keys.push(key);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('change');
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  public getTarget(id: Id) {
 | 
				
			||||||
   * 删除依赖
 | 
					    return this.watcher.getTarget(id);
 | 
				
			||||||
   * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖
 | 
					 | 
				
			||||||
   * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key
 | 
					 | 
				
			||||||
   * @returns void
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public removeDep(node?: MNode, key?: string | number) {
 | 
					 | 
				
			||||||
    if (!node) {
 | 
					 | 
				
			||||||
      Object.keys(this.deps).forEach((depKey) => {
 | 
					 | 
				
			||||||
        delete this.deps[depKey];
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      this.emit('change');
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const dep = this.deps[node.id];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!dep) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (key) {
 | 
					 | 
				
			||||||
      const index = dep.keys.indexOf(key);
 | 
					 | 
				
			||||||
      dep.keys.splice(index, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (dep.keys.length === 0) {
 | 
					 | 
				
			||||||
        delete this.deps[node.id];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      delete this.deps[node.id];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('change');
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 判断指定节点下的指定key是否存在在依赖列表中
 | 
					 | 
				
			||||||
   * @param node 哪个节点
 | 
					 | 
				
			||||||
   * @param key 哪个key
 | 
					 | 
				
			||||||
   * @returns boolean
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public hasDep(node: MNode, key: string | number) {
 | 
					 | 
				
			||||||
    const dep = this.deps[node.id];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Boolean(dep?.keys.find((d) => d === key));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  public destroy() {
 | 
					 | 
				
			||||||
    this.removeAllListeners();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export class Watcher extends EventEmitter {
 | 
					 | 
				
			||||||
  private targets = reactive<TargetList>({});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 获取指定类型中的所有target
 | 
					 | 
				
			||||||
   * @param type 分类
 | 
					 | 
				
			||||||
   * @returns Target[]
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public getTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
 | 
					 | 
				
			||||||
    return this.targets[type] || {};
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 添加新的目标
 | 
					 | 
				
			||||||
   * @param target Target
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public addTarget(target: Target) {
 | 
					  public addTarget(target: Target) {
 | 
				
			||||||
    const targets = this.getTargets(target.type) || {};
 | 
					    this.watcher.addTarget(target);
 | 
				
			||||||
    this.targets[target.type] = targets;
 | 
					 | 
				
			||||||
    targets[target.id] = target;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('add-target', target);
 | 
					    this.emit('add-target', target);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  public removeTarget(id: Id) {
 | 
				
			||||||
   * 获取指定id的target
 | 
					    this.watcher.removeTarget(id);
 | 
				
			||||||
   * @param id target id
 | 
					 | 
				
			||||||
   * @returns Target
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public getTarget(id: string | number) {
 | 
					 | 
				
			||||||
    const allTargets = Object.values(this.targets);
 | 
					 | 
				
			||||||
    for (const targets of allTargets) {
 | 
					 | 
				
			||||||
      if (targets[id]) {
 | 
					 | 
				
			||||||
        return targets[id];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 判断是否存在指定id的target
 | 
					 | 
				
			||||||
   * @param id target id
 | 
					 | 
				
			||||||
   * @returns boolean
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public hasTarget(id: string | number) {
 | 
					 | 
				
			||||||
    const allTargets = Object.values(this.targets);
 | 
					 | 
				
			||||||
    for (const targets of allTargets) {
 | 
					 | 
				
			||||||
      if (targets[id]) {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 删除指定id的target
 | 
					 | 
				
			||||||
   * @param id target id
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public removeTarget(id: string | number) {
 | 
					 | 
				
			||||||
    const allTargets = Object.values(this.targets);
 | 
					 | 
				
			||||||
    for (const targets of allTargets) {
 | 
					 | 
				
			||||||
      if (targets[id]) {
 | 
					 | 
				
			||||||
        targets[id].destroy();
 | 
					 | 
				
			||||||
        delete targets[id];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('remove-target');
 | 
					    this.emit('remove-target');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 删除指定分类的所有target
 | 
					 | 
				
			||||||
   * @param type 分类
 | 
					 | 
				
			||||||
   * @returns void
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public removeTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
 | 
					 | 
				
			||||||
    const targets = this.targets[type];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!targets) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const target of Object.values(targets)) {
 | 
					 | 
				
			||||||
      target.destroy();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    delete this.targets[type];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('remove-target');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 删除所有target
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public clearTargets() {
 | 
					  public clearTargets() {
 | 
				
			||||||
    Object.keys(this.targets).forEach((key) => {
 | 
					    this.watcher.clearTargets();
 | 
				
			||||||
      delete this.targets[key];
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 收集依赖
 | 
					 | 
				
			||||||
   * @param nodes 需要收集的节点
 | 
					 | 
				
			||||||
   * @param deep 是否需要收集子节点
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public collect(nodes: MNode[], deep = false) {
 | 
					  public collect(nodes: MNode[], deep = false) {
 | 
				
			||||||
    Object.values(this.targets).forEach((targets) => {
 | 
					    this.watcher.collect(nodes, deep);
 | 
				
			||||||
      Object.values(targets).forEach((target) => {
 | 
					 | 
				
			||||||
        nodes.forEach((node) => {
 | 
					 | 
				
			||||||
          // 先删除原有依赖,重新收集
 | 
					 | 
				
			||||||
          target.removeDep(node);
 | 
					 | 
				
			||||||
          this.collectItem(node, target, deep);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.emit('collected', nodes, deep);
 | 
					    this.emit('collected', nodes, deep);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 清除依赖
 | 
					 | 
				
			||||||
   * @param nodes 需要清除依赖的节点
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public clear(nodes?: MNode[]) {
 | 
					  public clear(nodes?: MNode[]) {
 | 
				
			||||||
    const clearedItemsNodeIds: Id[] = [];
 | 
					    return this.watcher.clear(nodes);
 | 
				
			||||||
    Object.values(this.targets).forEach((targets) => {
 | 
					 | 
				
			||||||
      Object.values(targets).forEach((target) => {
 | 
					 | 
				
			||||||
        if (nodes) {
 | 
					 | 
				
			||||||
          nodes.forEach((node) => {
 | 
					 | 
				
			||||||
            target.removeDep(node);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (Array.isArray(node.items) && node.items.length && !clearedItemsNodeIds.includes(node.id)) {
 | 
					 | 
				
			||||||
              clearedItemsNodeIds.push(node.id);
 | 
					 | 
				
			||||||
              this.clear(node.items);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          target.removeDep();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private collectItem(node: MNode, target: Target, deep = false) {
 | 
					  public hasTarget(id: Id) {
 | 
				
			||||||
    const collectTarget = (config: Record<string | number, any>, prop = '') => {
 | 
					    return this.watcher.hasTarget(id);
 | 
				
			||||||
      const doCollect = (key: string, value: any) => {
 | 
					 | 
				
			||||||
        const keyIsItems = key === 'items';
 | 
					 | 
				
			||||||
        const fullKey = prop ? `${prop}.${key}` : key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (target.isTarget(fullKey, value)) {
 | 
					 | 
				
			||||||
          target.updateDep(node, fullKey);
 | 
					 | 
				
			||||||
          this.emit('update-dep', node, fullKey);
 | 
					 | 
				
			||||||
        } else if (!keyIsItems && Array.isArray(value)) {
 | 
					 | 
				
			||||||
          value.forEach((item, index) => {
 | 
					 | 
				
			||||||
            if (isObject(item)) {
 | 
					 | 
				
			||||||
              collectTarget(item, `${fullKey}.${index}`);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        } else if (isObject(value)) {
 | 
					 | 
				
			||||||
          collectTarget(value, fullKey);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (keyIsItems && deep && Array.isArray(value)) {
 | 
					 | 
				
			||||||
          value.forEach((child) => {
 | 
					 | 
				
			||||||
            this.collectItem(child, target, deep);
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Object.entries(config).forEach(([key, value]) => {
 | 
					 | 
				
			||||||
        if (typeof value === 'undefined' || value === '') return;
 | 
					 | 
				
			||||||
        doCollect(key, value);
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collectTarget(node);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type DepService = Watcher;
 | 
					export type DepService = Dep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default new Watcher();
 | 
					export default new Dep();
 | 
				
			||||||
 | 
				
			|||||||
@ -425,13 +425,6 @@ export type CodeState = {
 | 
				
			|||||||
  paramsColConfig?: ColumnConfig;
 | 
					  paramsColConfig?: ColumnConfig;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type HookData = {
 | 
					 | 
				
			||||||
  /** 代码块id */
 | 
					 | 
				
			||||||
  codeId: Id;
 | 
					 | 
				
			||||||
  /** 参数 */
 | 
					 | 
				
			||||||
  params?: object;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export type CodeRelation = {
 | 
					export type CodeRelation = {
 | 
				
			||||||
  /** 组件id:[代码id1,代码id2] */
 | 
					  /** 组件id:[代码id1,代码id2] */
 | 
				
			||||||
  [compId: Id]: Id[];
 | 
					  [compId: Id]: Id[];
 | 
				
			||||||
@ -594,19 +587,6 @@ export interface DataSourceFieldSelectConfig {
 | 
				
			|||||||
  display?: boolean | FilterFunction;
 | 
					  display?: boolean | FilterFunction;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 依赖收集的目标类型 */
 | 
					 | 
				
			||||||
export enum DepTargetType {
 | 
					 | 
				
			||||||
  DEFAULT = 'default',
 | 
					 | 
				
			||||||
  /** 代码块 */
 | 
					 | 
				
			||||||
  CODE_BLOCK = 'code-block',
 | 
					 | 
				
			||||||
  /** 数据源 */
 | 
					 | 
				
			||||||
  DATA_SOURCE = 'data-source',
 | 
					 | 
				
			||||||
  /** 数据源方法 */
 | 
					 | 
				
			||||||
  DATA_SOURCE_METHOD = 'data-source-method',
 | 
					 | 
				
			||||||
  /** 数据源条件 */
 | 
					 | 
				
			||||||
  DATA_SOURCE_COND = 'data-source-cond',
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 可新增的数据源类型选项 */
 | 
					/** 可新增的数据源类型选项 */
 | 
				
			||||||
export interface DatasourceTypeOption {
 | 
					export interface DatasourceTypeOption {
 | 
				
			||||||
  /** 数据源类型 */
 | 
					  /** 数据源类型 */
 | 
				
			||||||
 | 
				
			|||||||
@ -39,12 +39,12 @@
 | 
				
			|||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "element-plus": "^2.2.32",
 | 
					    "element-plus": "^2.2.32",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "element-plus": "^2.2.32",
 | 
					    "element-plus": "^2.2.32",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
 | 
				
			|||||||
@ -41,10 +41,10 @@
 | 
				
			|||||||
    "@tmagic/utils": "1.3.1",
 | 
					    "@tmagic/utils": "1.3.1",
 | 
				
			||||||
    "lodash-es": "^4.17.21",
 | 
					    "lodash-es": "^4.17.21",
 | 
				
			||||||
    "sortablejs": "^1.14.0",
 | 
					    "sortablejs": "^1.14.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@babel/core": "^7.18.0",
 | 
					    "@babel/core": "^7.18.0",
 | 
				
			||||||
@ -52,7 +52,7 @@
 | 
				
			|||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
    "@types/sortablejs": "^1.10.7",
 | 
					    "@types/sortablejs": "^1.10.7",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2",
 | 
					    "@vue/test-utils": "^2.3.2",
 | 
				
			||||||
    "rimraf": "^3.0.2",
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
    "sass": "^1.35.1",
 | 
					    "sass": "^1.35.1",
 | 
				
			||||||
 | 
				
			|||||||
@ -64,7 +64,7 @@ export enum ActionType {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface DataSourceDeps {
 | 
					export interface DataSourceDeps {
 | 
				
			||||||
  [dataSourceId: string | number]: Dep;
 | 
					  [dataSourceId: string | number]: DepData;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 事件类型(已废弃,后续不建议继续使用) */
 | 
					/** 事件类型(已废弃,后续不建议继续使用) */
 | 
				
			||||||
@ -241,10 +241,17 @@ export interface DataSourceSchema {
 | 
				
			|||||||
  [key: string]: any;
 | 
					  [key: string]: any;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Dep {
 | 
					export interface DepData {
 | 
				
			||||||
  [nodeId: Id]: {
 | 
					  [nodeId: Id]: {
 | 
				
			||||||
    /** 组件名称 */
 | 
					    /** 组件名称 */
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    keys: (string | number)[];
 | 
					    keys: (string | number)[];
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type HookData = {
 | 
				
			||||||
 | 
					  /** 代码块id */
 | 
				
			||||||
 | 
					  codeId: Id;
 | 
				
			||||||
 | 
					  /** 参数 */
 | 
				
			||||||
 | 
					  params?: object;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -38,18 +38,18 @@
 | 
				
			|||||||
    "@tmagic/form": "1.3.1",
 | 
					    "@tmagic/form": "1.3.1",
 | 
				
			||||||
    "@tmagic/utils": "1.3.1",
 | 
					    "@tmagic/utils": "1.3.1",
 | 
				
			||||||
    "lodash-es": "^4.17.21",
 | 
					    "lodash-es": "^4.17.21",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "@tmagic/form": "1.3.1",
 | 
					    "@tmagic/form": "1.3.1",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/color": "^3.0.1",
 | 
					    "@types/color": "^3.0.1",
 | 
				
			||||||
    "@types/lodash-es": "^4.17.4",
 | 
					    "@types/lodash-es": "^4.17.4",
 | 
				
			||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2",
 | 
					    "@vue/test-utils": "^2.3.2",
 | 
				
			||||||
    "rimraf": "^3.0.2",
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
    "sass": "^1.35.1",
 | 
					    "sass": "^1.35.1",
 | 
				
			||||||
 | 
				
			|||||||
@ -39,16 +39,16 @@
 | 
				
			|||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "tdesign-vue-next": "^1.3.4",
 | 
					    "tdesign-vue-next": "^1.3.4",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "@tmagic/design": "1.3.1",
 | 
					    "@tmagic/design": "1.3.1",
 | 
				
			||||||
    "tdesign-vue-next": "^1.3.4",
 | 
					    "tdesign-vue-next": "^1.3.4",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@types/node": "^15.12.4",
 | 
					    "@types/node": "^15.12.4",
 | 
				
			||||||
    "rimraf": "^3.0.2",
 | 
					    "rimraf": "^3.0.2",
 | 
				
			||||||
    "typescript": "^5.0.4",
 | 
					    "typescript": "^5.0.4",
 | 
				
			||||||
 | 
				
			|||||||
@ -18,16 +18,16 @@
 | 
				
			|||||||
    "delegate": "^3.2.0",
 | 
					    "delegate": "^3.2.0",
 | 
				
			||||||
    "qrcode": "^1.5.0",
 | 
					    "qrcode": "^1.5.0",
 | 
				
			||||||
    "tiny-emitter": "^2.1.0",
 | 
					    "tiny-emitter": "^2.1.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "peerDependencies": {
 | 
					  "peerDependencies": {
 | 
				
			||||||
    "qrcode": "^1.5.0",
 | 
					    "qrcode": "^1.5.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@testing-library/vue": "^6.4.2",
 | 
					    "@testing-library/vue": "^6.4.2",
 | 
				
			||||||
    "@types/qrcode": "^1.4.2",
 | 
					    "@types/qrcode": "^1.4.2",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2"
 | 
					    "@vue/test-utils": "^2.3.2"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@
 | 
				
			|||||||
    "element-plus": "^2.2.32",
 | 
					    "element-plus": "^2.2.32",
 | 
				
			||||||
    "monaco-editor": "^0.41.0",
 | 
					    "monaco-editor": "^0.41.0",
 | 
				
			||||||
    "serialize-javascript": "^6.0.0",
 | 
					    "serialize-javascript": "^6.0.0",
 | 
				
			||||||
    "vue": "^3.3.4",
 | 
					    "vue": "^3.3.8",
 | 
				
			||||||
    "vue-router": "^4.0.10"
 | 
					    "vue-router": "^4.0.10"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
@ -34,7 +34,7 @@
 | 
				
			|||||||
    "@vitejs/plugin-legacy": "^4.1.0",
 | 
					    "@vitejs/plugin-legacy": "^4.1.0",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vitejs/plugin-vue-jsx": "^3.0.1",
 | 
					    "@vitejs/plugin-vue-jsx": "^3.0.1",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "sass": "^1.35.1",
 | 
					    "sass": "^1.35.1",
 | 
				
			||||||
    "terser": "^5.14.2",
 | 
					    "terser": "^5.14.2",
 | 
				
			||||||
    "typescript": "^5.0.4",
 | 
					    "typescript": "^5.0.4",
 | 
				
			||||||
 | 
				
			|||||||
@ -59,6 +59,7 @@ export default defineConfig({
 | 
				
			|||||||
      { find: /^@tmagic\/utils/, replacement: path.join(__dirname, '../packages/utils/src/index.ts') },
 | 
					      { find: /^@tmagic\/utils/, replacement: path.join(__dirname, '../packages/utils/src/index.ts') },
 | 
				
			||||||
      { find: /^@tmagic\/design/, replacement: path.join(__dirname, '../packages/design/src/index.ts') },
 | 
					      { find: /^@tmagic\/design/, replacement: path.join(__dirname, '../packages/design/src/index.ts') },
 | 
				
			||||||
      { find: /^@tmagic\/data-source/, replacement: path.join(__dirname, '../packages/data-source/src/index.ts') },
 | 
					      { find: /^@tmagic\/data-source/, replacement: path.join(__dirname, '../packages/data-source/src/index.ts') },
 | 
				
			||||||
 | 
					      { find: /^@tmagic\/dep/, replacement: path.join(__dirname, '../packages/dep/src/index.ts') },
 | 
				
			||||||
      { find: /^@data-source/, replacement: path.join(__dirname, '../packages/data-source/src') },
 | 
					      { find: /^@data-source/, replacement: path.join(__dirname, '../packages/data-source/src') },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        find: /^@tmagic\/element-plus-adapter/,
 | 
					        find: /^@tmagic\/element-plus-adapter/,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										540
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										540
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -26,7 +26,7 @@
 | 
				
			|||||||
    "@tmagic/stage": "1.3.1",
 | 
					    "@tmagic/stage": "1.3.1",
 | 
				
			||||||
    "@tmagic/utils": "1.3.1",
 | 
					    "@tmagic/utils": "1.3.1",
 | 
				
			||||||
    "axios": "^0.25.0",
 | 
					    "axios": "^0.25.0",
 | 
				
			||||||
    "vue": "^3.3.4"
 | 
					    "vue": "^3.3.8"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@babel/preset-env": "^7.21.4",
 | 
					    "@babel/preset-env": "^7.21.4",
 | 
				
			||||||
@ -34,7 +34,7 @@
 | 
				
			|||||||
    "@vitejs/plugin-legacy": "^4.1.0",
 | 
					    "@vitejs/plugin-legacy": "^4.1.0",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^4.2.3",
 | 
					    "@vitejs/plugin-vue": "^4.2.3",
 | 
				
			||||||
    "@vitejs/plugin-vue-jsx": "^3.0.1",
 | 
					    "@vitejs/plugin-vue-jsx": "^3.0.1",
 | 
				
			||||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
					    "@vue/compiler-sfc": "^3.3.8",
 | 
				
			||||||
    "@vue/test-utils": "^2.3.2",
 | 
					    "@vue/test-utils": "^2.3.2",
 | 
				
			||||||
    "recast": "^0.20.4",
 | 
					    "recast": "^0.20.4",
 | 
				
			||||||
    "rollup": "^2.25.0",
 | 
					    "rollup": "^2.25.0",
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@ export default defineConfig({
 | 
				
			|||||||
      './packages/stage/tests/**',
 | 
					      './packages/stage/tests/**',
 | 
				
			||||||
      './packages/utils/tests/**',
 | 
					      './packages/utils/tests/**',
 | 
				
			||||||
      './packages/data-source/tests/**',
 | 
					      './packages/data-source/tests/**',
 | 
				
			||||||
 | 
					      './packages/dep/tests/**',
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    environment: 'jsdom',
 | 
					    environment: 'jsdom',
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user