knex/lib/interface.js

101 lines
2.9 KiB
JavaScript
Raw Normal View History

const clone = require('lodash/clone');
const isEmpty = require('lodash/isEmpty');
const { callbackify } = require('util');
const finallyMixin = require('./util/finally-mixin');
2016-03-02 17:07:05 +01:00
2020-04-19 00:40:23 +02:00
module.exports = function (Target) {
Target.prototype.toQuery = function (tz) {
let data = this.toSQL(this._method, tz);
if (!Array.isArray(data)) data = [data];
return data
.map((statement) => {
return this.client._formatQuery(statement.sql, statement.bindings, tz);
})
.join(';\n');
2016-03-02 17:07:05 +01:00
};
// Create a new instance of the `Runner`, passing in the current object.
2020-04-19 00:40:23 +02:00
Target.prototype.then = function (/* onFulfilled, onRejected */) {
let result = this.client.runner(this).run();
2018-04-25 23:11:24 +02:00
if (this.client.config.asyncStackTraces) {
result = result.catch((err) => {
err.originalStack = err.stack;
const firstLine = err.stack.split('\n')[0];
this._asyncStack.unshift(firstLine);
2018-04-25 23:11:24 +02:00
// put the fake more helpful "async" stack on the thrown error
err.stack = this._asyncStack.join('\n');
throw err;
});
2018-04-25 23:11:24 +02:00
}
return result.then.apply(result, arguments);
2016-03-02 17:07:05 +01:00
};
// Add additional "options" to the builder. Typically used for client specific
// items, like the `mysql` and `sqlite3` drivers.
2020-04-19 00:40:23 +02:00
Target.prototype.options = function (opts) {
2016-03-02 17:07:05 +01:00
this._options = this._options || [];
this._options.push(clone(opts) || {});
return this;
};
// Sets an explicit "connection" we wish to use for this query.
2020-04-19 00:40:23 +02:00
Target.prototype.connection = function (connection) {
2016-03-02 17:07:05 +01:00
this._connection = connection;
return this;
};
// Set a debug flag for the current schema query stack.
2020-04-19 00:40:23 +02:00
Target.prototype.debug = function (enabled) {
2016-03-02 17:07:05 +01:00
this._debug = arguments.length ? enabled : true;
return this;
};
// Set the transaction object for this query.
2020-04-19 00:40:23 +02:00
Target.prototype.transacting = function (t) {
2016-03-02 17:07:05 +01:00
if (t && t.client) {
if (!t.client.transacting) {
t.client.logger.warn(`Invalid transaction value: ${t.client}`);
2016-03-02 17:07:05 +01:00
} else {
this.client = t.client;
2016-03-02 17:07:05 +01:00
}
}
if (isEmpty(t)) {
this.client.logger.error(
'Invalid value on transacting call, potential bug'
);
throw Error(
'Invalid transacting value (null, undefined or empty object)'
);
}
2016-03-02 17:07:05 +01:00
return this;
};
// Initializes a stream.
2020-04-19 00:40:23 +02:00
Target.prototype.stream = function (options) {
2016-03-02 17:07:05 +01:00
return this.client.runner(this).stream(options);
};
// Initialize a stream & pipe automatically.
2020-04-19 00:40:23 +02:00
Target.prototype.pipe = function (writable, options) {
return this.client.runner(this).pipe(writable, options);
2016-03-02 17:07:05 +01:00
};
2020-04-19 00:40:23 +02:00
Target.prototype.asCallback = function (cb) {
const promise = this.then();
callbackify(() => promise)(cb);
return promise;
};
2020-04-19 00:40:23 +02:00
Target.prototype.catch = function (onReject) {
return this.then().catch(onReject);
};
Object.defineProperty(Target.prototype, Symbol.toStringTag, {
get: () => 'object',
});
finallyMixin(Target.prototype);
};