UNPKG

nexorm

Version:

A powerful TypeScript ORM with advanced features.

1,325 lines 67 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Model = exports.Nexorm = void 0; exports.AllowNull = AllowNull; exports.UUID = UUID; exports.Enum = Enum; exports.AutoIncrement = AutoIncrement; exports.Default = Default; exports.Required = Required; exports.Unique = Unique; exports.Index = Index; exports.PrimaryKey = PrimaryKey; exports.Comment = Comment; exports.Hash = Hash; exports.Encrypt = Encrypt; exports.Decrypt = Decrypt; exports.Reference = Reference; exports.Column = Column; exports.Force = Force; exports.Paranoid = Paranoid; exports.Timestamps = Timestamps; exports.Debug = Debug; exports.Provider = Provider; exports.Schema = Schema; require("reflect-metadata"); const sequelize_1 = require("sequelize"); const uuid_1 = require("uuid"); const node_crypto_1 = __importDefault(require("node:crypto")); const lodash_1 = __importDefault(require("lodash")); const fileInspector_1 = require("./fileInspector"); const errorHandler_1 = __importDefault(require("./errorHandler")); const cacheManager_1 = __importDefault(require("./util/cacheManager")); var schema = {}; var havePrimaryKey = false; var haveAutoIncrement = {}; var primaryKeyCount = {}; var isWarned = false; var hashFieldsArray = []; var encryptFieldsArray = []; var decryptFieldsArray = []; const export_1 = require("./functions/export"); const chalk_1 = __importDefault(require("chalk")); const errorParser_1 = require("./util/errorParser"); /** * @name AllowNull * @description This decorator is used to define a column in the database. * @example @AllowNull * @public * @returns {void} */ function AllowNull(target, key) { if (!Reflect.hasMetadata(`allowNull-${target.name}`, target)) { Reflect.defineMetadata(`allowNull-${target.name}`, [], target); } const allowNullFields = Reflect.getMetadata(`allowNull-${target.name}`, target); allowNullFields.push(key); Reflect.defineMetadata(`allowNull-${target.name}`, allowNullFields, target); } ; /** * @name UUID * @description This decorator is used to define a column in the database. * @example @UUID(4) * @public * @param v * @returns {Function} */ function UUID(v) { return function (target, key) { var selectedUUID = { key: 'v4' }; if (v instanceof Object) { if (v.v1) selectedUUID = { key: 'v1' }; if (v.v4) selectedUUID = { key: 'v4' }; if (v.v3) selectedUUID = { key: 'v3', namespace: v.v3.namespace, name: v.v3.name }; if (v.v5) selectedUUID = { key: 'v5', namespace: v.v5.namespace, name: v.v5.name }; if (v.v6) selectedUUID = { key: 'v6' }; if (v.v7) selectedUUID = { key: 'v7' }; } else { if (v == 1) selectedUUID = { key: 'v1' }; if (v == 4) selectedUUID = { key: 'v4' }; if (v == 6) selectedUUID = { key: 'v6' }; if (v == 7) selectedUUID = { key: 'v7' }; } ; var uuidVersionList = { v1: () => (0, uuid_1.v1)(), v3: (namespace, name) => (0, uuid_1.v3)(namespace, name), v4: () => (0, uuid_1.v4)(), v5: (namespace, name) => (0, uuid_1.v5)(namespace, name), v6: () => (0, uuid_1.v6)(), v7: () => (0, uuid_1.v7)(), }; if (!Reflect.hasMetadata(`defaults-${target.name}`, target)) { Reflect.defineMetadata(`defaults-${target.name}`, {}, target); } const defaults = Reflect.getMetadata(`defaults-${target.name}`, target); defaults[key] = uuidVersionList[selectedUUID.key](selectedUUID.namespace || 'nexorm', selectedUUID.name || 'nexorm'); Reflect.defineMetadata(`defaults-${target.name}`, defaults, target); }; } /** * @name Enum * @description This decorator is used to define a column in the database. * @example @Enum * @public * @param values * @returns {Function} */ function Enum(values) { return function (target, key) { if (!Reflect.hasMetadata(`enum-${target.name}`, target)) { Reflect.defineMetadata(`enum-${target.name}`, {}, target); } const enums = Reflect.getMetadata(`enum-${target.name}`, target); enums[key] = values; Reflect.defineMetadata(`enum-${target.name}`, enums, target); }; } ; /** * @name AutoIncrement * @description This decorator is used to define a column in the database. * @example @AutoIncrement * @public * @returns {void} */ function AutoIncrement(target, key) { if (!Reflect.hasMetadata(`autoIncrement-${target.name}`, target)) { Reflect.defineMetadata(`autoIncrement-${target.name}`, [], target); } ; if (!Reflect.hasMetadata(`primaryKey-${target.name}`, target)) { Reflect.defineMetadata(`primaryKey-${target.name}`, [], target); } ; if (!Reflect.hasMetadata(`defaults-${target.name}`, target)) { Reflect.defineMetadata(`defaults-${target.name}`, {}, target); } ; const autoIncrements = Reflect.getMetadata(`autoIncrement-${target.name}`, target); const primaryKey = Reflect.getMetadata(`primaryKey-${target.name}`, target); const defaults = Reflect.getMetadata(`defaults-${target.name}`, target); autoIncrements.push(key); primaryKey.push(key); defaults[key] = 0; Reflect.defineMetadata(`autoIncrement-${target.name}`, autoIncrements, target); } ; /** * @name Default * @description This decorator is used to define a column in the database. * @example @Default * @public * @param value * @returns {Function} */ function Default(value) { return function (target, key) { if (!Reflect.hasMetadata(`defaults-${target.name}`, target)) { Reflect.defineMetadata(`defaults-${target.name}`, {}, target); } const defaults = Reflect.getMetadata(`defaults-${target.name}`, target); defaults[key] = value; Reflect.defineMetadata(`defaults-${target.name}`, defaults, target); }; } ; /** * @name Required * @description This decorator is used to define a column in the database. * @example @Required * @public * @returns {void} */ function Required(target, key) { if (!Reflect.hasMetadata(`required-${target.name}`, target)) { Reflect.defineMetadata(`required-${target.name}`, [], target); } const requiredFields = Reflect.getMetadata(`required-${target.name}`, target); requiredFields.push(key); Reflect.defineMetadata(`required-${target.name}`, requiredFields, target); } ; /** * @name Unique * @description This decorator is used to define a column in the database. * @example @Unique * @public * @returns {void} */ function Unique(target, key) { if (!Reflect.hasMetadata(`unique-${target.name}`, target)) { Reflect.defineMetadata(`unique-${target.name}`, [], target); } const uniqueFields = Reflect.getMetadata(`unique-${target.name}`, target); uniqueFields.push(key); Reflect.defineMetadata(`unique-${target.name}`, uniqueFields, target); } ; /** * @name Index * @description This decorator is used to define a column in the database. * @example @Index * @public * @returns {void} */ function Index(target, key) { if (!Reflect.hasMetadata(`index-${target.name}`, target)) { Reflect.defineMetadata(`index-${target.name}`, [], target); } const indexFields = Reflect.getMetadata(`index-${target.name}`, target); indexFields.push(key); Reflect.defineMetadata(`index-${target.name}`, indexFields, target); } ; /** * @name PrimaryKey * @description This decorator is used to define a column in the database. * @example @PrimaryKey * @public * @returns {void} */ function PrimaryKey(target, key) { if (!Reflect.hasMetadata(`primaryKey-${target.name}`, target)) { Reflect.defineMetadata(`primaryKey-${target.name}`, [], target); } const primaryKeyFields = Reflect.getMetadata(`primaryKey-${target.name}`, target); primaryKeyFields.push(key); if (primaryKeyCount[target.name] == undefined) { primaryKeyCount[target.name] = 1; } else { primaryKeyCount[target.name]++; } ; Reflect.defineMetadata(`primaryKey-${target.name}`, primaryKeyFields, target); } ; /** * @name Comment * @description This decorator is used to define a column in the database. * @example @Comment * @public * @param comment * @returns {Function} */ function Comment(comment) { return function (target, key) { if (!Reflect.hasMetadata(`comments-${target.name}`, target)) { Reflect.defineMetadata(`comments-${target.name}`, {}, target); } const comments = Reflect.getMetadata(`comments-${target.name}`, target); comments[key] = comment; Reflect.defineMetadata(`comments-${target.name}`, comments, target); }; } ; /** * @name Hash * @description This decorator is used to define a column in the database. * @example @Hash * @public * @param method * @param digest * @returns {Function} */ function Hash(method, digest) { if (!method) { throw new Error('Method is required'); } ; if (!digest) digest = 'hex'; return function (target, key) { if (!Reflect.hasMetadata(`hash-${target.name}`, target)) { Reflect.defineMetadata(`hash-${target.name}`, {}, target); } const hash = Reflect.getMetadata(`hash-${target.name}`, target); hash[key] = { method, digest }; Reflect.defineMetadata(`hash-${target.name}`, hash, target); }; } ; /** * @name Encrypt * @description This decorator is used to define a column in the database. * @example @Encrypt * @public * @param method * @param cipherKey * @param iv * @returns {Function} * @throws {Error} */ function Encrypt(method, cipherKey, iv) { if (!method) { throw new Error('Method is required'); } ; if (!cipherKey) { throw new Error('Cipher Key is required'); } ; if (!iv) { throw new Error('IV is required'); } ; return function (target, key) { if (!Reflect.hasMetadata(`encrypt-${target.name}`, target)) { Reflect.defineMetadata(`encrypt-${target.name}`, {}, target); } ; const encrypt = Reflect.getMetadata(`encrypt-${target.name}`, target); encrypt[key] = { method, cipherKey, iv }; Reflect.defineMetadata(`encrypt-${target.name}`, encrypt, target); }; } ; /** * @name Decrypt * @description This decorator is used to define a column in the database. * @example @Decrypt * @public * @param method * @param cipherKey * @param iv * @returns {Function} * @throws {Error} */ function Decrypt(method, cipherKey, iv) { if (!method) { throw new Error('Method is required'); } ; if (!cipherKey) { throw new Error('Cipher Key is required'); } ; if (!iv) { throw new Error('IV is required'); } ; return function (target, key) { if (!Reflect.hasMetadata(`decrypt-${target.name}`, target)) { Reflect.defineMetadata(`decrypt-${target.name}`, {}, target); } ; const decrypt = Reflect.getMetadata(`decrypt-${target.name}`, target); decrypt[key] = { method, cipherKey, iv }; Reflect.defineMetadata(`decrypt-${target.name}`, decrypt, target); }; } ; /** * @name Reference * @description This decorator is used to define a column in the database. * @example @Reference * @public * @param value * @returns {Function} */ function Reference(value) { return function (target, key) { if (!Reflect.hasMetadata(`references-${target.name}`, target)) { Reflect.defineMetadata(`references-${target.name}`, {}, target); } const references = Reflect.getMetadata(`references-${target.name}`, target); references[key] = value; Reflect.defineMetadata(`references-${target.name}`, references, target); }; } ; function Column(target, key) { if (!Reflect.hasMetadata(`rows-${target.name}`, target)) { Reflect.defineMetadata(`rows-${target.name}`, [], target); } const rows = Reflect.getMetadata(`rows-${target.name}`, target); rows.push({ key, keyType: target[key] }); Reflect.defineMetadata(`rows-${target.name}`, rows, target); } ; function Force(target) { Reflect.defineMetadata(`force-${target.name}`, true, target); } ; function Paranoid(target) { Reflect.defineMetadata(`paranoid-${target.name}`, true, target); } ; function Timestamps(target) { Reflect.defineMetadata(`timestamps-${target.name}`, true, target); } ; function Debug(target) { Reflect.defineMetadata(`debug-${target.name}`, true, target); } ; function Provider(providerName) { return function (target) { Reflect.defineMetadata(`databaseName-${target.name}`, providerName, target); }; } ; function Schema(target) { if (!target) throw new errorHandler_1.default('Schema Not Found', '#FF0000'); const rows = Reflect.getMetadata(`rows-${target.name}`, target) || []; for (var row of rows) { var key = row.key; var type = row.keyType; var defaultValue = Reflect.getMetadata(`defaults-${target.name}`, target) || null; var requiredFields = Reflect.getMetadata(`required-${target.name}`, target) || []; var autoIncrementFields = Reflect.getMetadata(`autoIncrement-${target.name}`, target) || []; var uniqueFields = Reflect.getMetadata(`unique-${target.name}`, target) || []; var indexFields = Reflect.getMetadata(`index-${target.name}`, target) || []; var primaryKeyFields = Reflect.getMetadata(`primaryKey-${target.name}`, target) || []; var allowNullFields = Reflect.getMetadata(`allowNull-${target.name}`, target) || []; var onUpdateFields = Reflect.getMetadata(`onUpdate-${target.name}`, target) || []; var onDeleteFields = Reflect.getMetadata(`onDelete-${target.name}`, target) || []; var comments = Reflect.getMetadata(`comments-${target.name}`, target) || []; var hashFields = Reflect.getMetadata(`hash-${target.name}`, target) || []; var encryptFields = Reflect.getMetadata(`encrypt-${target.name}`, target) || []; var decryptFields = Reflect.getMetadata(`decrypt-${target.name}`, target) || []; var references = Reflect.getMetadata(`references-${target.name}`, target) || []; var enums = Reflect.getMetadata(`enum-${target.name}`, target) || []; var isRequired = requiredFields.includes(key); var isAutoIncrement = autoIncrementFields.includes(key); var isUnique = uniqueFields.includes(key); var isIndex = indexFields.includes(key); var isPrimaryKey = primaryKeyFields.includes(key); var isAllowNull = allowNullFields.includes(key); var onUpdate = onUpdateFields[key]; var onDelete = onDeleteFields[key]; var comment = comments[key]; var hash = hashFields[key]; var encrypt = encryptFields[key]; var decrypt = decryptFields[key]; var reference = references[key]; var enumValues = enums[key]; if (isPrimaryKey) havePrimaryKey = true; if (hash) hashFieldsArray.push({ key, hash }); if (encrypt) encryptFieldsArray.push({ key, method: encrypt.method, cipher: encrypt.cipherKey, iv: encrypt.iv }); if (decrypt) decryptFieldsArray.push({ key, method: decrypt.method, cipher: decrypt.cipherKey, iv: decrypt.iv }); var objectSchema = { type: type, index: isIndex, allowNull: isAllowNull || false, defaultValue: defaultValue?.hasOwnProperty(key) ? defaultValue[key] : null, primaryKey: isPrimaryKey, autoIncrement: isAutoIncrement, unique: isUnique, onUpdate: onUpdate, onDelete: onDelete, comment: comment, hash: hash, encrypt: encrypt, decrypt: decrypt, references: reference, enum: enumValues, }; schema[key] = objectSchema; } ; var providerName = Reflect.getMetadata(`provider-${target.name}`, target) || "nexorm"; var newSchema = convertSchema(schema, providerName, target.name); schema = newSchema; Reflect.defineMetadata(`schema-${target.name}`, newSchema, target); schema = {}; } ; async function createTable(model, timestamps, force, paranoid, schema, dataName, debug) { return await new Promise(async (resolve, reject) => { var sequelize = fileInspector_1.sequelizes.find(x => x.name == dataName)?.sequelize; if (fileInspector_1.connections.length == 0) throw new errorHandler_1.default('Connection not found, Check nexorm.config file.', '#FF0000'); if (fileInspector_1.connections.some((item) => item == dataName) == false) return; if (!sequelize) throw new errorHandler_1.default('Provider not found, Check nexorm.config file.', '#FF0000'); if (!timestamps) timestamps = false; if (!force) force = false; if (!paranoid) paranoid = false; var schemaIndexes = Object.keys(schema).filter(x => schema[x]?.index == true); class ModelSchema extends sequelize_1.Model { } ; ModelSchema.init(schema, { freezeTableName: true, sequelize: sequelize, timestamps: timestamps, modelName: model, tableName: model, comment: model, paranoid: paranoid, }); if (hashFieldsArray.length > 0) { hashFieldsArray.forEach((field) => { ModelSchema.addHook('beforeSave', async (instance) => { if (lodash_1.default.isArray(instance)) { instance.forEach((item) => { var value = item?.getDataValue(field.key); if (!value) return; if (value) { var hash = node_crypto_1.default.createHash(field.hash.method).update(value).digest(field.hash.digest); item.setDataValue(field.key, hash); } ; }); } else { var value = instance?.getDataValue(field.key); if (!value) return; if (value) { var hash = node_crypto_1.default.createHash(field.hash.method).update(value).digest(field.hash.digest); instance.setDataValue(field.key, hash); } ; } }); }); } ; if (encryptFieldsArray.length > 0) { encryptFieldsArray.forEach((field) => { ModelSchema.addHook('beforeSave', async (instance) => { if (lodash_1.default.isArray(instance)) { instance.forEach((item) => { var value = item?.getDataValue(field.key); if (!value) return; if (value) { var cipher = node_crypto_1.default.createCipheriv(field.method, Buffer.from(field.cipher, 'utf8'), Buffer.from(field.iv, 'utf8')); var encrypt = cipher.update(value, 'utf8', 'hex'); encrypt += cipher.final('hex'); item.setDataValue(field.key, encrypt); } ; }); } else { var value = instance?.getDataValue(field.key); if (!value) return; if (value) { var cipher = node_crypto_1.default.createCipheriv(field.method, Buffer.from(field.cipher, 'utf8'), Buffer.from(field.iv, 'utf8')); var encrypt = cipher.update(value, 'utf8', 'hex'); encrypt += cipher.final('hex'); instance.setDataValue(field.key, encrypt); } ; } }); }); } ; if (decryptFieldsArray.length > 0) { decryptFieldsArray.forEach((field) => { ModelSchema.addHook('afterFind', async (instance, options) => { if (lodash_1.default.isArray(instance)) { instance.forEach((item) => { var value = item?.getDataValue(field.key); if (!value) return; if (value) { var cipher = node_crypto_1.default.createDecipheriv(field.method, Buffer.from(field.cipher), Buffer.from(field.iv)); var decrypted = cipher.update(value, 'hex', 'utf8'); decrypted += cipher.final('utf8'); item.setDataValue(field.key, decrypted); } ; }); } else { var value = instance?.getDataValue(field.key); if (!value) return; if (value) { var cipher = node_crypto_1.default.createDecipheriv(field.method, Buffer.from(field.cipher), Buffer.from(field.iv)); var decrypted = cipher.update(value, 'hex', 'utf8'); decrypted += cipher.final('utf8'); instance.setDataValue(field.key, decrypted); } ; } ; }); }); } ; /* * Sync the model schema with the database. * This will create the table if it doesn't exist, and update it if it does. */ try { await ModelSchema.sync({ alter: !force, force: force }); if (debug) debugLog(`Model '${model}' created successfully`); } catch (error) { console.log(error); throw (0, errorParser_1.errorParser)(error); } ; var queryInterface = sequelize.getQueryInterface(); await queryInterface.describeTable(model).then(async (table) => { var tableFields = Object.keys(table); var schemaFields = Object.keys(schema); var attributesFields = Object.keys(ModelSchema.getAttributes()); var indexes = await queryInterface.showIndex(model); await Promise.all(schemaIndexes.map(async (field) => { var indexExists = indexes.some((index) => index.name == `${model}_${field}_index`); if (!indexExists) { await queryInterface.addIndex(model, [field], { name: `${model}_${field}_index`, unique: schema[field]?.unique || false, using: schema[field]?.index || 'BTREE', }); } ; })); await Promise.all(schemaFields.filter(x => !tableFields.includes(x)).map(async (field) => { await queryInterface.addColumn(model, field, schema[field]); })); }); resolve(ModelSchema); }).catch((error) => { throw new errorHandler_1.default(error, '#FF0000'); }); } ; function convertSchema(schema, dataName, modelName) { var newSchema = {}; var dbType = (0, fileInspector_1.readConfig)().find(x => x.$provider == dataName)?.$database; if (!dbType) throw new errorHandler_1.default(`Provider '${dataName}' not found, Check nexorm.config file or @Provider decorator in '${modelName}' class.`, '#FF0000'); const typeMappings = { mysql: { string: sequelize_1.DataTypes.TEXT, number: sequelize_1.DataTypes.FLOAT, boolean: sequelize_1.DataTypes.BOOLEAN, date: sequelize_1.DataTypes.DATE, array: sequelize_1.DataTypes.TEXT, object: sequelize_1.DataTypes.TEXT, integer: sequelize_1.DataTypes.INTEGER, buffer: sequelize_1.DataTypes.BLOB('long') }, postgres: { string: sequelize_1.DataTypes.TEXT, number: sequelize_1.DataTypes.FLOAT, boolean: sequelize_1.DataTypes.BOOLEAN, date: sequelize_1.DataTypes.DATE, array: sequelize_1.DataTypes.JSON, object: sequelize_1.DataTypes.JSON, integer: sequelize_1.DataTypes.INTEGER, buffer: sequelize_1.DataTypes.BLOB('long') }, sqlite: { string: sequelize_1.DataTypes.STRING, number: sequelize_1.DataTypes.NUMBER, boolean: sequelize_1.DataTypes.BOOLEAN, date: sequelize_1.DataTypes.DATE, array: sequelize_1.DataTypes.JSON, object: sequelize_1.DataTypes.JSON, integer: sequelize_1.DataTypes.INTEGER, buffer: sequelize_1.DataTypes.BLOB('long') }, mariadb: { string: sequelize_1.DataTypes.TEXT, number: sequelize_1.DataTypes.FLOAT, boolean: sequelize_1.DataTypes.BOOLEAN, date: sequelize_1.DataTypes.DATE, array: sequelize_1.DataTypes.JSON, object: sequelize_1.DataTypes.JSON, integer: sequelize_1.DataTypes.INTEGER, buffer: sequelize_1.DataTypes.BLOB('long') }, mssql: { string: sequelize_1.DataTypes.TEXT, number: sequelize_1.DataTypes.FLOAT, boolean: sequelize_1.DataTypes.BOOLEAN, date: sequelize_1.DataTypes.DATE, array: sequelize_1.DataTypes.JSON, object: sequelize_1.DataTypes.JSON, integer: sequelize_1.DataTypes.INTEGER, buffer: sequelize_1.DataTypes.BLOB('long') }, }; var schemaKeys = Object.keys(schema); if (schemaKeys.length == 0) throw new errorHandler_1.default('Schema Not Found', '#FF0000'); schemaKeys?.forEach((key, index) => { var dbType = (0, fileInspector_1.readConfig)().find(x => x.$provider == dataName)?.$database; if (!dbType) throw new errorHandler_1.default('Database not found, Check nexorm.config file.', '#FF0000'); var schemaValue = schema[key]?.type; var defaultValue = schema[key]?.defaultValue; if (schemaValue == undefined || !["String", "Number", "Boolean", "Array", "Object", "Date", "BigInt", "Buffer"].some((query) => String(schemaValue).includes(query))) throw new errorHandler_1.default('Invalid Type Or Type Not Found, Use For Example: \'static username = String\'', '#FF0000'); var requiredValue = schema[key]?.required; if (index == 0) { newSchema["nexorm_id"] = { type: sequelize_1.DataTypes.TEXT, allowNull: false, defaultValue: node_crypto_1.default.randomUUID(), primaryKey: havePrimaryKey ? false : true, unique: false, comment: 'Nexorm ID', }; } ; if (!newSchema[key]) newSchema[key] = {}; if (String(schemaValue).includes("Array") || lodash_1.default.isArray(schemaValue)) { newSchema[key].type = typeMappings[dbType]?.array; } else if (String(schemaValue).includes("String")) { newSchema[key].type = typeMappings[dbType]?.string; } else if (String(schemaValue).includes("Number")) { if (schema[key]?.autoIncrement) { newSchema[key].type = typeMappings[dbType]?.integer; newSchema[key].autoIncrement = true; newSchema[key].primaryKey = true; } else { newSchema[key].type = typeMappings[dbType]?.number; } } else if (String(schemaValue).includes("Boolean")) { newSchema[key].type = typeMappings[dbType]?.boolean; } else if (String(schemaValue).includes("Object")) { newSchema[key].type = typeMappings[dbType]?.object; } else if (String(schemaValue).includes("Date")) { newSchema[key].type = typeMappings[dbType]?.date; } else if (String(schemaValue).includes("BigInt")) { newSchema[key].type = typeMappings[dbType]?.integer; newSchema[key].validate = { isInt: true }; } else if (String(schemaValue).includes("Buffer")) { newSchema[key].type = typeMappings[dbType]?.buffer; } ; if (defaultValue == null && requiredValue == true && !schema[key]?.autoIncrement) { if (String(schemaValue).includes("Object")) { schema[key].defaultValue = {}; } else if (String(schemaValue).includes("Array") || lodash_1.default.isArray(schemaValue)) { schema[key].defaultValue = []; } else if (String(schemaValue).includes("String")) { schema[key].defaultValue = ''; } else if (String(schemaValue).includes("Number")) { schema[key].defaultValue = 0; } else if (String(schemaValue).includes("Boolean")) { schema[key].defaultValue = dbType == 'sqlite' ? 0 : false; } else if (String(schemaValue).includes("Date")) { schema[key].defaultValue = new Date(); } if (String(schemaValue).includes("BigInt")) { schema[key].defaultValue = 0; } } ; if (schema[key]?.autoIncrement && !String(schemaValue).includes("Number") && !String(schemaValue).includes('BigInt')) throw new errorHandler_1.default('@AutoIncrement Can Only Be Used With Number Or Integer Type', '#FF0000'); if (schema[key]?.hash && !String(schemaValue).includes("String")) throw new errorHandler_1.default('@Hash Can Only Be Used With String Type', '#FF0000'); if (schema[key]?.encrypt && !String(schemaValue).includes("String")) throw new errorHandler_1.default('@Encrypt Can Only Be Used With String Type', '#FF0000'); if (schema[key]?.decrypt && !String(schemaValue).includes("String")) throw new errorHandler_1.default('@Decrypt Can Only Be Used With String Type', '#FF0000'); if (primaryKeyCount[modelName] > 1 && haveAutoIncrement[modelName]) throw new errorHandler_1.default('Multiple @PrimaryKey Not Supported With @AutoIncrement', '#FF0000'); if (!haveAutoIncrement[modelName] && schema[key]?.autoIncrement) haveAutoIncrement[modelName] = true; if (!schema[key]?.autoIncrement) newSchema[key].index = schema[key]?.index || false; if (!schema[key]?.autoIncrement) newSchema[key].allowNull = requiredValue ? false : true; if (!schema[key]?.autoIncrement) newSchema[key].defaultValue = schema[key]?.defaultValue; newSchema[key].primaryKey = schema[key]?.primaryKey || false; newSchema[key].autoIncrement = schema[key]?.autoIncrement || false; if (!schema[key]?.autoIncrement) newSchema[key].unique = schema[key]?.unique || false; if (!schema[key]?.autoIncrement) newSchema[key].onUpdate = schema[key]?.onUpdate || null; if (!schema[key]?.autoIncrement) newSchema[key].onDelete = schema[key]?.onDelete || null; if (!schema[key]?.autoIncrement) newSchema[key].comment = schema[key]?.comment || null; if (!schema[key]?.autoIncrement && schema[key]?.enum?.length > 0) newSchema[key].validate = { ...newSchema[key].validate, isIn: [schema[key]?.enum] }; if (schema[key]?.primaryKey) { newSchema[key].allowNull = false; newSchema[key].unique = true; } ; if (schema[key]?.unique) { delete newSchema[key].defaultValue; newSchema[key].unique = true; } ; }); return newSchema; } ; ; ; ; ; ; ; ; /* type IncludeOption = { $model: any; $as?: string; $attributes?: string[] | { $exclude?: string[]; $include?: string[] }; }[]; */ /** * Nexorm * @description Nexorm Main Class * @class Nexorm * @public * @async * @type {Class} * @example import Nexorm from 'nexorm'; * @returns {Class} */ class Nexorm { /** * Nexorm Config * @type {NexormConfig} * @public * @static * @example Nexorm.$config */ static $configs = (0, fileInspector_1.readConfig)(); /** * Nexorm Providers * @type {string[]} * @public * @static * @example Nexorm.$providers */ static $providers = fileInspector_1.sequelizes.map(x => x.name); /** * Nexorm Connections * @type {Object} * @public * @static * @example Nexorm.$connections.$size * @example Nexorm.$connections.$list * @returns {Object} * @description Get All Connections * @example Nexorm.$connections */ static $connections = { $size: fileInspector_1.connections.length, $list: fileInspector_1.connections }; /** * Connect To Database * @param providerName Provider Name * @returns Promise<void> * @example await Nexorm.$connect('nexorm') */ static async $connect(providerName) { if (!providerName) providerName = 'nexorm'; if (fileInspector_1.connections.find(x => x == providerName)) { throw new errorHandler_1.default('Connection Already Exists, Try Again by Trying Other Providers Or You\'re Already Connected', '#FF0000'); } ; await (0, fileInspector_1.autoConnect)(providerName); } ; /** * Disconnect From Database * @param providerName Provider Name * @returns Promise<void> * @example await Nexorm.$disconnect('nexorm') */ static async $disconnect(providerName) { if (!providerName) providerName = 'nexorm'; if (!fileInspector_1.connections.find(x => x == providerName)) { throw new errorHandler_1.default('Connection Not Found, Try Again by Trying Other Providers Or You\'re Already Disconnected', '#FF0000'); } ; await (0, fileInspector_1.closeConnection)(providerName); } ; /** * Drop Database * @param providerName Provider Name * @returns Promise<void> * @example await Nexorm.$drop('nexorm') */ static async $drop(providerName) { if (!providerName) providerName = 'nexorm'; if (!fileInspector_1.connections.find(x => x == providerName)) { throw new errorHandler_1.default('Connection Not Found, Try Again by Trying Other Providers Or You\'re Already Disconnected', '#FF0000'); } ; await (0, fileInspector_1.dropProvider)(providerName); } ; /** * Close All Connections * @returns Promise<void> * @example await Nexorm.$closeAllConnections() * @description Close All Connections */ static async $closeAllConnections() { for (var i = 0; i < fileInspector_1.connections.length; i++) { await (0, fileInspector_1.closeConnection)(fileInspector_1.connections[i]); } ; } ; /** * Connect All Providers * @returns Promise<void> * @example await Nexorm.$connectAll() * @description Connect All Providers */ static async $connectAll() { var notConnected = Nexorm.$providers.filter(x => !fileInspector_1.connections.find(y => y == x)); for (var i = 0; i < notConnected.length; i++) { await (0, fileInspector_1.autoConnect)(notConnected[i]); } ; } ; } exports.Nexorm = Nexorm; ; class Model { Schema; $type; $model; $middlewares = []; $cache = new cacheManager_1.default(); $config; $debugMode = false; schema; model; constructor(Schema) { this.Schema = Schema; this.schema = Schema; this.$middlewares = []; this.$config = (0, fileInspector_1.readConfig)()?.find(x => x.$provider == databaseName); if (!String(Schema).includes("class")) throw new errorHandler_1.default('Schema Must Be A Static Class', '#FF0000'); var databaseName = Reflect.getMetadata(`databaseName-${this.schema.name}`, this.schema) || "nexorm"; if (!databaseName) throw new errorHandler_1.default('Database Not Found, Check nexorm.config file.', '#FF0000'); if (!fileInspector_1.connections.find(x => x == databaseName)) return; var schema = Reflect.getMetadata(`schema-${this.schema.name}`, this.schema) || {}; var timestamps = Reflect.getMetadata(`timestamps-${this.schema.name}`, this.schema) || false; var force = Reflect.getMetadata(`force-${this.schema.name}`, this.schema) || false; var paranoid = Reflect.getMetadata(`paranoid-${this.schema.name}`, this.schema) || false; var debug = Reflect.getMetadata(`debug-${this.schema.name}`, this.schema) || false; this.$debugMode = debug; this.model = createTable(this.schema.name, timestamps, force, paranoid, schema, databaseName, debug).then((model) => { if (this.$debugMode) debugLog(`Table Created & Synced: ${this.schema.name}`); return model; }).catch((err) => { throw (0, errorParser_1.errorParser)(err); }); this.$model = fileInspector_1.sequelizes.find((x) => x.name == databaseName)?.sequelize.models[this.schema?.name]; } ; /** * Search * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$search({ $where: { name: 'John' } }) * @async * @public * @type {Function} */ async $search(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return (execute.search(query?.$where, query?.$options) || []); } ; /** * Search First * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$searchFirst() * @async * @public * @type {Function} */ async $searchFirst() { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching First Data: ${this.schema.name}`); return execute.searchOne({}, {}); } ; /** * Search One * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$searchOne({ $where: { name: 'John' } }) * @async * @public * @type {Function} */ async $searchOne(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching One Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.searchOne(query?.$where, query?.$options); } ; /** * Search By Id * @param nexorm_id Nexorm ID * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$searchById('1') * @async * @public * @type {Function} */ async $searchById(nexorm_id) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching By ID: ${this.schema.name} - $where: { nexorm_id: ${nexorm_id} }`); return execute.searchOne({ nexorm_id }); } ; /** * Search By Ids * @param ids Nexorm IDs * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$searchByIds(['1','2','3']) * @async * @public * @type {Function} */ async $searchByIds(ids) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching By IDs: ${this.schema.name} - $where: { nexorm_id: { $in: ${ids} } }`); return execute.search({ nexorm_id: { $in: ids } }); } ; /** * Search And Count * @param query Query * @param query.$where Where * @returns Promise<[StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>>[], number]> * @example model.$searchAndCount({ $where: { name: 'John' } }) * @async * @public * @type {Function} */ async $searchAndCount(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching And Counting Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)}`); var counts = await execute.count(query?.$where, {}); var data = await execute.search(query?.$where, {}); return [data, counts]; } ; /** * Create * @param data Data * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$create({ name: 'John' }) * @async * @public * @type {Function} */ async $everything() { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Searching Everything: ${this.schema.name}`); return execute.search({}, {}); } ; /** * Build * @param data Data * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$build({ name: 'John' }) * @async * @public * @type {Function} */ async $build(data) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Building Data: ${this.schema.name} - Data: ${JSON.stringify(data)}`); return execute.build(data); } ; /** * Build Many * @param data Data * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$buildMany([{ name: 'John' }, { name: 'Doe' }]) * @async * @public * @type {Function} */ async $buildMany(data) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Building Many Data: ${this.schema.name} - Data: ${JSON.stringify(data)}`); return execute.buildMany(data); } ; /** * Update * @param query Query * @param query.$where Where * @param query.$update Update * @param query.$rules Rules * @param query.$options Options * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$update({ $where: { name: 'John' }, $update: { $set: { name: 'Five' } } }) * @async * @public * @type {Function} */ async $update(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Updating Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $update: ${JSON.stringify(query?.$update)} - $options: ${JSON.stringify(query?.$options)} - $rules: ${JSON.stringify(query?.$rules)}`); if (query && !query.$options) query.$options = {}; return execute.update(query?.$where, query?.$update, query?.$rules, query?.$options); } ; /** * Update Many * @param query Query * @param query.$where Where * @param query.$update Update * @param query.$rules Rules * @param query.$options Options * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$updateMany({ $where: { name: 'John' }, $update: { $set: { name: 'Five' } } }) * @async * @public * @type {Function} */ async $updateMany(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Updating Many Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $update: ${JSON.stringify(query?.$update)} - $options: ${JSON.stringify(query?.$options)} - $rules: ${JSON.stringify(query?.$rules)}`); return execute.update(query?.$where, query?.$update, query?.$rules, { $multi: true, ...query?.$options }); } ; /** * Delete * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<boolean> * @example model.$delete({ $where: { name: 'John' } }) * @async * @public * @type {Function} * @returns {Promise<boolean>} */ async $delete(query) { if (typeof query?.$options?.$force == 'boolean') query.$options.$force = true; var execute = await this.#execute(); if (this.$debugMode) debugLog(`Deleting Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.delete(query?.$where, query?.$options, false); } ; /** * Delete Many * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<number> * @example model.$deleteMany({ $where: { name: 'John' } }) * @async * @public * @type {Function} * @returns {Promise<number>} */ async $deleteMany(query) { if (typeof query?.$options?.$force == 'boolean') query.$options.$force = true; var execute = await this.#execute(); if (this.$debugMode) debugLog(`Deleting Many Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.delete(query?.$where, query?.$options, true); } ; /** * Soft Delete * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<boolen> * @example model.$softDelete({ $where: { name: 'John' } }) * @async * @public * @type {Function} * @returns {Promise<boolean>} */ async $softDelete(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Soft Deleting Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.delete(query?.$where, { $force: false, ...query?.$options }, false); } ; /** * Soft Delete Many * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<boolean> * @example model.$softDeleteMany({ $where: { name: 'John' } }) * @async * @public * @type {Function} * @returns {Promise<boolean>} */ async $softDeleteMany(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Soft Deleting Many Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.delete(query?.$where, { $force: false, ...query?.$options }, true); } ; /** * Restore * @param query Query * @param query.$where Where * @param query.$options Options * @returns Promise<void> * @example model.$restore({ $where: { name: 'John' } }) * @async * @public * @type {Function} * @returns {Promise<void>} */ async $restore(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Restoring Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.restore(query?.$where, query?.$options); } async $count(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Counting Data: ${this.schema.name} - $where: ${JSON.stringify(query?.$where)} - $options: ${JSON.stringify(query?.$options)}`); return execute.count(query?.$where); } ; /** * Upsert * @param query Query * @param query.$where Where * @param query.$update Update * @param query.$rules Rules * @param query.$options Options * @returns Promise<StaticProps<ExtendType<SchemaProps,{nexorm_id:string}>> * @example model.$upsert({ $where: { name: 'John' }, $update: { $set: { name: 'Five' } } }) * @async * @public * @type {Function} */ async $upsert(query) { var execute = await this.#execute(); if (this.$debugMode) debugLog(`Upsertin