@autofleet/sheilta 1.4.5 → 1.4.6

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.
@@ -6,6 +6,7 @@ export type FormatPayloadOptions = {
6
6
  literalAttributes?: LiteralAttribute[];
7
7
  DBFormatter?: any;
8
8
  skipSearchTermFormat?: boolean;
9
+ additionalAllowedAttributes?: string[];
9
10
  };
10
11
  type ConditionWithOperator = {
11
12
  operator: string;
@@ -34,15 +35,21 @@ declare const formatPayload: ({ order, page, perPage, include, query, attributes
34
35
  query?: {};
35
36
  attributes?: any;
36
37
  searchTerm?: any;
37
- }, model?: any, options?: any) => {
38
+ }, model?: any, options?: FormatPayloadOptions) => {
39
+ externalQueryValues: Record<string, unknown>;
38
40
  attributes: any[] | {
39
41
  include: any[];
40
42
  };
41
- query: {};
43
+ query: Record<string, unknown>;
42
44
  order: SequelizeOrder[];
43
- page: any;
44
- perPage: any;
45
+ page: number;
46
+ perPage: number;
45
47
  include: any;
46
- scopes: any[];
48
+ scopes: (string | {
49
+ method: (string | {
50
+ replacementsMap: Record<string, string>;
51
+ scopeValue: any;
52
+ })[];
53
+ })[];
47
54
  };
48
55
  export default formatPayload;
@@ -145,10 +145,10 @@ const formatInclude = (include, associationsMap = {}) => {
145
145
  let formattedInclude = include.map((i) => {
146
146
  const includedAssociation = associationsMap[typeof i === 'string' ? i : (i.association || i.model)];
147
147
  return {
148
- ...i,
148
+ ...(typeof i !== 'string' && i),
149
149
  association: includedAssociation,
150
- required: i.required !== false,
151
- ...(i.include && {
150
+ required: typeof i === 'string' || i.required !== false,
151
+ ...(typeof i !== 'string' && i.include && {
152
152
  include: formatInclude(i.include, includedAssociation?.target?.associations),
153
153
  }),
154
154
  };
@@ -156,8 +156,9 @@ const formatInclude = (include, associationsMap = {}) => {
156
156
  formattedInclude = formattedInclude.map(({ model: _model, ...i }) => i);
157
157
  return formattedInclude;
158
158
  };
159
- const formatQuery = (query, associationModels, replacementsMap) => {
159
+ const formatQuery = (query, associationModels, replacementsMap, additionalAllowedAttributes = []) => {
160
160
  const formattedQuery = {};
161
+ const externalQueryValues = {};
161
162
  const formattedScopeMap = new Map();
162
163
  Object.entries(query).forEach(([queryItemKey, queryItemValue]) => {
163
164
  if (queryItemKey.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {
@@ -168,6 +169,9 @@ const formatQuery = (query, associationModels, replacementsMap) => {
168
169
  formattedScopeMap.get(CUSTOM_FIELDS_FILTER_SCOPE)[scopeKey] = parseCustomFieldScopeQueryValue(queryItemValue);
169
170
  return;
170
171
  }
172
+ if (additionalAllowedAttributes.includes(queryItemKey)) {
173
+ externalQueryValues[queryItemKey] = queryItemValue;
174
+ }
171
175
  const key = (0, utils_1.isAttributeByAssociation)(queryItemKey, associationModels)
172
176
  ? (0, utils_1.wrapAttributeWithOperator)(queryItemKey)
173
177
  : queryItemKey;
@@ -186,6 +190,7 @@ const formatQuery = (query, associationModels, replacementsMap) => {
186
190
  });
187
191
  return {
188
192
  formattedQuery,
193
+ externalQueryValues,
189
194
  formattedScopes,
190
195
  };
191
196
  };
@@ -212,8 +217,8 @@ const formatPayload = ({ order = [], page = utils_1.PAGE_DEFAULT, perPage = util
212
217
  const formattedInclude = formatInclude(include, model?.associations);
213
218
  const formattedPage = formatPage(page);
214
219
  const formattedPerPage = formatPerPage(perPage);
215
- const result = formatQuery(query, associationModels, replacementsMap);
216
- const queryScopes = result.formattedScopes;
220
+ const result = formatQuery(query, associationModels, replacementsMap, options?.additionalAllowedAttributes);
221
+ const { formattedScopes: queryScopes, externalQueryValues } = result;
217
222
  let { formattedQuery } = result;
218
223
  if (searchTerm && !options?.skipSearchTermFormat) {
219
224
  const attributesToSend = attributes?.length ? attributes : Object.keys(model.rawAttributes);
@@ -232,8 +237,8 @@ const formatPayload = ({ order = [], page = utils_1.PAGE_DEFAULT, perPage = util
232
237
  perPage: formattedPerPage,
233
238
  include: formattedInclude,
234
239
  scopes: [...queryScopes, ...orderScopes],
235
- // ...((allAttributes.length > 0) && { attributes: allAttributes }),
236
240
  ...(formattedAttribute && { attributes: formattedAttribute }),
241
+ ...(Object.keys(externalQueryValues).length > 0 && { externalQueryValues }),
237
242
  };
238
243
  };
239
244
  exports.default = formatPayload;
@@ -8,6 +8,7 @@ export type LiteralAttribute = {
8
8
  export type MiddlewareValidationOption = {
9
9
  literalAttributes?: LiteralAttribute[];
10
10
  enrichmentAttributes?: string[];
11
+ additionalAllowedAttributes?: string[];
11
12
  };
12
13
  export declare const newQueryValidationMiddleware: (inner?: string) => (model: any, options?: MiddlewareValidationOption) => (req: any, res: any, next: any) => Promise<void>;
13
14
  export declare const newQueryFormatMiddleware: (inner?: string) => (model: any, options?: FormatPayloadOptions) => (req: any, res: any, next: any) => Promise<void>;
@@ -20,7 +20,7 @@ const querySchema = object.keys({
20
20
  include: array.items(any),
21
21
  searchTerm: string,
22
22
  group: array.items(string),
23
- enrichments: alternatives.try(array.items(string), object.pattern(string, { exclude: array.items(string), include: array.items(string) })),
23
+ enrichments: alternatives.try(array.items(string), object.pattern(string, { exclude: array.items(string) })),
24
24
  });
25
25
  const newQueryValidationMiddleware = (inner = 'body') => (model, options = {}) => async (req, res, next) => {
26
26
  const { query, attributes, order, page, perPage, include, group, enrichments, } = req[inner];
@@ -4,7 +4,8 @@ exports.validatePayload = void 0;
4
4
  const utils_1 = require("../utils");
5
5
  const operators_1 = require("../operators");
6
6
  const validateOperator = (operator) => operators_1.OPERATORS.includes(operator.split(operators_1.OPERATOR_PREFIX)[1]);
7
- const validateQueryAttribute = (attribute, modelAttributes = [], associationModels = []) => [...modelAttributes, ...associationModels].includes(attribute.includes(utils_1.ASSOCIATION_PREFIX) ? attribute.split(utils_1.ASSOCIATION_PREFIX)[0] : attribute);
7
+ const validateQueryAttribute = (attribute, modelAttributes = [], associationModels = [], additionalAllowedAttributes = []) => ([...modelAttributes, ...associationModels].includes(attribute.includes(utils_1.ASSOCIATION_PREFIX) ? attribute.split(utils_1.ASSOCIATION_PREFIX)[0] : attribute)
8
+ || additionalAllowedAttributes.includes(attribute));
8
9
  const validateSingleOrder = (currentOrder, rawAttributes, associationModels, options = {}) => {
9
10
  const isOrderDescOrder = (0, utils_1.isOrderDesc)(currentOrder);
10
11
  if (isOrderDescOrder && currentOrder[0] !== utils_1.ORDER_PREFIX) {
@@ -42,18 +43,16 @@ const validateEnrichments = (enrichments, options) => {
42
43
  (0, utils_1.throwBadRequestError)(`enrichment attribute ${invalidEnrichment} is invalid`);
43
44
  }
44
45
  };
45
- const validateQueryPayload = (query, rawAttributes, associationModels = []) => {
46
- // eslint-disable-next-line array-callback-return
47
- Object.keys(query).map((key) => {
48
- const value = query[key];
46
+ const validateQueryPayload = (query, rawAttributes, associationModels = [], additionalAllowedAttributes = []) => {
47
+ Object.entries(query).forEach(([key, value]) => {
49
48
  if (Array.isArray(value)) {
50
49
  if (value[0] && typeof value[0] === 'object') {
51
- value.map((v) => validateQueryPayload(v, rawAttributes, associationModels));
50
+ value.map((v) => validateQueryPayload(v, rawAttributes, associationModels, additionalAllowedAttributes));
52
51
  }
53
52
  }
54
- else if (validateOperator(key) || validateQueryAttribute(key, rawAttributes, associationModels)) {
53
+ else if (validateOperator(key) || validateQueryAttribute(key, rawAttributes, associationModels, additionalAllowedAttributes)) {
55
54
  if (value && typeof value === 'object') {
56
- validateQueryPayload(value, rawAttributes);
55
+ validateQueryPayload(value, rawAttributes, [], additionalAllowedAttributes);
57
56
  }
58
57
  }
59
58
  else {
@@ -104,7 +103,7 @@ const validatePayload = ({ query = {}, order = [], attributes = [], include = []
104
103
  validateAttributes(attributes, rawAttributes);
105
104
  }
106
105
  validateOrderAttributes(order, rawAttributes, associationModels, options);
107
- validateQueryPayload(query, rawAttributes, associationModels);
106
+ validateQueryPayload(query, rawAttributes, associationModels, options.additionalAllowedAttributes);
108
107
  validateEnrichments(enrichments, options);
109
108
  if (!Array.isArray(group)) {
110
109
  (0, utils_1.throwBadRequestError)('group must be an array');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/sheilta",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "description": "Middlewares for validation and parsing of endpoints meant for data querying.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",