UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

441 lines (440 loc) 21 kB
import { Model } from "@decaf-ts/decorator-validation"; import { Repo } from "../repository/Repository"; import { RelationsMetadata } from "./types"; import { AdapterFlags, ContextOf } from "../persistence/types"; import { Context } from "../persistence/Context"; /** * @description Creates or updates a model instance * @summary Determines whether to create a new model or update an existing one based on the presence of a primary key * @template M - The model type extending Model * @template F - The repository flags type * @param {M} model - The model instance to create or update * @param {Context<F>} context - The context for the operation * @param {Repo<M, F, Context<F>>} [repository] - Optional repository to use for the operation * @return {Promise<M>} A promise that resolves to the created or updated model * @function createOrUpdate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant createOrUpdate * participant Repository * participant Model * * Caller->>createOrUpdate: model, context, repository? * alt repository not provided * createOrUpdate->>Model: get(model.constructor.name) * Model-->>createOrUpdate: constructor * createOrUpdate->>Repository: forModel(constructor) * Repository-->>createOrUpdate: repository * end * * alt primary key undefined * createOrUpdate->>Repository: create(model, context) * Repository-->>createOrUpdate: created model * else primary key defined * createOrUpdate->>Repository: update(model, context) * alt update successful * Repository-->>createOrUpdate: updated model * else NotFoundError * createOrUpdate->>Repository: create(model, context) * Repository-->>createOrUpdate: created model * end * end * * createOrUpdate-->>Caller: model */ export declare function createOrUpdate<M extends Model, F extends AdapterFlags>(model: M, context: Context<F>, alias: string, repository?: Repo<M>): Promise<M>; /** * @description Handles one-to-one relationship creation * @summary Processes a one-to-one relationship when creating a model, either by referencing an existing model or creating a new one * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param {string} key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToOneOnCreate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToOneOnCreate * participant repositoryFromTypeMetadata * participant Model * participant Repository * participant cacheModelForPopulate * * Caller->>oneToOneOnCreate: this, context, data, key, model * oneToOneOnCreate->>oneToOneOnCreate: check if propertyValue exists * * alt propertyValue is not an object * oneToOneOnCreate->>repositoryFromTypeMetadata: model, key * repositoryFromTypeMetadata-->>oneToOneOnCreate: innerRepo * oneToOneOnCreate->>innerRepo: read(propertyValue) * innerRepo-->>oneToOneOnCreate: read * oneToOneOnCreate->>cacheModelForPopulate: context, model, key, propertyValue, read * oneToOneOnCreate->>oneToOneOnCreate: set model[key] = propertyValue * else propertyValue is an object * oneToOneOnCreate->>Model: get(data.class) * Model-->>oneToOneOnCreate: constructor * oneToOneOnCreate->>Repository: forModel(constructor) * Repository-->>oneToOneOnCreate: repo * oneToOneOnCreate->>repo: create(propertyValue) * repo-->>oneToOneOnCreate: created * oneToOneOnCreate->>findPrimaryKey: created * findPrimaryKey-->>oneToOneOnCreate: pk * oneToOneOnCreate->>cacheModelForPopulate: context, model, key, created[pk], created * oneToOneOnCreate->>oneToOneOnCreate: set model[key] = created[pk] * end * * oneToOneOnCreate-->>Caller: void */ export declare function oneToOneOnCreate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Handles one-to-one relationship updates * @summary Processes a one-to-one relationship when updating a model, either by referencing an existing model or updating the related model * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToOneOnUpdate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToOneOnUpdate * participant repositoryFromTypeMetadata * participant createOrUpdate * participant findPrimaryKey * participant cacheModelForPopulate * * Caller->>oneToOneOnUpdate: this, context, data, key, model * oneToOneOnUpdate->>oneToOneOnUpdate: check if propertyValue exists * oneToOneOnUpdate->>oneToOneOnUpdate: check if cascade.update is CASCADE * * alt propertyValue is not an object * oneToOneOnUpdate->>repositoryFromTypeMetadata: model, key * repositoryFromTypeMetadata-->>oneToOneOnUpdate: innerRepo * oneToOneOnUpdate->>innerRepo: read(propertyValue) * innerRepo-->>oneToOneOnUpdate: read * oneToOneOnUpdate->>cacheModelForPopulate: context, model, key, propertyValue, read * oneToOneOnUpdate->>oneToOneOnUpdate: set model[key] = propertyValue * else propertyValue is an object * oneToOneOnUpdate->>createOrUpdate: model[key], context * createOrUpdate-->>oneToOneOnUpdate: updated * oneToOneOnUpdate->>findPrimaryKey: updated * findPrimaryKey-->>oneToOneOnUpdate: pk * oneToOneOnUpdate->>cacheModelForPopulate: context, model, key, updated[pk], updated * oneToOneOnUpdate->>oneToOneOnUpdate: set model[key] = updated[pk] * end * * oneToOneOnUpdate-->>Caller: void */ export declare function oneToOneOnUpdate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Handles one-to-one relationship deletion * @summary Processes a one-to-one relationship when deleting a model, deleting the related model if cascade is enabled * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToOneOnDelete * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToOneOnDelete * participant repositoryFromTypeMetadata * participant cacheModelForPopulate * * Caller->>oneToOneOnDelete: this, context, data, key, model * oneToOneOnDelete->>oneToOneOnDelete: check if propertyValue exists * oneToOneOnDelete->>oneToOneOnDelete: check if cascade.update is CASCADE * * oneToOneOnDelete->>repositoryFromTypeMetadata: model, key * repositoryFromTypeMetadata-->>oneToOneOnDelete: innerRepo * * alt propertyValue is not a Model instance * oneToOneOnDelete->>innerRepo: delete(model[key], context) * innerRepo-->>oneToOneOnDelete: deleted * else propertyValue is a Model instance * oneToOneOnDelete->>innerRepo: delete(model[key][innerRepo.pk], context) * innerRepo-->>oneToOneOnDelete: deleted * end * * oneToOneOnDelete->>cacheModelForPopulate: context, model, key, deleted[innerRepo.pk], deleted * oneToOneOnDelete-->>Caller: void */ export declare function oneToOneOnDelete<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Handles one-to-many relationship creation * @summary Processes a one-to-many relationship when creating a model, either by referencing existing models or creating new ones * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToManyOnCreate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToManyOnCreate * participant repositoryFromTypeMetadata * participant createOrUpdate * participant findPrimaryKey * participant cacheModelForPopulate * * Caller->>oneToManyOnCreate: this, context, data, key, model * oneToManyOnCreate->>oneToManyOnCreate: check if propertyValues exists and has length * oneToManyOnCreate->>oneToManyOnCreate: check if all elements have same type * oneToManyOnCreate->>oneToManyOnCreate: create uniqueValues set * * alt arrayType is not "object" * oneToManyOnCreate->>repositoryFromTypeMetadata: model, key * repositoryFromTypeMetadata-->>oneToManyOnCreate: repo * loop for each id in uniqueValues * oneToManyOnCreate->>repo: read(id) * repo-->>oneToManyOnCreate: read * oneToManyOnCreate->>cacheModelForPopulate: context, model, key, id, read * end * oneToManyOnCreate->>oneToManyOnCreate: set model[key] = [...uniqueValues] * else arrayType is "object" * oneToManyOnCreate->>findPrimaryKey: propertyValues[0] * findPrimaryKey-->>oneToManyOnCreate: pkName * oneToManyOnCreate->>oneToManyOnCreate: create result set * loop for each m in propertyValues * oneToManyOnCreate->>createOrUpdate: m, context * createOrUpdate-->>oneToManyOnCreate: record * oneToManyOnCreate->>cacheModelForPopulate: context, model, key, record[pkName], record * oneToManyOnCreate->>oneToManyOnCreate: add record[pkName] to result * end * oneToManyOnCreate->>oneToManyOnCreate: set model[key] = [...result] * end * * oneToManyOnCreate-->>Caller: void */ export declare function oneToManyOnCreate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Handles one-to-many relationship updates * @summary Processes a one-to-many relationship when updating a model, delegating to oneToManyOnCreate if cascade update is enabled * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToManyOnUpdate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToManyOnUpdate * participant oneToManyOnCreate * * Caller->>oneToManyOnUpdate: this, context, data, key, model * oneToManyOnUpdate->>oneToManyOnUpdate: check if cascade.update is CASCADE * * alt cascade.update is CASCADE * oneToManyOnUpdate->>oneToManyOnCreate: apply(this, [context, data, key, model]) * oneToManyOnCreate-->>oneToManyOnUpdate: void * end * * oneToManyOnUpdate-->>Caller: void */ export declare function oneToManyOnUpdate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Handles one-to-many relationship deletion * @summary Processes a one-to-many relationship when deleting a model, deleting all related models if cascade delete is enabled * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function oneToManyOnDelete * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant oneToManyOnDelete * participant Repository * participant repositoryFromTypeMetadata * participant cacheModelForPopulate * * Caller->>oneToManyOnDelete: this, context, data, key, model * oneToManyOnDelete->>oneToManyOnDelete: check if cascade.delete is CASCADE * oneToManyOnDelete->>oneToManyOnDelete: check if values exists and has length * oneToManyOnDelete->>oneToManyOnDelete: check if all elements have same type * * alt isInstantiated (arrayType is "object") * oneToManyOnDelete->>Repository: forModel(values[0]) * Repository-->>oneToManyOnDelete: repo * else not instantiated * oneToManyOnDelete->>repositoryFromTypeMetadata: model, key * repositoryFromTypeMetadata-->>oneToManyOnDelete: repo * end * * oneToManyOnDelete->>oneToManyOnDelete: create uniqueValues set * * loop for each id in uniqueValues * oneToManyOnDelete->>repo: delete(id, context) * repo-->>oneToManyOnDelete: deleted * oneToManyOnDelete->>cacheModelForPopulate: context, model, key, id, deleted * end * * oneToManyOnDelete->>oneToManyOnDelete: set model[key] = [...uniqueValues] * oneToManyOnDelete-->>Caller: void */ export declare function oneToManyOnDelete<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Generates a key for caching populated model relationships * @summary Creates a unique key for storing and retrieving populated model relationships in the cache * @param {string} tableName - The name of the table or model * @param {string} fieldName - The name of the field or property * @param {string|number} id - The identifier of the related model * @return {string} A dot-separated string that uniquely identifies the relationship * @function getPopulateKey * @memberOf module:core */ export declare function getPopulateKey(tableName: string, fieldName: string, id: string | number): string; /** * @description Caches a model for later population * @summary Stores a model in the context cache for efficient retrieval during relationship population * @template M - The model type extending Model * @template F - The repository flags type * @param {Context<F>} context - The context for the operation * @param {M} parentModel - The parent model that contains the relationship * @param propertyKey - The property key of the relationship * @param {string | number} pkValue - The primary key value of the related model * @param {any} cacheValue - The model instance to cache * @return {Promise<any>} A promise that resolves with the result of the cache operation * @function cacheModelForPopulate * @memberOf module:core */ export declare function cacheModelForPopulate<M extends Model, F extends AdapterFlags>(context: Context<F>, parentModel: M, propertyKey: keyof M | string, pkValue: string | number, cacheValue: any): Promise<import("@decaf-ts/db-decorators").Context<any>>; /** * @description Populates a model's relationship * @summary Retrieves and attaches related models to a model's relationship property * @template M - The model type extending Model * @template R - The repository type extending Repo<M, F, C> * @template V - The relations metadata type extending RelationsMetadata * @template F - The repository flags type * @template C - The context type extending Context<F> * @param {R} this - The repository instance * @param {Context<F>} context - The context for the operation * @param {V} data - The relations metadata * @param key - The property key of the relationship * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the operation is complete * @function populate * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant populate * participant fetchPopulateValues * participant getPopulateKey * participant Context * participant repositoryFromTypeMetadata * * Caller->>populate: this, context, data, key, model * populate->>populate: check if data.populate is true * populate->>populate: get nested value and check if it exists * * populate->>fetchPopulateValues: context, model, key, isArr ? nested : [nested] * * fetchPopulateValues->>fetchPopulateValues: initialize variables * * loop for each proKeyValue in propKeyValues * fetchPopulateValues->>getPopulateKey: model.constructor.name, propName, proKeyValue * getPopulateKey-->>fetchPopulateValues: cacheKey * * alt try to get from cache * fetchPopulateValues->>Context: get(cacheKey) * Context-->>fetchPopulateValues: val * else catch error * fetchPopulateValues->>repositoryFromTypeMetadata: model, propName * repositoryFromTypeMetadata-->>fetchPopulateValues: repo * fetchPopulateValues->>repo: read(proKeyValue) * repo-->>fetchPopulateValues: val * end * * fetchPopulateValues->>fetchPopulateValues: add val to results * end * * fetchPopulateValues-->>populate: results * populate->>populate: set model[key] = isArr ? res : res[0] * populate-->>Caller: void */ export declare function populate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>; /** * @description Retrieves a repository for a model property based on its type metadata * @summary Examines a model property's type metadata to determine the appropriate repository for related models * @template M - The model type extending Model * @param {any} model - The model instance containing the property * @param propertyKey - The property key to examine * @return {Repo<M>} A repository for the model type associated with the property * @function repositoryFromTypeMetadata * @memberOf module:core * @mermaid * sequenceDiagram * participant Caller * participant repositoryFromTypeMetadata * participant Reflect * participant Validation * participant Model * participant Repository * * Caller->>repositoryFromTypeMetadata: model, propertyKey * * repositoryFromTypeMetadata->>repositoryFromTypeMetadata: Get allowedTypes array * repositoryFromTypeMetadata->>repositoryFromTypeMetadata: find constructorName not in commomTypes * repositoryFromTypeMetadata->>repositoryFromTypeMetadata: check if constructorName exists * * repositoryFromTypeMetadata->>Model: get(constructorName) * Model-->>repositoryFromTypeMetadata: constructor * repositoryFromTypeMetadata->>repositoryFromTypeMetadata: check if constructor exists * * repositoryFromTypeMetadata->>Repository: forModel(constructor) * Repository-->>repositoryFromTypeMetadata: repo * * repositoryFromTypeMetadata-->>Caller: repo */ export declare function repositoryFromTypeMetadata<M extends Model>(model: M, propertyKey: keyof M, alias?: string): Repo<M>;