entity-factory.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import { getChangePart } from "../../shared";
  2. import {
  3. Entity,
  4. EntityKey,
  5. EntityShape,
  6. EntityTree,
  7. EntityType,
  8. EntityTypeInstance,
  9. } from "./entity";
  10. export const entityFactory = <
  11. P extends Entity,
  12. T,
  13. S extends EntityShape,
  14. C extends EntityType<T, S, EntityTree<P>>
  15. >(
  16. attrib: T,
  17. key: EntityKey,
  18. Type: C,
  19. parent?: P,
  20. extra?: (self: EntityTypeInstance<C>) => void,
  21. created?: (self: EntityTypeInstance<C>) => void
  22. ): EntityTypeInstance<C> => {
  23. const entity = new Type({
  24. attrib,
  25. key,
  26. }) as EntityTypeInstance<C>;
  27. extra && extra(entity);
  28. parent.addChild(entity);
  29. created && created(entity);
  30. return entity;
  31. };
  32. export type IncEntitys<
  33. P extends Entity,
  34. T,
  35. C extends EntityType<T, S, EntityTree<P>>,
  36. S extends EntityShape
  37. > = {
  38. adds: EntityTypeInstance<C>[];
  39. dels: EntityTypeInstance<C>[];
  40. upds: EntityTypeInstance<C>[];
  41. };
  42. export type IncEntitysFactory<
  43. P extends Entity,
  44. T,
  45. C extends EntityType<T, S, EntityTree<P>>,
  46. S extends EntityShape = EntityShape
  47. > = (attribs: T[]) => IncEntitys<P, T, C, S>;
  48. // 增量工厂
  49. export const incEntitysFactoryGenerate = <
  50. P extends Entity,
  51. T,
  52. S extends EntityShape,
  53. C extends EntityType<T, S, EntityTree<P>>
  54. >(
  55. Type: C,
  56. parent?: P,
  57. extra?: (self: EntityTypeInstance<C>) => void,
  58. created?: (self: EntityTypeInstance<C>) => void
  59. ): IncEntitysFactory<P, T, C, S> => {
  60. let oldKeys: string[] = [];
  61. let useIndex = false;
  62. let inited = false;
  63. const cache: { [key in string]: EntityTypeInstance<C> } = {};
  64. const findAttrib = (attribs: any[], key: string) => {
  65. if (useIndex) {
  66. return attribs[key];
  67. } else {
  68. return attribs.find((attrib) => attrib.id === key);
  69. }
  70. };
  71. const destory = (key: string) => {
  72. const delEntity = cache[key];
  73. delEntity.destory();
  74. delete cache[key];
  75. return delEntity;
  76. };
  77. const add = (attrib: T, key: string) => {
  78. const addEntity = entityFactory(attrib, key, Type, parent, extra, created);
  79. return (cache[key] = addEntity);
  80. };
  81. return (attribsRaw: T[]) => {
  82. const attribs = attribsRaw as any[];
  83. if (!inited && attribs.length && typeof attribs[0] === "object") {
  84. useIndex = "id" in attribs[0];
  85. inited = true;
  86. }
  87. if (
  88. !useIndex &&
  89. attribs.length &&
  90. attribs.some(
  91. (item) =>
  92. typeof item !== "object" ||
  93. (typeof item.id !== "string" && typeof item.id !== "number")
  94. )
  95. ) {
  96. throw "attribs 不合法,缺少id";
  97. }
  98. const newKeys = attribs.map((attrib, ndx) => (useIndex ? ndx : attrib.id));
  99. if (new Set(newKeys).size !== newKeys.length) {
  100. throw "attribs 的id不合法 不可重复";
  101. }
  102. const { addPort, delPort, holdPort } = getChangePart(newKeys, oldKeys);
  103. const dels = delPort.map(destory);
  104. const adds = addPort.map((key) => add(findAttrib(attribs, key), key));
  105. const upds = holdPort.map((key) => {
  106. const newAttrib = findAttrib(attribs, key);
  107. cache[key].setAttrib(newAttrib);
  108. return cache[key];
  109. });
  110. oldKeys = newKeys;
  111. return {
  112. adds,
  113. dels,
  114. upds,
  115. };
  116. };
  117. };
  118. export type SingleEntity<
  119. P extends Entity,
  120. T,
  121. C extends EntityType<T, S, EntityTree<P>>,
  122. S extends EntityShape
  123. > = {
  124. add?: EntityTypeInstance<C>;
  125. del?: EntityTypeInstance<C>;
  126. upd?: EntityTypeInstance<C>;
  127. };
  128. export type SingleEntityFactory<
  129. P extends Entity,
  130. T,
  131. C extends EntityType<T, S, EntityTree<P>>,
  132. S extends EntityShape = EntityShape
  133. > = (data: { attrib: T; key?: string }) => SingleEntity<P, T, C, S>;
  134. export const singleEntityFactory = <
  135. P extends Entity,
  136. T,
  137. S extends EntityShape,
  138. C extends EntityType<T, S, EntityTree<P>>
  139. >(
  140. Type: C,
  141. parent?: P,
  142. extra?: (self: EntityTypeInstance<C>) => void,
  143. created?: (self: EntityTypeInstance<C>) => void
  144. ): SingleEntityFactory<P, T, C, S> => {
  145. let entity: EntityTypeInstance<C> | null = null;
  146. return ({ attrib, key }) => {
  147. const result: SingleEntity<P, T, C, S> = {};
  148. if (entity) {
  149. if (!key) {
  150. entity.destory();
  151. result.del = entity;
  152. entity = null;
  153. } else if (key !== entity.getKey()) {
  154. console.error("entity 主键更改 销毁重建");
  155. entity.destory();
  156. result.del = entity;
  157. result.add = entityFactory(attrib, key, Type, parent, extra, created);
  158. entity = result.add;
  159. } else {
  160. entity.setAttrib(attrib);
  161. result.upd = entity;
  162. }
  163. } else if (key && attrib) {
  164. result.add = entityFactory(attrib, key, Type, parent, extra, created);
  165. entity = result.add;
  166. }
  167. return result;
  168. };
  169. };