From d7ee13011f5d3a8a8f203b7ae14228aedb137630 Mon Sep 17 00:00:00 2001 From: dswbx Date: Thu, 19 Dec 2024 08:16:47 +0100 Subject: [PATCH] isolated constructor functions for entities and relations from config --- app/src/data/AppData.ts | 54 ++++--------------- app/src/data/index.ts | 2 + app/src/data/schema/constructor.ts | 34 ++++++++++++ app/src/ui/client/api/use-data.ts | 2 +- .../ui/client/schema/data/use-bknd-data.ts | 5 +- app/src/ui/client/utils/AppReduced.ts | 7 ++- 6 files changed, 53 insertions(+), 51 deletions(-) create mode 100644 app/src/data/schema/constructor.ts diff --git a/app/src/data/AppData.ts b/app/src/data/AppData.ts index 821a3c6..6f885f0 100644 --- a/app/src/data/AppData.ts +++ b/app/src/data/AppData.ts @@ -1,52 +1,20 @@ import { transformObject } from "core/utils"; -import { DataPermissions, Entity, EntityIndex, type EntityManager, type Field } from "data"; +import { + DataPermissions, + type Entity, + EntityIndex, + type EntityManager, + constructEntity, + constructRelation +} from "data"; import { Module } from "modules/Module"; import { DataController } from "./api/DataController"; -import { - type AppDataConfig, - FIELDS, - RELATIONS, - type TAppDataEntity, - type TAppDataRelation, - dataConfigSchema -} from "./data-schema"; +import { type AppDataConfig, dataConfigSchema } from "./data-schema"; export class AppData extends Module { - static constructEntity(name: string, entityConfig: TAppDataEntity) { - const fields = transformObject(entityConfig.fields ?? {}, (fieldConfig, name) => { - const { type } = fieldConfig; - if (!(type in FIELDS)) { - throw new Error(`Field type "${type}" not found`); - } - - const { field } = FIELDS[type as any]; - const returnal = new field(name, fieldConfig.config) as Field; - return returnal; - }); - - // @todo: entity must be migrated to typebox - return new Entity( - name, - Object.values(fields), - entityConfig.config as any, - entityConfig.type as any - ); - } - - static constructRelation( - relationConfig: TAppDataRelation, - resolver: (name: Entity | string) => Entity - ) { - return new RELATIONS[relationConfig.type].cls( - resolver(relationConfig.source), - resolver(relationConfig.target), - relationConfig.config - ); - } - override async build() { const entities = transformObject(this.config.entities ?? {}, (entityConfig, name) => { - return AppData.constructEntity(name, entityConfig); + return constructEntity(name, entityConfig); }); const _entity = (_e: Entity | string): Entity => { @@ -57,7 +25,7 @@ export class AppData extends Module { }; const relations = transformObject(this.config.relations ?? {}, (relation) => - AppData.constructRelation(relation, _entity) + constructRelation(relation, _entity) ); const indices = transformObject(this.config.indices ?? {}, (index, name) => { diff --git a/app/src/data/index.ts b/app/src/data/index.ts index 284c653..3a287e6 100644 --- a/app/src/data/index.ts +++ b/app/src/data/index.ts @@ -18,6 +18,8 @@ export { LibsqlConnection, type LibSqlCredentials } from "./connection/LibsqlCon export { SqliteConnection } from "./connection/SqliteConnection"; export { SqliteLocalConnection } from "./connection/SqliteLocalConnection"; +export { constructEntity, constructRelation } from "./schema/constructor"; + export const DatabaseEvents = { ...MutatorEvents, ...RepositoryEvents diff --git a/app/src/data/schema/constructor.ts b/app/src/data/schema/constructor.ts new file mode 100644 index 0000000..a88ba5e --- /dev/null +++ b/app/src/data/schema/constructor.ts @@ -0,0 +1,34 @@ +import { transformObject } from "core/utils"; +import { Entity, type Field } from "data"; +import { FIELDS, RELATIONS, type TAppDataEntity, type TAppDataRelation } from "data/data-schema"; + +export function constructEntity(name: string, entityConfig: TAppDataEntity) { + const fields = transformObject(entityConfig.fields ?? {}, (fieldConfig, name) => { + const { type } = fieldConfig; + if (!(type in FIELDS)) { + throw new Error(`Field type "${type}" not found`); + } + + const { field } = FIELDS[type as any]; + const returnal = new field(name, fieldConfig.config) as Field; + return returnal; + }); + + return new Entity( + name, + Object.values(fields), + entityConfig.config as any, + entityConfig.type as any + ); +} + +export function constructRelation( + relationConfig: TAppDataRelation, + resolver: (name: Entity | string) => Entity +) { + return new RELATIONS[relationConfig.type].cls( + resolver(relationConfig.source), + resolver(relationConfig.target), + relationConfig.config + ); +} diff --git a/app/src/ui/client/api/use-data.ts b/app/src/ui/client/api/use-data.ts index 46cc81a..cd4ff22 100644 --- a/app/src/ui/client/api/use-data.ts +++ b/app/src/ui/client/api/use-data.ts @@ -10,7 +10,7 @@ type OmitFirstArg = F extends (x: any, ...args: infer P) => any * the first argument "entity" for convenience * @param entity */ -export const useData = (entity: string) => { +export const useData = >(entity: string) => { const api = useApi().data; const methods = [ "readOne", diff --git a/app/src/ui/client/schema/data/use-bknd-data.ts b/app/src/ui/client/schema/data/use-bknd-data.ts index 9de8636..36db148 100644 --- a/app/src/ui/client/schema/data/use-bknd-data.ts +++ b/app/src/ui/client/schema/data/use-bknd-data.ts @@ -1,6 +1,5 @@ import { Type, TypeInvalidError, parse, transformObject } from "core/utils"; -import type { Entity } from "data"; -import { AppData } from "data/AppData"; +import { constructEntity } from "data"; import { type TAppDataEntity, type TAppDataEntityFields, @@ -19,7 +18,7 @@ export function useBkndData() { // @todo: potentially store in ref, so it doesn't get recomputed? or use memo? const entities = transformObject(config.data.entities ?? {}, (entity, name) => { - return AppData.constructEntity(name, entity); + return constructEntity(name, entity); }); const actions = { diff --git a/app/src/ui/client/utils/AppReduced.ts b/app/src/ui/client/utils/AppReduced.ts index 0abc27b..8fa684f 100644 --- a/app/src/ui/client/utils/AppReduced.ts +++ b/app/src/ui/client/utils/AppReduced.ts @@ -1,6 +1,5 @@ import type { App } from "App"; -import type { Entity, EntityRelation } from "data"; -import { AppData } from "data/AppData"; +import { type Entity, type EntityRelation, constructEntity, constructRelation } from "data"; import { RelationAccessor } from "data/relations/RelationAccessor"; import { Flow, TaskMap } from "flows"; @@ -20,11 +19,11 @@ export class AppReduced { //console.log("received appjson", appJson); this._entities = Object.entries(this.appJson.data.entities ?? {}).map(([name, entity]) => { - return AppData.constructEntity(name, entity); + return constructEntity(name, entity); }); this._relations = Object.entries(this.appJson.data.relations ?? {}).map(([, relation]) => { - return AppData.constructRelation(relation, this.entity.bind(this)); + return constructRelation(relation, this.entity.bind(this)); }); for (const [name, obj] of Object.entries(this.appJson.flows.flows ?? {})) {