knex
Version:
A batteries-included SQL query & schema builder for Postgres, MySQL and SQLite3 and the Browser
395 lines (306 loc) • 11.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _bluebird = _interopRequireDefault(require("bluebird"));
var _raw = _interopRequireDefault(require("./raw"));
var _ref = _interopRequireDefault(require("./ref"));
var _runner = _interopRequireDefault(require("./runner"));
var _formatter = _interopRequireDefault(require("./formatter"));
var _transaction = _interopRequireDefault(require("./transaction"));
var _builder = _interopRequireDefault(require("./query/builder"));
var _compiler = _interopRequireDefault(require("./query/compiler"));
var _builder2 = _interopRequireDefault(require("./schema/builder"));
var _compiler2 = _interopRequireDefault(require("./schema/compiler"));
var _tablebuilder = _interopRequireDefault(require("./schema/tablebuilder"));
var _tablecompiler = _interopRequireDefault(require("./schema/tablecompiler"));
var _columnbuilder = _interopRequireDefault(require("./schema/columnbuilder"));
var _columncompiler = _interopRequireDefault(require("./schema/columncompiler"));
var _tarn = require("tarn");
var _inherits = _interopRequireDefault(require("inherits"));
var _events = require("events");
var _string = require("./query/string");
var _lodash = require("lodash");
var _logger = _interopRequireDefault(require("./logger"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = require('debug')('knex:client');
const debugQuery = require('debug')('knex:query');
const debugBindings = require('debug')('knex:bindings');
const _require = require('./constants'),
POOL_CONFIG_OPTIONS = _require.POOL_CONFIG_OPTIONS; // The base client provides the general structure
// for a dialect specific client object.
function Client(config = {}) {
this.config = config;
this.logger = new _logger.default(config); //Client is a required field, so throw error if it's not supplied.
//If 'this.dialect' is set, then this is a 'super()' call, in which case
//'client' does not have to be set as it's already assigned on the client prototype.
if (this.dialect && !this.config.client) {
this.logger.warn(`Using 'this.dialect' to identify the client is deprecated and support for it will be removed in the future. Please use configuration option 'client' instead.`);
}
const dbClient = this.config.client || this.dialect;
if (!dbClient) {
throw new Error(`knex: Required configuration option 'client' is missing.`);
}
if (config.version) {
this.version = config.version;
}
this.connectionSettings = (0, _lodash.cloneDeep)(config.connection || {});
if (this.driverName && config.connection) {
this.initializeDriver();
if (!config.pool || config.pool && config.pool.max !== 0) {
this.initializePool(config);
}
}
this.valueForUndefined = this.raw('DEFAULT');
if (config.useNullAsDefault) {
this.valueForUndefined = null;
}
}
(0, _inherits.default)(Client, _events.EventEmitter);
(0, _lodash.assign)(Client.prototype, {
formatter(builder) {
return new _formatter.default(this, builder);
},
queryBuilder() {
return new _builder.default(this);
},
queryCompiler(builder) {
return new _compiler.default(this, builder);
},
schemaBuilder() {
return new _builder2.default(this);
},
schemaCompiler(builder) {
return new _compiler2.default(this, builder);
},
tableBuilder(type, tableName, fn) {
return new _tablebuilder.default(this, type, tableName, fn);
},
tableCompiler(tableBuilder) {
return new _tablecompiler.default(this, tableBuilder);
},
columnBuilder(tableBuilder, type, args) {
return new _columnbuilder.default(this, tableBuilder, type, args);
},
columnCompiler(tableBuilder, columnBuilder) {
return new _columncompiler.default(this, tableBuilder, columnBuilder);
},
runner(builder) {
return new _runner.default(this, builder);
},
transaction(container, config, outerTx) {
return new _transaction.default(this, container, config, outerTx);
},
raw() {
return new _raw.default(this).set(...arguments);
},
ref() {
return new _ref.default(this, ...arguments);
},
_formatQuery(sql, bindings, timeZone) {
bindings = bindings == null ? [] : [].concat(bindings);
let index = 0;
return sql.replace(/\\?\?/g, match => {
if (match === '\\?') {
return '?';
}
if (index === bindings.length) {
return match;
}
const value = bindings[index++];
return this._escapeBinding(value, {
timeZone
});
});
},
_escapeBinding: (0, _string.makeEscape)({
escapeString(str) {
return `'${str.replace(/'/g, "''")}'`;
}
}),
query(connection, obj) {
if (typeof obj === 'string') obj = {
sql: obj
};
obj.bindings = this.prepBindings(obj.bindings);
const __knexUid = connection.__knexUid,
__knexTxId = connection.__knexTxId;
this.emit('query', (0, _lodash.assign)({
__knexUid,
__knexTxId
}, obj));
debugQuery(obj.sql, __knexTxId);
debugBindings(obj.bindings, __knexTxId);
obj.sql = this.positionBindings(obj.sql);
return this._query(connection, obj).catch(err => {
err.message = this._formatQuery(obj.sql, obj.bindings) + ' - ' + err.message;
this.emit('query-error', err, (0, _lodash.assign)({
__knexUid,
__knexTxId
}, obj));
throw err;
});
},
stream(connection, obj, stream, options) {
if (typeof obj === 'string') obj = {
sql: obj
};
obj.bindings = this.prepBindings(obj.bindings);
const __knexUid = connection.__knexUid,
__knexTxId = connection.__knexTxId;
this.emit('query', (0, _lodash.assign)({
__knexUid,
__knexTxId
}, obj));
debugQuery(obj.sql, __knexTxId);
debugBindings(obj.bindings, __knexTxId);
obj.sql = this.positionBindings(obj.sql);
return this._stream(connection, obj, stream, options);
},
prepBindings(bindings) {
return bindings;
},
positionBindings(sql) {
return sql;
},
postProcessResponse(resp, queryContext) {
if (this.config.postProcessResponse) {
return this.config.postProcessResponse(resp, queryContext);
}
return resp;
},
wrapIdentifier(value, queryContext) {
return this.customWrapIdentifier(value, this.wrapIdentifierImpl, queryContext);
},
customWrapIdentifier(value, origImpl, queryContext) {
if (this.config.wrapIdentifier) {
return this.config.wrapIdentifier(value, origImpl, queryContext);
}
return origImpl(value);
},
wrapIdentifierImpl(value) {
return value !== '*' ? `"${value.replace(/"/g, '""')}"` : '*';
},
initializeDriver() {
try {
this.driver = this._driver();
} catch (e) {
const message = `Knex: run\n$ npm install ${this.driverName} --save`;
this.logger.error(`${message}\n${e.message}\n${e.stack}`);
throw new Error(`${message}\n${e.message}`);
}
},
poolDefaults() {
return {
min: 2,
max: 10,
propagateCreateError: true
};
},
getPoolSettings(poolConfig) {
poolConfig = (0, _lodash.defaults)({}, poolConfig, this.poolDefaults());
POOL_CONFIG_OPTIONS.forEach(option => {
if (option in poolConfig) {
this.logger.warn([`Pool config option "${option}" is no longer supported.`, `See https://github.com/Vincit/tarn.js for possible pool config options.`].join(' '));
}
});
const timeouts = [this.config.acquireConnectionTimeout || 60000, poolConfig.acquireTimeoutMillis].filter(timeout => timeout !== undefined); // acquire connection timeout can be set on config or config.pool
// choose the smallest, positive timeout setting and set on poolConfig
poolConfig.acquireTimeoutMillis = Math.min(...timeouts);
return Object.assign(poolConfig, {
create: () => {
return this.acquireRawConnection().tap(connection => {
connection.__knexUid = (0, _lodash.uniqueId)('__knexUid');
if (poolConfig.afterCreate) {
return _bluebird.default.promisify(poolConfig.afterCreate)(connection);
}
});
},
destroy: connection => {
if (poolConfig.beforeDestroy) {
this.logger.warn(`
beforeDestroy is deprecated, please open an issue if you use this
to discuss alternative apis
`);
poolConfig.beforeDestroy(connection, function () {});
}
if (connection !== void 0) {
return this.destroyRawConnection(connection);
}
},
validate: connection => {
if (connection.__knex__disposed) {
this.logger.warn(`Connection Error: ${connection.__knex__disposed}`);
return false;
}
return this.validateConnection(connection);
}
});
},
initializePool(config = this.config) {
if (this.pool) {
this.logger.warn('The pool has already been initialized');
return;
}
this.pool = new _tarn.Pool(this.getPoolSettings(config.pool));
},
validateConnection(connection) {
return true;
},
// Acquire a connection from the pool.
acquireConnection() {
if (!this.pool) {
return _bluebird.default.reject(new Error('Unable to acquire a connection'));
}
return _bluebird.default.try(() => this.pool.acquire().promise).tap(connection => {
debug('acquired connection from pool: %s', connection.__knexUid);
}).catch(_tarn.TimeoutError, () => {
throw new _bluebird.default.TimeoutError('Knex: Timeout acquiring a connection. The pool is probably full. ' + 'Are you missing a .transacting(trx) call?');
});
},
// Releases a connection back to the connection pool,
// returning a promise resolved when the connection is released.
releaseConnection(connection) {
debug('releasing connection to pool: %s', connection.__knexUid);
const didRelease = this.pool.release(connection);
if (!didRelease) {
debug('pool refused connection: %s', connection.__knexUid);
}
return _bluebird.default.resolve();
},
// Destroy the current connection pool for the client.
destroy(callback) {
const maybeDestroy = this.pool && this.pool.destroy();
return _bluebird.default.resolve(maybeDestroy).then(() => {
this.pool = void 0;
if (typeof callback === 'function') {
callback();
}
}).catch(err => {
if (typeof callback === 'function') {
callback(err);
}
return _bluebird.default.reject(err);
});
},
// Return the database being used by this client.
database() {
return this.connectionSettings.database;
},
toString() {
return '[object KnexClient]';
},
canCancelQuery: false,
assertCanCancelQuery() {
if (!this.canCancelQuery) {
throw new Error('Query cancelling not supported for this dialect');
}
},
cancelQuery() {
throw new Error('Query cancelling not supported for this dialect');
}
});
var _default = Client;
exports.default = _default;
module.exports = exports.default;