@abedmurrar/objection 0.0.0-stage → 4.0.0-alpha.0

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 (190) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +69 -2
  3. package/lib/.eslintrc.json +8 -0
  4. package/lib/initialize.js +14 -0
  5. package/lib/model/AjvValidator.js +325 -0
  6. package/lib/model/Model.js +942 -0
  7. package/lib/model/ModifierNotFoundError.js +12 -0
  8. package/lib/model/NotFoundError.js +23 -0
  9. package/lib/model/RelationDoesNotExistError.js +14 -0
  10. package/lib/model/ValidationError.js +54 -0
  11. package/lib/model/Validator.js +26 -0
  12. package/lib/model/getModel.js +9 -0
  13. package/lib/model/graph/ModelGraph.js +80 -0
  14. package/lib/model/graph/ModelGraphBuilder.js +241 -0
  15. package/lib/model/graph/ModelGraphEdge.js +52 -0
  16. package/lib/model/graph/ModelGraphNode.js +240 -0
  17. package/lib/model/inheritModel.js +28 -0
  18. package/lib/model/modelBindKnex.js +83 -0
  19. package/lib/model/modelClone.js +121 -0
  20. package/lib/model/modelColPropMap.js +34 -0
  21. package/lib/model/modelId.js +62 -0
  22. package/lib/model/modelJsonAttributes.js +92 -0
  23. package/lib/model/modelParseRelations.js +82 -0
  24. package/lib/model/modelQueryProps.js +147 -0
  25. package/lib/model/modelSet.js +136 -0
  26. package/lib/model/modelTableMetadata.js +83 -0
  27. package/lib/model/modelToJson.js +187 -0
  28. package/lib/model/modelUtils.js +47 -0
  29. package/lib/model/modelValidate.js +48 -0
  30. package/lib/model/modelValues.js +126 -0
  31. package/lib/model/modelVisitor.js +41 -0
  32. package/lib/objection.js +114 -0
  33. package/lib/queryBuilder/FunctionBuilder.js +339 -0
  34. package/lib/queryBuilder/InternalOptions.js +29 -0
  35. package/lib/queryBuilder/JoinBuilder.js +157 -0
  36. package/lib/queryBuilder/QueryBuilder.js +1398 -0
  37. package/lib/queryBuilder/QueryBuilderBase.js +884 -0
  38. package/lib/queryBuilder/QueryBuilderContext.js +27 -0
  39. package/lib/queryBuilder/QueryBuilderContextBase.js +35 -0
  40. package/lib/queryBuilder/QueryBuilderOperationSupport.js +558 -0
  41. package/lib/queryBuilder/QueryBuilderUserContext.js +31 -0
  42. package/lib/queryBuilder/RawBuilder.js +93 -0
  43. package/lib/queryBuilder/ReferenceBuilder.js +284 -0
  44. package/lib/queryBuilder/RelationExpression.js +431 -0
  45. package/lib/queryBuilder/StaticHookArguments.js +134 -0
  46. package/lib/queryBuilder/ValueBuilder.js +127 -0
  47. package/lib/queryBuilder/expressions.js +151 -0
  48. package/lib/queryBuilder/functions/mysql.js +817 -0
  49. package/lib/queryBuilder/graph/GraphAction.js +69 -0
  50. package/lib/queryBuilder/graph/GraphData.js +14 -0
  51. package/lib/queryBuilder/graph/GraphFetcher.js +191 -0
  52. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +184 -0
  53. package/lib/queryBuilder/graph/GraphOperation.js +27 -0
  54. package/lib/queryBuilder/graph/GraphOptions.js +207 -0
  55. package/lib/queryBuilder/graph/GraphUpsert.js +305 -0
  56. package/lib/queryBuilder/graph/delete/GraphDelete.js +20 -0
  57. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +74 -0
  58. package/lib/queryBuilder/graph/insert/GraphInsert.js +145 -0
  59. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +225 -0
  60. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +92 -0
  61. package/lib/queryBuilder/graph/patch/GraphPatch.js +20 -0
  62. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +258 -0
  63. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +31 -0
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +126 -0
  65. package/lib/queryBuilder/join/JoinResultColumn.js +23 -0
  66. package/lib/queryBuilder/join/JoinResultParser.js +119 -0
  67. package/lib/queryBuilder/join/RelationJoiner.js +341 -0
  68. package/lib/queryBuilder/join/TableNode.js +163 -0
  69. package/lib/queryBuilder/join/TableTree.js +85 -0
  70. package/lib/queryBuilder/join/utils.js +25 -0
  71. package/lib/queryBuilder/operations/DelegateOperation.js +141 -0
  72. package/lib/queryBuilder/operations/DeleteOperation.js +51 -0
  73. package/lib/queryBuilder/operations/FindByIdOperation.js +37 -0
  74. package/lib/queryBuilder/operations/FindByIdsOperation.js +29 -0
  75. package/lib/queryBuilder/operations/FindOperation.js +164 -0
  76. package/lib/queryBuilder/operations/FirstOperation.js +27 -0
  77. package/lib/queryBuilder/operations/FromOperation.js +110 -0
  78. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +49 -0
  79. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +45 -0
  80. package/lib/queryBuilder/operations/InsertGraphOperation.js +108 -0
  81. package/lib/queryBuilder/operations/InsertOperation.js +206 -0
  82. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +46 -0
  83. package/lib/queryBuilder/operations/InstanceFindOperation.js +21 -0
  84. package/lib/queryBuilder/operations/InstanceInsertOperation.js +24 -0
  85. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +59 -0
  86. package/lib/queryBuilder/operations/JoinRelatedOperation.js +103 -0
  87. package/lib/queryBuilder/operations/KnexOperation.js +14 -0
  88. package/lib/queryBuilder/operations/MergeOperation.js +56 -0
  89. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +192 -0
  90. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +29 -0
  91. package/lib/queryBuilder/operations/OnBuildOperation.js +29 -0
  92. package/lib/queryBuilder/operations/OnErrorOperation.js +29 -0
  93. package/lib/queryBuilder/operations/QueryBuilderOperation.js +297 -0
  94. package/lib/queryBuilder/operations/RangeOperation.js +47 -0
  95. package/lib/queryBuilder/operations/RelateOperation.js +27 -0
  96. package/lib/queryBuilder/operations/ReturningOperation.js +30 -0
  97. package/lib/queryBuilder/operations/RunAfterOperation.js +29 -0
  98. package/lib/queryBuilder/operations/RunBeforeOperation.js +29 -0
  99. package/lib/queryBuilder/operations/UnrelateOperation.js +23 -0
  100. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +80 -0
  101. package/lib/queryBuilder/operations/UpdateOperation.js +155 -0
  102. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +45 -0
  103. package/lib/queryBuilder/operations/UpsertGraphOperation.js +66 -0
  104. package/lib/queryBuilder/operations/WhereCompositeOperation.js +57 -0
  105. package/lib/queryBuilder/operations/WhereInOperation.js +48 -0
  106. package/lib/queryBuilder/operations/eager/EagerOperation.js +61 -0
  107. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +51 -0
  108. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +13 -0
  109. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +285 -0
  110. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +36 -0
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +53 -0
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +31 -0
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +31 -0
  114. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +167 -0
  115. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +164 -0
  116. package/lib/queryBuilder/operations/select/SelectOperation.js +66 -0
  117. package/lib/queryBuilder/operations/select/Selection.js +123 -0
  118. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +117 -0
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +100 -0
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +104 -0
  121. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +886 -0
  122. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +97 -0
  123. package/lib/queryBuilder/parsers/relationExpressionParser.js +1042 -0
  124. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +141 -0
  125. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +22 -0
  126. package/lib/queryBuilder/transformations/QueryTransformation.js +11 -0
  127. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +71 -0
  128. package/lib/queryBuilder/transformations/index.js +15 -0
  129. package/lib/queryBuilder/whereScopes.js +227 -0
  130. package/lib/relations/Relation.js +401 -0
  131. package/lib/relations/RelationDeleteOperation.js +29 -0
  132. package/lib/relations/RelationFindOperation.js +149 -0
  133. package/lib/relations/RelationInsertOperation.js +33 -0
  134. package/lib/relations/RelationOwner.js +236 -0
  135. package/lib/relations/RelationProperty.js +247 -0
  136. package/lib/relations/RelationUpdateOperation.js +30 -0
  137. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +23 -0
  138. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +44 -0
  139. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +50 -0
  140. package/lib/relations/belongsToOne/BelongsToOneRelation.js +53 -0
  141. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +61 -0
  142. package/lib/relations/hasMany/HasManyInsertOperation.js +61 -0
  143. package/lib/relations/hasMany/HasManyRelateOperation.js +64 -0
  144. package/lib/relations/hasMany/HasManyRelation.js +49 -0
  145. package/lib/relations/hasMany/HasManyUnrelateOperation.js +33 -0
  146. package/lib/relations/hasOne/HasOneRelation.js +13 -0
  147. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +13 -0
  148. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +105 -0
  149. package/lib/relations/manyToMany/ManyToManyRelation.js +507 -0
  150. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +36 -0
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +10 -0
  152. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +26 -0
  153. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +12 -0
  154. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +105 -0
  155. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +52 -0
  156. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +81 -0
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +14 -0
  158. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +34 -0
  159. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +16 -0
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +10 -0
  161. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +82 -0
  162. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +12 -0
  163. package/lib/transaction.js +96 -0
  164. package/lib/utils/assert.js +25 -0
  165. package/lib/utils/buildUtils.js +21 -0
  166. package/lib/utils/classUtils.js +13 -0
  167. package/lib/utils/clone.js +2329 -0
  168. package/lib/utils/createModifier.js +42 -0
  169. package/lib/utils/deprecate.js +15 -0
  170. package/lib/utils/identifierMapping.js +227 -0
  171. package/lib/utils/internalPropUtils.js +11 -0
  172. package/lib/utils/knexUtils.js +76 -0
  173. package/lib/utils/mixin.js +25 -0
  174. package/lib/utils/mysqlJsonPath.js +55 -0
  175. package/lib/utils/normalizeIds.js +144 -0
  176. package/lib/utils/objectUtils.js +416 -0
  177. package/lib/utils/parseFieldExpression.js +51 -0
  178. package/lib/utils/postgresJsonPath.js +110 -0
  179. package/lib/utils/promiseUtils/after.js +17 -0
  180. package/lib/utils/promiseUtils/afterReturn.js +17 -0
  181. package/lib/utils/promiseUtils/index.js +17 -0
  182. package/lib/utils/promiseUtils/isPromise.js +11 -0
  183. package/lib/utils/promiseUtils/map.js +110 -0
  184. package/lib/utils/promiseUtils/mapAfterAllReturn.js +29 -0
  185. package/lib/utils/promiseUtils/try.js +22 -0
  186. package/lib/utils/resolveModel.js +107 -0
  187. package/lib/utils/tmpColumnUtils.js +16 -0
  188. package/package.json +86 -4
  189. package/typings/objection/index.d.ts +4104 -0
  190. package/typings/objection/relation-expression.d.ts +237 -0
@@ -0,0 +1,416 @@
1
+ 'use strict';
2
+
3
+ const { clone, cloneDeep } = require('./clone');
4
+ const SMALL_ARRAY_SIZE = 10;
5
+
6
+ function isEmpty(item) {
7
+ if (Array.isArray(item) || Buffer.isBuffer(item)) {
8
+ return item.length === 0;
9
+ } else if (isObject(item)) {
10
+ return Object.keys(item).length === 0;
11
+ } else {
12
+ return true;
13
+ }
14
+ }
15
+
16
+ function isObject(value) {
17
+ return value !== null && typeof value === 'object';
18
+ }
19
+
20
+ // Quick and dirty check if an object is a plain object and not
21
+ // for example an instance of some class.
22
+ function isPlainObject(value) {
23
+ return (
24
+ isObject(value) &&
25
+ (!value.constructor || value.constructor === Object) &&
26
+ (!value.toString || value.toString === Object.prototype.toString)
27
+ );
28
+ }
29
+
30
+ function isFunction(value) {
31
+ return typeof value === 'function';
32
+ }
33
+
34
+ function isRegExp(value) {
35
+ return value instanceof RegExp;
36
+ }
37
+
38
+ function isString(value) {
39
+ return typeof value === 'string';
40
+ }
41
+
42
+ function isNumber(value) {
43
+ return typeof value === 'number';
44
+ }
45
+
46
+ function asArray(value) {
47
+ return Array.isArray(value) ? value : [value];
48
+ }
49
+
50
+ function asSingle(value) {
51
+ return Array.isArray(value) ? value[0] : value;
52
+ }
53
+
54
+ function uniqBy(items, keyGetter = null) {
55
+ const map = new Map();
56
+
57
+ for (let i = 0, l = items.length; i < l; ++i) {
58
+ const item = items[i];
59
+ const key = keyGetter !== null ? keyGetter(item) : item;
60
+
61
+ map.set(key, item);
62
+ }
63
+
64
+ return Array.from(map.values());
65
+ }
66
+
67
+ function groupBy(items, keyGetter = null) {
68
+ const groups = new Map();
69
+
70
+ for (const item of items) {
71
+ const key = keyGetter !== null ? keyGetter(item) : item;
72
+ let group = groups.get(key);
73
+
74
+ if (!group) {
75
+ group = [];
76
+ groups.set(key, group);
77
+ }
78
+
79
+ group.push(item);
80
+ }
81
+
82
+ return groups;
83
+ }
84
+
85
+ function omit(obj, keysToOmit) {
86
+ keysToOmit = asArray(keysToOmit);
87
+
88
+ const keys = Object.keys(obj);
89
+ const out = {};
90
+
91
+ for (let i = 0, l = keys.length; i < l; ++i) {
92
+ const key = keys[i];
93
+
94
+ if (!keysToOmit.includes(key)) {
95
+ out[key] = obj[key];
96
+ }
97
+ }
98
+
99
+ return out;
100
+ }
101
+
102
+ function difference(arr1, arr2) {
103
+ const arr2Set = new Set(arr2);
104
+ const diff = [];
105
+
106
+ for (let i = 0; i < arr1.length; ++i) {
107
+ const value = arr1[i];
108
+
109
+ if (!arr2Set.has(value)) {
110
+ diff.push(value);
111
+ }
112
+ }
113
+
114
+ return diff;
115
+ }
116
+
117
+ function union(arr1, arr2) {
118
+ if (arr1.length < SMALL_ARRAY_SIZE && arr2.length < SMALL_ARRAY_SIZE) {
119
+ return unionSmall(arr1, arr2);
120
+ } else {
121
+ return unionGeneric(arr1, arr2);
122
+ }
123
+ }
124
+
125
+ function unionSmall(arr1, arr2) {
126
+ const all = arr1.slice();
127
+
128
+ for (let i = 0, l = arr2.length; i < l; ++i) {
129
+ const item = arr2[i];
130
+
131
+ if (all.indexOf(item) === -1) {
132
+ all.push(item);
133
+ }
134
+ }
135
+
136
+ return all;
137
+ }
138
+
139
+ function unionGeneric(arr1, arr2) {
140
+ const all = new Set();
141
+
142
+ for (let i = 0; i < arr1.length; ++i) {
143
+ all.add(arr1[i]);
144
+ }
145
+
146
+ for (let i = 0; i < arr2.length; ++i) {
147
+ all.add(arr2[i]);
148
+ }
149
+
150
+ return Array.from(all);
151
+ }
152
+
153
+ function last(arr) {
154
+ return arr[arr.length - 1];
155
+ }
156
+
157
+ function upperFirst(str) {
158
+ return str[0].toUpperCase() + str.substring(1);
159
+ }
160
+
161
+ function values(obj) {
162
+ if (isObject(obj)) {
163
+ const keys = Object.keys(obj);
164
+ const values = new Array(keys.length);
165
+
166
+ for (let i = 0, l = keys.length; i < l; ++i) {
167
+ values[i] = obj[keys[i]];
168
+ }
169
+
170
+ return values;
171
+ } else {
172
+ return [];
173
+ }
174
+ }
175
+
176
+ function once(func) {
177
+ let called = false;
178
+ let value = undefined;
179
+
180
+ return function () {
181
+ if (called === false) {
182
+ called = true;
183
+ value = func.apply(this, arguments);
184
+ }
185
+
186
+ return value;
187
+ };
188
+ }
189
+
190
+ function flatten(arrays) {
191
+ const out = [];
192
+
193
+ for (let i = 0, l = arrays.length; i < l; ++i) {
194
+ const value = arrays[i];
195
+
196
+ if (Array.isArray(value)) {
197
+ for (let j = 0; j < value.length; ++j) {
198
+ out.push(value[j]);
199
+ }
200
+ } else {
201
+ out.push(value);
202
+ }
203
+ }
204
+
205
+ return out;
206
+ }
207
+
208
+ function get(obj, path) {
209
+ for (let i = 0, l = path.length; i < l; ++i) {
210
+ const key = path[i];
211
+
212
+ if (!isObject(obj)) {
213
+ return undefined;
214
+ }
215
+
216
+ obj = obj[key];
217
+ }
218
+
219
+ return obj;
220
+ }
221
+
222
+ function set(obj, path, value) {
223
+ const inputObj = obj;
224
+
225
+ for (let i = 0, l = path.length - 1; i < l; ++i) {
226
+ const key = path[i];
227
+
228
+ if (!isSafeKey(key)) {
229
+ return inputObj;
230
+ }
231
+
232
+ let child = obj[key];
233
+
234
+ if (!isObject(child)) {
235
+ const nextKey = path[i + 1];
236
+
237
+ if (isNaN(nextKey)) {
238
+ child = {};
239
+ } else {
240
+ child = [];
241
+ }
242
+
243
+ obj[key] = child;
244
+ }
245
+
246
+ obj = child;
247
+ }
248
+
249
+ if (path.length > 0 && isObject(obj)) {
250
+ const key = path[path.length - 1];
251
+
252
+ if (isSafeKey(key)) {
253
+ obj[key] = value;
254
+ }
255
+ }
256
+
257
+ return inputObj;
258
+ }
259
+
260
+ function zipObject(keys, values) {
261
+ const out = {};
262
+
263
+ for (let i = 0, l = keys.length; i < l; ++i) {
264
+ const key = keys[i];
265
+
266
+ if (isSafeKey(key)) {
267
+ out[key] = values[i];
268
+ }
269
+ }
270
+
271
+ return out;
272
+ }
273
+
274
+ function chunk(arr, chunkSize) {
275
+ const out = [];
276
+
277
+ for (let i = 0, l = arr.length; i < l; ++i) {
278
+ const item = arr[i];
279
+
280
+ if (out.length === 0 || out[out.length - 1].length === chunkSize) {
281
+ out.push([]);
282
+ }
283
+
284
+ out[out.length - 1].push(item);
285
+ }
286
+
287
+ return out;
288
+ }
289
+
290
+ function jsonEquals(val1, val2) {
291
+ return jsonEqualsBase(val1, val2, compareStrict);
292
+ }
293
+
294
+ function jsonEqualsBase(val1, val2, compare) {
295
+ if (val1 === val2) {
296
+ return true;
297
+ }
298
+
299
+ return jsonEqualsSlowPath(val1, val2, compare);
300
+ }
301
+
302
+ function jsonEqualsSlowPath(val1, val2, compare) {
303
+ const type1 = typeof val1;
304
+ const type2 = typeof val2;
305
+
306
+ const isNonNullObject1 = type1 === 'object' && !compare(val1, null);
307
+ const isNonNullObject2 = type2 === 'object' && !compare(val2, null);
308
+
309
+ if (isNonNullObject1 && isNonNullObject2) {
310
+ const isArray1 = Array.isArray(val1);
311
+ const isArray2 = Array.isArray(val2);
312
+
313
+ if (isArray1 && isArray2) {
314
+ return jsonEqualsArray(val1, val2, compare);
315
+ } else if (!isArray1 && !isArray2) {
316
+ return jsonEqualsObject(val1, val2, compare);
317
+ } else {
318
+ return false;
319
+ }
320
+ } else if (isNonNullObject1 !== isNonNullObject2) {
321
+ return false;
322
+ } else {
323
+ return compare(val1, val2);
324
+ }
325
+ }
326
+
327
+ function jsonEqualsArray(arr1, arr2, compare) {
328
+ if (arr1.length !== arr2.length) {
329
+ return false;
330
+ }
331
+
332
+ for (let i = 0, l = arr1.length; i < l; ++i) {
333
+ if (!jsonEqualsBase(arr1[i], arr2[i], compare)) {
334
+ return false;
335
+ }
336
+ }
337
+
338
+ return true;
339
+ }
340
+
341
+ function jsonEqualsObject(obj1, obj2, compare) {
342
+ if (obj1.constructor === Date && obj2.constructor === Date) {
343
+ return equalsDate(obj1, obj2);
344
+ }
345
+
346
+ const keys1 = Object.keys(obj1);
347
+ const keys2 = Object.keys(obj2);
348
+
349
+ if (keys1.length !== keys2.length) {
350
+ return false;
351
+ }
352
+
353
+ for (let i = 0, l = keys1.length; i < l; ++i) {
354
+ const key = keys1[i];
355
+
356
+ if (!jsonEqualsBase(obj1[key], obj2[key], compare)) {
357
+ return false;
358
+ }
359
+ }
360
+
361
+ return true;
362
+ }
363
+
364
+ function equalsDate(date1, date2) {
365
+ return date1.getTime() === date2.getTime();
366
+ }
367
+
368
+ function compareStrict(val1, val2) {
369
+ return val1 === val2;
370
+ }
371
+
372
+ function isSafeKey(key) {
373
+ return isNumber(key) || (isString(key) && key !== '__proto__');
374
+ }
375
+
376
+ function mergeMaps(map1, map2) {
377
+ const map = new Map(map1);
378
+
379
+ if (map2) {
380
+ for (const key of map2.keys()) {
381
+ map.set(key, map2.get(key));
382
+ }
383
+ }
384
+
385
+ return map;
386
+ }
387
+
388
+ module.exports = {
389
+ isEmpty,
390
+ isString,
391
+ isRegExp,
392
+ isObject,
393
+ isNumber,
394
+ isFunction,
395
+ jsonEquals,
396
+ isPlainObject,
397
+ difference,
398
+ upperFirst,
399
+ zipObject,
400
+ mergeMaps,
401
+ cloneDeep,
402
+ asSingle,
403
+ asArray,
404
+ flatten,
405
+ groupBy,
406
+ uniqBy,
407
+ values,
408
+ union,
409
+ chunk,
410
+ clone,
411
+ omit,
412
+ once,
413
+ last,
414
+ get,
415
+ set,
416
+ };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ const jsonFieldExpressionParser = require('../queryBuilder/parsers/jsonFieldExpressionParser');
4
+ const cache = new Map();
5
+
6
+ function parseFieldExpression(expr) {
7
+ let parsedExpr = cache.get(expr);
8
+
9
+ if (parsedExpr !== undefined) {
10
+ return parsedExpr;
11
+ } else {
12
+ parsedExpr = jsonFieldExpressionParser.parse(expr);
13
+ parsedExpr = preprocessParsedExpression(parsedExpr);
14
+
15
+ // We don't take a copy of the parsedExpr each time we
16
+ // use if from cache. Instead to make sure it's never
17
+ // mutated we deep-freeze it.
18
+ parsedExpr = freezeParsedExpr(parsedExpr);
19
+
20
+ cache.set(expr, parsedExpr);
21
+ return parsedExpr;
22
+ }
23
+ }
24
+
25
+ function preprocessParsedExpression(parsedExpr) {
26
+ const columnParts = parsedExpr.columnName.split('.').map((part) => part.trim());
27
+ parsedExpr.column = columnParts[columnParts.length - 1];
28
+
29
+ if (columnParts.length >= 2) {
30
+ parsedExpr.table = columnParts.slice(0, columnParts.length - 1).join('.');
31
+ } else {
32
+ parsedExpr.table = null;
33
+ }
34
+
35
+ return parsedExpr;
36
+ }
37
+
38
+ function freezeParsedExpr(parsedExpr) {
39
+ for (const access of parsedExpr.access) {
40
+ Object.freeze(access);
41
+ }
42
+
43
+ Object.freeze(parsedExpr.access);
44
+ Object.freeze(parsedExpr);
45
+
46
+ return parsedExpr;
47
+ }
48
+
49
+ module.exports = {
50
+ parseFieldExpression,
51
+ };
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ const { getDialect } = require('./knexUtils');
4
+
5
+ // Characters that force an element of a postgres text array literal to be
6
+ // double quoted: the array syntax characters, whitespace and control chars.
7
+ const ARRAY_ELEMENT_NEEDS_QUOTES = /[{}",\\\s\x00-\x1f\x7f]|^$|^null$/i;
8
+ // Characters that can't appear as-is inside a plain '...' string literal
9
+ // without depending on the `standard_conforming_strings` setting.
10
+ const NEEDS_ESCAPE_STRING = /[\\\x00-\x1f\x7f]/;
11
+ const POSTGRES_DIALECTS = ['postgresql', 'redshift'];
12
+ const MYSQL_DIALECTS = ['mysql', 'mysql2'];
13
+
14
+ /**
15
+ * Converts the `access` part of a parsed field expression into a postgres
16
+ * text array literal like `{a,b,1}`. Elements are quoted and escaped so that
17
+ * keys containing array syntax characters can't change the path.
18
+ */
19
+ function toPgTextArray(access) {
20
+ const elements = access.map((it) => {
21
+ if (it.type === 'array' && Number.isInteger(it.ref)) {
22
+ return String(it.ref);
23
+ }
24
+
25
+ const ref = String(it.ref);
26
+
27
+ if (ARRAY_ELEMENT_NEEDS_QUOTES.test(ref)) {
28
+ return `"${ref.replace(/[\\"]/g, '\\$&')}"`;
29
+ } else {
30
+ return ref;
31
+ }
32
+ });
33
+
34
+ return `{${elements.join(',')}}`;
35
+ }
36
+
37
+ /**
38
+ * Converts a string into a postgres string literal that is safe to embed
39
+ * into a knex raw query. Single quotes are doubled and `?` characters are
40
+ * escaped so that knex doesn't treat them as binding placeholders.
41
+ *
42
+ * If the string contains backslashes or control characters, an escape
43
+ * string literal `E'...'` with octal escapes is used. This way the result
44
+ * is the same regardless of `standard_conforming_strings` and no literal
45
+ * backslash ever ends up next to a `?` (knex would eat it).
46
+ */
47
+ function toPgStringLiteral(str) {
48
+ let sql = str.replace(/'/g, "''");
49
+
50
+ if (NEEDS_ESCAPE_STRING.test(sql)) {
51
+ sql = sql.replace(/[\\\x00-\x1f\x7f]/g, (char) => {
52
+ return '\\' + char.charCodeAt(0).toString(8).padStart(3, '0');
53
+ });
54
+
55
+ sql = `E'${sql}'`;
56
+ } else {
57
+ sql = `'${sql}'`;
58
+ }
59
+
60
+ return sql.replace(/\?/g, '\\?');
61
+ }
62
+
63
+ /**
64
+ * Converts the `access` part of a parsed field expression into a string
65
+ * literal that can be used as the right hand side of `#>`, `#>>` and as the
66
+ * path argument of `jsonb_set`.
67
+ */
68
+ function toPgJsonPathLiteral(access) {
69
+ return toPgStringLiteral(toPgTextArray(access));
70
+ }
71
+
72
+ /**
73
+ * Quotes a (possibly table qualified) column name like `Table.column` as
74
+ * `"Table"."column"` for postgres.
75
+ */
76
+ function toPgQuotedColumn(columnName) {
77
+ return columnName
78
+ .split('.')
79
+ .map((part) => `"${part.replace(/"/g, '""')}"`)
80
+ .join('.')
81
+ .replace(/\?/g, '\\?');
82
+ }
83
+
84
+ /**
85
+ * Returns the flavor of JSON SQL to generate for field expressions: `'postgres'`
86
+ * or `'mysql'`. Other databases throw, since postgres SQL is invalid at best and
87
+ * dangerous at worst there (on MySQL `#` starts a comment). `knex` can be null,
88
+ * when the query has no knex instance bound yet, in which case postgres is used.
89
+ */
90
+ function getJsonDialect(knex, expression) {
91
+ const dialect = knex ? getDialect(knex) : null;
92
+
93
+ if (dialect === null || POSTGRES_DIALECTS.includes(dialect)) {
94
+ return 'postgres';
95
+ } else if (MYSQL_DIALECTS.includes(dialect)) {
96
+ return 'mysql';
97
+ } else {
98
+ throw new Error(
99
+ `JSON field expressions are only supported on postgres and mysql. Tried to use "${expression}" with dialect "${dialect}".`,
100
+ );
101
+ }
102
+ }
103
+
104
+ module.exports = {
105
+ toPgTextArray,
106
+ toPgStringLiteral,
107
+ toPgJsonPathLiteral,
108
+ toPgQuotedColumn,
109
+ getJsonDialect,
110
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { isPromise } = require('./isPromise');
4
+
5
+ // Call `func` after `obj` has been resolved. Call `func` synchronously if
6
+ // `obj` is not a promise for performance reasons.
7
+ function after(obj, func) {
8
+ if (isPromise(obj)) {
9
+ return obj.then(func);
10
+ } else {
11
+ return func(obj);
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ after,
17
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { isPromise } = require('./isPromise');
4
+
5
+ // Return `returnValue` after `obj` has been resolved. Return `returnValue`
6
+ // synchronously if `obj` is not a promise for performance reasons.
7
+ function afterReturn(obj, returnValue) {
8
+ if (isPromise(obj)) {
9
+ return obj.then(() => returnValue);
10
+ } else {
11
+ return returnValue;
12
+ }
13
+ }
14
+
15
+ module.exports = {
16
+ afterReturn,
17
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { isPromise } = require('./isPromise');
4
+ const { after } = require('./after');
5
+ const { afterReturn } = require('./afterReturn');
6
+ const { mapAfterAllReturn } = require('./mapAfterAllReturn');
7
+ const { promiseMap } = require('./map');
8
+ const { promiseTry } = require('./try');
9
+
10
+ module.exports = {
11
+ isPromise,
12
+ after,
13
+ afterReturn,
14
+ mapAfterAllReturn,
15
+ map: promiseMap,
16
+ try: promiseTry,
17
+ };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const { isObject, isFunction } = require('../objectUtils');
4
+
5
+ function isPromise(obj) {
6
+ return isObject(obj) && isFunction(obj.then);
7
+ }
8
+
9
+ module.exports = {
10
+ isPromise,
11
+ };