UNPKG

@fxjs/db-driver

Version:

[![NPM version](https://img.shields.io/npm/v/@fxjs/db-driver.svg)](https://www.npmjs.org/package/@fxjs/db-driver) [![Build Status](https://travis-ci.org/fxjs-modules/db-driver.svg)](https://travis-ci.org/fxjs-modules/db-driver) [![Build status](https://

215 lines (214 loc) 7.16 kB
/// <reference types="fib-pool" /> Object.defineProperty(exports, "__esModule", { value: true }); exports.SQLDriver = exports.Driver = void 0; const url = require("url"); const assert = require("assert"); const coroutine = require("coroutine"); const Utils = require("../utils"); function setReactivePool(driver) { let pool = false; Object.defineProperty(driver.extend_config, 'pool', { set(nextVal) { if (typeof nextVal === 'string') nextVal = Utils.castQueryStringToBoolean(nextVal); if (nextVal) { pool = Utils.parsePoolConfig(nextVal); pool.maxsize = Utils.forceInteger(pool.maxsize, 100); pool.timeout = Utils.forceInteger(pool.timeout, 1000); Utils.mountPoolToDriver(driver, pool); } else { pool = false; } }, get() { return pool; } }); } // function getDriver (name: 'mongodb'): typeof import('./driver-mongodb').default function getDriver(name) { switch (name) { case 'mysql': return require('./driver-mysql').default; case 'postgresql': case 'postgres': case 'pg': case 'psql': return require('./driver-postgresql').default; case 'sqlite': return require('./driver-sqlite').default; case 'redis': return require('./driver-redis').default; // case 'mongodb': // return require('./driver-mongodb').default default: if (name) { const type = Utils.filterDriverType(url.parse(name).protocol); if (type !== 'unknown') return getDriver(type); } // throw new Error(`[feature] driver type ${name} is not supported`) return Driver; } } class Driver { constructor(options) { this.extend_config = { pool: false, debug: false }; // options would be replaced, `Utils.parseConnectionString` return a fresh object options = Utils.parseConnectionString(options); Object.defineProperty(this, 'config', { get() { return options; } }); assert.ok(!!this.config.protocol, '[driver.config] invalid protocol'); // some db has no host switch (options.protocol) { default: break; case 'mysql:': case 'mssql:': case 'postgresql:': assert.ok(!!this.config.host || !!this.config.hostname, '[driver.config] host or hostname required'); break; } this.type = Utils.filterDriverType(this.config.protocol); const extend_config = {}; Object.defineProperty(this, 'extend_config', { get() { return extend_config; } }); setReactivePool(this); extend_config.pool = options.query.pool; extend_config.debug = Utils.castQueryStringToBoolean(options.query.debug); Object.defineProperty(this, 'uid', { value: Utils.driverUUid(), writable: false, configurable: false }); } static create(input) { const driver = Driver.getDriver(typeof input === 'object' ? input.protocol : input); return new driver(input); } /** * @descritpin there's a bug in fibjs <= 0.35.x, only string type `field` would be * used by `url.format` */ static formatUrl(input) { let protocol = input.protocol; // some user would like add // after valid protocol like `http:`, `mysql:` if (protocol === null || protocol === void 0 ? void 0 : protocol.endsWith('//')) protocol = protocol.slice(0, -2); return url.format(Object.assign(Object.assign(Object.assign({}, input), { protocol }), !!input.port && { port: input.port + '' })); } get uri() { const isSQLite = this.config.protocol === 'sqlite:'; return Driver.formatUrl(Object.assign(Object.assign(Object.assign({}, this.config), this.type === 'psql' && { protocol: 'psql:' }), { slashes: isSQLite ? false : this.config.slashes, query: isSQLite ? {} : this.config.query })); } get isPool() { return !!this.extend_config.pool; } get isSql() { const p = this.config.protocol || ''; return ((p === 'mysql:') || (p === 'mssql:') || (p === 'psql:') || (p.startsWith('sqlite:'))); } get isNoSql() { const p = this.config.protocol || ''; return ((p === 'mongodb:')); } get isCommand() { const p = this.config.protocol || ''; return ((p === 'mongodb:') || (p === 'redis:')); } /** * @description switch to another database, pointless for some databases such as sqlite * @param targetDb */ switchDb(targetDb) { this.currentDb = targetDb; } ; /** * @description re open db connection */ reopen() { try { this.close(); } catch (error) { } return this.open(); } /** * @description open db connection */ open() { return this.connection = this.getConnection(); } /** * @description close db connection */ close() { } /** * @description some db connection has `ping` method */ ping() { } /** * @description get connection instance but don't change internal status */ getConnection() { return null; } connectionPool(callback) { if (this.isPool) return this.pool((conn) => callback(conn)); return callback(this.getConnection()); } useTrans(callback) { return this.connectionPool((conn) => { if (typeof conn.trans === 'function') { const waitor = { ev: new (coroutine.Event)(), result: undefined }; conn.trans(() => { waitor.result = callback(conn); waitor.ev.set(); }); waitor.ev.wait(); return waitor.result; } else { return callback(conn); } }); } } exports.Driver = Driver; Driver.getDriver = getDriver; class SQLDriver extends Driver { constructor(opts) { super(opts); this.currentDb = null; const options = Utils.parseConnectionString(opts); this.extend_config.debug_sql = Utils.castQueryStringToBoolean(options.query.debug_sql); } /** * @override */ dbExists(dbname) { return false; } ; /** * @override */ begin() { } /** * @override */ commit() { } /** * @override */ trans(cb) { return true; } /** * @override */ rollback() { } /** * @override */ execute(sql) { return; } } exports.SQLDriver = SQLDriver;