Socket
Socket
Sign inDemoInstall

objection

Package Overview
Dependencies
Maintainers
2
Versions
200
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

objection - npm Package Compare versions

Comparing version 0.5.0-alpha.2 to 0.5.0-rc.1

lib/utils/decorators/deprecated.js

903

lib/model/Model.js

@@ -74,4 +74,10 @@ 'use strict';

var _decorators = require('../utils/decorators');
var _deprecated = require('../utils/decorators/deprecated');
var _deprecated2 = _interopRequireDefault(_deprecated);
var _memoize = require('../utils/decorators/memoize');
var _memoize2 = _interopRequireDefault(_memoize);
var _Relation = require('../relations/Relation');

@@ -128,88 +134,3 @@

/**
* Subclasses of this class represent database tables.
*
* Subclass can be created like this:
*
* ```js
* var Model = require('objection').Model;
*
* function Person() {
* Model.apply(this, arguments);
* }
*
* Model.extend(Person);
* module.exports = Person;
*
* // Table name is the only required property.
* Person.tableName = 'Person';
*
* // This is not the database schema! Nothing is generated based on this. Whenever a
* // Person object is created from a JSON object, the JSON is checked against this
* // schema. For example when you call Person.fromJson({firstName: 'Jennifer'});
* Person.jsonSchema = {
* type: 'object',
* required: ['firstName', 'lastName'],
*
* properties: {
* id: {type: 'integer'},
* parentId: {type: ['integer', 'null']},
* firstName: {type: 'string', minLength: 1, maxLength: 255},
* lastName: {type: 'string', minLength: 1, maxLength: 255},
* age: {type: 'number'},
*
* address: {
* type: 'object',
* properties: {
* street: {type: 'string'},
* city: {type: 'string'},
* zipCode: {type: 'string'}
* }
* }
* }
* };
*
* // This object defines the relations to other models.
* Person.relationMappings = {
* pets: {
* relation: Model.HasManyRelation,
* // The related model. This can be either a Model subclass constructor or an
* // absolute file path to a module that exports one. We use the file path version
* // here to prevent require loops.
* modelClass: __dirname + '/Animal',
* join: {
* from: 'Person.id',
* to: 'Animal.ownerId'
* }
* },
*
* movies: {
* relation: Model.ManyToManyRelation,
* modelClass: __dirname + '/Movie',
* join: {
* from: 'Person.id',
* // ManyToMany relation needs the `through` object to describe the join table.
* through: {
* from: 'Person_Movie.personId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* },
*
* children: {
* relation: Model.HasManyRelation,
* modelClass: Person,
* join: {
* from: 'Person.id',
* to: 'Person.parentId'
* }
* }
* };
* ```
*
* @extends ModelBase
* @constructor
*/
var Model = (_dec = (0, _decorators.deprecated)({ removedIn: '0.7.0', useInstead: 'BelongsToOneRelation' }), _dec2 = (0, _decorators.deprecated)({ removedIn: '0.7.0', useInstead: 'HasManyRelation' }), (_class = (_temp = _class2 = function (_ModelBase) {
var Model = (_dec = (0, _deprecated2.default)({ removedIn: '0.7.0', useInstead: 'BelongsToOneRelation' }), _dec2 = (0, _deprecated2.default)({ removedIn: '0.7.0', useInstead: 'HasManyRelation' }), (_class = (_temp = _class2 = function (_ModelBase) {
(0, _inherits3.default)(Model, _ModelBase);

@@ -226,24 +147,4 @@

/**
* Returns or sets the identifier of a model instance.
*
* ```js
* // Returns the id.
* model.$id();
* // Sets the id.
* model.$id(100);
* ```
*
* The identifier property does not have to be accessed or set using this method.
* If the identifier property is known it can be accessed or set just like any
* other property:
*
* ```js
* console.log(model.id);
* model.id = 100;
* ```
*
* This method is just a helper for the cases where the id property is not known.
*
* @param {*=} id
* @returns {*}
* @param {string|number|Array.<string|number>=} id
* @returns {string|number|Array.<string|number>}
*/

@@ -259,4 +160,2 @@ value: function $id() {

/**
* Shortcut to `this.constructor.knex()`.
*
* @returns {knex}

@@ -272,4 +171,2 @@ */

/**
* Shortcut to `this.constructor.transaction()`.
*
* @returns {knex}

@@ -285,44 +182,2 @@ */

/**
* Creates a query builder for this model instance.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* All queries built using the returned builder only affect this instance.
*
* Examples:
*
* Re-fetch the instance from the database:
*
* ```js
* person.$query().then(function (person) {
* console.log(person);
* });
* ```
*
* Insert a new model to database:
*
* ```js
* Person.fromJson({firstName: 'Jennifer'}).$query().insert().then(function (jennifer) {
* console.log(jennifer.id);
* });
* ```
*
* Patch a model:
*
* ```js
* person.$query().patch({lastName: 'Cooper'}).then(function (person) {
* console.log(person.lastName); // --> 'Cooper'.
* });
* ```
*
* Delete a model.
*
* ```js
* person.$query().delete().then(function () {
* console.log('person deleted');
* });
* ```
*
* @returns {QueryBuilder}

@@ -376,119 +231,3 @@ */

/**
* Use this to build a query that only affects the models related to this instance through a relation.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* Examples:
*
* Fetch all models related to this instance through a relation. The fetched models are
* also stored to the owner model's property named after the relation:
*
* ```js
* jennifer.$relatedQuery('pets').then(function (pets) {
* console.log('jennifer has', pets.length, 'pets');
* console.log(jennifer.pets === pets); // --> true
* });
* ```
*
* The related query is just like any other query. All *knex* methods are available:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .select('Animal.*', 'Person.name as ownerName')
* .where('species', '=', 'dog')
* .orWhere('breed', '=', 'cat')
* .innerJoin('Person', 'Person.id', 'Animal.ownerId')
* .orderBy('Animal.name')
* .then(function (dogsAndCats) {
* // All the dogs and cats have the owner's name "Jennifer" joined as the `ownerName` property.
* console.log(dogsAndCats);
* });
* ```
*
* This inserts a new model to the database and binds it to the owner model as defined
* by the relation:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .insert({species: 'dog', name: 'Fluffy'})
* .then(function (waldo) {
* console.log(waldo.id);
* });
* ```
*
* To add an existing model to a relation the `relate` method can be used. In this example
* the dog `fluffy` already exists in the database but it isn't related to `jennifer` through
* the `pets` relation. We can make the connection like this:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .relate(fluffy.id)
* .then(function () {
* console.log('fluffy is now related to jennifer through pets relation');
* });
* ```
*
* The connection can be removed using the `unrelate` method. Again, this doesn't delete the
* related model. Only the connection is removed. For example in the case of ManyToMany relation
* the join table entries are deleted.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .unrelate()
* .where('id', fluffy.id)
* .then(function () {
* console.log('jennifer no longer has fluffy as a pet');
* });
* ```
*
* Related models can be deleted using the delete method. Note that in the case of ManyToManyRelation
* the join table entries are not deleted. Naturally the delete query can be chained with any *knex*
* methods.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .delete()
* .where('species', 'cat')
* .then(function () {
* console.log('jennifer no longer has any cats');
* });
* ```
*
* `update` and `patch` can be used to update related models. Only difference between the mentioned
* methods is that `update` validates the input objects using the related model class's full schema
* and `patch` ignores the `required` property of the schema. Use `update` when you want to update
* _all_ properties of a model and `patch` when only a subset should be updated.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .update({species: 'dog', name: 'Fluffy the great', vaccinated: false})
* .where('id', fluffy.id)
* .then(function (updatedFluffy) {
* console.log('fluffy\'s new name is', updatedFluffy.name);
* });
*
* // This will throw assuming that `name` or `species` is a required property for an Animal.
* jennifer.$relatedQuery('pets').patch({vaccinated: true});
*
* // This will _not_ throw.
* jennifer
* .$relatedQuery('pets')
* .patch({vaccinated: true})
* .where('species', 'dog')
* .then(function () {
* console.log('jennifer just got all her dogs vaccinated');
* });
* ```
*
* @param {string} relationName
* Name of the relation.
*
* @returns {QueryBuilder}

@@ -523,38 +262,2 @@ */

/**
* Loads related models using a {@link RelationExpression}.
*
* Example:
*
* ```js
* jennifer.$loadRelated('[pets, children.[pets, father]]').then(function (jennifer) {
* console.log('Jennifer has', jennifer.pets.length, 'pets');
* console.log('Jennifer has', jennifer.children.length, 'children');
* console.log('Jennifer\'s first child has', jennifer.children[0].pets.length, 'pets');
* console.log('Jennifer had her first child with', jennifer.children[0].father.name);
* });
* ```
*
* Relations can be filtered by giving named filter functions as arguments
* to the relations:
*
* ```js
* jennifer
* .$loadRelated('children(orderByAge).[pets(onlyDogs, orderByName), movies]', {
* orderByAge: function (builder) {
* builder.orderBy('age')
* },
* orderByName: function (builder) {
* builder.orderBy('name');
* },
* onlyDogs: function (builder) {
* builder.where('species', 'dog')
* }
* })
* .then(function (jennifer) {
* console.log(jennifer.children.pets[0]);
* });
* ```
*
* @see {@link RelationExpression} for more examples on relation expressions.
*
* @param {string|RelationExpression} relationExpression

@@ -572,7 +275,3 @@ * @param {Object.<string, function(QueryBuilder)>=} filters

/**
* Shortcut for `Model.traverse(filterConstructor, this, callback)`.
*
* See the static method `Model.traverse` for more info.
*
* @param {function=} filterConstructor
* @param {Constructor.<Model>=} filterConstructor
* @param {function(Model)} callback

@@ -593,7 +292,2 @@ * @return {Model}

}
/**
* @override
*/
}, {

@@ -618,7 +312,2 @@ key: '$parseDatabaseJson',

}
/**
* @override
*/
}, {

@@ -643,7 +332,2 @@ key: '$formatDatabaseJson',

}
/**
* @override
*/
}, {

@@ -677,6 +361,3 @@ key: '$setJson',

/**
* @override
*
* @param {boolean} shallow
* If true the relations are omitted from the json.
* @param {boolean=} shallow
*/

@@ -713,11 +394,3 @@

/**
* Called before a model is inserted into the database.
*
* You can return a promise from this function if you need to do asynchronous stuff. You can
* also throw an exception to abort the insert and reject the query. This can be useful if
* you need to do insert specific validation.
*
* @param {Object} queryContext
* The context object of the insert query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}

@@ -731,9 +404,3 @@ */

/**
* Called after a model has been inserted into the database.
*
* You can return a promise from this function if you need to do asynchronous stuff.
*
* @param {Object} queryContext
* The context object of the insert query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}

@@ -747,34 +414,4 @@ */

/**
* Called before a model is updated.
*
* You can return a promise from this function if you need to do asynchronous stuff. You can
* also throw an exception to abort the update and reject the query. This can be useful if
* you need to do update specific validation.
*
* This method is also called before a model is patched. Therefore all the model's properties
* may not exist. You can check if the update operation is a patch by checking the `opt.patch`
* boolean.
*
* Also note that this method is called only once when you do something like this:
*
* ```js
* Person
* .$query()
* .patch({firstName: 'Jennifer'})
* .where('gender', 'female')
* .then(function () {
* ...
* });
* ```
*
* The example above updates all rows whose `gender` equals `female` but the `$beforeUpdate`
* method is called only once for the `{firstName: 'Jennifer'}` model. This is because the
* updating is done completely in the database and the affected models are never fetched
* to the javascript side.
*
* @param {ModelOptions} opt
*
* @param {Object} queryContext
* The context object of the update query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}

@@ -788,32 +425,4 @@ */

/**
* Called after a model is updated.
*
* You can return a promise from this function if you need to do asynchronous stuff.
*
* This method is also called after a model is patched. Therefore all the model's properties
* may not exist. You can check if the update operation is a patch by checking the `opt.patch`
* boolean.
*
* Also note that this method is called only once when you do something like this:
*
* ```js
* Person
* .$query()
* .patch({firstName: 'Jennifer'})
* .where('gender', 'female')
* .then(function () {
* ...
* });
* ```
*
* The example above updates all rows whose `gender` equals `female` but the `$beforeUpdate`
* method is called only once for the `{firstName: 'Jennifer'}` model. This is because the
* updating is done completely in the database and the affected models are never fetched
* to the javascript side.
*
* @param {ModelOptions} opt
*
* @param {Object} queryContext
* The context object of the update query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}

@@ -827,104 +436,2 @@ */

/**
* Creates a query builder for this table.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* Examples:
*
* Read models from the database:
*
* ```js
* // Get all rows.
* Person.query().then(function(allPersons) {
* console.log('there are', allPersons.length, 'persons in the database');
* });
*
* // Example of a more complex WHERE clause. This generates:
* // SELECT * FROM "Person" WHERE ("firstName" = 'Jennifer' AND "age" < 30) OR ("firstName" = "Mark" AND "age" > 30)
* Person
* .query()
* .where(function () {
* this.where('firstName', 'Jennifer').where('age', '<', 30);
* })
* .orWhere(function () {
* this.where('firstName', 'Mark').where('age', '>', 30);
* })
* .then(function (marksAndJennifers) {
* console.log(marksAndJennifers);
* });
*
* // Get a subset of rows and fetch related models for each row.
* Person
* .query()
* .where('age', '>', 60)
* .eager('children.children.movies')
* .then(function (oldPeople) {
* console.log('some old person\'s grand child has appeared in',
* oldPeople[0].children[0].children[0].movies.length,
* 'movies');
* });
* ```
*
* Insert models to the database:
*
* ```js
* Person.query().insert({firstName: 'Sylvester', lastName: 'Stallone'}).then(function (sylvester) {
* console.log(sylvester.fullName()); // --> 'Sylvester Stallone'.
* });
*
* // Batch insert. This only works on Postgresql as it is the only database that returns the
* // identifiers of _all_ inserted rows. If you need to do batch inserts on other databases use
* // *knex* directly. (See .knexQuery() method).
* Person
* .query()
* .insert([
* {firstName: 'Arnold', lastName: 'Schwarzenegger'},
* {firstName: 'Sylvester', lastName: 'Stallone'}
* ])
* .then(function (inserted) {
* console.log(inserted[0].fullName()); // --> 'Arnold Schwarzenegger'
* });
* ```
*
* `update` and `patch` can be used to update models. Only difference between the mentioned methods
* is that `update` validates the input objects using the model class's full jsonSchema and `patch`
* ignores the `required` property of the schema. Use `update` when you want to update _all_ properties
* of a model and `patch` when only a subset should be updated.
*
* ```js
* Person
* .query()
* .update({firstName: 'Jennifer', lastName: 'Lawrence', age: 35})
* .where('id', jennifer.id)
* .then(function (updatedJennifer) {
* console.log('Jennifer is now', updatedJennifer.age, 'years old');
* });
*
* // This will throw assuming that `firstName` or `lastName` is a required property for a Person.
* Person.query().patch({age: 100});
*
* // This will _not_ throw.
* Person
* .query()
* .patch({age: 100})
* .then(function () {
* console.log('Everyone is now 100 years old');
* });
* ```
*
* Models can be deleted using the delete method. Naturally the delete query can be chained with
* any *knex* methods:
*
* ```js
* Person
* .query()
* .delete()
* .where('age', '>', 90)
* .then(function () {
* console.log('anyone over 90 is now removed from the database');
* });
* ```
*
* @returns {QueryBuilder}

@@ -946,22 +453,3 @@ */

/**
* Get/Set the knex instance for this model class.
*
* Subclasses inherit the connection. A system-wide knex instance can thus be set by calling
* `Model.knex(knex)`. This works even after subclasses have been created.
*
* ```js
* var knex = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database.db'
* }
* });
*
* Model.knex(knex);
* knex = Model.knex();
* ```
*
* @param {knex=} knex
* The knex to set.
*
* @returns {knex}

@@ -988,16 +476,2 @@ */

/**
* Returns the transaction this model class is bound to using `bindTransaction` methods.
*
* Handy for making sure two model class are bound to the same transaction:
*
* ```js
* Person
* .bindTransaction(Animal.transaction())
* .query()
* ...
* ```
*
* The example above works even if `Animal` is not bound to any transaction. The
* `bindTransaction` call does nothing in this case.
*
* @returns {knex}

@@ -1013,3 +487,3 @@ */

/**
* Shortcut for `SomeModel.knex().raw()`.
* @return {Raw}
*/

@@ -1025,3 +499,3 @@

/**
* Shortcut for `SomeModel.knex().fn`.
* @return {Object}
*/

@@ -1037,4 +511,2 @@

/**
* Shortcut for `SomeModel.knex().client.formatter()`.
*
* @return {Formatter}

@@ -1050,4 +522,2 @@ */

/**
* Shortcut for `SomeModel.knex().table(SomeModel.tableName)`.
*
* @returns {knex.QueryBuilder}

@@ -1063,46 +533,2 @@ */

/**
* Creates a subclass of this class that is bound to the given knex.
*
* This method can be used to bind a Model subclass to multiple databases for example in
* a multi tenant system.
*
* Example:
*
* ```js
* var knex1 = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database1.db'
* }
* });
*
* var knex2 = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database2.db'
* }
* });
*
* SomeModel.knex(null);
*
* var BoundModel1 = SomeModel.bindKnex(knex1);
* var BoundModel2 = SomeModel.bindKnex(knex2);
*
* // Throws since the knex instance is null.
* SomeModel.query().then();
*
* // Works.
* BoundModel1.query().then(function (models) {
* console.log(models[0] instanceof SomeModel); // --> true
* console.log(models[0] instanceof BoundModel1); // --> true
* });
*
* // Works.
* BoundModel2.query().then(function (models) {
* console.log(models[0] instanceof SomeModel); // --> true
* console.log(models[0] instanceof BoundModel2); // --> true
* });
*
* ```
*
* @param {knex} knex

@@ -1143,28 +569,3 @@ * @returns {Constructor.<Model>}

/**
* Creates a subclass of this class that is bound to the given transaction.
*
* ```js
* var Person = require('./models/Person');
* var transaction;
*
* objection.transaction.start(Person).then(function (trx) {
* transaction = trx;
* return Person
* .bindTransaction(transaction)
* .query()
* .insert({firstName: 'Jennifer'});
* }).then(function (jennifer) {
* return Person
* .bindTransaction(transaction)
* .query()
* .patch({lastName: 'Lawrence'})
* .where('id', jennifer.id);
* }).then(function () {
* return transaction.commit();
* }).catch(function () {
* return transaction.rollback();
* });
* ```
*
* @param trx
* @param {knex} trx
* @returns {Constructor.<Model>}

@@ -1180,6 +581,2 @@ */

/**
* Ensures that the given model is an instance of this class.
*
* If `model` is already an instance of this class, nothing is done.
*
* @param {Model|Object} model

@@ -1209,6 +606,2 @@ * @param {ModelOptions=} options

/**
* Ensures that each element in the given array is an instance of this class.
*
* If an element is already an instance of this class, nothing is done for it.
*
* @param {Array.<Model|Object>} input

@@ -1242,3 +635,2 @@ * @param {ModelOptions=} options

/**
* @ignore
* @returns {number}

@@ -1248,8 +640,12 @@ */

}, {
key: 'getIdColumnDimension',
value: function getIdColumnDimension() {
if (_lodash2.default.isArray(this.idColumn)) {
return this.idColumn.length;
key: 'getIdPropertyArray',
value: function getIdPropertyArray() {
var ModelClass = this;
if (_lodash2.default.isArray(ModelClass.idColumn)) {
return _lodash2.default.map(ModelClass.idColumn, function (col) {
return idColumnToIdProperty(ModelClass, col);
});
} else {
return 1;
return [idColumnToIdProperty(ModelClass, ModelClass.idColumn)];
}

@@ -1259,8 +655,2 @@ }

/**
* Returns the name of the identifier property.
*
* The identifier property is equal to the `idColumn` if `$parseDatabaseJson` is not
* implemented. If `$parseDatabaseJson` is implemented it may change the id property's
* name. This method passes the `idColumn` through `$parseDatabaseJson`.
*
* @returns {string|Array.<string>}

@@ -1284,4 +674,2 @@ */

/**
* Full identifier column name like 'SomeTable.id'.
*
* @returns {string|Array.<string>}

@@ -1305,4 +693,2 @@ */

/**
* All relations of this class.
*
* @return {Object.<string, Relation>}

@@ -1329,6 +715,2 @@ */

/**
* Get a relation by name.
*
* This should not be used to make queries. Use `$relatedQuery` or `loadRelated` instead.
*
* @return {Relation}

@@ -1350,32 +732,2 @@ */

/**
* Exactly like $loadRelated but for multiple instances.
*
* ```js
* Person.loadRelated([person1, person2], 'children.pets').then(function (persons) {
* var person1 = persons[0];
* var person2 = persons[1];
* });
* ```
*
* Relations can be filtered by giving named filter functions as arguments
* to the relations:
*
* ```js
* Person
* .loadRelated([person1, person2], 'children(orderByAge).[pets(onlyDogs, orderByName), movies]', {
* orderByAge: function (builder) {
* builder.orderBy('age')
* },
* orderByName: function (builder) {
* builder.orderBy('name');
* },
* onlyDogs: function (builder) {
* builder.where('species', 'dog')
* }
* })
* .then(function (persons) {
* console.log(persons[1].children.pets[0]);
* });
* ```
*
* @param {Array.<Model|Object>} $models

@@ -1405,38 +757,5 @@ * @param {string|RelationExpression} expression

/**
* Traverses the relation tree of a list of models.
*
* Calls the callback for each related model recursively. The callback is called
* also for the input models themselves.
*
* There are two ways to call this method:
*
* ```js
* Model.traverse(models, function (model, parentModel, relationName) {
* doSomething(model);
* });
* ```
*
* and
*
* ```js
* Model.traverse(Person, models, function (person, parentModel, relationName) {
* doSomethingForPerson(person);
* });
* ```
*
* In the second example the traverser function is only called for `Person` instances.
*
* @param {function=} filterConstructor
* If this optional constructor is given, the `traverser` is only called for
* models for which `model instanceof filterConstructor` returns true.
*
* @param {Constructor.<Model>=} filterConstructor
* @param {Model|Array.<Model>} models
* The model(s) whose relation trees to traverse.
*
* @param {function(Model, Model, string)} traverser
* The traverser function that is called for each model. The first argument
* is the model itself. If the model is in a relation of some other model
* the second argument is the parent model and the third argument is the
* name of the relation.
*
* @return {Model}

@@ -1505,50 +824,5 @@ */

key: 'OneToOneRelation',
/**
* one-to-many relation type.
*
* @type {OneToOneRelation}
*/
/**
* one-to-one relation type.
*
* @type {BelongsToOneRelation}
*/
/**
* QueryBuilder subclass to use in `$relatedQuery()` method.
*
* This constructor is used whenever a query builder is created using the `$relatedQuery()` method.
* You can override this to use your own `QueryBuilder` subclass.
*/
get: function get() {
return _BelongsToOneRelation2.default;
}
/**
* one-to-many relation type.
*
* @type {OneToManyRelation}
*/
/**
* one-to-many relation type.
*
* @type {HasManyRelation}
*/
/**
* one-to-one relation type.
*
* @type {HasOneRelation}
*/
/**
* QueryBuilder subclass to use in `query()` or `$query()` methods.
*
* This constructor is used whenever a query builder is created using `query()` or `$query()` methods.
* You can override this to use your own `QueryBuilder` subclass.
*/
}, {

@@ -1561,10 +835,2 @@ key: 'OneToManyRelation',

/**
* may-to-many relation type.
*
* @type {ManyToManyRelation}
*/
/**
* Name of the database table of this model.
*
* @type {string}

@@ -1574,8 +840,2 @@ */

/**
* Name of the primary key column in the database table.
*
* Composite id can be specified by giving an array of column names.
*
* Defaults to 'id'.
*
* @type {string|Array.<string>}

@@ -1585,6 +845,2 @@ */

/**
* Name of the property used to store a temporary non-db identifier for the model.
*
* Defaults to '#id'.
*
* @type {string}

@@ -1594,6 +850,2 @@ */

/**
* Name of the property used to store a reference to a `uidProp`.
*
* Defaults to '#ref'.
*
* @type {string}

@@ -1603,4 +855,2 @@ */

/**
* Regular expression for parsing a reference to a property.
*
* @type {RegExp}

@@ -1610,31 +860,2 @@ */

/**
* Properties that should be saved to database as JSON strings.
*
* The properties listed here are serialized to JSON strings upon insertion to the database
* and parsed back to objects when models are read from the database. Combined with the
* postgresql's json or jsonb data type, this is a powerful way of representing documents
* as single database rows.
*
* If this property is left unset all properties declared as objects or arrays in the
* `jsonSchema` are implicitly added to this list.
*
* Example:
*
* ```js
* Person.jsonAttributes = ['address'];
*
* var jennifer = Person.fromJson({
* name: 'Jennifer',
* address: {
* address: 'Someroad 10',
* zipCode: '1234',
* city: 'Los Angeles'
* }
* });
*
* var dbRow = jennifer.$toDatabaseJson();
* console.log(dbRow);
* // --> {name: 'Jennifer', address: '{"address":"Someroad 10","zipCode":"1234","city":"Los Angeles"}'}
* ```
*
* @type {Array.<string>}

@@ -1644,53 +865,2 @@ */

/**
* This property defines the relations to other models.
*
* Relations to other models can be defined by setting this property. The best way to explain how to
* do this is by example:
*
* ```js
* Person.relationMappings = {
* pets: {
* relation: Model.HasManyRelation,
* modelClass: Animal,
* join: {
* from: 'Person.id',
* to: 'Animal.ownerId'
* }
* },
*
* father: {
* relation: Model.BelongsToOneRelation,
* modelClass: Person,
* join: {
* from: 'Person.fatherId',
* to: 'Person.id'
* }
* },
*
* movies: {
* relation: Model.ManyToManyRelation,
* modelClass: Movie,
* join: {
* from: 'Person.id',
* through: {
* from: 'Person_Movie.actorId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* }
* };
* ```
*
* relationMappings is an object whose keys are relation names and values define the relation. The
* `join` property in addition to the relation type define how the models are related to one another.
* The `from` and `to` properties of the `join` object define the database columns through which the
* models are associated. Note that neither of these columns need to be primary keys. They can be any
* columns!. In the case of ManyToManyRelation also the join table needs to be defined. This is
* done using the `through` object.
*
* The `modelClass` passed to the relation mappings is the class of the related model. It can be either
* a Model subclass constructor or an absolute path to a module that exports one. Using file paths
* is a handy way to prevent require loops.
*
* @type {Object.<string, RelationMapping>}

@@ -1709,9 +879,5 @@ */

return Model;
}(_ModelBase3.default), _class2.QueryBuilder = _QueryBuilder2.default, _class2.RelatedQueryBuilder = _QueryBuilder2.default, _class2.HasOneRelation = _HasOneRelation2.default, _class2.BelongsToOneRelation = _BelongsToOneRelation2.default, _class2.HasManyRelation = _HasManyRelation2.default, _class2.ManyToManyRelation = _ManyToManyRelation2.default, _class2.tableName = null, _class2.idColumn = 'id', _class2.uidProp = '#id', _class2.uidRefProp = '#ref', _class2.propRefRegex = /#ref{([^\.]+)\.([^}]+)}/g, _class2.jsonAttributes = null, _class2.relationMappings = null, _class2.$$knex = null, _class2.$$relations = null, _temp), (_applyDecoratedDescriptor(_class, 'OneToOneRelation', [_dec], (0, _getOwnPropertyDescriptor2.default)(_class, 'OneToOneRelation'), _class), _applyDecoratedDescriptor(_class, 'OneToManyRelation', [_dec2], (0, _getOwnPropertyDescriptor2.default)(_class, 'OneToManyRelation'), _class), _applyDecoratedDescriptor(_class, 'getIdProperty', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class, 'getIdProperty'), _class), _applyDecoratedDescriptor(_class, 'getFullIdColumn', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class, 'getFullIdColumn'), _class)), _class));
}(_ModelBase3.default), _class2.QueryBuilder = _QueryBuilder2.default, _class2.RelatedQueryBuilder = _QueryBuilder2.default, _class2.HasOneRelation = _HasOneRelation2.default, _class2.BelongsToOneRelation = _BelongsToOneRelation2.default, _class2.HasManyRelation = _HasManyRelation2.default, _class2.ManyToManyRelation = _ManyToManyRelation2.default, _class2.tableName = null, _class2.idColumn = 'id', _class2.uidProp = '#id', _class2.uidRefProp = '#ref', _class2.propRefRegex = /#ref{([^\.]+)\.([^}]+)}/g, _class2.jsonAttributes = null, _class2.relationMappings = null, _class2.$$knex = null, _class2.$$relations = null, _temp), (_applyDecoratedDescriptor(_class, 'OneToOneRelation', [_dec], (0, _getOwnPropertyDescriptor2.default)(_class, 'OneToOneRelation'), _class), _applyDecoratedDescriptor(_class, 'OneToManyRelation', [_dec2], (0, _getOwnPropertyDescriptor2.default)(_class, 'OneToManyRelation'), _class), _applyDecoratedDescriptor(_class, 'getIdPropertyArray', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class, 'getIdPropertyArray'), _class), _applyDecoratedDescriptor(_class, 'getIdProperty', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class, 'getIdProperty'), _class), _applyDecoratedDescriptor(_class, 'getFullIdColumn', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class, 'getFullIdColumn'), _class)), _class));
exports.default = Model;
/**
* @private
*/
exports.default = Model;
function ensureArray(obj) {

@@ -1725,5 +891,2 @@ if (_lodash2.default.isArray(obj)) {

/**
* @private
*/
function _traverse(models, parent, relationName, modelClass, callback) {

@@ -1743,5 +906,2 @@ if (!_lodash2.default.isObject(models)) {

/**
* @private
*/
function traverseOne(model, parent, relationName, modelClass, callback) {

@@ -1763,5 +923,2 @@ if (!(model instanceof Model)) {

/**
* @private
*/
function idColumnToIdProperty(ModelClass, idColumn) {

@@ -1777,5 +934,2 @@ var idProperty = ModelClass.columnNameToPropertyName(idColumn);

/**
* @private
*/
function setId(model, id) {

@@ -1814,5 +968,2 @@ var idProp = model.constructor.getIdProperty();

/**
* @private
*/
function getId(model) {

@@ -1819,0 +970,0 @@ var idProp = model.constructor.getIdProperty();

'use strict';
var _desc, _value, _class, _class2, _temp;
var _dec, _dec2, _dec3, _desc, _value, _class, _class2, _temp;

@@ -38,6 +38,16 @@ Object.defineProperty(exports, "__esModule", {

var _hiddenDataGetterSetter = require('../utils/decorators/hiddenDataGetterSetter');
var _hiddenDataGetterSetter2 = _interopRequireDefault(_hiddenDataGetterSetter);
var _splitQueryProps = require('../utils/splitQueryProps');
var _splitQueryProps2 = _interopRequireDefault(_splitQueryProps);
var _classUtils = require('../utils/classUtils');
var _decorators = require('../utils/decorators');
var _memoize = require('../utils/decorators/memoize');
var _memoize2 = _interopRequireDefault(_memoize);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -78,89 +88,6 @@

* @property {boolean} [patch]
* If true the json is treated as a patch and the `required` field of the json schema is
* ignored in the validation. This allows us to create models with a subset of required
* properties for patch operations.
*
* @property {boolean} [skipValidation]
* If true the json schema validation is skipped.
*/
/**
* Base class for models.
*
* ModelBase provides a mechanism for automatic JSON validation and a way to attach
* functionality to plain javascript objects. A subclass can be created like this:
*
* ```js
* function Person() {
* ModelBase.apply(this, arguments);
* }
*
* ModelBase.extend(Person);
*
* Person.prototype.fullName = function () {
* return this.firstName + ' ' + this.lastName;
* };
*
* Person.jsonSchema = {
* type: 'object',
* properties: {
* id: {type: 'integer'},
* firstName: {type: 'string'},
* lastName: {type: 'string'}
* }
* };
* ```
*
* Use `ModelBase.from*Json` methods to create models from JSON objects:
*
* ```js
* var person = Person.fromJson({firstName: 'Jennifer', lastName: 'Lawrence'});
*
* console.log(person.firstName); // --> 'Jennifer'
* console.log(person.lastName); // --> 'Lawrence'
* console.log(person.fullName()); // --> 'Jennifer Lawrence'
*
* // This throws because the schema validation fails.
* var person2 = Person.fromJson({firstName: 10});
* ```
*
* Properties that are prefixed with '$' are excluded from all JSON representations:
*
* ```js
* var person = Person.fromJson({firstName: 'Jennifer');
* person.$spam = 100;
*
* console.log(person); // --> {firstName: 'Jennifer'}
* console.log(person.$toJson()); // --> {firstName: 'Jennifer'}
* ```
*
* ModelBase makes it possible to have a different database representation for a model.
* For example if your column names are snake_cased in the database but you want to use
* camelCased properties in the code and outside the server you can do this:
*
* ```js
* // This is called when an object is serialized to database format.
* Person.prototype.$formatDatabaseJson = function (json) {
* // Call superclass implementation.
* json = ModelBase.prototype.$formatDatabaseJson.call(this, json);
*
* return _.mapKeys(json, function (value, key) {
* return _.snakeCase(key);
* });
* };
*
* // This is called when an object is read from database.
* Person.prototype.$parseDatabaseJson = function (json) {
* json = _.mapKeys(json, function (value, key) {
* return _.camelCase(key);
* });
*
* // Call superclass implementation.
* return ModelBase.prototype.$parseDatabaseJson.call(this, json);
* };
* ```
*
* @constructor
*/
var ModelBase = (_class = (_temp = _class2 = function () {
var ModelBase = (_dec = (0, _hiddenDataGetterSetter2.default)('omitFromJson'), _dec2 = (0, _hiddenDataGetterSetter2.default)('omitFromDatabaseJson'), _dec3 = (0, _hiddenDataGetterSetter2.default)('stashedQueryProps'), (_class = (_temp = _class2 = function () {
function ModelBase() {

@@ -174,17 +101,6 @@ (0, _classCallCheck3.default)(this, ModelBase);

/**
* This is called before validation.
*
* Here you can dynamically edit the jsonSchema if needed.
*
* @param {Object} jsonSchema
* A deep clone of this class's jsonSchema.
*
* @param {Object} json
* The JSON object to be validated.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The (possibly) modified jsonSchema.
*/

@@ -197,32 +113,9 @@ value: function $beforeValidate(jsonSchema, json, options) {

/**
* Validates the given JSON object.
*
* Calls `$beforeValidation` and `$afterValidation` methods. This method is called
* automatically from `fromJson` and `$setJson` methods. This method can also be
* called explicitly when needed.
*
* @throws {ValidationError}
* If validation fails.
*
* @param {Object=} json
* If not given ==> this.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The input json
*/
/**
* The optional schema against which the JSON is validated.
*
* The jsonSchema can be dynamically modified in the `$beforeValidate` method.
*
* Must follow http://json-schema.org specification. If null no validation is done.
*
* @see $beforeValidate()
* @see $validate()
* @see $afterValidate()
*
* @type {Object}

@@ -262,11 +155,4 @@ */

/**
* This is called after successful validation.
*
* You can do further validation here and throw a ValidationError if something goes wrong.
*
* @param {Object=} json
* The JSON object to validate.
*
* @param {ModelOptions=} options
* Optional options.
*/

@@ -280,18 +166,4 @@

/**
* This is called when a ModelBase is created from a database JSON object.
*
* Converts the JSON object from the database format to the internal format.
*
* @note This function must handle the case where any subset of the columns comes
* in the `json` argument. You cannot assume that all columns are present as it
* depends on the select statement. There can also be additional columns because
* of join clauses, aliases etc.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in database format.
*
* @return {Object}
* The JSON object in internal format.
*/

@@ -306,13 +178,4 @@

/**
* This is called when a ModelBase is converted to database format.
*
* Converts the JSON object from the internal format to the database format.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in internal format.
*
* @return {Object}
* The JSON object in database format.
*/

@@ -327,16 +190,5 @@

/**
* This is called when a ModelBase is created from a JSON object.
*
* Converts the JSON object to the internal format.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in external format.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The JSON object in internal format.
*/

@@ -351,11 +203,4 @@

/**
* This is called when a ModelBase is converted to JSON.
*
* @note Remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in internal format
*
* @return {Object}
* The JSON object in external format.
*/

@@ -370,8 +215,3 @@

/**
* Exports this model as a database JSON object.
*
* Calls `$formatDatabaseJson()`.
*
* @return {Object}
* This model as a JSON object in database format.
*/

@@ -386,8 +226,3 @@

/**
* Exports this model as a JSON object.
*
* Calls `$formatJson()`.
*
* @return {Object}
* This model as a JSON object.
*/

@@ -400,9 +235,2 @@

}
/**
* Alias for `this.$toJson()`.
*
* For JSON.stringify compatibility.
*/
}, {

@@ -415,16 +243,6 @@ key: 'toJSON',

/**
* Sets the values from a JSON object.
*
* Validates the JSON before setting values. Calls `this.$parseJson()`.
*
* @param {Object} json
* The JSON object to set.
*
* @param {ModelOptions=} options
* Optional options.
*
* @returns {ModelBase} `this` for chaining.
*
* @returns {ModelBase}
* @throws ValidationError
* If validation fails.
*/

@@ -448,17 +266,21 @@

json = this.$parseJson(json, options);
json = this.$validate(json, options);
// If the json contains query properties like, knex Raw queries or knex/objection query
// builders, we need to split those off into a separate object. This object will be
// joined back in the $toDatabaseJson method.
var split = (0, _splitQueryProps2.default)(this.constructor, json);
return this.$set(json);
if (split.query) {
// Stash the query properties for later use in $toDatabaseJson method.
this.$stashedQueryProps(split.query);
}
split.json = this.$parseJson(split.json, options);
split.json = this.$validate(split.json, options);
return this.$set(split.json);
}
/**
* Sets the values from a JSON object in database format.
*
* Calls `this.$parseDatabaseJson()`.
*
* @param {Object} json
* The JSON object in database format.
*
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -481,9 +303,4 @@

/**
* Sets the values from another model or object.
*
* Unlike $setJson, this doesn't call any `$parseJson` methods or validate the input.
* This simply sets each value in the object to this object.
*
* @param {Object} obj
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -506,37 +323,31 @@

/**
* Omits a set of properties.
*
* The selected properties are set to `undefined`. Note that this is done in-place.
* Properties are set to undefined instead of deleting them for performance reasons
* (V8 doesn't like delete).
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit('lastName')
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit(['lastName'])
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit({lastName: true})
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* @param {Array.<string>=} keys
* @returns {Array.<string>}
*/
}, {
key: '$omitFromJson',
value: function $omitFromJson(keys) {}
/**
* @param {Array.<string>=} keys
* @returns {Array.<string>}
*/
}, {
key: '$omitFromDatabaseJson',
value: function $omitFromDatabaseJson(keys) {}
/**
* @param {Object=} queryProps
* @returns {Object}
*/
}, {
key: '$stashedQueryProps',
value: function $stashedQueryProps(queryProps) {}
/**
* @param {string|Array.<string>|Object.<string, boolean>} keys
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -563,35 +374,2 @@

/**
* Picks a set of properties.
*
* All other properties but the selected ones are set to `undefined`. Note that
* this is done in-place. Properties are set to undefined instead of deleting
* them for performance reasons (V8 doesn't like delete).
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick('firstName', 'age')
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick(['firstName', 'age'])
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick({firstName: true, age: true})
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* @param {string|Array.<string>|Object.<string, boolean>} keys

@@ -620,4 +398,2 @@ * @returns {ModelBase} `this` for chaining.

/**
* Returns the values of the given properties as an array.
*
* @param {Array.<string>} props

@@ -646,7 +422,2 @@ * @return {Array.<*>}

/**
* Returns a deep copy of this model.
*
* If this object has instances of ModelBase as properties (or arrays of them)
* they are cloned using their `.$clone()` method.
*
* @return {ModelBase}

@@ -688,6 +459,4 @@ */

/**
* Makes the given constructor a subclass of this class.
*
* @param {function=} subclassConstructor
* @return {function}
* @return {Constructor.<ModelBase>}
*/

@@ -707,16 +476,6 @@

/**
* Creates a model instance from a JSON object.
*
* The object is checked against `jsonSchema` and an exception is thrown on failure.
*
* @param {Object=} json
* The JSON from which to create the model.
*
* @param {ModelOptions=} options
* Optional options.
*
* @returns {Model}
*
* @throws ValidationError
* If validation fails.
*/

@@ -733,7 +492,3 @@

/**
* Creates a model instance from a JSON object in database format.
*
* @param {Object=} json
* The JSON from which to create the model.
*
* @returns {Model}

@@ -751,8 +506,2 @@ */

/**
* Omit implementation to use.
*
* The default just sets the property to undefined for performance reasons.
* If the slight performance drop is not an issue for you, you can override
* this method to delete the property instead.
*
* @param {Object} obj

@@ -769,3 +518,2 @@ * @param {string} prop

/**
* @ignore
* @param {string} columnName

@@ -791,3 +539,2 @@ * @returns {string}

/**
* @ignore
* @param {string} propertyName

@@ -813,9 +560,5 @@ * @returns {string}

return ModelBase;
}(), _class2.jsonSchema = null, _temp), (_applyDecoratedDescriptor(_class, 'columnNameToPropertyName', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class, 'columnNameToPropertyName'), _class), _applyDecoratedDescriptor(_class, 'propertyNameToColumnName', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class, 'propertyNameToColumnName'), _class)), _class);
}(), _class2.jsonSchema = null, _temp), (_applyDecoratedDescriptor(_class.prototype, '$omitFromJson', [_dec], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, '$omitFromJson'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, '$omitFromDatabaseJson', [_dec2], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, '$omitFromDatabaseJson'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, '$stashedQueryProps', [_dec3], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, '$stashedQueryProps'), _class.prototype), _applyDecoratedDescriptor(_class, 'columnNameToPropertyName', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class, 'columnNameToPropertyName'), _class), _applyDecoratedDescriptor(_class, 'propertyNameToColumnName', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class, 'propertyNameToColumnName'), _class)), _class));
exports.default = ModelBase;
/**
* @private
*/
exports.default = ModelBase;
function mergeWithDefaults(jsonSchema, json) {

@@ -853,5 +596,2 @@ var merged = null;

/**
* @private
*/
function tryValidate(jsonSchema, json, options) {

@@ -874,5 +614,2 @@ var required = undefined;

/**
* @private
*/
function parseValidationError(report) {

@@ -908,11 +645,17 @@ var errorHash = {};

/**
* @private
*/
function toJsonImpl(self, createDbJson, omit, pick) {
function toJsonImpl(model, createDbJson, omit, pick) {
var json = {};
_lodash2.default.each(self, function (value, key) {
if (key.charAt(0) !== '$' && !_lodash2.default.isFunction(value) && !_lodash2.default.isUndefined(value) && (!omit || !omit[key]) && (!pick || pick[key])) {
var omitFromJson = createDbJson ? model.$omitFromDatabaseJson() : model.$omitFromJson();
if (createDbJson) {
// If creating a database json object, restore the query properties.
_lodash2.default.each(model.$stashedQueryProps(), function (query, key) {
json[key] = query;
});
}
_lodash2.default.each(model, function (value, key) {
if (key.charAt(0) !== '$' && !_lodash2.default.isFunction(value) && !_lodash2.default.isUndefined(value) && (!omit || !omit[key]) && (!pick || pick[key]) && (!omitFromJson || !contains(omitFromJson, key))) {
if (_lodash2.default.isObject(value)) {

@@ -929,5 +672,2 @@ json[key] = toJsonObject(value, createDbJson);

/**
* @private
*/
function toJsonObject(value, createDbJson) {

@@ -942,2 +682,4 @@ if (_lodash2.default.isArray(value)) {

}
} else if (Buffer.isBuffer(value)) {
return value;
} else {

@@ -948,5 +690,2 @@ return _lodash2.default.cloneDeep(value);

/**
* @private
*/
function toJsonArray(value, createDbJson) {

@@ -958,5 +697,2 @@ return _lodash2.default.map(value, function (value) {

/**
* @private
*/
function cloneObject(value) {

@@ -967,2 +703,4 @@ if (_lodash2.default.isArray(value)) {

return value.$clone();
} else if (Buffer.isBuffer(value)) {
return new Buffer(value);
} else {

@@ -973,5 +711,2 @@ return _lodash2.default.cloneDeep(value);

/**
* @private
*/
function cloneArray(value) {

@@ -981,5 +716,2 @@ return _lodash2.default.map(value, cloneObject);

/**
* @private
*/
function omitObject(model, keyObj) {

@@ -995,5 +727,2 @@ var ModelClass = model.constructor;

/**
* @private
*/
function omitArray(model, keys) {

@@ -1009,5 +738,2 @@ var ModelClass = model.constructor;

/**
* @private
*/
function pickObject(model, keyObj) {

@@ -1023,5 +749,2 @@ var ModelClass = model.constructor;

/**
* @private
*/
function pickArray(model, keys) {

@@ -1037,5 +760,2 @@ var ModelClass = model.constructor;

/**
* @private
*/
function contains(arr, value) {

@@ -1042,0 +762,0 @@ for (var i = 0, l = arr.length; i < l; ++i) {

@@ -38,6 +38,2 @@ 'use strict';

/**
* @ignore
*/
var EagerFetcher = function () {

@@ -44,0 +40,0 @@ function EagerFetcher(_ref) {

@@ -26,28 +26,2 @@ 'use strict';

/**
* Internal representation of insert and update data.
*
* Data passed to update or insert queries can be:
*
* 1. Javascript primitives
* 2. knex raw SQL expressions
* 3. knex queries
* 4. objection queries
*
* This class splits the insert data into two parts:
*
* Part 1:
* * Javascript primitives
*
* Part 2:
* * everything else
*
* The part 1 is converted into `Model` instances and the part 2 is left untouched. As the `InsertionOrUpdate`
* instance passes through objection during an insert or update operation, the different functions can operate
* on the models (for example call $beforeInsert etc. methods on them). When the `InsertionOrUpdate` instance
* finally reaches knex, the two parts are glued back together.
*
* @ignore
*/
var InsertionOrUpdate = function () {

@@ -60,8 +34,5 @@ function InsertionOrUpdate(_ref) {

this.ModelClass = ModelClass;
this._models = [];
this._rawOrQuery = [];
this._modelClass = ModelClass;
this._arrayInput = false;
this._models = null;
this.setData(modelsOrObjects, modelOptions);

@@ -82,5 +53,2 @@ }

/**
* Returns true if the input to `setData` method was an array.
*
* @ignore
* @returns {boolean}

@@ -96,6 +64,3 @@ */

/**
* Sets the actual insert/update data.
*
* @ignore
* @param {(Object|Array.<Object>)} data
* @param {(Object|Array.<Object>)} modelsOrObjects
* @param {ModelOptions} modelOptions

@@ -106,72 +71,6 @@ */

key: 'setData',
value: function setData(data, modelOptions) {
var _this = this;
var knex = this.ModelClass.knex();
var KnexQueryBuilder = knex.client.QueryBuilder;
var Raw = knex.client.Raw;
// knex.QueryBuilder and knex.Raw are not documented properties.
// We make sure here that things break if knex changes things.
if (!_lodash2.default.isFunction(KnexQueryBuilder) || !_lodash2.default.isFunction(Raw)) {
throw new Error('knex API has changed: knex.QueryBuilder or knex.Raw constructor missing.');
}
this._models = [];
this._rawOrQuery = [];
this._arrayInput = _lodash2.default.isArray(data);
if (!this._arrayInput) {
data = _lodash2.default.isObject(data) ? [data] : [];
}
// Separate raw queries and query builders from javascript primitives.
// The javascript primitives are converted into a Model instance and the
// "query" properties are stored separately.
_lodash2.default.forEach(data, function (obj) {
if (obj instanceof _this.ModelClass) {
_this._models.push(obj);
_this._rawOrQuery.push({});
} else {
(function () {
var modelJson = {};
var rawOrSubquery = {};
_lodash2.default.forEach(obj, function (value, key) {
if (value instanceof KnexQueryBuilder || value instanceof Raw) {
rawOrSubquery[key] = value;
} else if (value instanceof _QueryBuilderBase2.default) {
rawOrSubquery[key] = value.build();
} else {
modelJson[key] = value;
}
});
_this._models.push(_this.ModelClass.fromJson(modelJson, modelOptions));
_this._rawOrQuery.push(rawOrSubquery);
})();
}
});
value: function setData(modelsOrObjects, modelOptions) {
this._models = this._modelClass.ensureModelArray(modelsOrObjects, modelOptions);
this._arrayInput = _lodash2.default.isArray(modelsOrObjects);
}
/**
* Create an object that can be given for the knex update or insert method.
*
* @ignore
* @returns {Object|Array.<Object>}
*/
}, {
key: 'toKnexInput',
value: function toKnexInput() {
var _this2 = this;
var knexInput = _lodash2.default.map(this._models, function (model, i) {
return _lodash2.default.merge(model.$toDatabaseJson(), _lodash2.default.mapKeys(_this2._rawOrQuery[i], function (value, key) {
return model.constructor.propertyNameToColumnName(key);
}));
});
return knexInput.length === 1 ? knexInput[0] : knexInput;
}
}]);

@@ -178,0 +77,0 @@ return InsertionOrUpdate;

@@ -52,9 +52,2 @@ 'use strict';

/**
* Given an model with nested relations, finds a fast way to insert the models into
* database so that not-null constraints are not broken.
*
* @ignore
*/
var InsertWithRelated = function () {

@@ -235,6 +228,3 @@ function InsertWithRelated(_ref) {

var sourceVal = node.model.$values(conn.relation.ownerProp);
var targetVal = conn.node.model.$values(conn.relation.relatedProp);
var joinModel = {};
var ownerProp = node.model.$values(conn.relation.ownerProp);
var knex = conn.relation.ownerModelClass.knex();

@@ -248,12 +238,5 @@ var modelClass = conn.relation.joinTableModelClass;

for (var i = 0; i < sourceVal.length; ++i) {
joinModel[conn.relation.joinTableOwnerProp[i]] = sourceVal[i];
}
var joinModel = conn.relation.createJoinModels(ownerProp, [conn.node.model]);
joinModel = modelClass.fromJson(joinModel[0]);
for (var i = 0; i < targetVal.length; ++i) {
joinModel[conn.relation.joinTableRelatedProp[i]] = targetVal[i];
}
joinModel = modelClass.fromJson(joinModel);
if (!tableInsertion) {

@@ -394,2 +377,3 @@ tableInsertion = new TableInsertion(modelClass, true);

this.relation = relation;
relation.omitExtraProps([node.model]);
}

@@ -396,0 +380,0 @@

@@ -34,66 +34,11 @@ 'use strict';

/**
* Relation expression is a simple DSL for expressing relation trees.
*
* For example an expression `children.[movies.actors.[pets, children], pets]` represents a tree:
*
* ```
* children
* (Person)
* |
* -----------------
* | |
* movies pets
* (Movie) (Animal)
* |
* actors
* (Person)
* |
* -----------
* | |
* pets children
* (Animal) (Person)
*
* ```
*
* The model classes are shown in parenthesis.
*
* This class rarely needs to be used directly. The relation expression can be given to a bunch
* of functions in objection.js. For example:
*
* ```js
* Person
* .query()
* .eager('children.[movies.actors.[pets, children], pets]')
* .then(function (persons) {
* // All persons have the given relation tree fetched.
* console.log(persons[0].children[0].movies[0].actors[0].pets[0].name);
* });
* ```
*
* There are two tokens that have special meaning: `*` and `^`. `*` means "all relations recursively" and
* `^` means "this relation recursively".
*
* For example `children.*` means "relation `children` and all its relations, and all their relations and ...".
* The `*` token must be used with caution or you will end up fetching your entire database.
*
* Expression `parent.^` is equivalent to `parent.parent.parent.parent...` up to the point a relation no longer
* has results for the `parent` relation.
*
* Relation expressions can also have arguments. Arguments are listed in parenthesis after the relation names
* like this:
*
* ```js
* children(arg1, arg2).[movies.actors(arg3), pets]
* ```
*
* In this example `children` relation had arguments `arg1` and `arg2` and `actors` relation had
* the argument `arg3`.
*/
var RECURSIVE_REGEX = /^\^(\d*)$/;
var ALL_RECURSIVE_REGEX = /^\*$/;
var RelationExpression = function () {
function RelationExpression(node) {
function RelationExpression(node, recursionDepth) {
(0, _classCallCheck3.default)(this, RelationExpression);
node = node || {};
this.name = node.name || null;

@@ -103,7 +48,10 @@ this.args = node.args || [];

this.children = node.children || {};
Object.defineProperty(this, 'recursionDepth', {
enumerable: false,
value: recursionDepth || 0
});
}
/**
* Parses an expression string into a {@link RelationExpression} object.
*
* @param {string|RelationExpression} expr

@@ -117,18 +65,2 @@ * @returns {RelationExpression}

/**
* Tests if another expression is a sub expression of this one.
*
* Expression B is a sub expression of expression A if:
*
* - A and B have the same root
* - And each path from root to a leaf in B can be found in A
*
* For example sub expressions of `children.[movies.actors, pets]` are:
*
* - `children`
* - `children.movies`
* - `children.pets`
* - `children.movies.actors`
* - `children.[movies, pets]`
* - `children.[movies.actors, pets]`
*
* @param {string|RelationExpression} expr

@@ -154,4 +86,6 @@ * @returns {boolean}

if (expr.isRecursive()) {
return this.isAllRecursive() || this.isRecursive();
var maxRecursionDepth = expr.maxRecursionDepth();
if (maxRecursionDepth > 0) {
return this.isAllRecursive() || this.maxRecursionDepth() >= maxRecursionDepth;
}

@@ -168,14 +102,30 @@

/**
* @ignore
* @returns {boolean}
* @returns {number}
*/
}, {
key: 'isRecursive',
value: function isRecursive() {
return !!this.children['^'];
key: 'maxRecursionDepth',
value: function maxRecursionDepth() {
if (this.numChildren !== 1) {
return 0;
}
return _lodash2.default.map(this.children, function (val, key) {
var rec = RECURSIVE_REGEX.exec(key);
if (rec) {
var maxDepth = rec[1];
if (maxDepth) {
return parseInt(maxDepth, 10);
} else {
return Number.POSITIVE_INFINITY;
}
} else {
return 0;
}
})[0];
}
/**
* @ignore
* @returns {boolean}

@@ -187,7 +137,8 @@ */

value: function isAllRecursive() {
return this.numChildren === 1 && !!this.children['*'];
return this.numChildren === 1 && _lodash2.default.all(this.children, function (val, key) {
return ALL_RECURSIVE_REGEX.test(key);
});
}
/**
* @ignore
* @returns {RelationExpression}

@@ -199,4 +150,4 @@ */

value: function childExpression(childName) {
if (this.isAllRecursive() || this.isRecursive() && childName === this.name) {
return this;
if (this.isAllRecursive() || childName === this.name && this.recursionDepth < this.maxRecursionDepth() - 1) {
return new RelationExpression(this, this.recursionDepth + 1);
}

@@ -212,3 +163,3 @@

/**
* @ignore
* @returns {RelationExpression}
*/

@@ -221,7 +172,2 @@

}
/**
* @ignore
*/
}, {

@@ -231,3 +177,3 @@ key: 'forEachChild',

_lodash2.default.each(this.children, function (child, childName) {
if (childName !== '*' && childName !== '^') {
if (!ALL_RECURSIVE_REGEX.test(childName) && !RECURSIVE_REGEX.test(childName)) {
cb(child, childName);

@@ -239,3 +185,2 @@ }

/**
* @ignore
* @return {Array.<RelationExpression>}

@@ -242,0 +187,0 @@ */

@@ -36,9 +36,8 @@ 'use strict';

var _normalizeIds = require('../utils/normalizeIds');
var _normalizeIds2 = _interopRequireDefault(_normalizeIds);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @ignore
* @extends Relation
*/
var BelongsToOneRelation = function (_Relation) {

@@ -54,7 +53,2 @@ (0, _inherits3.default)(BelongsToOneRelation, _Relation);

key: 'createRelationProp',
/**
* @override
* @inheritDoc
*/
value: function createRelationProp(owners, related) {

@@ -72,8 +66,2 @@ var _this2 = this;

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -105,8 +93,2 @@ key: 'insert',

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -117,3 +99,3 @@ key: 'relate',

ids = this.normalizeId(ids, this.relatedProp.length);
ids = (0, _normalizeIds2.default)(ids, this.relatedProp, { arrayOutput: true });

@@ -135,8 +117,2 @@ if (ids.length > 1) {

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -143,0 +119,0 @@ key: 'unrelate',

@@ -36,9 +36,8 @@ 'use strict';

var _normalizeIds = require('../utils/normalizeIds');
var _normalizeIds2 = _interopRequireDefault(_normalizeIds);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @ignore
* @extends Relation
*/
var HasManyRelation = function (_Relation) {

@@ -54,7 +53,2 @@ (0, _inherits3.default)(HasManyRelation, _Relation);

key: 'createRelationProp',
/**
* @override
* @inheritDoc
*/
value: function createRelationProp(owners, related) {

@@ -72,8 +66,2 @@ var _this2 = this;

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -99,7 +87,2 @@ key: 'insert',

}
/**
* @protected
*/
}, {

@@ -110,8 +93,2 @@ key: 'appendRelationProp',

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -122,3 +99,3 @@ key: 'relate',

ids = this.normalizeId(ids, this.relatedModelClass.getIdColumnDimension());
ids = (0, _normalizeIds2.default)(ids, this.relatedModelClass.getIdPropertyArray(), { arrayOutput: true });

@@ -135,8 +112,2 @@ builder.setQueryExecutor(function (builder) {

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -143,0 +114,0 @@ key: 'unrelate',

@@ -38,7 +38,2 @@ 'use strict';

/**
* @ignore
* @extends HasManyRelation
*/
var HasOneRelation = function (_HasManyRelation) {

@@ -54,7 +49,2 @@ (0, _inherits3.default)(HasOneRelation, _HasManyRelation);

key: 'createRelationProp',
/**
* @override
* @inheritDoc
*/
value: function createRelationProp(owners, related) {

@@ -72,8 +62,2 @@ var _this2 = this;

}
/**
* @override
* @inheritDoc
*/
}, {

@@ -80,0 +64,0 @@ key: 'appendRelationProp',

@@ -46,2 +46,6 @@ 'use strict';

var _ModelBase = require('../model/ModelBase');
var _ModelBase2 = _interopRequireDefault(_ModelBase);
var _inheritModel = require('../model/inheritModel');

@@ -51,2 +55,6 @@

var _normalizeIds = require('../utils/normalizeIds');
var _normalizeIds2 = _interopRequireDefault(_normalizeIds);
var _dbUtils = require('../utils/dbUtils');

@@ -56,4 +64,6 @@

var _decorators = require('../utils/decorators');
var _memoize = require('../utils/decorators/memoize');
var _memoize2 = _interopRequireDefault(_memoize);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -93,6 +103,2 @@

/**
* @ignore
* @extends Relation
*/
var ManyToManyRelation = (_dec = (0, _dbUtils.overwriteForDatabase)(), _dec2 = (0, _dbUtils.overwriteForDatabase)({

@@ -115,4 +121,2 @@ sqlite3: 'unrelate_sqlite3'

/**
* The join table.
*
* @type {string}

@@ -126,4 +130,2 @@ */

/**
* The relation column in the join table that points to the owner table.
*
* @type {Array.<string>}

@@ -134,4 +136,2 @@ */

/**
* The relation property in the join model that points to the owner table.
*
* @type {Array.<string>}

@@ -142,4 +142,2 @@ */

/**
* The relation column in the join table that points to the related table.
*
* @type {Array.<string>}

@@ -150,4 +148,2 @@ */

/**
* The relation property in the join model that points to the related table.
*
* @type {Array.<string>}

@@ -158,18 +154,18 @@ */

/**
* The join table model class.
*
* This can be optionally given using the `join.through.modelClass` property,
* otherwise an anonymous model class is created in `setMapping` method.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/
_this.joinTableModelClass = null;
/**
* @type {Array.<string>}
*/
_this.joinTableExtraCols = null;
/**
* @type {Array.<string>}
*/
_this.joinTableExtraProps = null;
return _this;
}
/**
* @override
* @inheritDoc
*/
(0, _createClass3.default)(ManyToManyRelation, [{

@@ -194,2 +190,3 @@ key: 'setMapping',

var joinTableTo = this.parseReference(mapping.join.through.to);
var joinTableExtra = mapping.join.through.extra || [];

@@ -209,2 +206,3 @@ if (!joinTableFrom.table || _lodash2.default.isEmpty(joinTableFrom.columns)) {

this.joinTable = joinTableFrom.table;
this.joinTableExtraCols = joinTableExtra;

@@ -250,2 +248,3 @@ if (joinFrom.table === this.ownerModelClass.tableName) {

this.joinTableRelatedProp = this.propertyName(this.joinTableRelatedCol, this.joinTableModelClass);
this.joinTableExtraProps = this.propertyName(this.joinTableExtraCols, this.joinTableModelClass);

@@ -256,6 +255,2 @@ return retVal;

/**
* Reference to the column in the join table that refers to `fullOwnerCol()`.
*
* For example: [`Person_Movie.actorId`].
*
* @returns {Array.<string>}

@@ -275,6 +270,2 @@ */

/**
* Reference to the column in the join table that refers to `fullRelatedCol()`.
*
* For example: [`Person_Movie.movieId`].
*
* @returns {Array.<string>}

@@ -294,6 +285,16 @@ */

/**
* Alias to use for the join table when joining with the owner table.
*
* For example: `Person_Movie_rel_movies`.
*
* @returns {Array.<string>}
*/
}, {
key: 'fullJoinTableExtraCols',
value: function fullJoinTableExtraCols() {
var _this4 = this;
return _lodash2.default.map(this.joinTableExtraCols, function (col) {
return _this4.joinTable + '.' + col;
});
}
/**
* @returns {string}

@@ -309,4 +310,3 @@ */

/**
* @inheritDoc
* @override
* @returns {ManyToManyRelation}
*/

@@ -325,2 +325,4 @@

relation.joinTableModelClass = this.joinTableModelClass;
relation.joinTableExtraCols = this.joinTableExtraCols;
relation.joinTableExtraProps = this.joinTableExtraProps;

@@ -331,4 +333,3 @@ return relation;

/**
* @inheritDoc
* @override
* @returns {ManyToManyRelation}
*/

@@ -345,4 +346,2 @@

/**
* @override
* @inheritDoc
* @returns {QueryBuilder}

@@ -354,3 +353,3 @@ */

value: function findQuery(builder, ownerIds, isColumnRef) {
var _this4 = this;
var _this5 = this;

@@ -360,3 +359,3 @@ var fullRelatedCol = this.fullRelatedCol();

builder.join(this.joinTable, function (join) {
_lodash2.default.each(_this4.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
_lodash2.default.each(_this5.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
join.on(joinTableRelatedCol, fullRelatedCol[idx]);

@@ -385,4 +384,2 @@ });

/**
* @override
* @inheritDoc
* @returns {QueryBuilder}

@@ -426,12 +423,6 @@ */

}
/**
* @override
* @inheritDoc
*/
}, {
key: 'find',
value: function find(builder, owners) {
var _this5 = this;
var _this6 = this;

@@ -442,3 +433,3 @@ var ownerJoinColumnAlias = _lodash2.default.times(this.joinTableOwnerCol.length, function (idx) {

var ownerJoinPropertyAlias = _lodash2.default.map(ownerJoinColumnAlias, function (alias) {
return _this5.relatedModelClass.columnNameToPropertyName(alias);
return _this6.relatedModelClass.columnNameToPropertyName(alias);
});

@@ -448,3 +439,3 @@

var ids = (0, _lodash2.default)(owners).map(function (owner) {
return owner.$values(_this5.ownerProp);
return owner.$values(_this6.ownerProp);
}).unique(function (id) {

@@ -457,10 +448,15 @@ return id.join();

// If we don't do this we also get the join table's columns.
builder.select(_this5.relatedModelClass.tableName + '.*');
builder.select(_this6.relatedModelClass.tableName + '.*');
// Also select all extra columns.
_lodash2.default.each(_this6.fullJoinTableExtraCols(), function (col) {
builder.select(col);
});
}
_this5.findQuery(builder, ids);
_this6.findQuery(builder, ids);
// We must select the owner join columns so that we know for which owner model the related
// models belong to after the requests.
_lodash2.default.each(_this5.fullJoinTableOwnerCol(), function (fullJoinTableOwnerCol, idx) {
_lodash2.default.each(_this6.fullJoinTableOwnerCol(), function (fullJoinTableOwnerCol, idx) {
builder.select(fullJoinTableOwnerCol + ' as ' + ownerJoinColumnAlias[idx]);

@@ -476,3 +472,3 @@ });

_lodash2.default.each(owners, function (owner) {
owner[_this5.name] = relatedByOwnerId[owner.$values(_this5.ownerProp)] || [];
owner[_this6.name] = relatedByOwnerId[owner.$values(_this6.ownerProp)] || [];
});

@@ -490,13 +486,9 @@

}
/**
* @override
* @inheritDoc
*/
}, {
key: 'insert',
value: function insert(builder, owner, insertion) {
var _this6 = this;
var _this7 = this;
this.omitExtraProps(insertion.models());
builder.onBuild(function (builder) {

@@ -507,78 +499,51 @@ builder.$$insert(insertion);

builder.runAfterModelCreate(function (related) {
var ownerId = owner.$values(_this6.ownerProp);
var relatedIds = _lodash2.default.map(related, function (related) {
return related.$values(_this6.relatedProp);
});
var joinModels = _this6._createJoinModels(ownerId, relatedIds);
var ownerId = owner.$values(_this7.ownerProp);
var joinModels = _this7.createJoinModels(ownerId, related);
owner[_this6.name] = _this6.mergeModels(owner[_this6.name], related);
owner[_this7.name] = _this7.mergeModels(owner[_this7.name], related);
// Insert the join rows to the join table.
return _this6.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).insert(joinModels).return(related);
return _this7.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).insert(joinModels).return(related);
});
}
/**
* @override
* @inheritDoc
*/
}, {
key: 'update',
value: function update(builder, owner, _update) {
var _this7 = this;
var _this8 = this;
builder.onBuild(function (builder) {
_this7._selectForModify(builder, owner).$$update(_update).call(_this7.filter);
_this8._selectForModify(builder, owner).$$update(_update).call(_this8.filter);
});
}
/**
* @override
* @inheritDoc
*/
}, {
key: 'delete',
value: function _delete(builder, owner) {
var _this8 = this;
var _this9 = this;
builder.onBuild(function (builder) {
_this8._selectForModify(builder, owner).$$delete().call(_this8.filter);
_this9._selectForModify(builder, owner).$$delete().call(_this9.filter);
});
}
/**
* @override
* @inheritDoc
*/
}, {
key: 'relate',
value: function relate(builder, owner, ids) {
var _this9 = this;
var _this10 = this;
ids = this.normalizeId(ids, this.relatedProp.length);
ids = (0, _normalizeIds2.default)(ids, this.relatedProp);
builder.setQueryExecutor(function (builder) {
var joinModels = _this9._createJoinModels(owner.$values(_this9.ownerProp), ids);
var joinModels = _this10.createJoinModels(owner.$values(_this10.ownerProp), ids);
return _this9.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).insert(joinModels).runAfter(_lodash2.default.constant({}));
return _this10.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).insert(joinModels).runAfter(_lodash2.default.constant({}));
});
}
/**
* @override
* @inheritDoc
*/
}, {
key: 'unrelate',
value: function unrelate(builder, owner) {
var _this10 = this;
var _this11 = this;
builder.setQueryExecutor(function (builder) {
var selectRelatedColQuery = _this10.relatedModelClass.query().childQueryOf(builder).copyFrom(builder, /where/i).select(_this10.fullRelatedCol()).call(_this10.filter);
var selectRelatedColQuery = _this11.relatedModelClass.query().childQueryOf(builder).copyFrom(builder, /where/i).select(_this11.fullRelatedCol()).call(_this11.filter);
return _this10.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).delete().whereComposite(_this10.fullJoinTableOwnerCol(), owner.$values(_this10.ownerProp)).whereInComposite(_this10.fullJoinTableRelatedCol(), selectRelatedColQuery).runAfter(_lodash2.default.constant({}));
return _this11.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).delete().whereComposite(_this11.fullJoinTableOwnerCol(), owner.$values(_this11.ownerProp)).whereInComposite(_this11.fullJoinTableRelatedCol(), selectRelatedColQuery).runAfter(_lodash2.default.constant({}));
});

@@ -588,5 +553,2 @@ }

/**
* Special unrelate implementation for sqlite3. sqlite3 doesn't support multi-value
* where-in clauses. We need to use the built-in _rowid_ instead.
*
* @private

@@ -598,15 +560,15 @@ */

value: function unrelate_sqlite3(builder, owner) {
var _this11 = this;
var _this12 = this;
builder.setQueryExecutor(function (builder) {
var joinTableAlias = _this11.joinTableAlias();
var joinTableAsAlias = _this11.joinTable + ' as ' + joinTableAlias;
var joinTableAlias = _this12.joinTableAlias();
var joinTableAsAlias = _this12.joinTable + ' as ' + joinTableAlias;
var joinTableAliasRowId = joinTableAlias + '.' + sqliteBuiltInRowId;
var joinTableRowId = _this11.joinTable + '.' + sqliteBuiltInRowId;
var joinTableRowId = _this12.joinTable + '.' + sqliteBuiltInRowId;
var ownerId = owner.$values(_this11.ownerProp);
var fullRelatedCol = _this11.fullRelatedCol();
var ownerId = owner.$values(_this12.ownerProp);
var fullRelatedCol = _this12.fullRelatedCol();
var selectRelatedQuery = _this11.relatedModelClass.query().childQueryOf(builder).copyFrom(builder, /where/i).select(joinTableAliasRowId).call(_this11.filter).whereComposite(_this11.fullJoinTableOwnerCol(), ownerId).join(joinTableAsAlias, function (join) {
_lodash2.default.each(_this11.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
var selectRelatedQuery = _this12.relatedModelClass.query().childQueryOf(builder).copyFrom(builder, /where/i).select(joinTableAliasRowId).call(_this12.filter).whereComposite(_this12.fullJoinTableOwnerCol(), ownerId).join(joinTableAsAlias, function (join) {
_lodash2.default.each(_this12.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
join.on(joinTableRelatedCol, fullRelatedCol[idx]);

@@ -616,3 +578,3 @@ });

return _this11.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).delete().whereIn(joinTableRowId, selectRelatedQuery).runAfter(_lodash2.default.constant({}));
return _this12.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).delete().whereIn(joinTableRowId, selectRelatedQuery).runAfter(_lodash2.default.constant({}));
});

@@ -636,5 +598,2 @@ }

/**
* Special _selectForModify implementation for sqlite3. sqlite3 doesn't support multi-value
* where-in clauses. We need to use the built-in _rowid_ instead.
*
* @private

@@ -646,3 +605,3 @@ */

value: function _selectForModify_sqlite3(builder, owner) {
var _this12 = this;
var _this13 = this;

@@ -659,3 +618,3 @@ var relatedTable = this.relatedModelClass.tableName;

var selectRelatedQuery = this.joinTableModelClass.bindKnex(builder.knex()).query().childQueryOf(builder).select(relatedTableAliasRowId).whereComposite(this.fullJoinTableOwnerCol(), ownerId).join(relatedTableAsAlias, function (join) {
_lodash2.default.each(_this12.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
_lodash2.default.each(_this13.fullJoinTableRelatedCol(), function (joinTableRelatedCol, idx) {
join.on(joinTableRelatedCol, fullRelatedCol[idx]);

@@ -667,29 +626,39 @@ });

}
/**
* @private
*/
}, {
key: '_createJoinModels',
value: function _createJoinModels(ownerId, relatedIds) {
var _this13 = this;
key: 'createJoinModels',
value: function createJoinModels(ownerId, related) {
var _this14 = this;
return _lodash2.default.map(relatedIds, function (relatedId) {
return _lodash2.default.map(related, function (related) {
var joinModel = {};
_lodash2.default.each(_this13.joinTableOwnerProp, function (joinTableOwnerProp, idx) {
_lodash2.default.each(_this14.joinTableOwnerProp, function (joinTableOwnerProp, idx) {
joinModel[joinTableOwnerProp] = ownerId[idx];
});
_lodash2.default.each(_this13.joinTableRelatedProp, function (joinTableRelatedProp, idx) {
joinModel[joinTableRelatedProp] = relatedId[idx];
_lodash2.default.each(_this14.joinTableRelatedProp, function (joinTableRelatedProp, idx) {
joinModel[joinTableRelatedProp] = related[_this14.relatedProp[idx]];
});
_lodash2.default.each(_this14.joinTableExtraProps, function (extraProp) {
if (!_lodash2.default.isUndefined(related[extraProp])) {
joinModel[extraProp] = related[extraProp];
}
});
return joinModel;
});
}
}, {
key: 'omitExtraProps',
value: function omitExtraProps(models) {
var _this15 = this;
_lodash2.default.each(models, function (model) {
return model.$omitFromDatabaseJson(_this15.joinTableExtraProps);
});
}
}]);
return ManyToManyRelation;
}(_Relation3.default), (_applyDecoratedDescriptor(_class2.prototype, 'fullJoinTableOwnerCol', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'fullJoinTableOwnerCol'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, 'fullJoinTableRelatedCol', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'fullJoinTableRelatedCol'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, 'unrelate', [_dec2], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'unrelate'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, '_selectForModify', [_dec3], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, '_selectForModify'), _class2.prototype)), _class2)) || _class);
}(_Relation3.default), (_applyDecoratedDescriptor(_class2.prototype, 'fullJoinTableOwnerCol', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'fullJoinTableOwnerCol'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, 'fullJoinTableRelatedCol', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'fullJoinTableRelatedCol'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, 'fullJoinTableExtraCols', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'fullJoinTableExtraCols'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, 'unrelate', [_dec2], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, 'unrelate'), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, '_selectForModify', [_dec3], (0, _getOwnPropertyDescriptor2.default)(_class2.prototype, '_selectForModify'), _class2.prototype)), _class2)) || _class);
exports.default = ManyToManyRelation;

@@ -32,4 +32,6 @@ 'use strict';

var _decorators = require('../utils/decorators');
var _memoize = require('../utils/decorators/memoize');
var _memoize2 = _interopRequireDefault(_memoize);
var _QueryBuilder = require('../queryBuilder/QueryBuilder');

@@ -72,54 +74,10 @@

* @typedef {Object} RelationJoin
*
* An object literal that describes how two tables are related to one another. For example:
*
* ```js
* {
* from: 'Animal.ownerId',
* to: 'Person.id'
* }
* ```
*
* or in the case of a many-to-many relation:
*
* ```js
* {
* from: 'Person.id',
* through: {
* from: 'Person_Movie.actorId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* ```
*
* @property {string|Array.<string>} from
* The relation column in the owner table. Must be given with the table name.
* For example `Person.id`. Composite key can be specified using an array of
* columns e.g. `['Person.a', 'Person.b']`. Note that neither this nor `to`
* need to be foreign keys or primary keys. You can join any column to
* any column.
*
* @property {string|Array.<string>} to
* The relation column in the related table. Must be given with the table name.
* For example `Movie.id`. Composite key can be specified using an array of
* columns e.g. `['Movie.a', 'Movie.b']`. Note that neither this nor `from`
* need to be foreign keys or primary keys. You can join any column to any column.
*
* @property {Object} through
* Describes the join table if the models are related through one.
*
* @property {Class.<Model>} through.modelClass
* If the there is model class available for the join table, it can be provided
* using this property.
*
* @property {Constructor.<Model>} through.modelClass
* @property {string|Array.<string>} through.from
* The column that is joined to `from` property of the `RelationJoin`. For example
* `Person_Movie.actorId` where `Person_Movie` is the join table. Composite key can
* be specified using an array of columns e.g. `['Person_Movie.a', 'Person_Movie.b']`.
*
* @property {string|Array.<string>} through.to
* The column that is joined to `to` property of the `RelationJoin`. For example
* `Person_Movie.movieId` where `Person_Movie` is the join table. Composite key can
* be specified using an array of columns e.g. `['Person_Movie.a', 'Person_Movie.b']`.
* @property {Array.<string>} through.extra
*/

@@ -130,29 +88,9 @@

*
* @property {Class.<Model>|string} modelClass
* A {@link Model} subclass constructor or an absolute path to a module that exports one.
*
* @property {Constructor.<Model>|string} modelClass
* @property {Relation} relation
* A relation constructor. You can use one of Model.BelongsToOneRelation, Model.HasOneRelation, Model.HasManyRelation and
* Model.ManyToManyRelation or even write your own relation type by subclassing {@link Relation}.
*
* @property {Object|function(QueryBuilder)} filter
* Additional filter for the relation. It can be either a hash of {column: 'value'} pairs or
* a function that takes a QueryBuilder as a parameter.
*
* @property {RelationJoin} [join]
* An object that describes how the two models are related.
*/
/**
* Represents a relation between two `Model` subclasses.
*
* This is an abstract base class and should never be instantiated.
*
* @param {string} relationName
* Name of the relation.
*
* @param {Model} OwnerClass
* The Model subclass that owns this relation.
*
* @ignore
* @abstract

@@ -165,4 +103,2 @@ */

/**
* Name of the relation.
*
* @type {string}

@@ -173,7 +109,3 @@ */

/**
* The owner class of this relation.
*
* This must be a subclass of Model.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/

@@ -183,7 +115,3 @@ this.ownerModelClass = OwnerClass;

/**
* The related class.
*
* This must be a subclass of Model.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/

@@ -193,4 +121,2 @@ this.relatedModelClass = null;

/**
* The relation column in the owner table.
*
* @type {Array.<string>}

@@ -201,4 +127,2 @@ */

/**
* The relation property in the owner model.
*
* @type {Array.<string>}

@@ -209,4 +133,2 @@ */

/**
* The relation column in the related table.
*
* @type {Array.<string>}

@@ -217,4 +139,2 @@ */

/**
* The relation property in the related model.
*
* @type {Array.<string>}

@@ -225,4 +145,2 @@ */

/**
* Optional additional filter query.
*
* @type {function (QueryBuilder)}

@@ -234,6 +152,4 @@ */

/**
* Makes the given constructor a subclass of this class.
*
* @param {function=} subclassConstructor
* @return {Class.<Model>}
* @return {Constructor.<Model>}
*/

@@ -245,4 +161,2 @@

/**
* Constructs the instance based on a mapping data.
*
* @param {RelationMapping} mapping

@@ -330,3 +244,3 @@ */

/**
* Return the knex connection.
* @returns {knex}
*/

@@ -341,6 +255,2 @@

/**
* Reference to the relation column in the owner model's table.
*
* For example: [`Person.id`].
*
* @returns {Array.<string>}

@@ -360,6 +270,2 @@ */

/**
* Reference to the relation column in the related model's table.
*
* For example: [`Movie.id`].
*
* @returns {Array.<string>}

@@ -379,6 +285,2 @@ */

/**
* Alias to use for the related table when joining with the owner table.
*
* For example: `Movie_rel_movies`.
*
* @returns {string}

@@ -394,4 +296,2 @@ */

/**
* Clones this relation.
*
* @returns {Relation}

@@ -416,7 +316,3 @@ */

/**
* Returns a clone of this relation with `relatedModelClass` and `ownerModelClass` bound to the given knex.
*
* See `Model.bindKnex`.
*
* @param knex
* @param {knex} knex
* @returns {Relation}

@@ -704,5 +600,6 @@ */

for (var i = 0; i < ref.length; ++i) {
var parts = ref[i].split('.');
var tableName = parts[0] && parts[0].trim();
var columnName = parts[1] && parts[1].trim();
var refItem = ref[i];
var ndx = refItem.lastIndexOf('.');
var tableName = refItem.substr(0, ndx).trim();
var columnName = refItem.substr(ndx + 1, refItem.length).trim();

@@ -732,47 +629,2 @@ if (!tableName || table && table !== tableName || !columnName) {

}, {
key: 'normalizeId',
value: function normalizeId(ids, compositeLength) {
var _this7 = this;
var isComposite = compositeLength > 1;
if (isComposite) {
// For composite ids these two are okay:
//
// 1. [1, 3, 4]
// 2. [[1, 3, 4], [4, 6, 1]]
//
if (!_lodash2.default.isArray(ids) || !_lodash2.default.isArray(ids[0]) && ids.length !== compositeLength) {
this.throwError('Invalid composite key ' + ids);
}
// Normalize to array of arrays.
if (!_lodash2.default.isArray(ids[0])) {
ids = [ids];
}
} else {
// Normalize to array of arrays.
if (!_lodash2.default.isArray(ids)) {
ids = [[ids]];
} else if (!_lodash2.default.isArray(ids[0])) {
ids = _lodash2.default.map(ids, function (id) {
return [id];
});
}
}
_lodash2.default.each(ids, function (id) {
if (id.length !== compositeLength) {
_this7.throwError('Id ' + id + ' has invalid length. Expected ' + compositeLength);
}
});
return ids;
}
/**
* @protected
*/
}, {
key: 'throwError',

@@ -794,3 +646,3 @@ value: function throwError(message) {

return Relation;
}(), (_applyDecoratedDescriptor(_class.prototype, 'fullOwnerCol', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'fullOwnerCol'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'fullRelatedCol', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'fullRelatedCol'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'relatedTableAlias', [_decorators.memoize], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'relatedTableAlias'), _class.prototype)), _class);
}(), (_applyDecoratedDescriptor(_class.prototype, 'fullOwnerCol', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'fullOwnerCol'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'fullRelatedCol', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'fullRelatedCol'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'relatedTableAlias', [_memoize2.default], (0, _getOwnPropertyDescriptor2.default)(_class.prototype, 'relatedTableAlias'), _class.prototype)), _class);
exports.default = Relation;

@@ -25,76 +25,2 @@ 'use strict';

/**
* Starts a transaction.
*
* Give the the model classes you want to use in the transaction as arguments to this
* function. The model classes are bound to a newly created transaction and passed to
* the callback. All queries created using the bound model classes or any result acquired
* through them take part in the same transaction.
*
* You must return a promise from the callback. If this promise is fulfilled the transaction
* is committed. If the promise is rejected the transaction is rolled back.
*
* Examples:
*
* ```js
* objection.transaction(Person, Animal, function (Person, Animal) {
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function () {
* return Animal.query().insert({name: 'Scrappy'});
* });
*
* }).then(function (scrappy) {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* Related model classes are automatically bound to the same transaction. So if you use
* `Animal` implicitly through `Person`'s relations you don't have to bind Animal explicitly.
* The following example clarifies this:
*
* ```js
* objection.transaction(Person, function (Person) {
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function (jennifer) {
* // This insert takes part in the transaction even though we didn't explicitly
* // bind the `Animal` model class.
* return jennifer.$relatedQuery('pets').insert({name: 'Scrappy'});
* });
*
* }).then(function (scrappy) {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* Inside the callback `this` is the knex transaction object. So if you need to create
* knex queries you can do this:
*
* ```js
* objection.transaction(Person, function (Person) {
* let knex = this;
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function (jennifer) {
* return knex.insert({name: 'Scrappy'}}.into('Animal');
* });
*
* }).then(function () {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* @function transaction
* @returns {Promise}

@@ -143,37 +69,3 @@ */

/**
* Starts a transaction.
*
* The returned promise is resolved with a knex transaction object that can be used as
* a query builder. You can bind `Model` classes to the transaction using the `Model.bindTransaction`
* method. The transaction object has `commit` and `rollback` methods for committing and
* rolling back the transaction.
*
* ```js
* let Person = require('./models/Person');
* let transaction;
*
* objection.transaction.start(Person).then(function (trx) {
* transaction = trx;
* return Person
* .bindTransaction(transaction)
* .query()
* .insert({firstName: 'Jennifer'});
* }).then(function (jennifer) {
* return Person
* .bindTransaction(transaction)
* .query()
* .patch({lastName: 'Lawrence'})
* .where('id', jennifer.id);
* }).then(function () {
* return transaction.commit();
* }).catch(function () {
* return transaction.rollback();
* });
* ```
*
* @param {Class.<Model>|knex} modelClassOrKnex
* A knex instance or any model that has a knex connection set. Note that you can bind any model
* to the created transaction regardless of the model given to this method. This argument is used
* only to get a knex connection for starting the transaction.
*
* @param {Constructor.<Model>|knex} modelClassOrKnex
* @returns {Promise}

@@ -180,0 +72,0 @@ */

@@ -31,3 +31,2 @@ "use strict";

*
* @ignore
* @param {Object} subClass

@@ -60,3 +59,2 @@ * @param {Object} superClass

*
* @ignore
* @param {Object} Constructor

@@ -63,0 +61,0 @@ * @param {Object} SuperConstructor

@@ -13,2 +13,6 @@ 'use strict';

var _defineProperty = require('babel-runtime/core-js/object/define-property');
var _defineProperty2 = _interopRequireDefault(_defineProperty);
var _lodash = require('lodash');

@@ -20,5 +24,4 @@

/**
* @ignore
*/
var OVERWRITE_FOR_DATABASE_KEY = '@overwriteForDatabase';
function getDialect(knex) {

@@ -28,5 +31,2 @@ return knex.client.dialect;

/**
* @ignore
*/
function isPostgres(knex) {

@@ -36,5 +36,2 @@ return getDialect(knex) === 'postgresql';

/**
* @ignore
*/
function isMySql(knex) {

@@ -44,5 +41,2 @@ return getDialect(knex) === 'mysql';

/**
* @ignore
*/
function isSqlite(knex) {

@@ -52,5 +46,2 @@ return getDialect(knex) === 'sqlite3';

/**
* @ignore
*/
function isKnexQueryBuilder(knexQueryBuilder) {

@@ -60,14 +51,20 @@ return knexQueryBuilder && knexQueryBuilder.client && _lodash2.default.isString(knexQueryBuilder.client.dialect);

/**
* @ignore
*/
function overwriteForDatabase(input) {
if (!input) {
input = function input(inst) {
return inst.knex();
};
}
// If there is no input or if the input is a function, we assume that the
// decorator was applied to a class instead of a method.
var isClassDecorator = _lodash2.default.isUndefined(input) || _lodash2.default.isFunction(input);
if (_lodash2.default.isFunction(input)) {
return overwriteForDatabaseClass(input);
if (isClassDecorator) {
// In case of class decorator, the input should be a function that returns
// a knex instance that the method version can use.
var getKnex = input;
if (_lodash2.default.isUndefined(getKnex)) {
// The default getter attempts to call a function called `knex`.
getKnex = function getKnex(inst) {
return inst.knex();
};
}
return overwriteForDatabaseClass(getKnex);
} else {

@@ -78,14 +75,10 @@ return overwriteForDatabaseMethod(input);

/**
* @ignore
*/
function overwriteForDatabaseClass(input) {
function overwriteForDatabaseClass(getKnex) {
return function (constructor) {
var getKnex = input;
if (constructor['@overwriteForDatabase']) {
if (constructor[OVERWRITE_FOR_DATABASE_KEY]) {
// Knex getter is already registered. Do nothing.
return;
}
Object.defineProperty(constructor, '@overwriteForDatabase', {
(0, _defineProperty2.default)(constructor, OVERWRITE_FOR_DATABASE_KEY, {
enumerable: false,

@@ -98,5 +91,2 @@ writable: false,

/**
* @ignore
*/
function overwriteForDatabaseMethod(input) {

@@ -108,5 +98,6 @@ return function (target, property, descriptor) {

descriptor.value = function () {
var knex = this.constructor['@overwriteForDatabase'].getKnex(this);
var knex = this.constructor[OVERWRITE_FOR_DATABASE_KEY].getKnex(this);
var dialect = getDialect(knex);
// Call the correct method based on the dialect.
if (dialect in methodNameByDialect) {

@@ -113,0 +104,0 @@ var methodName = methodNameByDialect[dialect];

@@ -22,6 +22,3 @@ 'use strict';

/**
* Error of this class is thrown when a Model validation fails.
*
* @param {Object} errors
* @constructor
*/

@@ -33,4 +30,2 @@ function ValidationError(errors) {

/**
* Any data that describes the errors.
*
* @type {Object}

@@ -37,0 +32,0 @@ */

{
"name": "objection",
"version": "0.5.0-alpha.2",
"version": "0.5.0-rc.1",
"description": "An SQL-friendly ORM for Node.js",

@@ -5,0 +5,0 @@ "main": "lib/objection.js",

@@ -8,3 +8,4 @@ import _ from 'lodash';

import EagerFetcher from '../queryBuilder/EagerFetcher';
import {memoize, deprecated} from '../utils/decorators';
import deprecated from '../utils/decorators/deprecated';
import memoize from '../utils/decorators/memoize';

@@ -17,131 +18,11 @@ import Relation from '../relations/Relation';

/**
* Subclasses of this class represent database tables.
*
* Subclass can be created like this:
*
* ```js
* var Model = require('objection').Model;
*
* function Person() {
* Model.apply(this, arguments);
* }
*
* Model.extend(Person);
* module.exports = Person;
*
* // Table name is the only required property.
* Person.tableName = 'Person';
*
* // This is not the database schema! Nothing is generated based on this. Whenever a
* // Person object is created from a JSON object, the JSON is checked against this
* // schema. For example when you call Person.fromJson({firstName: 'Jennifer'});
* Person.jsonSchema = {
* type: 'object',
* required: ['firstName', 'lastName'],
*
* properties: {
* id: {type: 'integer'},
* parentId: {type: ['integer', 'null']},
* firstName: {type: 'string', minLength: 1, maxLength: 255},
* lastName: {type: 'string', minLength: 1, maxLength: 255},
* age: {type: 'number'},
*
* address: {
* type: 'object',
* properties: {
* street: {type: 'string'},
* city: {type: 'string'},
* zipCode: {type: 'string'}
* }
* }
* }
* };
*
* // This object defines the relations to other models.
* Person.relationMappings = {
* pets: {
* relation: Model.HasManyRelation,
* // The related model. This can be either a Model subclass constructor or an
* // absolute file path to a module that exports one. We use the file path version
* // here to prevent require loops.
* modelClass: __dirname + '/Animal',
* join: {
* from: 'Person.id',
* to: 'Animal.ownerId'
* }
* },
*
* movies: {
* relation: Model.ManyToManyRelation,
* modelClass: __dirname + '/Movie',
* join: {
* from: 'Person.id',
* // ManyToMany relation needs the `through` object to describe the join table.
* through: {
* from: 'Person_Movie.personId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* },
*
* children: {
* relation: Model.HasManyRelation,
* modelClass: Person,
* join: {
* from: 'Person.id',
* to: 'Person.parentId'
* }
* }
* };
* ```
*
* @extends ModelBase
* @constructor
*/
export default class Model extends ModelBase {
/**
* QueryBuilder subclass to use in `query()` or `$query()` methods.
*
* This constructor is used whenever a query builder is created using `query()` or `$query()` methods.
* You can override this to use your own `QueryBuilder` subclass.
*/
static QueryBuilder = QueryBuilder;
/**
* QueryBuilder subclass to use in `$relatedQuery()` method.
*
* This constructor is used whenever a query builder is created using the `$relatedQuery()` method.
* You can override this to use your own `QueryBuilder` subclass.
*/
static RelatedQueryBuilder = QueryBuilder;
/**
* one-to-one relation type.
*
* @type {HasOneRelation}
*/
static HasOneRelation = HasOneRelation;
/**
* one-to-one relation type.
*
* @type {BelongsToOneRelation}
*/
static BelongsToOneRelation = BelongsToOneRelation;
/**
* one-to-many relation type.
*
* @type {HasManyRelation}
*/
static HasManyRelation = HasManyRelation;
static ManyToManyRelation = ManyToManyRelation;
/**
* one-to-many relation type.
*
* @type {OneToOneRelation}
*/
@deprecated({removedIn: '0.7.0', useInstead: 'BelongsToOneRelation'})

@@ -152,7 +33,2 @@ static get OneToOneRelation() {

/**
* one-to-many relation type.
*
* @type {OneToManyRelation}
*/
@deprecated({removedIn: '0.7.0', useInstead: 'HasManyRelation'})

@@ -164,11 +40,2 @@ static get OneToManyRelation() {

/**
* may-to-many relation type.
*
* @type {ManyToManyRelation}
*/
static ManyToManyRelation = ManyToManyRelation;
/**
* Name of the database table of this model.
*
* @type {string}

@@ -179,8 +46,2 @@ */

/**
* Name of the primary key column in the database table.
*
* Composite id can be specified by giving an array of column names.
*
* Defaults to 'id'.
*
* @type {string|Array.<string>}

@@ -191,6 +52,2 @@ */

/**
* Name of the property used to store a temporary non-db identifier for the model.
*
* Defaults to '#id'.
*
* @type {string}

@@ -201,6 +58,2 @@ */

/**
* Name of the property used to store a reference to a `uidProp`.
*
* Defaults to '#ref'.
*
* @type {string}

@@ -211,4 +64,2 @@ */

/**
* Regular expression for parsing a reference to a property.
*
* @type {RegExp}

@@ -219,31 +70,2 @@ */

/**
* Properties that should be saved to database as JSON strings.
*
* The properties listed here are serialized to JSON strings upon insertion to the database
* and parsed back to objects when models are read from the database. Combined with the
* postgresql's json or jsonb data type, this is a powerful way of representing documents
* as single database rows.
*
* If this property is left unset all properties declared as objects or arrays in the
* `jsonSchema` are implicitly added to this list.
*
* Example:
*
* ```js
* Person.jsonAttributes = ['address'];
*
* var jennifer = Person.fromJson({
* name: 'Jennifer',
* address: {
* address: 'Someroad 10',
* zipCode: '1234',
* city: 'Los Angeles'
* }
* });
*
* var dbRow = jennifer.$toDatabaseJson();
* console.log(dbRow);
* // --> {name: 'Jennifer', address: '{"address":"Someroad 10","zipCode":"1234","city":"Los Angeles"}'}
* ```
*
* @type {Array.<string>}

@@ -254,53 +76,2 @@ */

/**
* This property defines the relations to other models.
*
* Relations to other models can be defined by setting this property. The best way to explain how to
* do this is by example:
*
* ```js
* Person.relationMappings = {
* pets: {
* relation: Model.HasManyRelation,
* modelClass: Animal,
* join: {
* from: 'Person.id',
* to: 'Animal.ownerId'
* }
* },
*
* father: {
* relation: Model.BelongsToOneRelation,
* modelClass: Person,
* join: {
* from: 'Person.fatherId',
* to: 'Person.id'
* }
* },
*
* movies: {
* relation: Model.ManyToManyRelation,
* modelClass: Movie,
* join: {
* from: 'Person.id',
* through: {
* from: 'Person_Movie.actorId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* }
* };
* ```
*
* relationMappings is an object whose keys are relation names and values define the relation. The
* `join` property in addition to the relation type define how the models are related to one another.
* The `from` and `to` properties of the `join` object define the database columns through which the
* models are associated. Note that neither of these columns need to be primary keys. They can be any
* columns!. In the case of ManyToManyRelation also the join table needs to be defined. This is
* done using the `through` object.
*
* The `modelClass` passed to the relation mappings is the class of the related model. It can be either
* a Model subclass constructor or an absolute path to a module that exports one. Using file paths
* is a handy way to prevent require loops.
*
* @type {Object.<string, RelationMapping>}

@@ -321,24 +92,4 @@ */

/**
* Returns or sets the identifier of a model instance.
*
* ```js
* // Returns the id.
* model.$id();
* // Sets the id.
* model.$id(100);
* ```
*
* The identifier property does not have to be accessed or set using this method.
* If the identifier property is known it can be accessed or set just like any
* other property:
*
* ```js
* console.log(model.id);
* model.id = 100;
* ```
*
* This method is just a helper for the cases where the id property is not known.
*
* @param {*=} id
* @returns {*}
* @param {string|number|Array.<string|number>=} id
* @returns {string|number|Array.<string|number>}
*/

@@ -354,4 +105,2 @@ $id() {

/**
* Shortcut to `this.constructor.knex()`.
*
* @returns {knex}

@@ -364,4 +113,2 @@ */

/**
* Shortcut to `this.constructor.transaction()`.
*
* @returns {knex}

@@ -374,44 +121,2 @@ */

/**
* Creates a query builder for this model instance.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* All queries built using the returned builder only affect this instance.
*
* Examples:
*
* Re-fetch the instance from the database:
*
* ```js
* person.$query().then(function (person) {
* console.log(person);
* });
* ```
*
* Insert a new model to database:
*
* ```js
* Person.fromJson({firstName: 'Jennifer'}).$query().insert().then(function (jennifer) {
* console.log(jennifer.id);
* });
* ```
*
* Patch a model:
*
* ```js
* person.$query().patch({lastName: 'Cooper'}).then(function (person) {
* console.log(person.lastName); // --> 'Cooper'.
* });
* ```
*
* Delete a model.
*
* ```js
* person.$query().delete().then(function () {
* console.log('person deleted');
* });
* ```
*
* @returns {QueryBuilder}

@@ -468,119 +173,3 @@ */

/**
* Use this to build a query that only affects the models related to this instance through a relation.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* Examples:
*
* Fetch all models related to this instance through a relation. The fetched models are
* also stored to the owner model's property named after the relation:
*
* ```js
* jennifer.$relatedQuery('pets').then(function (pets) {
* console.log('jennifer has', pets.length, 'pets');
* console.log(jennifer.pets === pets); // --> true
* });
* ```
*
* The related query is just like any other query. All *knex* methods are available:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .select('Animal.*', 'Person.name as ownerName')
* .where('species', '=', 'dog')
* .orWhere('breed', '=', 'cat')
* .innerJoin('Person', 'Person.id', 'Animal.ownerId')
* .orderBy('Animal.name')
* .then(function (dogsAndCats) {
* // All the dogs and cats have the owner's name "Jennifer" joined as the `ownerName` property.
* console.log(dogsAndCats);
* });
* ```
*
* This inserts a new model to the database and binds it to the owner model as defined
* by the relation:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .insert({species: 'dog', name: 'Fluffy'})
* .then(function (waldo) {
* console.log(waldo.id);
* });
* ```
*
* To add an existing model to a relation the `relate` method can be used. In this example
* the dog `fluffy` already exists in the database but it isn't related to `jennifer` through
* the `pets` relation. We can make the connection like this:
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .relate(fluffy.id)
* .then(function () {
* console.log('fluffy is now related to jennifer through pets relation');
* });
* ```
*
* The connection can be removed using the `unrelate` method. Again, this doesn't delete the
* related model. Only the connection is removed. For example in the case of ManyToMany relation
* the join table entries are deleted.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .unrelate()
* .where('id', fluffy.id)
* .then(function () {
* console.log('jennifer no longer has fluffy as a pet');
* });
* ```
*
* Related models can be deleted using the delete method. Note that in the case of ManyToManyRelation
* the join table entries are not deleted. Naturally the delete query can be chained with any *knex*
* methods.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .delete()
* .where('species', 'cat')
* .then(function () {
* console.log('jennifer no longer has any cats');
* });
* ```
*
* `update` and `patch` can be used to update related models. Only difference between the mentioned
* methods is that `update` validates the input objects using the related model class's full schema
* and `patch` ignores the `required` property of the schema. Use `update` when you want to update
* _all_ properties of a model and `patch` when only a subset should be updated.
*
* ```js
* jennifer
* .$relatedQuery('pets')
* .update({species: 'dog', name: 'Fluffy the great', vaccinated: false})
* .where('id', fluffy.id)
* .then(function (updatedFluffy) {
* console.log('fluffy\'s new name is', updatedFluffy.name);
* });
*
* // This will throw assuming that `name` or `species` is a required property for an Animal.
* jennifer.$relatedQuery('pets').patch({vaccinated: true});
*
* // This will _not_ throw.
* jennifer
* .$relatedQuery('pets')
* .patch({vaccinated: true})
* .where('species', 'dog')
* .then(function () {
* console.log('jennifer just got all her dogs vaccinated');
* });
* ```
*
* @param {string} relationName
* Name of the relation.
*
* @returns {QueryBuilder}

@@ -618,38 +207,2 @@ */

/**
* Loads related models using a {@link RelationExpression}.
*
* Example:
*
* ```js
* jennifer.$loadRelated('[pets, children.[pets, father]]').then(function (jennifer) {
* console.log('Jennifer has', jennifer.pets.length, 'pets');
* console.log('Jennifer has', jennifer.children.length, 'children');
* console.log('Jennifer\'s first child has', jennifer.children[0].pets.length, 'pets');
* console.log('Jennifer had her first child with', jennifer.children[0].father.name);
* });
* ```
*
* Relations can be filtered by giving named filter functions as arguments
* to the relations:
*
* ```js
* jennifer
* .$loadRelated('children(orderByAge).[pets(onlyDogs, orderByName), movies]', {
* orderByAge: function (builder) {
* builder.orderBy('age')
* },
* orderByName: function (builder) {
* builder.orderBy('name');
* },
* onlyDogs: function (builder) {
* builder.where('species', 'dog')
* }
* })
* .then(function (jennifer) {
* console.log(jennifer.children.pets[0]);
* });
* ```
*
* @see {@link RelationExpression} for more examples on relation expressions.
*
* @param {string|RelationExpression} relationExpression

@@ -664,7 +217,3 @@ * @param {Object.<string, function(QueryBuilder)>=} filters

/**
* Shortcut for `Model.traverse(filterConstructor, this, callback)`.
*
* See the static method `Model.traverse` for more info.
*
* @param {function=} filterConstructor
* @param {Constructor.<Model>=} filterConstructor
* @param {function(Model)} callback

@@ -683,5 +232,2 @@ * @return {Model}

/**
* @override
*/
$parseDatabaseJson(json) {

@@ -705,5 +251,2 @@ const ModelClass = this.constructor;

/**
* @override
*/
$formatDatabaseJson(json) {

@@ -727,5 +270,2 @@ const ModelClass = this.constructor;

/**
* @override
*/
$setJson(json, options) {

@@ -757,6 +297,3 @@ super.$setJson(json, options);

/**
* @override
*
* @param {boolean} shallow
* If true the relations are omitted from the json.
* @param {boolean=} shallow
*/

@@ -787,210 +324,28 @@ $toJson(shallow) {

/**
* Called before a model is inserted into the database.
*
* You can return a promise from this function if you need to do asynchronous stuff. You can
* also throw an exception to abort the insert and reject the query. This can be useful if
* you need to do insert specific validation.
*
* @param {Object} queryContext
* The context object of the insert query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}
*/
$beforeInsert(queryContext) {
$beforeInsert(queryContext) {}
}
/**
* Called after a model has been inserted into the database.
*
* You can return a promise from this function if you need to do asynchronous stuff.
*
* @param {Object} queryContext
* The context object of the insert query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}
*/
$afterInsert(queryContext) {
$afterInsert(queryContext) {}
}
/**
* Called before a model is updated.
*
* You can return a promise from this function if you need to do asynchronous stuff. You can
* also throw an exception to abort the update and reject the query. This can be useful if
* you need to do update specific validation.
*
* This method is also called before a model is patched. Therefore all the model's properties
* may not exist. You can check if the update operation is a patch by checking the `opt.patch`
* boolean.
*
* Also note that this method is called only once when you do something like this:
*
* ```js
* Person
* .$query()
* .patch({firstName: 'Jennifer'})
* .where('gender', 'female')
* .then(function () {
* ...
* });
* ```
*
* The example above updates all rows whose `gender` equals `female` but the `$beforeUpdate`
* method is called only once for the `{firstName: 'Jennifer'}` model. This is because the
* updating is done completely in the database and the affected models are never fetched
* to the javascript side.
*
* @param {ModelOptions} opt
*
* @param {Object} queryContext
* The context object of the update query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}
*/
$beforeUpdate(opt, queryContext) {
$beforeUpdate(opt, queryContext) {}
}
/**
* Called after a model is updated.
*
* You can return a promise from this function if you need to do asynchronous stuff.
*
* This method is also called after a model is patched. Therefore all the model's properties
* may not exist. You can check if the update operation is a patch by checking the `opt.patch`
* boolean.
*
* Also note that this method is called only once when you do something like this:
*
* ```js
* Person
* .$query()
* .patch({firstName: 'Jennifer'})
* .where('gender', 'female')
* .then(function () {
* ...
* });
* ```
*
* The example above updates all rows whose `gender` equals `female` but the `$beforeUpdate`
* method is called only once for the `{firstName: 'Jennifer'}` model. This is because the
* updating is done completely in the database and the affected models are never fetched
* to the javascript side.
*
* @param {ModelOptions} opt
*
* @param {Object} queryContext
* The context object of the update query. See {@link QueryBuilder#context}.
*
* @returns {Promise|*}
*/
$afterUpdate(opt, queryContext) {
$afterUpdate(opt, queryContext) {}
}
/**
* Creates a query builder for this table.
*
* The returned query builder has all the methods a *knex* query builder has. See
* {@link QueryBuilder} and <a href="http://knexjs.org/#Builder">knexjs.org</a>
* for more information.
*
* Examples:
*
* Read models from the database:
*
* ```js
* // Get all rows.
* Person.query().then(function(allPersons) {
* console.log('there are', allPersons.length, 'persons in the database');
* });
*
* // Example of a more complex WHERE clause. This generates:
* // SELECT * FROM "Person" WHERE ("firstName" = 'Jennifer' AND "age" < 30) OR ("firstName" = "Mark" AND "age" > 30)
* Person
* .query()
* .where(function () {
* this.where('firstName', 'Jennifer').where('age', '<', 30);
* })
* .orWhere(function () {
* this.where('firstName', 'Mark').where('age', '>', 30);
* })
* .then(function (marksAndJennifers) {
* console.log(marksAndJennifers);
* });
*
* // Get a subset of rows and fetch related models for each row.
* Person
* .query()
* .where('age', '>', 60)
* .eager('children.children.movies')
* .then(function (oldPeople) {
* console.log('some old person\'s grand child has appeared in',
* oldPeople[0].children[0].children[0].movies.length,
* 'movies');
* });
* ```
*
* Insert models to the database:
*
* ```js
* Person.query().insert({firstName: 'Sylvester', lastName: 'Stallone'}).then(function (sylvester) {
* console.log(sylvester.fullName()); // --> 'Sylvester Stallone'.
* });
*
* // Batch insert. This only works on Postgresql as it is the only database that returns the
* // identifiers of _all_ inserted rows. If you need to do batch inserts on other databases use
* // *knex* directly. (See .knexQuery() method).
* Person
* .query()
* .insert([
* {firstName: 'Arnold', lastName: 'Schwarzenegger'},
* {firstName: 'Sylvester', lastName: 'Stallone'}
* ])
* .then(function (inserted) {
* console.log(inserted[0].fullName()); // --> 'Arnold Schwarzenegger'
* });
* ```
*
* `update` and `patch` can be used to update models. Only difference between the mentioned methods
* is that `update` validates the input objects using the model class's full jsonSchema and `patch`
* ignores the `required` property of the schema. Use `update` when you want to update _all_ properties
* of a model and `patch` when only a subset should be updated.
*
* ```js
* Person
* .query()
* .update({firstName: 'Jennifer', lastName: 'Lawrence', age: 35})
* .where('id', jennifer.id)
* .then(function (updatedJennifer) {
* console.log('Jennifer is now', updatedJennifer.age, 'years old');
* });
*
* // This will throw assuming that `firstName` or `lastName` is a required property for a Person.
* Person.query().patch({age: 100});
*
* // This will _not_ throw.
* Person
* .query()
* .patch({age: 100})
* .then(function () {
* console.log('Everyone is now 100 years old');
* });
* ```
*
* Models can be deleted using the delete method. Naturally the delete query can be chained with
* any *knex* methods:
*
* ```js
* Person
* .query()
* .delete()
* .where('age', '>', 90)
* .then(function () {
* console.log('anyone over 90 is now removed from the database');
* });
* ```
*
* @returns {QueryBuilder}

@@ -1012,22 +367,3 @@ */

/**
* Get/Set the knex instance for this model class.
*
* Subclasses inherit the connection. A system-wide knex instance can thus be set by calling
* `Model.knex(knex)`. This works even after subclasses have been created.
*
* ```js
* var knex = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database.db'
* }
* });
*
* Model.knex(knex);
* knex = Model.knex();
* ```
*
* @param {knex=} knex
* The knex to set.
*
* @returns {knex}

@@ -1051,16 +387,2 @@ */

/**
* Returns the transaction this model class is bound to using `bindTransaction` methods.
*
* Handy for making sure two model class are bound to the same transaction:
*
* ```js
* Person
* .bindTransaction(Animal.transaction())
* .query()
* ...
* ```
*
* The example above works even if `Animal` is not bound to any transaction. The
* `bindTransaction` call does nothing in this case.
*
* @returns {knex}

@@ -1073,3 +395,3 @@ */

/**
* Shortcut for `SomeModel.knex().raw()`.
* @return {Raw}
*/

@@ -1082,3 +404,3 @@ static raw() {

/**
* Shortcut for `SomeModel.knex().fn`.
* @return {Object}
*/

@@ -1091,4 +413,2 @@ static fn() {

/**
* Shortcut for `SomeModel.knex().client.formatter()`.
*
* @return {Formatter}

@@ -1101,4 +421,2 @@ */

/**
* Shortcut for `SomeModel.knex().table(SomeModel.tableName)`.
*
* @returns {knex.QueryBuilder}

@@ -1111,46 +429,2 @@ */

/**
* Creates a subclass of this class that is bound to the given knex.
*
* This method can be used to bind a Model subclass to multiple databases for example in
* a multi tenant system.
*
* Example:
*
* ```js
* var knex1 = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database1.db'
* }
* });
*
* var knex2 = require('knex')({
* client: 'sqlite3',
* connection: {
* filename: 'database2.db'
* }
* });
*
* SomeModel.knex(null);
*
* var BoundModel1 = SomeModel.bindKnex(knex1);
* var BoundModel2 = SomeModel.bindKnex(knex2);
*
* // Throws since the knex instance is null.
* SomeModel.query().then();
*
* // Works.
* BoundModel1.query().then(function (models) {
* console.log(models[0] instanceof SomeModel); // --> true
* console.log(models[0] instanceof BoundModel1); // --> true
* });
*
* // Works.
* BoundModel2.query().then(function (models) {
* console.log(models[0] instanceof SomeModel); // --> true
* console.log(models[0] instanceof BoundModel2); // --> true
* });
*
* ```
*
* @param {knex} knex

@@ -1188,28 +462,3 @@ * @returns {Constructor.<Model>}

/**
* Creates a subclass of this class that is bound to the given transaction.
*
* ```js
* var Person = require('./models/Person');
* var transaction;
*
* objection.transaction.start(Person).then(function (trx) {
* transaction = trx;
* return Person
* .bindTransaction(transaction)
* .query()
* .insert({firstName: 'Jennifer'});
* }).then(function (jennifer) {
* return Person
* .bindTransaction(transaction)
* .query()
* .patch({lastName: 'Lawrence'})
* .where('id', jennifer.id);
* }).then(function () {
* return transaction.commit();
* }).catch(function () {
* return transaction.rollback();
* });
* ```
*
* @param trx
* @param {knex} trx
* @returns {Constructor.<Model>}

@@ -1222,6 +471,2 @@ */

/**
* Ensures that the given model is an instance of this class.
*
* If `model` is already an instance of this class, nothing is done.
*
* @param {Model|Object} model

@@ -1248,6 +493,2 @@ * @param {ModelOptions=} options

/**
* Ensures that each element in the given array is an instance of this class.
*
* If an element is already an instance of this class, nothing is done for it.
*
* @param {Array.<Model|Object>} input

@@ -1278,10 +519,12 @@ * @param {ModelOptions=} options

/**
* @ignore
* @returns {number}
*/
static getIdColumnDimension() {
if (_.isArray(this.idColumn)) {
return this.idColumn.length;
@memoize
static getIdPropertyArray() {
let ModelClass = this;
if (_.isArray(ModelClass.idColumn)) {
return _.map(ModelClass.idColumn, col => idColumnToIdProperty(ModelClass, col));
} else {
return 1;
return [idColumnToIdProperty(ModelClass, ModelClass.idColumn)];
}

@@ -1291,8 +534,2 @@ }

/**
* Returns the name of the identifier property.
*
* The identifier property is equal to the `idColumn` if `$parseDatabaseJson` is not
* implemented. If `$parseDatabaseJson` is implemented it may change the id property's
* name. This method passes the `idColumn` through `$parseDatabaseJson`.
*
* @returns {string|Array.<string>}

@@ -1312,4 +549,2 @@ */

/**
* Full identifier column name like 'SomeTable.id'.
*
* @returns {string|Array.<string>}

@@ -1327,4 +562,2 @@ */

/**
* All relations of this class.
*
* @return {Object.<string, Relation>}

@@ -1348,6 +581,2 @@ */

/**
* Get a relation by name.
*
* This should not be used to make queries. Use `$relatedQuery` or `loadRelated` instead.
*
* @return {Relation}

@@ -1366,32 +595,2 @@ */

/**
* Exactly like $loadRelated but for multiple instances.
*
* ```js
* Person.loadRelated([person1, person2], 'children.pets').then(function (persons) {
* var person1 = persons[0];
* var person2 = persons[1];
* });
* ```
*
* Relations can be filtered by giving named filter functions as arguments
* to the relations:
*
* ```js
* Person
* .loadRelated([person1, person2], 'children(orderByAge).[pets(onlyDogs, orderByName), movies]', {
* orderByAge: function (builder) {
* builder.orderBy('age')
* },
* orderByName: function (builder) {
* builder.orderBy('name');
* },
* onlyDogs: function (builder) {
* builder.where('species', 'dog')
* }
* })
* .then(function (persons) {
* console.log(persons[1].children.pets[0]);
* });
* ```
*
* @param {Array.<Model|Object>} $models

@@ -1418,38 +617,5 @@ * @param {string|RelationExpression} expression

/**
* Traverses the relation tree of a list of models.
*
* Calls the callback for each related model recursively. The callback is called
* also for the input models themselves.
*
* There are two ways to call this method:
*
* ```js
* Model.traverse(models, function (model, parentModel, relationName) {
* doSomething(model);
* });
* ```
*
* and
*
* ```js
* Model.traverse(Person, models, function (person, parentModel, relationName) {
* doSomethingForPerson(person);
* });
* ```
*
* In the second example the traverser function is only called for `Person` instances.
*
* @param {function=} filterConstructor
* If this optional constructor is given, the `traverser` is only called for
* models for which `model instanceof filterConstructor` returns true.
*
* @param {Constructor.<Model>=} filterConstructor
* @param {Model|Array.<Model>} models
* The model(s) whose relation trees to traverse.
*
* @param {function(Model, Model, string)} traverser
* The traverser function that is called for each model. The first argument
* is the model itself. If the model is in a relation of some other model
* the second argument is the parent model and the third argument is the
* name of the relation.
*
* @return {Model}

@@ -1510,5 +676,2 @@ */

/**
* @private
*/
function ensureArray(obj) {

@@ -1522,5 +685,2 @@ if (_.isArray(obj)) {

/**
* @private
*/
function traverse(models, parent, relationName, modelClass, callback) {

@@ -1540,5 +700,2 @@ if (!_.isObject(models)) {

/**
* @private
*/
function traverseOne(model, parent, relationName, modelClass, callback) {

@@ -1560,5 +717,2 @@ if (!(model instanceof Model)) {

/**
* @private
*/
function idColumnToIdProperty(ModelClass, idColumn) {

@@ -1574,5 +728,2 @@ let idProperty = ModelClass.columnNameToPropertyName(idColumn);

/**
* @private
*/
function setId(model, id) {

@@ -1611,5 +762,2 @@ const idProp = model.constructor.getIdProperty();

/**
* @private
*/
function getId(model) {

@@ -1616,0 +764,0 @@ const idProp = model.constructor.getIdProperty();

@@ -5,4 +5,6 @@ import _ from 'lodash';

import ValidationError from '../ValidationError';
import hiddenDataGetterSetter from '../utils/decorators/hiddenDataGetterSetter';
import splitQueryProps from '../utils/splitQueryProps';
import {inherits} from '../utils/classUtils';
import {memoize} from '../utils/decorators';
import memoize from '../utils/decorators/memoize';

@@ -13,101 +15,8 @@ /**

* @property {boolean} [patch]
* If true the json is treated as a patch and the `required` field of the json schema is
* ignored in the validation. This allows us to create models with a subset of required
* properties for patch operations.
*
* @property {boolean} [skipValidation]
* If true the json schema validation is skipped.
*/
/**
* Base class for models.
*
* ModelBase provides a mechanism for automatic JSON validation and a way to attach
* functionality to plain javascript objects. A subclass can be created like this:
*
* ```js
* function Person() {
* ModelBase.apply(this, arguments);
* }
*
* ModelBase.extend(Person);
*
* Person.prototype.fullName = function () {
* return this.firstName + ' ' + this.lastName;
* };
*
* Person.jsonSchema = {
* type: 'object',
* properties: {
* id: {type: 'integer'},
* firstName: {type: 'string'},
* lastName: {type: 'string'}
* }
* };
* ```
*
* Use `ModelBase.from*Json` methods to create models from JSON objects:
*
* ```js
* var person = Person.fromJson({firstName: 'Jennifer', lastName: 'Lawrence'});
*
* console.log(person.firstName); // --> 'Jennifer'
* console.log(person.lastName); // --> 'Lawrence'
* console.log(person.fullName()); // --> 'Jennifer Lawrence'
*
* // This throws because the schema validation fails.
* var person2 = Person.fromJson({firstName: 10});
* ```
*
* Properties that are prefixed with '$' are excluded from all JSON representations:
*
* ```js
* var person = Person.fromJson({firstName: 'Jennifer');
* person.$spam = 100;
*
* console.log(person); // --> {firstName: 'Jennifer'}
* console.log(person.$toJson()); // --> {firstName: 'Jennifer'}
* ```
*
* ModelBase makes it possible to have a different database representation for a model.
* For example if your column names are snake_cased in the database but you want to use
* camelCased properties in the code and outside the server you can do this:
*
* ```js
* // This is called when an object is serialized to database format.
* Person.prototype.$formatDatabaseJson = function (json) {
* // Call superclass implementation.
* json = ModelBase.prototype.$formatDatabaseJson.call(this, json);
*
* return _.mapKeys(json, function (value, key) {
* return _.snakeCase(key);
* });
* };
*
* // This is called when an object is read from database.
* Person.prototype.$parseDatabaseJson = function (json) {
* json = _.mapKeys(json, function (value, key) {
* return _.camelCase(key);
* });
*
* // Call superclass implementation.
* return ModelBase.prototype.$parseDatabaseJson.call(this, json);
* };
* ```
*
* @constructor
*/
export default class ModelBase {
/**
* The optional schema against which the JSON is validated.
*
* The jsonSchema can be dynamically modified in the `$beforeValidate` method.
*
* Must follow http://json-schema.org specification. If null no validation is done.
*
* @see $beforeValidate()
* @see $validate()
* @see $afterValidate()
*
* @type {Object}

@@ -118,17 +27,6 @@ */

/**
* This is called before validation.
*
* Here you can dynamically edit the jsonSchema if needed.
*
* @param {Object} jsonSchema
* A deep clone of this class's jsonSchema.
*
* @param {Object} json
* The JSON object to be validated.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The (possibly) modified jsonSchema.
*/

@@ -141,19 +39,6 @@ $beforeValidate(jsonSchema, json, options) {

/**
* Validates the given JSON object.
*
* Calls `$beforeValidation` and `$afterValidation` methods. This method is called
* automatically from `fromJson` and `$setJson` methods. This method can also be
* called explicitly when needed.
*
* @throws {ValidationError}
* If validation fails.
*
* @param {Object=} json
* If not given ==> this.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The input json
*/

@@ -186,11 +71,4 @@ $validate(json = this, options = {}) {

/**
* This is called after successful validation.
*
* You can do further validation here and throw a ValidationError if something goes wrong.
*
* @param {Object=} json
* The JSON object to validate.
*
* @param {ModelOptions=} options
* Optional options.
*/

@@ -202,18 +80,4 @@ $afterValidate(json, options) {

/**
* This is called when a ModelBase is created from a database JSON object.
*
* Converts the JSON object from the database format to the internal format.
*
* @note This function must handle the case where any subset of the columns comes
* in the `json` argument. You cannot assume that all columns are present as it
* depends on the select statement. There can also be additional columns because
* of join clauses, aliases etc.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in database format.
*
* @return {Object}
* The JSON object in internal format.
*/

@@ -225,13 +89,4 @@ $parseDatabaseJson(json) {

/**
* This is called when a ModelBase is converted to database format.
*
* Converts the JSON object from the internal format to the database format.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in internal format.
*
* @return {Object}
* The JSON object in database format.
*/

@@ -243,16 +98,5 @@ $formatDatabaseJson(json) {

/**
* This is called when a ModelBase is created from a JSON object.
*
* Converts the JSON object to the internal format.
*
* @note If you override this remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in external format.
*
* @param {ModelOptions=} options
* Optional options.
*
* @return {Object}
* The JSON object in internal format.
*/

@@ -264,11 +108,4 @@ $parseJson(json, options) {

/**
* This is called when a ModelBase is converted to JSON.
*
* @note Remember to call the super class's implementation.
*
* @param {Object} json
* The JSON object in internal format
*
* @return {Object}
* The JSON object in external format.
*/

@@ -280,8 +117,3 @@ $formatJson(json) {

/**
* Exports this model as a database JSON object.
*
* Calls `$formatDatabaseJson()`.
*
* @return {Object}
* This model as a JSON object in database format.
*/

@@ -293,8 +125,3 @@ $toDatabaseJson() {

/**
* Exports this model as a JSON object.
*
* Calls `$formatJson()`.
*
* @return {Object}
* This model as a JSON object.
*/

@@ -305,7 +132,2 @@ $toJson() {

/**
* Alias for `this.$toJson()`.
*
* For JSON.stringify compatibility.
*/
toJSON() {

@@ -316,16 +138,6 @@ return this.$toJson();

/**
* Sets the values from a JSON object.
*
* Validates the JSON before setting values. Calls `this.$parseJson()`.
*
* @param {Object} json
* The JSON object to set.
*
* @param {ModelOptions=} options
* Optional options.
*
* @returns {ModelBase} `this` for chaining.
*
* @returns {ModelBase}
* @throws ValidationError
* If validation fails.
*/

@@ -353,17 +165,21 @@ $setJson(json, options = {}) {

json = this.$parseJson(json, options);
json = this.$validate(json, options);
// If the json contains query properties like, knex Raw queries or knex/objection query
// builders, we need to split those off into a separate object. This object will be
// joined back in the $toDatabaseJson method.
const split = splitQueryProps(this.constructor, json);
return this.$set(json);
if (split.query) {
// Stash the query properties for later use in $toDatabaseJson method.
this.$stashedQueryProps(split.query);
}
split.json = this.$parseJson(split.json, options);
split.json = this.$validate(split.json, options);
return this.$set(split.json);
}
/**
* Sets the values from a JSON object in database format.
*
* Calls `this.$parseDatabaseJson()`.
*
* @param {Object} json
* The JSON object in database format.
*
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -381,9 +197,4 @@ $setDatabaseJson(json = {}) {

/**
* Sets the values from another model or object.
*
* Unlike $setJson, this doesn't call any `$parseJson` methods or validate the input.
* This simply sets each value in the object to this object.
*
* @param {Object} obj
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -403,37 +214,25 @@ $set(obj) {

/**
* Omits a set of properties.
*
* The selected properties are set to `undefined`. Note that this is done in-place.
* Properties are set to undefined instead of deleting them for performance reasons
* (V8 doesn't like delete).
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit('lastName')
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit(['lastName'])
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$omit({lastName: true})
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* @param {Array.<string>=} keys
* @returns {Array.<string>}
*/
@hiddenDataGetterSetter('omitFromJson')
$omitFromJson(keys) {}
/**
* @param {Array.<string>=} keys
* @returns {Array.<string>}
*/
@hiddenDataGetterSetter('omitFromDatabaseJson')
$omitFromDatabaseJson(keys) {}
/**
* @param {Object=} queryProps
* @returns {Object}
*/
@hiddenDataGetterSetter('stashedQueryProps')
$stashedQueryProps(queryProps) {}
/**
* @param {string|Array.<string>|Object.<string, boolean>} keys
* @returns {ModelBase} `this` for chaining.
* @returns {ModelBase}
*/

@@ -457,35 +256,2 @@ $omit() {

/**
* Picks a set of properties.
*
* All other properties but the selected ones are set to `undefined`. Note that
* this is done in-place. Properties are set to undefined instead of deleting
* them for performance reasons (V8 doesn't like delete).
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick('firstName', 'age')
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick(['firstName', 'age'])
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* ```js
* var json = person
* .fromJson({firstName: 'Jennifer', lastName: 'Lawrence', age: 24})
* .$pick({firstName: true, age: true})
* .toJSON();
*
* console.log(_.has(json, 'lastName')); // --> false
* ```
*
* @param {string|Array.<string>|Object.<string, boolean>} keys

@@ -511,4 +277,2 @@ * @returns {ModelBase} `this` for chaining.

/**
* Returns the values of the given properties as an array.
*
* @param {Array.<string>} props

@@ -528,7 +292,2 @@ * @return {Array.<*>}

/**
* Returns a deep copy of this model.
*
* If this object has instances of ModelBase as properties (or arrays of them)
* they are cloned using their `.$clone()` method.
*
* @return {ModelBase}

@@ -564,6 +323,4 @@ */

/**
* Makes the given constructor a subclass of this class.
*
* @param {function=} subclassConstructor
* @return {function}
* @return {Constructor.<ModelBase>}
*/

@@ -580,16 +337,6 @@ static extend(subclassConstructor) {

/**
* Creates a model instance from a JSON object.
*
* The object is checked against `jsonSchema` and an exception is thrown on failure.
*
* @param {Object=} json
* The JSON from which to create the model.
*
* @param {ModelOptions=} options
* Optional options.
*
* @returns {Model}
*
* @throws ValidationError
* If validation fails.
*/

@@ -603,7 +350,3 @@ static fromJson(json, options) {

/**
* Creates a model instance from a JSON object in database format.
*
* @param {Object=} json
* The JSON from which to create the model.
*
* @returns {Model}

@@ -618,8 +361,2 @@ */

/**
* Omit implementation to use.
*
* The default just sets the property to undefined for performance reasons.
* If the slight performance drop is not an issue for you, you can override
* this method to delete the property instead.
*
* @param {Object} obj

@@ -633,3 +370,2 @@ * @param {string} prop

/**
* @ignore
* @param {string} columnName

@@ -653,3 +389,2 @@ * @returns {string}

/**
* @ignore
* @param {string} propertyName

@@ -673,5 +408,2 @@ * @returns {string}

/**
* @private
*/
function mergeWithDefaults(jsonSchema, json) {

@@ -709,5 +441,2 @@ let merged = null;

/**
* @private
*/
function tryValidate(jsonSchema, json, options) {

@@ -730,5 +459,2 @@ let required;

/**
* @private
*/
function parseValidationError(report) {

@@ -764,9 +490,17 @@ let errorHash = {};

/**
* @private
*/
function toJsonImpl(self, createDbJson, omit, pick) {
function toJsonImpl(model, createDbJson, omit, pick) {
let json = {};
_.each(self, (value, key) => {
const omitFromJson = createDbJson
? model.$omitFromDatabaseJson()
: model.$omitFromJson();
if (createDbJson) {
// If creating a database json object, restore the query properties.
_.each(model.$stashedQueryProps(), (query, key) => {
json[key] = query;
});
}
_.each(model, (value, key) => {
if (key.charAt(0) !== '$'

@@ -776,3 +510,4 @@ && !_.isFunction(value)

&& (!omit || !omit[key])
&& (!pick || pick[key])) {
&& (!pick || pick[key])
&& (!omitFromJson || !contains(omitFromJson, key))) {

@@ -790,5 +525,2 @@ if (_.isObject(value)) {

/**
* @private
*/
function toJsonObject(value, createDbJson) {

@@ -803,2 +535,4 @@ if (_.isArray(value)) {

}
} else if (Buffer.isBuffer(value)) {
return value;
} else {

@@ -809,5 +543,2 @@ return _.cloneDeep(value);

/**
* @private
*/
function toJsonArray(value, createDbJson) {

@@ -817,5 +548,2 @@ return _.map(value, (value) => toJsonObject(value, createDbJson));

/**
* @private
*/
function cloneObject(value) {

@@ -826,2 +554,4 @@ if (_.isArray(value)) {

return value.$clone();
} else if (Buffer.isBuffer(value)) {
return new Buffer(value);
} else {

@@ -832,5 +562,2 @@ return _.cloneDeep(value);

/**
* @private
*/
function cloneArray(value) {

@@ -840,5 +567,2 @@ return _.map(value, cloneObject);

/**
* @private
*/
function omitObject(model, keyObj) {

@@ -854,5 +578,2 @@ const ModelClass = model.constructor;

/**
* @private
*/
function omitArray(model, keys) {

@@ -868,5 +589,2 @@ const ModelClass = model.constructor;

/**
* @private
*/
function pickObject(model, keyObj) {

@@ -882,5 +600,2 @@ const ModelClass = model.constructor;

/**
* @private
*/
function pickArray(model, keys) {

@@ -896,5 +611,2 @@ const ModelClass = model.constructor;

/**
* @private
*/
function contains(arr, value) {

@@ -901,0 +613,0 @@ for (let i = 0, l = arr.length; i < l; ++i) {

@@ -6,5 +6,2 @@ import _ from 'lodash';

/**
* @ignore
*/
export default class EagerFetcher {

@@ -11,0 +8,0 @@

import _ from 'lodash';
import QueryBuilderBase from './QueryBuilderBase';
/**
* Internal representation of insert and update data.
*
* Data passed to update or insert queries can be:
*
* 1. Javascript primitives
* 2. knex raw SQL expressions
* 3. knex queries
* 4. objection queries
*
* This class splits the insert data into two parts:
*
* Part 1:
* * Javascript primitives
*
* Part 2:
* * everything else
*
* The part 1 is converted into `Model` instances and the part 2 is left untouched. As the `InsertionOrUpdate`
* instance passes through objection during an insert or update operation, the different functions can operate
* on the models (for example call $beforeInsert etc. methods on them). When the `InsertionOrUpdate` instance
* finally reaches knex, the two parts are glued back together.
*
* @ignore
*/
export default class InsertionOrUpdate {
constructor({ModelClass, modelsOrObjects, modelOptions}) {
this.ModelClass = ModelClass;
this._models = [];
this._rawOrQuery = [];
this._modelClass = ModelClass;
this._arrayInput = false;
this._models = null;
this.setData(modelsOrObjects, modelOptions);

@@ -50,5 +22,2 @@ }

/**
* Returns true if the input to `setData` method was an array.
*
* @ignore
* @returns {boolean}

@@ -61,70 +30,10 @@ */

/**
* Sets the actual insert/update data.
*
* @ignore
* @param {(Object|Array.<Object>)} data
* @param {(Object|Array.<Object>)} modelsOrObjects
* @param {ModelOptions} modelOptions
*/
setData(data, modelOptions) {
let knex = this.ModelClass.knex();
let KnexQueryBuilder = knex.client.QueryBuilder;
let Raw = knex.client.Raw;
// knex.QueryBuilder and knex.Raw are not documented properties.
// We make sure here that things break if knex changes things.
if (!_.isFunction(KnexQueryBuilder) || !_.isFunction(Raw)) {
throw new Error('knex API has changed: knex.QueryBuilder or knex.Raw constructor missing.');
}
this._models = [];
this._rawOrQuery = [];
this._arrayInput = _.isArray(data);
if (!this._arrayInput) {
data = _.isObject(data) ? [data] : [];
}
// Separate raw queries and query builders from javascript primitives.
// The javascript primitives are converted into a Model instance and the
// "query" properties are stored separately.
_.forEach(data, obj => {
if (obj instanceof this.ModelClass) {
this._models.push(obj);
this._rawOrQuery.push({});
} else {
let modelJson = {};
let rawOrSubquery = {};
_.forEach(obj, (value, key) => {
if (value instanceof KnexQueryBuilder|| value instanceof Raw) {
rawOrSubquery[key] = value;
} else if (value instanceof QueryBuilderBase) {
rawOrSubquery[key] = value.build();
} else {
modelJson[key] = value;
}
});
this._models.push(this.ModelClass.fromJson(modelJson, modelOptions));
this._rawOrQuery.push(rawOrSubquery);
}
});
setData(modelsOrObjects, modelOptions) {
this._models = this._modelClass.ensureModelArray(modelsOrObjects, modelOptions);
this._arrayInput = _.isArray(modelsOrObjects);
}
/**
* Create an object that can be given for the knex update or insert method.
*
* @ignore
* @returns {Object|Array.<Object>}
*/
toKnexInput() {
let knexInput = _.map(this._models, (model, i) => {
return _.merge(model.$toDatabaseJson(), _.mapKeys(this._rawOrQuery[i], (value, key) => {
return model.constructor.propertyNameToColumnName(key);
}));
});
return knexInput.length === 1 ? knexInput[0] : knexInput;
}
}

@@ -10,8 +10,2 @@ import _ from 'lodash';

/**
* Given an model with nested relations, finds a fast way to insert the models into
* database so that not-null constraints are not broken.
*
* @ignore
*/
export default class InsertWithRelated {

@@ -163,6 +157,3 @@

let sourceVal = node.model.$values(conn.relation.ownerProp);
let targetVal = conn.node.model.$values(conn.relation.relatedProp);
let joinModel = {};
let ownerProp = node.model.$values(conn.relation.ownerProp);
let knex = conn.relation.ownerModelClass.knex();

@@ -176,12 +167,5 @@ let modelClass = conn.relation.joinTableModelClass;

for (let i = 0; i < sourceVal.length; ++i) {
joinModel[conn.relation.joinTableOwnerProp[i]] = sourceVal[i];
}
let joinModel = conn.relation.createJoinModels(ownerProp, [conn.node.model]);
joinModel = modelClass.fromJson(joinModel[0]);
for (let i = 0; i < targetVal.length; ++i) {
joinModel[conn.relation.joinTableRelatedProp[i]] = targetVal[i];
}
joinModel = modelClass.fromJson(joinModel);
if (!tableInsertion) {

@@ -297,2 +281,3 @@ tableInsertion = new TableInsertion(modelClass, true);

this.relation = relation;
relation.omitExtraProps([node.model]);
}

@@ -299,0 +284,0 @@

import _ from 'lodash';
import jsonFieldExpressionParser from './parsers/jsonFieldExpressionParser';
import InsertionOrUpdate from './InsertionOrUpdate';
import {inherits} from '../utils/classUtils';

@@ -8,9 +7,4 @@ import {isKnexQueryBuilder, overwriteForDatabase} from '../utils/dbUtils';

/**
* Knex query builder wrapper.
*
* This class is a thin wrapper around knex query builder. This class allows us to add our own
* query builder methods without monkey patching knex query builder.
*
* @constructor
* @ignore
*/

@@ -29,6 +23,4 @@ @overwriteForDatabase()

/**
* Makes the given constructor a subclass of this class.
*
* @param {function=} subclassConstructor
* @return {Class.<QueryBuilderBase>}
* @return {Constructor.<QueryBuilderBase>}
*/

@@ -54,6 +46,2 @@ static extend(subclassConstructor) {

* Sets/gets the query's internal context.
*
* For internal use only.
*
* @ignore
*/

@@ -70,5 +58,3 @@ internalContext() {

/**
* Returns the knex connection passed to the constructor.
*
* @ignore
* @returns {knex}
*/

@@ -80,14 +66,2 @@ knex() {

/**
* Calls the given function immediately and passes `this` as an argument.
*
* Handy for chaining conditional stuff:
*
* ```js
* new QueryBuilderBase().call(function (builder) {
* if (someCondition) {
* builder.where('something', someValue);
* }
* });
* ```
*
* @param {function} func

@@ -102,4 +76,2 @@ * @returns {QueryBuilderBase}

/**
* Returns the SQL string.
*
* @returns {string}

@@ -112,4 +84,2 @@ */

/**
* Returns the SQL string.
*
* @returns {string}

@@ -122,4 +92,2 @@ */

/**
* Create a clone of this builder.
*
* @returns {QueryBuilderBase}

@@ -143,9 +111,3 @@ */

/**
* Removes query builder method calls.
*
* @param {RegExp=} methodNameRegex
* Optional patter to that must match the method names to remove.
* If not given, all calls are removed.
*
* @ignore
*/

@@ -165,11 +127,4 @@ clear(methodNameRegex) {

/**
* Copy query builder method calls from another query builder.
*
* @param {QueryBuilderBase} queryBuilder
* The builder to copy from.
*
* @param {RegExp} methodNameRegex
* Optional regular expression to filter which method calls are copied.
*
* @ignore
*/

@@ -189,7 +144,4 @@ copyFrom(queryBuilder, methodNameRegex) {

/**
* Returns true if the builder has a call to a method whose name matches the `methodNameRegex`.
*
* @param {RegExp} methodNameRegex
*
* @ignore
* @returns {boolean}
*/

@@ -203,8 +155,4 @@ has(methodNameRegex) {

/**
* Builds the query into a knex query builder.
*
* @protected
* @returns {knex.QueryBuilder}
* The built knex query builder.
*
* @protected
*/

@@ -259,3 +207,2 @@ build() {

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -267,3 +214,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -275,3 +221,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -283,3 +228,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -291,3 +235,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -299,3 +242,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -307,3 +249,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -315,3 +256,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -323,3 +263,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -331,3 +270,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -339,3 +277,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -347,3 +284,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -355,3 +291,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -363,3 +298,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -371,3 +305,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -379,3 +312,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -387,3 +319,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -395,3 +326,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -403,3 +333,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -411,3 +340,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -419,3 +347,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -427,3 +354,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -435,3 +361,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -443,3 +368,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -451,3 +375,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -459,3 +382,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -467,3 +389,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -475,3 +396,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -483,3 +403,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -491,3 +410,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -499,3 +417,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -507,3 +424,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -515,3 +431,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -523,3 +438,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -530,5 +444,3 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -540,3 +452,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -548,3 +459,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -556,3 +466,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -564,3 +473,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -572,3 +480,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -580,3 +487,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -588,3 +494,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -596,3 +501,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
*/

@@ -603,3 +507,2 @@ @knexQueryMethod()

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -611,3 +514,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -619,3 +521,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -627,3 +528,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -635,3 +535,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -643,3 +542,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -651,3 +549,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -659,3 +556,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -667,3 +563,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -675,3 +570,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -683,3 +577,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -691,3 +584,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -699,3 +591,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -707,3 +598,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -715,3 +605,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -723,3 +612,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -731,3 +619,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -739,3 +626,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -747,3 +633,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -755,3 +640,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -763,3 +647,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -771,3 +654,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -779,3 +661,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -787,3 +668,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -795,3 +675,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -803,3 +682,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -811,3 +689,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -819,3 +696,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -827,3 +703,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -835,3 +710,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -843,3 +717,2 @@ */

/**
* See <a href="http://knexjs.org">knex documentation</a>
* @returns {QueryBuilderBase}

@@ -851,7 +724,3 @@ */

/**
* Compares a column reference to another
*
* ```js
* builder.whereRef('Person.id', '=', 'Animal.ownerId');
* ```
* @returns {QueryBuilderBase}
*/

@@ -863,7 +732,3 @@ whereRef(lhs, op, rhs) {

/**
* Compares a column reference to another
*
* ```js
* builder.orWhereRef('Person.id', '=', 'Animal.ownerId');
* ```
* @returns {QueryBuilderBase}
*/

@@ -875,16 +740,2 @@ orWhereRef(lhs, op, rhs) {

/**
* `where` for (possibly) composite keys.
*
* ```js
* builder.whereComposite(['id', 'name'], [1, 'Jennifer']);
* ```
*
* ```js
* builder.whereComposite('id', '=', 1);
* ```
*
* @param {string|Array.<string>} cols
* @param {string|*|Array.<*>} op
* @param {*|Array.<*>=} values
*
* @returns {QueryBuilderBase}

@@ -914,21 +765,2 @@ */

/**
* `whereIn` for (possibly) composite keys.
*
*
* ```js
* builder.whereInComposite(['a', 'b'], [[1, 2], [3, 4], [1, 4]]);
* ```
*
* ```js
* builder.whereInComposite('a', [[1], [3], [1]]);
* ```
*
* ```js
* builder.whereInComposite('a', [1, 3, 1]);
* ```
*
* ```js
* builder.whereInComposite(['a', 'b'], SomeModel.query().select('a', 'b'));
* ```
*
* @returns {QueryBuilderBase}

@@ -1044,29 +876,4 @@ */

/**
* Where jsonb field reference equals jsonb object or other field reference.
*
* Also supports having field expression in both sides of equality.
*
* ```js
* Person
* .query()
* .whereJsonEquals('additionalData:myDogs', 'additionalData:dogsAtHome')
* .then(function (people) {
* // oh joy! these people have all their dogs at home!
* });
*
* Person
* .query()
* .whereJsonEquals('additionalData:myDogs[0]', { name: "peter"})
* .then(function (people) {
* // these people's first dog name is "peter" and the dog has no other
* // attributes, but its name
* });
* ```
*
* @param {FieldExpression} fieldExpression
* Reference to column / json field.
*
* @param {Object|Array|FieldExpression} jsonObjectOrFieldExpression
* Reference to column / json field or json object.
*
* @returns {QueryBuilderBase}

@@ -1079,3 +886,3 @@ */

/**
* @see {@link QueryBuilderBase#whereJsonEquals}
* @returns {QueryBuilderBase}
*/

@@ -1087,3 +894,3 @@ orWhereJsonEquals(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonEquals}
* @returns {QueryBuilderBase}
*/

@@ -1095,3 +902,3 @@ whereJsonNotEquals(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonEquals}
* @returns {QueryBuilderBase}
*/

@@ -1103,62 +910,4 @@ orWhereJsonNotEquals(fieldExpression, jsonObjectOrFieldExpression) {

/**
* Where left hand json field reference is a superset of the right hand json value or reference.
*
* ```js
* Person
* .query()
* .whereJsonSupersetOf('additionalData:myDogs', 'additionalData:dogsAtHome')
* .then(function (people) {
* // These people have all or some of their dogs at home. Person might have some
* // additional dogs in their custody since myDogs is superset of dogsAtHome.
* });
*
* Person
* .query()
* .whereJsonSupersetOf('additionalData:myDogs[0]', { name: "peter"})
* .then(function (people) {
* // These people's first dog name is "peter", but the dog might have
* // additional attributes as well.
* });
* ```
*
* Object and array are always their own supersets.
*
* For arrays this means that left side matches if it has all the elements
* listed in the right hand side. e.g.
*
* ```
* [1,2,3] isSuperSetOf [2] => true
* [1,2,3] isSuperSetOf [2,1,3] => true
* [1,2,3] isSuperSetOf [2,null] => false
* [1,2,3] isSuperSetOf [] => true
* ```
*
* The `not` variants with jsonb operators behave in a way that they won't match rows, which don't have
* the referred json key referred in field expression. e.g. for table
*
* ```
* id | jsonObject
* ----+--------------------------
* 1 | {}
* 2 | NULL
* 3 | {"a": 1}
* 4 | {"a": 1, "b": 2}
* 5 | {"a": ['3'], "b": ['3']}
* ```
*
* query:
*
* ```js
* builder.whereJsonNotEquals("jsonObject:a", "jsonObject:b")
* ```
*
* Returns only the row `4` which has keys `a` and `b` and `a` != `b`, but it won't return any rows which
* does not have `jsonObject.a` or `jsonObject.b`.
*
* @param {FieldExpression} fieldExpression
* Reference to column / json field, which is tested for being a superset.
*
* @param {Object|Array|FieldExpression} jsonObjectOrFieldExpression
* To which to compare.
*
* @returns {QueryBuilderBase}

@@ -1171,3 +920,3 @@ */

/**
* @see {@link QueryBuilderBase#whereJsonSupersetOf}
* @returns {QueryBuilderBase}
*/

@@ -1179,3 +928,3 @@ orWhereJsonSupersetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonSupersetOf}
* @returns {QueryBuilderBase}
*/

@@ -1187,3 +936,3 @@ whereJsonNotSupersetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonSupersetOf}
* @returns {QueryBuilderBase}
*/

@@ -1195,8 +944,2 @@ orWhereJsonNotSupersetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* Where left hand json field reference is a subset of the right hand json value or reference.
*
* Object and array are always their own subsets.
*
* @see {@link QueryBuilderBase#whereJsonSupersetOf}
*
* @param {FieldExpression} fieldExpression

@@ -1211,3 +954,3 @@ * @param {Object|Array|FieldExpression} jsonObjectOrFieldExpression

/**
* @see {@link QueryBuilderBase#whereJsonSubsetOf}
* @returns {QueryBuilderBase}
*/

@@ -1219,3 +962,3 @@ orWhereJsonSubsetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonSubsetOf}
* @returns {QueryBuilderBase}
*/

@@ -1227,3 +970,3 @@ whereJsonNotSubsetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonSubsetOf}
* @returns {QueryBuilderBase}
*/

@@ -1235,4 +978,2 @@ orWhereJsonNotSubsetOf(fieldExpression, jsonObjectOrFieldExpression) {

/**
* Where json field reference is an array.
*
* @param {FieldExpression} fieldExpression

@@ -1246,3 +987,3 @@ * @returns {QueryBuilderBase}

/**
* @see {@link QueryBuilderBase#whereJsonIsArray}
* @returns {QueryBuilderBase}
*/

@@ -1254,4 +995,3 @@ orWhereJsonIsArray(fieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonIsArray}
* @note Also returns rows where `fieldExpression` does not exist.
* @returns {QueryBuilderBase}
*/

@@ -1271,4 +1011,3 @@ whereJsonNotArray(fieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonIsArray}
* @note Also returns rows where `fieldExpression` does not exist.
* @returns {QueryBuilderBase}
*/

@@ -1287,4 +1026,2 @@ orWhereJsonNotArray(fieldExpression) {

/**
* Where json field reference is an object.
*
* @param {FieldExpression} fieldExpression

@@ -1298,3 +1035,3 @@ * @returns {QueryBuilderBase}

/**
* @see {@link QueryBuilderBase#whereJsonIsObject}
* @returns {QueryBuilderBase}
*/

@@ -1306,4 +1043,3 @@ orWhereJsonIsObject(fieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonIsObject}
* @note Also returns rows where `fieldExpression` does not exist.
* @returns {QueryBuilderBase}
*/

@@ -1322,4 +1058,3 @@ whereJsonNotObject(fieldExpression) {

/**
* @see {@link QueryBuilderBase#whereJsonIsObject}
* @note Also returns rows where `fieldExpression` does not exist.
* @returns {QueryBuilderBase}
*/

@@ -1338,6 +1073,4 @@ orWhereJsonNotObject(fieldExpression) {

/**
* Where any of given strings is found from json object key(s) or array items.
*
* @param {FieldExpression} fieldExpression
* @param {string|Array.<string>} keys Strings that are looked from object or array.
* @param {string|Array.<string>} keys
* @returns {QueryBuilderBase}

@@ -1350,3 +1083,3 @@ */

/**
* @see {@link QueryBuilderBase#whereJsonHasAny}
* @returns {QueryBuilderBase}
*/

@@ -1358,6 +1091,4 @@ orWhereJsonHasAny(fieldExpression, keys) {

/**
* Where all of given strings are found from json object key(s) or array items.
*
* @param {FieldExpression} fieldExpression
* @param {string|Array.<string>} keys Strings that are looked from object or array.
* @param {string|Array.<string>} keys
* @returns {QueryBuilderBase}

@@ -1370,3 +1101,3 @@ */

/**
* @see {@link QueryBuilderBase#whereJsonHasAll}
* @returns {QueryBuilderBase}
*/

@@ -1378,18 +1109,5 @@ orWhereJsonHasAll(fieldExpression, keys) {

/**
* Where referred json field value casted to same type with value fulfill given operand.
*
* Value may be number, string, null, boolean and referred json field is converted
* to TEXT, NUMERIC or BOOLEAN sql type for comparison.
*
* If left hand field does not exist rows appear IS null so if one needs to get only
* rows, which has key and it's value is null one may use e.g.
* `.whereJsonSupersetOf("column", { field: null })` or check is key exist and
* then `.whereJsonField('column:field', 'IS', null)`
*
* For testing against objects or arrays one should see tested with whereJsonEqual,
* whereJsonSupersetOf and whereJsonSubsetOf methods.
*
* @param {FieldExpression} fieldExpression Expression pointing to certain value.
* @param {string} operator SQL comparator usually `<`, `>`, `<>`, `=` or `!=`
* @param {boolean|Number|string|null} value Value to which field is compared to.
* @param {FieldExpression} fieldExpression
* @param {string} operator
* @param {boolean|Number|string|null} value
* @returns {QueryBuilderBase}

@@ -1403,3 +1121,3 @@ */

/**
* @see {@link QueryBuilderBase#whereJsonField}
* @returns {QueryBuilderBase}
*/

@@ -1436,5 +1154,2 @@ orWhereJsonField(fieldExpression, operator, value) {

/**
* @private
*/
function knexQueryMethod(overrideMethodName) {

@@ -1448,5 +1163,2 @@ return function (target, methodName, descriptor) {

/**
* @private
*/
function wrapFunctionArg(func, query) {

@@ -1464,27 +1176,2 @@ return function () {

/**
* Parses a objection.js json field expression into a postgres jsonb field reference.
*
* For example, assume we have this object stored in the column `jsonColumn` of a table `Table`:
*
* ```
* {obj: { "key.with.dots": [{"key": { "0": { me : [ "I was referred" ] } } } ] } }
* ```
*
* We can refer to the value "I was referred" using the following field expression:
*
* ```
* Table.jsonColumn:obj[key.with.dots][0].key.0.me[0]
* ```
*
* Since Postgresql #>{field,0,field2,...} operator does not make difference if
* reference is string or a number, one can actually use also jsonArray.0 notation
* to refer index of an array. Like wise one can use object[123] notation to refer
* key of an object { "123" : null }.
*
* @private
* @param {string} expression
* @param {boolean} extractAsText Return text instead of jsonb object (useful for type casting).
* @returns {string} postgres json reference.
*/
function parseFieldExpression(expression, extractAsText) {

@@ -1498,24 +1185,2 @@ let parsed = jsonFieldExpressionParser.parse(expression);

/**
* Where jsonb reference on left hand side is compared to jsonb value or reference on the right hand side.
*
* Converts left and right hand values to PostgreSQL acceptable format and add user chosen
* operator between left and right hand expressions.
*
* ```javascript
* whereJsonbRefOnLeftJsonbValOrRefOnRight(queryBuilder, "ModelJson.jsonObject:objectField", "<@", { key: 1 })
* ```
*
* ```sql
* select * from "ModelJson" where ("ModelJson"."jsonObject"#>'{objectField}')::jsonb <@ '{\"key\":\ 1}'::jsonb
* ```
*
* @private
* @param {QueryBuilderBase} builder
* @param {FieldExpression} fieldExpression Reference to column / jsonField.
* @param {string} operator operator to apply.
* @param {Object|Array|FieldExpression} jsonObjectOrFieldExpression Reference to column / jsonField or json object.
* @param {string=} queryPrefix string prepended to query e.g. 'not'. Space after string added implicitly.
* @returns {QueryBuilderBase}
*/
function whereJsonbRefOnLeftJsonbValOrRefOnRight(builder, fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix) {

@@ -1526,6 +1191,2 @@ let queryParams = whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams(fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix);

/**
* @private
* @see {@link whereJsonbRefOnLeftJsonbValOrRefOnRight} for documentation.
*/
function orWhereJsonbRefOnLeftJsonbValOrRefOnRight(builder, fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix) {

@@ -1536,7 +1197,2 @@ let queryParams = whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams(fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix);

/**
* @private
* @see {@link whereJsonbRefOnLeftJsonbValOrRefOnRight} for documentation.
* @return {Array} Parameters for whereRaw call.
*/
function whereJsonbRefOnLeftJsonbValOrRefOnRightRawQueryParams(fieldExpression, operator, jsonObjectOrFieldExpression, queryPrefix) {

@@ -1563,20 +1219,2 @@ let fieldReference = parseFieldExpression(fieldExpression);

/**
* Where field expression on left side and string or an array of strings on right hand side.
*
* ```javascript
* whereJsonFieldRightStringArrayOnLeft(queryBuilder, "ModelJson.jsonObject:a", "?&", ["1","2"])
* ```
*
* ```sql
* select * from "ModelJson" where "ModelJson"."jsonObject"#>'{a}' ?& array['1','2']
* ```
*
* @private
* @param {QueryBuilderBase} builder
* @param {FieldExpression} fieldExpression
* @param {string} operator
* @param {Array.<string>} keys
* @returns {QueryBuilderBase}
*/
function whereJsonFieldRightStringArrayOnLeft(builder, fieldExpression, operator, keys) {

@@ -1586,6 +1224,2 @@ return builder.whereRaw(whereJsonFieldRightStringArrayOnLeftQuery(builder, fieldExpression, operator, keys));

/**
* @private
* @see {@link whereJsonFieldRightStringArrayOnLeft} for documentation.
*/
function orWhereJsonFieldRightStringArrayOnLeft(builder, fieldExpression, operator, keys) {

@@ -1595,6 +1229,2 @@ return builder.orWhereRaw(whereJsonFieldRightStringArrayOnLeftQuery(builder, fieldExpression, operator, keys));

/**
* @private
* @see {@link whereJsonFieldRightStringArrayOnLeft} for documentation.
*/
function whereJsonFieldRightStringArrayOnLeftQuery(builder, fieldExpression, operator, keys) {

@@ -1618,6 +1248,2 @@ let knex = builder._knex;

/**
* @private
* @see {@link QueryBuilderBase#whereJsonField} for documentation.
*/
function whereJsonFieldQuery(knex, fieldExpression, operator, value) {

@@ -1646,8 +1272,2 @@ let fieldReference = parseFieldExpression(fieldExpression, true);

/**
* @private
* @param knex
* @param {string} operator
* @returns {string}
*/
function normalizeOperator(knex, operator) {

@@ -1654,0 +1274,0 @@ let trimmedLowerCase = operator.trim().toLowerCase();

@@ -5,64 +5,10 @@ import _ from 'lodash';

/**
* Relation expression is a simple DSL for expressing relation trees.
*
* For example an expression `children.[movies.actors.[pets, children], pets]` represents a tree:
*
* ```
* children
* (Person)
* |
* -----------------
* | |
* movies pets
* (Movie) (Animal)
* |
* actors
* (Person)
* |
* -----------
* | |
* pets children
* (Animal) (Person)
*
* ```
*
* The model classes are shown in parenthesis.
*
* This class rarely needs to be used directly. The relation expression can be given to a bunch
* of functions in objection.js. For example:
*
* ```js
* Person
* .query()
* .eager('children.[movies.actors.[pets, children], pets]')
* .then(function (persons) {
* // All persons have the given relation tree fetched.
* console.log(persons[0].children[0].movies[0].actors[0].pets[0].name);
* });
* ```
*
* There are two tokens that have special meaning: `*` and `^`. `*` means "all relations recursively" and
* `^` means "this relation recursively".
*
* For example `children.*` means "relation `children` and all its relations, and all their relations and ...".
* The `*` token must be used with caution or you will end up fetching your entire database.
*
* Expression `parent.^` is equivalent to `parent.parent.parent.parent...` up to the point a relation no longer
* has results for the `parent` relation.
*
* Relation expressions can also have arguments. Arguments are listed in parenthesis after the relation names
* like this:
*
* ```js
* children(arg1, arg2).[movies.actors(arg3), pets]
* ```
*
* In this example `children` relation had arguments `arg1` and `arg2` and `actors` relation had
* the argument `arg3`.
*/
const RECURSIVE_REGEX = /^\^(\d*)$/;
const ALL_RECURSIVE_REGEX = /^\*$/;
export default class RelationExpression {
constructor(node) {
constructor(node, recursionDepth) {
node = node || {};
this.name = node.name || null;

@@ -72,7 +18,10 @@ this.args = node.args || [];

this.children = node.children || {};
Object.defineProperty(this, 'recursionDepth', {
enumerable: false,
value: recursionDepth || 0
});
}
/**
* Parses an expression string into a {@link RelationExpression} object.
*
* @param {string|RelationExpression} expr

@@ -99,18 +48,2 @@ * @returns {RelationExpression}

/**
* Tests if another expression is a sub expression of this one.
*
* Expression B is a sub expression of expression A if:
*
* - A and B have the same root
* - And each path from root to a leaf in B can be found in A
*
* For example sub expressions of `children.[movies.actors, pets]` are:
*
* - `children`
* - `children.movies`
* - `children.pets`
* - `children.movies.actors`
* - `children.[movies, pets]`
* - `children.[movies.actors, pets]`
*
* @param {string|RelationExpression} expr

@@ -134,4 +67,6 @@ * @returns {boolean}

if (expr.isRecursive()) {
return this.isAllRecursive() || this.isRecursive();
const maxRecursionDepth = expr.maxRecursionDepth();
if (maxRecursionDepth > 0) {
return this.isAllRecursive() || this.maxRecursionDepth() >= maxRecursionDepth;
}

@@ -148,24 +83,39 @@

/**
* @ignore
* @returns {boolean}
* @returns {number}
*/
isRecursive() {
return !!this.children['^'];
maxRecursionDepth() {
if (this.numChildren !== 1) {
return 0;
}
return _.map(this.children, (val, key) => {
const rec = RECURSIVE_REGEX.exec(key);
if (rec) {
const maxDepth = rec[1];
if (maxDepth) {
return parseInt(maxDepth, 10);
} else {
return Number.POSITIVE_INFINITY;
}
} else {
return 0;
}
})[0];
}
/**
* @ignore
* @returns {boolean}
*/
isAllRecursive() {
return this.numChildren === 1 && !!this.children['*'];
return this.numChildren === 1 && _.all(this.children, (val, key) => ALL_RECURSIVE_REGEX.test(key));
}
/**
* @ignore
* @returns {RelationExpression}
*/
childExpression(childName) {
if (this.isAllRecursive() || (this.isRecursive() && childName === this.name)) {
return this;
if (this.isAllRecursive() || (childName === this.name && this.recursionDepth < this.maxRecursionDepth() - 1)) {
return new RelationExpression(this, this.recursionDepth + 1);
}

@@ -181,3 +131,3 @@

/**
* @ignore
* @returns {RelationExpression}
*/

@@ -188,8 +138,5 @@ clone() {

/**
* @ignore
*/
forEachChild(cb) {
_.each(this.children, (child, childName) => {
if (childName !== '*' && childName !== '^') {
if (!ALL_RECURSIVE_REGEX.test(childName) && !RECURSIVE_REGEX.test(childName)) {
cb(child, childName);

@@ -201,3 +148,2 @@ }

/**
* @ignore
* @return {Array.<RelationExpression>}

@@ -204,0 +150,0 @@ */

import _ from 'lodash';
import Relation from './Relation';
import normalizeIds from '../utils/normalizeIds';
/**
* @ignore
* @extends Relation
*/
export default class BelongsToOneRelation extends Relation {
/**
* @override
* @inheritDoc
*/
createRelationProp(owners, related) {

@@ -22,6 +16,2 @@ let relatedByOwnerId = _.indexBy(related, related => related.$values(this.relatedProp));

/**
* @override
* @inheritDoc
*/
insert(builder, owner, insertion) {

@@ -55,8 +45,4 @@ if (insertion.models().length > 1) {

/**
* @override
* @inheritDoc
*/
relate(builder, owner, ids) {
ids = this.normalizeId(ids, this.relatedProp.length);
ids = normalizeIds(ids, this.relatedProp, {arrayOutput: true});

@@ -85,6 +71,2 @@ if (ids.length > 1) {

/**
* @override
* @inheritDoc
*/
unrelate(builder, owner) {

@@ -91,0 +73,0 @@ builder.setQueryExecutor(builder => {

import _ from 'lodash';
import Relation from './Relation';
import normalizeIds from '../utils/normalizeIds';
/**
* @ignore
* @extends Relation
*/
export default class HasManyRelation extends Relation {
/**
* @override
* @inheritDoc
*/
createRelationProp(owners, related) {

@@ -22,6 +16,2 @@ let relatedByOwnerId = _.groupBy(related, related => related.$values(this.relatedProp));

/**
* @override
* @inheritDoc
*/
insert(builder, owner, insertion) {

@@ -44,5 +34,2 @@ _.each(insertion.models(), insert => {

/**
* @protected
*/
appendRelationProp(owner, related) {

@@ -52,8 +39,4 @@ owner[this.name] = this.mergeModels(owner[this.name], related);

/**
* @override
* @inheritDoc
*/
relate(builder, owner, ids) {
ids = this.normalizeId(ids, this.relatedModelClass.getIdColumnDimension());
ids = normalizeIds(ids, this.relatedModelClass.getIdPropertyArray(), {arrayOutput: true});

@@ -78,6 +61,2 @@ builder.setQueryExecutor(builder => {

/**
* @override
* @inheritDoc
*/
unrelate(builder, owner) {

@@ -84,0 +63,0 @@ builder.setQueryExecutor(builder => {

import _ from 'lodash';
import HasManyRelation from './HasManyRelation';
/**
* @ignore
* @extends HasManyRelation
*/
export default class HasOneRelation extends HasManyRelation {
/**
* @override
* @inheritDoc
*/
createRelationProp(owners, related) {

@@ -22,6 +15,2 @@ let relatedByOwnerId = _.indexBy(related, related => related.$values(this.relatedProp));

/**
* @override
* @inheritDoc
*/
appendRelationProp(owner, related) {

@@ -28,0 +17,0 @@ owner[this.name] = related[0] || null;

import _ from 'lodash';
import Relation from './Relation';
import ModelBase from '../model/ModelBase';
import inheritModel from '../model/inheritModel';
import normalizeIds from '../utils/normalizeIds';
import {overwriteForDatabase} from '../utils/dbUtils';
import {isSubclassOf} from '../utils/classUtils';
import {memoize} from '../utils/decorators';
import memoize from '../utils/decorators/memoize';

@@ -11,6 +13,2 @@ const ownerJoinColumnAliasPrefix = 'objectiontmpjoin';

/**
* @ignore
* @extends Relation
*/
@overwriteForDatabase()

@@ -23,4 +21,2 @@ export default class ManyToManyRelation extends Relation {

/**
* The join table.
*
* @type {string}

@@ -31,4 +27,2 @@ */

/**
* The relation column in the join table that points to the owner table.
*
* @type {Array.<string>}

@@ -39,4 +33,2 @@ */

/**
* The relation property in the join model that points to the owner table.
*
* @type {Array.<string>}

@@ -47,4 +39,2 @@ */

/**
* The relation column in the join table that points to the related table.
*
* @type {Array.<string>}

@@ -55,4 +45,2 @@ */

/**
* The relation property in the join model that points to the related table.
*
* @type {Array.<string>}

@@ -63,16 +51,17 @@ */

/**
* The join table model class.
*
* This can be optionally given using the `join.through.modelClass` property,
* otherwise an anonymous model class is created in `setMapping` method.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/
this.joinTableModelClass = null;
/**
* @type {Array.<string>}
*/
this.joinTableExtraCols = null;
/**
* @type {Array.<string>}
*/
this.joinTableExtraProps = null;
}
/**
* @override
* @inheritDoc
*/
setMapping(mapping) {

@@ -95,2 +84,3 @@ let retVal = super.setMapping(mapping);

let joinTableTo = this.parseReference(mapping.join.through.to);
let joinTableExtra = mapping.join.through.extra || [];

@@ -110,2 +100,3 @@ if (!joinTableFrom.table || _.isEmpty(joinTableFrom.columns)) {

this.joinTable = joinTableFrom.table;
this.joinTableExtraCols = joinTableExtra;

@@ -151,2 +142,3 @@ if (joinFrom.table === this.ownerModelClass.tableName) {

this.joinTableRelatedProp = this.propertyName(this.joinTableRelatedCol, this.joinTableModelClass);
this.joinTableExtraProps = this.propertyName(this.joinTableExtraCols, this.joinTableModelClass);

@@ -157,6 +149,2 @@ return retVal;

/**
* Reference to the column in the join table that refers to `fullOwnerCol()`.
*
* For example: [`Person_Movie.actorId`].
*
* @returns {Array.<string>}

@@ -170,6 +158,2 @@ */

/**
* Reference to the column in the join table that refers to `fullRelatedCol()`.
*
* For example: [`Person_Movie.movieId`].
*
* @returns {Array.<string>}

@@ -183,6 +167,10 @@ */

/**
* Alias to use for the join table when joining with the owner table.
*
* For example: `Person_Movie_rel_movies`.
*
* @returns {Array.<string>}
*/
@memoize
fullJoinTableExtraCols() {
return _.map(this.joinTableExtraCols, col => this.joinTable + '.' + col);
}
/**
* @returns {string}

@@ -195,4 +183,3 @@ */

/**
* @inheritDoc
* @override
* @returns {ManyToManyRelation}
*/

@@ -208,2 +195,4 @@ clone() {

relation.joinTableModelClass = this.joinTableModelClass;
relation.joinTableExtraCols = this.joinTableExtraCols;
relation.joinTableExtraProps = this.joinTableExtraProps;

@@ -214,4 +203,3 @@ return relation;

/**
* @inheritDoc
* @override
* @returns {ManyToManyRelation}
*/

@@ -225,4 +213,2 @@ bindKnex(knex) {

/**
* @override
* @inheritDoc
* @returns {QueryBuilder}

@@ -256,4 +242,2 @@ */

/**
* @override
* @inheritDoc
* @returns {QueryBuilder}

@@ -292,6 +276,2 @@ */

/**
* @override
* @inheritDoc
*/
find(builder, owners) {

@@ -311,2 +291,7 @@ const ownerJoinColumnAlias = _.times(this.joinTableOwnerCol.length, idx => ownerJoinColumnAliasPrefix + idx);

builder.select(this.relatedModelClass.tableName + '.*');
// Also select all extra columns.
_.each(this.fullJoinTableExtraCols(), col => {
builder.select(col);
});
}

@@ -341,7 +326,5 @@

/**
* @override
* @inheritDoc
*/
insert(builder, owner, insertion) {
this.omitExtraProps(insertion.models());
builder.onBuild(builder => {

@@ -353,4 +336,3 @@ builder.$$insert(insertion);

let ownerId = owner.$values(this.ownerProp);
let relatedIds = _.map(related, related => related.$values(this.relatedProp));
let joinModels = this._createJoinModels(ownerId, relatedIds);
let joinModels = this.createJoinModels(ownerId, related);

@@ -369,6 +351,2 @@ owner[this.name] = this.mergeModels(owner[this.name], related);

/**
* @override
* @inheritDoc
*/
update(builder, owner, update) {

@@ -380,6 +358,2 @@ builder.onBuild(builder => {

/**
* @override
* @inheritDoc
*/
delete(builder, owner) {

@@ -391,11 +365,7 @@ builder.onBuild(builder => {

/**
* @override
* @inheritDoc
*/
relate(builder, owner, ids) {
ids = this.normalizeId(ids, this.relatedProp.length);
ids = normalizeIds(ids, this.relatedProp);
builder.setQueryExecutor(builder => {
let joinModels = this._createJoinModels(owner.$values(this.ownerProp), ids);
let joinModels = this.createJoinModels(owner.$values(this.ownerProp), ids);

@@ -411,6 +381,2 @@ return this.joinTableModelClass

/**
* @override
* @inheritDoc
*/
@overwriteForDatabase({

@@ -440,5 +406,2 @@ sqlite3: 'unrelate_sqlite3'

/**
* Special unrelate implementation for sqlite3. sqlite3 doesn't support multi-value
* where-in clauses. We need to use the built-in _rowid_ instead.
*
* @private

@@ -499,5 +462,2 @@ */

/**
* Special _selectForModify implementation for sqlite3. sqlite3 doesn't support multi-value
* where-in clauses. We need to use the built-in _rowid_ instead.
*
* @private

@@ -530,7 +490,4 @@ */

/**
* @private
*/
_createJoinModels(ownerId, relatedIds) {
return _.map(relatedIds, relatedId => {
createJoinModels(ownerId, related) {
return _.map(related, related => {
let joinModel = {};

@@ -543,8 +500,18 @@

_.each(this.joinTableRelatedProp, (joinTableRelatedProp, idx) => {
joinModel[joinTableRelatedProp] = relatedId[idx];
joinModel[joinTableRelatedProp] = related[this.relatedProp[idx]];
});
_.each(this.joinTableExtraProps, extraProp => {
if (!_.isUndefined(related[extraProp])) {
joinModel[extraProp] = related[extraProp];
}
});
return joinModel;
});
}
omitExtraProps(models) {
_.each(models, model => model.$omitFromDatabaseJson(this.joinTableExtraProps));
}
}
import _ from 'lodash';
import {inherits, isSubclassOf} from '../utils/classUtils';
import {memoize} from '../utils/decorators';
import memoize from '../utils/decorators/memoize';
import QueryBuilder from '../queryBuilder/QueryBuilder';

@@ -8,54 +8,10 @@

* @typedef {Object} RelationJoin
*
* An object literal that describes how two tables are related to one another. For example:
*
* ```js
* {
* from: 'Animal.ownerId',
* to: 'Person.id'
* }
* ```
*
* or in the case of a many-to-many relation:
*
* ```js
* {
* from: 'Person.id',
* through: {
* from: 'Person_Movie.actorId',
* to: 'Person_Movie.movieId'
* },
* to: 'Movie.id'
* }
* ```
*
* @property {string|Array.<string>} from
* The relation column in the owner table. Must be given with the table name.
* For example `Person.id`. Composite key can be specified using an array of
* columns e.g. `['Person.a', 'Person.b']`. Note that neither this nor `to`
* need to be foreign keys or primary keys. You can join any column to
* any column.
*
* @property {string|Array.<string>} to
* The relation column in the related table. Must be given with the table name.
* For example `Movie.id`. Composite key can be specified using an array of
* columns e.g. `['Movie.a', 'Movie.b']`. Note that neither this nor `from`
* need to be foreign keys or primary keys. You can join any column to any column.
*
* @property {Object} through
* Describes the join table if the models are related through one.
*
* @property {Class.<Model>} through.modelClass
* If the there is model class available for the join table, it can be provided
* using this property.
*
* @property {Constructor.<Model>} through.modelClass
* @property {string|Array.<string>} through.from
* The column that is joined to `from` property of the `RelationJoin`. For example
* `Person_Movie.actorId` where `Person_Movie` is the join table. Composite key can
* be specified using an array of columns e.g. `['Person_Movie.a', 'Person_Movie.b']`.
*
* @property {string|Array.<string>} through.to
* The column that is joined to `to` property of the `RelationJoin`. For example
* `Person_Movie.movieId` where `Person_Movie` is the join table. Composite key can
* be specified using an array of columns e.g. `['Person_Movie.a', 'Person_Movie.b']`.
* @property {Array.<string>} through.extra
*/

@@ -66,29 +22,9 @@

*
* @property {Class.<Model>|string} modelClass
* A {@link Model} subclass constructor or an absolute path to a module that exports one.
*
* @property {Constructor.<Model>|string} modelClass
* @property {Relation} relation
* A relation constructor. You can use one of Model.BelongsToOneRelation, Model.HasOneRelation, Model.HasManyRelation and
* Model.ManyToManyRelation or even write your own relation type by subclassing {@link Relation}.
*
* @property {Object|function(QueryBuilder)} filter
* Additional filter for the relation. It can be either a hash of {column: 'value'} pairs or
* a function that takes a QueryBuilder as a parameter.
*
* @property {RelationJoin} [join]
* An object that describes how the two models are related.
*/
/**
* Represents a relation between two `Model` subclasses.
*
* This is an abstract base class and should never be instantiated.
*
* @param {string} relationName
* Name of the relation.
*
* @param {Model} OwnerClass
* The Model subclass that owns this relation.
*
* @ignore
* @abstract

@@ -100,4 +36,2 @@ */

/**
* Name of the relation.
*
* @type {string}

@@ -108,7 +42,3 @@ */

/**
* The owner class of this relation.
*
* This must be a subclass of Model.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/

@@ -118,7 +48,3 @@ this.ownerModelClass = OwnerClass;

/**
* The related class.
*
* This must be a subclass of Model.
*
* @type {Class.<Model>}
* @type {Constructor.<Model>}
*/

@@ -128,4 +54,2 @@ this.relatedModelClass = null;

/**
* The relation column in the owner table.
*
* @type {Array.<string>}

@@ -136,4 +60,2 @@ */

/**
* The relation property in the owner model.
*
* @type {Array.<string>}

@@ -144,4 +66,2 @@ */

/**
* The relation column in the related table.
*
* @type {Array.<string>}

@@ -152,4 +72,2 @@ */

/**
* The relation property in the related model.
*
* @type {Array.<string>}

@@ -160,4 +78,2 @@ */

/**
* Optional additional filter query.
*
* @type {function (QueryBuilder)}

@@ -169,6 +85,4 @@ */

/**
* Makes the given constructor a subclass of this class.
*
* @param {function=} subclassConstructor
* @return {Class.<Model>}
* @return {Constructor.<Model>}
*/

@@ -181,4 +95,2 @@ static extend(subclassConstructor) {

/**
* Constructs the instance based on a mapping data.
*
* @param {RelationMapping} mapping

@@ -267,3 +179,3 @@ */

/**
* Return the knex connection.
* @returns {knex}
*/

@@ -275,6 +187,2 @@ knex() {

/**
* Reference to the relation column in the owner model's table.
*
* For example: [`Person.id`].
*
* @returns {Array.<string>}

@@ -288,6 +196,2 @@ */

/**
* Reference to the relation column in the related model's table.
*
* For example: [`Movie.id`].
*
* @returns {Array.<string>}

@@ -301,6 +205,2 @@ */

/**
* Alias to use for the related table when joining with the owner table.
*
* For example: `Movie_rel_movies`.
*
* @returns {string}

@@ -314,4 +214,2 @@ */

/**
* Clones this relation.
*
* @returns {Relation}

@@ -333,7 +231,3 @@ */

/**
* Returns a clone of this relation with `relatedModelClass` and `ownerModelClass` bound to the given knex.
*
* See `Model.bindKnex`.
*
* @param knex
* @param {knex} knex
* @returns {Relation}

@@ -568,5 +462,6 @@ */

for (let i = 0; i < ref.length; ++i) {
let parts = ref[i].split('.');
let tableName = parts[0] && parts[0].trim();
let columnName = parts[1] && parts[1].trim();
const refItem = ref[i];
const ndx = refItem.lastIndexOf('.');
let tableName = refItem.substr(0, ndx).trim();
let columnName = refItem.substr(ndx + 1, refItem.length).trim();

@@ -594,40 +489,2 @@ if (!tableName || (table && table !== tableName) || !columnName) {

*/
normalizeId(ids, compositeLength) {
let isComposite = compositeLength > 1;
if (isComposite) {
// For composite ids these two are okay:
//
// 1. [1, 3, 4]
// 2. [[1, 3, 4], [4, 6, 1]]
//
if (!_.isArray(ids) || (!_.isArray(ids[0]) && ids.length !== compositeLength)) {
this.throwError(`Invalid composite key ${ids}`);
}
// Normalize to array of arrays.
if (!_.isArray(ids[0])) {
ids = [ids];
}
} else {
// Normalize to array of arrays.
if (!_.isArray(ids)) {
ids = [[ids]];
} else if (!_.isArray(ids[0])) {
ids = _.map(ids, id => [id]);
}
}
_.each(ids, id => {
if (id.length !== compositeLength) {
this.throwError(`Id ${id} has invalid length. Expected ${compositeLength}`)
}
});
return ids;
}
/**
* @protected
*/
throwError(message) {

@@ -634,0 +491,0 @@ if (this.ownerModelClass && this.ownerModelClass.name && this.name) {

@@ -7,76 +7,2 @@ import _ from 'lodash';

/**
* Starts a transaction.
*
* Give the the model classes you want to use in the transaction as arguments to this
* function. The model classes are bound to a newly created transaction and passed to
* the callback. All queries created using the bound model classes or any result acquired
* through them take part in the same transaction.
*
* You must return a promise from the callback. If this promise is fulfilled the transaction
* is committed. If the promise is rejected the transaction is rolled back.
*
* Examples:
*
* ```js
* objection.transaction(Person, Animal, function (Person, Animal) {
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function () {
* return Animal.query().insert({name: 'Scrappy'});
* });
*
* }).then(function (scrappy) {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* Related model classes are automatically bound to the same transaction. So if you use
* `Animal` implicitly through `Person`'s relations you don't have to bind Animal explicitly.
* The following example clarifies this:
*
* ```js
* objection.transaction(Person, function (Person) {
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function (jennifer) {
* // This insert takes part in the transaction even though we didn't explicitly
* // bind the `Animal` model class.
* return jennifer.$relatedQuery('pets').insert({name: 'Scrappy'});
* });
*
* }).then(function (scrappy) {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* Inside the callback `this` is the knex transaction object. So if you need to create
* knex queries you can do this:
*
* ```js
* objection.transaction(Person, function (Person) {
* let knex = this;
*
* return Person
* .query()
* .insert({firstName: 'Jennifer', lastName: 'Lawrence'})
* .then(function (jennifer) {
* return knex.insert({name: 'Scrappy'}}.into('Animal');
* });
*
* }).then(function () {
* console.log('Jennifer and Scrappy were successfully inserted');
* }).catch(function (err) {
* console.log('Something went wrong. Neither Jennifer nor Scrappy were inserted');
* });
* ```
*
* @function transaction
* @returns {Promise}

@@ -125,37 +51,3 @@ */

/**
* Starts a transaction.
*
* The returned promise is resolved with a knex transaction object that can be used as
* a query builder. You can bind `Model` classes to the transaction using the `Model.bindTransaction`
* method. The transaction object has `commit` and `rollback` methods for committing and
* rolling back the transaction.
*
* ```js
* let Person = require('./models/Person');
* let transaction;
*
* objection.transaction.start(Person).then(function (trx) {
* transaction = trx;
* return Person
* .bindTransaction(transaction)
* .query()
* .insert({firstName: 'Jennifer'});
* }).then(function (jennifer) {
* return Person
* .bindTransaction(transaction)
* .query()
* .patch({lastName: 'Lawrence'})
* .where('id', jennifer.id);
* }).then(function () {
* return transaction.commit();
* }).catch(function () {
* return transaction.rollback();
* });
* ```
*
* @param {Class.<Model>|knex} modelClassOrKnex
* A knex instance or any model that has a knex connection set. Note that you can bind any model
* to the created transaction regardless of the model given to this method. This argument is used
* only to get a knex connection for starting the transaction.
*
* @param {Constructor.<Model>|knex} modelClassOrKnex
* @returns {Promise}

@@ -162,0 +54,0 @@ */

@@ -11,3 +11,2 @@ import _ from 'lodash';

*
* @ignore
* @param {Object} subClass

@@ -40,3 +39,2 @@ * @param {Object} superClass

*
* @ignore
* @param {Object} Constructor

@@ -43,0 +41,0 @@ * @param {Object} SuperConstructor

import _ from 'lodash';
/**
* @ignore
*/
const OVERWRITE_FOR_DATABASE_KEY = `@overwriteForDatabase`;
export function getDialect(knex) {

@@ -10,5 +9,2 @@ return knex.client.dialect;

/**
* @ignore
*/
export function isPostgres(knex) {

@@ -18,5 +14,2 @@ return getDialect(knex) === 'postgresql';

/**
* @ignore
*/
export function isMySql(knex) {

@@ -26,5 +19,2 @@ return getDialect(knex) === 'mysql';

/**
* @ignore
*/
export function isSqlite(knex) {

@@ -34,5 +24,2 @@ return getDialect(knex) === 'sqlite3';

/**
* @ignore
*/
export function isKnexQueryBuilder(knexQueryBuilder) {

@@ -44,12 +31,18 @@ return knexQueryBuilder

/**
* @ignore
*/
export function overwriteForDatabase(input) {
if (!input) {
input = (inst) => inst.knex();
}
// If there is no input or if the input is a function, we assume that the
// decorator was applied to a class instead of a method.
let isClassDecorator = _.isUndefined(input) || _.isFunction(input);
if (_.isFunction(input)) {
return overwriteForDatabaseClass(input);
if (isClassDecorator) {
// In case of class decorator, the input should be a function that returns
// a knex instance that the method version can use.
let getKnex = input;
if (_.isUndefined(getKnex)) {
// The default getter attempts to call a function called `knex`.
getKnex = (inst) => inst.knex();
}
return overwriteForDatabaseClass(getKnex);
} else {

@@ -60,14 +53,10 @@ return overwriteForDatabaseMethod(input);

/**
* @ignore
*/
function overwriteForDatabaseClass(input) {
function overwriteForDatabaseClass(getKnex) {
return function (constructor) {
const getKnex = input;
if (constructor['@overwriteForDatabase']) {
if (constructor[OVERWRITE_FOR_DATABASE_KEY]) {
// Knex getter is already registered. Do nothing.
return;
}
Object.defineProperty(constructor, '@overwriteForDatabase', {
Object.defineProperty(constructor, OVERWRITE_FOR_DATABASE_KEY, {
enumerable: false,

@@ -80,5 +69,2 @@ writable: false,

/**
* @ignore
*/
function overwriteForDatabaseMethod(input) {

@@ -90,5 +76,6 @@ return function (target, property, descriptor) {

descriptor.value = function () {
let knex = this.constructor['@overwriteForDatabase'].getKnex(this);
let knex = this.constructor[OVERWRITE_FOR_DATABASE_KEY].getKnex(this);
let dialect = getDialect(knex);
// Call the correct method based on the dialect.
if (dialect in methodNameByDialect) {

@@ -95,0 +82,0 @@ let methodName = methodNameByDialect[dialect];

@@ -7,6 +7,3 @@ import util from 'util';

/**
* Error of this class is thrown when a Model validation fails.
*
* @param {Object} errors
* @constructor
*/

@@ -18,4 +15,2 @@ export default function ValidationError(errors) {

/**
* Any data that describes the errors.
*
* @type {Object}

@@ -22,0 +17,0 @@ */

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc