objection
Advanced tools
Comparing version 2.0.0-alpha.7 to 2.0.0-alpha.8
@@ -284,4 +284,4 @@ 'use strict'; | ||
$transaction() { | ||
return this.constructor.transaction(); | ||
$transaction(...args) { | ||
return this.constructor.transaction(...args); | ||
} | ||
@@ -592,4 +592,9 @@ | ||
static transaction() { | ||
return this.knex(); | ||
static transaction(knexOrTrx, cb) { | ||
if (!cb) { | ||
cb = knexOrTrx; | ||
knexOrTrx = null; | ||
} | ||
return (knexOrTrx || this.knex()).transaction(cb); | ||
} | ||
@@ -760,2 +765,10 @@ | ||
Object.defineProperties(Model, { | ||
isObjectionModelClass: { | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
} | ||
}); | ||
Object.defineProperties(Model.prototype, { | ||
@@ -762,0 +775,0 @@ $isObjectionModel: { |
@@ -14,2 +14,3 @@ 'use strict'; | ||
const FETCH_STRATEGY = 'fetchStrategy'; | ||
const ALLOW_REFS = 'allowRefs'; | ||
@@ -141,2 +142,6 @@ const FetchStrategy = { | ||
allowRefs() { | ||
return !!this.options[ALLOW_REFS]; | ||
} | ||
rebasedOptions(newRoot) { | ||
@@ -143,0 +148,0 @@ const newOpt = {}; |
'use strict'; | ||
const { ModelGraph } = require('../../model/graph/ModelGraph'); | ||
const { ModelGraphEdge } = require('../../model/graph/ModelGraphEdge'); | ||
const { createNotModelError } = require('../../model/graph/ModelGraphBuilder'); | ||
@@ -96,4 +97,24 @@ const { GraphOperation } = require('../graph/GraphOperation'); | ||
const deleteNodes = currentGraph.nodes.filter(currentNode => !graph.nodeForNode(currentNode)); | ||
const roots = findRoots(deleteNodes); | ||
removeBranchesFromGraph(findRoots(deleteNodes), currentGraph); | ||
// Don't delete relations the current graph doesn't even mention. | ||
// So if the parent node doesn't even have the relation, it's not | ||
// supposed to be deleted. | ||
const rootsNotInRelation = roots.filter(deleteRoot => { | ||
if (!deleteRoot.parentNode) { | ||
return false; | ||
} | ||
const { relation } = deleteRoot.parentEdge; | ||
const parentNode = graph.nodeForNode(deleteRoot.parentNode); | ||
if (!parentNode) { | ||
return false; | ||
} | ||
return parentNode.obj[relation.name] === undefined; | ||
}); | ||
removeBranchesFromGraph(roots, currentGraph); | ||
removeNodesFromGraph(new Set(rootsNotInRelation), currentGraph); | ||
} | ||
@@ -129,2 +150,6 @@ | ||
removeNodesFromGraph(nodesToRemove, graph); | ||
} | ||
function removeNodesFromGraph(nodesToRemove, graph) { | ||
const edgesToRemove = new Set(); | ||
@@ -153,2 +178,3 @@ | ||
checkForUnallowedRelationErrors(graph, builder); | ||
checkForUnallowedReferenceErrors(graph, graphOptions, builder); | ||
@@ -202,2 +228,16 @@ if (graphOptions.isInsertOnly()) { | ||
function checkForUnallowedReferenceErrors(graph, graphOptions, builder) { | ||
if (graphOptions.allowRefs()) { | ||
return; | ||
} | ||
if (graph.edges.some(edge => edge.type === ModelGraphEdge.Type.Reference)) { | ||
throw builder.modelClass().createValidationError({ | ||
type: ValidationErrorType.InvalidGraph, | ||
message: | ||
'#ref references are not allowed in a graph by default. see the allowRefs insert/upsert graph option' | ||
}); | ||
} | ||
} | ||
function checkForHasManyRelateErrors(graph, currentGraph, graphOptions) { | ||
@@ -204,0 +244,0 @@ for (const node of graph.nodes) { |
@@ -255,4 +255,12 @@ 'use strict'; | ||
Object.defineProperties(QueryBuilderOperation, { | ||
isObjectionQueryBuilderOperationClass: { | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
} | ||
}); | ||
module.exports = { | ||
QueryBuilderOperation | ||
}; |
@@ -28,7 +28,7 @@ 'use strict'; | ||
onBuild(builder) { | ||
super.onBuild(builder); | ||
if (!this.skipIdWhere) { | ||
builder.findById(this.id); | ||
} | ||
super.onBuild(builder); | ||
} | ||
@@ -44,6 +44,9 @@ | ||
const fetched = await builder | ||
.modelClass() | ||
.query() | ||
.emptyInstance() | ||
.childQueryOf(builder) | ||
.findById(this.id) | ||
.modify(builder => { | ||
if (!this.skipIdWhere) { | ||
builder.findById(this.id); | ||
} | ||
}) | ||
.castTo(builder.resultModelClass()); | ||
@@ -50,0 +53,0 @@ |
@@ -565,3 +565,3 @@ 'use strict'; | ||
clone() { | ||
const builder = new this.constructor(this.modelClass()); | ||
const builder = this.emptyInstance(); | ||
@@ -581,2 +581,8 @@ // Call the super class's clone implementation. | ||
return builder; | ||
} | ||
emptyInstance() { | ||
const builder = new this.constructor(this.modelClass()); | ||
builder._findOperationFactory = this._findOperationFactory; | ||
@@ -589,2 +595,3 @@ builder._insertOperationFactory = this._insertOperationFactory; | ||
builder._deleteOperationFactory = this._deleteOperationFactory; | ||
builder._relatedQueryFor = this._relatedQueryFor; | ||
@@ -1107,3 +1114,3 @@ return builder; | ||
range(...args) { | ||
return this.addOperation(new RangeOperation('range'), args); | ||
return this.clear(RangeOperation).addOperation(new RangeOperation('range'), args); | ||
} | ||
@@ -1110,0 +1117,0 @@ |
@@ -79,6 +79,2 @@ 'use strict'; | ||
skipLocked(...args) { | ||
return this.addOperation(new KnexOperation('skipLocked'), args); | ||
} | ||
as(...args) { | ||
@@ -85,0 +81,0 @@ return this.addOperation(new KnexOperation('as'), args); |
@@ -5,5 +5,3 @@ 'use strict'; | ||
const { isSubclassOf } = require('../utils/classUtils'); | ||
const { isString, isFunction, isRegExp, last } = require('../utils/objectUtils'); | ||
const { QueryBuilderOperation } = require('./operations/QueryBuilderOperation'); | ||
const { QueryBuilderContextBase } = require('./QueryBuilderContextBase'); | ||
@@ -472,3 +470,6 @@ const { QueryBuilderUserContext } = require('./QueryBuilderUserContext'); | ||
return op => op.name === operationSelector; | ||
} else if (isSubclassOf(operationSelector, QueryBuilderOperation)) { | ||
} else if ( | ||
isFunction(operationSelector) && | ||
operationSelector.isObjectionQueryBuilderOperationClass | ||
) { | ||
return op => op.is(operationSelector); | ||
@@ -475,0 +476,0 @@ } else if (isFunction(operationSelector)) { |
@@ -42,7 +42,3 @@ 'use strict'; | ||
.runAfter(models => { | ||
if (Array.isArray(this.input)) { | ||
return models; | ||
} else { | ||
return models[0]; | ||
} | ||
return Array.isArray(models) ? models.length : 1; | ||
}); | ||
@@ -49,0 +45,0 @@ } |
'use strict'; | ||
const { RelationProperty } = require('./RelationProperty'); | ||
const getModel = () => require('../model/Model').Model; | ||
@@ -10,3 +9,2 @@ const { RelationFindOperation } = require('./RelationFindOperation'); | ||
const { isSubclassOf } = require('../utils/classUtils'); | ||
const { resolveModel } = require('../utils/resolveModel'); | ||
@@ -235,2 +233,10 @@ const { get, isFunction } = require('../utils/objectUtils'); | ||
Object.defineProperties(Relation, { | ||
isObjectionRelationClass: { | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
} | ||
}); | ||
Object.defineProperties(Relation.prototype, { | ||
@@ -255,3 +261,3 @@ isObjectionRelation: { | ||
function checkOwnerModelClass(ctx) { | ||
if (!isSubclassOf(ctx.ownerModelClass, getModel())) { | ||
if (!isFunction(ctx.ownerModelClass) || !ctx.ownerModelClass.isObjectionModelClass) { | ||
throw ctx.createError(`Relation's owner is not a subclass of Model`); | ||
@@ -292,3 +298,3 @@ } | ||
if (!isSubclassOf(ctx.mapping.relation, Relation)) { | ||
if (!isFunction(ctx.mapping.relation) || !ctx.mapping.relation.isObjectionRelationClass) { | ||
throw ctx.createError('relation is not a subclass of Relation'); | ||
@@ -295,0 +301,0 @@ } |
@@ -45,3 +45,3 @@ 'use strict'; | ||
this._propSetters = paths.map(it => createSetter(it.path)); | ||
this._patchers = refs.map(it => createPatcher(it)); | ||
this._patchers = refs.map((it, i) => createPatcher(it, paths[i].path)); | ||
} | ||
@@ -239,5 +239,5 @@ | ||
function createPatcher(ref) { | ||
function createPatcher(ref, path) { | ||
if (ref.isPlainColumnRef) { | ||
return (patch, value) => (patch[ref.column] = value); | ||
return (patch, value) => (patch[path[0]] = value); | ||
} else { | ||
@@ -244,0 +244,0 @@ // Objection `patch`, `update` etc. methods understand field expressions. |
'use strict'; | ||
const { Model } = require('./model/Model'); | ||
const promiseUtils = require('./utils/promiseUtils'); | ||
const { isSubclassOf } = require('./utils/classUtils'); | ||
const { isFunction } = require('./utils/objectUtils'); | ||
@@ -20,3 +18,3 @@ | ||
if (!isSubclassOf(args[0], Model) && isFunction(args[0].transaction)) { | ||
if (!isModelClass(args[0]) && isFunction(args[0].transaction)) { | ||
let knex = args[0]; | ||
@@ -33,3 +31,3 @@ args = args.slice(1); | ||
for (i = 0; i < modelClasses.length; ++i) { | ||
if (!isSubclassOf(modelClasses[i], Model)) { | ||
if (!isModelClass(modelClasses[i])) { | ||
return Promise.reject( | ||
@@ -71,3 +69,3 @@ new Error('objection.transaction: all but the last argument should be Model subclasses') | ||
if (isSubclassOf(modelClassOrKnex, Model)) { | ||
if (isModelClass(modelClassOrKnex)) { | ||
knex = modelClassOrKnex.knex(); | ||
@@ -95,4 +93,8 @@ } | ||
function isModelClass(maybeModel) { | ||
return isFunction(maybeModel) && maybeModel.isObjectionModelClass; | ||
} | ||
module.exports = { | ||
transaction | ||
}; |
'use strict'; | ||
const { isFunction } = require('./objectUtils'); | ||
function isSubclassOf(Constructor, SuperConstructor) { | ||
if (!isFunction(SuperConstructor)) { | ||
return false; | ||
} | ||
while (isFunction(Constructor)) { | ||
if (Constructor === SuperConstructor) { | ||
return true; | ||
} | ||
Constructor = Object.getPrototypeOf(Constructor); | ||
} | ||
return false; | ||
} | ||
function inherit(Constructor, BaseConstructor) { | ||
@@ -30,4 +12,3 @@ Constructor.prototype = Object.create(BaseConstructor.prototype); | ||
module.exports = { | ||
isSubclassOf, | ||
inherit | ||
}; |
'use strict'; | ||
const path = require('path'); | ||
const { once, isString, isFunction } = require('../utils/objectUtils'); | ||
const { isSubclassOf } = require('../utils/classUtils'); | ||
const { isString, isFunction } = require('../utils/objectUtils'); | ||
const getModel = once(() => require('../model/Model').Model); | ||
class ResolveError extends Error {} | ||
@@ -19,7 +17,7 @@ | ||
} else { | ||
if (isFunction(modelRef) && !isSubclassOf(modelRef, getModel())) { | ||
if (isFunction(modelRef) && !isModelClass(modelRef)) { | ||
modelRef = modelRef(); | ||
} | ||
if (!isSubclassOf(modelRef, getModel())) { | ||
if (!isModelClass(modelRef)) { | ||
throw new ResolveError( | ||
@@ -62,3 +60,2 @@ `is not a subclass of Model or a file path to a module that exports one. You may be dealing with a require loop. See the documentation section about require loops.` | ||
function requireModel(modelPath) { | ||
const Model = getModel(); | ||
/** | ||
@@ -73,5 +70,5 @@ * Wrap path string in template literal to prevent | ||
if (isSubclassOf(mod, Model)) { | ||
if (isModelClass(mod)) { | ||
modelClass = mod; | ||
} else if (isSubclassOf(mod.default, Model)) { | ||
} else if (isModelClass(mod.default)) { | ||
// Babel 6 style of exposing default export. | ||
@@ -83,3 +80,3 @@ modelClass = mod.default; | ||
if (isSubclassOf(exp, Model)) { | ||
if (isModelClass(exp)) { | ||
if (modelClass !== null) { | ||
@@ -96,3 +93,3 @@ throw new ResolveError( | ||
if (!isSubclassOf(modelClass, Model)) { | ||
if (!isModelClass(modelClass)) { | ||
throw new ResolveError(`${modelPath} is an invalid file path to a model class`); | ||
@@ -108,4 +105,8 @@ } | ||
function isModelClass(maybeModel) { | ||
return isFunction(maybeModel) && maybeModel.isObjectionModelClass; | ||
} | ||
module.exports = { | ||
resolveModel | ||
}; |
{ | ||
"name": "objection", | ||
"version": "2.0.0-alpha.7", | ||
"version": "2.0.0-alpha.8", | ||
"description": "An SQL-friendly ORM for Node.js", | ||
@@ -77,3 +77,3 @@ "main": "lib/objection.js", | ||
"coveralls": "^3.0.6", | ||
"cross-env": "^5.2.0", | ||
"cross-env": "^6.0.0", | ||
"eslint": "^6.1.0", | ||
@@ -84,3 +84,3 @@ "eslint-plugin-prettier": "^3.1.0", | ||
"glob": "^7.1.4", | ||
"knex": "0.19.2", | ||
"knex": "0.19.4", | ||
"mocha": "^6.2.0", | ||
@@ -93,3 +93,3 @@ "mysql": "^2.17.1", | ||
"typescript": "3.5.3", | ||
"vuepress": "1.0.3" | ||
"vuepress": "1.0.4" | ||
}, | ||
@@ -96,0 +96,0 @@ "nyc": { |
@@ -15,5 +15,5 @@ /// <reference types="node" /> | ||
import * as knex from 'knex'; | ||
import * as ajv from 'ajv'; | ||
import * as dbErrors from 'db-errors'; | ||
import * as knex from 'knex'; | ||
@@ -72,2 +72,4 @@ export = Objection; | ||
now(precision: number): FunctionBuilder; | ||
now(): FunctionBuilder; | ||
coalesce: SqlFunctionShortcut; | ||
@@ -161,3 +163,3 @@ concat: SqlFunctionShortcut; | ||
type Modifier<QB extends AnyQueryBuilder = AnyQueryBuilder> = | ||
| ((qb: QB) => void) | ||
| ((qb: QB, ...args: any[]) => void) | ||
| string | ||
@@ -295,2 +297,5 @@ | object; | ||
<QBP extends QB>(columns: Selection<QBP>[]): QB; | ||
// Allows things like `select(1)`, not sure if we should be more specific here? | ||
<QBP extends QB>(...args: any[]): QB; | ||
} | ||
@@ -369,3 +374,3 @@ | ||
interface WhereJsonSupersetOfMethod<QB extends AnyQueryBuilder> { | ||
interface WhereJson<QB extends AnyQueryBuilder> { | ||
( | ||
@@ -377,6 +382,18 @@ fieldExpression: FieldExpression, | ||
interface WhereJsonIsArrayMethod<QB extends AnyQueryBuilder> { | ||
interface WhereFieldExpression<QB extends AnyQueryBuilder> { | ||
(fieldExpression: FieldExpression): QB; | ||
} | ||
interface WhereJsonExpression<QB extends AnyQueryBuilder> { | ||
(fieldExpression: FieldExpression, keys: string | string[]): QB; | ||
} | ||
interface WhereJsonField<QB extends AnyQueryBuilder> { | ||
( | ||
fieldExpression: FieldExpression, | ||
operator: string, | ||
value: boolean | number | string | null | ||
): QB; | ||
} | ||
interface WhereCompositeMethod<QB extends AnyQueryBuilder> { | ||
@@ -553,11 +570,11 @@ (column: ColumnRef, value: Value): QB; | ||
ids: MaybeCompositeId | Partial<RelatedModel> | Partial<RelatedModel>[] | ||
): SingleQueryBuilder<QB>; | ||
): NumberQueryBuilder<QB>; | ||
<RelatedModel extends Model>( | ||
ids: MaybeCompositeId | Partial<RelatedModel> | Partial<RelatedModel>[] | ||
): ArrayQueryBuilder<QB>; | ||
): NumberQueryBuilder<QB>; | ||
} | ||
interface UnrelateMethod<QB extends AnyQueryBuilder> { | ||
(): QB; | ||
(): NumberQueryBuilder<QB>; | ||
} | ||
@@ -714,2 +731,3 @@ | ||
relate?: boolean | string[]; | ||
allowRefs?: boolean; | ||
} | ||
@@ -741,2 +759,3 @@ | ||
noUnrelate?: boolean | string[]; | ||
allowRefs?: boolean; | ||
} | ||
@@ -868,4 +887,22 @@ | ||
whereJsonSupersetOf: WhereJsonSupersetOfMethod<this>; | ||
whereJsonIsArray: WhereJsonIsArrayMethod<this>; | ||
whereJsonSupersetOf: WhereJson<this>; | ||
orWhereJsonSupersetOf: WhereJson<this>; | ||
whereJsonNotSupersetOf: WhereJson<this>; | ||
orWhereJsonNotSupersetOf: WhereJson<this>; | ||
whereJsonSubsetOf: WhereJson<this>; | ||
orWhereJsonSubsetOf: WhereJson<this>; | ||
whereJsonNotSubsetOf: WhereJson<this>; | ||
orWhereJsonNotSubsetOf: WhereJson<this>; | ||
whereJsonIsArray: WhereFieldExpression<this>; | ||
orWhereJsonIsArray: WhereFieldExpression<this>; | ||
whereJsonNotArray: WhereFieldExpression<this>; | ||
orWhereJsonNotArray: WhereFieldExpression<this>; | ||
whereJsonIsObject: WhereFieldExpression<this>; | ||
orWhereJsonIsObject: WhereFieldExpression<this>; | ||
whereJsonNotObject: WhereFieldExpression<this>; | ||
orWhereJsonNotObject: WhereFieldExpression<this>; | ||
whereJsonHasAny: WhereJsonExpression<this>; | ||
orWhereJsonHasAny: WhereJsonExpression<this>; | ||
whereJsonHasAll: WhereJsonExpression<this>; | ||
orWhereJsonHasAll: WhereJsonExpression<this>; | ||
@@ -1003,3 +1040,2 @@ having: WhereMethod<this>; | ||
forShare: IdentityMethod<this>; | ||
skipLocked: IdentityMethod<this>; | ||
skipUndefined: IdentityMethod<this>; | ||
@@ -1217,7 +1253,3 @@ debug: IdentityMethod<this>; | ||
export interface Transaction extends knex { | ||
savepoint(transactionScope: (trx: Transaction) => any): Promise<any>; | ||
commit<QM>(value?: any): Promise<QM>; | ||
rollback<QM>(error?: Error): Promise<QM>; | ||
} | ||
export type Transaction = knex.Transaction; | ||
@@ -1396,2 +1428,7 @@ export interface RelationMappings { | ||
interface TransactionMethod { | ||
<T>(callback: (trx: Transaction) => Promise<T>): Promise<T>; | ||
<T>(trxOrKnex: Transaction | knex, callback: (trx: Transaction) => Promise<T>): Promise<T>; | ||
} | ||
interface BindKnexMethod { | ||
@@ -1470,2 +1507,3 @@ <M>(this: M, trxOrKnex: Transaction | knex): M; | ||
static startTransaction(knexOrTransaction?: Transaction | knex): Transaction; | ||
static transaction: TransactionMethod; | ||
@@ -1472,0 +1510,0 @@ static bindKnex: BindKnexMethod; |
617919
19253