knex 0.21.20 → 0.21.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/CONTRIBUTING.md +184 -184
  3. package/LICENSE +22 -22
  4. package/README.md +95 -95
  5. package/bin/cli.js +414 -414
  6. package/bin/utils/cli-config-utils.js +151 -151
  7. package/bin/utils/constants.js +7 -7
  8. package/bin/utils/migrationsLister.js +37 -37
  9. package/knex.js +8 -8
  10. package/lib/client.js +413 -413
  11. package/lib/config-resolver.js +61 -61
  12. package/lib/constants.js +44 -44
  13. package/lib/dialects/mssql/index.js +390 -390
  14. package/lib/dialects/mssql/query/compiler.js +444 -444
  15. package/lib/dialects/mssql/schema/columncompiler.js +103 -103
  16. package/lib/dialects/mssql/schema/compiler.js +59 -59
  17. package/lib/dialects/mssql/schema/tablecompiler.js +245 -245
  18. package/lib/dialects/mssql/transaction.js +97 -97
  19. package/lib/dialects/mysql/index.js +191 -191
  20. package/lib/dialects/mysql/query/compiler.js +142 -142
  21. package/lib/dialects/mysql/schema/columncompiler.js +171 -171
  22. package/lib/dialects/mysql/schema/compiler.js +60 -60
  23. package/lib/dialects/mysql/schema/tablecompiler.js +262 -262
  24. package/lib/dialects/mysql/transaction.js +48 -48
  25. package/lib/dialects/mysql2/index.js +35 -35
  26. package/lib/dialects/mysql2/transaction.js +46 -46
  27. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  28. package/lib/dialects/oracle/formatter.js +20 -20
  29. package/lib/dialects/oracle/index.js +79 -79
  30. package/lib/dialects/oracle/query/compiler.js +327 -327
  31. package/lib/dialects/oracle/schema/columnbuilder.js +18 -18
  32. package/lib/dialects/oracle/schema/columncompiler.js +139 -139
  33. package/lib/dialects/oracle/schema/compiler.js +81 -81
  34. package/lib/dialects/oracle/schema/tablecompiler.js +165 -165
  35. package/lib/dialects/oracle/schema/trigger.js +126 -126
  36. package/lib/dialects/oracle/utils.js +86 -86
  37. package/lib/dialects/oracledb/index.js +489 -489
  38. package/lib/dialects/oracledb/query/compiler.js +363 -363
  39. package/lib/dialects/oracledb/schema/columncompiler.js +35 -35
  40. package/lib/dialects/oracledb/transaction.js +76 -76
  41. package/lib/dialects/oracledb/utils.js +14 -14
  42. package/lib/dialects/postgres/index.js +319 -319
  43. package/lib/dialects/postgres/query/compiler.js +206 -206
  44. package/lib/dialects/postgres/schema/columncompiler.js +125 -125
  45. package/lib/dialects/postgres/schema/compiler.js +109 -109
  46. package/lib/dialects/postgres/schema/tablecompiler.js +183 -183
  47. package/lib/dialects/redshift/index.js +73 -73
  48. package/lib/dialects/redshift/query/compiler.js +119 -119
  49. package/lib/dialects/redshift/schema/columnbuilder.js +20 -20
  50. package/lib/dialects/redshift/schema/columncompiler.js +60 -60
  51. package/lib/dialects/redshift/schema/compiler.js +14 -14
  52. package/lib/dialects/redshift/schema/tablecompiler.js +123 -123
  53. package/lib/dialects/redshift/transaction.js +18 -18
  54. package/lib/dialects/sqlite3/formatter.js +21 -21
  55. package/lib/dialects/sqlite3/index.js +169 -169
  56. package/lib/dialects/sqlite3/query/compiler.js +222 -222
  57. package/lib/dialects/sqlite3/schema/columncompiler.js +27 -27
  58. package/lib/dialects/sqlite3/schema/compiler.js +49 -49
  59. package/lib/dialects/sqlite3/schema/ddl.js +525 -525
  60. package/lib/dialects/sqlite3/schema/tablecompiler.js +238 -238
  61. package/lib/formatter.js +295 -295
  62. package/lib/functionhelper.js +14 -14
  63. package/lib/helpers.js +92 -92
  64. package/lib/index.js +3 -3
  65. package/lib/interface.js +115 -115
  66. package/lib/knex.js +42 -42
  67. package/lib/logger.js +76 -76
  68. package/lib/migrate/MigrationGenerator.js +82 -82
  69. package/lib/migrate/Migrator.js +611 -611
  70. package/lib/migrate/configuration-merger.js +60 -60
  71. package/lib/migrate/migrate-stub.js +17 -17
  72. package/lib/migrate/migration-list-resolver.js +36 -36
  73. package/lib/migrate/sources/fs-migrations.js +99 -99
  74. package/lib/migrate/stub/cjs.stub +15 -15
  75. package/lib/migrate/stub/coffee.stub +13 -13
  76. package/lib/migrate/stub/eg.stub +14 -14
  77. package/lib/migrate/stub/js.stub +15 -15
  78. package/lib/migrate/stub/knexfile-coffee.stub +34 -34
  79. package/lib/migrate/stub/knexfile-eg.stub +43 -43
  80. package/lib/migrate/stub/knexfile-js.stub +44 -44
  81. package/lib/migrate/stub/knexfile-ls.stub +35 -35
  82. package/lib/migrate/stub/knexfile-ts.stub +44 -44
  83. package/lib/migrate/stub/ls.stub +14 -14
  84. package/lib/migrate/stub/ts.stub +21 -21
  85. package/lib/migrate/table-creator.js +67 -67
  86. package/lib/migrate/table-resolver.js +27 -27
  87. package/lib/query/builder.js +1372 -1372
  88. package/lib/query/compiler.js +889 -889
  89. package/lib/query/constants.js +13 -13
  90. package/lib/query/joinclause.js +263 -263
  91. package/lib/query/methods.js +92 -92
  92. package/lib/query/string.js +190 -190
  93. package/lib/raw.js +188 -188
  94. package/lib/ref.js +39 -39
  95. package/lib/runner.js +285 -285
  96. package/lib/schema/builder.js +82 -82
  97. package/lib/schema/columnbuilder.js +117 -117
  98. package/lib/schema/columncompiler.js +177 -177
  99. package/lib/schema/compiler.js +101 -101
  100. package/lib/schema/helpers.js +51 -51
  101. package/lib/schema/tablebuilder.js +288 -288
  102. package/lib/schema/tablecompiler.js +296 -296
  103. package/lib/seed/Seeder.js +203 -203
  104. package/lib/seed/seed-stub.js +13 -13
  105. package/lib/seed/stub/coffee.stub +9 -9
  106. package/lib/seed/stub/eg.stub +11 -11
  107. package/lib/seed/stub/js.stub +13 -13
  108. package/lib/seed/stub/ls.stub +11 -11
  109. package/lib/seed/stub/ts.stub +13 -13
  110. package/lib/transaction.js +363 -363
  111. package/lib/util/batchInsert.js +59 -59
  112. package/lib/util/delay.js +6 -6
  113. package/lib/util/fake-client.js +9 -9
  114. package/lib/util/finally-mixin.js +13 -13
  115. package/lib/util/fs.js +76 -76
  116. package/lib/util/import-file.js +13 -13
  117. package/lib/util/is-module-type.js +14 -14
  118. package/lib/util/is.js +32 -32
  119. package/lib/util/make-knex.js +338 -338
  120. package/lib/util/nanoid.js +29 -29
  121. package/lib/util/noop.js +1 -1
  122. package/lib/util/parse-connection.js +66 -66
  123. package/lib/util/save-async-stack.js +14 -14
  124. package/lib/util/template.js +52 -52
  125. package/lib/util/timeout.js +29 -29
  126. package/lib/util/timestamp.js +16 -16
  127. package/package.json +1 -1
  128. package/scripts/build.js +125 -125
  129. package/scripts/docker-compose.yml +111 -111
  130. package/scripts/next-release-howto.md +24 -24
  131. package/scripts/release.sh +34 -34
  132. package/scripts/runkit-example.js +34 -34
  133. package/scripts/stress-test/README.txt +18 -18
  134. package/scripts/stress-test/docker-compose.yml +47 -47
  135. package/scripts/stress-test/knex-stress-test.js +196 -196
  136. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +145 -145
  137. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +100 -100
  138. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +184 -184
  139. package/types/index.d.ts +2249 -2249
  140. package/types/result.d.ts +27 -27
  141. package/types/tables.d.ts +4 -4
@@ -1,338 +1,338 @@
1
- const { EventEmitter } = require('events');
2
-
3
- const { Migrator } = require('../migrate/Migrator');
4
- const Seeder = require('../seed/Seeder');
5
- const FunctionHelper = require('../functionhelper');
6
- const QueryInterface = require('../query/methods');
7
- const merge = require('lodash/merge');
8
- const batchInsert = require('./batchInsert');
9
-
10
- // Javascript does not officially support "callable objects". Instead,
11
- // you must create a regular Function and inject properties/methods
12
- // into it. In other words: you can't leverage Prototype Inheritance
13
- // to share the property/method definitions.
14
- //
15
- // To work around this, we're creating an Object Property Definition.
16
- // This allow us to quickly inject everything into the `knex` function
17
- // via the `Object.defineProperties(..)` function. More importantly,
18
- // it allows the same definitions to be shared across `knex` instances.
19
- const KNEX_PROPERTY_DEFINITIONS = {
20
- client: {
21
- get() {
22
- return this.context.client;
23
- },
24
- set(client) {
25
- this.context.client = client;
26
- },
27
- configurable: true,
28
- },
29
-
30
- userParams: {
31
- get() {
32
- return this.context.userParams;
33
- },
34
- set(userParams) {
35
- this.context.userParams = userParams;
36
- },
37
- configurable: true,
38
- },
39
-
40
- schema: {
41
- get() {
42
- return this.client.schemaBuilder();
43
- },
44
- configurable: true,
45
- },
46
-
47
- migrate: {
48
- get() {
49
- return new Migrator(this);
50
- },
51
- configurable: true,
52
- },
53
-
54
- seed: {
55
- get() {
56
- return new Seeder(this);
57
- },
58
- configurable: true,
59
- },
60
-
61
- fn: {
62
- get() {
63
- return new FunctionHelper(this.client);
64
- },
65
- configurable: true,
66
- },
67
- };
68
-
69
- // `knex` instances serve as proxies around `context` objects. So, calling
70
- // any of these methods on the `knex` instance will forward the call to
71
- // the `knex.context` object. This ensures that `this` will correctly refer
72
- // to `context` within each of these methods.
73
- const CONTEXT_METHODS = [
74
- 'raw',
75
- 'batchInsert',
76
- 'transaction',
77
- 'transactionProvider',
78
- 'initialize',
79
- 'destroy',
80
- 'ref',
81
- 'withUserParams',
82
- 'queryBuilder',
83
- 'disableProcessing',
84
- 'enableProcessing',
85
- ];
86
-
87
- for (const m of CONTEXT_METHODS) {
88
- KNEX_PROPERTY_DEFINITIONS[m] = {
89
- value: function (...args) {
90
- return this.context[m](...args);
91
- },
92
- configurable: true,
93
- };
94
- }
95
-
96
- function makeKnex(client) {
97
- // The object we're potentially using to kick off an initial chain.
98
- function knex(tableName, options) {
99
- return createQueryBuilder(knex.context, tableName, options);
100
- }
101
-
102
- redefineProperties(knex, client);
103
- return knex;
104
- }
105
-
106
- function initContext(knexFn) {
107
- const knexContext = knexFn.context || {};
108
- Object.assign(knexContext, {
109
- queryBuilder() {
110
- return this.client.queryBuilder();
111
- },
112
-
113
- raw() {
114
- return this.client.raw.apply(this.client, arguments);
115
- },
116
-
117
- batchInsert(table, batch, chunkSize = 1000) {
118
- return batchInsert(this, table, batch, chunkSize);
119
- },
120
-
121
- // Creates a new transaction.
122
- // If container is provided, returns a promise for when the transaction is resolved.
123
- // If container is not provided, returns a promise with a transaction that is resolved
124
- // when transaction is ready to be used.
125
- transaction(container, _config) {
126
- const config = Object.assign({}, _config);
127
- config.userParams = this.userParams || {};
128
- if (config.doNotRejectOnRollback === undefined) {
129
- // Backwards-compatibility: default value changes depending upon
130
- // whether or not a `container` was provided.
131
- config.doNotRejectOnRollback = !container;
132
- }
133
-
134
- return this._transaction(container, config);
135
- },
136
-
137
- // Internal method that actually establishes the Transaction. It makes no assumptions
138
- // about the `config` or `outerTx`, and expects the caller to handle these details.
139
- _transaction(container, config, outerTx = null) {
140
- if (container) {
141
- const trx = this.client.transaction(container, config, outerTx);
142
- return trx;
143
- } else {
144
- return new Promise((resolve, reject) => {
145
- const trx = this.client.transaction(resolve, config, outerTx);
146
- trx.catch(reject);
147
- });
148
- }
149
- },
150
-
151
- transactionProvider(config) {
152
- let trx;
153
- return () => {
154
- if (!trx) {
155
- trx = this.transaction(undefined, config);
156
- }
157
- return trx;
158
- };
159
- },
160
-
161
- // Typically never needed, initializes the pool for a knex client.
162
- initialize(config) {
163
- return this.client.initializePool(config);
164
- },
165
-
166
- // Convenience method for tearing down the pool.
167
- destroy(callback) {
168
- return this.client.destroy(callback);
169
- },
170
-
171
- ref(ref) {
172
- return this.client.ref(ref);
173
- },
174
-
175
- // Do not document this as public API until naming and API is improved for general consumption
176
- // This method exists to disable processing of internal queries in migrations
177
- disableProcessing() {
178
- if (this.userParams.isProcessingDisabled) {
179
- return;
180
- }
181
- this.userParams.wrapIdentifier = this.client.config.wrapIdentifier;
182
- this.userParams.postProcessResponse = this.client.config.postProcessResponse;
183
- this.client.config.wrapIdentifier = null;
184
- this.client.config.postProcessResponse = null;
185
- this.userParams.isProcessingDisabled = true;
186
- },
187
-
188
- // Do not document this as public API until naming and API is improved for general consumption
189
- // This method exists to enable execution of non-internal queries with consistent identifier naming in migrations
190
- enableProcessing() {
191
- if (!this.userParams.isProcessingDisabled) {
192
- return;
193
- }
194
- this.client.config.wrapIdentifier = this.userParams.wrapIdentifier;
195
- this.client.config.postProcessResponse = this.userParams.postProcessResponse;
196
- this.userParams.isProcessingDisabled = false;
197
- },
198
-
199
- withUserParams(params) {
200
- const knexClone = shallowCloneFunction(knexFn); // We need to include getters in our clone
201
- if (this.client) {
202
- knexClone.client = Object.create(this.client.constructor.prototype); // Clone client to avoid leaking listeners that are set on it
203
- merge(knexClone.client, this.client);
204
- knexClone.client.config = Object.assign({}, this.client.config); // Clone client config to make sure they can be modified independently
205
- }
206
-
207
- redefineProperties(knexClone, knexClone.client);
208
- _copyEventListeners('query', knexFn, knexClone);
209
- _copyEventListeners('query-error', knexFn, knexClone);
210
- _copyEventListeners('query-response', knexFn, knexClone);
211
- _copyEventListeners('start', knexFn, knexClone);
212
- knexClone.userParams = params;
213
- return knexClone;
214
- },
215
- });
216
-
217
- if (!knexFn.context) {
218
- knexFn.context = knexContext;
219
- }
220
- }
221
-
222
- function _copyEventListeners(eventName, sourceKnex, targetKnex) {
223
- const listeners = sourceKnex.listeners(eventName);
224
- listeners.forEach((listener) => {
225
- targetKnex.on(eventName, listener);
226
- });
227
- }
228
-
229
- function redefineProperties(knex, client) {
230
- // Allow chaining methods from the root object, before
231
- // any other information is specified.
232
- //
233
- // TODO: `QueryBuilder.extend(..)` allows new QueryBuilder
234
- // methods to be introduced via external components.
235
- // As a side-effect, it also pushes the new method names
236
- // into the `QueryInterface` array.
237
- //
238
- // The Problem: due to the way the code is currently
239
- // structured, these new methods cannot be retroactively
240
- // injected into existing `knex` instances! As a result,
241
- // some `knex` instances will support the methods, and
242
- // others will not.
243
- //
244
- // We should revisit this once we figure out the desired
245
- // behavior / usage. For instance: do we really want to
246
- // allow external components to directly manipulate `knex`
247
- // data structures? Or, should we come up w/ a different
248
- // approach that avoids side-effects / mutation?
249
- //
250
- // (FYI: I noticed this issue because I attempted to integrate
251
- // this logic directly into the `KNEX_PROPERTY_DEFINITIONS`
252
- // construction. However, `KNEX_PROPERTY_DEFINITIONS` is
253
- // constructed before any `knex` instances are created.
254
- // As a result, the method extensions were missing from all
255
- // `knex` instances.)
256
- QueryInterface.forEach(function (method) {
257
- knex[method] = function () {
258
- const builder = this.queryBuilder();
259
- return builder[method].apply(builder, arguments);
260
- };
261
- });
262
-
263
- Object.defineProperties(knex, KNEX_PROPERTY_DEFINITIONS);
264
-
265
- initContext(knex);
266
- knex.client = client;
267
-
268
- // TODO: It looks like this field is never actually used.
269
- // It should probably be removed in a future PR.
270
- knex.client.makeKnex = makeKnex;
271
-
272
- knex.userParams = {};
273
-
274
- // Hook up the "knex" object as an EventEmitter.
275
- const ee = new EventEmitter();
276
- for (const key in ee) {
277
- knex[key] = ee[key];
278
- }
279
-
280
- // Unfortunately, something seems to be broken in Node 6 and removing events from a clone also mutates original Knex,
281
- // which is highly undesirable
282
- if (knex._internalListeners) {
283
- knex._internalListeners.forEach(({ eventName, listener }) => {
284
- knex.client.removeListener(eventName, listener); // Remove duplicates for copies
285
- });
286
- }
287
- knex._internalListeners = [];
288
-
289
- // Passthrough all "start" and "query" events to the knex object.
290
- _addInternalListener(knex, 'start', (obj) => {
291
- knex.emit('start', obj);
292
- });
293
- _addInternalListener(knex, 'query', (obj) => {
294
- knex.emit('query', obj);
295
- });
296
- _addInternalListener(knex, 'query-error', (err, obj) => {
297
- knex.emit('query-error', err, obj);
298
- });
299
- _addInternalListener(knex, 'query-response', (response, obj, builder) => {
300
- knex.emit('query-response', response, obj, builder);
301
- });
302
- }
303
-
304
- function _addInternalListener(knex, eventName, listener) {
305
- knex.client.on(eventName, listener);
306
- knex._internalListeners.push({
307
- eventName,
308
- listener,
309
- });
310
- }
311
-
312
- function createQueryBuilder(knexContext, tableName, options) {
313
- const qb = knexContext.queryBuilder();
314
- if (!tableName)
315
- knexContext.client.logger.warn(
316
- 'calling knex without a tableName is deprecated. Use knex.queryBuilder() instead.'
317
- );
318
- return tableName ? qb.table(tableName, options) : qb;
319
- }
320
-
321
- function shallowCloneFunction(originalFunction) {
322
- const fnContext = Object.create(
323
- Object.getPrototypeOf(originalFunction),
324
- Object.getOwnPropertyDescriptors(originalFunction)
325
- );
326
-
327
- const knexContext = {};
328
- const knexFnWrapper = (tableName, options) => {
329
- return createQueryBuilder(knexContext, tableName, options);
330
- };
331
-
332
- const clonedFunction = knexFnWrapper.bind(fnContext);
333
- Object.assign(clonedFunction, originalFunction);
334
- clonedFunction.context = knexContext;
335
- return clonedFunction;
336
- }
337
-
338
- module.exports = makeKnex;
1
+ const { EventEmitter } = require('events');
2
+
3
+ const { Migrator } = require('../migrate/Migrator');
4
+ const Seeder = require('../seed/Seeder');
5
+ const FunctionHelper = require('../functionhelper');
6
+ const QueryInterface = require('../query/methods');
7
+ const merge = require('lodash/merge');
8
+ const batchInsert = require('./batchInsert');
9
+
10
+ // Javascript does not officially support "callable objects". Instead,
11
+ // you must create a regular Function and inject properties/methods
12
+ // into it. In other words: you can't leverage Prototype Inheritance
13
+ // to share the property/method definitions.
14
+ //
15
+ // To work around this, we're creating an Object Property Definition.
16
+ // This allow us to quickly inject everything into the `knex` function
17
+ // via the `Object.defineProperties(..)` function. More importantly,
18
+ // it allows the same definitions to be shared across `knex` instances.
19
+ const KNEX_PROPERTY_DEFINITIONS = {
20
+ client: {
21
+ get() {
22
+ return this.context.client;
23
+ },
24
+ set(client) {
25
+ this.context.client = client;
26
+ },
27
+ configurable: true,
28
+ },
29
+
30
+ userParams: {
31
+ get() {
32
+ return this.context.userParams;
33
+ },
34
+ set(userParams) {
35
+ this.context.userParams = userParams;
36
+ },
37
+ configurable: true,
38
+ },
39
+
40
+ schema: {
41
+ get() {
42
+ return this.client.schemaBuilder();
43
+ },
44
+ configurable: true,
45
+ },
46
+
47
+ migrate: {
48
+ get() {
49
+ return new Migrator(this);
50
+ },
51
+ configurable: true,
52
+ },
53
+
54
+ seed: {
55
+ get() {
56
+ return new Seeder(this);
57
+ },
58
+ configurable: true,
59
+ },
60
+
61
+ fn: {
62
+ get() {
63
+ return new FunctionHelper(this.client);
64
+ },
65
+ configurable: true,
66
+ },
67
+ };
68
+
69
+ // `knex` instances serve as proxies around `context` objects. So, calling
70
+ // any of these methods on the `knex` instance will forward the call to
71
+ // the `knex.context` object. This ensures that `this` will correctly refer
72
+ // to `context` within each of these methods.
73
+ const CONTEXT_METHODS = [
74
+ 'raw',
75
+ 'batchInsert',
76
+ 'transaction',
77
+ 'transactionProvider',
78
+ 'initialize',
79
+ 'destroy',
80
+ 'ref',
81
+ 'withUserParams',
82
+ 'queryBuilder',
83
+ 'disableProcessing',
84
+ 'enableProcessing',
85
+ ];
86
+
87
+ for (const m of CONTEXT_METHODS) {
88
+ KNEX_PROPERTY_DEFINITIONS[m] = {
89
+ value: function (...args) {
90
+ return this.context[m](...args);
91
+ },
92
+ configurable: true,
93
+ };
94
+ }
95
+
96
+ function makeKnex(client) {
97
+ // The object we're potentially using to kick off an initial chain.
98
+ function knex(tableName, options) {
99
+ return createQueryBuilder(knex.context, tableName, options);
100
+ }
101
+
102
+ redefineProperties(knex, client);
103
+ return knex;
104
+ }
105
+
106
+ function initContext(knexFn) {
107
+ const knexContext = knexFn.context || {};
108
+ Object.assign(knexContext, {
109
+ queryBuilder() {
110
+ return this.client.queryBuilder();
111
+ },
112
+
113
+ raw() {
114
+ return this.client.raw.apply(this.client, arguments);
115
+ },
116
+
117
+ batchInsert(table, batch, chunkSize = 1000) {
118
+ return batchInsert(this, table, batch, chunkSize);
119
+ },
120
+
121
+ // Creates a new transaction.
122
+ // If container is provided, returns a promise for when the transaction is resolved.
123
+ // If container is not provided, returns a promise with a transaction that is resolved
124
+ // when transaction is ready to be used.
125
+ transaction(container, _config) {
126
+ const config = Object.assign({}, _config);
127
+ config.userParams = this.userParams || {};
128
+ if (config.doNotRejectOnRollback === undefined) {
129
+ // Backwards-compatibility: default value changes depending upon
130
+ // whether or not a `container` was provided.
131
+ config.doNotRejectOnRollback = !container;
132
+ }
133
+
134
+ return this._transaction(container, config);
135
+ },
136
+
137
+ // Internal method that actually establishes the Transaction. It makes no assumptions
138
+ // about the `config` or `outerTx`, and expects the caller to handle these details.
139
+ _transaction(container, config, outerTx = null) {
140
+ if (container) {
141
+ const trx = this.client.transaction(container, config, outerTx);
142
+ return trx;
143
+ } else {
144
+ return new Promise((resolve, reject) => {
145
+ const trx = this.client.transaction(resolve, config, outerTx);
146
+ trx.catch(reject);
147
+ });
148
+ }
149
+ },
150
+
151
+ transactionProvider(config) {
152
+ let trx;
153
+ return () => {
154
+ if (!trx) {
155
+ trx = this.transaction(undefined, config);
156
+ }
157
+ return trx;
158
+ };
159
+ },
160
+
161
+ // Typically never needed, initializes the pool for a knex client.
162
+ initialize(config) {
163
+ return this.client.initializePool(config);
164
+ },
165
+
166
+ // Convenience method for tearing down the pool.
167
+ destroy(callback) {
168
+ return this.client.destroy(callback);
169
+ },
170
+
171
+ ref(ref) {
172
+ return this.client.ref(ref);
173
+ },
174
+
175
+ // Do not document this as public API until naming and API is improved for general consumption
176
+ // This method exists to disable processing of internal queries in migrations
177
+ disableProcessing() {
178
+ if (this.userParams.isProcessingDisabled) {
179
+ return;
180
+ }
181
+ this.userParams.wrapIdentifier = this.client.config.wrapIdentifier;
182
+ this.userParams.postProcessResponse = this.client.config.postProcessResponse;
183
+ this.client.config.wrapIdentifier = null;
184
+ this.client.config.postProcessResponse = null;
185
+ this.userParams.isProcessingDisabled = true;
186
+ },
187
+
188
+ // Do not document this as public API until naming and API is improved for general consumption
189
+ // This method exists to enable execution of non-internal queries with consistent identifier naming in migrations
190
+ enableProcessing() {
191
+ if (!this.userParams.isProcessingDisabled) {
192
+ return;
193
+ }
194
+ this.client.config.wrapIdentifier = this.userParams.wrapIdentifier;
195
+ this.client.config.postProcessResponse = this.userParams.postProcessResponse;
196
+ this.userParams.isProcessingDisabled = false;
197
+ },
198
+
199
+ withUserParams(params) {
200
+ const knexClone = shallowCloneFunction(knexFn); // We need to include getters in our clone
201
+ if (this.client) {
202
+ knexClone.client = Object.create(this.client.constructor.prototype); // Clone client to avoid leaking listeners that are set on it
203
+ merge(knexClone.client, this.client);
204
+ knexClone.client.config = Object.assign({}, this.client.config); // Clone client config to make sure they can be modified independently
205
+ }
206
+
207
+ redefineProperties(knexClone, knexClone.client);
208
+ _copyEventListeners('query', knexFn, knexClone);
209
+ _copyEventListeners('query-error', knexFn, knexClone);
210
+ _copyEventListeners('query-response', knexFn, knexClone);
211
+ _copyEventListeners('start', knexFn, knexClone);
212
+ knexClone.userParams = params;
213
+ return knexClone;
214
+ },
215
+ });
216
+
217
+ if (!knexFn.context) {
218
+ knexFn.context = knexContext;
219
+ }
220
+ }
221
+
222
+ function _copyEventListeners(eventName, sourceKnex, targetKnex) {
223
+ const listeners = sourceKnex.listeners(eventName);
224
+ listeners.forEach((listener) => {
225
+ targetKnex.on(eventName, listener);
226
+ });
227
+ }
228
+
229
+ function redefineProperties(knex, client) {
230
+ // Allow chaining methods from the root object, before
231
+ // any other information is specified.
232
+ //
233
+ // TODO: `QueryBuilder.extend(..)` allows new QueryBuilder
234
+ // methods to be introduced via external components.
235
+ // As a side-effect, it also pushes the new method names
236
+ // into the `QueryInterface` array.
237
+ //
238
+ // The Problem: due to the way the code is currently
239
+ // structured, these new methods cannot be retroactively
240
+ // injected into existing `knex` instances! As a result,
241
+ // some `knex` instances will support the methods, and
242
+ // others will not.
243
+ //
244
+ // We should revisit this once we figure out the desired
245
+ // behavior / usage. For instance: do we really want to
246
+ // allow external components to directly manipulate `knex`
247
+ // data structures? Or, should we come up w/ a different
248
+ // approach that avoids side-effects / mutation?
249
+ //
250
+ // (FYI: I noticed this issue because I attempted to integrate
251
+ // this logic directly into the `KNEX_PROPERTY_DEFINITIONS`
252
+ // construction. However, `KNEX_PROPERTY_DEFINITIONS` is
253
+ // constructed before any `knex` instances are created.
254
+ // As a result, the method extensions were missing from all
255
+ // `knex` instances.)
256
+ QueryInterface.forEach(function (method) {
257
+ knex[method] = function () {
258
+ const builder = this.queryBuilder();
259
+ return builder[method].apply(builder, arguments);
260
+ };
261
+ });
262
+
263
+ Object.defineProperties(knex, KNEX_PROPERTY_DEFINITIONS);
264
+
265
+ initContext(knex);
266
+ knex.client = client;
267
+
268
+ // TODO: It looks like this field is never actually used.
269
+ // It should probably be removed in a future PR.
270
+ knex.client.makeKnex = makeKnex;
271
+
272
+ knex.userParams = {};
273
+
274
+ // Hook up the "knex" object as an EventEmitter.
275
+ const ee = new EventEmitter();
276
+ for (const key in ee) {
277
+ knex[key] = ee[key];
278
+ }
279
+
280
+ // Unfortunately, something seems to be broken in Node 6 and removing events from a clone also mutates original Knex,
281
+ // which is highly undesirable
282
+ if (knex._internalListeners) {
283
+ knex._internalListeners.forEach(({ eventName, listener }) => {
284
+ knex.client.removeListener(eventName, listener); // Remove duplicates for copies
285
+ });
286
+ }
287
+ knex._internalListeners = [];
288
+
289
+ // Passthrough all "start" and "query" events to the knex object.
290
+ _addInternalListener(knex, 'start', (obj) => {
291
+ knex.emit('start', obj);
292
+ });
293
+ _addInternalListener(knex, 'query', (obj) => {
294
+ knex.emit('query', obj);
295
+ });
296
+ _addInternalListener(knex, 'query-error', (err, obj) => {
297
+ knex.emit('query-error', err, obj);
298
+ });
299
+ _addInternalListener(knex, 'query-response', (response, obj, builder) => {
300
+ knex.emit('query-response', response, obj, builder);
301
+ });
302
+ }
303
+
304
+ function _addInternalListener(knex, eventName, listener) {
305
+ knex.client.on(eventName, listener);
306
+ knex._internalListeners.push({
307
+ eventName,
308
+ listener,
309
+ });
310
+ }
311
+
312
+ function createQueryBuilder(knexContext, tableName, options) {
313
+ const qb = knexContext.queryBuilder();
314
+ if (!tableName)
315
+ knexContext.client.logger.warn(
316
+ 'calling knex without a tableName is deprecated. Use knex.queryBuilder() instead.'
317
+ );
318
+ return tableName ? qb.table(tableName, options) : qb;
319
+ }
320
+
321
+ function shallowCloneFunction(originalFunction) {
322
+ const fnContext = Object.create(
323
+ Object.getPrototypeOf(originalFunction),
324
+ Object.getOwnPropertyDescriptors(originalFunction)
325
+ );
326
+
327
+ const knexContext = {};
328
+ const knexFnWrapper = (tableName, options) => {
329
+ return createQueryBuilder(knexContext, tableName, options);
330
+ };
331
+
332
+ const clonedFunction = knexFnWrapper.bind(fnContext);
333
+ Object.assign(clonedFunction, originalFunction);
334
+ clonedFunction.context = knexContext;
335
+ return clonedFunction;
336
+ }
337
+
338
+ module.exports = makeKnex;