entity.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import { nanoid } from 'nanoid';
  6. import { interfaces } from 'inversify';
  7. import { Compare, Disposable, DisposableCollection, Emitter, type Event } from '@flowgram.ai/utils';
  8. import { type PlaygroundContext } from './playground-context';
  9. import type { EntityManager } from './entity-manager';
  10. import type { EntityData, EntityDataProps, EntityDataRegistry } from './entity-data';
  11. // import type { AbleChangedEvent, EntityAbles } from './entity-ables';
  12. // import type { AbleManager } from './able-manager';
  13. // import type { Able, AbleRegistry } from './able';
  14. /**
  15. * 注册类
  16. */
  17. export interface EntityRegistry<E extends Entity = Entity> {
  18. new (opts: any): E;
  19. readonly type: E['type'];
  20. }
  21. /**
  22. * 持久化数据
  23. */
  24. export interface EntityJSON {
  25. type: string;
  26. id: string;
  27. // ableList?: string[];
  28. dataList: object[];
  29. }
  30. // eslint-disable-next-line no-proto
  31. const ObjectProto = (Object as any).__proto__;
  32. export interface EntityDataChangedEvent<T extends Entity = Entity> {
  33. type: 'add' | 'delete' | 'update';
  34. data: EntityData;
  35. entity: T;
  36. }
  37. export interface EntityOpts {
  38. entityManager: EntityManager;
  39. id?: string;
  40. // ables?: AbleRegistry[]; // 添加的 able
  41. datas?: { registry: EntityDataRegistry; data?: EntityDataProps<any> }[];
  42. savedInManager?: boolean; // 是否存储到 manager 上,默认 true
  43. }
  44. let _version = 0;
  45. export class Entity<OPTS extends EntityOpts = EntityOpts> implements Disposable {
  46. static type = 'Entity';
  47. private readonly onEntityChangeEmitter = new Emitter<Entity>();
  48. private readonly onDataChangeEmitter = new Emitter<EntityDataChangedEvent>();
  49. private readonly initializeDataKeys: string[] = []; // 初始化的
  50. protected readonly dataManager: Map<string, EntityData> = new Map(); // 存储的数据
  51. // readonly onBeforeAbleDispatchedEmitter = new Emitter<Able>();
  52. //
  53. // readonly onAfterAbleDispatchedEmitter = new Emitter<Able>();
  54. /**
  55. * 销毁事件管理
  56. */
  57. readonly toDispose = new DisposableCollection();
  58. /**
  59. * 销毁前事件管理
  60. */
  61. readonly preDispose = new DisposableCollection();
  62. // /**
  63. // * able 管理
  64. // */
  65. // readonly ables: EntityAbles;
  66. /**
  67. * 修改会触发
  68. */
  69. readonly onEntityChange = this.onEntityChangeEmitter.event;
  70. // /**
  71. // * able 触发之前
  72. // */
  73. // readonly onBeforeAbleDispatched = this.onBeforeAbleDispatchedEmitter.event;
  74. // /**
  75. // * able 触发之后
  76. // */
  77. // readonly onAfterAbleDispatched = this.onAfterAbleDispatchedEmitter.event;
  78. /**
  79. * 数据更改事件
  80. */
  81. readonly onDataChange = this.onDataChangeEmitter.event;
  82. // /**
  83. // * able 数据更改
  84. // */
  85. // readonly onAbleChange: Event<AbleChangedEvent>;
  86. // /**
  87. // * 默认初始化的 Able
  88. // */
  89. // getDefaultAbleRegistries(): AbleRegistry[] {
  90. // return [];
  91. // }
  92. /**
  93. * 默认初始化的 Data
  94. */
  95. getDefaultDataRegistries(): EntityDataRegistry[] {
  96. return [];
  97. }
  98. private _changeLockedTimes = 0;
  99. protected isInitialized = true;
  100. private _id: string;
  101. private _version: number = _version++; // 每次创建都有一个新 version,避免 id 相同的 entity 频繁创建销毁导致碰撞
  102. private _savedInManager = true;
  103. // readonly ableManager: AbleManager;
  104. /**
  105. * 暂停更新开关
  106. * @protected
  107. */
  108. protected get changeLocked(): boolean {
  109. return this._changeLockedTimes > 0;
  110. }
  111. protected set changeLocked(changeLocked) {
  112. this._changeLockedTimes = changeLocked
  113. ? this._changeLockedTimes + 1
  114. : this._changeLockedTimes - 1;
  115. /* istanbul ignore next */
  116. if (this._changeLockedTimes < 0) this._changeLockedTimes = 0;
  117. }
  118. /**
  119. * 实体类型
  120. */
  121. get type(): string {
  122. if (!(this.constructor as any).type) {
  123. throw new Error(`Entity Registry need a type: ${this.constructor.name}`);
  124. }
  125. return (this.constructor as any).type;
  126. }
  127. /**
  128. * 全局的entity管理器
  129. */
  130. readonly entityManager: EntityManager;
  131. get context(): PlaygroundContext {
  132. return this.entityManager.context;
  133. }
  134. constructor(opts: OPTS) {
  135. this.entityManager = opts.entityManager;
  136. this._id = opts.id || nanoid();
  137. this._savedInManager = opts.savedInManager === undefined ? true : opts.savedInManager;
  138. // this.ableManager = this.entityManager.ableManager;
  139. // this.context = this.entityManager.context;
  140. this.isInitialized = true;
  141. // this.ables = this.entityManager.ableManager.createAbleMap(this);
  142. // this.ables.onAbleChange(event => {
  143. // // 只需要监听删除,add 和 update 都由 entityData 去监听
  144. // if (event.type === 'delete') {
  145. // this.fireChange();
  146. // }
  147. // });
  148. this.toDispose.push(this.onEntityChangeEmitter);
  149. // this.toDispose.push(this.onBeforeAbleDispatchedEmitter);
  150. // this.toDispose.push(this.onAfterAbleDispatchedEmitter);
  151. this.toDispose.push(this.onDataChangeEmitter);
  152. // this.toDispose.push(this.ables);
  153. // this.onAbleChange = this.ables.onAbleChange;
  154. this.register();
  155. // if (opts.ables) {
  156. // opts.ables.forEach(able => this.ables.add(able));
  157. // }
  158. if (opts.datas) {
  159. opts.datas.forEach((data) => this.addData(data.registry, data.data));
  160. }
  161. this.isInitialized = false;
  162. }
  163. addInitializeData(datas: EntityDataRegistry[], dataConfig?: any) {
  164. this.isInitialized = true;
  165. datas.forEach((data) => this.addData(data, dataConfig));
  166. this.isInitialized = false;
  167. }
  168. /**
  169. * 实体的版本
  170. */
  171. get version(): number {
  172. return this._version;
  173. }
  174. /**
  175. * 存储数据,用于持久化存储
  176. */
  177. toJSON(): EntityJSON | any {
  178. const dataList: object[] = [];
  179. for (const data of this.dataManager.values()) {
  180. dataList.push({
  181. type: data.type,
  182. data: data.toJSON(),
  183. });
  184. }
  185. return {
  186. type: this.type,
  187. id: this.id,
  188. // ableList: this.ables.toJSON(),
  189. dataList,
  190. };
  191. }
  192. /**
  193. * 还原数据
  194. */
  195. fromJSON(data?: EntityJSON | any): void {
  196. if (!data || !data.id || !data.type) return;
  197. this.changeLocked = true;
  198. this.reset();
  199. if (data.dataList) {
  200. data.dataList.forEach((d: any) => {
  201. const registry = this.entityManager.getDataRegistryByType(d.type);
  202. if (registry) {
  203. const dataEntity = this.addData(registry);
  204. dataEntity.update(d.data);
  205. }
  206. });
  207. }
  208. this.changeLocked = false;
  209. this.fireChange();
  210. }
  211. /**
  212. * 实体 id
  213. */
  214. get id(): string {
  215. return this._id;
  216. }
  217. /**
  218. * 销毁实体
  219. */
  220. dispose(): void {
  221. this.preDispose.dispose();
  222. this.toDispose.dispose();
  223. }
  224. get disposed(): boolean {
  225. return this.toDispose.disposed;
  226. }
  227. /**
  228. * 重制为初始化状态
  229. */
  230. reset(): void {
  231. this.changeLocked = true;
  232. for (const data of this.dataManager.values()) {
  233. if (!this.initializeDataKeys.includes(data.type)) {
  234. data.dispose();
  235. }
  236. }
  237. // this.ables.reset();
  238. this.register();
  239. this.changeLocked = false;
  240. this.fireChange();
  241. }
  242. /**
  243. * 销毁事件
  244. */
  245. get onDispose(): Event<void> {
  246. return this.toDispose.onDispose;
  247. }
  248. /**
  249. * 触发实体更新
  250. * @protected
  251. */
  252. protected fireChange(): void {
  253. if (this.changeLocked || this.isInitialized || this.disposed) return;
  254. this._version++;
  255. /* istanbul ignore next */
  256. if (this._version >= Number.MAX_SAFE_INTEGER) {
  257. this._version = 0;
  258. }
  259. this.onEntityChangeEmitter.fire(this);
  260. }
  261. /**
  262. * 添加数据
  263. */
  264. addData<D extends EntityData>(
  265. Registry: EntityDataRegistry,
  266. defaultProps?: EntityDataProps<D>
  267. ): D {
  268. this.entityManager.registerEntityData(Registry);
  269. let entityData = this.dataManager.get(Registry.type) as D;
  270. if (entityData) {
  271. if (defaultProps) this.updateData(Registry, defaultProps);
  272. return entityData;
  273. }
  274. // 是否存在EntityData依赖注入器
  275. const injector = this.entityManager.getDataInjector(Registry);
  276. entityData = new Registry(this, injector?.()) as D;
  277. if (this.isInitialized) this.initializeDataKeys.push(entityData.type);
  278. this.dataManager.set(Registry.type, entityData);
  279. this.toDispose.push(entityData);
  280. entityData.onDataChange(() => {
  281. const event: EntityDataChangedEvent = {
  282. type: 'update',
  283. data: entityData,
  284. entity: this,
  285. };
  286. this.onDataChangeEmitter.fire(event);
  287. this.fireChange();
  288. });
  289. entityData.toDispose.push(
  290. Disposable.create(() => {
  291. // 初始化的 data 数据无法被删除
  292. if (!this.initializeDataKeys.includes(Registry.type)) {
  293. this.dataManager.delete(Registry.type);
  294. }
  295. const event: EntityDataChangedEvent = {
  296. type: 'delete',
  297. data: entityData,
  298. entity: this,
  299. };
  300. this.onDataChangeEmitter.fire(event);
  301. this.fireChange();
  302. })
  303. );
  304. entityData.changeLocked = true;
  305. this.updateData(Registry, defaultProps || entityData.getDefaultData());
  306. entityData.changeLocked = false;
  307. const event: EntityDataChangedEvent = {
  308. type: 'add',
  309. data: entityData,
  310. entity: this,
  311. };
  312. this.onDataChangeEmitter.fire(event);
  313. return entityData;
  314. }
  315. /**
  316. * 是否存到全局 manager,默认 true
  317. */
  318. get savedInManager(): boolean {
  319. return this._savedInManager;
  320. }
  321. /**
  322. * 更新实体的数据
  323. */
  324. updateData<D extends EntityData>(
  325. Registry: EntityDataRegistry<D>,
  326. props: EntityDataProps<D>
  327. ): void {
  328. const entityData = this.dataManager.get(Registry.type);
  329. if (entityData) {
  330. entityData.update(props);
  331. }
  332. }
  333. /**
  334. * 获取 data 数据
  335. */
  336. getData<D extends EntityData>(Registry: EntityDataRegistry<D>): D {
  337. return this.dataManager.get(Registry.type) as D;
  338. }
  339. /**
  340. * 是否有指定数据
  341. */
  342. hasData(Registry: EntityDataRegistry): boolean {
  343. return this.dataManager.has(Registry.type);
  344. }
  345. /**
  346. * 删除数据,初始化状态注入的数据无法被删除
  347. */
  348. removeData<D extends EntityData>(Registry: EntityDataRegistry<D>): void {
  349. // 初始化的数据无法被删除
  350. if (this.initializeDataKeys.includes(Registry.type)) return;
  351. const entityData = this.dataManager.get(Registry.type);
  352. if (entityData) {
  353. entityData.dispose();
  354. }
  355. }
  356. /**
  357. * 获取 IOC 服务
  358. * @param identifier
  359. */
  360. getService<T>(identifier: interfaces.ServiceIdentifier<T>): T {
  361. return this.entityManager.getService<T>(identifier);
  362. }
  363. // /**
  364. // * 添加 able
  365. // */
  366. // addAbles(...ables: AbleRegistry[]): void {
  367. // ables.forEach(able => this.ables.add(able));
  368. // }
  369. //
  370. // /**
  371. // * 删除 able
  372. // */
  373. // removeAbles(...ables: AbleRegistry[]): void {
  374. // ables.forEach(able => this.ables.remove(able));
  375. // }
  376. //
  377. // /**
  378. // * 是否有 able
  379. // */
  380. // hasAble(able: AbleRegistry): boolean {
  381. // return this.ables.has(able);
  382. // }
  383. //
  384. // hasAbles(...ables: AbleRegistry[]): boolean {
  385. // for (const able of ables) {
  386. // if (!this.ables.has(able)) return false;
  387. // }
  388. // return true;
  389. // }
  390. protected register(): void {
  391. // 注册默认 able
  392. // this.getDefaultAbleRegistries().forEach(Registry => this.ables.add(Registry));
  393. // 注册默认 data
  394. this.getDefaultDataRegistries().forEach((Registry) => this.addData(Registry));
  395. }
  396. declare __opts_type__: OPTS;
  397. }
  398. export namespace Entity {
  399. export function getType(registry: EntityRegistry): string {
  400. return registry.type;
  401. }
  402. /**
  403. * 默认数据比较,采用浅比较
  404. */
  405. export function checkDataChanged(oldProps: any, newProps: any): boolean {
  406. return Compare.isChanged(oldProps, newProps);
  407. }
  408. export function isRegistryOf(target: any, Registry: any): boolean {
  409. if (target === Registry) return true;
  410. // eslint-disable-next-line no-proto
  411. let proto = target.__proto__;
  412. while (proto && proto !== ObjectProto) {
  413. if (proto.prototype === Registry.prototype) return true;
  414. // eslint-disable-next-line no-proto
  415. proto = proto.__proto__;
  416. }
  417. return false;
  418. }
  419. }