@spinajs/orm
Advanced tools
Comparing version 2.0.39 to 2.0.44
import { Container, Constructor, IContainer } from '@spinajs/di'; | ||
import { ColumnType, QueryMethod, SordOrder, WhereBoolean, SqlOperator } from './enums'; | ||
import { IColumnsBuilder, ICompilerOutput, ILimitBuilder, IOrderByBuilder, IQueryBuilder, IQueryLimit, ISort, IWhereBuilder, QueryContext, IJoinBuilder, IBuilderMiddleware, IWithRecursiveBuilder, ReferentialAction, IGroupByBuilder, IUpdateResult, DefaultValueBuilder, ColumnAlterationType, ISelectBuilderExtensions, QueryMiddleware } from './interfaces'; | ||
import { IColumnsBuilder, ICompilerOutput, ILimitBuilder, IOrderByBuilder, IQueryBuilder, IQueryLimit, ISort, IWhereBuilder, QueryContext, IJoinBuilder, IBuilderMiddleware, IWithRecursiveBuilder, ReferentialAction, IGroupByBuilder, IUpdateResult, DefaultValueBuilder, ColumnAlterationType, QueryMiddleware } from './interfaces'; | ||
import { ColumnStatement, IQueryStatement, RawQueryStatement, Wrap } from './statements'; | ||
@@ -23,3 +23,3 @@ import { PartialModel, PickRelations, WhereFunction } from './types'; | ||
} | ||
export interface SelectQueryBuilder<T> extends IColumnsBuilder, IOrderByBuilder, ILimitBuilder<T>, IWhereBuilder<T>, IJoinBuilder, IWithRecursiveBuilder, IGroupByBuilder, ISelectBuilderExtensions { | ||
export interface SelectQueryBuilder<T> extends IColumnsBuilder, IOrderByBuilder, ILimitBuilder<T>, IWhereBuilder<T>, IJoinBuilder, IWithRecursiveBuilder, IGroupByBuilder { | ||
} | ||
@@ -263,2 +263,4 @@ export declare class Builder<T = any> implements PromiseLike<T> { | ||
} | ||
export declare class SelectQueryBuilderC<T = any> extends SelectQueryBuilder<T> { | ||
} | ||
export declare class DeleteQueryBuilder<T> extends QueryBuilder<IUpdateResult> { | ||
@@ -265,0 +267,0 @@ /** |
@@ -36,3 +36,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SchemaQueryBuilder = exports.ScheduleQueryBuilder = exports.DropEventQueryBuilder = exports.EventQueryBuilder = exports.EventIntervalDesc = exports.CloneTableQueryBuilder = exports.TruncateTableQueryBuilder = exports.TableQueryBuilder = exports.AlterTableQueryBuilder = exports.DropTableQueryBuilder = exports.TableExistsQueryBuilder = exports.AlterColumnQueryBuilder = exports.ColumnQueryBuilder = exports.ForeignKeyBuilder = exports.IndexQueryBuilder = exports.InsertQueryBuilder = exports.UpdateQueryBuilder = exports.OnDuplicateQueryBuilder = exports.DeleteQueryBuilder = exports.SelectQueryBuilder = exports.WhereBuilder = exports.WithRecursiveBuilder = exports.JoinBuilder = exports.GroupByBuilder = exports.RawQuery = exports.ColumnsBuilder = exports.OrderByBuilder = exports.LimitBuilder = exports.QueryBuilder = exports.Builder = void 0; | ||
exports.SchemaQueryBuilder = exports.ScheduleQueryBuilder = exports.DropEventQueryBuilder = exports.EventQueryBuilder = exports.EventIntervalDesc = exports.CloneTableQueryBuilder = exports.TruncateTableQueryBuilder = exports.TableQueryBuilder = exports.AlterTableQueryBuilder = exports.DropTableQueryBuilder = exports.TableExistsQueryBuilder = exports.AlterColumnQueryBuilder = exports.ColumnQueryBuilder = exports.ForeignKeyBuilder = exports.IndexQueryBuilder = exports.InsertQueryBuilder = exports.UpdateQueryBuilder = exports.OnDuplicateQueryBuilder = exports.DeleteQueryBuilder = exports.SelectQueryBuilderC = exports.SelectQueryBuilder = exports.WhereBuilder = exports.WithRecursiveBuilder = exports.JoinBuilder = exports.GroupByBuilder = exports.RawQuery = exports.ColumnsBuilder = exports.OrderByBuilder = exports.LimitBuilder = exports.QueryBuilder = exports.Builder = void 0; | ||
/* eslint-disable prettier/prettier */ | ||
@@ -800,2 +800,5 @@ const di_1 = require("@spinajs/di"); | ||
exports.SelectQueryBuilder = SelectQueryBuilder; | ||
class SelectQueryBuilderC extends SelectQueryBuilder { | ||
} | ||
exports.SelectQueryBuilderC = SelectQueryBuilderC; | ||
class DeleteQueryBuilder extends QueryBuilder { | ||
@@ -802,0 +805,0 @@ constructor(container, driver, model) { |
@@ -558,5 +558,5 @@ import { Op } from './enums'; | ||
/** | ||
* Dummy interface for allowing to add extensions for builder via declaration merging & mixins | ||
* Dummy abstract class for allowing to add extensions for builder via declaration merging & mixins | ||
*/ | ||
export interface ISelectBuilderExtensions { | ||
export interface ISelectBuilderExtensions<T> { | ||
} | ||
@@ -595,3 +595,3 @@ export interface IJoinBuilder { | ||
} | ||
export interface ISelectQueryBuilder<T> extends IColumnsBuilder, IOrderByBuilder, ILimitBuilder<T>, IWhereBuilder<T>, IJoinBuilder, IWithRecursiveBuilder, IGroupByBuilder { | ||
export interface ISelectQueryBuilder<T> extends IColumnsBuilder, IOrderByBuilder, ILimitBuilder<T>, IWhereBuilder<T>, IJoinBuilder, IWithRecursiveBuilder, IGroupByBuilder, PromiseLike<T> { | ||
min(column: string, as?: string): this; | ||
@@ -598,0 +598,0 @@ max(column: string, as?: string): this; |
@@ -232,2 +232,10 @@ import { PickRelations } from './types'; | ||
/** | ||
* | ||
* Shorthand for inserting model when no primary key exists, or update | ||
* its value in db if primary key is set | ||
* | ||
* @param insertBehaviour - insert mode | ||
*/ | ||
insertOrUpdate(insertBehaviour?: InsertBehaviour): Promise<void>; | ||
/** | ||
* Gets model data from database and returns as fresh instance. | ||
@@ -234,0 +242,0 @@ * |
@@ -338,3 +338,2 @@ "use strict"; | ||
async archive() { | ||
const { query } = this.createUpdateQuery(); | ||
if (this.ModelDescriptor.Archived) { | ||
@@ -346,2 +345,3 @@ this[this.ModelDescriptor.Archived.ArchivedAt] = luxon_1.DateTime.now(); | ||
} | ||
const { query } = this.createUpdateQuery(); | ||
await query.update(this.toSql()).where(this.PrimaryKeyName, this.PrimaryKeyValue); | ||
@@ -386,2 +386,17 @@ } | ||
/** | ||
* | ||
* Shorthand for inserting model when no primary key exists, or update | ||
* its value in db if primary key is set | ||
* | ||
* @param insertBehaviour - insert mode | ||
*/ | ||
async insertOrUpdate(insertBehaviour = interfaces_1.InsertBehaviour.None) { | ||
if (this.PrimaryKeyValue) { | ||
await this.update(); | ||
} | ||
else { | ||
await this.insert(insertBehaviour); | ||
} | ||
} | ||
/** | ||
* Gets model data from database and returns as fresh instance. | ||
@@ -388,0 +403,0 @@ * |
@@ -6,2 +6,3 @@ import { IRelationDescriptor, IModelDescriptor, InsertBehaviour, ForwardRefFunction, IBuilderMiddleware } from './interfaces'; | ||
import { Orm } from './orm'; | ||
import { OrmDriver } from './driver'; | ||
export interface IOrmRelation { | ||
@@ -103,3 +104,3 @@ /** | ||
protected owner: O; | ||
protected model: Constructor<R> | ForwardRefFunction; | ||
protected Model: Constructor<R> | ForwardRefFunction; | ||
protected Relation: IRelationDescriptor; | ||
@@ -109,3 +110,5 @@ TargetModelDescriptor: IModelDescriptor; | ||
Populated: boolean; | ||
constructor(owner: O, model: Constructor<R> | ForwardRefFunction, Relation: IRelationDescriptor, objects?: R[]); | ||
protected Driver: OrmDriver; | ||
protected IsModelAForwardRef: boolean; | ||
constructor(owner: O, Model: Constructor<R> | ForwardRefFunction, Relation: IRelationDescriptor, objects?: R[]); | ||
/** | ||
@@ -129,9 +132,36 @@ * Removes from relation & deletes from db | ||
empty(): void; | ||
abstract intersection(obj: R[], callback?: (a: R, b: R) => boolean): Promise<void>; | ||
abstract union(obj: R[], mode?: InsertBehaviour): Promise<void>; | ||
abstract diff(obj: R[], callback?: (a: R, b: R) => boolean): Promise<void>; | ||
abstract set(obj: R[]): Promise<void>; | ||
/** | ||
* Populates this relation | ||
* | ||
* Calculates intersection between data in this relation and provided dataset | ||
* It saves result to db | ||
* | ||
* @param dataset - dataset to compare | ||
* @param callback - function to compare models, if not set it is compared by primary key value | ||
*/ | ||
abstract intersection(dataset: R[], callback?: (a: R, b: R) => boolean): Promise<void>; | ||
/** | ||
* Adds all items to this relation & adds to database | ||
* | ||
* @param dataset - data to add | ||
* @param mode - insert mode | ||
*/ | ||
abstract union(dataset: R[], mode?: InsertBehaviour): Promise<void>; | ||
/** | ||
* | ||
* Calculates difference between data in this relation and provides set. Result is saved to db. | ||
* | ||
* @param dataset - data to compare | ||
* @param callback - function to compare objects, if none provideded - primary key value is used | ||
*/ | ||
abstract diff(dataset: R[], callback?: (a: R, b: R) => boolean): Promise<void>; | ||
/** | ||
* | ||
* Clears data and replace it with new dataset. | ||
* | ||
* @param dataset - data for replace. | ||
*/ | ||
abstract set(dataset: R[]): Promise<void>; | ||
/** | ||
* Populates this relation ( loads all data related to owner of this relation) | ||
*/ | ||
populate(callback?: (this: SelectQueryBuilder<this>) => void): Promise<void>; | ||
@@ -148,3 +178,4 @@ } | ||
export declare class OneToManyRelationList<T extends ModelBase, O extends ModelBase> extends Relation<T, O> { | ||
diff(obj: T[], callback?: (a: T, b: T) => boolean): Promise<void>; | ||
protected deleteRelationData(data: T[]): Promise<void>; | ||
diff(dataset: T[], callback?: (a: T, b: T) => boolean): Promise<void>; | ||
set(obj: T[]): Promise<void>; | ||
@@ -151,0 +182,0 @@ intersection(obj: T[], callback?: (a: T, b: T) => boolean): Promise<void>; |
@@ -496,6 +496,6 @@ "use strict"; | ||
class Relation extends Array { | ||
constructor(owner, model, Relation, objects) { | ||
constructor(owner, Model, Relation, objects) { | ||
super(); | ||
this.owner = owner; | ||
this.model = model; | ||
this.Model = Model; | ||
this.Relation = Relation; | ||
@@ -506,4 +506,8 @@ this.Populated = false; | ||
} | ||
this.TargetModelDescriptor = (0, model_1.extractModelDescriptor)(model); | ||
this.TargetModelDescriptor = (0, model_1.extractModelDescriptor)(Model); | ||
this.Orm = di_1.DI.get(orm_1.Orm); | ||
if (this.TargetModelDescriptor) { | ||
this.Driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
} | ||
this.IsModelAForwardRef = !(0, di_1.isConstructor)(this.Model); | ||
} | ||
@@ -520,3 +524,3 @@ /** | ||
/** | ||
* Populates this relation | ||
* Populates this relation ( loads all data related to owner of this relation) | ||
*/ | ||
@@ -553,8 +557,4 @@ async populate(callback) { | ||
const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue); | ||
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
const jmodelDescriptor = (0, model_1.extractModelDescriptor)(this.Relation.JunctionModel); | ||
if (!driver) { | ||
throw new exceptions_1.InvalidArgument(`connection ${this.TargetModelDescriptor.Connection} not exists`); | ||
} | ||
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.JunctionModel]) | ||
const query = this.Driver.del() | ||
.from(jmodelDescriptor.TableName) | ||
@@ -565,2 +565,5 @@ .where(function () { | ||
}); | ||
if (this.Driver.Options.Database) { | ||
query.database(this.Driver.Options.Database); | ||
} | ||
await query; | ||
@@ -585,74 +588,47 @@ _.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1); | ||
class OneToManyRelationList extends Relation { | ||
async diff(obj, callback) { | ||
const result = callback ? _.differenceWith(obj, [...this], callback) : _.differenceBy(obj, [...this], this.TargetModelDescriptor.PrimaryKey); | ||
const result2 = callback ? _.differenceWith([...this], obj, callback) : _.differenceBy([...this], obj, this.TargetModelDescriptor.PrimaryKey); | ||
const finalDiff = [...result, ...result2]; | ||
async deleteRelationData(data) { | ||
if (data.length === 0) { | ||
return; | ||
} | ||
const self = this; | ||
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
const relData = finalDiff.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue); | ||
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () { | ||
if (relData.length !== 0) { | ||
this.whereNotIn(self.Relation.PrimaryKey, relData); | ||
} | ||
const query = this.Driver.del() | ||
.from(this.TargetModelDescriptor.TableName) | ||
.andWhere(function () { | ||
this.whereNotIn(self.Relation.PrimaryKey, data.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue)); | ||
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue); | ||
}); | ||
query.setTable(this.TargetModelDescriptor.TableName); | ||
if (driver.Options.Database) { | ||
query.database(driver.Options.Database); | ||
if (this.Driver.Options.Database) { | ||
query.database(this.Driver.Options.Database); | ||
} | ||
await query; | ||
this.empty(); | ||
await this.add(finalDiff), interfaces_1.InsertBehaviour.InsertOrUpdate; | ||
} | ||
async diff(dataset, callback) { | ||
// calculate difference between this data in relation and dataset ( objects from this relation) | ||
const result = callback ? _.differenceWith(dataset, [...this], callback) : _.differenceBy(dataset, [...this], this.TargetModelDescriptor.PrimaryKey); | ||
// calculate difference between dataset and data in this relation ( objects from dataset ) | ||
const result2 = callback ? _.differenceWith([...this], dataset, callback) : _.differenceBy([...this], dataset, this.TargetModelDescriptor.PrimaryKey); | ||
// combine difference from two sets | ||
const finalDiff = [...result, ...result2]; | ||
await this.deleteRelationData(finalDiff); | ||
await this.add(finalDiff, interfaces_1.InsertBehaviour.InsertOrUpdate); | ||
} | ||
async set(obj) { | ||
const self = this; | ||
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () { | ||
const relData = obj.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue); | ||
if (relData.length !== 0) { | ||
this.whereNotIn(self.Relation.PrimaryKey, relData); | ||
} | ||
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue); | ||
}); | ||
query.setTable(this.TargetModelDescriptor.TableName); | ||
if (driver.Options.Database) { | ||
query.database(driver.Options.Database); | ||
} | ||
await query; | ||
this.empty(); | ||
await this.deleteRelationData(obj); | ||
await this.add(obj, interfaces_1.InsertBehaviour.InsertOrUpdate); | ||
} | ||
async intersection(obj, callback) { | ||
const self = this; | ||
const result = callback ? _.intersectionWith(obj, [...this], callback) : _.intersectionBy(obj, [...this], this.TargetModelDescriptor.PrimaryKey); | ||
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).andWhere(function () { | ||
const relData = result.filter((x) => x.PrimaryKeyValue).map((x) => x.PrimaryKeyValue); | ||
if (relData.length !== 0) { | ||
this.whereNotIn(self.Relation.PrimaryKey, relData); | ||
} | ||
this.where(self.Relation.ForeignKey, self.owner.PrimaryKeyValue); | ||
}); | ||
query.setTable(this.TargetModelDescriptor.TableName); | ||
if (driver.Options.Database) { | ||
query.database(driver.Options.Database); | ||
} | ||
await query; | ||
this.empty(); | ||
await this.deleteRelationData(result); | ||
await this.add(result, interfaces_1.InsertBehaviour.InsertOrUpdate); | ||
} | ||
async union(obj, mode) { | ||
await this.add(obj, mode); | ||
await this.add(obj, mode !== null && mode !== void 0 ? mode : interfaces_1.InsertBehaviour.InsertOrIgnore); | ||
} | ||
async remove(obj) { | ||
const data = (Array.isArray(obj) ? obj : [obj]).map((d) => d.PrimaryKeyValue); | ||
const driver = this.Orm.Connections.get(this.TargetModelDescriptor.Connection); | ||
if (!driver) { | ||
throw new exceptions_1.InvalidArgument(`connection ${this.TargetModelDescriptor.Connection} not exists`); | ||
const query = this.Driver.del().whereIn(this.Relation.ForeignKey, data).setTable(this.TargetModelDescriptor.TableName); | ||
if (this.Driver.Options.Database) { | ||
query.database(this.Driver.Options.Database); | ||
} | ||
const query = driver.Container.resolve(builders_1.DeleteQueryBuilder, [driver, this.Relation.TargetModel]).whereIn(this.Relation.ForeignKey, data); | ||
query.setTable(this.TargetModelDescriptor.TableName); | ||
if (driver.Options.Database) { | ||
query.database(driver.Options.Database); | ||
} | ||
await query; | ||
@@ -667,6 +643,6 @@ _.remove(this, (o) => data.indexOf(o.PrimaryKeyValue) !== -1); | ||
} | ||
if (_.isFunction(this.model)) { | ||
return new (this.model())(x); | ||
if (this.IsModelAForwardRef) { | ||
new (this.Model())(x); | ||
} | ||
return new this.model(x); | ||
return new this.Model(x); | ||
}); | ||
@@ -676,9 +652,4 @@ data.forEach((d) => { | ||
}); | ||
for (const m of data) { | ||
if (m.PrimaryKeyValue) { | ||
await m.update(); | ||
} | ||
else { | ||
await m.insert(mode); | ||
} | ||
for (const m of tInsert) { | ||
await m.insertOrUpdate(mode); | ||
} | ||
@@ -685,0 +656,0 @@ this.push(...tInsert); |
{ | ||
"name": "@spinajs/orm", | ||
"version": "2.0.39", | ||
"version": "2.0.44", | ||
"description": "framework orm module", | ||
@@ -44,3 +44,3 @@ "main": "lib/index.js", | ||
"@types/lodash": "4.14.182", | ||
"@types/luxon": "2.4.0", | ||
"@types/luxon": "^3.2.0", | ||
"@types/node": "^16.11.44", | ||
@@ -50,15 +50,14 @@ "@types/uuid": "8.3.4" | ||
"dependencies": { | ||
"@spinajs/configuration": "^2.0.39", | ||
"@spinajs/di": "^2.0.39", | ||
"@spinajs/configuration": "^2.0.44", | ||
"@spinajs/di": "^2.0.44", | ||
"@spinajs/exceptions": "^2.0.39", | ||
"@spinajs/internal-logger": "^2.0.39", | ||
"@spinajs/log": "^2.0.39", | ||
"@spinajs/reflection": "^2.0.39", | ||
"@spinajs/internal-logger": "^2.0.44", | ||
"@spinajs/log": "^2.0.44", | ||
"@spinajs/reflection": "^2.0.44", | ||
"glob": "^7.1.4", | ||
"helmet": "^3.23.0", | ||
"lodash": "^4.17.14", | ||
"luxon": "^2.2.0", | ||
"luxon": "^3.2.1", | ||
"uuid": "^8.3.2" | ||
}, | ||
"gitHead": "002dc553b0ffffd72193d0121ac425a4083bc9ee" | ||
"gitHead": "1857a6e3626e0fed22ffb0b44b48d587c79898db" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
10
7409
425263
+ Added@spinajs/configuration@2.0.315(transitive)
+ Added@spinajs/configuration-common@2.0.315(transitive)
+ Added@spinajs/di@2.0.315(transitive)
+ Added@spinajs/exceptions@2.0.315(transitive)
+ Added@spinajs/internal-logger@2.0.315(transitive)
+ Added@spinajs/log@2.0.315(transitive)
+ Added@spinajs/log-common@2.0.315(transitive)
+ Added@spinajs/reflection@2.0.315(transitive)
+ Added@spinajs/util@2.0.315(transitive)
- Removedhelmet@^3.23.0
- Removed@spinajs/configuration@2.0.314(transitive)
- Removed@spinajs/configuration-common@2.0.314(transitive)
- Removed@spinajs/di@2.0.314(transitive)
- Removed@spinajs/exceptions@2.0.314(transitive)
- Removed@spinajs/internal-logger@2.0.314(transitive)
- Removed@spinajs/log@2.0.314(transitive)
- Removed@spinajs/log-common@2.0.314(transitive)
- Removed@spinajs/reflection@2.0.314(transitive)
- Removed@spinajs/util@2.0.314(transitive)
- Removedbowser@2.9.0(transitive)
- Removedcamelize@1.0.0(transitive)
- Removedcontent-security-policy-builder@2.1.0(transitive)
- Removeddasherize@2.0.0(transitive)
- Removeddepd@2.0.0(transitive)
- Removeddont-sniff-mimetype@1.1.0(transitive)
- Removedfeature-policy@0.3.0(transitive)
- Removedhelmet@3.23.3(transitive)
- Removedhelmet-crossdomain@0.4.0(transitive)
- Removedhelmet-csp@2.10.0(transitive)
- Removedhide-powered-by@1.1.0(transitive)
- Removedhpkp@2.0.0(transitive)
- Removedhsts@2.2.0(transitive)
- Removedluxon@2.5.2(transitive)
- Removednocache@2.1.0(transitive)
- Removedreferrer-policy@1.2.0(transitive)
- Removedx-xss-protection@1.3.0(transitive)
Updated@spinajs/di@^2.0.44
Updated@spinajs/log@^2.0.44
Updated@spinajs/reflection@^2.0.44
Updatedluxon@^3.2.1