UNPKG

simple-oracledb

Version:

Extend capabilities of oracledb with simplified API for quicker development.

351 lines (328 loc) 11.7 kB
'use strict'; /** * This events is triggered when a pool is created. * * @event SimpleOracleDB#pool-created * @param {Pool} pool - The pool instance */ /** * This events is triggered after a pool is released. * * @event SimpleOracleDB#pool-released * @param {Pool} pool - The pool instance */ /** * This events is triggered when a connection is created via oracledb. * * @event SimpleOracleDB#connection-created * @param {Connection} connection - The connection instance */ /** * This events is triggered when a connection is released successfully. * * @event SimpleOracleDB#connection-released * @param {Connection} connection - The connection instance */ /** * Invoked when an async operation has finished. * * @callback AsyncCallback * @param {Error} [error] - Any possible error * @param {Object} [output] - The operation output */ const util = require('util'); const EventEmitterEnhancer = require('event-emitter-enhancer'); const OracleDB = require('./oracledb'); const Pool = require('./pool'); const Connection = require('./connection'); const extensions = require('./extensions'); const Monitor = require('./monitor'); const funcs = require('funcs-js'); const promiseHelper = require('./promise-helper'); /** * Simple oracledb enables to extend the oracledb main object, oracledb pool and oracledb connection.<br> * See extend function for more info. * * @author Sagie Gur-Ari * @class SimpleOracleDB * @public */ function SimpleOracleDB() { //call super constructor EventEmitterEnhancer.EnhancedEventEmitter.call(this); const monitor = Monitor.create(this); /*eslint-disable func-name-matching*/ Object.defineProperty(this, 'diagnosticInfo', { /** * Getter for the diagnostic info data. * * @function * @memberof! Info * @private * @returns {Object} The diagnostic info data */ get: function getDiagnosticInfo() { /** * The pool/connection diagnostics info.<br> * This includes info of all live pools (including live time and create time) and all live connections (including parent pool if any, live time, create time and last SQL) * * @memberof! SimpleOracleDB * @member {Object} * @alias SimpleOracleDB.diagnosticInfo * @public */ const diagnosticInfo = monitor.diagnosticInfo; return diagnosticInfo; } }); Object.defineProperty(this, 'enableDiagnosticInfo', { /** * Getter for the diagnostic info enabled flag. * * @function * @memberof! Info * @private * @returns {Boolean} The diagnostic info enabled flag */ get: function isEnabled() { /** * True if the monitoring is enabled and it will listen and store pool/connection diagnostics information.<br> * By default this is set to false. * * @memberof! SimpleOracleDB * @member {Boolean} * @alias SimpleOracleDB.enableDiagnosticInfo * @public */ const enableDiagnosticInfo = monitor.enabled; return enableDiagnosticInfo; }, /** * Setter for the diagnostic info enabled flag. * * @function * @memberof! Info * @private * @param {Boolean} value - The diagnostic info enabled flag */ set: function setEnabled(value) { monitor.enabled = value; } }); /*eslint-enable func-name-matching*/ } //setup SimpleOracleDB as an event emitter util.inherits(SimpleOracleDB, EventEmitterEnhancer.EnhancedEventEmitter); /*eslint-disable valid-jsdoc*/ //jscs:disable jsDoc /** * Extends the oracledb library which from that point will allow fetching the modified * connection objects via oracledb.getConnection or via pool.getConnection * * @function * @memberof! SimpleOracleDB * @public * @param {oracledb} oracledb - The oracledb library * @example * ```js * //load the oracledb library * const oracledb = require('oracledb'); * * //load the simple oracledb * const SimpleOracleDB = require('simple-oracledb'); * * //modify the original oracledb library * SimpleOracleDB.extend(oracledb); * ``` * * @also * * Extends the oracledb pool instance which from that point will allow fetching the modified * connection objects via pool.getConnection * * @function * @memberof! SimpleOracleDB * @public * @param {Pool} pool - The oracledb pool instance * @example * ```js * //load the simple oracledb * const SimpleOracleDB = require('simple-oracledb'); * * function myFunction(pool) { * //modify the original oracledb pool instance * SimpleOracleDB.extend(pool); * * //from this point connections fetched via pool.getConnection(...) * //have access to additional functionality. * pool.getConnection(function onConnection(error, connection) { * if (error) { * //handle error * } else { * //work with new capabilities or original oracledb capabilities * connection.query(...); * } * }); * } * ``` * * @also * * Extends the oracledb connection instance which from that point will allow access to all * the extended capabilities of this library. * * @function * @memberof! SimpleOracleDB * @public * @param {Connection} connection - The oracledb connection instance * @example * ```js * //load the simple oracledb * const SimpleOracleDB = require('simple-oracledb'); * * function doSomething(connection, callback) { * //modify the original oracledb connection instance * SimpleOracleDB.extend(connection); * * //from this point the connection has access to additional functionality as well as the original oracledb capabilities. * connection.query(...); * } * ``` */ SimpleOracleDB.prototype.extend = function (oracle) { const self = this; if (oracle) { if (oracle.createPool) { if (!oracle.simplified) { OracleDB.extend(oracle); self.proxyEvents(oracle, [ 'pool-created', 'pool-released', 'connection-created', 'connection-released' ]); } } else if (oracle.getConnection) { Pool.extend(oracle); } else if (oracle.execute) { Connection.extend(oracle); } else { throw new Error('Unsupported object provided.'); } } else { throw new Error('Invalid input provided.'); } }; //jscs:enable jsDoc /*eslint-enable valid-jsdoc*/ /** * Adds an extension to all newly created objects of the requested type.<br> * An extension, is a function which will be added to any pool or connection instance created after the extension was added.<br> * This function enables external libraries to further extend oracledb using a very simple API and without the need to wrap the pool/connection creation functions.<br> * Extension functions automatically get promisified unless specified differently in the optional options. * * @function * @memberof! SimpleOracleDB * @public * @param {String} type - Either 'connection' or 'pool' * @param {String} name - The function name which will be added to the object * @param {function} extension - The function to be added * @param {Object} [options] - Any extension options needed * @param {Object} [options.promise] - Promise options * @param {Boolean} [options.promise.noPromise=false] - If true, do not promisify function * @param {Boolean} [options.promise.force=false] - If true, do not check if promise is supported * @param {Boolean} [options.promise.defaultCallback=false] - If true and no callback provided, generate an empty callback * @param {Number} [options.promise.callbackMinIndex=0] - The minimum index in the arguments that the callback is found in * @returns {Boolean} True if added, false if ignored * @example * ```js * //define a new function for all new connection objects called 'myConnFunc' which accepts 2 arguments * SimpleOracleDB.addExtension('connection', 'myConnFunc', function (myParam1, myParam2, callback) { * //implement some custom functionality... * * callback(); * }); * * //get connection (via oracledb directly or via pool) and start using the new function * connection.myConnFunc('test', 123, function () { * //continue flow... * }); * * //extensions are automatically promisified (can be disabled) so you can also run extension functions without callback * const promise = connection.myConnFunc('test', 123); * promise.then(function () { * //continue flow... * }).catch(function (error) { * //got some error... * }); * * //define a new function for all new pool objects called 'myPoolFunc' * SimpleOracleDB.addExtension('pool', 'myPoolFunc', function () { * //implement some custom functionality * }); * * //get pool and start using the new function * pool.myPoolFunc(); * ``` */ SimpleOracleDB.prototype.addExtension = function (type, name, extension, options) { return extensions.add(type, name, extension, options); }; /** * Internal utility function which returns a callback function which will invoke the requested action on the provided connection. * * @function * @memberof! SimpleOracleDB * @private * @param {function} action - The function to invoke with the provided connection * @param {Object} invocationOptions - See oracledb.run/pool.run * @param {Object} releaseOptions - See oracledb.run/pool.run * @param {function} callback - Invoked with result/error after the action is invoked and the connection is released * @returns {function} The callback function * @example * ```js * const actionRunner = simpleOracleDB.createOnConnectionCallback(function (connection) { * return connection.query('SELECT * FROM PEOPLE'); * }, { * ignoreReleaseErrors: false * }, { * retryCount: 5 * }, callback); * oracledb.getConnection(connectionAttributes, actionRunner); * ``` */ SimpleOracleDB.prototype.createOnConnectionCallback = function (action, invocationOptions, releaseOptions, callback) { return function onConnection(connectionError, connection) { if (connectionError) { callback(connectionError); } else { try { let onActionDone = function (actionAsyncError, result) { connection.release(releaseOptions, function onConnectionRelease(releaseError) { if (actionAsyncError) { callback(actionAsyncError); } else if (releaseError && (!invocationOptions.ignoreReleaseErrors)) { callback(releaseError); } else { callback(null, result); } }); }; onActionDone = funcs.once(onActionDone, { callbackStyle: true }); const promise = action(connection, onActionDone); if (promiseHelper.isPromise(promise)) { promise.then(function onActionResult(result) { onActionDone(null, result); }).catch(onActionDone); } } catch (actionSyncError) { connection.release(releaseOptions, function onConnectionRelease() { callback(actionSyncError); }); } } }; }; module.exports = new SimpleOracleDB();