@abedmurrar/objection 0.0.0-stage → 4.0.0-beta.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.
- package/LICENSE +23 -0
- package/README.md +105 -2
- package/lib/index.mjs +6 -0
- package/lib/initialize.js +11 -0
- package/lib/model/AjvValidator.js +278 -0
- package/lib/model/Model.js +772 -0
- package/lib/model/ModifierNotFoundError.js +10 -0
- package/lib/model/NotFoundError.js +19 -0
- package/lib/model/RelationDoesNotExistError.js +11 -0
- package/lib/model/ValidationError.js +46 -0
- package/lib/model/Validator.js +20 -0
- package/lib/model/getModel.js +7 -0
- package/lib/model/graph/ModelGraph.js +60 -0
- package/lib/model/graph/ModelGraphBuilder.js +188 -0
- package/lib/model/graph/ModelGraphEdge.js +40 -0
- package/lib/model/graph/ModelGraphNode.js +201 -0
- package/lib/model/inheritModel.js +19 -0
- package/lib/model/modelBindKnex.js +69 -0
- package/lib/model/modelClone.js +102 -0
- package/lib/model/modelColPropMap.js +24 -0
- package/lib/model/modelConcurrency.js +24 -0
- package/lib/model/modelId.js +57 -0
- package/lib/model/modelJsonAttributes.js +72 -0
- package/lib/model/modelParseRelations.js +83 -0
- package/lib/model/modelQueryProps.js +116 -0
- package/lib/model/modelSet.js +116 -0
- package/lib/model/modelTableMetadata.js +71 -0
- package/lib/model/modelToJson.js +157 -0
- package/lib/model/modelUtils.js +40 -0
- package/lib/model/modelValidate.js +40 -0
- package/lib/model/modelValues.js +113 -0
- package/lib/model/modelVisitor.js +34 -0
- package/lib/objection.js +89 -0
- package/lib/queryBuilder/FunctionBuilder.js +291 -0
- package/lib/queryBuilder/InternalOptions.js +24 -0
- package/lib/queryBuilder/JoinBuilder.js +124 -0
- package/lib/queryBuilder/QueryBuilder.js +1136 -0
- package/lib/queryBuilder/QueryBuilderBase.js +666 -0
- package/lib/queryBuilder/QueryBuilderContext.js +20 -0
- package/lib/queryBuilder/QueryBuilderContextBase.js +26 -0
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +484 -0
- package/lib/queryBuilder/QueryBuilderUserContext.js +25 -0
- package/lib/queryBuilder/RawBuilder.js +78 -0
- package/lib/queryBuilder/ReferenceBuilder.js +246 -0
- package/lib/queryBuilder/RelationExpression.js +373 -0
- package/lib/queryBuilder/StaticHookArguments.js +122 -0
- package/lib/queryBuilder/ValueBuilder.js +115 -0
- package/lib/queryBuilder/expressions.js +121 -0
- package/lib/queryBuilder/functions/mysql.js +762 -0
- package/lib/queryBuilder/graph/GraphAction.js +54 -0
- package/lib/queryBuilder/graph/GraphData.js +12 -0
- package/lib/queryBuilder/graph/GraphFetcher.js +155 -0
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +146 -0
- package/lib/queryBuilder/graph/GraphOperation.js +21 -0
- package/lib/queryBuilder/graph/GraphOptions.js +165 -0
- package/lib/queryBuilder/graph/GraphUpsert.js +231 -0
- package/lib/queryBuilder/graph/delete/GraphDelete.js +15 -0
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +56 -0
- package/lib/queryBuilder/graph/insert/GraphInsert.js +116 -0
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +183 -0
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +70 -0
- package/lib/queryBuilder/graph/patch/GraphPatch.js +15 -0
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +205 -0
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +26 -0
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +96 -0
- package/lib/queryBuilder/join/JoinResultColumn.js +19 -0
- package/lib/queryBuilder/join/JoinResultParser.js +106 -0
- package/lib/queryBuilder/join/RelationJoiner.js +258 -0
- package/lib/queryBuilder/join/TableNode.js +136 -0
- package/lib/queryBuilder/join/TableTree.js +69 -0
- package/lib/queryBuilder/join/utils.js +19 -0
- package/lib/queryBuilder/operations/DelegateOperation.js +101 -0
- package/lib/queryBuilder/operations/DeleteOperation.js +47 -0
- package/lib/queryBuilder/operations/FindByIdOperation.js +29 -0
- package/lib/queryBuilder/operations/FindByIdsOperation.js +23 -0
- package/lib/queryBuilder/operations/FindOperation.js +147 -0
- package/lib/queryBuilder/operations/FirstOperation.js +22 -0
- package/lib/queryBuilder/operations/FromOperation.js +91 -0
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +38 -0
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +35 -0
- package/lib/queryBuilder/operations/InsertGraphOperation.js +87 -0
- package/lib/queryBuilder/operations/InsertOperation.js +173 -0
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +37 -0
- package/lib/queryBuilder/operations/InstanceFindOperation.js +17 -0
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +20 -0
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +45 -0
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +83 -0
- package/lib/queryBuilder/operations/KnexOperation.js +11 -0
- package/lib/queryBuilder/operations/MergeOperation.js +43 -0
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +173 -0
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +23 -0
- package/lib/queryBuilder/operations/OnBuildOperation.js +23 -0
- package/lib/queryBuilder/operations/OnErrorOperation.js +23 -0
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +258 -0
- package/lib/queryBuilder/operations/RangeOperation.js +37 -0
- package/lib/queryBuilder/operations/RelateOperation.js +20 -0
- package/lib/queryBuilder/operations/ReturningOperation.js +24 -0
- package/lib/queryBuilder/operations/RunAfterOperation.js +23 -0
- package/lib/queryBuilder/operations/RunBeforeOperation.js +23 -0
- package/lib/queryBuilder/operations/UnrelateOperation.js +18 -0
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +63 -0
- package/lib/queryBuilder/operations/UpdateOperation.js +130 -0
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +35 -0
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +47 -0
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +48 -0
- package/lib/queryBuilder/operations/WhereInOperation.js +46 -0
- package/lib/queryBuilder/operations/eager/EagerOperation.js +46 -0
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +41 -0
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +10 -0
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +227 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +29 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +37 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +30 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +33 -0
- package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +155 -0
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +135 -0
- package/lib/queryBuilder/operations/select/SelectOperation.js +50 -0
- package/lib/queryBuilder/operations/select/Selection.js +112 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +84 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +90 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +95 -0
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +787 -0
- package/lib/queryBuilder/parsers/relationExpressionParser.js +930 -0
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +17 -0
- package/lib/queryBuilder/transformations/QueryTransformation.js +9 -0
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +57 -0
- package/lib/queryBuilder/transformations/index.js +9 -0
- package/lib/queryBuilder/whereScopes.js +199 -0
- package/lib/relations/Relation.js +317 -0
- package/lib/relations/RelationDeleteOperation.js +23 -0
- package/lib/relations/RelationFindOperation.js +116 -0
- package/lib/relations/RelationInsertOperation.js +25 -0
- package/lib/relations/RelationOwner.js +199 -0
- package/lib/relations/RelationProperty.js +207 -0
- package/lib/relations/RelationUpdateOperation.js +23 -0
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +18 -0
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +33 -0
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +39 -0
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +45 -0
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +46 -0
- package/lib/relations/hasMany/HasManyInsertOperation.js +45 -0
- package/lib/relations/hasMany/HasManyRelateOperation.js +48 -0
- package/lib/relations/hasMany/HasManyRelation.js +41 -0
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +26 -0
- package/lib/relations/hasOne/HasOneRelation.js +10 -0
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +10 -0
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +82 -0
- package/lib/relations/manyToMany/ManyToManyRelation.js +405 -0
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +29 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +8 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +20 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +8 -0
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +82 -0
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +40 -0
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +64 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +11 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +27 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +11 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +8 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +65 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +8 -0
- package/lib/transaction.js +66 -0
- package/lib/utils/assert.js +19 -0
- package/lib/utils/buildUtils.js +19 -0
- package/lib/utils/classUtils.js +9 -0
- package/lib/utils/cloneDeep.js +365 -0
- package/lib/utils/createModifier.js +37 -0
- package/lib/utils/deprecate.js +11 -0
- package/lib/utils/identifierMapping.js +188 -0
- package/lib/utils/internalPropUtils.js +7 -0
- package/lib/utils/knexUtils.js +81 -0
- package/lib/utils/mixin.js +18 -0
- package/lib/utils/mysqlJsonPath.js +70 -0
- package/lib/utils/normalizeIds.js +127 -0
- package/lib/utils/objectUtils.js +314 -0
- package/lib/utils/parseFieldExpression.js +73 -0
- package/lib/utils/postgresJsonPath.js +96 -0
- package/lib/utils/promiseUtils/after.js +14 -0
- package/lib/utils/promiseUtils/afterReturn.js +14 -0
- package/lib/utils/promiseUtils/index.js +15 -0
- package/lib/utils/promiseUtils/isPromise.js +8 -0
- package/lib/utils/promiseUtils/map.js +96 -0
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +23 -0
- package/lib/utils/promiseUtils/try.js +19 -0
- package/lib/utils/resolveModel.js +104 -0
- package/lib/utils/tmpColumnUtils.js +7 -0
- package/package.json +113 -4
- package/typings/objection/index.d.mts +362 -0
- package/typings/objection/index.d.ts +4131 -0
- package/typings/objection/relation-expression.d.ts +237 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.snakeCaseKeys = exports.camelCaseKeys = void 0;
|
|
4
|
+
exports.snakeCase = snakeCase;
|
|
5
|
+
exports.camelCase = camelCase;
|
|
6
|
+
exports.snakeCaseMappers = snakeCaseMappers;
|
|
7
|
+
exports.knexSnakeCaseMappers = knexSnakeCaseMappers;
|
|
8
|
+
exports.knexIdentifierMappers = knexIdentifierMappers;
|
|
9
|
+
exports.knexIdentifierMapping = knexIdentifierMapping;
|
|
10
|
+
const objectUtils_1 = require("./objectUtils");
|
|
11
|
+
// Super fast memoize for single argument functions.
|
|
12
|
+
function memoize(func) {
|
|
13
|
+
const cache = new Map();
|
|
14
|
+
return (input) => {
|
|
15
|
+
let output = cache.get(input);
|
|
16
|
+
if (output === undefined) {
|
|
17
|
+
output = func(input);
|
|
18
|
+
cache.set(input, output);
|
|
19
|
+
}
|
|
20
|
+
return output;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// camelCase to snake_case converter that also works with non-ascii characters
|
|
24
|
+
// This is needed especially so that aliases containing the `:` character,
|
|
25
|
+
// objection uses internally, work.
|
|
26
|
+
function snakeCase(str, { upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
|
|
27
|
+
if (str.length === 0) {
|
|
28
|
+
return str;
|
|
29
|
+
}
|
|
30
|
+
const upper = str.toUpperCase();
|
|
31
|
+
const lower = str.toLowerCase();
|
|
32
|
+
let out = lower[0];
|
|
33
|
+
for (let i = 1, l = str.length; i < l; ++i) {
|
|
34
|
+
const char = str[i];
|
|
35
|
+
const prevChar = str[i - 1];
|
|
36
|
+
const upperChar = upper[i];
|
|
37
|
+
const prevUpperChar = upper[i - 1];
|
|
38
|
+
const lowerChar = lower[i];
|
|
39
|
+
const prevLowerChar = lower[i - 1];
|
|
40
|
+
// If underScoreBeforeDigits is true then, well, insert an underscore
|
|
41
|
+
// before digits :). Only the first digit gets an underscore if
|
|
42
|
+
// there are multiple.
|
|
43
|
+
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
|
|
44
|
+
out += '_' + char;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Test if `char` is an upper-case character and that the character
|
|
48
|
+
// actually has different upper and lower case versions.
|
|
49
|
+
if (char === upperChar && upperChar !== lowerChar) {
|
|
50
|
+
const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
|
|
51
|
+
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
|
|
52
|
+
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
|
|
53
|
+
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
|
|
54
|
+
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
|
|
55
|
+
out += '_' + lowerChar;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
out += lowerChar;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
out += char;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (upperCase) {
|
|
66
|
+
return out.toUpperCase();
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// snake_case to camelCase converter that simply reverses
|
|
73
|
+
// the actions done by `snakeCase` function.
|
|
74
|
+
function camelCase(str, { upperCase = false } = {}) {
|
|
75
|
+
if (str.length === 0) {
|
|
76
|
+
return str;
|
|
77
|
+
}
|
|
78
|
+
if (upperCase && isAllUpperCaseSnakeCase(str)) {
|
|
79
|
+
// Only convert to lower case if the string is all upper
|
|
80
|
+
// case snake_case. This allowes camelCase strings to go
|
|
81
|
+
// through without changing.
|
|
82
|
+
str = str.toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
let out = str[0];
|
|
85
|
+
for (let i = 1, l = str.length; i < l; ++i) {
|
|
86
|
+
const char = str[i];
|
|
87
|
+
const prevChar = str[i - 1];
|
|
88
|
+
if (char !== '_') {
|
|
89
|
+
if (prevChar === '_') {
|
|
90
|
+
out += char.toUpperCase();
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
out += char;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
function isAllUpperCaseSnakeCase(str) {
|
|
100
|
+
for (let i = 1, l = str.length; i < l; ++i) {
|
|
101
|
+
const char = str[i];
|
|
102
|
+
if (char !== '_' && char !== char.toUpperCase()) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
function isDigit(char) {
|
|
109
|
+
return char >= '0' && char <= '9';
|
|
110
|
+
}
|
|
111
|
+
// Returns a function that splits the inputs string into pieces using `separator`,
|
|
112
|
+
// only calls `mapper` for the last part and concatenates the string back together.
|
|
113
|
+
// If no separators are found, `mapper` is called for the entire string.
|
|
114
|
+
function mapLastPart(mapper, separator) {
|
|
115
|
+
return (str) => {
|
|
116
|
+
if (!str)
|
|
117
|
+
return str;
|
|
118
|
+
const idx = str.lastIndexOf(separator);
|
|
119
|
+
const mapped = mapper(str.slice(idx + separator.length));
|
|
120
|
+
return str.slice(0, idx + separator.length) + mapped;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Returns a function that takes an object as an input and maps the object's keys
|
|
124
|
+
// using `mapper`. If the input is not an object, the input is returned unchanged.
|
|
125
|
+
function keyMapper(mapper) {
|
|
126
|
+
return (obj) => {
|
|
127
|
+
if (!(0, objectUtils_1.isObject)(obj) || Array.isArray(obj)) {
|
|
128
|
+
return obj;
|
|
129
|
+
}
|
|
130
|
+
const keys = Object.keys(obj);
|
|
131
|
+
const out = {};
|
|
132
|
+
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
133
|
+
const key = keys[i];
|
|
134
|
+
out[mapper(key)] = obj[key];
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function snakeCaseMappers(opt = {}) {
|
|
140
|
+
return {
|
|
141
|
+
parse: keyMapper(memoize((str) => camelCase(str, opt))),
|
|
142
|
+
format: keyMapper(memoize((str) => snakeCase(str, opt))),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function knexIdentifierMappers({ parse, format, idSeparator = ':', } = {}) {
|
|
146
|
+
// Without `parse` or `format`, the mappers throw when they're used, as they
|
|
147
|
+
// did in the JavaScript code.
|
|
148
|
+
const formatId = memoize(mapLastPart(format, idSeparator));
|
|
149
|
+
const parseId = memoize(mapLastPart(parse, idSeparator));
|
|
150
|
+
const parseKeys = keyMapper(parseId);
|
|
151
|
+
return {
|
|
152
|
+
wrapIdentifier(identifier, origWrap) {
|
|
153
|
+
return origWrap(formatId(identifier));
|
|
154
|
+
},
|
|
155
|
+
postProcessResponse(result) {
|
|
156
|
+
if (Array.isArray(result)) {
|
|
157
|
+
const output = new Array(result.length);
|
|
158
|
+
for (let i = 0, l = result.length; i < l; ++i) {
|
|
159
|
+
output[i] = parseKeys(result[i]);
|
|
160
|
+
}
|
|
161
|
+
return output;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
return parseKeys(result);
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function knexSnakeCaseMappers(opt = {}) {
|
|
170
|
+
return knexIdentifierMappers({
|
|
171
|
+
parse: (str) => camelCase(str, opt),
|
|
172
|
+
format: (str) => snakeCase(str, opt),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function knexIdentifierMapping(colToProp) {
|
|
176
|
+
const propToCol = Object.keys(colToProp).reduce((propToCol, column) => {
|
|
177
|
+
propToCol[colToProp[column]] = column;
|
|
178
|
+
return propToCol;
|
|
179
|
+
}, {});
|
|
180
|
+
return knexIdentifierMappers({
|
|
181
|
+
parse: (column) => colToProp[column] || column,
|
|
182
|
+
format: (prop) => propToCol[prop] || prop,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const camelCaseKeys = keyMapper(memoize(camelCase));
|
|
186
|
+
exports.camelCaseKeys = camelCaseKeys;
|
|
187
|
+
const snakeCaseKeys = keyMapper(memoize(snakeCase));
|
|
188
|
+
exports.snakeCaseKeys = snakeCaseKeys;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDialect = getDialect;
|
|
4
|
+
exports.isPostgres = isPostgres;
|
|
5
|
+
exports.isMySql = isMySql;
|
|
6
|
+
exports.isMariaDb = isMariaDb;
|
|
7
|
+
exports.getMariaDbVersion = getMariaDbVersion;
|
|
8
|
+
exports.isSqlite = isSqlite;
|
|
9
|
+
exports.isMsSql = isMsSql;
|
|
10
|
+
exports.isOracle = isOracle;
|
|
11
|
+
exports.isKnexQueryBuilder = isKnexQueryBuilder;
|
|
12
|
+
exports.isKnexJoinBuilder = isKnexJoinBuilder;
|
|
13
|
+
exports.isKnexRaw = isKnexRaw;
|
|
14
|
+
const objectUtils_1 = require("../utils/objectUtils");
|
|
15
|
+
function getDialect(knex) {
|
|
16
|
+
const type = typeof knex;
|
|
17
|
+
const knexLike = knex;
|
|
18
|
+
return ((knex !== null &&
|
|
19
|
+
(type === 'object' || type === 'function') &&
|
|
20
|
+
knexLike.client &&
|
|
21
|
+
knexLike.client.dialect) ||
|
|
22
|
+
null);
|
|
23
|
+
}
|
|
24
|
+
function isPostgres(knex) {
|
|
25
|
+
return getDialect(knex) === 'postgresql';
|
|
26
|
+
}
|
|
27
|
+
function isOracle(knex) {
|
|
28
|
+
const dialect = getDialect(knex);
|
|
29
|
+
return dialect === 'oracledb';
|
|
30
|
+
}
|
|
31
|
+
function isMySql(knex) {
|
|
32
|
+
const dialect = getDialect(knex);
|
|
33
|
+
return dialect === 'mysql' || dialect === 'mysql2';
|
|
34
|
+
}
|
|
35
|
+
// knex reports MariaDB as the `mysql` dialect. It's recognized from knex's
|
|
36
|
+
// `mariadb` client, or from a `version` like '11.4.0-MariaDB' in the knex config
|
|
37
|
+
// when the mysql2 driver is used. knex finds out about MariaDB itself only
|
|
38
|
+
// after connecting, which would build the first queries differently than the
|
|
39
|
+
// later ones, so that isn't used.
|
|
40
|
+
function isMariaDb(knex) {
|
|
41
|
+
if (!isMySql(knex)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// isMySql() returned true, so the client exists.
|
|
45
|
+
const client = knex.client;
|
|
46
|
+
return client.driverName === 'mariadb' || /mariadb/i.test(configVersion(client));
|
|
47
|
+
}
|
|
48
|
+
// The MariaDB version as [major, minor], when it's known from the knex config.
|
|
49
|
+
function getMariaDbVersion(knex) {
|
|
50
|
+
if (!isMariaDb(knex)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const match = /^(\d+)\.(\d+)/.exec(configVersion(knex.client));
|
|
54
|
+
return match ? [Number(match[1]), Number(match[2])] : null;
|
|
55
|
+
}
|
|
56
|
+
function configVersion(client) {
|
|
57
|
+
const version = client.config && client.config.version;
|
|
58
|
+
return typeof version === 'string' ? version : '';
|
|
59
|
+
}
|
|
60
|
+
function isSqlite(knex) {
|
|
61
|
+
return getDialect(knex) === 'sqlite3';
|
|
62
|
+
}
|
|
63
|
+
function isMsSql(knex) {
|
|
64
|
+
return getDialect(knex) === 'mssql';
|
|
65
|
+
}
|
|
66
|
+
function isKnexQueryBuilder(value) {
|
|
67
|
+
return (hasConstructor(value) &&
|
|
68
|
+
(0, objectUtils_1.isFunction)(value.select) &&
|
|
69
|
+
(0, objectUtils_1.isFunction)(value.column) &&
|
|
70
|
+
value.select === value.column &&
|
|
71
|
+
'client' in value);
|
|
72
|
+
}
|
|
73
|
+
function isKnexJoinBuilder(value) {
|
|
74
|
+
return hasConstructor(value) && value.grouping === 'join' && 'joinType' in value;
|
|
75
|
+
}
|
|
76
|
+
function isKnexRaw(value) {
|
|
77
|
+
return hasConstructor(value) && value.isRawInstance && 'client' in value;
|
|
78
|
+
}
|
|
79
|
+
function hasConstructor(value) {
|
|
80
|
+
return (0, objectUtils_1.isObject)(value) && (0, objectUtils_1.isFunction)(value.constructor);
|
|
81
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compose = compose;
|
|
4
|
+
exports.mixin = mixin;
|
|
5
|
+
const objectUtils_1 = require("./objectUtils");
|
|
6
|
+
function mixin(...mixinArgs) {
|
|
7
|
+
const args = (0, objectUtils_1.flatten)(mixinArgs);
|
|
8
|
+
const mixins = args.slice(1);
|
|
9
|
+
return mixins.reduce((Class, mixinFunc) => {
|
|
10
|
+
return mixinFunc(Class);
|
|
11
|
+
}, args[0]);
|
|
12
|
+
}
|
|
13
|
+
function compose(...composeArgs) {
|
|
14
|
+
const mixins = (0, objectUtils_1.flatten)(composeArgs);
|
|
15
|
+
return function (Class) {
|
|
16
|
+
return mixin(Class, mixins);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JSON_CAST = void 0;
|
|
4
|
+
exports.toMySqlJsonPath = toMySqlJsonPath;
|
|
5
|
+
exports.toMySqlCastType = toMySqlCastType;
|
|
6
|
+
exports.isBooleanType = isBooleanType;
|
|
7
|
+
exports.toJsonSql = toJsonSql;
|
|
8
|
+
exports.jsonCastsForDialect = jsonCastsForDialect;
|
|
9
|
+
const knexUtils_1 = require("./knexUtils");
|
|
10
|
+
// SQL types of `ReferenceBuilder` casts that MySQL's `CAST()` calls differently.
|
|
11
|
+
// `CAST(x AS integer)` for example is a syntax error on MySQL.
|
|
12
|
+
const MYSQL_CAST_TYPES = {
|
|
13
|
+
text: 'CHAR',
|
|
14
|
+
varchar: 'CHAR',
|
|
15
|
+
integer: 'SIGNED',
|
|
16
|
+
int: 'SIGNED',
|
|
17
|
+
smallint: 'SIGNED',
|
|
18
|
+
bigint: 'SIGNED',
|
|
19
|
+
float: 'FLOAT',
|
|
20
|
+
real: 'DOUBLE',
|
|
21
|
+
double: 'DOUBLE',
|
|
22
|
+
'double precision': 'DOUBLE',
|
|
23
|
+
decimal: 'DECIMAL(65,30)',
|
|
24
|
+
numeric: 'DECIMAL(65,30)',
|
|
25
|
+
json: 'JSON',
|
|
26
|
+
jsonb: 'JSON',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Converts the `access` part of a parsed field expression into a MySQL JSON
|
|
30
|
+
* path like `$."a"[1]."b.c"`. Keys are always quoted, so they can contain any
|
|
31
|
+
* characters. The path must be passed to MySQL as a binding.
|
|
32
|
+
*/
|
|
33
|
+
function toMySqlJsonPath(access) {
|
|
34
|
+
return ('$' +
|
|
35
|
+
access
|
|
36
|
+
.map((it) => {
|
|
37
|
+
if (it.type === 'array' && Number.isInteger(it.ref)) {
|
|
38
|
+
return `[${it.ref}]`;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return `.${JSON.stringify(String(it.ref))}`;
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
.join(''));
|
|
45
|
+
}
|
|
46
|
+
function toMySqlCastType(sqlType) {
|
|
47
|
+
return MYSQL_CAST_TYPES[sqlType.toLowerCase()] || sqlType;
|
|
48
|
+
}
|
|
49
|
+
function isBooleanType(sqlType) {
|
|
50
|
+
const type = sqlType.toLowerCase();
|
|
51
|
+
return type === 'boolean' || type === 'bool';
|
|
52
|
+
}
|
|
53
|
+
// The SQL that makes `sql` a JSON value. MariaDB has no JSON type to cast to:
|
|
54
|
+
// its JSON columns are text. `JSON_COMPACT()` returns the value as JSON, which
|
|
55
|
+
// `JSON_SET()` nests instead of storing a string, and in the compact form
|
|
56
|
+
// objection stores JSON in, so comparisons with columns work.
|
|
57
|
+
function toJsonSql(sql, knex) {
|
|
58
|
+
return (0, knexUtils_1.isMariaDb)(knex) ? `JSON_COMPACT(${sql})` : `CAST(${sql} AS JSON)`;
|
|
59
|
+
}
|
|
60
|
+
const JSON_CAST = 'CAST(? AS JSON)';
|
|
61
|
+
exports.JSON_CAST = JSON_CAST;
|
|
62
|
+
// For SQL that objection generates before the knex instance is known, like the
|
|
63
|
+
// conditions of the `whereJson*` methods: replaces `CAST(? AS JSON)` with
|
|
64
|
+
// `JSON_COMPACT(?)` on MariaDB. The values are always bindings, so the text
|
|
65
|
+
// only contains what objection generated.
|
|
66
|
+
function jsonCastsForDialect(sql, knex) {
|
|
67
|
+
return (0, knexUtils_1.isMariaDb)(knex) && sql.includes(JSON_CAST)
|
|
68
|
+
? sql.split(JSON_CAST).join('JSON_COMPACT(?)')
|
|
69
|
+
: sql;
|
|
70
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeIds = normalizeIds;
|
|
4
|
+
const objectUtils_1 = require("../utils/objectUtils");
|
|
5
|
+
function normalizeIds(ids, prop, opt) {
|
|
6
|
+
opt = opt || {};
|
|
7
|
+
const isComposite = prop.size > 1;
|
|
8
|
+
let ret;
|
|
9
|
+
if (isComposite) {
|
|
10
|
+
// For composite ids these are okay:
|
|
11
|
+
//
|
|
12
|
+
// 1. [1, 'foo', 4]
|
|
13
|
+
// 2. {a: 1, b: 'foo', c: 4}
|
|
14
|
+
// 3. [[1, 'foo', 4], [4, 'bar', 1]]
|
|
15
|
+
// 4. [{a: 1, b: 'foo', c: 4}, {a: 4, b: 'bar', c: 1}]
|
|
16
|
+
//
|
|
17
|
+
if (Array.isArray(ids)) {
|
|
18
|
+
if (Array.isArray(ids[0])) {
|
|
19
|
+
ret = new Array(ids.length);
|
|
20
|
+
// 3.
|
|
21
|
+
for (let i = 0, l = ids.length; i < l; ++i) {
|
|
22
|
+
ret[i] = convertIdArrayToObject(ids[i], prop);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if ((0, objectUtils_1.isObject)(ids[0])) {
|
|
26
|
+
ret = new Array(ids.length);
|
|
27
|
+
// 4.
|
|
28
|
+
for (let i = 0, l = ids.length; i < l; ++i) {
|
|
29
|
+
ret[i] = ensureObject(ids[i]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// 1.
|
|
34
|
+
ret = [convertIdArrayToObject(ids, prop)];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if ((0, objectUtils_1.isObject)(ids)) {
|
|
38
|
+
// 2.
|
|
39
|
+
ret = [ids];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw new Error(`invalid composite key ${JSON.stringify(ids)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// For non-composite ids, these are okay:
|
|
47
|
+
//
|
|
48
|
+
// 1. 1
|
|
49
|
+
// 2. {id: 1}
|
|
50
|
+
// 3. [1, 'foo', 4]
|
|
51
|
+
// 4. [{id: 1}, {id: 'foo'}, {id: 4}]
|
|
52
|
+
//
|
|
53
|
+
if (Array.isArray(ids)) {
|
|
54
|
+
if ((0, objectUtils_1.isObject)(ids[0])) {
|
|
55
|
+
ret = new Array(ids.length);
|
|
56
|
+
// 4.
|
|
57
|
+
for (let i = 0, l = ids.length; i < l; ++i) {
|
|
58
|
+
ret[i] = ensureObject(ids[i]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
ret = new Array(ids.length);
|
|
63
|
+
// 3.
|
|
64
|
+
for (let i = 0, l = ids.length; i < l; ++i) {
|
|
65
|
+
ret[i] = {};
|
|
66
|
+
prop.setProp(ret[i], 0, ids[i]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if ((0, objectUtils_1.isObject)(ids)) {
|
|
71
|
+
// 2.
|
|
72
|
+
ret = [ids];
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// 1.
|
|
76
|
+
const obj = {};
|
|
77
|
+
prop.setProp(obj, 0, ids);
|
|
78
|
+
ret = [obj];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
checkProperties(ret, prop);
|
|
82
|
+
if (opt.arrayOutput) {
|
|
83
|
+
return normalizedToArray(ret, prop);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return ret;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function convertIdArrayToObject(ids, prop) {
|
|
90
|
+
if (!Array.isArray(ids)) {
|
|
91
|
+
throw new Error(`invalid composite key ${JSON.stringify(ids)}`);
|
|
92
|
+
}
|
|
93
|
+
if (ids.length != prop.size) {
|
|
94
|
+
throw new Error(`composite identifier ${JSON.stringify(ids)} should have ${prop.size} values`);
|
|
95
|
+
}
|
|
96
|
+
const obj = {};
|
|
97
|
+
for (let i = 0; i < ids.length; ++i) {
|
|
98
|
+
prop.setProp(obj, i, ids[i]);
|
|
99
|
+
}
|
|
100
|
+
return obj;
|
|
101
|
+
}
|
|
102
|
+
function ensureObject(ids) {
|
|
103
|
+
if ((0, objectUtils_1.isObject)(ids)) {
|
|
104
|
+
return ids;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
throw new Error(`invalid composite key ${JSON.stringify(ids)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function checkProperties(ret, prop) {
|
|
111
|
+
for (let i = 0, l = ret.length; i < l; ++i) {
|
|
112
|
+
const obj = ret[i];
|
|
113
|
+
for (let j = 0, lp = prop.size; j < lp; ++j) {
|
|
114
|
+
const val = prop.getProp(obj, j);
|
|
115
|
+
if (typeof val === 'undefined') {
|
|
116
|
+
throw new Error(`expected id ${JSON.stringify(obj)} to have property ${prop.propDescription(j)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function normalizedToArray(ret, prop) {
|
|
122
|
+
const arr = new Array(ret.length);
|
|
123
|
+
for (let i = 0, l = ret.length; i < l; ++i) {
|
|
124
|
+
arr[i] = prop.getProps(ret[i]);
|
|
125
|
+
}
|
|
126
|
+
return arr;
|
|
127
|
+
}
|