accel-record-core
Advanced tools
Comparing version 1.11.0 to 1.12.0
import { Model } from "../index.js"; | ||
import { Association as Info } from "../fields"; | ||
import { Association as Info } from "../model/association.js"; | ||
export declare class Association<O extends Model, T extends Model> { | ||
@@ -4,0 +4,0 @@ protected owner: O; |
@@ -7,2 +7,6 @@ import { Models } from "../index.js"; | ||
import { HasOneAssociation } from "./hasOneAssociation.js"; | ||
const isHasOneOrBelongsTo = (association) => { | ||
return (association instanceof HasOneAssociation || | ||
association instanceof BelongsToAssociation); | ||
}; | ||
export class ModelInstanceBuilder { | ||
@@ -32,30 +36,13 @@ static build(klass, input) { | ||
return new Proxy(instance, { | ||
get(target, prop, receiver) { | ||
get: (target, prop, receiver) => { | ||
const column = klass.attributeToColumn(prop); | ||
if (typeof column === "string") { | ||
if (typeof column === "string") | ||
return target[column]; | ||
} | ||
const association = target.associations.get(prop); | ||
if (association instanceof HasOneAssociation || | ||
association instanceof BelongsToAssociation) { | ||
if (isHasOneOrBelongsTo(association)) | ||
return association.reader(); | ||
} | ||
return Reflect.get(target, prop, receiver); | ||
}, | ||
set(target, prop, value, receiver) { | ||
const column = klass.attributeToColumn(prop); | ||
if (typeof column === "string") { | ||
target[column] = value; | ||
return true; | ||
} | ||
const association = target.associations.get(prop); | ||
if (association instanceof HasOneAssociation || | ||
association instanceof BelongsToAssociation) { | ||
association.setter(value); | ||
} | ||
if (target[prop] instanceof Collection && Array.isArray(value)) { | ||
target[prop].replace(value); | ||
return true; | ||
} | ||
target[prop] = value; | ||
set(target, prop, value, _receiver) { | ||
updateTarget(klass, target, prop, value); | ||
return true; | ||
@@ -84,1 +71,16 @@ }, | ||
} | ||
const updateTarget = (klass, target, prop, value) => { | ||
const column = klass.attributeToColumn(prop); | ||
if (typeof column === "string") { | ||
target[column] = value; | ||
return; | ||
} | ||
const association = target.associations.get(prop); | ||
if (isHasOneOrBelongsTo(association)) | ||
association.setter(value); | ||
if (target[prop] instanceof Collection && Array.isArray(value)) { | ||
target[prop].replace(value); | ||
return; | ||
} | ||
target[prop] = value; | ||
}; |
@@ -25,4 +25,4 @@ declare const callbackMethods: readonly ["validation", "create", "save", "update", "destroy"]; | ||
callbacks: { | ||
before: Record<"create" | "update" | "save" | "destroy" | "validation", Function[]>; | ||
after: Record<"create" | "update" | "save" | "destroy" | "validation", Function[]>; | ||
before: Record<"create" | "update" | "save" | "destroy" | "validation", (() => any)[]>; | ||
after: Record<"create" | "update" | "save" | "destroy" | "validation", (() => any)[]>; | ||
}; | ||
@@ -29,0 +29,0 @@ /** |
@@ -104,2 +104,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
_queryCount++; | ||
return formatByEngine(ret); | ||
}; | ||
const formatByEngine = (ret) => { | ||
if (_config.type == "pg") { | ||
@@ -106,0 +109,0 @@ if (ret.command == "SELECT" || ret.rows.length > 0) { |
@@ -1,120 +0,5 @@ | ||
import { DMMF } from "prisma/prisma-client/runtime/library.js"; | ||
import { Model } from "./index.js"; | ||
/** | ||
* Represents an association between two models. | ||
*/ | ||
export declare class Association { | ||
klass: string; | ||
foreignKey: string; | ||
primaryKey: string; | ||
field: Field; | ||
isBelongsTo: boolean; | ||
through: string | undefined; | ||
/** | ||
* Creates a new Association instance. | ||
* @param relation - The DMMF.Field object representing the relation. | ||
* @param association - The Field object representing the association. | ||
* @param primaryKeys - An array of primary key column names. | ||
* @param foreignKeyColumns - An array of foreign key column names. | ||
* @param primaryKeyColumns - An array of primary key column names. | ||
*/ | ||
constructor(relation: DMMF.Field, association: Field, primaryKeys: readonly string[], foreignKeyColumns: string[], primaryKeyColumns: string[]); | ||
/** | ||
* Gets the model associated with this association. | ||
*/ | ||
get model(): typeof Model; | ||
/** | ||
* Checks if the association represents a has-one relation. | ||
*/ | ||
get isHasOne(): boolean; | ||
/** | ||
* Gets the join key for the Implicit Many-to-Many association. | ||
*/ | ||
get joinKey(): "A" | "B"; | ||
} | ||
/** | ||
* Represents a field in a database table. | ||
*/ | ||
export declare class Field { | ||
/** | ||
* The name of the field. | ||
*/ | ||
name: string; | ||
/** | ||
* The name of the field in the database. | ||
*/ | ||
dbName: string; | ||
/** | ||
* The type of the field. | ||
*/ | ||
type: string; | ||
/** | ||
* The name of the related field in a relation, or null if not applicable. | ||
*/ | ||
relationName: string | null; | ||
/** | ||
* Indicates whether the field is a list. | ||
*/ | ||
isList: boolean; | ||
/** | ||
* Indicates whether the field is required. | ||
*/ | ||
isRequired: boolean; | ||
/** | ||
* The kind of the field. | ||
*/ | ||
kind: "scalar" | "object" | "enum" | "unsupported"; | ||
/** | ||
* Indicates whether the field is an updated timestamp. | ||
*/ | ||
isUpdatedAt: boolean; | ||
/** | ||
* The default value of the field. | ||
*/ | ||
default: any; | ||
/** | ||
* The foreign keys associated with the field. | ||
*/ | ||
foreignKeys: string[]; | ||
/** | ||
* The primary keys associated with the field. | ||
*/ | ||
primaryKeys: string[]; | ||
/** | ||
* Constructs a new Field instance. | ||
* @param field - The DMMF.Field object representing the field. | ||
*/ | ||
constructor(field: DMMF.Field); | ||
/** | ||
* Checks if the default is "now" function. | ||
* @returns True if the default value is "now", false otherwise. | ||
*/ | ||
get defaultIsNow(): boolean; | ||
/** | ||
* Checks if the default is "uuid" function. | ||
* @returns True if the default value is "uuid", false otherwise. | ||
*/ | ||
get defaultIsUuid(): boolean; | ||
/** | ||
* Checks if the default is "cuid" function. | ||
* @returns True if the default value is "cuid", false otherwise. | ||
*/ | ||
get defaultIsCuid(): boolean; | ||
/** | ||
* Gets the scalar default value. | ||
* @returns The scalar default value, or undefined if not applicable. | ||
*/ | ||
get scalarDefault(): any; | ||
/** | ||
* Gets the initial value for the field. | ||
* @returns The initial value for the field. | ||
*/ | ||
getInitialValue(): any; | ||
/** | ||
* Casts a value to the appropriate type based on the field's type. | ||
* @param value - The value to cast. | ||
* @returns The casted value. | ||
*/ | ||
cast(value: any): any; | ||
} | ||
import { BaseDMMF } from "prisma/prisma-client/runtime/library.js"; | ||
import { Association } from "./model/association.js"; | ||
import { Field } from "./model/field.js"; | ||
export declare let dmmf: BaseDMMF; | ||
export declare const loadDmmf: () => Promise<void>; | ||
@@ -121,0 +6,0 @@ /** |
@@ -10,156 +10,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
import { createId as cuid } from "@paralleldrive/cuid2"; | ||
import { Models } from "./index.js"; | ||
/** | ||
* Represents an association between two models. | ||
*/ | ||
export class Association { | ||
/** | ||
* Creates a new Association instance. | ||
* @param relation - The DMMF.Field object representing the relation. | ||
* @param association - The Field object representing the association. | ||
* @param primaryKeys - An array of primary key column names. | ||
* @param foreignKeyColumns - An array of foreign key column names. | ||
* @param primaryKeyColumns - An array of primary key column names. | ||
*/ | ||
constructor(relation, association, primaryKeys, foreignKeyColumns, primaryKeyColumns) { | ||
var _a, _b, _c, _d; | ||
this.klass = association.type; | ||
this.foreignKey = (_a = foreignKeyColumns[0]) !== null && _a !== void 0 ? _a : ""; | ||
this.primaryKey = (_b = primaryKeyColumns[0]) !== null && _b !== void 0 ? _b : ""; | ||
this.field = association; | ||
if (this.foreignKey == "" && this.primaryKey == "") { | ||
// Implicit many-to-many relations | ||
this.isBelongsTo = false; | ||
this.foreignKey = relation.type < association.type ? "A" : "B"; | ||
this.primaryKey = primaryKeys[0]; | ||
this.through = `_${association.relationName}`; | ||
} | ||
else { | ||
this.isBelongsTo = ((_d = (_c = relation.relationToFields) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) == 0; | ||
} | ||
} | ||
/** | ||
* Gets the model associated with this association. | ||
*/ | ||
get model() { | ||
return Models[this.klass]; | ||
} | ||
/** | ||
* Checks if the association represents a has-one relation. | ||
*/ | ||
get isHasOne() { | ||
return !this.field.isList && !this.isBelongsTo; | ||
} | ||
/** | ||
* Gets the join key for the Implicit Many-to-Many association. | ||
*/ | ||
get joinKey() { | ||
return this.foreignKey == "A" ? "B" : "A"; | ||
} | ||
} | ||
/** | ||
* Represents a field in a database table. | ||
*/ | ||
export class Field { | ||
/** | ||
* Constructs a new Field instance. | ||
* @param field - The DMMF.Field object representing the field. | ||
*/ | ||
constructor(field) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j; | ||
this.name = field.name; | ||
this.dbName = (_a = field.dbName) !== null && _a !== void 0 ? _a : field.name; | ||
this.type = field.type; | ||
this.relationName = (_c = (_b = field.relationName) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : null; | ||
this.isList = !!field.isList; | ||
this.isRequired = !!field.isRequired; | ||
this.kind = field.kind.toString(); | ||
this.isUpdatedAt = !!field.isUpdatedAt; | ||
this.default = (_e = (_d = field.default) === null || _d === void 0 ? void 0 : _d.valueOf()) !== null && _e !== void 0 ? _e : undefined; | ||
this.foreignKeys = (_g = (_f = field.relationFromFields) === null || _f === void 0 ? void 0 : _f.map((f) => f)) !== null && _g !== void 0 ? _g : []; | ||
this.primaryKeys = (_j = (_h = field.relationToFields) === null || _h === void 0 ? void 0 : _h.map((f) => f)) !== null && _j !== void 0 ? _j : []; | ||
} | ||
/** | ||
* Checks if the default is "now" function. | ||
* @returns True if the default value is "now", false otherwise. | ||
*/ | ||
get defaultIsNow() { | ||
return this.default != undefined && this.default.name === "now"; | ||
} | ||
/** | ||
* Checks if the default is "uuid" function. | ||
* @returns True if the default value is "uuid", false otherwise. | ||
*/ | ||
get defaultIsUuid() { | ||
return this.default != undefined && this.default.name === "uuid"; | ||
} | ||
/** | ||
* Checks if the default is "cuid" function. | ||
* @returns True if the default value is "cuid", false otherwise. | ||
*/ | ||
get defaultIsCuid() { | ||
return this.default != undefined && this.default.name === "cuid"; | ||
} | ||
/** | ||
* Gets the scalar default value. | ||
* @returns The scalar default value, or undefined if not applicable. | ||
*/ | ||
get scalarDefault() { | ||
if (this.default != undefined && typeof this.default != "object") { | ||
return this.cast(this.default); | ||
} | ||
return undefined; | ||
} | ||
/** | ||
* Gets the initial value for the field. | ||
* @returns The initial value for the field. | ||
*/ | ||
getInitialValue() { | ||
if (this.defaultIsUuid) | ||
return crypto.randomUUID(); | ||
if (this.defaultIsCuid) | ||
return cuid(); | ||
return this.scalarDefault; | ||
} | ||
/** | ||
* Casts a value to the appropriate type based on the field's type. | ||
* @param value - The value to cast. | ||
* @returns The casted value. | ||
*/ | ||
cast(value) { | ||
if (value == undefined) | ||
return value; | ||
switch (this.type) { | ||
case "BigInt": | ||
case "Decimal": | ||
case "Float": | ||
case "Int": | ||
return Number(value); | ||
case "Bytes": | ||
case "String": | ||
return String(value); | ||
case "Boolean": | ||
return !!value; | ||
case "DateTime": | ||
return new Date(value); | ||
case "JSON": | ||
return JSON.parse(value); | ||
default: | ||
return value; | ||
} | ||
} | ||
} | ||
const buildAssociation = (model, field, primaryKeys) => { | ||
const rModel = dmmf.datamodel.models.find((m) => m.name === field.type); | ||
const r = rModel === null || rModel === void 0 ? void 0 : rModel.fields.find((f) => f.relationName === field.relationName); | ||
if ((r === null || r === void 0 ? void 0 : r.relationFromFields) == undefined || (r === null || r === void 0 ? void 0 : r.relationToFields) == undefined) | ||
return undefined; | ||
const foreignKeys1 = r.relationFromFields.map((name) => { var _a, _b; return (_b = (_a = rModel.fields.find((f) => f.name === name)) === null || _a === void 0 ? void 0 : _a.dbName) !== null && _b !== void 0 ? _b : name; }); | ||
const foreignKeys2 = field.foreignKeys.map((name) => { var _a, _b; return (_b = (_a = model.fields.find((f) => f.name === name)) === null || _a === void 0 ? void 0 : _a.dbName) !== null && _b !== void 0 ? _b : name; }); | ||
const primaryKeys1 = r.relationToFields.map((name) => { var _a, _b; return (_b = (_a = model.fields.find((f) => f.name === name)) === null || _a === void 0 ? void 0 : _a.dbName) !== null && _b !== void 0 ? _b : name; }); | ||
const primaryKeys2 = field.primaryKeys.map((name) => { var _a, _b; return (_b = (_a = rModel.fields.find((f) => f.name === name)) === null || _a === void 0 ? void 0 : _a.dbName) !== null && _b !== void 0 ? _b : name; }); | ||
return new Association(r, field, primaryKeys, foreignKeys1.concat(foreignKeys2), primaryKeys1.concat(primaryKeys2)); | ||
}; | ||
let dmmf; | ||
import { buildAssociation } from "./model/association.js"; | ||
import { Field } from "./model/field.js"; | ||
export let dmmf; | ||
export const loadDmmf = () => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -166,0 +15,0 @@ const { Prisma } = yield import("@prisma/client"); |
@@ -9,2 +9,3 @@ import { Association } from "./associations/association.js"; | ||
import { Import } from "./model/import.js"; | ||
import { Lock, LockType } from "./model/lock.js"; | ||
import { Naming } from "./model/naming.js"; | ||
@@ -48,3 +49,3 @@ import { Searchable } from "./model/search.js"; | ||
export declare const registerModel: (model: any) => void; | ||
declare const Model_base: (new () => AttributeAssignment & Callbacks & Connection & Dirty & Fields & Import & Naming & Persistence & Query & Searchable & Serialization & Transaction & Validations) & { | ||
declare const Model_base: (new () => AttributeAssignment & Callbacks & Connection & Dirty & Fields & Import & Lock & Naming & Persistence & Query & Searchable & Serialization & Transaction & Validations) & { | ||
prototype: AttributeAssignment; | ||
@@ -77,9 +78,9 @@ } & { | ||
readonly tableName: string; | ||
readonly fields: readonly import("./fields.js").Field[]; | ||
readonly fields: readonly import("./model/field.js").Field[]; | ||
findField: typeof Fields.findField; | ||
readonly columnFields: readonly import("./fields.js").Field[]; | ||
readonly columnFields: readonly import("./model/field.js").Field[]; | ||
attributeToColumn: typeof Fields.attributeToColumn; | ||
columnToAttribute: typeof Fields.columnToAttribute; | ||
readonly primaryKeys: readonly string[]; | ||
readonly associations: Record<string, import("./fields.js").Association>; | ||
readonly associations: Record<string, import("./model/association.js").Association>; | ||
} & { | ||
@@ -89,2 +90,5 @@ prototype: Import; | ||
} & { | ||
prototype: Lock; | ||
lock: typeof Lock.lock; | ||
} & { | ||
prototype: Naming; | ||
@@ -164,3 +168,5 @@ readonly modelName: { | ||
*/ | ||
reload(): this; | ||
reload(options?: { | ||
lock?: LockType; | ||
}): this; | ||
} | ||
@@ -167,0 +173,0 @@ declare module "knex" { |
@@ -10,2 +10,3 @@ import { Collection } from "./associations/collectionProxy.js"; | ||
import { Import } from "./model/import.js"; | ||
import { Lock } from "./model/lock.js"; | ||
import { Naming } from "./model/naming.js"; | ||
@@ -36,3 +37,3 @@ import { Searchable } from "./model/search.js"; | ||
}; | ||
export class Model extends Mix(AttributeAssignment, Callbacks, Connection, Dirty, Fields, Import, Naming, Persistence, Query, Searchable, Serialization, Transaction, Validations) { | ||
export class Model extends Mix(AttributeAssignment, Callbacks, Connection, Dirty, Fields, Import, Lock, Naming, Persistence, Query, Searchable, Serialization, Transaction, Validations) { | ||
constructor() { | ||
@@ -71,4 +72,4 @@ super(...arguments); | ||
*/ | ||
reload() { | ||
this.retriveInsertedAttributes({}); | ||
reload(options) { | ||
this.retriveInsertedAttributes({}, options === null || options === void 0 ? void 0 : options.lock); | ||
for (const [key, association] of this.associations.entries()) { | ||
@@ -75,0 +76,0 @@ if (association instanceof HasOneAssociation) { |
@@ -61,6 +61,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
yield this.resetLogsMap(); | ||
let applyCount = 0; | ||
// let applyCount = 0; | ||
for (const dir of fs.readdirSync(this.migrationsPath)) { | ||
if (yield this.applyIfPending(dir)) { | ||
applyCount++; | ||
// applyCount++; | ||
} | ||
@@ -67,0 +67,0 @@ } |
@@ -27,23 +27,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const config = getConfig(); | ||
const parse = () => { | ||
const knexConfig = getKnexConfig(config); | ||
if (typeof (knexConfig === null || knexConfig === void 0 ? void 0 : knexConfig.connection) == "string") { | ||
const u = new URL(knexConfig.connection); | ||
const database = u.pathname.replace("/", ""); | ||
u.pathname = ""; | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: u.toString() }); | ||
return [database, newConfig]; | ||
} | ||
else if (knexConfig) { | ||
// @ts-ignore | ||
const _a = knexConfig.connection, { database } = _a, rest = __rest(_a, ["database"]); | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: rest }); | ||
return [database, newConfig]; | ||
} | ||
else { | ||
throw new Error("Invalid knexConfig"); | ||
} | ||
}; | ||
const [database, newConfig] = parse(); | ||
const [database, newConfig] = parseConfig(); | ||
const knex = Knex(newConfig); | ||
@@ -64,2 +44,21 @@ const exists = yield knex.raw(`SHOW DATABASES LIKE "${database}";`); | ||
} | ||
const parseConfig = () => { | ||
const knexConfig = getKnexConfig(getConfig()); | ||
if (typeof (knexConfig === null || knexConfig === void 0 ? void 0 : knexConfig.connection) == "string") { | ||
const u = new URL(knexConfig.connection); | ||
const database = u.pathname.replace("/", ""); | ||
u.pathname = ""; | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: u.toString() }); | ||
return [database, newConfig]; | ||
} | ||
else if (knexConfig) { | ||
// @ts-ignore | ||
const _a = knexConfig.connection, { database } = _a, rest = __rest(_a, ["database"]); | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: rest }); | ||
return [database, newConfig]; | ||
} | ||
else { | ||
throw new Error("Invalid knexConfig"); | ||
} | ||
}; | ||
const CREATE_LOGS_TABLE_DDL = `CREATE TABLE IF NOT EXISTS \`_prisma_migrations\` ( | ||
@@ -66,0 +65,0 @@ \`id\` varchar(36) COLLATE utf8mb4_unicode_ci NOT NULL, |
@@ -27,23 +27,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const config = getConfig(); | ||
const parse = () => { | ||
const knexConfig = getKnexConfig(config); | ||
if (typeof (knexConfig === null || knexConfig === void 0 ? void 0 : knexConfig.connection) == "string") { | ||
const u = new URL(knexConfig.connection); | ||
const database = u.pathname.replace("/", ""); | ||
u.pathname = "postgres"; | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: u.toString() }); | ||
return [database, newConfig]; | ||
} | ||
else if (knexConfig) { | ||
// @ts-ignore | ||
const _a = knexConfig.connection, { database } = _a, rest = __rest(_a, ["database"]); | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: Object.assign(Object.assign({}, rest), { database: "postgres" }) }); | ||
return [database, newConfig]; | ||
} | ||
else { | ||
throw new Error("Invalid knexConfig"); | ||
} | ||
}; | ||
const [database, newConfig] = parse(); | ||
const [database, newConfig] = parseConfig(); | ||
const knex = Knex(newConfig); | ||
@@ -64,2 +44,22 @@ const exists = yield knex.raw(`SELECT 1 FROM pg_database WHERE datname='${database}'`); | ||
} | ||
const parseConfig = () => { | ||
const config = getConfig(); | ||
const knexConfig = getKnexConfig(config); | ||
if (typeof (knexConfig === null || knexConfig === void 0 ? void 0 : knexConfig.connection) == "string") { | ||
const u = new URL(knexConfig.connection); | ||
const database = u.pathname.replace("/", ""); | ||
u.pathname = "postgres"; | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: u.toString() }); | ||
return [database, newConfig]; | ||
} | ||
else if (knexConfig) { | ||
// @ts-ignore | ||
const _a = knexConfig.connection, { database } = _a, rest = __rest(_a, ["database"]); | ||
const newConfig = Object.assign(Object.assign({}, knexConfig), { connection: Object.assign(Object.assign({}, rest), { database: "postgres" }) }); | ||
return [database, newConfig]; | ||
} | ||
else { | ||
throw new Error("Invalid knexConfig"); | ||
} | ||
}; | ||
const CREATE_LOGS_TABLE_DDL = `CREATE TABLE IF NOT EXISTS public._prisma_migrations ( | ||
@@ -66,0 +66,0 @@ id character varying(36) NOT NULL, |
@@ -18,15 +18,3 @@ import { exec } from "../database.js"; | ||
const _records = records.map((r) => r instanceof Model ? r : this.build(r)); | ||
const failedInstances = []; | ||
const params = _records | ||
.map((record) => { | ||
if (options.validate === false || record.isValid()) { | ||
return makeInsertParams(record); | ||
} | ||
if (options.validate === "throw") { | ||
throw new Error("Validation failed"); | ||
} | ||
failedInstances.push(record); | ||
return undefined; | ||
}) | ||
.filter(Boolean); | ||
const { params, failedInstances } = formatParams(_records, options); | ||
let q = this.queryBuilder.insert(params); | ||
@@ -41,2 +29,18 @@ q = addOnConflictMerge(this, options, q); | ||
} | ||
const formatParams = (records, options) => { | ||
const failedInstances = []; | ||
const params = records | ||
.map((record) => { | ||
if (options.validate === false || record.isValid()) { | ||
return makeInsertParams(record); | ||
} | ||
if (options.validate === "throw") { | ||
throw new Error("Validation failed"); | ||
} | ||
failedInstances.push(record); | ||
return undefined; | ||
}) | ||
.filter(Boolean); | ||
return { params, failedInstances }; | ||
}; | ||
/** | ||
@@ -43,0 +47,0 @@ * Creates the insert parameters for a record. |
@@ -52,5 +52,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
} | ||
catch (e) { | ||
catch (_a) { | ||
// i18next not found | ||
} | ||
}); |
@@ -79,3 +79,3 @@ import { Model } from "../index.js"; | ||
*/ | ||
static search<T extends typeof Model>(this: T, params: Record<string, any>): Search; | ||
static search<T extends typeof Model>(this: T, params: Record<string, any> | undefined): Search; | ||
/** | ||
@@ -82,0 +82,0 @@ * An array of searchable scopes used in the search() method. |
@@ -14,2 +14,3 @@ import { compareSync, genSaltSync, hashSync } from "bcrypt-ts"; | ||
*/ | ||
// eslint-disable-next-line max-lines-per-function | ||
export function hasSecurePassword(options = {}) { | ||
@@ -16,0 +17,0 @@ var _a, _b; |
@@ -0,1 +1,2 @@ | ||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
import { BelongsToAssociation } from "../associations/belongsToAssociation.js"; | ||
@@ -2,0 +3,0 @@ import { HasManyAssociation } from "../associations/hasManyAssociation.js"; |
@@ -32,2 +32,3 @@ import { Model } from "../index.js"; | ||
isValid<T extends Model>(this: T): boolean; | ||
private validateAssociations; | ||
/** | ||
@@ -34,0 +35,0 @@ * Checks if the model is invalid by negating the result of the `isValid` method. |
@@ -28,7 +28,10 @@ import { Collection } from "../associations/collectionProxy.js"; | ||
this.validateAttributes(); | ||
let result = this.errors.isEmpty(); | ||
this.validateAssociations(); | ||
this.runAfterCallbacks("validation"); | ||
return this.errors.isEmpty(); | ||
} | ||
validateAssociations() { | ||
for (const [key, association] of this.associations) { | ||
if (association instanceof HasOneAssociation) { | ||
if (association.isValid() === false) { | ||
result = false; | ||
this.errors.add(key, "is invalid"); | ||
@@ -41,3 +44,2 @@ } | ||
if (value instanceof Collection && value.isValid() === false) { | ||
result = false; | ||
this.errors.add(key, "is invalid"); | ||
@@ -47,4 +49,2 @@ } | ||
} | ||
this.runAfterCallbacks("validation"); | ||
return result; | ||
} | ||
@@ -88,22 +88,16 @@ /** | ||
const value = this[attribute]; | ||
if (options.acceptance) { | ||
if (options.acceptance) | ||
new AcceptanceValidator(this, attribute, options.acceptance).validate(); | ||
} | ||
if (options.presence) { | ||
if (options.presence) | ||
new PresenceValidator(this, attribute, options.presence).validate(); | ||
} | ||
if (options.length && value != undefined) { | ||
if (options.length && value != undefined) | ||
new LengthValidator(this, attribute, options.length).validate(); | ||
} | ||
if (options.inclusion && value != undefined) { | ||
if (options.inclusion && value != undefined) | ||
new InclusionValidator(this, attribute, options.inclusion).validate(); | ||
} | ||
if (options.format && value != undefined) { | ||
if (options.format && value != undefined) | ||
new FormatValidator(this, attribute, options.format).validate(); | ||
} | ||
if (options.uniqueness) { | ||
if (options.uniqueness) | ||
new UniquenessValidator(this, attribute, options.uniqueness).validate(); | ||
} | ||
} | ||
} | ||
} |
import { Model } from "./index.js"; | ||
import { Meta, New, Persisted } from "./meta.js"; | ||
import { LockType } from "./model/lock.js"; | ||
/** | ||
@@ -84,12 +85,2 @@ * Represents a Persistence class that provides methods for managing records. | ||
/** | ||
* Creates the parameters for updating the record. | ||
* @returns The update parameters. | ||
*/ | ||
protected makeUpdateParams<T extends Model>(this: T): Record<string, any>; | ||
/** | ||
* Retrieves the updated attributes of the record from the database. | ||
* @param data - The updated data returned from the database. | ||
*/ | ||
protected retriveUpdatedAt<T extends Model>(this: T, data: Record<string, any>): void; | ||
/** | ||
* Creates the record in the database. | ||
@@ -103,4 +94,3 @@ * @returns A boolean indicating whether the record was successfully created. | ||
*/ | ||
protected retriveInsertedAttributes<T extends Model>(this: T, returning: Record<keyof T, any>): void; | ||
protected getLastInsertId<T extends Model>(this: T): any; | ||
protected retriveInsertedAttributes<T extends Model>(this: T, returning: Record<keyof T, any>, lock?: LockType): void; | ||
/** | ||
@@ -120,7 +110,2 @@ * Creates the parameters for inserting the record. | ||
protected deleteRecord<T extends Model>(this: T): boolean; | ||
/** | ||
* Creates the condition for the primary keys of the record. | ||
* @returns The primary keys condition. | ||
*/ | ||
protected primaryKeysCondition<T extends Model>(this: T): Record<keyof T, any>; | ||
} |
import { HasManyAssociation } from "./associations/hasManyAssociation.js"; | ||
import { HasOneAssociation } from "./associations/hasOneAssociation.js"; | ||
import { ModelInstanceBuilder } from "./associations/modelInstanceBuilder.js"; | ||
import { exec, execSQL } from "./database.js"; | ||
import { Collection, Model } from "./index.js"; | ||
import { exec } from "./database.js"; | ||
import { Collection } from "./index.js"; | ||
import { InsertManager } from "./table/insert.js"; | ||
import { UpdateManager } from "./table/update.js"; | ||
import { primaryKeysCondition } from "./table/utils.js"; | ||
/** | ||
@@ -148,5 +151,3 @@ * Represents a Persistence class that provides methods for managing records. | ||
this.runBeforeCallbacks("update"); | ||
const data = this.makeUpdateParams(); | ||
exec(this.queryBuilder.where(this.primaryKeysCondition()).update(data)); | ||
this.retriveUpdatedAt(data); | ||
new UpdateManager(this).update(); | ||
this.runAfterCallbacks("update"); | ||
@@ -157,36 +158,2 @@ } | ||
/** | ||
* Creates the parameters for updating the record. | ||
* @returns The update parameters. | ||
*/ | ||
makeUpdateParams() { | ||
var _a, _b; | ||
const data = {}; | ||
const now = new Date(); | ||
for (const field of this.columnFields) { | ||
const column = field.dbName; | ||
if (this.isAttributeChanged(field.name) && this[column] !== undefined) { | ||
data[column] = this[column]; | ||
} | ||
if ((_a = this.findField(column)) === null || _a === void 0 ? void 0 : _a.isUpdatedAt) { | ||
data[column] = now; | ||
} | ||
if (((_b = this.findField(column)) === null || _b === void 0 ? void 0 : _b.type) === "Json") { | ||
data[column] = JSON.stringify(this[column]); | ||
} | ||
} | ||
return data; | ||
} | ||
/** | ||
* Retrieves the updated attributes of the record from the database. | ||
* @param data - The updated data returned from the database. | ||
*/ | ||
retriveUpdatedAt(data) { | ||
var _a; | ||
for (const column of this.columns) { | ||
if ((_a = this.findField(column)) === null || _a === void 0 ? void 0 : _a.isUpdatedAt) { | ||
this[column] = data[column]; | ||
} | ||
} | ||
} | ||
/** | ||
* Creates the record in the database. | ||
@@ -196,11 +163,4 @@ * @returns A boolean indicating whether the record was successfully created. | ||
createRecord() { | ||
var _a; | ||
this.runBeforeCallbacks("create"); | ||
const data = this.makeInsertParams(); | ||
let q = this.queryBuilder; | ||
if (Model.connection.returningUsable()) { | ||
q = q.returning(this.primaryKeys); | ||
} | ||
const returning = exec(q.insert(data)); | ||
this.retriveInsertedAttributes((_a = returning[0]) !== null && _a !== void 0 ? _a : {}); | ||
new InsertManager(this).insert(); | ||
this.runAfterCallbacks("create"); | ||
@@ -213,21 +173,5 @@ return true; | ||
*/ | ||
retriveInsertedAttributes(returning) { | ||
var _a, _b; | ||
const data = {}; | ||
for (const key of this.primaryKeys) { | ||
data[key] = this[key] || returning[key] || this.getLastInsertId(); | ||
} | ||
const [record] = exec(this.queryBuilder.where(data).limit(1), "TRACE"); | ||
for (const [key, value] of Object.entries(record)) { | ||
this[key] = (_b = (_a = this.findField(key)) === null || _a === void 0 ? void 0 : _a.cast(value)) !== null && _b !== void 0 ? _b : value; | ||
} | ||
retriveInsertedAttributes(returning, lock) { | ||
new InsertManager(this).retriveInsertedAttributes(returning, lock); | ||
} | ||
// for MySQL (The 'returning' clause is not available.) | ||
getLastInsertId() { | ||
return execSQL({ | ||
sql: "select last_insert_id() as id;", | ||
bindings: [], | ||
logLevel: "TRACE", | ||
})[0]["id"]; | ||
} | ||
/** | ||
@@ -238,21 +182,3 @@ * Creates the parameters for inserting the record. | ||
makeInsertParams() { | ||
var _a; | ||
const data = {}; | ||
const now = new Date(); | ||
for (const column of this.columns) { | ||
if (this[column] !== undefined) { | ||
data[column] = this[column]; | ||
} | ||
const field = this.findField(column); | ||
if ((field === null || field === void 0 ? void 0 : field.isUpdatedAt) && data[column] == undefined) { | ||
data[column] = now; | ||
} | ||
if ((field === null || field === void 0 ? void 0 : field.defaultIsNow) && data[column] == undefined) { | ||
data[column] = now; | ||
} | ||
if (((_a = this.findField(column)) === null || _a === void 0 ? void 0 : _a.type) === "Json") { | ||
data[column] = JSON.stringify(this[column]); | ||
} | ||
} | ||
return data; | ||
return new InsertManager(this).makeInsertParams(); | ||
} | ||
@@ -282,16 +208,5 @@ /** | ||
deleteRecord() { | ||
exec(this.queryBuilder.where(this.primaryKeysCondition()).delete()); | ||
exec(this.queryBuilder.where(primaryKeysCondition(this)).delete()); | ||
return true; | ||
} | ||
/** | ||
* Creates the condition for the primary keys of the record. | ||
* @returns The primary keys condition. | ||
*/ | ||
primaryKeysCondition() { | ||
const where = {}; | ||
for (const key of this.primaryKeys) { | ||
where[key] = this[key]; | ||
} | ||
return where; | ||
} | ||
} |
@@ -1,3 +0,4 @@ | ||
import { RecordNotFound } from "./errors.js"; | ||
import { Relation } from "./relation/index.js"; | ||
// FIXME: This file is too long . [max-lines] | ||
/*eslint max-lines: ["error", {"max": 213, "skipBlankLines": true, "skipComments": true }]*/ | ||
/** | ||
@@ -178,11 +179,3 @@ * Represents a query class for performing database queries. | ||
static find(id) { | ||
const instance = isFinite(id) | ||
? this.all() | ||
.setOption("wheres", [{ [this.primaryKeys[0]]: id }]) | ||
.first() | ||
: undefined; | ||
if (!instance) { | ||
throw new RecordNotFound("Record Not Found"); | ||
} | ||
return instance; | ||
return this.all().find(id); | ||
} | ||
@@ -189,0 +182,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { Association as Info } from "../fields.js"; | ||
import { Association as Info } from "../model/association.js"; | ||
import { ModelMeta } from "../meta.js"; | ||
@@ -3,0 +3,0 @@ import { Relation, Relations } from "./index.js"; |
@@ -19,6 +19,5 @@ import { Knex } from "knex"; | ||
protected query<T>(this: Relation<T, ModelMeta>): any; | ||
protected loadIncludes<T>(this: Relation<T, ModelMeta>, rows: any[]): void; | ||
private loadHasManyThroughIncludes; | ||
protected loadBelongsToIncludes(rows: any[], association: Options["includes"][0]): void; | ||
protected affectWheres<T>(this: Relation<T, ModelMeta>, q: any): any; | ||
protected affectOrWheres<T>(this: Relation<T, ModelMeta>, q: any): any; | ||
protected makeAttributes<T>(this: Relation<T, ModelMeta>, row: object): any; | ||
} |
import { exec } from "../database.js"; | ||
import { Models } from "../index.js"; | ||
import { affectLock } from "../model/lock.js"; | ||
import { IncludesLoader } from "./includes.js"; | ||
/** | ||
@@ -14,2 +15,3 @@ * Provides the base methods for relations. | ||
load() { | ||
var _a; | ||
const select = this.options.select.length > 0 | ||
@@ -19,3 +21,5 @@ ? this.options.select.map((column) => `${this.model.tableName}.${this.model.attributeToColumn(column)}`) | ||
const rows = exec(this.query().select(...select)); | ||
this.loadIncludes(rows); | ||
for (const association of (_a = this.options.includes) !== null && _a !== void 0 ? _a : []) { | ||
new IncludesLoader(this.model, rows, association).load(); | ||
} | ||
const records = rows.map((row) => this.makeAttributes(row)); | ||
@@ -46,2 +50,15 @@ if (this.options.select.length > 0) | ||
} | ||
q = this.affectWheres(q); | ||
q = this.affectOrWheres(q); | ||
if (this.options.limit) | ||
q = q.limit(this.options.limit); | ||
if (this.options.offset) | ||
q = q.offset(this.options.offset); | ||
for (const [column, direction] of (_a = this.options.orders) !== null && _a !== void 0 ? _a : []) { | ||
q = q.orderBy(column, direction); | ||
} | ||
q = affectLock(q, this.options.lock); | ||
return q; | ||
} | ||
affectWheres(q) { | ||
for (const where of this.options.wheres) { | ||
@@ -66,2 +83,5 @@ if (Array.isArray(where)) { | ||
} | ||
return q; | ||
} | ||
affectOrWheres(q) { | ||
for (const where of this.options.orWheres) { | ||
@@ -91,79 +111,4 @@ q = q.orWhere(function () { | ||
} | ||
if (this.options.limit) | ||
q = q.limit(this.options.limit); | ||
if (this.options.offset) | ||
q = q.offset(this.options.offset); | ||
for (const [column, direction] of (_a = this.options.orders) !== null && _a !== void 0 ? _a : []) { | ||
q = q.orderBy(column, direction); | ||
} | ||
return q; | ||
} | ||
loadIncludes(rows) { | ||
var _a, _b; | ||
var _c; | ||
for (const association of (_a = this.options.includes) !== null && _a !== void 0 ? _a : []) { | ||
if (association.isBelongsTo) { | ||
this.loadBelongsToIncludes(rows, association); | ||
} | ||
else if (association.through) { | ||
this.loadHasManyThroughIncludes(association, rows); | ||
} | ||
else { | ||
const { klass, primaryKey, foreignKey } = association; | ||
const name = association.field.name; | ||
const primaryKeys = rows.map((row) => row[primaryKey]); | ||
const attribute = Models[klass].columnToAttribute(foreignKey); | ||
const included = Models[klass].where({ [attribute]: primaryKeys }); | ||
const mapping = {}; | ||
for (const row of included) { | ||
(mapping[_c = row[foreignKey]] || (mapping[_c] = [])).push(row); | ||
} | ||
for (const row of rows) { | ||
row[name] = (_b = mapping[row[primaryKey]]) !== null && _b !== void 0 ? _b : []; | ||
} | ||
} | ||
} | ||
} | ||
loadHasManyThroughIncludes(association, rows) { | ||
var _a; | ||
var _b; | ||
const { klass, primaryKey, foreignKey, joinKey } = association; | ||
const name = association.field.name; | ||
const primaryKeys = rows.map((row) => row[primaryKey]); | ||
const relations = this.model.connection | ||
.knex(association.through) | ||
.where(foreignKey, "in", primaryKeys) | ||
.execute(); | ||
const targetModel = Models[klass]; | ||
const pk = targetModel.primaryKeys[0]; | ||
const attribute = targetModel.columnToAttribute(pk); | ||
const included = targetModel.where({ | ||
[attribute]: relations.map((r) => r[joinKey]), | ||
}); | ||
const includedMap = {}; | ||
for (const row of included) { | ||
includedMap[row[pk]] = row; | ||
} | ||
const mapping = {}; | ||
for (const row of relations) { | ||
(mapping[_b = row[foreignKey]] || (mapping[_b] = [])).push(includedMap[row[joinKey]]); | ||
} | ||
for (const row of rows) { | ||
row[name] = (_a = mapping[row[primaryKey]]) !== null && _a !== void 0 ? _a : []; | ||
} | ||
} | ||
loadBelongsToIncludes(rows, association) { | ||
const { klass, primaryKey, foreignKey } = association; | ||
const name = association.field.name; | ||
const foreignKeys = rows.map((row) => row[foreignKey]); | ||
const mapping = {}; | ||
const attribute = Models[klass].columnToAttribute(primaryKey); | ||
const included = Models[klass].where({ [attribute]: foreignKeys }); | ||
for (const row of included) { | ||
mapping[row[primaryKey]] = row; | ||
} | ||
for (const row of rows) { | ||
row[name] = mapping[row[foreignKey]]; | ||
} | ||
} | ||
makeAttributes(row) { | ||
@@ -170,0 +115,0 @@ var _a, _b; |
@@ -22,6 +22,3 @@ export class Batches { | ||
} | ||
return { | ||
done: cache.length == 0, | ||
value: cache[count++], | ||
}; | ||
return { done: cache.length == 0, value: cache[count++] }; | ||
}, | ||
@@ -28,0 +25,0 @@ }; |
import { Collection, Model } from "../index.js"; | ||
import { type ModelMeta } from "../meta.js"; | ||
import { LockType } from "../model/lock.js"; | ||
import { ToHashOptions, ToHashResult } from "../model/serialization.js"; | ||
@@ -67,2 +68,3 @@ import { Association } from "./association.js"; | ||
map<F extends (value: T, index: number, array: T[]) => any>(func: F): ReturnType<F>[]; | ||
lock<T, M extends ModelMeta>(this: Relation<T, M>, type?: LockType): Relation<T, M>; | ||
/** | ||
@@ -69,0 +71,0 @@ * Returns an iterator for the Relation class. |
@@ -12,2 +12,3 @@ import { Model } from "../index.js"; | ||
import { Where } from "./where.js"; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
export class Relation extends Mix(Association, Batches, Calculations, Merge, Query, RelationBase, Searchable, Where) { | ||
@@ -53,2 +54,5 @@ constructor(model, options = {}, cache = undefined) { | ||
} | ||
lock(type = "forUpdate") { | ||
return new Relation(this.model, Object.assign(Object.assign({}, this.options), { lock: type })); | ||
} | ||
/** | ||
@@ -55,0 +59,0 @@ * Returns an iterator for the Relation class. |
@@ -14,3 +14,3 @@ export class Merge { | ||
function deepMerge(target, source) { | ||
let output = Object.assign({}, target); | ||
const output = Object.assign({}, target); | ||
if (isObject(target) && isObject(source)) { | ||
@@ -17,0 +17,0 @@ Object.keys(source).forEach((key) => { |
@@ -1,2 +0,3 @@ | ||
import { Association } from "../fields.js"; | ||
import { Association } from "../model/association.js"; | ||
import { LockType } from "../model/lock.js"; | ||
export type Options = { | ||
@@ -15,3 +16,4 @@ select: string[]; | ||
includes: Association[]; | ||
lock: LockType; | ||
}; | ||
export declare const getDefaultOptions: () => Options; |
@@ -14,2 +14,3 @@ export const getDefaultOptions = () => ({ | ||
limit: undefined, | ||
lock: undefined, | ||
}); |
@@ -12,2 +12,9 @@ import { Model } from "../index.js"; | ||
/** | ||
* Finds a record by its ID. | ||
* @param id - The ID of the record. | ||
* @returns The found record. | ||
* @throws An error if the record is not found. | ||
*/ | ||
find<T, M extends ModelMeta>(this: Relation<T, M>, id: number): T; | ||
/** | ||
* Retrieves the first n elements. | ||
@@ -14,0 +21,0 @@ * |
import { exec } from "../database.js"; | ||
import { RecordNotFound } from "../errors.js"; | ||
import { Model } from "../index.js"; | ||
@@ -15,2 +16,17 @@ import { Relation } from "./index.js"; | ||
} | ||
/** | ||
* Finds a record by its ID. | ||
* @param id - The ID of the record. | ||
* @returns The found record. | ||
* @throws An error if the record is not found. | ||
*/ | ||
find(id) { | ||
const instance = isFinite(id) | ||
? this.setOption("wheres", [{ [this.model.primaryKeys[0]]: id }]).first() | ||
: undefined; | ||
if (!instance) { | ||
throw new RecordNotFound("Record Not Found"); | ||
} | ||
return instance; | ||
} | ||
first(limit) { | ||
@@ -17,0 +33,0 @@ const queryLimit = limit !== null && limit !== void 0 ? limit : 1; |
@@ -80,3 +80,3 @@ import { ModelMeta } from "../meta.js"; | ||
*/ | ||
search<T, M extends ModelMeta>(this: Relation<T, M>, params: Record<string, any>): Search; | ||
search<T, M extends ModelMeta>(this: Relation<T, M>, params: Record<string, any> | undefined): Search; | ||
} |
import { AttributeNotFound } from "../errors.js"; | ||
import { Model, Models, Relation } from "../index.js"; | ||
// FIXME: Fix the behavior of 'or' and resolve the accompanying Linter error | ||
/* eslint-disable max-lines-per-function */ | ||
/* eslint-disable max-lines */ | ||
/** | ||
@@ -4,0 +7,0 @@ * Provides the *where* related methods for relations. |
@@ -12,5 +12,7 @@ /** | ||
*/ | ||
export function scope(method, context) { | ||
export function scope(method, | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
context) { | ||
method.isAccelRecordScope = true; | ||
return method; | ||
} |
@@ -0,1 +1,2 @@ | ||
/* eslint-disable-next-line max-lines-per-function */ | ||
export const getCondition = (predicate, value) => { | ||
@@ -2,0 +3,0 @@ switch (predicate) { |
@@ -5,5 +5,6 @@ import type { Model } from "../index.js"; | ||
protected model: typeof Model; | ||
protected params: Record<string, number | string>; | ||
protected relation: Relation<any, any> | undefined; | ||
constructor(model: typeof Model, params: Record<string, number | string>, relation?: Relation<any, any> | undefined); | ||
readonly params: Record<string, any>; | ||
readonly [key: string]: any; | ||
constructor(model: typeof Model, params: Record<string, any> | undefined, relation?: Relation<any, any> | undefined); | ||
/** | ||
@@ -13,6 +14,2 @@ * Retrieves the search result based on the specified parameters. | ||
result(): Relation<Model, import("../meta.js").ModelMeta> | Relation<any, any>; | ||
private updateRelation; | ||
private affectQuery; | ||
private affectDefaultQuery; | ||
private buildWhere; | ||
} |
import { AttributeNotFound } from "../errors.js"; | ||
import { getCondition } from "./condition.js"; | ||
import { Query } from "./query.js"; | ||
import { isBlank } from "../validation/validator/presence.js"; | ||
import { RelationUpdater } from "./relation.js"; | ||
export class Search { | ||
constructor(model, params, relation = undefined) { | ||
this.model = model; | ||
this.params = params; | ||
this.relation = relation; | ||
this.params = JSON.parse(JSON.stringify(params !== null && params !== void 0 ? params : {})); | ||
for (const key of Object.keys(this.params)) { | ||
if (isBlank(this.params[key])) | ||
delete this.params[key]; | ||
else if (key.match(/.+_.+/)) { | ||
Object.defineProperty(this, key, { | ||
value: this.params[key], | ||
writable: true, | ||
configurable: true, | ||
}); | ||
} | ||
} | ||
} | ||
@@ -18,3 +29,3 @@ /** | ||
try { | ||
relation = this.updateRelation(relation, key, value); | ||
relation = new RelationUpdater(this.model, relation, key, value).update(); | ||
} | ||
@@ -31,86 +42,2 @@ catch (e) { | ||
} | ||
updateRelation(relation, key, value) { | ||
if (this.model.searchableScopes.includes(key)) { | ||
return relation.merge(this.model[key](value)); | ||
} | ||
const q = new Query(key, value); | ||
if (!q.isValid) | ||
return relation; | ||
const { predicate, orList } = q; | ||
if (orList.length > 1) { | ||
let tmp = orList.reduce((acc, attr) => { | ||
var _a; | ||
const r = this.affectQuery(this.model.all(), attr, predicate, value); | ||
return (_a = acc === null || acc === void 0 ? void 0 : acc.or(r)) !== null && _a !== void 0 ? _a : r; | ||
}, undefined); | ||
return relation.merge(tmp); | ||
} | ||
for (const attr of q.attributes) { | ||
relation = this.affectQuery(relation, attr, predicate, value); | ||
} | ||
return relation; | ||
} | ||
affectQuery(relation, attrStr, predicate, value) { | ||
switch (predicate.name) { | ||
case "blank": { | ||
const w1 = this.buildWhere(this.model, attrStr, predicate, ""); | ||
const w2 = this.buildWhere(this.model, attrStr, predicate, null); | ||
return relation.joins(w1.joins).where(w1.where).or(w2.where); | ||
} | ||
case "present": { | ||
const w1 = this.buildWhere(this.model, attrStr, predicate, ""); | ||
const w2 = this.buildWhere(this.model, attrStr, predicate, null); | ||
return relation.joins(w1.joins).whereNot(w1.where).whereNot(w2.where); | ||
} | ||
default: | ||
return this.affectDefaultQuery(relation, attrStr, predicate, value); | ||
} | ||
} | ||
affectDefaultQuery(relation, attrStr, predicate, value) { | ||
const method = predicate.not ? "whereNot" : "where"; | ||
const values = [value].flat(); | ||
switch (predicate.type) { | ||
case "all": { | ||
let ret = relation; | ||
for (const v of values) { | ||
const w = this.buildWhere(this.model, attrStr, predicate, v); | ||
ret = ret.joins(w.joins)[method](w.where); | ||
} | ||
return ret; | ||
} | ||
case "any": { | ||
let tmp = values.reduce((acc, v) => { | ||
var _a; | ||
const w = this.buildWhere(this.model, attrStr, predicate, v); | ||
const r = this.model[method](w.where); | ||
return (_a = acc === null || acc === void 0 ? void 0 : acc.or(r)) !== null && _a !== void 0 ? _a : r.joins(w.joins); | ||
}, undefined); | ||
return relation.merge(tmp); | ||
} | ||
default: { | ||
const w = this.buildWhere(this.model, attrStr, predicate, value); | ||
return relation.joins(w.joins)[method](w.where); | ||
} | ||
} | ||
} | ||
buildWhere(model, attrStr, predicate, value) { | ||
const field = model.findField(attrStr); | ||
if (!field) { | ||
for (const [key, association] of Object.entries(model.associations)) { | ||
if (attrStr.startsWith(`${key}_`)) { | ||
const nextAttr = attrStr.substring(key.length + 1); | ||
const { model: nextModel } = association; | ||
const next = this.buildWhere(nextModel, nextAttr, predicate, value); | ||
return { | ||
where: { [key]: next.where }, | ||
joins: { [key]: next.joins }, | ||
}; | ||
} | ||
} | ||
} | ||
return { | ||
where: { [attrStr]: getCondition(predicate.name, value) }, | ||
joins: {}, | ||
}; | ||
} | ||
} |
@@ -105,3 +105,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
static transactionAsync(callback) { | ||
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { | ||
return (() => __awaiter(this, void 0, void 0, function* () { | ||
let result = undefined; | ||
@@ -115,14 +115,13 @@ this.startNestableTransaction(); | ||
if (e instanceof Rollback) { | ||
resolve(undefined); | ||
return undefined; | ||
} | ||
else { | ||
reject(e); | ||
throw e; | ||
} | ||
return; | ||
} | ||
this.tryCommitNestableTransaction(); | ||
resolve(result); | ||
})); | ||
return result; | ||
}))(); | ||
} | ||
} | ||
Transaction.transactionCount = 0; |
@@ -37,3 +37,3 @@ type WithoutConstructor<T> = { | ||
export declare const Mix: <T extends (new (...args: any) => any)[]>(...classes: T) => (new () => InstanceTypeIntersection<T>) & ObjectIntersection<T>; | ||
export declare const getStaticProperties: <T extends Function>(cls: T) => Map<string, any>; | ||
export declare const getStaticProperties: (cls: any) => Map<string, any>; | ||
export {}; |
@@ -26,5 +26,16 @@ /** | ||
export const Mix = (...classes) => { | ||
const BaseClass = classes[0]; | ||
const classList = classes.slice(1); | ||
const newClass = class extends BaseClass { | ||
const [BaseClass, ...classList] = classes; | ||
const newClass = defineNewClass(BaseClass, classList); | ||
for (const cls of classList) { | ||
getStaticProperties(cls).forEach((klass, key) => { | ||
assign(newClass, klass, key); | ||
}); | ||
getInstanceMethods(cls).forEach((proto, key) => { | ||
assign(newClass.prototype, proto, key); | ||
}); | ||
} | ||
return newClass; | ||
}; | ||
const defineNewClass = (BaseClass, classList) => { | ||
return class extends BaseClass { | ||
constructor() { | ||
@@ -40,11 +51,2 @@ super(); | ||
}; | ||
for (let cls of classList) { | ||
getStaticProperties(cls).forEach((klass, key) => { | ||
assign(newClass, klass, key); | ||
}); | ||
getInstanceMethods(cls).forEach((proto, key) => { | ||
assign(newClass.prototype, proto, key); | ||
}); | ||
} | ||
return newClass; | ||
}; | ||
@@ -108,7 +110,6 @@ const findMethod = (target, key) => { | ||
currentCls = Object.getPrototypeOf(currentCls); | ||
if (currentCls === Function.prototype) { | ||
if (currentCls === Function.prototype) | ||
break; | ||
} | ||
} | ||
return properties; | ||
}; |
{ | ||
"name": "accel-record-core", | ||
"version": "1.11.0", | ||
"version": "1.12.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "type": "module", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
AI-detected potential security risk
Supply chain riskAI has determined that this package may contain potential security issues or vulnerabilities.
Found 2 instances in 1 package
257189
137
6944
4
6