@autofleet/sheilta 1.0.0-beta-test-4 → 1.0.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/lib/formatter/index.js +9 -222
- package/lib/formatter/index.js.map +1 -0
- package/lib/formatter/index.test.js +10 -259
- package/lib/formatter/index.test.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/lib/middleware/index.js +11 -57
- package/lib/middleware/index.js.map +1 -0
- package/lib/operators/index.js +5 -26
- package/lib/operators/index.js.map +1 -0
- package/lib/utils.js +3 -32
- package/lib/utils.js.map +1 -0
- package/lib/validations/index.js +22 -84
- package/lib/validations/index.js.map +1 -0
- package/lib/validations/index.test.js +23 -176
- package/lib/validations/index.test.js.map +1 -0
- package/package.json +9 -29
- package/lib/formatter/index.d.ts +0 -48
- package/lib/formatter/index.test.d.ts +0 -1
- package/lib/index.d.ts +0 -3
- package/lib/middleware/index.d.ts +0 -16
- package/lib/operators/index.d.ts +0 -20
- package/lib/utils.d.ts +0 -14
- package/lib/validations/index.d.ts +0 -10
- package/lib/validations/index.test.d.ts +0 -1
package/lib/formatter/index.js
CHANGED
|
@@ -1,228 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
-
const common_types_1 = require("@autofleet/common-types");
|
|
3
|
+
exports.formatOrder = void 0;
|
|
9
4
|
const utils_1 = require("../utils");
|
|
10
|
-
const operators_1 = require("../operators");
|
|
11
|
-
const DEFAULT_ORDER = 'id';
|
|
12
5
|
const DESCENDING_KEY = 'DESC';
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return
|
|
6
|
+
exports.formatOrder = ({ order = [], }) => order.map((o) => {
|
|
7
|
+
const isOrderDescOrder = utils_1.isOrderDesc(o);
|
|
8
|
+
let column = o;
|
|
9
|
+
if (isOrderDescOrder) {
|
|
10
|
+
column = utils_1.extractAttributeNameFromOrder(o);
|
|
11
|
+
return [column, DESCENDING_KEY];
|
|
19
12
|
}
|
|
20
|
-
return
|
|
21
|
-
operator: operators_1.OPERATORS_TO_SQL[operator],
|
|
22
|
-
value: conditionValue,
|
|
23
|
-
}));
|
|
24
|
-
};
|
|
25
|
-
const getAttributeFromOrder = (order, options = {}) => {
|
|
26
|
-
const { literalAttributes = [], DBFormatter = undefined } = options;
|
|
27
|
-
const [formattedOrder, attributes] = order.reduce((acc, o) => {
|
|
28
|
-
const [item, orderStyle = 'ASC'] = Array.isArray(o) ? o : [o];
|
|
29
|
-
const found = literalAttributes === null || literalAttributes === void 0 ? void 0 : literalAttributes.find(obj => obj.attribute === item);
|
|
30
|
-
if (found) {
|
|
31
|
-
acc[1].push(found.literal);
|
|
32
|
-
acc[0].push([DBFormatter ? DBFormatter(`"${found.attribute}" ${orderStyle}`) : `${found.attribute} ${orderStyle}`]);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
acc[0].push(o);
|
|
36
|
-
}
|
|
37
|
-
return acc;
|
|
38
|
-
}, [[], []]);
|
|
39
|
-
return [formattedOrder, attributes];
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Generates replacements for the given conditions.
|
|
43
|
-
*
|
|
44
|
-
* @param conditions - The conditions to generate replacements for.
|
|
45
|
-
* @returns The replacements object.
|
|
46
|
-
*/
|
|
47
|
-
exports.generateFilterReplacements = (conditions) => {
|
|
48
|
-
const replacements = {};
|
|
49
|
-
Object.entries(conditions).forEach(([key, condition]) => {
|
|
50
|
-
const replacementKey = utils_1.generateRandomString();
|
|
51
|
-
// eslint-disable-next-line prefer-destructuring
|
|
52
|
-
replacements[replacementKey] = key.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];
|
|
53
|
-
if (Array.isArray(condition)) {
|
|
54
|
-
condition.forEach((value) => {
|
|
55
|
-
const valueKey = utils_1.generateRandomString();
|
|
56
|
-
replacements[valueKey] = typeof value === 'string' ? value : value.value;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
else if (typeof condition === 'string' || typeof condition === 'number') {
|
|
60
|
-
const conditionKey = utils_1.generateRandomString();
|
|
61
|
-
replacements[conditionKey] = condition;
|
|
62
|
-
}
|
|
63
|
-
else if (condition === null || condition === void 0 ? void 0 : condition.operator) {
|
|
64
|
-
const operatorKey = utils_1.generateRandomString();
|
|
65
|
-
replacements[operatorKey] = condition.value;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
return replacements;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Generates replacements for the given order array.
|
|
72
|
-
*
|
|
73
|
-
* @param order - The order array to generate replacements for.
|
|
74
|
-
* @returns The replacements object.
|
|
75
|
-
*/
|
|
76
|
-
exports.generateOrderReplacements = (order) => {
|
|
77
|
-
const replacementMap = {};
|
|
78
|
-
order.forEach((o) => {
|
|
79
|
-
if (o.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {
|
|
80
|
-
const rand = utils_1.generateRandomString();
|
|
81
|
-
// eslint-disable-next-line prefer-destructuring
|
|
82
|
-
replacementMap[rand] = o.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];
|
|
83
|
-
}
|
|
84
|
-
else if (o.substring(1).startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {
|
|
85
|
-
const rand = utils_1.generateRandomString();
|
|
86
|
-
// eslint-disable-next-line prefer-destructuring
|
|
87
|
-
replacementMap[rand] = o.substring(1).split(CUSTOM_FIELDS_QUERY_PREFIX)[1];
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
return replacementMap;
|
|
91
|
-
};
|
|
92
|
-
/**
|
|
93
|
-
* Creates a combined replacement map from order and query.
|
|
94
|
-
*
|
|
95
|
-
* @param order - The order array.
|
|
96
|
-
* @param query - The query object.
|
|
97
|
-
* @returns The combined replacements object.
|
|
98
|
-
*/
|
|
99
|
-
const createReplacementMap = (order, query) => (Object.assign(Object.assign({}, exports.generateOrderReplacements(order)), exports.generateFilterReplacements(query)));
|
|
100
|
-
const formatOrder = ({ order, associationModels = [], replacementsMap = {}, }) => {
|
|
101
|
-
const formattedOrders = [];
|
|
102
|
-
const orderScopesMap = new Map();
|
|
103
|
-
order.forEach((o) => {
|
|
104
|
-
if ([o, o.substring(1)].some(t => t.startsWith(CUSTOM_FIELDS_QUERY_PREFIX))) {
|
|
105
|
-
if (!orderScopesMap.has(CUSTOM_FIELDS_SORT_SCOPE)) {
|
|
106
|
-
orderScopesMap.set(CUSTOM_FIELDS_SORT_SCOPE, {});
|
|
107
|
-
}
|
|
108
|
-
const scopeKey = o.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];
|
|
109
|
-
orderScopesMap.get(CUSTOM_FIELDS_SORT_SCOPE)[scopeKey] = (utils_1.isOrderDesc(o) ?
|
|
110
|
-
DESCENDING_KEY :
|
|
111
|
-
ASCENDING_KEY);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const formattedOrder = [utils_1.extractAttributeNameFromOrder(o, associationModels)];
|
|
115
|
-
const isOrderDescOrder = utils_1.isOrderDesc(o);
|
|
116
|
-
const isOrderAssociation = utils_1.isAttributeByAssociation(isOrderDescOrder
|
|
117
|
-
? o.split(utils_1.ORDER_PREFIX)[1]
|
|
118
|
-
: o, associationModels);
|
|
119
|
-
if (isOrderAssociation) {
|
|
120
|
-
formattedOrder.push(utils_1.extractAssociatedAttributeNameFromOrder(o));
|
|
121
|
-
}
|
|
122
|
-
if (isOrderDescOrder) {
|
|
123
|
-
formattedOrder.push(DESCENDING_KEY);
|
|
124
|
-
}
|
|
125
|
-
formattedOrders.push(formattedOrder);
|
|
126
|
-
});
|
|
127
|
-
return {
|
|
128
|
-
formattedOrders,
|
|
129
|
-
replacementsMap,
|
|
130
|
-
orderScopes: Array.from(orderScopesMap.entries()).map(([scopeName, scopeValue]) => {
|
|
131
|
-
if (!scopeValue) {
|
|
132
|
-
return scopeName;
|
|
133
|
-
}
|
|
134
|
-
return {
|
|
135
|
-
method: [scopeName, {
|
|
136
|
-
replacementsMap,
|
|
137
|
-
scopeValue,
|
|
138
|
-
}],
|
|
139
|
-
};
|
|
140
|
-
}),
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
const formatPage = page => page || utils_1.PAGE_DEFAULT;
|
|
144
|
-
const formatPerPage = perPage => perPage || utils_1.PER_PAGE_DEFAULT;
|
|
145
|
-
const formatInclude = (include, associationsMap = {}) => {
|
|
146
|
-
let formattedInclude = include.map((i) => {
|
|
147
|
-
var _a;
|
|
148
|
-
const includedAssociation = associationsMap[typeof i === 'string' ? i : (i.association || i.model)];
|
|
149
|
-
return Object.assign(Object.assign(Object.assign({}, i), { association: includedAssociation, required: i.required !== false }), (i.include && {
|
|
150
|
-
include: formatInclude(i.include, (_a = includedAssociation === null || includedAssociation === void 0 ? void 0 : includedAssociation.target) === null || _a === void 0 ? void 0 : _a.associations),
|
|
151
|
-
}));
|
|
152
|
-
});
|
|
153
|
-
formattedInclude = formattedInclude.map(i => lodash_1.default.omit(i, ['model']));
|
|
154
|
-
return formattedInclude;
|
|
155
|
-
};
|
|
156
|
-
const formatQuery = (query, associationModels, replacementsMap) => {
|
|
157
|
-
const formattedQuery = {};
|
|
158
|
-
const formattedScopeMap = new Map();
|
|
159
|
-
Object.entries(query).forEach(([queryItemKey, queryItemValue]) => {
|
|
160
|
-
if (queryItemKey.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {
|
|
161
|
-
if (!formattedScopeMap.has(CUSTOM_FIELDS_FILTER_SCOPE)) {
|
|
162
|
-
formattedScopeMap.set(CUSTOM_FIELDS_FILTER_SCOPE, {});
|
|
163
|
-
}
|
|
164
|
-
const scopeKey = queryItemKey.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];
|
|
165
|
-
formattedScopeMap.get(CUSTOM_FIELDS_FILTER_SCOPE)[scopeKey] =
|
|
166
|
-
parseCustomFieldScopeQueryValue(queryItemValue);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
const key = utils_1.isAttributeByAssociation(queryItemKey, associationModels)
|
|
170
|
-
? utils_1.wrapAttributeWithOperator(queryItemKey)
|
|
171
|
-
: queryItemKey;
|
|
172
|
-
formattedQuery[key] = queryItemValue;
|
|
173
|
-
});
|
|
174
|
-
const formattedScopes = Array.from(formattedScopeMap.entries()).map(([scopeName, scopeValue]) => {
|
|
175
|
-
if (!scopeValue) {
|
|
176
|
-
return scopeName;
|
|
177
|
-
}
|
|
178
|
-
return {
|
|
179
|
-
method: [scopeName, {
|
|
180
|
-
replacementsMap,
|
|
181
|
-
scopeValue,
|
|
182
|
-
}],
|
|
183
|
-
};
|
|
184
|
-
});
|
|
185
|
-
return {
|
|
186
|
-
formattedQuery,
|
|
187
|
-
formattedScopes,
|
|
188
|
-
};
|
|
189
|
-
};
|
|
190
|
-
const formatSearchTerm = (searchTerm, attributesToSend, rawAttributes) => ({
|
|
191
|
-
$and: searchTerm.split(' ').map(term => ({
|
|
192
|
-
$or: attributesToSend.filter(attrKey => rawAttributes[attrKey].type.key === 'STRING').map(attr => ({
|
|
193
|
-
[attr]: {
|
|
194
|
-
$iLike: `%${term}%`,
|
|
195
|
-
},
|
|
196
|
-
})),
|
|
197
|
-
})),
|
|
13
|
+
return [column];
|
|
198
14
|
});
|
|
199
|
-
|
|
200
|
-
const replacementsMap = createReplacementMap(order, query);
|
|
201
|
-
const associationModels = Object.keys((model === null || model === void 0 ? void 0 : model.associations) || {});
|
|
202
|
-
const { formattedOrders, orderScopes } = formatOrder({
|
|
203
|
-
order: [...order, DEFAULT_ORDER],
|
|
204
|
-
associationModels,
|
|
205
|
-
replacementsMap,
|
|
206
|
-
});
|
|
207
|
-
const [filteredFormattedOrder, filteredLiteralAttributes] = getAttributeFromOrder(formattedOrders, options);
|
|
208
|
-
const allAttributes = [...filteredLiteralAttributes, ...(attributes || [])];
|
|
209
|
-
const formattedAttribute = (attributes === null || attributes === void 0 ? void 0 : attributes.length) ? allAttributes : { include: allAttributes };
|
|
210
|
-
const formattedInclude = formatInclude(include, model === null || model === void 0 ? void 0 : model.associations);
|
|
211
|
-
const formattedPage = formatPage(page);
|
|
212
|
-
const formattedPerPage = formatPerPage(perPage);
|
|
213
|
-
const result = formatQuery(query, associationModels, replacementsMap);
|
|
214
|
-
const queryScopes = result.formattedScopes;
|
|
215
|
-
let { formattedQuery } = result;
|
|
216
|
-
if (searchTerm && !(options === null || options === void 0 ? void 0 : options.skipSearchTermFormat)) {
|
|
217
|
-
const attributesToSend = (attributes === null || attributes === void 0 ? void 0 : attributes.length) ? attributes : Object.keys(model.rawAttributes);
|
|
218
|
-
const queryWithSearchTerm = formatSearchTerm(searchTerm, attributesToSend, model.rawAttributes);
|
|
219
|
-
formattedQuery = lodash_1.default.isEmpty(formattedQuery) ? queryWithSearchTerm : {
|
|
220
|
-
$and: [
|
|
221
|
-
formattedQuery,
|
|
222
|
-
queryWithSearchTerm,
|
|
223
|
-
],
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
return Object.assign({ query: formattedQuery, order: filteredFormattedOrder, page: formattedPage, perPage: formattedPerPage, include: formattedInclude, scopes: [...queryScopes, ...orderScopes] }, (formattedAttribute && { attributes: formattedAttribute }));
|
|
227
|
-
};
|
|
228
|
-
exports.default = formatPayload;
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatter/index.ts"],"names":[],"mappings":";;;AAAA,oCAAsE;AAEtE,MAAM,cAAc,GAAG,MAAM,CAAC;AAIjB,QAAA,WAAW,GAAG,CAAC,EAC1B,KAAK,GAAG,EAAE,GACX,EAAoB,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAS,EAAkB,EAAE;IAC9D,MAAM,gBAAgB,GAAG,mBAAW,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,gBAAgB,EAAE;QACpB,MAAM,GAAG,qCAA6B,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;KACjC;IAED,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,267 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const _1 =
|
|
3
|
+
const _1 = require(".");
|
|
7
4
|
describe('formatting test', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
order: [],
|
|
12
|
-
query: {
|
|
13
|
-
'json.field': {
|
|
14
|
-
$gt: 4,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
}, {
|
|
18
|
-
rawAttributes: {
|
|
19
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', json: '',
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
expect(JSON.stringify(query)).toBe(JSON.stringify({ 'json.field': { $gt: 4 } }));
|
|
23
|
-
});
|
|
24
|
-
it('query included model field', () => {
|
|
25
|
-
const { query } = _1.default({
|
|
26
|
-
order: [],
|
|
27
|
-
query: {
|
|
28
|
-
'status.field': {
|
|
29
|
-
$gt: 4,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
}, {
|
|
33
|
-
rawAttributes: {
|
|
34
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
35
|
-
},
|
|
36
|
-
associations: {
|
|
37
|
-
status: {},
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
expect(JSON.stringify(query)).toBe(JSON.stringify({ '$status.field$': { $gt: 4 } }));
|
|
41
|
-
});
|
|
42
|
-
it('query with searchTerm', () => {
|
|
43
|
-
const searchTerm = 'aviv';
|
|
44
|
-
const { query } = _1.default({
|
|
45
|
-
order: [],
|
|
46
|
-
query: {
|
|
47
|
-
'json.field': {
|
|
48
|
-
$gt: 4,
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
searchTerm,
|
|
52
|
-
}, {
|
|
53
|
-
rawAttributes: {
|
|
54
|
-
startTime: {
|
|
55
|
-
type: {
|
|
56
|
-
key: 'STRING',
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
endTime: {
|
|
60
|
-
type: {
|
|
61
|
-
key: 'NUMBER',
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
expect(JSON.stringify(query)).toBe(JSON.stringify({
|
|
67
|
-
$and: [{ 'json.field': { $gt: 4 } }, {
|
|
68
|
-
$and: [{
|
|
69
|
-
$or: [
|
|
70
|
-
{
|
|
71
|
-
startTime: {
|
|
72
|
-
$iLike: `%${searchTerm}%`,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
}],
|
|
77
|
-
}],
|
|
78
|
-
}));
|
|
79
|
-
});
|
|
80
|
-
it('query with searchTerm with spaces', () => {
|
|
81
|
-
const searchTerm = 'aviv good guy';
|
|
82
|
-
const splitSearch = searchTerm.split(' ');
|
|
83
|
-
const { query } = _1.default({
|
|
84
|
-
order: [],
|
|
85
|
-
query: {
|
|
86
|
-
'json.field': {
|
|
87
|
-
$gt: 4,
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
searchTerm,
|
|
91
|
-
}, {
|
|
92
|
-
rawAttributes: {
|
|
93
|
-
startTime: {
|
|
94
|
-
type: {
|
|
95
|
-
key: 'STRING',
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
endTime: {
|
|
99
|
-
type: {
|
|
100
|
-
key: 'NUMBER',
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
expect(JSON.stringify(query)).toBe(JSON.stringify({
|
|
106
|
-
$and: [{ 'json.field': { $gt: 4 } }, {
|
|
107
|
-
$and: [{
|
|
108
|
-
$or: [
|
|
109
|
-
{
|
|
110
|
-
startTime: {
|
|
111
|
-
$iLike: `%${splitSearch[0]}%`,
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
],
|
|
115
|
-
}, {
|
|
116
|
-
$or: [{
|
|
117
|
-
startTime: {
|
|
118
|
-
$iLike: `%${splitSearch[1]}%`,
|
|
119
|
-
},
|
|
120
|
-
}],
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
$or: [{
|
|
124
|
-
startTime: {
|
|
125
|
-
$iLike: `%${splitSearch[2]}%`,
|
|
126
|
-
},
|
|
127
|
-
}],
|
|
128
|
-
}],
|
|
129
|
-
}],
|
|
130
|
-
}));
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
describe('order formatting', () => {
|
|
134
|
-
it('simple check', () => {
|
|
135
|
-
const { order } = _1.default({
|
|
136
|
-
order: ['startTime', '-endTime'],
|
|
137
|
-
});
|
|
138
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['startTime'], ['endTime', 'DESC'], ['id']]));
|
|
139
|
-
});
|
|
140
|
-
it('simple check asc', () => {
|
|
141
|
-
const { order } = _1.default({
|
|
142
|
-
order: ['startTime', 'endTime'],
|
|
143
|
-
});
|
|
144
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['startTime'], ['endTime'], ['id']]));
|
|
145
|
-
});
|
|
146
|
-
it('by included model', () => {
|
|
147
|
-
const { order } = _1.default({
|
|
148
|
-
order: ['status.name'],
|
|
149
|
-
}, {
|
|
150
|
-
rawAttributes: {
|
|
151
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
152
|
-
},
|
|
153
|
-
associations: {
|
|
154
|
-
status: {},
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['status', 'name'], ['id']]));
|
|
158
|
-
});
|
|
159
|
-
it('by included model descending', () => {
|
|
160
|
-
const { order } = _1.default({
|
|
161
|
-
order: ['-status.name'],
|
|
162
|
-
}, {
|
|
163
|
-
rawAttributes: {
|
|
164
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
165
|
-
},
|
|
166
|
-
associations: {
|
|
167
|
-
status: {},
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['status', 'name', 'DESC'], ['id']]));
|
|
171
|
-
});
|
|
172
|
-
it('by json field', () => {
|
|
173
|
-
const { order } = _1.default({
|
|
174
|
-
order: ['status.name'],
|
|
175
|
-
}, {
|
|
176
|
-
rawAttributes: {
|
|
177
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', json: '',
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['status.name'], ['id']]));
|
|
181
|
-
});
|
|
182
|
-
it('by json field descending', () => {
|
|
183
|
-
const { order } = _1.default({
|
|
184
|
-
order: ['-status.name'],
|
|
185
|
-
}, {
|
|
186
|
-
rawAttributes: {
|
|
187
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', json: '',
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([['status.name', 'DESC'], ['id']]));
|
|
191
|
-
});
|
|
192
|
-
it('by literal field ascending', () => {
|
|
193
|
-
const literalAttribute = { attribute: 'genericField', literal: [{ 0: e => `${e}0` }] };
|
|
194
|
-
const { order, attributes } = _1.default({
|
|
195
|
-
order: [literalAttribute.attribute],
|
|
196
|
-
}, {
|
|
197
|
-
rawAttributes: {
|
|
198
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
199
|
-
},
|
|
200
|
-
}, {
|
|
201
|
-
literalAttributes: [literalAttribute],
|
|
202
|
-
});
|
|
203
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([[`${literalAttribute.attribute} ASC`], ['id']]));
|
|
204
|
-
expect(JSON.stringify(attributes))
|
|
205
|
-
.toBe(JSON.stringify({ include: [literalAttribute.literal] }));
|
|
206
|
-
});
|
|
207
|
-
it('by literal field descending', () => {
|
|
208
|
-
const literalAttribute = { attribute: 'genericField', literal: ['void', 'field'] };
|
|
209
|
-
const { order, attributes } = _1.default({
|
|
210
|
-
order: [`-${literalAttribute.attribute}`, 'currencySymbol'],
|
|
211
|
-
attributes: ['endTime'],
|
|
212
|
-
}, {
|
|
213
|
-
rawAttributes: {
|
|
214
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
215
|
-
},
|
|
216
|
-
}, {
|
|
217
|
-
literalAttributes: [literalAttribute],
|
|
218
|
-
});
|
|
219
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([[`${literalAttribute.attribute} DESC`], ['currencySymbol'], ['id']]));
|
|
220
|
-
expect(JSON.stringify(attributes))
|
|
221
|
-
.toBe(JSON.stringify([[literalAttribute.literal[0], literalAttribute.literal[1]], 'endTime']));
|
|
222
|
-
});
|
|
223
|
-
it('by literal field - not found', () => {
|
|
224
|
-
const literalAttribute = { attribute: 'genericField', literal: 'void' };
|
|
225
|
-
const { order, attributes } = _1.default({
|
|
226
|
-
order: [`-O${literalAttribute.attribute}`],
|
|
227
|
-
}, {
|
|
228
|
-
rawAttributes: {
|
|
229
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
230
|
-
},
|
|
231
|
-
}, {
|
|
232
|
-
literalAttributes: [literalAttribute],
|
|
233
|
-
});
|
|
234
|
-
expect(JSON.stringify(order)).toBe(JSON.stringify([[`O${literalAttribute.attribute}`, 'DESC'], ['id']]));
|
|
235
|
-
expect(JSON.stringify(attributes)).toBe(JSON.stringify({ include: [] }));
|
|
5
|
+
it('check order formatting', () => {
|
|
6
|
+
const payload = _1.formatOrder({
|
|
7
|
+
order: ['startTime', '-endTime'],
|
|
236
8
|
});
|
|
9
|
+
expect(JSON.stringify(payload)).toBe(JSON.stringify([['startTime'], ['endTime', 'DESC']]));
|
|
237
10
|
});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
order: [],
|
|
242
|
-
include: [{
|
|
243
|
-
model: 'status',
|
|
244
|
-
}],
|
|
245
|
-
}, {
|
|
246
|
-
associations: {
|
|
247
|
-
status: {},
|
|
248
|
-
},
|
|
249
|
-
});
|
|
250
|
-
expect(include[0].required).toBe(true);
|
|
251
|
-
});
|
|
252
|
-
it('include required should be false', () => {
|
|
253
|
-
const { include } = _1.default({
|
|
254
|
-
order: [],
|
|
255
|
-
include: [{
|
|
256
|
-
model: 'status',
|
|
257
|
-
required: false,
|
|
258
|
-
}],
|
|
259
|
-
}, {
|
|
260
|
-
associations: {
|
|
261
|
-
status: {},
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
expect(include[0].required).toBe(false);
|
|
11
|
+
it('check order formatting', () => {
|
|
12
|
+
const payload = _1.formatOrder({
|
|
13
|
+
order: ['startTime', 'endTime'],
|
|
265
14
|
});
|
|
15
|
+
expect(JSON.stringify(payload)).toBe(JSON.stringify([['startTime'], ['endTime']]));
|
|
266
16
|
});
|
|
267
17
|
});
|
|
18
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/formatter/index.test.ts"],"names":[],"mappings":";;AAAA,wBAAgC;AAEhC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,OAAO,GAAG,cAAW,CAAC;YAC1B,KAAK,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC;SACjC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,OAAO,GAAG,cAAW,CAAC;YAC1B,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -6,3 +6,4 @@ Object.defineProperty(exports, "formatOperators", { enumerable: true, get: funct
|
|
|
6
6
|
const middleware_1 = require("./middleware");
|
|
7
7
|
Object.defineProperty(exports, "queryFormatMiddleware", { enumerable: true, get: function () { return middleware_1.queryFormatMiddleware; } });
|
|
8
8
|
Object.defineProperty(exports, "queryValidationMiddleware", { enumerable: true, get: function () { return middleware_1.queryValidationMiddleware; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA8C;AAO5C,gGAPO,2BAAe,OAOP;AANjB,6CAGsB;AAIpB,sGANA,kCAAqB,OAMA;AACrB,0GANA,sCAAyB,OAMA"}
|
package/lib/middleware/index.js
CHANGED
|
@@ -8,41 +8,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.queryFormatMiddleware = exports.queryValidationMiddleware =
|
|
12
|
+
exports.queryFormatMiddleware = exports.queryValidationMiddleware = void 0;
|
|
16
13
|
const errors_1 = require("@autofleet/errors");
|
|
17
|
-
const
|
|
18
|
-
const formatter_1 = __importDefault(require("../formatter"));
|
|
14
|
+
const formatter_1 = require("../formatter");
|
|
19
15
|
const validations_1 = require("../validations");
|
|
20
|
-
|
|
21
|
-
query
|
|
22
|
-
attributes: joi_1.array().items(joi_1.string()),
|
|
23
|
-
order: joi_1.array().items(joi_1.string()),
|
|
24
|
-
page: joi_1.number(),
|
|
25
|
-
perPage: joi_1.number(),
|
|
26
|
-
include: joi_1.array().items(joi_1.any()),
|
|
27
|
-
searchTerm: joi_1.string(),
|
|
28
|
-
enrichments: joi_1.array().items(joi_1.string()),
|
|
29
|
-
});
|
|
30
|
-
exports.newQueryValidationMiddleware = (inner = 'body') => (model, options = {}) => (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
-
const { query, attributes, order, page, perPage, include, enrichments, } = req[inner];
|
|
16
|
+
exports.queryValidationMiddleware = model => (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
const { query, attributes, order, } = req.body;
|
|
32
18
|
try {
|
|
33
|
-
const result = querySchema.validate(req[inner]);
|
|
34
|
-
if (result.error) {
|
|
35
|
-
throw new errors_1.BadRequest([result.error], null);
|
|
36
|
-
}
|
|
37
19
|
validations_1.validatePayload({
|
|
38
20
|
query,
|
|
39
21
|
attributes,
|
|
40
22
|
order,
|
|
41
|
-
|
|
42
|
-
perPage,
|
|
43
|
-
include,
|
|
44
|
-
enrichments,
|
|
45
|
-
}, model, options);
|
|
23
|
+
}, model);
|
|
46
24
|
return next();
|
|
47
25
|
}
|
|
48
26
|
catch (error) {
|
|
@@ -57,36 +35,12 @@ exports.newQueryValidationMiddleware = (inner = 'body') => (model, options = {})
|
|
|
57
35
|
});
|
|
58
36
|
}
|
|
59
37
|
});
|
|
60
|
-
exports.
|
|
61
|
-
const { order,
|
|
62
|
-
const
|
|
63
|
-
query,
|
|
38
|
+
exports.queryFormatMiddleware = () => (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const { order, } = req.body;
|
|
40
|
+
const formattedOrder = formatter_1.formatOrder({
|
|
64
41
|
order,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
include,
|
|
68
|
-
attributes,
|
|
69
|
-
searchTerm,
|
|
70
|
-
}, model, options);
|
|
71
|
-
req[inner].query = formattedQuery;
|
|
72
|
-
req[inner].order = formattedOrder;
|
|
73
|
-
req[inner].attributes = formattedAttribute;
|
|
74
|
-
req[inner].page = formattedPage;
|
|
75
|
-
req[inner].perPage = formattedPerPage;
|
|
76
|
-
req[inner].include = formattedInclude;
|
|
77
|
-
req[inner].scopes = formattedScopes;
|
|
78
|
-
if (options.includeRawPayload) {
|
|
79
|
-
req[inner].rawPayload = {
|
|
80
|
-
order,
|
|
81
|
-
page,
|
|
82
|
-
perPage,
|
|
83
|
-
include,
|
|
84
|
-
query,
|
|
85
|
-
attributes,
|
|
86
|
-
searchTerm,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
42
|
+
});
|
|
43
|
+
req.body.order = formattedOrder;
|
|
89
44
|
return next();
|
|
90
45
|
});
|
|
91
|
-
|
|
92
|
-
exports.queryFormatMiddleware = exports.newQueryFormatMiddleware();
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAgD;AAChD,4CAA2C;AAC3C,gDAAiD;AAEpC,QAAA,yBAAyB,GAAG,KAAK,CAAC,EAAE,CAAC,CAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAgB,EAAE;IACvF,MAAM,EACJ,KAAK,EACL,UAAU,EACV,KAAK,GACN,GAAG,GAAG,CAAC,IAAI,CAAC;IAEb,IAAI;QACF,6BAAe,CAAC;YACd,KAAK;YACL,UAAU;YACV,KAAK;SACN,EAAE,KAAK,CAAC,CAAC;QAEV,OAAO,IAAI,EAAE,CAAC;KACf;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,oBAAW,CAAC,KAAK,EAAE,GAAG,EAAE;YAC7B,OAAO,EAAE,2BAA2B;YACpC,OAAO,EAAE;gBACP,KAAK;gBACL,KAAK;gBACL,UAAU;gBACV,KAAK;aACN;SACF,CAAC,CAAC;KACJ;AACH,CAAC,CAAA,CAAC;AAGW,QAAA,qBAAqB,GAAG,GAAG,EAAE,CAAC,CAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAgB,EAAE;IAChF,MAAM,EACJ,KAAK,GACN,GAAG,GAAG,CAAC,IAAI,CAAC;IAEb,MAAM,cAAc,GAAG,uBAAW,CAAC;QACjC,KAAK;KACN,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC;IAChC,OAAO,IAAI,EAAE,CAAC;AAChB,CAAC,CAAA,CAAC"}
|
package/lib/operators/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatOperators = exports.
|
|
3
|
+
exports.formatOperators = exports.OPERATOR_PREFIX = exports.OPERATORS = void 0;
|
|
4
4
|
exports.OPERATORS = [
|
|
5
5
|
'eq',
|
|
6
6
|
'ne',
|
|
@@ -13,37 +13,16 @@ exports.OPERATORS = [
|
|
|
13
13
|
'notIn',
|
|
14
14
|
'is',
|
|
15
15
|
'like',
|
|
16
|
-
'iLike',
|
|
17
16
|
'notLike',
|
|
18
17
|
'between',
|
|
19
18
|
'and',
|
|
20
19
|
'or',
|
|
21
|
-
'overlap',
|
|
22
|
-
'contains',
|
|
23
20
|
];
|
|
24
21
|
exports.OPERATOR_PREFIX = '$';
|
|
25
|
-
exports.OPERATORS_TO_SQL = {
|
|
26
|
-
$eq: '=',
|
|
27
|
-
$ne: '!=',
|
|
28
|
-
$gte: '>=',
|
|
29
|
-
$gt: '>',
|
|
30
|
-
$lte: '<=',
|
|
31
|
-
$lt: '<',
|
|
32
|
-
$not: 'NOT',
|
|
33
|
-
$in: 'IN',
|
|
34
|
-
$notIn: 'NOT IN',
|
|
35
|
-
$is: 'IS',
|
|
36
|
-
$like: 'LIKE',
|
|
37
|
-
$iLike: 'ILIKE',
|
|
38
|
-
$notLike: 'NOT LIKE',
|
|
39
|
-
$and: 'AND',
|
|
40
|
-
$or: 'OR',
|
|
41
|
-
};
|
|
42
22
|
exports.formatOperators = (Sequelize) => {
|
|
43
23
|
const { Op } = Sequelize;
|
|
44
|
-
return exports.OPERATORS.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return map;
|
|
48
|
-
}, {});
|
|
24
|
+
return exports.OPERATORS.map(o => ({
|
|
25
|
+
[`${exports.OPERATOR_PREFIX + o}`]: Op[o],
|
|
26
|
+
}));
|
|
49
27
|
};
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/operators/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,SAAS,GAAG;IACvB,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,OAAO;IACP,IAAI;IACJ,MAAM;IACN,SAAS;IACT,SAAS;IACT,KAAK;IACL,IAAI;CACL,CAAC;AAEW,QAAA,eAAe,GAAG,GAAG,CAAC;AAEtB,QAAA,eAAe,GAAG,CAAC,SAAS,EAAE,EAAE;IAC3C,MAAM,EAAE,EAAE,EAAE,GAAG,SAAS,CAAC;IACzB,OAAO,iBAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzB,CAAC,GAAG,uBAAe,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;KAClC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC"}
|
package/lib/utils.js
CHANGED
|
@@ -1,36 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const errors_1 = require("@autofleet/errors");
|
|
5
|
-
const operators_1 = require("./operators");
|
|
6
|
-
const randomInt = max => Math.floor(Math.random() * Math.floor(max));
|
|
3
|
+
exports.isOrderDesc = exports.extractAttributeNameFromOrder = exports.ORDER_PREFIX = void 0;
|
|
7
4
|
exports.ORDER_PREFIX = '-';
|
|
8
|
-
exports.
|
|
9
|
-
exports.PER_PAGE_DEFAULT = 20;
|
|
10
|
-
exports.PAGE_DEFAULT = 1;
|
|
11
|
-
exports.PER_PAGE_MAX_LIMIT = 100;
|
|
12
|
-
exports.PER_PAGE_MIN_LIMIT = 1;
|
|
13
|
-
exports.PAGE_MIN = 1;
|
|
14
|
-
exports.wrapAttributeWithOperator = attribute => `${operators_1.OPERATOR_PREFIX}${attribute}${operators_1.OPERATOR_PREFIX}`;
|
|
15
|
-
exports.isAttributeByAssociation = (attributeName, associatedModels) => attributeName.includes(exports.ASSOCIATION_PREFIX)
|
|
16
|
-
&& associatedModels.includes(attributeName.split(exports.ASSOCIATION_PREFIX)[0]);
|
|
17
|
-
exports.extractAttributeNameFromOrder = (order, associationModels) => {
|
|
18
|
-
let formattedOrder = order;
|
|
19
|
-
if (order.includes(exports.ORDER_PREFIX)) {
|
|
20
|
-
// eslint-disable-next-line prefer-destructuring
|
|
21
|
-
formattedOrder = formattedOrder.split(exports.ORDER_PREFIX)[1];
|
|
22
|
-
}
|
|
23
|
-
if (exports.isAttributeByAssociation(formattedOrder, associationModels)) {
|
|
24
|
-
[formattedOrder] = formattedOrder.split(exports.ASSOCIATION_PREFIX);
|
|
25
|
-
}
|
|
26
|
-
return formattedOrder;
|
|
27
|
-
};
|
|
5
|
+
exports.extractAttributeNameFromOrder = (order) => order.split(exports.ORDER_PREFIX)[1];
|
|
28
6
|
exports.isOrderDesc = (order) => order.includes(exports.ORDER_PREFIX);
|
|
29
|
-
|
|
30
|
-
throw new errors_1.BadRequest([{ message }], null);
|
|
31
|
-
};
|
|
32
|
-
exports.extractAssociatedAttributeNameFromOrder = (order) => order.split(exports.ASSOCIATION_PREFIX)[1];
|
|
33
|
-
exports.generateRandomString = (length = 5) => {
|
|
34
|
-
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
35
|
-
return Array.from({ length }, () => characters.charAt(randomInt(characters.length))).join('');
|
|
36
|
-
};
|
|
7
|
+
//# sourceMappingURL=utils.js.map
|
package/lib/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG,GAAG,CAAC;AAEnB,QAAA,6BAA6B,GAAG,CAAC,KAAK,EAAU,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,QAAA,WAAW,GAAG,CAAC,KAAK,EAAW,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAY,CAAC,CAAC"}
|
package/lib/validations/index.js
CHANGED
|
@@ -4,108 +4,56 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.validatePayload = void 0;
|
|
7
|
+
const errors_1 = require("@autofleet/errors");
|
|
7
8
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
9
|
const utils_1 = require("../utils");
|
|
9
10
|
const operators_1 = require("../operators");
|
|
10
11
|
const validateOperator = (operator) => operators_1.OPERATORS.includes(operator.split(operators_1.OPERATOR_PREFIX)[1]);
|
|
11
|
-
const validateQueryAttribute = (attribute, modelAttributes
|
|
12
|
-
|
|
13
|
-
? attribute.split(utils_1.ASSOCIATION_PREFIX)[0] : attribute);
|
|
14
|
-
const validateSingleOrder = (currentOrder, rawAttributes, associationModels, options = {}) => {
|
|
15
|
-
var _a, _b;
|
|
12
|
+
const validateQueryAttribute = (attribute, modelAttributes) => modelAttributes.includes(attribute);
|
|
13
|
+
const validateSingleOrder = (currentOrder, rawAttributes) => {
|
|
16
14
|
const isOrderDescOrder = utils_1.isOrderDesc(currentOrder);
|
|
17
15
|
if (isOrderDescOrder && currentOrder[0] !== utils_1.ORDER_PREFIX) {
|
|
18
|
-
|
|
16
|
+
throw new errors_1.BadRequest(`${utils_1.ORDER_PREFIX} must be only at the beginning of the word`, null);
|
|
19
17
|
}
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!isOrderAssociation && formattedOrderString.includes(utils_1.ASSOCIATION_PREFIX)) {
|
|
26
|
-
[formattedOrderString] = formattedOrderString.split(utils_1.ASSOCIATION_PREFIX);
|
|
27
|
-
}
|
|
28
|
-
if (!(rawAttributes.includes(formattedOrderString) || isOrderAssociation || isLiteralAttribute)) {
|
|
29
|
-
utils_1.throwBadRequestError(`${currentOrder} is invalid. isLiteralAttribute: ${isLiteralAttribute}`);
|
|
18
|
+
const formattedOrderString = isOrderDescOrder ?
|
|
19
|
+
utils_1.extractAttributeNameFromOrder(currentOrder) :
|
|
20
|
+
currentOrder;
|
|
21
|
+
if (!rawAttributes.includes(formattedOrderString)) {
|
|
22
|
+
throw new errors_1.BadRequest(`${currentOrder} is invalid`, null);
|
|
30
23
|
}
|
|
31
24
|
};
|
|
32
25
|
const validateSingleAttribute = (currentAttribute, rawAttributes) => {
|
|
33
26
|
if (!rawAttributes.includes(currentAttribute)) {
|
|
34
|
-
|
|
27
|
+
throw new errors_1.BadRequest(`${currentAttribute} is invalid`, null);
|
|
35
28
|
}
|
|
36
29
|
};
|
|
37
|
-
const validateOrderAttributes = (order, rawAttributes
|
|
38
|
-
order.map(o => validateSingleOrder(o, rawAttributes
|
|
30
|
+
const validateOrderAttributes = (order, rawAttributes) => {
|
|
31
|
+
order.map(o => validateSingleOrder(o, rawAttributes));
|
|
39
32
|
};
|
|
40
33
|
const validateAttributes = (attributes, rawAttributes) => {
|
|
41
34
|
attributes.map(a => validateSingleAttribute(a, rawAttributes));
|
|
42
35
|
};
|
|
43
|
-
const
|
|
44
|
-
if (!(enrichments === null || enrichments === void 0 ? void 0 : enrichments.length)) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const invalidEnrichment = enrichments
|
|
48
|
-
.find(enrichment => { var _a; return !((_a = options === null || options === void 0 ? void 0 : options.enrichmentAttributes) === null || _a === void 0 ? void 0 : _a.includes(enrichment)); });
|
|
49
|
-
if (invalidEnrichment) {
|
|
50
|
-
utils_1.throwBadRequestError(`enrichment attribute ${invalidEnrichment} is invalid`);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const validateQueryPayload = (query, rawAttributes, associationModels = []) => {
|
|
36
|
+
const validateQueryPayload = (query, rawAttributes) => {
|
|
54
37
|
// eslint-disable-next-line array-callback-return
|
|
55
38
|
Object.keys(query).map((key) => {
|
|
56
39
|
const value = query[key];
|
|
57
|
-
if (
|
|
40
|
+
if (lodash_1.default.isArray(value)) {
|
|
58
41
|
if (lodash_1.default.isObject(value[0])) {
|
|
59
|
-
value.map(v => validateQueryPayload(v, rawAttributes
|
|
42
|
+
value.map(v => validateQueryPayload(v, rawAttributes));
|
|
60
43
|
}
|
|
61
44
|
}
|
|
62
|
-
else if (validateOperator(key)
|
|
63
|
-
|| validateQueryAttribute(key, rawAttributes, associationModels)) {
|
|
45
|
+
else if (validateOperator(key) || validateQueryAttribute(key, rawAttributes)) {
|
|
64
46
|
if (lodash_1.default.isObject(value)) {
|
|
65
47
|
validateQueryPayload(value, rawAttributes);
|
|
66
48
|
}
|
|
67
49
|
}
|
|
68
50
|
else {
|
|
69
|
-
|
|
51
|
+
throw new errors_1.BadRequest(`invalid key: ${key}`, null);
|
|
70
52
|
}
|
|
71
53
|
});
|
|
72
54
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
utils_1.throwBadRequestError('Page must be greater than 0');
|
|
76
|
-
}
|
|
77
|
-
if (perPage > utils_1.PER_PAGE_MAX_LIMIT || perPage < utils_1.PER_PAGE_MIN_LIMIT) {
|
|
78
|
-
utils_1.throwBadRequestError(`PerPage must be between ${utils_1.PER_PAGE_MIN_LIMIT} to ${utils_1.PER_PAGE_MAX_LIMIT}`);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const validateIncludePayload = (include, associations) => {
|
|
82
|
-
const associationsKeys = Object.keys(associations);
|
|
83
|
-
include.forEach((i) => {
|
|
84
|
-
var _a;
|
|
85
|
-
validateQueryAttribute(i.model, associationsKeys);
|
|
86
|
-
const target = (_a = associations[i.model]) === null || _a === void 0 ? void 0 : _a.target;
|
|
87
|
-
if (!target) {
|
|
88
|
-
utils_1.throwBadRequestError('model not found in associations');
|
|
89
|
-
}
|
|
90
|
-
const { rawAttributes } = target;
|
|
91
|
-
const attributeKeys = Object.keys(rawAttributes);
|
|
92
|
-
if (i.where) {
|
|
93
|
-
validateQueryPayload(i.where, attributeKeys);
|
|
94
|
-
}
|
|
95
|
-
if (i.order) {
|
|
96
|
-
validateOrderAttributes(i.order, attributeKeys);
|
|
97
|
-
}
|
|
98
|
-
if (i.attributes) {
|
|
99
|
-
validateAttributes(i.attributes, attributeKeys);
|
|
100
|
-
}
|
|
101
|
-
if (!lodash_1.default.isNil(i.required) && !lodash_1.default.isBoolean(i.required)) {
|
|
102
|
-
utils_1.throwBadRequestError('include.required must be a boolean');
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
exports.validatePayload = ({ query = {}, order = [], attributes = [], include = [], page = utils_1.PAGE_DEFAULT, perPage = utils_1.PER_PAGE_DEFAULT, enrichments = [], }, model, options = {}) => {
|
|
107
|
-
const rawAttributes = Object.keys(model.rawAttributes);
|
|
108
|
-
const associationModels = Object.keys((model === null || model === void 0 ? void 0 : model.associations) || {});
|
|
55
|
+
exports.validatePayload = ({ query = {}, order = [], attributes = [], }, model) => {
|
|
56
|
+
const { rawAttributes } = model;
|
|
109
57
|
if (!attributes || attributes.length === 0) {
|
|
110
58
|
// eslint-disable-next-line no-param-reassign
|
|
111
59
|
attributes = rawAttributes;
|
|
@@ -113,18 +61,8 @@ exports.validatePayload = ({ query = {}, order = [], attributes = [], include =
|
|
|
113
61
|
else {
|
|
114
62
|
validateAttributes(attributes, rawAttributes);
|
|
115
63
|
}
|
|
116
|
-
validateOrderAttributes(order, rawAttributes
|
|
117
|
-
validateQueryPayload(query, rawAttributes
|
|
118
|
-
validateEnrichments(enrichments, options);
|
|
119
|
-
if (include.length && typeof include === 'object') {
|
|
120
|
-
validateIncludePayload(include, model === null || model === void 0 ? void 0 : model.associations);
|
|
121
|
-
}
|
|
122
|
-
else if (include && typeof include !== 'object') {
|
|
123
|
-
utils_1.throwBadRequestError('include must be an array');
|
|
124
|
-
}
|
|
125
|
-
validatePagination({
|
|
126
|
-
page,
|
|
127
|
-
perPage,
|
|
128
|
-
});
|
|
64
|
+
validateOrderAttributes(order, rawAttributes);
|
|
65
|
+
validateQueryPayload(query, rawAttributes);
|
|
129
66
|
return true;
|
|
130
67
|
};
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validations/index.ts"],"names":[],"mappings":";;;;;;AAAA,8CAA+C;AAC/C,oDAAuB;AACvB,oCAAoF;AACpF,4CAA0D;AAG1D,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAW,EAAE,CACrD,qBAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,2BAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD,MAAM,sBAAsB,GACxB,CAAC,SAAiB,EAAE,eAAyB,EAAW,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEnG,MAAM,mBAAmB,GAAG,CAAC,YAAoB,EAAE,aAAuB,EAAQ,EAAE;IAClF,MAAM,gBAAgB,GAAG,mBAAW,CAAC,YAAY,CAAC,CAAC;IACnD,IAAI,gBAAgB,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,oBAAY,EAAE;QACxD,MAAM,IAAI,mBAAU,CAAC,GAAG,oBAAY,4CAA4C,EAAE,IAAI,CAAC,CAAC;KACzF;IAED,MAAM,oBAAoB,GAC1B,gBAAgB,CAAC,CAAC;QAChB,qCAA6B,CAAC,YAAY,CAAC,CAAC,CAAC;QAC7C,YAAY,CAAC;IAEf,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE;QACjD,MAAM,IAAI,mBAAU,CAAC,GAAG,YAAY,aAAa,EAAE,IAAI,CAAC,CAAC;KAC1D;AACH,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,gBAAwB,EAAE,aAAuB,EAAQ,EAAE;IAC1F,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAC7C,MAAM,IAAI,mBAAU,CAAC,GAAG,gBAAgB,aAAa,EAAE,IAAI,CAAC,CAAC;KAC9D;AACH,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,KAAe,EAAE,aAAuB,EAAQ,EAAE;IACjF,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;AACxD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,UAAoB,EAAE,aAAuB,EAAQ,EAAE;IACjF,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;AACjE,CAAC,CAAC;AAGF,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,aAAa,EAAQ,EAAE;IAC1D,iDAAiD;IACjD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,gBAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACpB,IAAI,gBAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;gBACxB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;aACxD;SACF;aAAM,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,sBAAsB,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE;YAC9E,IAAI,gBAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;gBACrB,oBAAoB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;aAC5C;SACF;aAAM;YACL,MAAM,IAAI,mBAAU,CAAC,gBAAgB,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;SACnD;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAGW,QAAA,eAAe,GAAG,CAAC,EAC9B,KAAK,GAAG,EAAE,EACV,KAAK,GAAG,EAAE,EACV,UAAU,GAAG,EAAE,GAChB,EAAE,KAAK,EAAW,EAAE;IACnB,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;QAC1C,6CAA6C;QAC7C,UAAU,GAAG,aAAa,CAAC;KAC5B;SAAM;QACL,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;KAC/C;IAED,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC9C,oBAAoB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -38,182 +38,29 @@ const query = {
|
|
|
38
38
|
};
|
|
39
39
|
const order = ['startTime', '-endTime'];
|
|
40
40
|
describe('validations test', () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
rawAttributes: {
|
|
45
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
expect(payload).toBe(true);
|
|
49
|
-
});
|
|
50
|
-
it('check query by json property field', () => {
|
|
51
|
-
const payload = _1.validatePayload({
|
|
52
|
-
query: {
|
|
53
|
-
'jsonField.exampleField': {
|
|
54
|
-
$eq: 'a',
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
}, {
|
|
58
|
-
rawAttributes: {
|
|
59
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', jsonField: {},
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
expect(payload).toBe(true);
|
|
63
|
-
});
|
|
64
|
-
it('check query by included model field', () => {
|
|
65
|
-
const payload = _1.validatePayload({
|
|
66
|
-
query: {
|
|
67
|
-
'status.name': {
|
|
68
|
-
$eq: 'a',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
}, {
|
|
72
|
-
rawAttributes: {
|
|
73
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
74
|
-
},
|
|
75
|
-
associations: {
|
|
76
|
-
status: {},
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
expect(payload).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it('check query by non existent field', () => {
|
|
82
|
-
try {
|
|
83
|
-
_1.validatePayload({
|
|
84
|
-
query: {
|
|
85
|
-
nonExistent: {
|
|
86
|
-
$eq: 'a',
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
}, {
|
|
90
|
-
rawAttributes: {
|
|
91
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
expect(error.statusCode).toBe(400);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
41
|
+
it('check query validation', () => {
|
|
42
|
+
const payload = _1.validatePayload({ query }, { rawAttributes: ['startTime', 'endTime', 'currencySymbol', 'currencyCode', 'startStationId'] });
|
|
43
|
+
expect(payload).toBe(true);
|
|
99
44
|
});
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
it('prefix in the wrong place', () => {
|
|
122
|
-
try {
|
|
123
|
-
_1.validatePayload({ order: ['startTime-', 'currencySymbol'] }, {
|
|
124
|
-
rawAttributes: {
|
|
125
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
expect(error.statusCode).toBe(400);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
it('order by included model', () => {
|
|
134
|
-
const payload = _1.validatePayload({ order: ['status.title'] }, {
|
|
135
|
-
rawAttributes: {
|
|
136
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
137
|
-
},
|
|
138
|
-
associations: {
|
|
139
|
-
status: {},
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
expect(payload).toBe(true);
|
|
143
|
-
});
|
|
144
|
-
it('order by included model descending', () => {
|
|
145
|
-
const payload = _1.validatePayload({ order: ['-status.title'] }, {
|
|
146
|
-
rawAttributes: {
|
|
147
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
|
|
148
|
-
},
|
|
149
|
-
associations: {
|
|
150
|
-
status: {},
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
expect(payload).toBe(true);
|
|
154
|
-
});
|
|
155
|
-
it('order by json field', () => {
|
|
156
|
-
const payload = _1.validatePayload({ order: ['status.title'] }, {
|
|
157
|
-
rawAttributes: {
|
|
158
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
expect(payload).toBe(true);
|
|
162
|
-
});
|
|
163
|
-
it('order by json field desc', () => {
|
|
164
|
-
const payload = _1.validatePayload({ order: ['-status.title'] }, {
|
|
165
|
-
rawAttributes: {
|
|
166
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
expect(payload).toBe(true);
|
|
170
|
-
});
|
|
171
|
-
it('try order by json field that doesnt exist', () => {
|
|
172
|
-
try {
|
|
173
|
-
_1.validatePayload({ order: ['-stas.title'] }, {
|
|
174
|
-
rawAttributes: {
|
|
175
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
176
|
-
},
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
expect(error.statusCode).toBe(400);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
it('try order by literal field that exist', () => {
|
|
184
|
-
const literalAttribute = { attribute: 'genericField', literal: 'void' };
|
|
185
|
-
const payload = _1.validatePayload({ order: [literalAttribute.attribute] }, {
|
|
186
|
-
rawAttributes: {
|
|
187
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
188
|
-
},
|
|
189
|
-
}, {
|
|
190
|
-
literalAttributes: [literalAttribute],
|
|
191
|
-
});
|
|
192
|
-
expect(payload).toBe(true);
|
|
193
|
-
});
|
|
194
|
-
it('try order by literal field that exist - desc', () => {
|
|
195
|
-
const literalAttribute = { attribute: 'genericField', literal: 'void' };
|
|
196
|
-
const payload = _1.validatePayload({ order: [`-${literalAttribute.attribute}`] }, {
|
|
197
|
-
rawAttributes: {
|
|
198
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
199
|
-
},
|
|
200
|
-
}, {
|
|
201
|
-
literalAttributes: [literalAttribute],
|
|
202
|
-
});
|
|
203
|
-
expect(payload).toBe(true);
|
|
204
|
-
});
|
|
205
|
-
it('try order by literal field that doesnt exist', () => {
|
|
206
|
-
const literalAttribute = { attribute: 'genericField', literal: 'void' };
|
|
207
|
-
try {
|
|
208
|
-
_1.validatePayload({ order: ['here'] }, {
|
|
209
|
-
rawAttributes: {
|
|
210
|
-
startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
|
|
211
|
-
},
|
|
212
|
-
}, { literalAttributes: [literalAttribute] });
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
expect(error.statusCode).toBe(400);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
45
|
+
it('check order validation', () => {
|
|
46
|
+
const payload = _1.validatePayload({ order }, { rawAttributes: ['startTime', 'endTime', 'currencySymbol', 'currencyCode', 'startStationId'] });
|
|
47
|
+
expect(payload).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it('check order validation - order does not exist', () => {
|
|
50
|
+
try {
|
|
51
|
+
_1.validatePayload({ order: ['aviv'] }, { rawAttributes: ['startTime', 'endTime', 'currencySymbol', 'currencyCode', 'startStationId'] });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
expect(error.statusCode).toBe(400);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
it('check order validation - prefix in the wrong place', () => {
|
|
58
|
+
try {
|
|
59
|
+
_1.validatePayload({ order: ['startTime-', 'currencySymbol'] }, { rawAttributes: ['startTime', 'endTime', 'currencySymbol', 'currencyCode', 'startStationId'] });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
expect(error.statusCode).toBe(400);
|
|
63
|
+
}
|
|
218
64
|
});
|
|
219
65
|
});
|
|
66
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/validations/index.test.ts"],"names":[],"mappings":";;AAAA,wBAAoC;AAEpC,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE;QACJ;YACE,SAAS,EAAE;gBACT,IAAI,EAAE,qBAAqB;aAC5B;SACF;QACD;YACE,OAAO,EAAE;gBACP,GAAG,EAAE,qBAAqB;aAC3B;SACF;KACF;IACD,GAAG,EAAE;QACH;YACE,IAAI,EAAE;gBACJ;oBACE,cAAc,EAAE;wBACd,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;qBAChB;iBACF;gBACD;oBACE,YAAY,EAAE;wBACZ,GAAG,EAAE,KAAK;qBACX;iBACF;aACF;SACF;QACD;YACE,cAAc,EAAE;gBACd,GAAG,EAAE,GAAG;aACT;SACF;KACF;CACF,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAExC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,OAAO,GAAG,kBAAe,CAC7B,EAAE,KAAK,EAAE,EACT,EAAE,aAAa,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAChG,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,OAAO,GAAG,kBAAe,CAC7B,EAAE,KAAK,EAAE,EACT,EAAE,aAAa,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAChG,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,IAAI;YACF,kBAAe,CACb,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EACnB,EAAE,aAAa,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAChG,CAAC;SACH;QAAC,OAAO,KAAK,EAAE;YACd,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACpC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,IAAI;YACF,kBAAe,CACb,EAAE,KAAK,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,EAAE,EAC3C,EAAE,aAAa,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC,EAAE,CAChG,CAAC;SACH;QAAC,OAAO,KAAK,EAAE;YACd,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACpC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/sheilta",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "manage cache",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -10,24 +10,7 @@
|
|
|
10
10
|
"coverage": "jest --coverage --forceExit --runInBand",
|
|
11
11
|
"test": "jest --forceExit --runInBand",
|
|
12
12
|
"test-auto": "jest --watch --runInBand",
|
|
13
|
-
"linter": "./node_modules/.bin/eslint src/**/*.ts"
|
|
14
|
-
"build-to-local-repo": "npm run build && cp -r lib/* ../$REPO/node_modules/$npm_package_name/lib",
|
|
15
|
-
"watch": "npm-watch build-to-local-repo"
|
|
16
|
-
},
|
|
17
|
-
"watch": {
|
|
18
|
-
"build-to-local-repo": {
|
|
19
|
-
"extensions": [
|
|
20
|
-
"js",
|
|
21
|
-
"jsx",
|
|
22
|
-
"ts",
|
|
23
|
-
"tsx",
|
|
24
|
-
"css"
|
|
25
|
-
],
|
|
26
|
-
"patterns": [
|
|
27
|
-
"src"
|
|
28
|
-
],
|
|
29
|
-
"quiet": false
|
|
30
|
-
}
|
|
13
|
+
"linter": "./node_modules/.bin/eslint src/**/*.ts"
|
|
31
14
|
},
|
|
32
15
|
"jest": {
|
|
33
16
|
"setupTestFrameworkScriptFile": "jest-extended",
|
|
@@ -44,24 +27,21 @@
|
|
|
44
27
|
},
|
|
45
28
|
"homepage": "https://github.com/Autofleet/sheilta",
|
|
46
29
|
"dependencies": {
|
|
47
|
-
"@autofleet/common-types": "^1.7.42",
|
|
48
30
|
"@autofleet/errors": "^1.0.10",
|
|
49
|
-
"
|
|
31
|
+
"@types/node": "^14.14.20",
|
|
50
32
|
"lodash": "^4.17.21"
|
|
51
33
|
},
|
|
52
34
|
"devDependencies": {
|
|
53
|
-
"
|
|
54
|
-
"@types/node": "^16.11.68",
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^2.34.0",
|
|
56
|
-
"@typescript-eslint/parser": "^2.23.0",
|
|
35
|
+
"typescript": "^3.9.5",
|
|
57
36
|
"eslint": "^6.8.0",
|
|
58
37
|
"eslint-config-airbnb": "^16.1.0",
|
|
59
38
|
"eslint-plugin-import": "^2.20.1",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"typescript": "^3.9.5",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^2.34.0",
|
|
40
|
+
"@typescript-eslint/parser": "^2.23.0",
|
|
63
41
|
"typescript-eslint": "0.0.1-alpha.0",
|
|
64
|
-
"
|
|
42
|
+
"ts-jest": "^25.0.0",
|
|
43
|
+
"jest": "^25.1.0",
|
|
44
|
+
"@types/jest": "^24.9.0"
|
|
65
45
|
},
|
|
66
46
|
"files": [
|
|
67
47
|
"lib/**/*"
|
package/lib/formatter/index.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { LiteralAttribute } from '../middleware';
|
|
2
|
-
declare type OrderItem = string | [string, string];
|
|
3
|
-
declare type SequelizeOrder = string | OrderItem[];
|
|
4
|
-
export declare type FormatPayloadOptions = {
|
|
5
|
-
includeRawPayload?: boolean;
|
|
6
|
-
literalAttributes?: LiteralAttribute[];
|
|
7
|
-
DBFormatter?: any;
|
|
8
|
-
skipSearchTermFormat?: boolean;
|
|
9
|
-
};
|
|
10
|
-
declare type ConditionWithOperator = {
|
|
11
|
-
operator: string;
|
|
12
|
-
value: string;
|
|
13
|
-
};
|
|
14
|
-
export declare type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];
|
|
15
|
-
/**
|
|
16
|
-
* Generates replacements for the given conditions.
|
|
17
|
-
*
|
|
18
|
-
* @param conditions - The conditions to generate replacements for.
|
|
19
|
-
* @returns The replacements object.
|
|
20
|
-
*/
|
|
21
|
-
export declare const generateFilterReplacements: (conditions: Record<string, ConditionValue>) => Record<string, string>;
|
|
22
|
-
/**
|
|
23
|
-
* Generates replacements for the given order array.
|
|
24
|
-
*
|
|
25
|
-
* @param order - The order array to generate replacements for.
|
|
26
|
-
* @returns The replacements object.
|
|
27
|
-
*/
|
|
28
|
-
export declare const generateOrderReplacements: (order: string[]) => Record<string, string>;
|
|
29
|
-
declare const formatPayload: ({ order, page, perPage, include, query, attributes, searchTerm, }: {
|
|
30
|
-
order?: any[];
|
|
31
|
-
page?: number;
|
|
32
|
-
perPage?: number;
|
|
33
|
-
include?: any[];
|
|
34
|
-
query?: {};
|
|
35
|
-
attributes?: any;
|
|
36
|
-
searchTerm?: any;
|
|
37
|
-
}, model?: any, options?: any) => {
|
|
38
|
-
attributes: any[] | {
|
|
39
|
-
include: any[];
|
|
40
|
-
};
|
|
41
|
-
query: {};
|
|
42
|
-
order: SequelizeOrder[];
|
|
43
|
-
page: any;
|
|
44
|
-
perPage: any;
|
|
45
|
-
include: any;
|
|
46
|
-
scopes: any[];
|
|
47
|
-
};
|
|
48
|
-
export default formatPayload;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/index.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { formatOperators } from './operators';
|
|
2
|
-
import { queryFormatMiddleware, queryValidationMiddleware, MiddlewareValidationOption, LiteralAttribute } from './middleware';
|
|
3
|
-
export { formatOperators, queryFormatMiddleware, queryValidationMiddleware, MiddlewareValidationOption, LiteralAttribute, };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { FormatPayloadOptions } from '../formatter';
|
|
2
|
-
declare type literal = any;
|
|
3
|
-
declare type LiteralQuery = (literal | string)[] | literal;
|
|
4
|
-
export declare type LiteralAttribute = {
|
|
5
|
-
attribute: string;
|
|
6
|
-
literal: LiteralQuery;
|
|
7
|
-
};
|
|
8
|
-
export declare type MiddlewareValidationOption = {
|
|
9
|
-
literalAttributes?: LiteralAttribute[];
|
|
10
|
-
enrichmentAttributes?: string[];
|
|
11
|
-
};
|
|
12
|
-
export declare const newQueryValidationMiddleware: (inner?: string) => (model: any, options?: MiddlewareValidationOption) => (req: any, res: any, next: any) => Promise<void>;
|
|
13
|
-
export declare const newQueryFormatMiddleware: (inner?: string) => (model: any, options?: FormatPayloadOptions) => (req: any, res: any, next: any) => Promise<void>;
|
|
14
|
-
export declare const queryValidationMiddleware: (model: any, options?: MiddlewareValidationOption) => (req: any, res: any, next: any) => Promise<void>;
|
|
15
|
-
export declare const queryFormatMiddleware: (model: any, options?: FormatPayloadOptions) => (req: any, res: any, next: any) => Promise<void>;
|
|
16
|
-
export {};
|
package/lib/operators/index.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare const OPERATORS: string[];
|
|
2
|
-
export declare const OPERATOR_PREFIX = "$";
|
|
3
|
-
export declare const OPERATORS_TO_SQL: {
|
|
4
|
-
$eq: string;
|
|
5
|
-
$ne: string;
|
|
6
|
-
$gte: string;
|
|
7
|
-
$gt: string;
|
|
8
|
-
$lte: string;
|
|
9
|
-
$lt: string;
|
|
10
|
-
$not: string;
|
|
11
|
-
$in: string;
|
|
12
|
-
$notIn: string;
|
|
13
|
-
$is: string;
|
|
14
|
-
$like: string;
|
|
15
|
-
$iLike: string;
|
|
16
|
-
$notLike: string;
|
|
17
|
-
$and: string;
|
|
18
|
-
$or: string;
|
|
19
|
-
};
|
|
20
|
-
export declare const formatOperators: (Sequelize: any) => {};
|
package/lib/utils.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export declare const ORDER_PREFIX = "-";
|
|
2
|
-
export declare const ASSOCIATION_PREFIX = ".";
|
|
3
|
-
export declare const PER_PAGE_DEFAULT = 20;
|
|
4
|
-
export declare const PAGE_DEFAULT = 1;
|
|
5
|
-
export declare const PER_PAGE_MAX_LIMIT = 100;
|
|
6
|
-
export declare const PER_PAGE_MIN_LIMIT = 1;
|
|
7
|
-
export declare const PAGE_MIN = 1;
|
|
8
|
-
export declare const wrapAttributeWithOperator: (attribute: any) => string;
|
|
9
|
-
export declare const isAttributeByAssociation: (attributeName: any, associatedModels: any) => boolean;
|
|
10
|
-
export declare const extractAttributeNameFromOrder: (order: any, associationModels: any) => string;
|
|
11
|
-
export declare const isOrderDesc: (order: any) => boolean;
|
|
12
|
-
export declare const throwBadRequestError: (message: string) => never;
|
|
13
|
-
export declare const extractAssociatedAttributeNameFromOrder: (order: any) => string;
|
|
14
|
-
export declare const generateRandomString: (length?: number) => string;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { MiddlewareValidationOption } from '../middleware';
|
|
2
|
-
export declare const validatePayload: ({ query, order, attributes, include, page, perPage, enrichments, }: {
|
|
3
|
-
query?: {};
|
|
4
|
-
order?: any[];
|
|
5
|
-
attributes?: any[];
|
|
6
|
-
include?: any[];
|
|
7
|
-
page?: number;
|
|
8
|
-
perPage?: number;
|
|
9
|
-
enrichments?: any[];
|
|
10
|
-
}, model?: any, options?: MiddlewareValidationOption) => boolean;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|