global-connection.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. 'use strict'
  2. const shared = require('./shared')
  3. let globalConnection = null
  4. const globalConnectionHandlers = {}
  5. /**
  6. * Open global connection pool.
  7. *
  8. * @param {Object|String} config Connection configuration object or connection string.
  9. * @param {basicCallback} [callback] A callback which is called after connection has established, or an error has occurred. If omited, method returns Promise.
  10. * @return {Promise.<ConnectionPool>}
  11. */
  12. function connect (config, callback) {
  13. if (globalConnection) {
  14. if (typeof callback === 'function') {
  15. setImmediate(callback, null, globalConnection)
  16. } else {
  17. return shared.Promise.resolve(globalConnection)
  18. }
  19. } else {
  20. globalConnection = new shared.driver.ConnectionPool(config)
  21. for (const event in globalConnectionHandlers) {
  22. for (let i = 0, l = globalConnectionHandlers[event].length; i < l; i++) {
  23. globalConnection.on(event, globalConnectionHandlers[event][i])
  24. }
  25. }
  26. const ogClose = globalConnection.close
  27. const globalClose = function (callback) {
  28. // remove event handlers from the global connection
  29. for (const event in globalConnectionHandlers) {
  30. for (let i = 0, l = globalConnectionHandlers[event].length; i < l; i++) {
  31. this.removeListener(event, globalConnectionHandlers[event][i])
  32. }
  33. }
  34. // attach error handler to prevent process crash in case of error
  35. this.on('error', err => {
  36. if (globalConnectionHandlers.error) {
  37. for (let i = 0, l = globalConnectionHandlers.error.length; i < l; i++) {
  38. globalConnectionHandlers.error[i].call(this, err)
  39. }
  40. }
  41. })
  42. globalConnection = null
  43. return ogClose.call(this, callback)
  44. }
  45. globalConnection.close = globalClose.bind(globalConnection)
  46. return globalConnection.connect(callback)
  47. }
  48. }
  49. /**
  50. * Close all active connections in the global pool.
  51. *
  52. * @param {basicCallback} [callback] A callback which is called after connection has closed, or an error has occurred. If omited, method returns Promise.
  53. * @return {ConnectionPool|Promise}
  54. */
  55. function close (callback) {
  56. if (globalConnection) {
  57. const gc = globalConnection
  58. globalConnection = null
  59. return gc.close(callback)
  60. }
  61. if (typeof callback === 'function') {
  62. setImmediate(callback)
  63. return null
  64. }
  65. return new shared.Promise((resolve) => {
  66. resolve(globalConnection)
  67. })
  68. }
  69. /**
  70. * Attach event handler to global connection pool.
  71. *
  72. * @param {String} event Event name.
  73. * @param {Function} handler Event handler.
  74. * @return {ConnectionPool}
  75. */
  76. function on (event, handler) {
  77. if (!globalConnectionHandlers[event]) globalConnectionHandlers[event] = []
  78. globalConnectionHandlers[event].push(handler)
  79. if (globalConnection) globalConnection.on(event, handler)
  80. return globalConnection
  81. }
  82. /**
  83. * Detach event handler from global connection.
  84. *
  85. * @param {String} event Event name.
  86. * @param {Function} handler Event handler.
  87. * @return {ConnectionPool}
  88. */
  89. function removeListener (event, handler) {
  90. if (!globalConnectionHandlers[event]) return globalConnection
  91. const index = globalConnectionHandlers[event].indexOf(handler)
  92. if (index === -1) return globalConnection
  93. globalConnectionHandlers[event].splice(index, 1)
  94. if (globalConnectionHandlers[event].length === 0) globalConnectionHandlers[event] = undefined
  95. if (globalConnection) globalConnection.removeListener(event, handler)
  96. return globalConnection
  97. }
  98. /**
  99. * Creates a new query using global connection from a tagged template string.
  100. *
  101. * @variation 1
  102. * @param {Array|String} strings Array of string literals or sql command.
  103. * @param {...*} keys Values.
  104. * @return {Request}
  105. */
  106. /**
  107. * Execute the SQL command.
  108. *
  109. * @variation 2
  110. * @param {String} command T-SQL command to be executed.
  111. * @param {Request~requestCallback} [callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
  112. * @return {Request|Promise}
  113. */
  114. function query () {
  115. if (typeof arguments[0] === 'string') { return new shared.driver.Request().query(arguments[0], arguments[1]) }
  116. const values = Array.prototype.slice.call(arguments)
  117. const strings = values.shift()
  118. return new shared.driver.Request()._template(strings, values, 'query')
  119. }
  120. /**
  121. * Creates a new batch using global connection from a tagged template string.
  122. *
  123. * @variation 1
  124. * @param {Array} strings Array of string literals.
  125. * @param {...*} keys Values.
  126. * @return {Request}
  127. */
  128. /**
  129. * Execute the SQL command.
  130. *
  131. * @variation 2
  132. * @param {String} command T-SQL command to be executed.
  133. * @param {Request~requestCallback} [callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
  134. * @return {Request|Promise}
  135. */
  136. function batch () {
  137. if (typeof arguments[0] === 'string') { return new shared.driver.Request().batch(arguments[0], arguments[1]) }
  138. const values = Array.prototype.slice.call(arguments)
  139. const strings = values.shift()
  140. return new shared.driver.Request()._template(strings, values, 'batch')
  141. }
  142. module.exports = {
  143. batch,
  144. close,
  145. connect,
  146. off: removeListener,
  147. on,
  148. query,
  149. removeListener
  150. }
  151. Object.defineProperty(module.exports, 'pool', {
  152. get: () => {
  153. return globalConnection
  154. },
  155. set: () => {}
  156. })