From 9091387a6e036d97abf9b5784b7da8c837497276 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Fri, 16 Dec 2022 16:19:44 -0300 Subject: [PATCH 1/9] refactor: moved API model layer moved from database folder to src/models --- src/database/seeders/index.ts | 8 ++++---- src/{database => }/models/AssetModel.ts | 6 +++--- src/{database => }/models/CompanyModel.ts | 6 +++--- src/{database => }/models/Model.ts | 6 +++--- src/{database => }/models/UnitModel.ts | 6 +++--- src/{database => }/models/UserModel.ts | 6 +++--- src/services/AssetService.ts | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) rename src/{database => }/models/AssetModel.ts (57%) rename src/{database => }/models/CompanyModel.ts (89%) rename src/{database => }/models/Model.ts (91%) rename src/{database => }/models/UnitModel.ts (79%) rename src/{database => }/models/UserModel.ts (85%) diff --git a/src/database/seeders/index.ts b/src/database/seeders/index.ts index 90e1a8d..c0613e5 100644 --- a/src/database/seeders/index.ts +++ b/src/database/seeders/index.ts @@ -1,8 +1,8 @@ /* eslint-disable no-console */ -import AssetModel from '../models/AssetModel'; -import CompanyModel from '../models/CompanyModel'; -import UnitModel from '../models/UnitModel'; -import UserModel from '../models/UserModel'; +import AssetModel from '../../models/AssetModel'; +import CompanyModel from '../../models/CompanyModel'; +import UnitModel from '../../models/UnitModel'; +import UserModel from '../../models/UserModel'; import assets from './Assets'; import companies from './Companies'; import units from './Units'; diff --git a/src/database/models/AssetModel.ts b/src/models/AssetModel.ts similarity index 57% rename from src/database/models/AssetModel.ts rename to src/models/AssetModel.ts index 44ff06c..d8d0966 100644 --- a/src/database/models/AssetModel.ts +++ b/src/models/AssetModel.ts @@ -1,6 +1,6 @@ -import { Asset } from '../../@types/Entities'; -import { IAssetModel } from '../../interfaces/IAssetModel'; -import assetSchema from '../schemas/assetSchema'; +import { Asset } from '../@types/Entities'; +import { IAssetModel } from '../interfaces/IAssetModel'; +import assetSchema from '../database/schemas/assetSchema'; import Model from './Model'; class AssetModel extends Model implements IAssetModel { diff --git a/src/database/models/CompanyModel.ts b/src/models/CompanyModel.ts similarity index 89% rename from src/database/models/CompanyModel.ts rename to src/models/CompanyModel.ts index 40dd061..55cc5d9 100644 --- a/src/database/models/CompanyModel.ts +++ b/src/models/CompanyModel.ts @@ -1,6 +1,6 @@ -import { Company } from '../../@types/Entities'; -import { ICompanyModel } from '../../interfaces/ICompanyModel'; -import companySchema from '../schemas/companySchema'; +import { Company } from '../@types/Entities'; +import { ICompanyModel } from '../interfaces/ICompanyModel'; +import companySchema from '../database/schemas/companySchema'; import Model from './Model'; class CompanyModel extends Model implements ICompanyModel { diff --git a/src/database/models/Model.ts b/src/models/Model.ts similarity index 91% rename from src/database/models/Model.ts rename to src/models/Model.ts index 0013dec..71ae191 100644 --- a/src/database/models/Model.ts +++ b/src/models/Model.ts @@ -1,7 +1,7 @@ import { model, Schema } from 'mongoose'; -import { IModel } from '../../interfaces/IModel'; -import { Entity, Archive } from '../../@types/Entities'; -import archiveSchema from '../schemas/archiveSchema'; +import { IModel } from '../interfaces/IModel'; +import { Entity, Archive } from '../@types/Entities'; +import archiveSchema from '../database/schemas/archiveSchema'; abstract class Model implements IModel { protected abstract _populate: string; diff --git a/src/database/models/UnitModel.ts b/src/models/UnitModel.ts similarity index 79% rename from src/database/models/UnitModel.ts rename to src/models/UnitModel.ts index d8667de..9632b81 100644 --- a/src/database/models/UnitModel.ts +++ b/src/models/UnitModel.ts @@ -1,6 +1,6 @@ -import { Unit } from '../../@types/Entities'; -import { IUnitModel } from '../../interfaces/IUnitModel'; -import unitSchema from '../schemas/unitSchema'; +import { Unit } from '../@types/Entities'; +import { IUnitModel } from '../interfaces/IUnitModel'; +import unitSchema from '../database/schemas/unitSchema'; import Model from './Model'; class UnitModel extends Model implements IUnitModel { diff --git a/src/database/models/UserModel.ts b/src/models/UserModel.ts similarity index 85% rename from src/database/models/UserModel.ts rename to src/models/UserModel.ts index 629e7a4..64a8165 100644 --- a/src/database/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -1,6 +1,6 @@ -import { User } from '../../@types/Entities'; -import { IUserModel } from '../../interfaces/IUserModel'; -import userSchema from '../schemas/userSchema'; +import { User } from '../@types/Entities'; +import { IUserModel } from '../interfaces/IUserModel'; +import userSchema from '../database/schemas/userSchema'; import Model from './Model'; class UserModel extends Model implements IUserModel { diff --git a/src/services/AssetService.ts b/src/services/AssetService.ts index 5532524..41db511 100644 --- a/src/services/AssetService.ts +++ b/src/services/AssetService.ts @@ -1,6 +1,6 @@ import { AssetStatus } from '../@types/AssetStatus'; import { Asset } from '../@types/Entities'; -import AssetModel from '../database/models/AssetModel'; +import AssetModel from '../models/AssetModel'; import Service from './Service'; class AssetService extends Service { From 19d4ce92b461b53906624a65a96faa36085d4bd3 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Fri, 16 Dec 2022 16:27:12 -0300 Subject: [PATCH 2/9] feat: created mongo db internal static models --- src/database/models/index.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/database/models/index.ts diff --git a/src/database/models/index.ts b/src/database/models/index.ts new file mode 100644 index 0000000..d513f8d --- /dev/null +++ b/src/database/models/index.ts @@ -0,0 +1,12 @@ +import { model } from 'mongoose'; +import archiveSchema from '../schemas/archiveSchema'; +import assetSchema from '../schemas/assetSchema'; +import companySchema from '../schemas/companySchema'; +import unitSchema from '../schemas/unitSchema'; +import userSchema from '../schemas/userSchema'; + +export const User = model('User', userSchema); +export const Asset = model('Asset', assetSchema); +export const Company = model('Company', companySchema); +export const Unit = model('Unit', unitSchema); +export const Archive = model('Archive', archiveSchema); From ce940ed449cb149be1c8f8f42df2a5b0110adbcd Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 00:41:53 -0300 Subject: [PATCH 3/9] refactor: made entity types more versatile they are now compatible with mongoose schema types --- src/@types/Entities.ts | 19 +++++++++++++++---- src/database/schemas/assetSchema.ts | 8 ++------ src/database/schemas/companySchema.ts | 10 ++-------- src/database/schemas/unitSchema.ts | 9 ++------- src/database/schemas/userSchema.ts | 8 ++------ 5 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/@types/Entities.ts b/src/@types/Entities.ts index 06aa4c6..47f9fc3 100644 --- a/src/@types/Entities.ts +++ b/src/@types/Entities.ts @@ -6,12 +6,23 @@ import { export type Entity = z.infer; -export type User = z.infer; +export type User = Omit, 'company'> & { + company: string | Record; +}; -export type Company = z.infer; +export type Company = Omit, 'employees' | 'assets' | 'units'> & { + employees: string[] | Record[]; + assets: string[] | Record[]; + units: string[] | Record[]; +}; -export type Unit = z.infer; +export type Unit = Omit, 'assets' | 'owner'> & { + assets: string[] | Record[]; + owner: string | Record; +}; -export type Asset = z.infer; +export type Asset = Omit, 'owner'> & { + owner: string | Record; +}; export type Archive = z.infer; diff --git a/src/database/schemas/assetSchema.ts b/src/database/schemas/assetSchema.ts index af7dcf9..7bdb4de 100644 --- a/src/database/schemas/assetSchema.ts +++ b/src/database/schemas/assetSchema.ts @@ -1,11 +1,7 @@ -import { ObjectId, Schema } from 'mongoose'; +import { Schema } from 'mongoose'; import { Asset } from '../../@types/Entities'; -type SchemaCompatibleAsset = Omit & { - owner: ObjectId; -}; - -const assetSchema = new Schema({ +const assetSchema = new Schema({ name: { type: String, require: [true, 'Asset name field is required.'], diff --git a/src/database/schemas/companySchema.ts b/src/database/schemas/companySchema.ts index 7f51eba..9905a72 100644 --- a/src/database/schemas/companySchema.ts +++ b/src/database/schemas/companySchema.ts @@ -1,13 +1,7 @@ -import { ObjectId, Schema } from 'mongoose'; +import { Schema } from 'mongoose'; import { Company } from '../../@types/Entities'; -type SchemaCompatibleCompany = Omit & { - assets: ObjectId[]; - employees: ObjectId[]; - units: ObjectId[]; -}; - -const companySchema = new Schema({ +const companySchema = new Schema({ name: { type: String, required: [true, 'Company name field is required.'], diff --git a/src/database/schemas/unitSchema.ts b/src/database/schemas/unitSchema.ts index 628c42b..3389ddc 100644 --- a/src/database/schemas/unitSchema.ts +++ b/src/database/schemas/unitSchema.ts @@ -1,12 +1,7 @@ -import { ObjectId, Schema } from 'mongoose'; +import { Schema } from 'mongoose'; import { Unit } from '../../@types/Entities'; -type SchemaCompatibleUnit = Omit & { - assets: ObjectId[]; - owner: ObjectId; -}; - -const unitSchema = new Schema({ +const unitSchema = new Schema({ name: { type: String, required: [true, 'Unit name field is required.'], diff --git a/src/database/schemas/userSchema.ts b/src/database/schemas/userSchema.ts index 4cc4f03..18a91fd 100644 --- a/src/database/schemas/userSchema.ts +++ b/src/database/schemas/userSchema.ts @@ -1,11 +1,7 @@ -import { ObjectId, Schema } from 'mongoose'; +import { Schema } from 'mongoose'; import { User } from '../../@types/Entities'; -type SchemaCompatibleUser = Omit & { - company: ObjectId; -}; - -const userSchema = new Schema({ +const userSchema = new Schema({ name: { type: String, required: [true, 'User name is required.'], From 831667f5ae242ce3f579e525760cff7a93893cb5 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 00:43:52 -0300 Subject: [PATCH 4/9] refactor: changed generic Model dependency type it now receives a static mongoose Model --- src/models/Model.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/models/Model.ts b/src/models/Model.ts index 71ae191..dc389b7 100644 --- a/src/models/Model.ts +++ b/src/models/Model.ts @@ -1,4 +1,4 @@ -import { model, Schema } from 'mongoose'; +import { Model as MongoModel } from 'mongoose'; import { IModel } from '../interfaces/IModel'; import { Entity, Archive } from '../@types/Entities'; import archiveSchema from '../database/schemas/archiveSchema'; @@ -8,9 +8,8 @@ abstract class Model implements IModel { private _archive; protected _model; - constructor(entityName: string, schema: Schema) { - this._model = model(entityName, schema); - this._archive = model('Archive', archiveSchema); + constructor(model: MongoModel) { + this._model = model; } async createOne(object: T): Promise { From 96a59eb081d54d6ede0c7cc3d75c7d150829feb5 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 00:46:26 -0300 Subject: [PATCH 5/9] refactor(Model): changed archiving now using static Archive model directly from import --- src/models/Model.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/models/Model.ts b/src/models/Model.ts index dc389b7..31325bc 100644 --- a/src/models/Model.ts +++ b/src/models/Model.ts @@ -1,11 +1,10 @@ import { Model as MongoModel } from 'mongoose'; import { IModel } from '../interfaces/IModel'; -import { Entity, Archive } from '../@types/Entities'; -import archiveSchema from '../database/schemas/archiveSchema'; +import { Entity, Archive as ArchiveType } from '../@types/Entities'; +import { Archive } from '../database/models'; abstract class Model implements IModel { protected abstract _populate: string; - private _archive; protected _model; constructor(model: MongoModel) { @@ -50,12 +49,12 @@ abstract class Model implements IModel { // This saves the object in an archive that is only accessible by the database admins. // With this, data is not lost forever and can be consulted if necessary. - const archived: Archive = { + const archived: ArchiveType = { collectionName: this._model.collection.collectionName, document: deleted, }; - await this._archive.create(archived); + await Archive.create(archived); return deleted as T; } From d7b07399ab6cf4ccd8fdac4c89685a95af499595 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 00:54:58 -0300 Subject: [PATCH 6/9] build: increased eslint max-len limit --- .eslintrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index ec7da8d..fe664dc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -24,6 +24,7 @@ "rules": { "@typescript-eslint/lines-between-class-members": "off", "no-underscore-dangle": "off", - "import/prefer-default-export": "off" + "import/prefer-default-export": "off", + "max-len": ["warn", 120] } } From 984d2c18f93244e918e770e168a1ccef1801e93c Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 00:59:28 -0300 Subject: [PATCH 7/9] refactor: changed all API Models constructors now they all pass a static mongoose model as dependency through super --- src/models/AssetModel.ts | 8 ++++---- src/models/CompanyModel.ts | 20 ++++++++++---------- src/models/UnitModel.ts | 12 ++++++------ src/models/UserModel.ts | 16 ++++++++-------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/models/AssetModel.ts b/src/models/AssetModel.ts index d8d0966..0a73aff 100644 --- a/src/models/AssetModel.ts +++ b/src/models/AssetModel.ts @@ -1,13 +1,13 @@ -import { Asset } from '../@types/Entities'; +import { Asset as AssetType } from '../@types/Entities'; import { IAssetModel } from '../interfaces/IAssetModel'; -import assetSchema from '../database/schemas/assetSchema'; import Model from './Model'; +import { Asset } from '../database/models'; -class AssetModel extends Model implements IAssetModel { +class AssetModel extends Model implements IAssetModel { protected _populate = 'owner'; constructor() { - super('Asset', assetSchema); + super(Asset); } } diff --git a/src/models/CompanyModel.ts b/src/models/CompanyModel.ts index 55cc5d9..a20335e 100644 --- a/src/models/CompanyModel.ts +++ b/src/models/CompanyModel.ts @@ -1,16 +1,16 @@ -import { Company } from '../@types/Entities'; +import { Company as CompanyType } from '../@types/Entities'; +import { Company } from '../database/models'; import { ICompanyModel } from '../interfaces/ICompanyModel'; -import companySchema from '../database/schemas/companySchema'; import Model from './Model'; -class CompanyModel extends Model implements ICompanyModel { +class CompanyModel extends Model implements ICompanyModel { protected _populate = 'employees assets units'; constructor() { - super('Company', companySchema); + super(Company); } - async editEmployeeList(id: string, employeeId: string, add: boolean): Promise { + async editEmployeeList(id: string, employeeId: string, add: boolean): Promise { const edited = add ? await this._model.findByIdAndUpdate(id, { $push: { employees: employeeId }, @@ -19,10 +19,10 @@ class CompanyModel extends Model implements ICompanyModel { $pull: { employees: employeeId }, }, { new: true }); - return edited?.toObject() as Company; + return edited?.toObject() as CompanyType; } - async editAssetList(id: string, assetId: string, add: boolean): Promise { + async editAssetList(id: string, assetId: string, add: boolean): Promise { const edited = add ? await this._model.findByIdAndUpdate(id, { $push: { assets: assetId }, @@ -31,10 +31,10 @@ class CompanyModel extends Model implements ICompanyModel { $pull: { assets: assetId }, }, { new: true }); - return edited?.toObject() as Company; + return edited?.toObject() as CompanyType; } - async editUnitList(id: string, unitId: string, add: boolean): Promise { + async editUnitList(id: string, unitId: string, add: boolean): Promise { const edited = add ? await this._model.findByIdAndUpdate(id, { $push: { units: unitId }, @@ -43,7 +43,7 @@ class CompanyModel extends Model implements ICompanyModel { $pull: { units: unitId }, }, { new: true }); - return edited?.toObject() as Company; + return edited?.toObject() as CompanyType; } } diff --git a/src/models/UnitModel.ts b/src/models/UnitModel.ts index 9632b81..498caa9 100644 --- a/src/models/UnitModel.ts +++ b/src/models/UnitModel.ts @@ -1,16 +1,16 @@ -import { Unit } from '../@types/Entities'; +import { Unit as UnitType } from '../@types/Entities'; import { IUnitModel } from '../interfaces/IUnitModel'; -import unitSchema from '../database/schemas/unitSchema'; import Model from './Model'; +import { Unit } from '../database/models'; -class UnitModel extends Model implements IUnitModel { +class UnitModel extends Model implements IUnitModel { protected _populate = 'owner assets'; constructor() { - super('Unit', unitSchema); + super(Unit); } - async editAssetList(id: string, assetId: string, add: boolean): Promise { + async editAssetList(id: string, assetId: string, add: boolean): Promise { const edited = add ? await this._model.findByIdAndUpdate(id, { $push: { assets: assetId }, @@ -19,7 +19,7 @@ class UnitModel extends Model implements IUnitModel { $pull: { assets: assetId }, }, { new: true }); - return edited?.toObject() as Unit; + return edited?.toObject() as UnitType; } } diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts index 64a8165..818a0d2 100644 --- a/src/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -1,19 +1,19 @@ -import { User } from '../@types/Entities'; +import { User as UserType } from '../@types/Entities'; import { IUserModel } from '../interfaces/IUserModel'; -import userSchema from '../database/schemas/userSchema'; import Model from './Model'; +import { User } from '../database/models'; -class UserModel extends Model implements IUserModel { +class UserModel extends Model implements IUserModel { protected _populate = 'company'; constructor() { - super('User', userSchema); + super(User); } // Override for deleting the user password. - async createOne(user: User): Promise { + async createOne(user: UserType): Promise { const created = await (await this._model.create(user)).toObject(); delete created.password; - return created as User; + return created as UserType; } /** @@ -21,13 +21,13 @@ class UserModel extends Model implements IUserModel { * @param email The user's email. * @returns The user with the passed email. Null if no user found. */ - async findByEmail(email: string, login = false): Promise { + async findByEmail(email: string, login = false): Promise { const select = login ? '+password' : ''; const found = await this._model.findOne({ email }) .populate(this._populate) .select(select); - return found as User | null; + return found as UserType | null; } } From 114bb5393d019208da4e7ad5f80a5cc252fa7f72 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 01:02:27 -0300 Subject: [PATCH 8/9] refactor: removed seed method from generic Model it resets the Model's collection, a disaster waiting to happen --- src/models/Model.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/models/Model.ts b/src/models/Model.ts index 31325bc..b50f909 100644 --- a/src/models/Model.ts +++ b/src/models/Model.ts @@ -58,11 +58,6 @@ abstract class Model implements IModel { return deleted as T; } - - async seed(objects: T[], reset = true): Promise { - if (reset) await this._model.deleteMany(); - await this._model.insertMany(objects); - } } export default Model; From bf2fd32f028d697db62f003cce92f1d9a342e4c6 Mon Sep 17 00:00:00 2001 From: DanielErhardt Date: Mon, 19 Dec 2022 01:07:07 -0300 Subject: [PATCH 9/9] refactor: changed seeding method it now seeds directly through the mongoose static models --- src/database/seeders/index.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/database/seeders/index.ts b/src/database/seeders/index.ts index c0613e5..1da435e 100644 --- a/src/database/seeders/index.ts +++ b/src/database/seeders/index.ts @@ -1,34 +1,28 @@ /* eslint-disable no-console */ -import AssetModel from '../../models/AssetModel'; -import CompanyModel from '../../models/CompanyModel'; -import UnitModel from '../../models/UnitModel'; -import UserModel from '../../models/UserModel'; import assets from './Assets'; import companies from './Companies'; import units from './Units'; import users from './Users'; import { connect, disconnect, MONGO_URI_DEV } from '..'; +import { + Asset, Company, User, Unit, +} from '../models'; const seed = async (mongoURI = MONGO_URI_DEV) => { - const userModel = new UserModel(); - const companyModel = new CompanyModel(); - const assetModel = new AssetModel(); - const unitModel = new UnitModel(); - try { await connect(mongoURI); console.log('Seeding users collection.'); - await userModel.seed(users); + await User.insertMany(users); console.log('Seeding companies collection.'); - await companyModel.seed(companies); + await Company.insertMany(companies); console.log('Seeding assets collection.'); - await assetModel.seed(assets); + await Asset.insertMany(assets); console.log('Seeding units collection.'); - await unitModel.seed(units); + await Unit.insertMany(units); console.log('Database seeding completed successfully.'); await disconnect();