@spinajs/orm
Advanced tools
Comparing version 1.2.77 to 1.2.79
@@ -1,3 +0,3 @@ | ||
import { Container, Constructor } from '@spinajs/di'; | ||
import { QueryMethod, SORT_ORDER, WhereBoolean, WhereOperators } from './enums'; | ||
import { Container, Constructor, IContainer } from '@spinajs/di'; | ||
import { ColumnType, QueryMethod, SORT_ORDER, WhereBoolean, SqlOperator } from './enums'; | ||
import { IColumnsBuilder, ICompilerOutput, ILimitBuilder, IOrderByBuilder, IQueryBuilder, IQueryLimit, ISort, IWhereBuilder, QueryContext, IJoinBuilder, IBuilderMiddleware, IWithRecursiveBuilder, ReferentialAction, IGroupByBuilder } from './interfaces'; | ||
@@ -9,2 +9,3 @@ import { ColumnStatement, IQueryStatement, WrapStatement } from './statements'; | ||
import { OrmRelation, IOrmRelation } from './relations'; | ||
import { ColumnAlterationType, IUpdateResult } from '.'; | ||
/** | ||
@@ -25,17 +26,20 @@ * Trick typescript by using the inbuilt interface inheritance and declaration merging | ||
} | ||
export declare class Builder<T = any> { | ||
export declare class Builder<T = any> implements PromiseLike<T> { | ||
protected _driver: OrmDriver; | ||
protected _container: Container; | ||
protected _container: IContainer; | ||
protected _model?: Constructor<ModelBase>; | ||
protected _nonSelect: boolean; | ||
protected _queryContext: QueryContext; | ||
protected _middlewares: IBuilderMiddleware[]; | ||
protected _middlewares: IBuilderMiddleware<T>[]; | ||
protected _asRaw: boolean; | ||
constructor(container: Container, driver: OrmDriver, model?: Constructor<ModelBase>); | ||
middleware(middleware: IBuilderMiddleware): this; | ||
QueryContext: QueryContext; | ||
get Driver(): OrmDriver; | ||
get Container(): IContainer; | ||
get Model(): Constructor<ModelBase> | undefined; | ||
constructor(container: IContainer, driver: OrmDriver, model?: Constructor<ModelBase>); | ||
then<TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; | ||
middleware(middleware: IBuilderMiddleware<T>): this; | ||
/** | ||
* Builds query that is ready to use in DB | ||
*/ | ||
toDB(): ICompilerOutput; | ||
then(resolve: (rows: any[]) => void, reject: (err: Error) => void): Promise<T>; | ||
toDB(): ICompilerOutput | ICompilerOutput[]; | ||
} | ||
@@ -50,4 +54,4 @@ /** | ||
protected _tableAlias: string; | ||
protected _schema: string; | ||
constructor(container: Container, driver: OrmDriver, model?: Constructor<ModelBase>); | ||
protected _database: string; | ||
constructor(container: IContainer, driver: OrmDriver, model?: Constructor<ModelBase>); | ||
/** | ||
@@ -70,9 +74,9 @@ * SQL table name that query is executed on | ||
*/ | ||
get Schema(): string; | ||
get Database(): string; | ||
/** | ||
* Sets schema to this query. | ||
* | ||
* @param schema - schema or database name in database | ||
* @param database - schema or database name in database | ||
*/ | ||
schema(schema: string): this; | ||
database(database: string): this; | ||
/** | ||
@@ -99,3 +103,2 @@ * Sets table that query is executed on | ||
export declare class LimitBuilder implements ILimitBuilder { | ||
protected _fail: boolean; | ||
protected _first: boolean; | ||
@@ -108,2 +111,4 @@ protected _limit: IQueryLimit; | ||
firstOrFail(): Promise<any>; | ||
orThrow(error: Error): Promise<any>; | ||
firstOrThrow(error: Error): Promise<any>; | ||
getLimits(): IQueryLimit; | ||
@@ -190,3 +195,3 @@ } | ||
constructor(container: Container, tableAlias?: string); | ||
where(column: string | boolean | WhereFunction | RawQuery | WrapStatement | {}, operator?: WhereOperators | any, value?: any): this; | ||
where(column: string | boolean | WhereFunction | RawQuery | WrapStatement | {}, operator?: SqlOperator | any, value?: any): this; | ||
orWhere(column: string | boolean | WhereFunction | {}, ..._args: any[]): this; | ||
@@ -238,3 +243,3 @@ andWhere(column: string | boolean | WhereFunction | {}, ..._args: any[]): this; | ||
get Relations(): IOrmRelation[]; | ||
constructor(container: Container, driver: OrmDriver, model: Constructor<any>, owner?: IOrmRelation); | ||
constructor(container: IContainer, driver: OrmDriver, model?: Constructor<any>, owner?: IOrmRelation); | ||
asRaw<T>(): Promise<T>; | ||
@@ -252,6 +257,6 @@ setAlias(alias: string): this; | ||
toDB(): ICompilerOutput; | ||
then(resolve: (rows: any[]) => void, reject: (err: Error) => void): Promise<T>; | ||
then<TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; | ||
execute(): Promise<T>; | ||
} | ||
export declare class DeleteQueryBuilder extends QueryBuilder { | ||
export declare class DeleteQueryBuilder extends QueryBuilder<IUpdateResult> { | ||
/** | ||
@@ -262,9 +267,6 @@ * where query props | ||
protected _boolean: WhereBoolean; | ||
protected _truncate: boolean; | ||
protected _limit: IQueryLimit; | ||
get Truncate(): boolean; | ||
private this; | ||
constructor(container: Container, driver: OrmDriver, model: Constructor<any>); | ||
toDB(): ICompilerOutput; | ||
truncate(): this; | ||
} | ||
@@ -275,4 +277,4 @@ export declare class OnDuplicateQueryBuilder { | ||
protected _columnsToUpdate: Array<string | RawQuery>; | ||
protected _container: Container; | ||
constructor(container: Container, insertQueryBuilder: InsertQueryBuilder, column?: string | string[]); | ||
protected _container: IContainer; | ||
constructor(container: IContainer, insertQueryBuilder: InsertQueryBuilder, column?: string | string[]); | ||
getColumn(): string[]; | ||
@@ -282,6 +284,6 @@ getColumnsToUpdate(): (string | RawQuery)[]; | ||
update(columns: string[] | RawQuery[]): this; | ||
then(resolve: (rows: any[]) => void, reject: (err: Error) => void): Promise<any>; | ||
then<TResult1, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; | ||
toDB(): ICompilerOutput; | ||
} | ||
export declare class UpdateQueryBuilder extends QueryBuilder { | ||
export declare class UpdateQueryBuilder extends QueryBuilder<IUpdateResult> { | ||
/** | ||
@@ -300,3 +302,3 @@ * where query props | ||
} | ||
export declare class InsertQueryBuilder extends QueryBuilder { | ||
export declare class InsertQueryBuilder extends QueryBuilder<IUpdateResult> { | ||
DuplicateQueryBuilder: OnDuplicateQueryBuilder; | ||
@@ -306,5 +308,9 @@ protected _values: any[][]; | ||
protected _ignore: boolean; | ||
protected _update: boolean; | ||
protected _replace: boolean; | ||
this: this; | ||
get Values(): any[][]; | ||
get Ignore(): boolean; | ||
get Update(): boolean; | ||
get Replace(): boolean; | ||
constructor(container: Container, driver: OrmDriver, model: Constructor<any>); | ||
@@ -314,3 +320,4 @@ /** | ||
*/ | ||
ignore(): this; | ||
orIgnore(): this; | ||
orReplace(): this; | ||
values(data: {} | Array<{}>): this; | ||
@@ -385,5 +392,5 @@ into(table: string, schema?: string): this; | ||
NotNull: boolean; | ||
Type: string; | ||
Type: ColumnType; | ||
Args: any[]; | ||
constructor(name: string, type: string, ...args: any[]); | ||
constructor(name: string, type: ColumnType, ...args: any[]); | ||
notNull(): this; | ||
@@ -399,2 +406,12 @@ unique(): this; | ||
} | ||
export declare class AlterColumnQueryBuilder extends ColumnQueryBuilder { | ||
AlterType: ColumnAlterationType; | ||
AfterColumn: string; | ||
OldName: string; | ||
constructor(name: string, type: ColumnType, ...args: any[]); | ||
addColumn(): this; | ||
modify(): this; | ||
rename(newName: string): this; | ||
after(columnName: string): this; | ||
} | ||
export declare class TableExistsQueryBuilder extends QueryBuilder { | ||
@@ -404,2 +421,43 @@ constructor(container: Container, driver: OrmDriver, name: string); | ||
} | ||
export declare class AlterTableQueryBuilder extends QueryBuilder { | ||
protected _columns: ColumnQueryBuilder[]; | ||
NewTableName: string; | ||
DroppedColumns: string[]; | ||
get Columns(): ColumnQueryBuilder[]; | ||
constructor(container: Container, driver: OrmDriver, name: string); | ||
int: (name: string) => AlterColumnQueryBuilder; | ||
bigint: (name: string) => AlterColumnQueryBuilder; | ||
tinyint: (name: string) => AlterColumnQueryBuilder; | ||
smallint: (name: string) => AlterColumnQueryBuilder; | ||
mediumint: (name: string) => AlterColumnQueryBuilder; | ||
text: (name: string) => AlterColumnQueryBuilder; | ||
tinytext: (name: string) => AlterColumnQueryBuilder; | ||
mediumtext: (name: string) => AlterColumnQueryBuilder; | ||
smalltext: (name: string) => AlterColumnQueryBuilder; | ||
longtext: (name: string) => AlterColumnQueryBuilder; | ||
string: (name: string, length?: number) => AlterColumnQueryBuilder; | ||
float: (name: string, precision?: number, scale?: number) => AlterColumnQueryBuilder; | ||
double: (name: string, precision?: number, scale?: number) => AlterColumnQueryBuilder; | ||
decimal: (name: string, precision?: number, scale?: number) => AlterColumnQueryBuilder; | ||
boolean: (name: string) => AlterColumnQueryBuilder; | ||
bit: (name: string) => AlterColumnQueryBuilder; | ||
date: (name: string) => AlterColumnQueryBuilder; | ||
dateTime: (name: string) => AlterColumnQueryBuilder; | ||
time: (name: string) => AlterColumnQueryBuilder; | ||
timestamp: (name: string) => AlterColumnQueryBuilder; | ||
enum: (name: string, values: any[]) => AlterColumnQueryBuilder; | ||
json: (name: string) => AlterColumnQueryBuilder; | ||
binary: (name: string, size: number) => AlterColumnQueryBuilder; | ||
tinyblob: (name: string) => AlterColumnQueryBuilder; | ||
mediumblob: (name: string) => AlterColumnQueryBuilder; | ||
longblob: (name: string) => AlterColumnQueryBuilder; | ||
/** | ||
* Renames table | ||
* | ||
* @param newTableName - new table name | ||
*/ | ||
rename(newTableName: string): void; | ||
dropColumn(column: string): void; | ||
toDB(): ICompilerOutput[]; | ||
} | ||
export declare class TableQueryBuilder extends QueryBuilder { | ||
@@ -433,2 +491,3 @@ int: (name: string) => ColumnQueryBuilder; | ||
ifExists(): TableQueryBuilder; | ||
temporary(): TableQueryBuilder; | ||
set: (name: string, allowed: string[]) => ColumnQueryBuilder; | ||
@@ -442,3 +501,5 @@ get Columns(): ColumnQueryBuilder[]; | ||
protected _checkExists: boolean; | ||
protected _temporary: boolean; | ||
get CheckExists(): boolean; | ||
get Temporary(): boolean; | ||
constructor(container: Container, driver: OrmDriver, name: string); | ||
@@ -451,2 +512,38 @@ increments(name: string): ColumnQueryBuilder; | ||
} | ||
export declare class TruncateTableQueryBuilder extends QueryBuilder { | ||
protected container: Container; | ||
protected driver: OrmDriver; | ||
constructor(container: Container, driver: OrmDriver); | ||
toDB(): ICompilerOutput; | ||
} | ||
export declare class CloneTableQueryBuilder extends QueryBuilder { | ||
protected container: Container; | ||
protected driver: OrmDriver; | ||
protected _cloneSrc: string; | ||
protected _temporary: boolean; | ||
protected _shallow: boolean; | ||
protected _filter: SelectQueryBuilder; | ||
get CloneSource(): string; | ||
get Temporary(): boolean; | ||
get Shallow(): boolean; | ||
get Filter(): SelectQueryBuilder<any>; | ||
constructor(container: Container, driver: OrmDriver); | ||
/** | ||
* Clones table structure without data | ||
* Shorthand for createTable(( table) => table.clone("new")); | ||
* | ||
* @param srcTable - source table name | ||
* @param newTable - target table name | ||
*/ | ||
shallowClone(srcTable: string, newTable: string): this; | ||
/** | ||
* Clones table with data | ||
* | ||
* @param srcTable - source table name | ||
* @param newTable - target table name | ||
* @param filter - data filter, set null if all data is to be cloned | ||
*/ | ||
deepClone(srcTable: string, newTable: string, filter?: (query: SelectQueryBuilder) => void): Promise<any>; | ||
toDB(): ICompilerOutput[]; | ||
} | ||
export declare class SchemaQueryBuilder { | ||
@@ -457,3 +554,5 @@ protected container: Container; | ||
createTable(name: string, callback: (table: TableQueryBuilder) => void): TableQueryBuilder; | ||
tableExists(name: string): Promise<boolean>; | ||
cloneTable(callback: (clone: CloneTableQueryBuilder) => void): CloneTableQueryBuilder; | ||
alterTable(name: string, callback: (table: AlterTableQueryBuilder) => void): AlterTableQueryBuilder; | ||
tableExists(name: string, schema?: string): Promise<boolean>; | ||
} |
"use strict"; | ||
/* eslint-disable prettier/prettier */ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -9,2 +25,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __metadata = (this && this.__metadata) || function (k, v) { | ||
@@ -15,6 +38,7 @@ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SchemaQueryBuilder = exports.TableQueryBuilder = exports.TableExistsQueryBuilder = 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.CloneTableQueryBuilder = exports.TruncateTableQueryBuilder = exports.TableQueryBuilder = exports.AlterTableQueryBuilder = 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; | ||
const di_1 = require("@spinajs/di"); | ||
const exceptions_1 = require("@spinajs/exceptions"); | ||
const _ = require("lodash"); | ||
const exceptions_2 = require("./exceptions"); | ||
const _ = __importStar(require("lodash")); | ||
const typescript_mix_1 = require("typescript-mix"); | ||
@@ -30,3 +54,3 @@ const enums_1 = require("./enums"); | ||
function isWhereOperator(val) { | ||
return _.isString(val) && Object.values(enums_1.WhereOperators).includes(val.toLowerCase()); | ||
return _.isString(val) && Object.values(enums_1.SqlOperator).includes(val.toLowerCase()); | ||
} | ||
@@ -42,67 +66,84 @@ let Builder = class Builder { | ||
} | ||
middleware(middleware) { | ||
this._middlewares.push(middleware); | ||
return this; | ||
get Driver() { | ||
return this._driver; | ||
} | ||
/** | ||
* Builds query that is ready to use in DB | ||
*/ | ||
toDB() { | ||
throw new exceptions_1.MethodNotImplemented(); | ||
get Container() { | ||
return this._container; | ||
} | ||
then(resolve, reject) { | ||
const compiled = this.toDB(); | ||
return this._driver | ||
.execute(compiled.expression, compiled.bindings, this._queryContext) | ||
.then((result) => { | ||
try { | ||
if (this._asRaw) { | ||
resolve(result); | ||
return; | ||
} | ||
if (this._model && !this._nonSelect) { | ||
get Model() { | ||
return this._model; | ||
} | ||
then(onfulfilled, onrejected) { | ||
const execute = (compiled) => { | ||
return this._driver | ||
.execute(compiled.expression, compiled.bindings, this.QueryContext) | ||
.then((result) => { | ||
try { | ||
if (this._asRaw) { | ||
onfulfilled(result); | ||
return; | ||
} | ||
let transformedResult = result; | ||
if (this._middlewares.length > 0) { | ||
transformedResult = this._middlewares.reduce((_, current) => { | ||
return current.afterData(result); | ||
this._middlewares.forEach((m) => { | ||
Object.assign(transformedResult, m.afterQuery(transformedResult)); | ||
}); | ||
if (this._model && !this._nonSelect) { | ||
// TODO: rething this casting | ||
const models = transformedResult.map((r) => { | ||
let model = null; | ||
for (const middleware of this._middlewares.reverse()) { | ||
model = middleware.modelCreation(r); | ||
if (model !== null) { | ||
break; | ||
} | ||
} | ||
if (model === null) { | ||
model = new this._model(); | ||
model.hydrate(r); | ||
} | ||
return model; | ||
}); | ||
const afterMiddlewarePromises = this._middlewares.reduce((prev, current) => { | ||
return prev.concat([current.afterHydration(models)]); | ||
}, []); | ||
} | ||
const models = transformedResult.map((r) => { | ||
let model = null; | ||
for (const middleware of this._middlewares) { | ||
model = middleware.modelCreation(r); | ||
if (model !== null) { | ||
break; | ||
} | ||
if (this._middlewares.length > 0) { | ||
Promise.all(afterMiddlewarePromises).then(() => { | ||
onfulfilled(models); | ||
}, onrejected); | ||
} | ||
if (model === null) { | ||
model = new this._model(); | ||
model.hydrate(r); | ||
else { | ||
onfulfilled(models); | ||
} | ||
return model; | ||
}); | ||
const afterMiddlewarePromises = this._middlewares.reduce((prev, current) => { | ||
return prev.concat([current.afterHydration(models)]); | ||
}, []); | ||
if (this._middlewares.length > 0) { | ||
Promise.all(afterMiddlewarePromises).then(() => { | ||
resolve(models); | ||
}, reject); | ||
} | ||
else { | ||
resolve(models); | ||
onfulfilled(transformedResult); | ||
} | ||
} | ||
else { | ||
resolve(result); | ||
catch (err) { | ||
onrejected(err); | ||
} | ||
} | ||
catch (err) { | ||
reject(err); | ||
} | ||
}) | ||
.catch((err) => { | ||
reject(err); | ||
}); | ||
}) | ||
.catch((err) => { | ||
onrejected(err); | ||
}); | ||
}; | ||
const compiled = this.toDB(); | ||
if (Array.isArray(compiled)) { | ||
// TODO: rethink this cast | ||
return Promise.all(compiled.map((c) => execute(c))); | ||
} | ||
else { | ||
return execute(compiled); | ||
} | ||
} | ||
middleware(middleware) { | ||
this._middlewares.push(middleware); | ||
return this; | ||
} | ||
/** | ||
* Builds query that is ready to use in DB | ||
*/ | ||
toDB() { | ||
throw new exceptions_1.MethodNotImplemented(); | ||
} | ||
}; | ||
@@ -112,3 +153,3 @@ Builder = __decorate([ | ||
(0, di_1.Inject)(di_1.Container), | ||
__metadata("design:paramtypes", [di_1.Container, driver_1.OrmDriver, Object]) | ||
__metadata("design:paramtypes", [Object, driver_1.OrmDriver, Object]) | ||
], Builder); | ||
@@ -145,4 +186,4 @@ exports.Builder = Builder; | ||
*/ | ||
get Schema() { | ||
return this._schema; | ||
get Database() { | ||
return this._database; | ||
} | ||
@@ -152,9 +193,9 @@ /** | ||
* | ||
* @param schema - schema or database name in database | ||
* @param database - schema or database name in database | ||
*/ | ||
schema(schema) { | ||
if (!schema) { | ||
database(database) { | ||
if (!database) { | ||
throw new exceptions_1.InvalidArgument(`schema argument cannot be null or empty`); | ||
} | ||
this._schema = schema; | ||
this._database = database; | ||
return this; | ||
@@ -197,3 +238,3 @@ } | ||
(0, di_1.Inject)(di_1.Container), | ||
__metadata("design:paramtypes", [di_1.Container, driver_1.OrmDriver, Object]) | ||
__metadata("design:paramtypes", [Object, driver_1.OrmDriver, Object]) | ||
], QueryBuilder); | ||
@@ -203,3 +244,2 @@ exports.QueryBuilder = QueryBuilder; | ||
constructor() { | ||
this._fail = false; | ||
this._first = false; | ||
@@ -230,6 +270,19 @@ this._limit = { | ||
} | ||
firstOrFail() { | ||
this._fail = true; | ||
return this.first(); | ||
async firstOrFail() { | ||
return this.firstOrThrow(new exceptions_2.OrmException('not found')); | ||
} | ||
async orThrow(error) { | ||
const result = (await this); | ||
if (result === undefined || (Array.isArray(result) && result.length === 0)) { | ||
throw error; | ||
} | ||
return result; | ||
} | ||
async firstOrThrow(error) { | ||
const result = await this.first(); | ||
if (result === undefined) { | ||
throw error; | ||
} | ||
return result; | ||
} | ||
getLimits() { | ||
@@ -490,3 +543,3 @@ return this._limit; | ||
} | ||
self._statements.push(self._container.resolve(statements_1.WhereStatement, [c, enums_1.WhereOperators.EQ, v, self._tableAlias, this._container])); | ||
self._statements.push(self._container.resolve(statements_1.WhereStatement, [c, enums_1.SqlOperator.EQ, v, self._tableAlias, this._container])); | ||
return self; | ||
@@ -509,3 +562,3 @@ } | ||
if (v === null) { | ||
return o === enums_1.WhereOperators.NOT_NULL ? this.whereNotNull(c) : this.whereNull(c); | ||
return o === enums_1.SqlOperator.NOT_NULL ? this.whereNotNull(c) : this.whereNull(c); | ||
} | ||
@@ -526,3 +579,3 @@ self._statements.push(self._container.resolve(statements_1.WhereStatement, [c, o, v, self._tableAlias, this._container])); | ||
for (const key of Object.keys(obj)) { | ||
this.andWhere(key, enums_1.WhereOperators.EQ, obj[key]); | ||
this.andWhere(key, enums_1.SqlOperator.EQ, obj[key]); | ||
} | ||
@@ -532,11 +585,11 @@ return this; | ||
whereNotNull(column) { | ||
this._statements.push(this._container.resolve(statements_1.WhereStatement, [column, enums_1.WhereOperators.NOT_NULL, null, this._tableAlias])); | ||
this._statements.push(this._container.resolve(statements_1.WhereStatement, [column, enums_1.SqlOperator.NOT_NULL, null, this._tableAlias])); | ||
return this; | ||
} | ||
whereNull(column) { | ||
this._statements.push(this._container.resolve(statements_1.WhereStatement, [column, enums_1.WhereOperators.NULL, null, this._tableAlias])); | ||
this._statements.push(this._container.resolve(statements_1.WhereStatement, [column, enums_1.SqlOperator.NULL, null, this._tableAlias])); | ||
return this; | ||
} | ||
whereNot(column, val) { | ||
return this.where(column, enums_1.WhereOperators.NOT, val); | ||
return this.where(column, enums_1.SqlOperator.NOT, val); | ||
} | ||
@@ -609,3 +662,3 @@ whereIn(column, val) { | ||
this._nonSelect = false; | ||
this._queryContext = interfaces_1.QueryContext.Select; | ||
this.QueryContext = interfaces_1.QueryContext.Select; | ||
this._owner = owner; | ||
@@ -715,16 +768,21 @@ } | ||
} | ||
then(resolve, reject) { | ||
then(onfulfilled, onrejected) { | ||
return super.then((result) => { | ||
if (this._first) { | ||
if (this._fail && result.length === 0) { | ||
reject(new Error('empty results')); | ||
if (Array.isArray(result)) { | ||
if (result.length !== 0) { | ||
return onfulfilled(result ? result[0] : null); | ||
} | ||
else { | ||
return onfulfilled(undefined); | ||
} | ||
} | ||
else { | ||
resolve(result ? result[0] : null); | ||
return onfulfilled(result); | ||
} | ||
} | ||
else { | ||
resolve(result); | ||
return onfulfilled(result); | ||
} | ||
}, reject); | ||
}, onrejected); | ||
} | ||
@@ -743,3 +801,2 @@ async execute() { | ||
super(container, driver, model); | ||
this._truncate = false; | ||
this._method = enums_1.QueryMethod.DELETE; | ||
@@ -752,14 +809,7 @@ this._statements = []; | ||
}; | ||
this._queryContext = interfaces_1.QueryContext.Delete; | ||
this.QueryContext = interfaces_1.QueryContext.Delete; | ||
} | ||
get Truncate() { | ||
return this._truncate; | ||
} | ||
toDB() { | ||
return this._container.resolve(interfaces_1.DeleteQueryCompiler, [this]).compile(); | ||
} | ||
truncate() { | ||
this._truncate = true; | ||
return this; | ||
} | ||
} | ||
@@ -790,4 +840,4 @@ __decorate([ | ||
} | ||
then(resolve, reject) { | ||
return this._parent.then(resolve, reject); | ||
then(onfulfilled, onrejected) { | ||
return this._parent.then(onfulfilled, onrejected); | ||
} | ||
@@ -806,3 +856,3 @@ toDB() { | ||
this._statements = []; | ||
this._queryContext = interfaces_1.QueryContext.Update; | ||
this.QueryContext = interfaces_1.QueryContext.Update; | ||
} | ||
@@ -835,3 +885,3 @@ get Value() { | ||
this._values = []; | ||
this._queryContext = interfaces_1.QueryContext.Insert; | ||
this.QueryContext = interfaces_1.QueryContext.Insert; | ||
} | ||
@@ -844,9 +894,19 @@ get Values() { | ||
} | ||
get Update() { | ||
return this._update; | ||
} | ||
get Replace() { | ||
return this._replace; | ||
} | ||
/** | ||
* Sets insert to ignore on duplicate | ||
*/ | ||
ignore() { | ||
orIgnore() { | ||
this._ignore = true; | ||
return this; | ||
} | ||
orReplace() { | ||
this._update = true; | ||
return this; | ||
} | ||
values(data) { | ||
@@ -884,7 +944,8 @@ const self = this; | ||
let columnToCheck = column; | ||
if (!columnToCheck && this.this._model) { | ||
if (!columnToCheck && this._model) { | ||
columnToCheck = (0, model_1.extractModelDescriptor)(this._model) | ||
.Columns.filter((c) => c.Unique && !c.PrimaryKey) | ||
.Columns.filter((c) => c.Unique) | ||
.map((c) => c.Name); | ||
} | ||
this._update = true; | ||
this.DuplicateQueryBuilder = new OnDuplicateQueryBuilder(this._container, this, columnToCheck); | ||
@@ -905,3 +966,3 @@ return this.DuplicateQueryBuilder; | ||
super(container, driver); | ||
this._queryContext = interfaces_1.QueryContext.Schema; | ||
this.QueryContext = interfaces_1.QueryContext.Schema; | ||
} | ||
@@ -1052,2 +1113,28 @@ name(name) { | ||
exports.ColumnQueryBuilder = ColumnQueryBuilder; | ||
class AlterColumnQueryBuilder extends ColumnQueryBuilder { | ||
constructor(name, type, ...args) { | ||
super(name, type, ...args); | ||
this.OldName = name; | ||
// we assume add by default | ||
this.AlterType = _1.ColumnAlterationType.Add; | ||
} | ||
addColumn() { | ||
this.AlterType = _1.ColumnAlterationType.Add; | ||
return this; | ||
} | ||
modify() { | ||
this.AlterType = _1.ColumnAlterationType.Modify; | ||
return this; | ||
} | ||
rename(newName) { | ||
this.AlterType = _1.ColumnAlterationType.Rename; | ||
this.Name = newName; | ||
return this; | ||
} | ||
after(columnName) { | ||
this.AfterColumn = columnName; | ||
return this; | ||
} | ||
} | ||
exports.AlterColumnQueryBuilder = AlterColumnQueryBuilder; | ||
class TableExistsQueryBuilder extends QueryBuilder { | ||
@@ -1057,3 +1144,3 @@ constructor(container, driver, name) { | ||
this.setTable(name); | ||
this._queryContext = interfaces_1.QueryContext.Select; | ||
this.QueryContext = interfaces_1.QueryContext.Select; | ||
} | ||
@@ -1065,2 +1152,29 @@ toDB() { | ||
exports.TableExistsQueryBuilder = TableExistsQueryBuilder; | ||
class AlterTableQueryBuilder extends QueryBuilder { | ||
constructor(container, driver, name) { | ||
super(container, driver, null); | ||
this.setTable(name); | ||
this.QueryContext = interfaces_1.QueryContext.Schema; | ||
this._columns = []; | ||
this.DroppedColumns = []; | ||
} | ||
get Columns() { | ||
return this._columns; | ||
} | ||
/** | ||
* Renames table | ||
* | ||
* @param newTableName - new table name | ||
*/ | ||
rename(newTableName) { | ||
this.NewTableName = newTableName; | ||
} | ||
dropColumn(column) { | ||
this.DroppedColumns.push(column); | ||
} | ||
toDB() { | ||
return this._container.resolve(interfaces_1.AlterTableQueryCompiler, [this]).compile(); | ||
} | ||
} | ||
exports.AlterTableQueryBuilder = AlterTableQueryBuilder; | ||
class TableQueryBuilder extends QueryBuilder { | ||
@@ -1073,4 +1187,5 @@ constructor(container, driver, name) { | ||
this._foreignKeys = []; | ||
this._temporary = false; | ||
this.setTable(name); | ||
this._queryContext = interfaces_1.QueryContext.Schema; | ||
this.QueryContext = interfaces_1.QueryContext.Schema; | ||
} | ||
@@ -1081,2 +1196,6 @@ ifExists() { | ||
} | ||
temporary() { | ||
this._temporary = true; | ||
return this; | ||
} | ||
get Columns() { | ||
@@ -1091,2 +1210,5 @@ return this._columns; | ||
} | ||
get Temporary() { | ||
return this._temporary; | ||
} | ||
increments(name) { | ||
@@ -1112,2 +1234,79 @@ return this.int(name).autoIncrement().notNull().primaryKey(); | ||
exports.TableQueryBuilder = TableQueryBuilder; | ||
let TruncateTableQueryBuilder = class TruncateTableQueryBuilder extends QueryBuilder { | ||
constructor(container, driver) { | ||
super(container, driver); | ||
this.container = container; | ||
this.driver = driver; | ||
} | ||
toDB() { | ||
return this._container.resolve(interfaces_1.TruncateTableQueryCompiler, [this]).compile(); | ||
} | ||
}; | ||
TruncateTableQueryBuilder = __decorate([ | ||
(0, di_1.NewInstance)(), | ||
(0, di_1.Inject)(di_1.Container), | ||
__metadata("design:paramtypes", [di_1.Container, driver_1.OrmDriver]) | ||
], TruncateTableQueryBuilder); | ||
exports.TruncateTableQueryBuilder = TruncateTableQueryBuilder; | ||
let CloneTableQueryBuilder = class CloneTableQueryBuilder extends QueryBuilder { | ||
constructor(container, driver) { | ||
super(container, driver); | ||
this.container = container; | ||
this.driver = driver; | ||
this._shallow = true; | ||
this._cloneSrc = ''; | ||
this._temporary = false; | ||
} | ||
get CloneSource() { | ||
return this._cloneSrc; | ||
} | ||
get Temporary() { | ||
return this._temporary; | ||
} | ||
get Shallow() { | ||
return this._shallow; | ||
} | ||
get Filter() { | ||
return this._filter; | ||
} | ||
/** | ||
* Clones table structure without data | ||
* Shorthand for createTable(( table) => table.clone("new")); | ||
* | ||
* @param srcTable - source table name | ||
* @param newTable - target table name | ||
*/ | ||
shallowClone(srcTable, newTable) { | ||
this.setTable(newTable); | ||
this._cloneSrc = srcTable; | ||
return this; | ||
} | ||
/** | ||
* Clones table with data | ||
* | ||
* @param srcTable - source table name | ||
* @param newTable - target table name | ||
* @param filter - data filter, set null if all data is to be cloned | ||
*/ | ||
async deepClone(srcTable, newTable, filter) { | ||
this.setTable(newTable); | ||
this._cloneSrc = srcTable; | ||
this._shallow = false; | ||
if (filter) { | ||
this._filter = new SelectQueryBuilder(this._container, this._driver); | ||
this._filter.setTable(this._cloneSrc); | ||
filter(this._filter); | ||
} | ||
return this; | ||
} | ||
toDB() { | ||
return this._container.resolve(_1.TableCloneQueryCompiler, [this]).compile(); | ||
} | ||
}; | ||
CloneTableQueryBuilder = __decorate([ | ||
(0, di_1.NewInstance)(), | ||
(0, di_1.Inject)(di_1.Container), | ||
__metadata("design:paramtypes", [di_1.Container, driver_1.OrmDriver]) | ||
], CloneTableQueryBuilder); | ||
exports.CloneTableQueryBuilder = CloneTableQueryBuilder; | ||
let SchemaQueryBuilder = class SchemaQueryBuilder { | ||
@@ -1123,4 +1322,17 @@ constructor(container, driver) { | ||
} | ||
async tableExists(name) { | ||
cloneTable(callback) { | ||
const builder = new CloneTableQueryBuilder(this.container, this.driver); | ||
callback(builder); | ||
return builder; | ||
} | ||
alterTable(name, callback) { | ||
const builder = new AlterTableQueryBuilder(this.container, this.driver, name); | ||
callback.call(this, builder); | ||
return builder; | ||
} | ||
async tableExists(name, schema) { | ||
const query = new TableExistsQueryBuilder(this.container, this.driver, name); | ||
if (schema) { | ||
query.database(schema); | ||
} | ||
const exists = await query; | ||
@@ -1143,2 +1355,9 @@ return exists !== null && exists.length === 1; | ||
}); | ||
Object.values(enums_1.ColumnType).forEach((type) => { | ||
AlterTableQueryBuilder.prototype[type] = function (name, ...args) { | ||
const _builder = new AlterColumnQueryBuilder(name, type, ...args); | ||
this._columns.push(_builder); | ||
return _builder; | ||
}; | ||
}); | ||
//# sourceMappingURL=builders.js.map |
import { Log } from '@spinajs/log'; | ||
import { QueryContext } from './interfaces'; | ||
import { SyncModule, IContainer, Container } from '@spinajs/di'; | ||
import { IDriverOptions, IColumnDescriptor } from '.'; | ||
import { IDriverOptions, IColumnDescriptor, TruncateTableQueryBuilder } from '.'; | ||
import { UpdateQueryBuilder, SelectQueryBuilder, IndexQueryBuilder, DeleteQueryBuilder, InsertQueryBuilder, SchemaQueryBuilder, QueryBuilder } from './builders'; | ||
@@ -56,2 +56,6 @@ export declare type TransactionCallback = (driver: OrmDriver) => Promise<any>; | ||
/** | ||
* Truncates given table | ||
*/ | ||
truncate(table: string): TruncateTableQueryBuilder; | ||
/** | ||
* Creates update query builder associated with this connection. | ||
@@ -58,0 +62,0 @@ * This can be used to execute raw queries to db without orm model layer |
@@ -15,4 +15,6 @@ "use strict"; | ||
const di_1 = require("@spinajs/di"); | ||
const _1 = require("."); | ||
const builders_1 = require("./builders"); | ||
const hydrators_1 = require("./hydrators"); | ||
const dehydrators_1 = require("./dehydrators"); | ||
class OrmDriver extends di_1.SyncModule { | ||
@@ -36,2 +38,3 @@ constructor(options) { | ||
di_1.DI.register(hydrators_1.JunctionModelPropertyHydrator).as(hydrators_1.ModelHydrator); | ||
di_1.DI.register(dehydrators_1.StandardModelDehydrator).as(dehydrators_1.ModelDehydrator); | ||
} | ||
@@ -60,2 +63,10 @@ /** | ||
/** | ||
* Truncates given table | ||
*/ | ||
truncate(table) { | ||
const b = this.Container.resolve(_1.TruncateTableQueryBuilder, [this]); | ||
b.setTable(table); | ||
return b; | ||
} | ||
/** | ||
* Creates update query builder associated with this connection. | ||
@@ -62,0 +73,0 @@ * This can be used to execute raw queries to db without orm model layer |
@@ -40,3 +40,3 @@ /** | ||
*/ | ||
export declare enum WhereOperators { | ||
export declare enum SqlOperator { | ||
LT = "<", | ||
@@ -47,3 +47,5 @@ LTE = "<=", | ||
NOT = "!=", | ||
NOT_2 = "<>", | ||
EQ = "=", | ||
EQ_NULL = "<=>", | ||
IN = "in", | ||
@@ -57,2 +59,3 @@ NOT_IN = "not in", | ||
} | ||
export declare type Op = '<' | '>' | '!=' | '<=>' | '>=' | '<=' | '<>' | 'like' | '='; | ||
/** | ||
@@ -59,0 +62,0 @@ * Allowed join methods in queries |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SORT_ORDER = exports.ColumnType = exports.ColumnMethods = exports.JoinMethod = exports.WhereOperators = exports.WhereBoolean = exports.QueryMethod = void 0; | ||
exports.SORT_ORDER = exports.ColumnType = exports.ColumnMethods = exports.JoinMethod = exports.SqlOperator = exports.WhereBoolean = exports.QueryMethod = void 0; | ||
/** | ||
@@ -45,18 +45,20 @@ * Allowed query methods and types. | ||
*/ | ||
var WhereOperators; | ||
(function (WhereOperators) { | ||
WhereOperators["LT"] = "<"; | ||
WhereOperators["LTE"] = "<="; | ||
WhereOperators["GT"] = ">"; | ||
WhereOperators["GTE"] = ">="; | ||
WhereOperators["NOT"] = "!="; | ||
WhereOperators["EQ"] = "="; | ||
WhereOperators["IN"] = "in"; | ||
WhereOperators["NOT_IN"] = "not in"; | ||
WhereOperators["NULL"] = "is null"; | ||
WhereOperators["NOT_NULL"] = "is not null"; | ||
WhereOperators["BETWEEN"] = "between"; | ||
WhereOperators["NOT_BETWEEN"] = "not between"; | ||
WhereOperators["LIKE"] = "like"; | ||
})(WhereOperators = exports.WhereOperators || (exports.WhereOperators = {})); | ||
var SqlOperator; | ||
(function (SqlOperator) { | ||
SqlOperator["LT"] = "<"; | ||
SqlOperator["LTE"] = "<="; | ||
SqlOperator["GT"] = ">"; | ||
SqlOperator["GTE"] = ">="; | ||
SqlOperator["NOT"] = "!="; | ||
SqlOperator["NOT_2"] = "<>"; | ||
SqlOperator["EQ"] = "="; | ||
SqlOperator["EQ_NULL"] = "<=>"; | ||
SqlOperator["IN"] = "in"; | ||
SqlOperator["NOT_IN"] = "not in"; | ||
SqlOperator["NULL"] = "is null"; | ||
SqlOperator["NOT_NULL"] = "is not null"; | ||
SqlOperator["BETWEEN"] = "between"; | ||
SqlOperator["NOT_BETWEEN"] = "not between"; | ||
SqlOperator["LIKE"] = "like"; | ||
})(SqlOperator = exports.SqlOperator || (exports.SqlOperator = {})); | ||
/** | ||
@@ -63,0 +65,0 @@ * Allowed join methods in queries |
export * from './interfaces'; | ||
export * from './enums'; | ||
export * from './statements'; | ||
@@ -10,4 +11,6 @@ export * from './builders'; | ||
export * from './hydrators'; | ||
export * from './dehydrators'; | ||
export * from './driver'; | ||
export * from './converters'; | ||
export * from './wrappers'; | ||
export * from './exceptions'; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -14,2 +18,3 @@ if (k2 === undefined) k2 = k; | ||
__exportStar(require("./interfaces"), exports); | ||
__exportStar(require("./enums"), exports); | ||
__exportStar(require("./statements"), exports); | ||
@@ -23,5 +28,7 @@ __exportStar(require("./builders"), exports); | ||
__exportStar(require("./hydrators"), exports); | ||
__exportStar(require("./dehydrators"), exports); | ||
__exportStar(require("./driver"), exports); | ||
__exportStar(require("./converters"), exports); | ||
__exportStar(require("./wrappers"), exports); | ||
__exportStar(require("./exceptions"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,3 @@ | ||
import { RawQuery } from './builders'; | ||
import { Op } from './enums'; | ||
import { QueryBuilder, RawQuery } from './builders'; | ||
import { SORT_ORDER, WhereBoolean } from './enums'; | ||
@@ -6,3 +7,3 @@ import { IQueryStatement, WrapStatement } from './statements'; | ||
import { OrmDriver } from './driver'; | ||
import { Constructor } from '@spinajs/di'; | ||
import { Constructor, IContainer } from '@spinajs/di'; | ||
import { ModelBase } from './model'; | ||
@@ -17,16 +18,20 @@ export declare enum QueryContext { | ||
} | ||
export declare enum ColumnAlterationType { | ||
Add = 0, | ||
Modify = 1, | ||
Rename = 2 | ||
} | ||
export declare enum InsertBehaviour { | ||
/** | ||
* On duplicate entry ignore & fetch only model primary key | ||
* On duplicate check not only for pkeys but also for unique constrain | ||
* Ignores if primary key exists in db | ||
*/ | ||
OnDuplicateIgnore = 0, | ||
InsertOrIgnore = 0, | ||
/** | ||
* On duplicate update entry ( when unique constraint is hit update db from model data) | ||
* Updates entry if pk exists | ||
*/ | ||
OnDuplicateUpdate = 1, | ||
InsertOrUpdate = 1, | ||
/** | ||
* Throw error if model hits constraint ( primary or unique keys ) | ||
* Replaces entry if pk exists | ||
*/ | ||
OnDuplicateThrow = 2, | ||
InsertOrReplace = 2, | ||
None = 3 | ||
@@ -203,2 +208,9 @@ } | ||
export declare type ForwardRefFunction = () => Constructor<ModelBase>; | ||
/** | ||
* Returns result of last insert or affected rows ( eg. rows affected would be 0 if insert is ignored ) | ||
*/ | ||
export interface IUpdateResult { | ||
RowsAffected: number; | ||
LastInsertId: number; | ||
} | ||
export interface IRelationDescriptor { | ||
@@ -381,6 +393,8 @@ /** | ||
TableAlias: string; | ||
Schema: string; | ||
schema(schema: string): IQueryBuilder; | ||
Database: string; | ||
database(database: string): IQueryBuilder; | ||
from(table: string, alias?: string): this; | ||
setAlias(alias: string): this; | ||
Driver: OrmDriver; | ||
Container: IContainer; | ||
} | ||
@@ -392,2 +406,4 @@ export interface ILimitBuilder { | ||
firstOrFail<T>(): Promise<T>; | ||
firstOrThrow<T>(error: Error): Promise<T>; | ||
orThrow<T>(error: Error): Promise<T>; | ||
getLimits(): IQueryLimit; | ||
@@ -441,5 +457,23 @@ } | ||
Op: WhereBoolean; | ||
where(column: string | boolean | {} | WhereFunction | WrapStatement, operator?: any, value?: any): this; | ||
orWhere(column: string | boolean | {} | WhereFunction | WrapStatement, operator?: any, value?: any): this; | ||
andWhere(column: string | boolean | {} | WhereFunction | WrapStatement, operator?: any, value?: any): this; | ||
where(val: boolean): this; | ||
where(val: {}): this; | ||
where(func: WhereFunction): this; | ||
where(column: string, operator: Op, value: any): this; | ||
where(column: string, value: any): this; | ||
where(statement: WrapStatement): this; | ||
where(column: string | boolean | WhereFunction | RawQuery | {} | WrapStatement, operator?: Op | any, value?: any): this; | ||
orWhere(val: boolean): this; | ||
orWhere(val: {}): this; | ||
orWhere(func: WhereFunction): this; | ||
orWhere(column: string, operator: Op, value: any): this; | ||
orWhere(column: string, value: any): this; | ||
orWhere(statement: WrapStatement): this; | ||
orWhere(column: string | boolean | WhereFunction | RawQuery | {}, operator?: Op | any, value?: any): this; | ||
andWhere(val: boolean): this; | ||
andWhere(val: {}): this; | ||
andWhere(func: WhereFunction): this; | ||
andWhere(column: string, operator: Op, value: any): this; | ||
andWhere(column: string, value: any): this; | ||
andWhere(statement: WrapStatement): this; | ||
andWhere(column: string | boolean | WhereFunction | RawQuery | {}, operator?: Op | any, value?: any): this; | ||
whereObject(obj: any): this; | ||
@@ -507,3 +541,3 @@ whereNotNull(column: string): this; | ||
export interface IQueryCompiler { | ||
compile(): ICompilerOutput; | ||
compile(): ICompilerOutput | ICompilerOutput[]; | ||
} | ||
@@ -544,2 +578,5 @@ export interface ILimitCompiler { | ||
} | ||
export declare abstract class LimitQueryCompiler implements IQueryCompiler { | ||
abstract compile(): ICompilerOutput; | ||
} | ||
export declare abstract class ForeignKeyQueryCompiler implements IQueryCompiler { | ||
@@ -563,2 +600,11 @@ abstract compile(): ICompilerOutput; | ||
} | ||
export declare abstract class TruncateTableQueryCompiler implements IQueryCompiler { | ||
abstract compile(): ICompilerOutput; | ||
} | ||
export declare abstract class TableCloneQueryCompiler implements IQueryCompiler { | ||
abstract compile(): ICompilerOutput[]; | ||
} | ||
export declare abstract class AlterTableQueryCompiler implements IQueryCompiler { | ||
abstract compile(): ICompilerOutput[]; | ||
} | ||
export declare abstract class TableExistsCompiler implements IQueryCompiler { | ||
@@ -570,2 +616,5 @@ abstract compile(): ICompilerOutput; | ||
} | ||
export declare abstract class AlterColumnQueryCompiler implements IQueryCompiler { | ||
abstract compile(): ICompilerOutput; | ||
} | ||
export declare abstract class OrderByQueryCompiler implements IQueryCompiler { | ||
@@ -583,3 +632,3 @@ abstract compile(): ICompilerOutput; | ||
*/ | ||
export interface IBuilderMiddleware { | ||
export interface IBuilderMiddleware<T = any[]> { | ||
/** | ||
@@ -592,3 +641,3 @@ * | ||
*/ | ||
afterData(data: any[]): any[]; | ||
afterQuery(data: T): T; | ||
/** | ||
@@ -633,1 +682,4 @@ * Executed when model is about to create. Use it to | ||
} | ||
export declare abstract class TableAliasCompiler { | ||
abstract compile(builder: QueryBuilder, tbl?: string): string; | ||
} |
@@ -9,3 +9,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SetValueConverter = exports.DatetimeValueConverter = exports.ValueConverter = exports.GroupByQueryCompiler = exports.OrderByQueryCompiler = exports.ColumnQueryCompiler = exports.TableExistsCompiler = exports.TableQueryCompiler = exports.OnDuplicateQueryCompiler = exports.InsertQueryCompiler = exports.UpdateQueryCompiler = exports.DeleteQueryCompiler = exports.ForeignKeyQueryCompiler = exports.IndexQueryCompiler = exports.JoinQueryCompiler = exports.SelectQueryCompiler = exports.RecursiveQueryCompiler = exports.OrmMigration = exports.RelationType = exports.MigrationTransactionMode = exports.ReferentialAction = exports.InsertBehaviour = exports.QueryContext = void 0; | ||
exports.TableAliasCompiler = exports.SetValueConverter = exports.DatetimeValueConverter = exports.ValueConverter = exports.GroupByQueryCompiler = exports.OrderByQueryCompiler = exports.AlterColumnQueryCompiler = exports.ColumnQueryCompiler = exports.TableExistsCompiler = exports.AlterTableQueryCompiler = exports.TableCloneQueryCompiler = exports.TruncateTableQueryCompiler = exports.TableQueryCompiler = exports.OnDuplicateQueryCompiler = exports.InsertQueryCompiler = exports.UpdateQueryCompiler = exports.DeleteQueryCompiler = exports.ForeignKeyQueryCompiler = exports.LimitQueryCompiler = exports.IndexQueryCompiler = exports.JoinQueryCompiler = exports.SelectQueryCompiler = exports.RecursiveQueryCompiler = exports.OrmMigration = exports.RelationType = exports.MigrationTransactionMode = exports.ReferentialAction = exports.InsertBehaviour = exports.ColumnAlterationType = exports.QueryContext = void 0; | ||
const di_1 = require("@spinajs/di"); | ||
@@ -22,17 +22,22 @@ const exceptions_1 = require("@spinajs/exceptions"); | ||
})(QueryContext = exports.QueryContext || (exports.QueryContext = {})); | ||
var ColumnAlterationType; | ||
(function (ColumnAlterationType) { | ||
ColumnAlterationType[ColumnAlterationType["Add"] = 0] = "Add"; | ||
ColumnAlterationType[ColumnAlterationType["Modify"] = 1] = "Modify"; | ||
ColumnAlterationType[ColumnAlterationType["Rename"] = 2] = "Rename"; | ||
})(ColumnAlterationType = exports.ColumnAlterationType || (exports.ColumnAlterationType = {})); | ||
var InsertBehaviour; | ||
(function (InsertBehaviour) { | ||
/** | ||
* On duplicate entry ignore & fetch only model primary key | ||
* On duplicate check not only for pkeys but also for unique constrain | ||
* Ignores if primary key exists in db | ||
*/ | ||
InsertBehaviour[InsertBehaviour["OnDuplicateIgnore"] = 0] = "OnDuplicateIgnore"; | ||
InsertBehaviour[InsertBehaviour["InsertOrIgnore"] = 0] = "InsertOrIgnore"; | ||
/** | ||
* On duplicate update entry ( when unique constraint is hit update db from model data) | ||
* Updates entry if pk exists | ||
*/ | ||
InsertBehaviour[InsertBehaviour["OnDuplicateUpdate"] = 1] = "OnDuplicateUpdate"; | ||
InsertBehaviour[InsertBehaviour["InsertOrUpdate"] = 1] = "InsertOrUpdate"; | ||
/** | ||
* Throw error if model hits constraint ( primary or unique keys ) | ||
* Replaces entry if pk exists | ||
*/ | ||
InsertBehaviour[InsertBehaviour["OnDuplicateThrow"] = 2] = "OnDuplicateThrow"; | ||
InsertBehaviour[InsertBehaviour["InsertOrReplace"] = 2] = "InsertOrReplace"; | ||
InsertBehaviour[InsertBehaviour["None"] = 3] = "None"; | ||
@@ -105,2 +110,8 @@ })(InsertBehaviour = exports.InsertBehaviour || (exports.InsertBehaviour = {})); | ||
exports.IndexQueryCompiler = IndexQueryCompiler; | ||
let LimitQueryCompiler = class LimitQueryCompiler { | ||
}; | ||
LimitQueryCompiler = __decorate([ | ||
(0, di_1.NewInstance)() | ||
], LimitQueryCompiler); | ||
exports.LimitQueryCompiler = LimitQueryCompiler; | ||
let ForeignKeyQueryCompiler = class ForeignKeyQueryCompiler { | ||
@@ -142,2 +153,20 @@ }; | ||
exports.TableQueryCompiler = TableQueryCompiler; | ||
let TruncateTableQueryCompiler = class TruncateTableQueryCompiler { | ||
}; | ||
TruncateTableQueryCompiler = __decorate([ | ||
(0, di_1.NewInstance)() | ||
], TruncateTableQueryCompiler); | ||
exports.TruncateTableQueryCompiler = TruncateTableQueryCompiler; | ||
let TableCloneQueryCompiler = class TableCloneQueryCompiler { | ||
}; | ||
TableCloneQueryCompiler = __decorate([ | ||
(0, di_1.NewInstance)() | ||
], TableCloneQueryCompiler); | ||
exports.TableCloneQueryCompiler = TableCloneQueryCompiler; | ||
let AlterTableQueryCompiler = class AlterTableQueryCompiler { | ||
}; | ||
AlterTableQueryCompiler = __decorate([ | ||
(0, di_1.NewInstance)() | ||
], AlterTableQueryCompiler); | ||
exports.AlterTableQueryCompiler = AlterTableQueryCompiler; | ||
let TableExistsCompiler = class TableExistsCompiler { | ||
@@ -155,2 +184,8 @@ }; | ||
exports.ColumnQueryCompiler = ColumnQueryCompiler; | ||
let AlterColumnQueryCompiler = class AlterColumnQueryCompiler { | ||
}; | ||
AlterColumnQueryCompiler = __decorate([ | ||
(0, di_1.NewInstance)() | ||
], AlterColumnQueryCompiler); | ||
exports.AlterColumnQueryCompiler = AlterColumnQueryCompiler; | ||
let OrderByQueryCompiler = class OrderByQueryCompiler { | ||
@@ -199,2 +234,8 @@ }; | ||
exports.SetValueConverter = SetValueConverter; | ||
let TableAliasCompiler = class TableAliasCompiler { | ||
}; | ||
TableAliasCompiler = __decorate([ | ||
(0, di_1.Singleton)() | ||
], TableAliasCompiler); | ||
exports.TableAliasCompiler = TableAliasCompiler; | ||
//# sourceMappingURL=interfaces.js.map |
@@ -1,7 +0,11 @@ | ||
import { IModelDescrtiptor, InsertBehaviour } from './interfaces'; | ||
import { IModelDescrtiptor, InsertBehaviour, IUpdateResult, IWhereBuilder } from './interfaces'; | ||
import { WhereFunction } from './types'; | ||
import { RawQuery, UpdateQueryBuilder, SelectQueryBuilder, InsertQueryBuilder } from './builders'; | ||
import { WhereOperators } from './enums'; | ||
import { Op } from './enums'; | ||
import { IContainer } from '@spinajs/di'; | ||
import { WrapStatement } from './statements'; | ||
export declare function extractModelDescriptor(targetOrForward: any): IModelDescrtiptor; | ||
export declare class ModelBase { | ||
private _descriptor; | ||
private _container; | ||
/** | ||
@@ -12,2 +16,6 @@ * Gets descriptor for this model. It contains information about relations, orm driver, connection properties, | ||
get ModelDescriptor(): IModelDescrtiptor; | ||
/** | ||
* Gets di container associated with this model ( via connection object eg. different drivers have their own implementation of things) | ||
*/ | ||
get Container(): IContainer; | ||
get PrimaryKeyName(): string; | ||
@@ -25,3 +33,3 @@ get PrimaryKeyValue(): any; | ||
*/ | ||
static insert<T extends typeof ModelBase>(this: T, _data: InstanceType<T> | Partial<InstanceType<T>> | Array<InstanceType<T>> | Array<Partial<InstanceType<T>>>): InsertQueryBuilder; | ||
static insert<T extends typeof ModelBase>(this: T, _data: InstanceType<T> | Partial<InstanceType<T>> | Array<InstanceType<T>> | Array<Partial<InstanceType<T>>>, _insertBehaviour?: InsertBehaviour): InsertQueryBuilder; | ||
/** | ||
@@ -34,3 +42,9 @@ * Search entities in db | ||
*/ | ||
static where<T extends typeof ModelBase>(this: T, _column: string | boolean | WhereFunction | RawQuery | object, _operator?: WhereOperators | any, _value?: any): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, val: boolean): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, val: {}): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, func: WhereFunction): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, column: string, operator: Op, value: any): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, column: string, value: any): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, statement: WrapStatement): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
static where<T extends typeof ModelBase>(this: T, column: string | boolean | WhereFunction | RawQuery | {}, operator?: Op | any, value?: any): SelectQueryBuilder<Array<InstanceType<T>>>; | ||
/** | ||
@@ -47,2 +61,26 @@ * Updates single or multiple records at once with provided value based on condition | ||
/** | ||
* Tries to get first result from db | ||
* | ||
* Orders by Primary key, if pk not exists then by unique constraints and lastly by CreateAt if no unique columns exists. | ||
*/ | ||
static first<T extends typeof ModelBase>(this: T, callback?: (builder: IWhereBuilder) => void): Promise<number>; | ||
/** | ||
* Tries to get first result from db | ||
* | ||
* Orders by Primary key, if pk not exists then by unique constraints and lastly by CreateAt if no unique columns exists. | ||
*/ | ||
static last<T extends typeof ModelBase>(this: T, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T>>; | ||
/** | ||
* Tries to get newest result from db. It throws if model dont have CreatedAt decorated property | ||
*/ | ||
static newest<T extends typeof ModelBase>(this: T, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T>>; | ||
/** | ||
* Tries to get oldest result from db. It throws if model dont have CreatedAt decorated property | ||
*/ | ||
static oldest<T extends typeof ModelBase>(this: T, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T>>; | ||
/** | ||
* Returns total count of entries in db for this model | ||
*/ | ||
static count<T extends typeof ModelBase>(this: T, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T>>; | ||
/** | ||
* Tries to find all models in db. If not all exists, throws exception | ||
@@ -114,2 +152,6 @@ */ | ||
destroy(): Promise<void>; | ||
/** | ||
* If model can be in achived state - sets archived at date and saves it to db | ||
*/ | ||
archive(): Promise<void>; | ||
update(): Promise<void>; | ||
@@ -120,8 +162,18 @@ /** | ||
*/ | ||
insert(insertBehaviour?: InsertBehaviour): Promise<void>; | ||
insert(insertBehaviour?: InsertBehaviour): Promise<IUpdateResult>; | ||
/** | ||
* Gets model data from database and returns as fresh instance. | ||
* | ||
* If primary key is not fetched, tries to load by columns with unique constraint. | ||
* If there is no unique columns or primary key, throws error | ||
*/ | ||
fresh(): Promise<this>; | ||
/** | ||
* Refresh model from database. | ||
* | ||
* If no primary key is set, tries to fetch data base on columns | ||
* with unique constraints. If none exists, throws exception | ||
*/ | ||
refresh(): Promise<void>; | ||
/** | ||
* sets default values for model. values are taken from DB default column prop | ||
@@ -133,9 +185,9 @@ */ | ||
query(): SelectQueryBuilder; | ||
where(column: string | boolean | WhereFunction | RawQuery | {}, operator?: WhereOperators | any, value?: any): SelectQueryBuilder; | ||
where(column: string | boolean | WhereFunction | RawQuery | {}, operator?: Op | any, value?: any): SelectQueryBuilder; | ||
update<T extends typeof ModelBase>(data: Partial<InstanceType<T>>): UpdateQueryBuilder; | ||
all(page: number, perPage: number): SelectQueryBuilder; | ||
all(page?: number, perPage?: number): SelectQueryBuilder<unknown>; | ||
/** | ||
* Try to insert new value | ||
*/ | ||
insert<T_1 extends typeof ModelBase>(this: T_1, data: InstanceType<T_1> | Partial<InstanceType<T_1>> | InstanceType<T_1>[] | Partial<InstanceType<T_1>>[]): InsertQueryBuilder; | ||
insert<T_1 extends typeof ModelBase>(this: T_1, data: InstanceType<T_1> | Partial<InstanceType<T_1>> | InstanceType<T_1>[] | Partial<InstanceType<T_1>>[], insertBehaviour?: InsertBehaviour): Promise<IUpdateResult>; | ||
find<T_2 extends typeof ModelBase>(this: T_2, pks: any[]): Promise<InstanceType<T_2>[]>; | ||
@@ -149,2 +201,7 @@ findOrFail<T_3 extends typeof ModelBase>(this: T_3, pks: any[]): Promise<InstanceType<T_3>[]>; | ||
getOrNew<T_8 extends typeof ModelBase>(this: T_8, pk: any, data?: Partial<InstanceType<T_8>>): Promise<InstanceType<T_8>>; | ||
first<T_9 extends typeof ModelBase>(this: T_9, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T_9>>; | ||
last<T_10 extends typeof ModelBase>(this: T_10, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T_10>>; | ||
newest<T_11 extends typeof ModelBase>(this: T_11, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T_11>>; | ||
oldest<T_12 extends typeof ModelBase>(this: T_12, callback?: (builder: IWhereBuilder) => void): Promise<InstanceType<T_12>>; | ||
count<T_13 extends typeof ModelBase>(this: T_13, callback?: (builder: IWhereBuilder) => void): Promise<number>; | ||
}; |
355
lib/model.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -6,2 +29,3 @@ exports.MODEL_STATIC_MIXINS = exports.ModelBase = exports.extractModelDescriptor = void 0; | ||
const relations_1 = require("./relations"); | ||
const enums_1 = require("./enums"); | ||
const decorators_1 = require("./decorators"); | ||
@@ -13,5 +37,6 @@ const interfaces_1 = require("./interfaces"); | ||
const hydrators_1 = require("./hydrators"); | ||
const _ = require("lodash"); | ||
const _ = __importStar(require("lodash")); | ||
const uuid_1 = require("uuid"); | ||
const exceptions_1 = require("./exceptions"); | ||
const dehydrators_1 = require("./dehydrators"); | ||
function extractModelDescriptor(targetOrForward) { | ||
@@ -47,2 +72,8 @@ const target = !(0, di_1.isConstructor)(targetOrForward) && targetOrForward ? targetOrForward() : targetOrForward; | ||
class ModelBase { | ||
constructor(data) { | ||
this.setDefaults(); | ||
if (data) { | ||
Object.assign(this, data); | ||
} | ||
} | ||
/** | ||
@@ -53,4 +84,21 @@ * Gets descriptor for this model. It contains information about relations, orm driver, connection properties, | ||
get ModelDescriptor() { | ||
return extractModelDescriptor(this.constructor); | ||
if (!this._descriptor) { | ||
this._descriptor = extractModelDescriptor(this.constructor); | ||
} | ||
return this._descriptor; | ||
} | ||
/** | ||
* Gets di container associated with this model ( via connection object eg. different drivers have their own implementation of things) | ||
*/ | ||
get Container() { | ||
if (!this._container) { | ||
const orm = di_1.DI.get(orm_1.Orm); | ||
const driver = orm.Connections.get(this.ModelDescriptor.Connection); | ||
if (!driver) { | ||
throw new Error(`model ${this.constructor.name} have invalid connection ${this.ModelDescriptor.Connection}, please check your db config file or model connection name`); | ||
} | ||
this._container = driver.Container; | ||
} | ||
return this._container; | ||
} | ||
get PrimaryKeyName() { | ||
@@ -92,12 +140,5 @@ return this.ModelDescriptor.PrimaryKey; | ||
*/ | ||
static insert(_data) { | ||
static insert(_data, _insertBehaviour = interfaces_1.InsertBehaviour.None) { | ||
throw Error('Not implemented'); | ||
} | ||
/** | ||
* Search entities in db | ||
* | ||
* @param column - column to search or function | ||
* @param operator - boolean operator | ||
* @param value - value to compare | ||
*/ | ||
static where(_column, _operator, _value) { | ||
@@ -120,2 +161,17 @@ throw Error('Not implemented'); | ||
} | ||
static first() { | ||
throw Error('Not implemented'); | ||
} | ||
static last() { | ||
throw Error('Not implemented'); | ||
} | ||
static newest() { | ||
throw Error('Not implemented'); | ||
} | ||
static oldest() { | ||
throw Error('Not implemented'); | ||
} | ||
static count() { | ||
throw Error('Not implemented'); | ||
} | ||
/** | ||
@@ -182,8 +238,2 @@ * Tries to find all models in db. If not all exists, throws exception | ||
} | ||
constructor(data) { | ||
this.setDefaults(); | ||
if (data) { | ||
Object.assign(this, data); | ||
} | ||
} | ||
/** | ||
@@ -195,3 +245,3 @@ * Fills model with data. It only fills properties that exists in database | ||
hydrate(data) { | ||
di_1.DI.resolve(Array.ofType(hydrators_1.ModelHydrator)).forEach((h) => h.hydrate(this, data)); | ||
this.Container.resolve(Array.ofType(hydrators_1.ModelHydrator)).forEach((h) => h.hydrate(this, data)); | ||
} | ||
@@ -226,19 +276,3 @@ /** | ||
dehydrate() { | ||
var _a; | ||
const obj = {}; | ||
(_a = this.ModelDescriptor.Columns) === null || _a === void 0 ? void 0 : _a.forEach((c) => { | ||
const val = this[c.Name]; | ||
if (c.PrimaryKey && !c.Nullable && (val === null || val === undefined || val === '')) { | ||
throw new exceptions_1.OrmException(`Field ${c.Name} cannot be null`); | ||
} | ||
obj[c.Name] = c.Converter ? c.Converter.toDB(val) : val; | ||
}); | ||
for (const [, val] of this.ModelDescriptor.Relations) { | ||
if (val.Type === interfaces_1.RelationType.One) { | ||
if (this[val.Name]) { | ||
obj[val.ForeignKey] = this[val.Name].PrimaryKeyValue; | ||
} | ||
} | ||
} | ||
return obj; | ||
return this.Container.resolve(dehydrators_1.ModelDehydrator).dehydrate(this); | ||
} | ||
@@ -254,2 +288,15 @@ /** | ||
} | ||
/** | ||
* If model can be in achived state - sets archived at date and saves it to db | ||
*/ | ||
async archive() { | ||
const { query } = _createQuery(this.constructor, builders_1.UpdateQueryBuilder); | ||
if (this.ModelDescriptor.Archived) { | ||
this[this.ModelDescriptor.Archived.ArchivedAt] = new Date(); | ||
} | ||
else { | ||
throw new exceptions_1.OrmException('archived at column not exists in model'); | ||
} | ||
await query.update(this.dehydrate()).where(this.PrimaryKeyName, this.PrimaryKeyValue); | ||
} | ||
async update() { | ||
@@ -267,47 +314,57 @@ const { query } = _createQuery(this.constructor, builders_1.UpdateQueryBuilder); | ||
async insert(insertBehaviour = interfaces_1.InsertBehaviour.None) { | ||
var _a; | ||
const self = this; | ||
const { query, description } = _createQuery(this.constructor, builders_1.InsertQueryBuilder); | ||
switch (insertBehaviour) { | ||
case interfaces_1.InsertBehaviour.OnDuplicateIgnore: | ||
query.ignore(); | ||
case interfaces_1.InsertBehaviour.InsertOrIgnore: | ||
query.orIgnore(); | ||
break; | ||
case interfaces_1.InsertBehaviour.OnDuplicateUpdate: | ||
case interfaces_1.InsertBehaviour.InsertOrUpdate: | ||
query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name)); | ||
break; | ||
case interfaces_1.InsertBehaviour.InsertOrReplace: | ||
query.orReplace(); | ||
break; | ||
} | ||
const id = await query.values(this.dehydrate()); | ||
// ignore fired, we dont have insert ID | ||
if (insertBehaviour === interfaces_1.InsertBehaviour.OnDuplicateThrow && id === 0) { | ||
throw new exceptions_1.OrmException(`Duplicated entry in db for unique keys: ${description.Columns.filter((c) => c.Unique) | ||
.map((c) => { | ||
self[c.Name]; | ||
}) | ||
.join(',')}`); | ||
} | ||
else if (insertBehaviour === interfaces_1.InsertBehaviour.OnDuplicateIgnore && !this.PrimaryKeyValue) { | ||
// if OnDuplicateIgnore is set && we dont have pkey value, refresh pkey | ||
// based on unique column constrains | ||
const { query, description } = _createQuery(this.constructor, builders_1.SelectQueryBuilder, false); | ||
const idRes = await query | ||
.columns([this.PrimaryKeyName]) | ||
.where(function () { | ||
description.Columns.filter((c) => c.Unique).forEach((c) => { | ||
this.where(c, self[c.Name]); | ||
}); | ||
}) | ||
.first(); | ||
this.PrimaryKeyValue = idRes[this.PrimaryKeyName]; | ||
} | ||
else { | ||
this.PrimaryKeyValue = (_a = this.PrimaryKeyValue) !== null && _a !== void 0 ? _a : id; | ||
} | ||
const iMidleware = { | ||
afterQuery: (data) => { | ||
var _a; | ||
this.PrimaryKeyValue = (_a = this.PrimaryKeyValue) !== null && _a !== void 0 ? _a : data.LastInsertId; | ||
return data; | ||
}, | ||
modelCreation: () => null, | ||
afterHydration: () => null, | ||
}; | ||
query.middleware(iMidleware); | ||
return query.values(this.dehydrate()); | ||
} | ||
/** | ||
* Gets model data from database and returns as fresh instance. | ||
* | ||
* If primary key is not fetched, tries to load by columns with unique constraint. | ||
* If there is no unique columns or primary key, throws error | ||
*/ | ||
async fresh() { | ||
return this.constructor.get(this.PrimaryKeyValue); | ||
const { query, description } = _createQuery(this.constructor, builders_1.SelectQueryBuilder); | ||
query.select('*'); | ||
_preparePkWhere(description, query, this); | ||
_prepareOrderBy(description, query); | ||
return await query.firstOrFail(); | ||
} | ||
/** | ||
* Refresh model from database. | ||
* | ||
* If no primary key is set, tries to fetch data base on columns | ||
* with unique constraints. If none exists, throws exception | ||
*/ | ||
async refresh() { | ||
let model = null; | ||
const { query, description } = _createQuery(this.constructor, builders_1.SelectQueryBuilder); | ||
query.select('*'); | ||
_preparePkWhere(description, query, this); | ||
_prepareOrderBy(description, query); | ||
model = await query.firstOrFail(); | ||
for (const c of this.ModelDescriptor.Columns) { | ||
this[c.Name] = model[c.Name]; | ||
} | ||
} | ||
/** | ||
* sets default values for model. values are taken from DB default column prop | ||
@@ -345,2 +402,36 @@ */ | ||
} | ||
function _preparePkWhere(description, query, model) { | ||
if (description.PrimaryKey) { | ||
query.where(description.PrimaryKey, model.PrimaryKeyValue); | ||
} | ||
else { | ||
const unique = description.Columns.filter((x) => x.Unique); | ||
if (unique.length !== 0) { | ||
for (const c of unique) { | ||
query.where(c.Name, '=', model[c.Name]); | ||
} | ||
} | ||
else { | ||
throw new exceptions_1.OrmException('Model dont have primary key set or columns with unique constraint, cannot fetch model from database'); | ||
} | ||
} | ||
} | ||
function _prepareOrderBy(description, query, order) { | ||
var _a, _b; | ||
if (description.PrimaryKey) { | ||
query.order(description.PrimaryKey, order !== null && order !== void 0 ? order : enums_1.SORT_ORDER.DESC); | ||
} | ||
else { | ||
const unique = description.Columns.filter((c) => c.Unique); | ||
if (unique.length !== 0) { | ||
unique.forEach((c) => query.order(c.Name, order !== null && order !== void 0 ? order : enums_1.SORT_ORDER.DESC)); | ||
} | ||
else if ((_a = description.Timestamps) === null || _a === void 0 ? void 0 : _a.CreatedAt) { | ||
query.order(description.Timestamps.CreatedAt, order !== null && order !== void 0 ? order : enums_1.SORT_ORDER.DESC); | ||
} | ||
else if ((_b = description.Timestamps) === null || _b === void 0 ? void 0 : _b.UpdatedAt) { | ||
query.order(description.Timestamps.UpdatedAt, order !== null && order !== void 0 ? order : enums_1.SORT_ORDER.DESC); | ||
} | ||
} | ||
} | ||
function _createQuery(model, query, injectModel = true) { | ||
@@ -361,3 +452,3 @@ const dsc = _descriptor(model); | ||
if (driver.Options.Database) { | ||
qr.schema(driver.Options.Database); | ||
qr.database(driver.Options.Database); | ||
} | ||
@@ -395,5 +486,8 @@ return { | ||
*/ | ||
insert(data) { | ||
const { query } = _createQuery(this, builders_1.InsertQueryBuilder); | ||
async insert(data, insertBehaviour = interfaces_1.InsertBehaviour.None) { | ||
const { query, description } = _createQuery(this, builders_1.InsertQueryBuilder); | ||
if (Array.isArray(data)) { | ||
if (insertBehaviour !== interfaces_1.InsertBehaviour.None) { | ||
throw new exceptions_1.OrmException(`insert behaviour is not supported with arrays`); | ||
} | ||
query.values(data.map((d) => { | ||
@@ -407,2 +501,13 @@ if (d instanceof ModelBase) { | ||
else { | ||
switch (insertBehaviour) { | ||
case interfaces_1.InsertBehaviour.InsertOrIgnore: | ||
query.orIgnore(); | ||
break; | ||
case interfaces_1.InsertBehaviour.InsertOrUpdate: | ||
query.onDuplicate().update(description.Columns.filter((c) => !c.PrimaryKey).map((c) => c.Name)); | ||
break; | ||
case interfaces_1.InsertBehaviour.InsertOrReplace: | ||
query.orReplace(); | ||
break; | ||
} | ||
if (data instanceof ModelBase) { | ||
@@ -415,2 +520,22 @@ query.values(data.dehydrate()); | ||
} | ||
const iMidleware = { | ||
afterQuery: (result) => { | ||
var _a; | ||
if (Array.isArray(data)) { | ||
data.forEach((v, idx) => { | ||
var _a; | ||
if (v instanceof ModelBase) { | ||
v.PrimaryKeyValue = (_a = v.PrimaryKeyValue) !== null && _a !== void 0 ? _a : result.LastInsertId - data.length + idx; | ||
} | ||
}); | ||
} | ||
else if (data instanceof ModelBase) { | ||
data.PrimaryKeyValue = (_a = data.PrimaryKeyValue) !== null && _a !== void 0 ? _a : result.LastInsertId; | ||
} | ||
return result; | ||
}, | ||
modelCreation: () => null, | ||
afterHydration: () => null, | ||
}; | ||
query.middleware(iMidleware); | ||
return query; | ||
@@ -426,21 +551,11 @@ }, | ||
async findOrFail(pks) { | ||
const { query, description } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
const { query, description, model } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
const pkey = description.PrimaryKey; | ||
const middleware = { | ||
afterData(data) { | ||
if (data.length !== pks.length) { | ||
throw new Error(`could not find all of pkeys in model ${this.model.name}`); | ||
} | ||
return data; | ||
}, | ||
modelCreation(_) { | ||
return null; | ||
}, | ||
// tslint:disable-next-line: no-empty | ||
async afterHydration(_data) { }, | ||
}; | ||
query.select('*'); | ||
query.whereIn(pkey, pks); | ||
query.middleware(middleware); | ||
return await query; | ||
const result = await query; | ||
if (result.length !== pks.length) { | ||
throw new Error(`could not find all results for model ${model.name}`); | ||
} | ||
return result; | ||
}, | ||
@@ -452,2 +567,3 @@ async get(pk) { | ||
query.where(pkey, pk); | ||
_prepareOrderBy(description, query); | ||
return await query.first(); | ||
@@ -460,2 +576,3 @@ }, | ||
query.where(pkey, pk); | ||
_prepareOrderBy(description, query); | ||
return await query.firstOrFail(); | ||
@@ -466,8 +583,8 @@ }, | ||
const description = _descriptor(this); | ||
const orm = di_1.DI.get(orm_1.Orm); | ||
const driver = orm.Connections.get(description.Connection); | ||
const converter = driver.Container.resolve(interfaces_1.DatetimeValueConverter); | ||
const data = Array.isArray(pks) ? pks : [pks]; | ||
if ((_a = description.SoftDelete) === null || _a === void 0 ? void 0 : _a.DeletedAt) { | ||
const { query } = _createQuery(this, builders_1.UpdateQueryBuilder); | ||
const orm = di_1.DI.get(orm_1.Orm); | ||
const driver = orm.Connections.get(description.Connection); | ||
const converter = driver.Container.resolve(interfaces_1.DatetimeValueConverter); | ||
await query.whereIn(description.PrimaryKey, data).update({ | ||
@@ -490,3 +607,5 @@ [description.SoftDelete.DeletedAt]: converter.toDB(new Date()), | ||
// pk constrain | ||
query.where(description.PrimaryKey, pk); | ||
if (description.PrimaryKey) { | ||
query.where(description.PrimaryKey, pk); | ||
} | ||
// check for all unique columns ( unique constrain ) | ||
@@ -496,2 +615,3 @@ description.Columns.filter((c) => c.Unique).forEach((c) => { | ||
}); | ||
_prepareOrderBy(description, query); | ||
let entity = (await query.first()); | ||
@@ -508,3 +628,5 @@ if (!entity) { | ||
// pk constrain | ||
query.where(description.PrimaryKey, pk); | ||
if (description.PrimaryKey) { | ||
query.where(description.PrimaryKey, pk); | ||
} | ||
// check for all unique columns ( unique constrain ) | ||
@@ -514,2 +636,3 @@ description.Columns.filter((c) => c.Unique).forEach((c) => { | ||
}); | ||
_prepareOrderBy(description, query); | ||
let entity = (await query.first()); | ||
@@ -522,3 +645,55 @@ if (!entity) { | ||
}, | ||
async first(callback) { | ||
const { query, description } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
_prepareOrderBy(description, query, enums_1.SORT_ORDER.ASC); | ||
if (callback) { | ||
callback(query); | ||
} | ||
return await query.first(); | ||
}, | ||
async last(callback) { | ||
const { query, description } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
_prepareOrderBy(description, query, enums_1.SORT_ORDER.DESC); | ||
if (callback) { | ||
callback(query); | ||
} | ||
return await query.first(); | ||
}, | ||
async newest(callback) { | ||
var _a; | ||
const { query, description } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
if ((_a = description.Timestamps) === null || _a === void 0 ? void 0 : _a.CreatedAt) { | ||
query.order(description.Timestamps.CreatedAt, enums_1.SORT_ORDER.DESC); | ||
} | ||
else { | ||
throw new exceptions_1.OrmException('cannot fetch newest entity - CreateAt column not exists in model/db'); | ||
} | ||
if (callback) { | ||
callback(query); | ||
} | ||
return await query.first(); | ||
}, | ||
async oldest(callback) { | ||
var _a; | ||
const { query, description } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
if ((_a = description.Timestamps) === null || _a === void 0 ? void 0 : _a.CreatedAt) { | ||
query.order(description.Timestamps.CreatedAt, enums_1.SORT_ORDER.ASC); | ||
} | ||
else { | ||
throw new exceptions_1.OrmException('cannot fetch oldest entity - CreateAt column not exists in model/db'); | ||
} | ||
if (callback) { | ||
callback(query); | ||
} | ||
return await query.first(); | ||
}, | ||
async count(callback) { | ||
const { query } = _createQuery(this, builders_1.SelectQueryBuilder); | ||
query.count('*', 'count'); | ||
if (callback) { | ||
callback(query); | ||
} | ||
return await (await query.asRaw()).count; | ||
}, | ||
}; | ||
//# sourceMappingURL=model.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,2 +24,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __metadata = (this && this.__metadata) || function (k, v) { | ||
@@ -19,3 +42,3 @@ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); | ||
const reflection_1 = require("@spinajs/reflection"); | ||
const _ = require("lodash"); | ||
const _ = __importStar(require("lodash")); | ||
const interfaces_1 = require("./interfaces"); | ||
@@ -25,4 +48,4 @@ const model_1 = require("./model"); | ||
const exceptions_1 = require("@spinajs/exceptions"); | ||
const exceptions_2 = require("./exceptions"); | ||
const luxon_1 = require("luxon"); | ||
const exceptions_2 = require("./exceptions"); | ||
/** | ||
@@ -252,3 +275,3 @@ * Used to exclude sensitive data to others. eg. removed password field from cfg | ||
const migrationTableName = (_b = (_a = cn.Options.Migration) === null || _a === void 0 ? void 0 : _a.Table) !== null && _b !== void 0 ? _b : MIGRATION_TABLE_NAME; | ||
const exists = await cn.select().from(migrationTableName).where({ Migration: m.name }).first(); | ||
const exists = await cn.select().from(migrationTableName).where({ Migration: m.name }).orderByDescending('CreatedAt').first(); | ||
if (!exists) { | ||
@@ -266,3 +289,3 @@ const migration = await this.Container.resolve(m.type, [cn]); | ||
// if there is no info on migraiton table | ||
const migrationTableExists = await connection.schema().tableExists(migrationTableName); | ||
const migrationTableExists = await connection.schema().tableExists(migrationTableName, connection.Options.Database); | ||
if (!migrationTableExists) { | ||
@@ -269,0 +292,0 @@ this.Log.info(`No migration table in database, recreating migration information ...`); |
@@ -24,3 +24,3 @@ import { IRelationDescriptor, IModelDescrtiptor, IBuilderMiddleware, InsertBehaviour, ForwardRefFunction } from './interfaces'; | ||
constructor(_description: IModelDescrtiptor); | ||
afterData(data: any[]): any[]; | ||
afterQuery(data: any[]): any[]; | ||
modelCreation(data: any): ModelBase; | ||
@@ -27,0 +27,0 @@ afterHydration(_data: ModelBase[]): Promise<void>; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,2 +24,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __metadata = (this && this.__metadata) || function (k, v) { | ||
@@ -22,3 +45,3 @@ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); | ||
const orm_1 = require("./orm"); | ||
const _ = require("lodash"); | ||
const _ = __importStar(require("lodash")); | ||
class OrmRelation { | ||
@@ -37,3 +60,3 @@ constructor(_orm, _query, _description, parentRelation) { | ||
if (driver.Options.Database) { | ||
this._relationQuery.schema(driver.Options.Database); | ||
this._relationQuery.database(driver.Options.Database); | ||
} | ||
@@ -52,3 +75,3 @@ } | ||
} | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -70,3 +93,3 @@ } | ||
const hydrateMiddleware = { | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -110,3 +133,3 @@ }, | ||
} | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -121,3 +144,3 @@ } | ||
const hydrateMiddleware = { | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -158,3 +181,3 @@ }, | ||
} | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -169,3 +192,3 @@ } | ||
const hydrateMiddleware = { | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data.map((d) => Object.assign({}, d[self._description.Name], { JunctionModel: self.pickProps(d, [self._description.Name]) })); | ||
@@ -204,3 +227,3 @@ }, | ||
class BelongsToRelationResultTransformMiddleware { | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data.map((d) => { | ||
@@ -257,3 +280,3 @@ const transformedData = Object.assign(d); | ||
} | ||
afterData(data) { | ||
afterQuery(data) { | ||
return data; | ||
@@ -377,3 +400,3 @@ } | ||
if (driver.Options.Database) { | ||
this._joinQuery.schema(driver.Options.Database); | ||
this._joinQuery.database(driver.Options.Database); | ||
} | ||
@@ -380,0 +403,0 @@ this._joinQuery.from(this._joinModelDescriptor.TableName, `$${this._joinModelDescriptor.TableName}$`); |
import { SelectQueryBuilder, WhereBuilder, RawQuery } from './builders'; | ||
import { ColumnMethods, WhereOperators, JoinMethod } from './enums'; | ||
import { ColumnMethods, SqlOperator, JoinMethod } from './enums'; | ||
import { Container, Class } from '@spinajs/di'; | ||
@@ -53,6 +53,6 @@ import { IColumnDescriptor } from './interfaces'; | ||
protected _column: string | Wrap; | ||
protected _operator: WhereOperators; | ||
protected _operator: SqlOperator; | ||
protected _value: any; | ||
protected _container: Container; | ||
constructor(column: string, operator: WhereOperators, value: any, tableAlias: string, container: Container); | ||
constructor(column: string, operator: SqlOperator, value: any, tableAlias: string, container: Container); | ||
abstract build(): IQueryStatementResult; | ||
@@ -59,0 +59,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,2 +24,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __metadata = (this && this.__metadata) || function (k, v) { | ||
@@ -18,3 +41,3 @@ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); | ||
const di_1 = require("@spinajs/di"); | ||
const _ = require("lodash"); | ||
const _ = __importStar(require("lodash")); | ||
class QueryStatement { | ||
@@ -21,0 +44,0 @@ constructor(tableAlias) { |
{ | ||
"name": "@spinajs/orm", | ||
"version": "1.2.77", | ||
"version": "1.2.79", | ||
"description": "framework orm module", | ||
@@ -43,8 +43,8 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@spinajs/configuration": "^1.2.71", | ||
"@spinajs/di": "^1.2.68", | ||
"@spinajs/exceptions": "^1.2.7", | ||
"@spinajs/internal-logger": "^1.2.68", | ||
"@spinajs/log": "^1.2.75", | ||
"@spinajs/reflection": "^1.2.75", | ||
"@spinajs/configuration": "^1.2.79", | ||
"@spinajs/di": "^1.2.79", | ||
"@spinajs/exceptions": "^1.2.79", | ||
"@spinajs/internal-logger": "^1.2.79", | ||
"@spinajs/log": "^1.2.79", | ||
"@spinajs/reflection": "^1.2.79", | ||
"lodash": "^4.17.14", | ||
@@ -55,3 +55,3 @@ "luxon": "^2.3.0", | ||
}, | ||
"gitHead": "d5de22590f032ca82db60ebb9a7eb9fe7e7688ba" | ||
"gitHead": "ae595f5daffb88372496b6e5bf38973f07e33683" | ||
} |
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
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
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
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
354129
53
6208
Updated@spinajs/di@^1.2.79
Updated@spinajs/exceptions@^1.2.79
Updated@spinajs/log@^1.2.79
Updated@spinajs/reflection@^1.2.79