@autofleet/sheilta 1.3.2-1 → 1.3.2-4

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.
@@ -1,7 +1,9 @@
1
+ import type { Attribute } from '../interface';
1
2
  declare type OrderItem = string | [string, string];
2
3
  declare type SequelizeOrder = string | OrderItem[];
3
4
  export declare type FormatPayloadOptions = {
4
5
  includeRawPayload?: boolean;
6
+ literalAttributes?: Attribute[];
5
7
  };
6
8
  declare const formatPayload: ({ order, page, perPage, include, query, attributes, searchTerm, }: {
7
9
  order?: any[];
@@ -9,9 +11,9 @@ declare const formatPayload: ({ order, page, perPage, include, query, attributes
9
11
  perPage?: number;
10
12
  include?: any[];
11
13
  query?: {};
12
- attributes?: any;
14
+ attributes?: any[];
13
15
  searchTerm?: any;
14
- }, model?: any) => {
16
+ }, model?: any, options?: any) => {
15
17
  query: {};
16
18
  order: SequelizeOrder[];
17
19
  page: any;
@@ -20,5 +22,6 @@ declare const formatPayload: ({ order, page, perPage, include, query, attributes
20
22
  scopes: (string | {
21
23
  method: any[];
22
24
  })[];
25
+ attributes: any[];
23
26
  };
24
27
  export default formatPayload;
@@ -8,8 +8,18 @@ const common_types_1 = require("@autofleet/common-types");
8
8
  const utils_1 = require("../utils");
9
9
  const DEFAULT_ORDER = 'id';
10
10
  const DESCENDING_KEY = 'DESC';
11
+ const ASCENDING_KEY = 'ASC';
11
12
  const CUSTOM_FIELDS_QUERY_PREFIX = 'customFields.';
12
13
  const { CUSTOM_FIELDS_FILTER_SCOPE } = common_types_1.customFields;
14
+ const getAttributeFromOrder = (order, literalAttributes) => {
15
+ const [formattedOrder, attributes] = order.reduce((acc, o) => {
16
+ const [item, itemOrder = ASCENDING_KEY] = Array.isArray(o) ? o : [o];
17
+ const found = literalAttributes === null || literalAttributes === void 0 ? void 0 : literalAttributes.find(obj => obj.attribute === item);
18
+ (found ? acc[1] : acc[0]).push(found ? `${found.literal} ${itemOrder}` : o);
19
+ return acc;
20
+ }, [[], []]);
21
+ return [formattedOrder, attributes];
22
+ };
13
23
  const formatOrder = ({ order, associationModels = [], }) => order.map((o) => {
14
24
  const formattedOrder = [utils_1.extractAttributeNameFromOrder(o, associationModels)];
15
25
  const isOrderDescOrder = utils_1.isOrderDesc(o);
@@ -68,12 +78,14 @@ const formatSearchTerm = (searchTerm, attributesToSend, rawAttributes) => ({
68
78
  })),
69
79
  })),
70
80
  });
71
- const formatPayload = ({ order = [], page = utils_1.PAGE_DEFAULT, perPage = utils_1.PER_PAGE_DEFAULT, include = [], query = {}, attributes = null, searchTerm = null, }, model) => {
81
+ const formatPayload = ({ order = [], page = utils_1.PAGE_DEFAULT, perPage = utils_1.PER_PAGE_DEFAULT, include = [], query = {}, attributes = [], searchTerm = null, }, model, options) => {
72
82
  const associationModels = Object.keys((model === null || model === void 0 ? void 0 : model.associations) || {});
73
83
  const formattedOrder = formatOrder({
74
84
  order: [...order, DEFAULT_ORDER],
75
85
  associationModels,
76
86
  });
87
+ const [filteredFormattedOrder, filteredLiteralAttributes] = getAttributeFromOrder(formattedOrder, options === null || options === void 0 ? void 0 : options.literalAttributes);
88
+ const formattedAttribute = [...filteredLiteralAttributes, ...attributes];
77
89
  const formattedInclude = formatInclude(include, model === null || model === void 0 ? void 0 : model.associations);
78
90
  const formattedPage = formatPage(page);
79
91
  const formattedPerPage = formatPerPage(perPage);
@@ -91,11 +103,12 @@ const formatPayload = ({ order = [], page = utils_1.PAGE_DEFAULT, perPage = util
91
103
  }
92
104
  return {
93
105
  query: formattedQuery,
94
- order: formattedOrder,
106
+ order: filteredFormattedOrder,
95
107
  page: formattedPage,
96
108
  perPage: formattedPerPage,
97
109
  include: formattedInclude,
98
110
  scopes: result.formattedScopes,
111
+ attributes: formattedAttribute,
99
112
  };
100
113
  };
101
114
  exports.default = formatPayload;
@@ -189,6 +189,48 @@ describe('formatting test', () => {
189
189
  });
190
190
  expect(JSON.stringify(order)).toBe(JSON.stringify([['status.name', 'DESC'], ['id']]));
191
191
  });
192
+ it('by literal field ascending', () => {
193
+ const literalAttribute = { attribute: 'genericField', literal: 'void' };
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([['id']]));
204
+ expect(JSON.stringify(attributes)).toBe(JSON.stringify([`${literalAttribute.literal} ASC`]));
205
+ });
206
+ it('by literal field descending', () => {
207
+ const literalAttribute = { attribute: 'genericField', literal: 'void' };
208
+ const { order, attributes } = _1.default({
209
+ order: [`-${literalAttribute.attribute}`, 'currencySymbol'],
210
+ }, {
211
+ rawAttributes: {
212
+ startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
213
+ },
214
+ }, {
215
+ literalAttributes: [literalAttribute],
216
+ });
217
+ expect(JSON.stringify(order)).toBe(JSON.stringify([['currencySymbol'], ['id']]));
218
+ expect(JSON.stringify(attributes)).toBe(JSON.stringify([`${literalAttribute.literal} DESC`]));
219
+ });
220
+ it('by literal field - not found', () => {
221
+ const literalAttribute = { attribute: 'genericField', literal: 'void' };
222
+ const { order, attributes } = _1.default({
223
+ order: [`-O${literalAttribute.attribute}`],
224
+ }, {
225
+ rawAttributes: {
226
+ startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '',
227
+ },
228
+ }, {
229
+ literalAttributes: [literalAttribute],
230
+ });
231
+ expect(JSON.stringify(order)).toBe(JSON.stringify([[`O${literalAttribute.attribute}`, 'DESC'], ['id']]));
232
+ expect(JSON.stringify(attributes)).toBe(JSON.stringify([]));
233
+ });
192
234
  });
193
235
  describe('include formatting', () => {
194
236
  it('include required should be true', () => {
@@ -1,3 +1,7 @@
1
+ export declare type Attribute = {
2
+ attribute: string;
3
+ literal: any;
4
+ };
1
5
  export declare type MiddlewareValidationOption = {
2
- literalAttribute?: string[];
6
+ literalAttributes?: Attribute[];
3
7
  };
@@ -57,7 +57,7 @@ exports.newQueryValidationMiddleware = (inner = 'body') => (model, options = {})
57
57
  });
58
58
  exports.newQueryFormatMiddleware = (inner = 'body') => (model, options = {}) => (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
59
59
  const { order, page, perPage, include, query, attributes, searchTerm, } = req[inner];
60
- const { query: formattedQuery, order: formattedOrder, page: formattedPage, perPage: formattedPerPage, include: formattedInclude, scopes: formattedScopes, } = formatter_1.default({
60
+ const { query: formattedQuery, order: formattedOrder, page: formattedPage, perPage: formattedPerPage, include: formattedInclude, scopes: formattedScopes, attributes: formattedAttribute, } = formatter_1.default({
61
61
  query,
62
62
  order,
63
63
  page,
@@ -65,9 +65,10 @@ exports.newQueryFormatMiddleware = (inner = 'body') => (model, options = {}) =>
65
65
  include,
66
66
  attributes,
67
67
  searchTerm,
68
- }, model);
68
+ }, model, options);
69
69
  req[inner].query = formattedQuery;
70
70
  req[inner].order = formattedOrder;
71
+ req[inner].attributes = formattedAttribute;
71
72
  req[inner].page = formattedPage;
72
73
  req[inner].perPage = formattedPerPage;
73
74
  req[inner].include = formattedInclude;
@@ -12,7 +12,7 @@ const validateQueryAttribute = (attribute, modelAttributes = [], associationMode
12
12
  .includes(attribute.includes(utils_1.ASSOCIATION_PREFIX)
13
13
  ? attribute.split(utils_1.ASSOCIATION_PREFIX)[0] : attribute);
14
14
  const validateSingleOrder = (currentOrder, rawAttributes, associationModels, options = {}) => {
15
- var _a;
15
+ var _a, _b;
16
16
  const isOrderDescOrder = utils_1.isOrderDesc(currentOrder);
17
17
  if (isOrderDescOrder && currentOrder[0] !== utils_1.ORDER_PREFIX) {
18
18
  utils_1.throwBadRequestError(`${utils_1.ORDER_PREFIX} must be only at the beginning of the word`);
@@ -21,12 +21,12 @@ const validateSingleOrder = (currentOrder, rawAttributes, associationModels, opt
21
21
  currentOrder.split(utils_1.ORDER_PREFIX)[1] : currentOrder;
22
22
  const isOrderAssociation = utils_1.isAttributeByAssociation(orderStringWithoutDesc, associationModels);
23
23
  let formattedOrderString = utils_1.extractAttributeNameFromOrder(currentOrder, associationModels);
24
- const isLiteralAttribute = (_a = options === null || options === void 0 ? void 0 : options.literalAttribute) === null || _a === void 0 ? void 0 : _a.includes(orderStringWithoutDesc);
24
+ const isLiteralAttribute = (_b = (_a = options === null || options === void 0 ? void 0 : options.literalAttributes) === null || _a === void 0 ? void 0 : _a.map(la => la.attribute)) === null || _b === void 0 ? void 0 : _b.includes(orderStringWithoutDesc);
25
25
  if (!isOrderAssociation && formattedOrderString.includes(utils_1.ASSOCIATION_PREFIX)) {
26
26
  [formattedOrderString] = formattedOrderString.split(utils_1.ASSOCIATION_PREFIX);
27
27
  }
28
28
  if (!(rawAttributes.includes(formattedOrderString) || isOrderAssociation || isLiteralAttribute)) {
29
- utils_1.throwBadRequestError(`${currentOrder} is invalid`);
29
+ utils_1.throwBadRequestError(`${currentOrder} is invalid isLiteralAttribute: ${isLiteralAttribute}`);
30
30
  }
31
31
  };
32
32
  const validateSingleAttribute = (currentAttribute, rawAttributes) => {
@@ -181,23 +181,35 @@ describe('validations test', () => {
181
181
  }
182
182
  });
183
183
  it('try order by literal field that exist', () => {
184
- const literalAttribute = 'genericField';
185
- const payload = _1.validatePayload({ order: [literalAttribute] }, {
184
+ const literalAttribute = { attribute: 'genericField', literal: 'void' };
185
+ const payload = _1.validatePayload({ order: [literalAttribute.attribute] }, {
186
186
  rawAttributes: {
187
187
  startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
188
188
  },
189
189
  }, {
190
- literalAttribute: [literalAttribute],
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],
191
202
  });
192
203
  expect(payload).toBe(true);
193
204
  });
194
205
  it('try order by literal field that doesnt exist', () => {
206
+ const literalAttribute = { attribute: 'genericField', literal: 'void' };
195
207
  try {
196
208
  _1.validatePayload({ order: ['here'] }, {
197
209
  rawAttributes: {
198
210
  startTime: '', endTime: '', currencySymbol: '', currencyCode: '', startStationId: '', status: '',
199
211
  },
200
- }, { literalAttribute: ['not'] });
212
+ }, { literalAttributes: [literalAttribute] });
201
213
  }
202
214
  catch (error) {
203
215
  expect(error.statusCode).toBe(400);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/sheilta",
3
- "version": "1.3.2-1",
3
+ "version": "1.3.2-4",
4
4
  "description": "manage cache",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",