UNPKG

3.71 kBJavaScriptView Raw
1var async = require('./lib/async')
2var query = require('./lib/query')
3var Table = require('./lib/table')
4var hide = require('./lib/hideProperty')
5var promiseResolver = require('./lib/promiseResolver')
6var extend = require('./lib/extend')
7
8var supportedDrivers = [
9 'pg',
10 'mysql'
11]
12
13var oreo = module.exports = function oreo(opts, cb) {
14 if (!(this instanceof oreo)) {
15 return new oreo(opts, cb)
16 }
17
18 var self = this
19
20 // use _ prefix to avoid conflict with table names
21 hide(self, '_driver')
22 hide(self, '_platform')
23 hide(self, '_query')
24 hide(self, '_tables')
25 hide(self, '_opts')
26 hide(self, '_Promise')
27 hide(self, '_promiseResolver')
28 hide(self, '_onReady')
29 hide(self, '_isReady')
30 hide(self, '_memo')
31
32 self._isReady = false
33 self._tables = []
34 self._opts = extend({}, opts)
35 self._Promise = opts.Promise
36 self._promiseResolver = promiseResolver
37 self._memo = {} // memoized query results
38
39 cb = cb || function () {}
40
41 if (supportedDrivers.indexOf(opts.driver) === -1) {
42 return cb(new Error('"' + opts.driver + '" is not a supported driver.'))
43 }
44
45 self._driver = require(opts.driver)
46
47 // bind the platform-specific methods to this
48 self._platform = require('./lib/platforms/' + opts.driver)
49 self._platform.db = self
50
51 if (opts.debug && typeof opts.debug !== 'function') {
52 self._opts.debug = console.log
53 }
54
55 if (typeof opts.memoize !== 'number') {
56 self._opts.memoize = false
57 }
58
59 self._query = query(self, self._opts, function(err) {
60 if (err) {
61 return cb(err)
62 }
63 self._opts.pass = '***************' // obfuscate the password
64 self.execute = self._query.execute.bind(self._query)
65 self.executeWrite = self._query.executeWrite.bind(self._query)
66 self.discover(cb)
67 })
68
69 // purge memoized values periodically
70 var memoMs = self._opts.memoize
71 if (memoMs) {
72 var intervalMs = self._opts.memoizePurgeInterval || 10000
73 setInterval(function purgeMemo () {
74 Object.keys(self._memo).forEach(function (key) {
75 if (Date.now() - self._memo[key].timestamp > memoMs) {
76 delete self._memo[key]
77 }
78 })
79 }, intervalMs)
80 }
81
82 return this
83}
84
85/**
86 * [discover description]
87 */
88oreo.prototype.discover = function(cb) {
89 var sql
90 var self = this
91 self._tables = []
92
93 cb = cb || self._promiseResolver()
94
95 // get the tables
96 self._platform.getTables(function(err, tables) {
97 if (err) return cb(err)
98
99 // for each table
100 async.each(tables, function(table_name, callback) {
101 self._tables.push(table_name)
102 // create a table object
103 self[table_name] = new Table(table_name, self, callback)
104
105 }, function(err) {
106 if (err) return cb(err)
107
108 // determine the 1-to-m relationships for each table
109 self._tables.forEach(function(table) {
110 if (self[table].fk) {
111 Object.keys(self[table].fk).forEach(function(fkName) {
112 var fk = self[table].fk[fkName]
113 if (self[fk.foreignTable] && self[fk.foreignTable].many) {
114 var link = fk.constraintName + '_' + fk.table
115 self[fk.foreignTable].many[link] = fk
116 }
117 })
118 }
119 })
120
121 self._onReady = self._onReady || []
122 self._onReady.forEach(function (fn) {
123 fn()
124 })
125 self._isReady = true
126
127 cb(null, self)
128 })
129 })
130
131 return cb.promise ? cb.promise : this
132}
133
134/**
135 * Adds a function to the stack to be executed when the database is ready
136 */
137oreo.prototype.onReady = function(fn) {
138 if (this._isReady) {
139 return fn()
140 }
141 this._onReady = this._onReady || []
142 this._onReady.push(fn)
143 return this
144}
145
146/**
147 *
148 */
149oreo.prototype.end = function(cb) {
150 cb = cb || function () {}
151 this._platform.end(cb)
152}