import { getChangePart } from "../../shared"; import { Entity, EntityShape, EntityTransmit, EntityTree, EntityType, EntityTypeInstance, } from "./entity"; const getEntityTransmitProps = (parent: Entity): EntityTransmit => { return { root: parent.root, }; }; export const entityFactoryAfter = < P extends Entity, C extends Entity> >( entity: C, parent?: P ) => { if (parent) { const transmit = getEntityTransmitProps(parent); for (const key in transmit) { entity[key] = parent[key]; } entity.setParent(parent); } entity.init(); entity.mount(); if (parent?.isMounted) { entity.mounted(); } }; export const entityFactory = < P extends Entity, T, S extends EntityShape, C extends EntityType> >( attrib: T, key: string, Type: C, parent?: P, extra?: (self: EntityTypeInstance) => void, created?: (self: EntityTypeInstance) => void ): EntityTypeInstance => { const entity = new Type({ attrib, key, }) as EntityTypeInstance; extra && extra(entity); entityFactoryAfter(entity as any, parent); created && created(entity); return entity; }; export type IncEntitys< P extends Entity, T, C extends EntityType>, S extends EntityShape > = { adds: EntityTypeInstance[]; dels: EntityTypeInstance[]; upds: EntityTypeInstance[]; }; export type IncEntitysFactory< P extends Entity, T, C extends EntityType>, S extends EntityShape = EntityShape > = (attribs: T[]) => IncEntitys; // 增量工厂 export const incEntitysFactoryGenerate = < P extends Entity, T, S extends EntityShape, C extends EntityType> >( Type: C, parent?: P, extra?: (self: EntityTypeInstance) => void, created?: (self: EntityTypeInstance) => void ): IncEntitysFactory => { let oldKeys: string[] = []; let useIndex = false; let inited = false; const cache: { [key in string]: EntityTypeInstance } = {}; const findAttrib = (attribs: any[], key: string) => { if (useIndex) { return attribs[key]; } else { return attribs.find((attrib) => attrib.id === key); } }; const destory = (key: string) => { const delEntity = cache[key]; delEntity.destory(); delete cache[key]; return delEntity; }; const add = (attrib: T, key: string) => { const addEntity = entityFactory(attrib, key, Type, parent, extra, created); return (cache[key] = addEntity); }; return (attribsRaw: T[]) => { const attribs = attribsRaw as any[]; if (!inited && attribs.length && typeof attribs[0] === "object") { useIndex = !!attribs[0].id; inited = true; } if ( !useIndex && attribs.length && attribs.some( (item) => typeof item !== "object" || typeof item.id !== "string" ) ) { throw "attribs 不合法,缺少id"; } const newKeys = attribs.map((attrib, ndx) => useIndex ? ndx.toString() : attrib.id ); if (new Set(newKeys).size !== newKeys.length) { throw "attribs 的id不合法 不可重复"; } const { addPort, delPort, holdPort } = getChangePart(newKeys, oldKeys); const dels = delPort.map(destory); const adds = addPort.map((key) => add(findAttrib(attribs, key), key)); const upds = holdPort.map((key) => { const newAttrib = findAttrib(attribs, key); cache[key].setAttrib(newAttrib); return cache[key]; }); oldKeys = newKeys; return { adds, dels, upds, }; }; }; export type SingleEntity< P extends Entity, T, C extends EntityType>, S extends EntityShape > = { add?: EntityTypeInstance; del?: EntityTypeInstance; upd?: EntityTypeInstance; }; export type SingleEntityFactory< P extends Entity, T, C extends EntityType>, S extends EntityShape = EntityShape > = (data: { attrib: T; key?: string }) => SingleEntity; export const singleEntityFactory = < P extends Entity, T, S extends EntityShape, C extends EntityType> >( Type: C, parent?: P, extra?: (self: EntityTypeInstance) => void, created?: (self: EntityTypeInstance) => void ): SingleEntityFactory => { let entity: EntityTypeInstance | null = null; return ({ attrib, key }) => { const result: SingleEntity = {}; if (entity) { if (!key) { entity.destory(); result.del = entity; entity = null; } else if (key !== entity.getKey()) { console.error("entity 主键更改 销毁重建"); entity.destory(); result.del = entity; result.add = entityFactory(attrib, key, Type, parent, extra, created); entity = result.add; } else { entity.setAttrib(attrib); result.upd = entity; } } else if (key && attrib) { result.add = entityFactory(attrib, key, Type, parent, extra, created); entity = result.add; } return result; }; };