backend/lib/seed/engine/EngineModel.ts
2025-05-14 21:45:16 +02:00

278 lines
10 KiB
TypeScript

import _ from 'lodash';
import { ObjectType } from 'type-graphql';
import { classToPlain, Exclude, plainToClassFromExist } from 'class-transformer';
import { Collection, ObjectId } from 'mongodb';
import DB from '@seed/services/database/DBService';
import { Permission } from '@seed/interfaces/permission';
import { ApolloContext } from '@seed/interfaces/context';
import { IEngineSchema, MetaBy } from './EngineSchema';
import { GetArgs } from '@seed/graphql/Request';
import {
bulk,
deleteOne,
getAll,
getCount,
getMany,
getOne,
getQuery,
saveMany,
saveOne,
updateOne,
updateOneCustom,
updateOneSubField,
} from './utils/crud.utils';
import { getCountGeneric, getManyGeneric, getManyGenericWithArgs, getOneGeneric } from './utils/service.utils';
import {
BulkInput,
DeleteOneInput,
GetAllInput,
GetCountInput,
GetManyInput,
GetOneInput,
GetQueryInput,
SaveManyInput,
SaveOneInput,
UpdateOneCustomInput,
UpdateOneInput,
UpdateOneSubField,
} from './utils/__interface';
import { EnginePathComponent } from '@seed/interfaces/components';
import { ModelCollectionEnum } from '@src/__indexes/__collections';
import { nullToUndefined } from '@seed/helpers/Utils';
@ObjectType()
export abstract class EngineModel<SchemaDBInterface, SchemaDB, Schema> implements IEngineSchema {
@Exclude()
public collectionName: ModelCollectionEnum | string;
@Exclude()
public permissions: Permission;
@Exclude()
defaultSort: string;
dbData: SchemaDB;
searchT?: string;
_id: string;
organisationId?: string | undefined;
paths?: EnginePathComponent[];
by?: MetaBy | undefined;
createdAt: Date;
updatedAt: Date;
tagsIds?: string[];
public constructor(init: {
collectionName: ModelCollectionEnum | string;
permissions: Permission;
dataInit: SchemaDB & Partial<IEngineSchema>;
defaultSort?: string;
}) {
this.collectionName = init.collectionName;
this.permissions = init.permissions;
this.dbData = init.dataInit;
this.permissions = {
c: init.permissions.c,
r: init.permissions.r,
w: init.permissions.w,
d: init.permissions.d,
};
this.createdAt = new Date();
this.updatedAt = new Date();
this.defaultSort = init.defaultSort || 'createdAt desc';
}
/*
*
* Model functions
*
*/
public get(): Schema {
const data: any = this.dbData;
if (this._id) data._id = this._id;
if (this.permissions) data.permissions = this.permissions;
if (this.organisationId) data.organisationId = this.organisationId;
if (this.by) data.by = this.by;
if (this.createdAt) data.createdAt = this.createdAt;
if (this.updatedAt) data.updatedAt = this.updatedAt;
return this.plainToClass(data) as Schema;
}
public set(doc: any): void {
const newData = {
...classToPlain(this.dbData), // Get old data
...doc, // Replace with new data
};
this.dbData = _.assign(this.dbData, newData);
if (doc._id) this._id = doc._id;
if (doc.permissions) {
this.permissions = {
c: _.uniq(_.concat(doc.permissions.c)),
r: _.uniq(_.concat(doc.permissions.r)),
w: _.uniq(_.concat(doc.permissions.w)),
d: _.uniq(_.concat(doc.permissions.d)),
};
}
if (doc.organisationId) this.organisationId = doc.organisationId;
if (doc.paths) this.paths = doc.paths;
if (doc.createdAt) this.createdAt = doc.createdAt;
if (doc.updatedAt) this.updatedAt = doc.updatedAt;
}
async beforeCreate?(ctx?: ApolloContext | null): Promise<void>;
async beforeUpdate?(ctx?: ApolloContext | null): Promise<void>;
async beforeDelete?(ctx?: ApolloContext | null): Promise<void>;
async afterCreate?(changeStream: any): Promise<void>;
async afterUpdate?(changeStream: any): Promise<void>;
async afterDelete?(changeStream: any): Promise<void>;
/*
*
* Search Functions & Helpers
*
*/
searchEngine?(): any;
searchText?(): any;
/*
*
* Transform Functions
*
*/
abstract plainToClass(plain: any): Schema | Schema[];
/*
*
* DB Functions
*
*/
public async db(): Promise<Collection<SchemaDBInterface & IEngineSchema>> {
return await (await DB.getInstance()).db.collection<SchemaDBInterface & IEngineSchema>(this.collectionName);
}
generatePaths?(): EnginePathComponent[];
public getPaths(): EnginePathComponent[] {
return this.generatePaths ? this.generatePaths() : this.paths ? this.paths : [];
}
public getFullPath(): EnginePathComponent[] {
const myPath = this.getPaths();
myPath.push({
ressourceModel: this.collectionName,
ressourceId: this._id,
});
return myPath;
}
// ██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗
// ██╔═══██╗██║ ██║██╔════╝██╔══██╗╚██╗ ██╔╝
// ██║ ██║██║ ██║█████╗ ██████╔╝ ╚████╔╝
// ██║▄▄ ██║██║ ██║██╔══╝ ██╔══██╗ ╚██╔╝
// ╚██████╔╝╚██████╔╝███████╗██║ ██║ ██║
// ╚══▀▀═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝
public async getQuery(input: GetQueryInput<SchemaDBInterface>): Promise<any> {
return getQuery(this, input);
}
public async getMany(input: GetManyInput<SchemaDBInterface>): Promise<Schema[]> {
return getMany(this, input);
}
public async getCount(input: GetCountInput<SchemaDBInterface>): Promise<number> {
return getCount(this, input);
}
public async getAll(input: GetAllInput<SchemaDBInterface>): Promise<Schema[]> {
return getAll(this, input);
}
public async getOne(input: GetOneInput<SchemaDBInterface>): Promise<Schema> {
let newInput;
if (!input.query) {
newInput = { query: input };
} else newInput = input;
return getOne(this, newInput);
}
// ███╗ ███╗██╗ ██╗████████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗
// ████╗ ████║██║ ██║╚══██╔══╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║
// ██╔████╔██║██║ ██║ ██║ ███████║ ██║ ██║██║ ██║██╔██╗ ██║
// ██║╚██╔╝██║██║ ██║ ██║ ██╔══██║ ██║ ██║██║ ██║██║╚██╗██║
// ██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
// ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
public async saveOne(input: SaveOneInput<SchemaDBInterface>): Promise<Schema> {
return saveOne(this, input);
}
public async updateOne(input: UpdateOneInput<SchemaDBInterface>): Promise<Schema> {
return updateOne(this, input);
}
public async updateOneCustom(input: UpdateOneCustomInput<SchemaDBInterface>): Promise<Schema> {
return updateOneCustom(this, input);
}
public async updateOneSubField(input: UpdateOneSubField<SchemaDBInterface>): Promise<Schema> {
return updateOneSubField(this, input);
}
public async deleteOne(input: DeleteOneInput<SchemaDBInterface>): Promise<Schema> {
return deleteOne(this, input);
}
public async saveMany(input: SaveManyInput<SchemaDBInterface>): Promise<Schema[]> {
return saveMany(this, input);
}
public async bulk(input: BulkInput<SchemaDBInterface, SchemaDB, Schema>): Promise<void> {
return bulk(this, input);
}
// ██████╗ ███████╗███╗ ██╗███████╗██████╗ ██╗ ██████╗███████╗
// ██╔════╝ ██╔════╝████╗ ██║██╔════╝██╔══██╗██║██╔════╝██╔════╝
// ██║ ███╗█████╗ ██╔██╗ ██║█████╗ ██████╔╝██║██║ ███████╗
// ██║ ██║██╔══╝ ██║╚██╗██║██╔══╝ ██╔══██╗██║██║ ╚════██║
// ╚██████╔╝███████╗██║ ╚████║███████╗██║ ██║██║╚██████╗███████║
// ╚═════╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚══════
public async getOneGeneric(id: string, ctx: ApolloContext): Promise<Schema> {
return getOneGeneric(this, id, ctx);
}
public async getManyGeneric(query: any, pagination: GetArgs | undefined, ctx: ApolloContext | null): Promise<Schema[]> {
return getManyGeneric(this, query, pagination, ctx);
}
public async getCountGeneric(baseArguments: any, ctx: ApolloContext): Promise<number> {
return getCountGeneric(this, baseArguments, ctx);
}
public async getManyGenericWithArgs(baseArguments: any, ctx: ApolloContext | null): Promise<Schema[]> {
return getManyGenericWithArgs(this, baseArguments, ctx);
}
}