@autofleet/sheilta 2.2.7 → 2.3.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/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +95 -179
- package/lib/index.d.ts +95 -179
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +33 -7
package/lib/index.d.ts
CHANGED
|
@@ -1,196 +1,112 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { LoggerInstanceManager } from
|
|
3
|
-
import { Handler } from "express";
|
|
1
|
+
import { Handler } from 'express';
|
|
2
|
+
import { LoggerInstanceManager } from '@autofleet/logger';
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
declare const formatOperators: (Sequelize: any) => {};
|
|
6
5
|
|
|
7
|
-
declare const formatOperators: (sequelize?: {
|
|
8
|
-
Op: typeof Op;
|
|
9
|
-
}) => Record<string, symbol>;
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/formatter/jsonAttributesFormater.d.ts
|
|
12
|
-
declare const ComputedActions: {
|
|
13
|
-
readonly length: "length";
|
|
14
|
-
};
|
|
15
|
-
interface JsonSelectAttribute {
|
|
16
|
-
columnName: string;
|
|
17
|
-
keys: string[];
|
|
18
|
-
alias?: string;
|
|
19
|
-
}
|
|
20
|
-
interface JsonComputedAttribute {
|
|
21
|
-
columnName: string;
|
|
22
|
-
action: keyof typeof ComputedActions;
|
|
23
|
-
alias: string;
|
|
24
|
-
}
|
|
25
|
-
interface JsonAttributes {
|
|
26
|
-
select?: JsonSelectAttribute[];
|
|
27
|
-
computed?: JsonComputedAttribute[];
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/formatter/index.d.ts
|
|
31
6
|
type OrderItem = string | [string, string];
|
|
32
7
|
type SequelizeOrder = string | OrderItem[];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
8
|
+
type FormatPayloadOptions = {
|
|
9
|
+
includeRawPayload?: boolean;
|
|
10
|
+
literalAttributes?: LiteralAttribute[];
|
|
11
|
+
DBFormatter?: any;
|
|
12
|
+
skipSearchTermFormat?: boolean;
|
|
13
|
+
additionalAllowedAttributes?: string[];
|
|
14
|
+
};
|
|
15
|
+
type ConditionWithOperator = {
|
|
16
|
+
operator: string;
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
44
19
|
type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];
|
|
45
20
|
/**
|
|
46
|
-
* Generates replacements for the given conditions.
|
|
47
|
-
*
|
|
48
|
-
* @param conditions - The conditions to generate replacements for.
|
|
49
|
-
* @returns The replacements object.
|
|
50
|
-
*/
|
|
21
|
+
* Generates replacements for the given conditions.
|
|
22
|
+
*
|
|
23
|
+
* @param conditions - The conditions to generate replacements for.
|
|
24
|
+
* @returns The replacements object.
|
|
25
|
+
*/
|
|
51
26
|
declare const generateFilterReplacements: (conditions: Record<string, ConditionValue>) => Record<string, string>;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
page: number;
|
|
77
|
-
perPage: number;
|
|
78
|
-
include: any;
|
|
79
|
-
scopes: (string | {
|
|
80
|
-
method: (string | {
|
|
81
|
-
replacementsMap: Record<string, string>;
|
|
82
|
-
scopeValue: any;
|
|
27
|
+
declare const formatPayload: ({ order, page, perPage, include, query, attributes, searchTerm, jsonAttributes, }: {
|
|
28
|
+
order?: any[];
|
|
29
|
+
page?: number;
|
|
30
|
+
perPage?: number;
|
|
31
|
+
include?: any[];
|
|
32
|
+
query?: {};
|
|
33
|
+
attributes?: any;
|
|
34
|
+
searchTerm?: any;
|
|
35
|
+
jsonAttributes?: {};
|
|
36
|
+
}, model?: any, options?: FormatPayloadOptions) => {
|
|
37
|
+
externalQueryValues: Record<string, unknown>;
|
|
38
|
+
attributes: any[] | {
|
|
39
|
+
include: any[];
|
|
40
|
+
};
|
|
41
|
+
query: Record<string, unknown>;
|
|
42
|
+
order: SequelizeOrder[];
|
|
43
|
+
page: number;
|
|
44
|
+
perPage: number;
|
|
45
|
+
include: any;
|
|
46
|
+
scopes: (string | {
|
|
47
|
+
method: (string | {
|
|
48
|
+
replacementsMap: Record<string, string>;
|
|
49
|
+
scopeValue: any;
|
|
50
|
+
})[];
|
|
83
51
|
})[];
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
type
|
|
99
|
-
type LiteralQuery = (literal$1 | string)[] | literal$1;
|
|
100
|
-
interface LiteralAttribute {
|
|
101
|
-
attribute: string;
|
|
102
|
-
literal: LiteralQuery;
|
|
103
|
-
}
|
|
104
|
-
interface MiddlewareValidationOption {
|
|
105
|
-
literalAttributes?: LiteralAttribute[];
|
|
106
|
-
enrichmentAttributes?: string[];
|
|
107
|
-
additionalAllowedAttributes?: string[];
|
|
108
|
-
logger?: LoggerInstanceManager;
|
|
109
|
-
}
|
|
110
|
-
type ReqKeys = "body" | "query";
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type literal = any;
|
|
55
|
+
type LiteralQuery = (literal | string)[] | literal;
|
|
56
|
+
type LiteralAttribute = {
|
|
57
|
+
attribute: string;
|
|
58
|
+
literal: LiteralQuery;
|
|
59
|
+
};
|
|
60
|
+
type MiddlewareValidationOption = {
|
|
61
|
+
literalAttributes?: LiteralAttribute[];
|
|
62
|
+
enrichmentAttributes?: string[];
|
|
63
|
+
additionalAllowedAttributes?: string[];
|
|
64
|
+
logger?: LoggerInstanceManager;
|
|
65
|
+
};
|
|
66
|
+
type ReqKeys = 'body' | 'query';
|
|
111
67
|
/** consider using @see {@link queryHandler} directly */
|
|
112
68
|
declare const queryValidationMiddleware: (model: any, options?: MiddlewareValidationOption, inner?: ReqKeys) => Handler;
|
|
113
69
|
/** consider using @see {@link queryHandler} directly */
|
|
114
70
|
declare const queryFormatMiddleware: (model: any, options?: FormatPayloadOptions, inner?: ReqKeys) => Handler;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
};
|
|
129
|
-
group?: string[];
|
|
130
|
-
jsonAttributes?: {
|
|
131
|
-
select?: {
|
|
132
|
-
columnName: string;
|
|
133
|
-
keys: string[];
|
|
134
|
-
alias?: string;
|
|
135
|
-
}[];
|
|
136
|
-
computed?: {
|
|
137
|
-
columnName: string;
|
|
138
|
-
action: "length";
|
|
139
|
-
alias: string;
|
|
140
|
-
}[];
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
declare const validatePayload: ({
|
|
144
|
-
query,
|
|
145
|
-
order,
|
|
146
|
-
attributes,
|
|
147
|
-
include,
|
|
148
|
-
page,
|
|
149
|
-
perPage,
|
|
150
|
-
enrichments,
|
|
151
|
-
group,
|
|
152
|
-
jsonAttributes
|
|
153
|
-
}: PayloadValidationData, model?: any, options?: MiddlewareValidationOption) => boolean;
|
|
154
|
-
//#endregion
|
|
155
|
-
//#region src/handler/index.d.ts
|
|
71
|
+
|
|
72
|
+
declare const validatePayload: ({ query, order, attributes, include, page, perPage, enrichments, group, jsonAttributes, }: {
|
|
73
|
+
query?: {};
|
|
74
|
+
order?: any[];
|
|
75
|
+
attributes?: any[];
|
|
76
|
+
include?: any[];
|
|
77
|
+
page?: number;
|
|
78
|
+
perPage?: number;
|
|
79
|
+
enrichments?: any[];
|
|
80
|
+
group?: any[];
|
|
81
|
+
jsonAttributes?: {};
|
|
82
|
+
}, model?: any, options?: MiddlewareValidationOption) => boolean;
|
|
83
|
+
|
|
156
84
|
interface QueryValues extends ReturnType<typeof formatPayload> {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
searchTerm?: string;
|
|
85
|
+
enrichments?: string[] | Record<string, {
|
|
86
|
+
exclude: string[];
|
|
87
|
+
}>;
|
|
88
|
+
distinct: boolean;
|
|
162
89
|
}
|
|
163
90
|
interface QueryHandlerOptions {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
91
|
+
/** The sequelize model too which querying abilities are added. */
|
|
92
|
+
model: any;
|
|
93
|
+
/** Optional settings for validation. */
|
|
94
|
+
validationOptions?: Omit<MiddlewareValidationOption, 'logger'>;
|
|
95
|
+
/** Optional settings for payload formatting */
|
|
96
|
+
formatOptions?: FormatPayloadOptions;
|
|
97
|
+
logger: LoggerInstanceManager;
|
|
98
|
+
/** The name of model to be printed in logs. defaults to `model`s constructor name. */
|
|
99
|
+
modelName?: string;
|
|
100
|
+
/** Sequelize scopes of the model to be used within the query. @example ['userScope'] */
|
|
101
|
+
additionalScopes?: string[];
|
|
102
|
+
/** Callback to allow modifying the query values prior to querying the DB */
|
|
103
|
+
modifyQueryValues?: (queryValues: QueryValues) => QueryValues;
|
|
104
|
+
/** Optional callback to modify endpoint's response based on the DBs response. */
|
|
105
|
+
onRowsRetrieved?: (data: {
|
|
106
|
+
rows: any[];
|
|
107
|
+
count: number;
|
|
108
|
+
}, queryValues: QueryValues) => any;
|
|
182
109
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
model,
|
|
186
|
-
logger,
|
|
187
|
-
validationOptions,
|
|
188
|
-
formatOptions,
|
|
189
|
-
modelName,
|
|
190
|
-
additionalScopes,
|
|
191
|
-
modifyQueryValues,
|
|
192
|
-
onRowsRetrieved
|
|
193
|
-
}: QueryHandlerOptions) => Asyncify<Handler>;
|
|
194
|
-
//#endregion
|
|
110
|
+
declare const queryHandler: ({ model, logger, validationOptions, formatOptions, modelName, additionalScopes, modifyQueryValues, onRowsRetrieved, }: QueryHandlerOptions) => Handler;
|
|
111
|
+
|
|
195
112
|
export { type LiteralAttribute, type MiddlewareValidationOption, formatOperators, generateFilterReplacements, queryFormatMiddleware, queryHandler, queryValidationMiddleware, validatePayload };
|
|
196
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Op as e,literal as t}from"sequelize";import n from"@autofleet/logger";import{BadRequest as r,UnexpectedError as i,handleError as a}from"@autofleet/errors";import o from"joi";import{customFields as s}from"@autofleet/common-types";import{randomInt as c}from"node:crypto";const l=[`eq`,`ne`,`gte`,`gt`,`lte`,`lt`,`not`,`in`,`notIn`,`is`,`like`,`iLike`,`notLike`,`between`,`and`,`or`,`overlap`,`contains`],u={$eq:`=`,$ne:`!=`,$gte:`>=`,$gt:`>`,$lte:`<=`,$lt:`<`,$not:`NOT`,$in:`IN`,$notIn:`NOT IN`,$is:`IS`,$like:`LIKE`,$iLike:`ILIKE`,$notLike:`NOT LIKE`,$and:`AND`,$or:`OR`},d=(t={Op:e})=>{let{Op:n}=t;return Object.fromEntries(l.map(e=>[`${`$`+e}`,n[e]]))},f=e=>`\$${e}\$`,p=(e,t)=>e.includes(`.`)&&t.includes(e.split(`.`,1)[0]),m=(e,t)=>{let n=e;return e.includes(`-`)&&([,n]=n.split(`-`,2)),p(n,t)&&([n]=n.split(`.`,1)),n},h=e=>e.includes(`-`),g=e=>{throw new r([Error(e)])},_=e=>e.split(`.`,2)[1],v=(e=5)=>Array.from({length:e},()=>`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`.charAt(c(52))).join(``),y=(e,t)=>Object.fromEntries(t.map(t=>[t,e[t]])),b={length:`length`};function x(e){return e.replace(/(?!^)[A-Z]/g,e=>`_${e.toLowerCase()}`)}function S(e){switch(e.action){case b.length:return[t(`jsonb_array_length(${x(e.columnName)})`),e.alias];default:return e.action,[]}}function C(e){return e.map(e=>S(e))}function w(e){return e.map(e=>{let n=x(e.columnName),r=`json_build_object(${e.keys.map(e=>`'${e}', ${n} -> '${e}'`).join(`, `)})`,i=e.alias||e.columnName;return[t(r),i]})}function T({select:e=[],computed:t=[]}={}){let n=w(e),r=C(t);return[...n,...r]}const E=`DESC`,D=`customFields.`,{CUSTOM_FIELDS_FILTER_SCOPE:O,CUSTOM_FIELDS_SORT_SCOPE:k}=s,ee=e=>[`string`,`number`].includes(typeof e)||Array.isArray(e)?e:Object.entries(e).map(([e,t])=>({operator:u[e],value:t})),A=(e,t={})=>{let{literalAttributes:n=[],DBFormatter:r=void 0}=t,[i,a]=e.reduce((e,t)=>{let[i,a=`ASC`]=Array.isArray(t)?t:[t],o=n?.find(e=>e.attribute===i);if(o){let t=r?r(`"${o.attribute}" ${a}`):`${o.attribute} ${a}`;e[1].push(o.literal),e[0].push([t])}else e[0].push(t);return e},[[],[]]);return[i,a]},j=e=>{let t={};return Object.entries(e).forEach(([e,n])=>{let r=v();if(t[r]=e.split(D,2)[1],Array.isArray(n))n.forEach(e=>{let n=v();t[n]=typeof e==`string`?e:e.value});else if(typeof n==`string`||typeof n==`number`){let e=v();t[e]=n}else if(n?.operator){let e=v();t[e]=n.value}}),t},M=e=>{let t={};return e.forEach(e=>{if(e.startsWith(D)){let n=v();t[n]=e.split(D,2)[1]}else if(e.substring(1).startsWith(D)){let n=v();t[n]=e.substring(1).split(D,2)[1]}}),t},N=(e,t)=>({...M(e),...j(t)}),P=({order:e,associationModels:t=[],replacementsMap:n={}})=>{let r=[],i=new Map;return e.forEach(e=>{if([e,e.substring(1)].some(e=>e.startsWith(D))){i.has(k)||i.set(k,{});let t=e.split(D,2)[1];i.get(k)[t]=h(e)?E:`ASC`;return}let n=[m(e,t)],a=h(e);p(a?e.split(`-`,2)[1]:e,t)&&n.push(_(e)),a&&n.push(E),r.push(n)}),{formattedOrders:r,replacementsMap:n,orderScopes:Array.from(i.entries()).map(([e,t])=>t?{method:[e,{replacementsMap:n,scopeValue:t}]}:e)}},te=e=>e||1,ne=e=>e||20,F=(e,t={})=>{let n=e.map(e=>{let n=t[typeof e==`string`?e:e.association||e.model];return{...typeof e!=`string`&&e,association:n,required:typeof e==`string`||e.required!==!1,...typeof e!=`string`&&e.include&&{include:F(e.include,n?.target?.associations)}}});return n=n.map(({model:e,...t})=>t),n},re=(e,t,n,r=[])=>{let i={},a={},o=new Map;return Object.entries(e).forEach(([e,n])=>{if(e.startsWith(D)){o.has(O)||o.set(O,{});let t=e.split(D,2)[1];o.get(O)[t]=ee(n);return}if(r.includes(e)){a[e]=n;return}let s=p(e,t)?f(e):e;i[s]=n}),{formattedQuery:i,externalQueryValues:a,formattedScopes:Array.from(o.entries()).map(([e,t])=>t?{method:[e,{replacementsMap:n,scopeValue:t}]}:e)}},ie=(e,t,n)=>({$and:e.split(` `).map(e=>({$or:t.filter(e=>n[e].type.key===`STRING`).map(t=>({[t]:{$iLike:`%${e}%`}}))}))});var ae=({order:e=[],page:t=1,perPage:n=20,include:r=[],query:i={},attributes:a=null,searchTerm:o=null,jsonAttributes:s={}},c,l)=>{let u=N(e,i),d=Object.keys(c?.associations||{}),{formattedOrders:f,orderScopes:p}=P({order:[...e,`id`],associationModels:d,replacementsMap:u}),[m,h]=A(f,l),g=T(s),_=[...h,...a??[],...g],v=a?.length?_:{include:_},y=F(r,c?.associations),b=te(t),x=ne(n),S=re(i,d,u,l?.additionalAllowedAttributes),{formattedScopes:C,externalQueryValues:w}=S,{formattedQuery:E}=S;if(o&&!l?.skipSearchTermFormat){let e=ie(o,a?.length?a:Object.keys(c.rawAttributes||{}),c.rawAttributes);E=!E||Object.keys(E).length===0?e:{$and:[E,e]}}return{query:E,order:m,page:b,perPage:x,include:y,scopes:[...C,...p],...v&&{attributes:v},...Object.keys(w).length>0&&{externalQueryValues:w}}};const oe=e=>l.includes(e.split(`$`,2)[1]),I=(e,t=[],n=[],r=[])=>{let i=e.startsWith(`$`)&&e.endsWith(`$`)?e.slice(1,-1):e;return[...t,...n].includes(i.includes(`.`)?i.split(`.`,1)[0]:i)||r.includes(i)},L=(e,t,n,r={})=>{let i=h(e);i&&!e.startsWith(`-`)&&g(`- must be only at the beginning of the word`);let a=i?e.split(`-`,2)[1]:e,o=p(a,n),s=m(e,n),c=r?.literalAttributes?.map(e=>e.attribute)?.includes(a);!o&&s.includes(`.`)&&([s]=s.split(`.`,1)),t.includes(s)||o||c||g(`${e} is invalid. isLiteralAttribute: ${c}`)},R=(e,t)=>{t.includes(e)||g(`${e} is invalid`)},z=(e,t,n=[],r={})=>{e.forEach(e=>L(e,t,n,r))},B=(e,t)=>{e.forEach(e=>R(e,t))},V=(e,t)=>{B([...e.select?.map(e=>e.columnName)??[],...e.computed?.map(e=>e.columnName)??[]],t)},H=(e,t)=>{let n=Array.isArray(e)?e:Object.keys(e);if(!n?.length)return;let r=n.find(e=>!t?.enrichmentAttributes?.includes(e));r&&g(`enrichment attribute ${r} is invalid`)},U=(e,t,n=[],r=[])=>{Object.entries(e).forEach(([e,i])=>{Array.isArray(i)?i[0]&&typeof i[0]==`object`&&i.map(e=>U(e,t,n,r)):oe(e)||I(e,t,n,r)?i&&typeof i==`object`&&U(i,t,[],r):g(`invalid key: ${e}`)})},W=({page:e,perPage:t})=>{e<1&&g(`Page must be greater than 0`),(t>100||t<1)&&g(`PerPage must be between 1 to 100`)},G=(e,t)=>{let n=Object.keys(t);e.forEach(e=>{I(e.model,n);let r=t[e.model]?.target;r||g(`model not found in associations`);let{rawAttributes:i}=r,a=Object.keys(i);e.where&&U(e.where,a),e.order&&z(e.order,a),e.attributes&&B(e.attributes,a),[null,void 0,!0,!1].includes(e.required)||g(`include.required must be a boolean`)})},K=({query:e={},order:t=[],attributes:n=[],include:r=[],page:i=1,perPage:a=20,enrichments:o=[],group:s=[],jsonAttributes:c={}},l,u={})=>{let d=Object.keys(l.rawAttributes),f=Object.keys(l?.associations||{});return!n||n.length===0?n=d:B(n,d),z(t,d,f,u),U(e,d,f,u.additionalAllowedAttributes),H(o,u),V(c,d),Array.isArray(s)||g(`group must be an array`),r.length&&typeof r==`object`?G(r,l?.associations):r&&typeof r!=`object`&&g(`include must be an array`),W({page:i,perPage:a}),!0},{object:q,string:J,number:Y,any:se,array:X,alternatives:ce}=o.types(),le=n(),ue=q.keys({query:q,attributes:X.items(J),order:X.items(J),page:Y,perPage:Y,include:X.items(se),searchTerm:J,group:X.items(J),enrichments:ce.try(X.items(J),q.pattern(J,{exclude:X.items(J)})),jsonAttributes:o.object({select:o.array().items(o.object({columnName:o.string().required(),keys:o.array().items(o.string().required()).required(),alias:o.string().optional()})).default([]),computed:o.array().items(o.object({columnName:o.string().required(),action:o.string().valid(...Object.values(b)).required(),alias:o.string().required()})).default([])}).default({})}),Z=(e,t,n={})=>{let{query:i,attributes:a,order:o,page:s,perPage:c,include:l,group:u,enrichments:d,jsonAttributes:f}=t,p=ue.validate(t);if(p.error)throw new r([p.error]);K({query:i,attributes:a,order:o,page:s,perPage:c,include:l,enrichments:d,group:u,jsonAttributes:f},e,n)},Q=(e,t={},n=`body`)=>(r,i,o)=>{try{Z(e,r[n],t),o()}catch(e){let{query:o,attributes:s,order:c}=r[n];a(e,i,{logger:t.logger??le,message:`error in query middleware`,payload:{error:e,query:o,attributes:s,order:c}})}},$=(e,t,n={})=>{let{order:r,page:i,perPage:a,include:o,query:s,attributes:c,searchTerm:l,jsonAttributes:u}=t,{query:d,externalQueryValues:f,order:p,page:m,perPage:h,include:g,scopes:_,attributes:v}=ae({query:s,order:r,page:i,perPage:a,include:o,attributes:c,searchTerm:l,jsonAttributes:u},e,n);t.query=d,t.externalQueryValues=f,t.order=p,t.attributes=v,t.page=m,t.perPage=h,t.include=g,t.scopes=_,n.includeRawPayload&&(t.rawPayload={order:r,page:i,perPage:a,include:o,query:s,attributes:c,searchTerm:l})},de=(e,t={},n=`body`)=>(r,i,a)=>{$(e,r[n],t),a()},fe=({model:e,logger:t,validationOptions:n,formatOptions:r,modelName:o=e.constructor?.name,additionalScopes:s=[],modifyQueryValues:c,onRowsRetrieved:l})=>async(u,d)=>{try{Z(e,u.body,{...n,logger:t})}catch(e){a(e,d,{logger:t,message:`error in query endpoint`,payload:y(u.body,[`query`,`order`,`attributes`])});return}try{$(e,u.body,r);let n=Object.assign(y(u.body,[`query`,`externalQueryValues`,`order`,`attributes`,`page`,`perPage`,`include`,`scopes`,`enrichments`]),{distinct:!0});t.info(`querying ${o}`,{queryValues:n});let i=c?.(n)??n,{scopes:a=[],query:f,perPage:p,page:m,enrichments:h,externalQueryValues:g,..._}=i,v=await e.scope([...s,...a]).findAndCountAll({where:f,limit:p,offset:(m-1)*p,..._});if(!v.rows.length||!l){d.json(v);return}let b=await l(v,i);d.json(b)}catch(e){a(new i(e),d,{logger:t,message:`Error while querying ${o}`,payload:{query:u.body}})}};export{d as formatOperators,j as generateFilterReplacements,de as queryFormatMiddleware,fe as queryHandler,Q as queryValidationMiddleware,K as validatePayload};
|
|
1
|
+
import Jt from'@autofleet/logger';import {handleError,UnexpectedError,BadRequest}from'@autofleet/errors';import m from'joi';import {customFields}from'@autofleet/common-types';import {literal}from'sequelize';var j=["eq","ne","gte","gt","lte","lt","not","in","notIn","is","like","iLike","notLike","between","and","or","overlap","contains"],R="$",et={$eq:"=",$ne:"!=",$gte:">=",$gt:">",$lte:"<=",$lt:"<",$not:"NOT",$in:"IN",$notIn:"NOT IN",$is:"IS",$like:"LIKE",$iLike:"ILIKE",$notLike:"NOT LIKE",$and:"AND",$or:"OR"},bt=t=>{let{Op:e}=t;return j.reduce((o,r)=>(o[`${R+r}`]=e[r],o),{})};var Ot=t=>Math.floor(Math.random()*Math.floor(t)),y="-",f=".",C="$",q=20,I=1,V=100,v=1,rt=1,ot=t=>`${R}${t}${R}`,S=(t,e)=>t.includes(f)&&e.includes(t.split(f)[0]),k=(t,e)=>{let o=t;return t.includes(y)&&(o=o.split(y)[1]),S(o,e)&&([o]=o.split(f)),o},M=t=>t.includes(y),g=t=>{throw new BadRequest([new Error(t)])},nt=t=>t.split(f)[1],O=(t=5)=>{let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";return Array.from({length:t},()=>e.charAt(Ot(e.length))).join("")},D=(t,e)=>Object.fromEntries(e.map(o=>[o,t[o]]));var J={length:"length"};function it(t){return t.replace(/(?!^)[A-Z]/g,e=>`_${e.toLowerCase()}`)}function ht(t){switch(t.action){case J.length:{let e=`jsonb_array_length(${it(t.columnName)})`;return [literal(e),t.alias]}default:return t.action,[]}}function Pt(t){return t.map(e=>ht(e))}function Et(t){return t.map(e=>{let o=it(e.columnName),r=`json_build_object(${e.keys.map(n=>`'${n}', ${o} -> '${n}'`).join(", ")})`,s=e.alias||e.columnName;return [literal(r),s]})}function G({select:t=[],computed:e=[]}={}){let o=Et(t),r=Pt(e);return [...o,...r]}var St="id",at="DESC",xt="ASC",b="customFields.",{CUSTOM_FIELDS_FILTER_SCOPE:W,CUSTOM_FIELDS_SORT_SCOPE:K}=customFields,_t=t=>["string","number"].includes(typeof t)||Array.isArray(t)?t:Object.entries(t).map(([e,o])=>({operator:et[e],value:o})),Ft=(t,e={})=>{let{literalAttributes:o=[],DBFormatter:r=void 0}=e,[s,n]=t.reduce((i,d)=>{let[a,c="ASC"]=Array.isArray(d)?d:[d],l=o?.find(u=>u.attribute===a);return l?(i[1].push(l.literal),i[0].push([r?r(`"${l.attribute}" ${c}`):`${l.attribute} ${c}`])):i[0].push(d),i},[[],[]]);return [s,n]},ct=t=>{let e={};return Object.entries(t).forEach(([o,r])=>{let s=O();if(e[s]=o.split(b)[1],Array.isArray(r))r.forEach(n=>{let i=O();e[i]=typeof n=="string"?n:n.value;});else if(typeof r=="string"||typeof r=="number"){let n=O();e[n]=r;}else if(r?.operator){let n=O();e[n]=r.value;}}),e},Tt=t=>{let e={};return t.forEach(o=>{if(o.startsWith(b)){let r=O();e[r]=o.split(b)[1];}else if(o.substring(1).startsWith(b)){let r=O();e[r]=o.substring(1).split(b)[1];}}),e},wt=(t,e)=>({...Tt(t),...ct(e)}),qt=({order:t,associationModels:e=[],replacementsMap:o={}})=>{let r=[],s=new Map;return t.forEach(n=>{if([n,n.substring(1)].some(c=>c.startsWith(b))){s.has(K)||s.set(K,{});let c=n.split(b)[1];s.get(K)[c]=M(n)?at:xt;return}let i=[k(n,e)],d=M(n);S(d?n.split(y)[1]:n,e)&&i.push(nt(n)),d&&i.push(at),r.push(i);}),{formattedOrders:r,replacementsMap:o,orderScopes:Array.from(s.entries()).map(([n,i])=>i?{method:[n,{replacementsMap:o,scopeValue:i}]}:n)}},It=t=>t||I,Mt=t=>t||q,lt=(t,e={})=>{let o=t.map(r=>{let s=e[typeof r=="string"?r:r.association||r.model];return {...typeof r!="string"&&r,association:s,required:typeof r=="string"||r.required!==false,...typeof r!="string"&&r.include&&{include:lt(r.include,s?.target?.associations)}}});return o=o.map(({model:r,...s})=>s),o},$t=(t,e,o,r=[])=>{console.log("formatQuery - input query:",JSON.stringify(t,null,2)),console.log("formatQuery - associationModels:",e);let s={},n={},i=new Map;Object.entries(t).forEach(([a,c])=>{if(console.log("formatQuery - processing field:",{queryItemKey:a,queryItemValue:c}),a.startsWith(b)){i.has(W)||i.set(W,{});let u=a.split(b)[1];i.get(W)[u]=_t(c);return}if(r.includes(a)){n[a]=c;return}let l=S(a,e)?ot(a):a;console.log("formatQuery - final key assignment:",{original:a,final:l}),s[l]=c;});let d=Array.from(i.entries()).map(([a,c])=>c?{method:[a,{replacementsMap:o,scopeValue:c}]}:a);return console.log("formatQuery - final result:",{formattedQuery:s,externalQueryValues:n,formattedScopes:d}),{formattedQuery:s,externalQueryValues:n,formattedScopes:d}},Lt=(t,e,o)=>{console.log("formatSearchTerm - inputs:",{searchTerm:t,attributesToSend:e,rawAttributesKeys:Object.keys(o)});let r=e.filter(n=>o[n].type.key==="STRING");console.log("formatSearchTerm - stringAttributes:",r);let s={$and:t.split(" ").map(n=>({$or:r.map(i=>({[i]:{$iLike:`%${n}%`}}))}))};return console.log("formatSearchTerm - generated query:",JSON.stringify(s,null,2)),s},kt=({order:t=[],page:e=I,perPage:o=q,include:r=[],query:s={},attributes:n=null,searchTerm:i=null,jsonAttributes:d={}},a,c)=>{let l=wt(t,s),u=Object.keys(a?.associations||{}),{formattedOrders:p,orderScopes:_}=qt({order:[...t,St],associationModels:u,replacementsMap:l}),[P,F]=Ft(p,c),$=G(d),T=[...F,...n||[],...$],E=n?.length?T:{include:T},L=lt(r,a?.associations),w=It(e),N=Mt(o),Y=$t(s,u,l,c?.additionalAllowedAttributes),{formattedScopes:yt,externalQueryValues:Z}=Y,{formattedQuery:A}=Y;if(i&&!c?.skipSearchTermFormat){console.log("Processing searchTerm in formatPayload:",{searchTerm:i,skipSearchTermFormat:c?.skipSearchTermFormat});let ft=n?.length?n:Object.keys(a.rawAttributes);console.log("formatPayload - formattedQuery before searchTerm processing:",JSON.stringify(A,null,2));let tt=Lt(i,ft,a.rawAttributes);A=!A||Object.keys(A).length===0?tt:{$and:[A,tt]},console.log("formatPayload - formattedQuery after searchTerm processing:",JSON.stringify(A,null,2));}return {query:A,order:P,page:w,perPage:N,include:L,scopes:[...yt,..._],...E&&{attributes:E},...Object.keys(Z).length>0&&{externalQueryValues:Z}}},dt=kt;var Qt=t=>j.includes(t.split(R)[1]),ut=(t,e=[],o=[],r=[])=>{let s=t.startsWith(C)&&t.endsWith(C)?t.slice(1,-1):t;return [...e,...o].includes(s.includes(f)?s.split(f)[0]:s)||r.includes(s)},Nt=(t,e,o,r={})=>{let s=M(t);s&&t[0]!==y&&g(`${y} must be only at the beginning of the word`);let n=s?t.split(y)[1]:t,i=S(n,o),d=k(t,o),a=r?.literalAttributes?.map(c=>c.attribute)?.includes(n);!i&&d.includes(f)&&([d]=d.split(f)),e.includes(d)||i||a||g(`${t} is invalid. isLiteralAttribute: ${a}`);},jt=(t,e)=>{e.includes(t)||g(`${t} is invalid`);},mt=(t,e,o=[],r={})=>{t.forEach(s=>Nt(s,e,o,r));},H=(t,e)=>{t.forEach(o=>jt(o,e));},Ct=(t,e)=>{let o=[...t.select?.map(r=>r.columnName)||[],...t.computed?.map(r=>r.columnName)||[]];H(o,e);},Vt=(t,e)=>{let o=Array.isArray(t)?t:Object.keys(t);if(!o?.length)return;let r=o.find(s=>!e?.enrichmentAttributes?.includes(s));r&&g(`enrichment attribute ${r} is invalid`);},Q=(t,e,o=[],r=[])=>{Object.entries(t).forEach(([s,n])=>{Array.isArray(n)?n[0]&&typeof n[0]=="object"&&n.map(i=>Q(i,e,o,r)):Qt(s)||ut(s,e,o,r)?n&&typeof n=="object"&&Q(n,e,[],r):g(`invalid key: ${s}`);});},vt=({page:t,perPage:e})=>{t<rt&&g("Page must be greater than 0"),(e>V||e<v)&&g(`PerPage must be between ${v} to ${V}`);},Dt=(t,e)=>{let o=Object.keys(e);t.forEach(r=>{ut(r.model,o);let s=e[r.model]?.target;s||g("model not found in associations");let{rawAttributes:n}=s,i=Object.keys(n);r.where&&Q(r.where,i),r.order&&mt(r.order,i),r.attributes&&H(r.attributes,i),[null,void 0,true,false].includes(r.required)||g("include.required must be a boolean");});},U=({query:t={},order:e=[],attributes:o=[],include:r=[],page:s=I,perPage:n=q,enrichments:i=[],group:d=[],jsonAttributes:a={}},c,l={})=>{let u=Object.keys(c.rawAttributes),p=Object.keys(c?.associations||{});return !o||o.length===0?o=u:H(o,u),mt(e,u,p,l),Q(t,u,p,l.additionalAllowedAttributes),Vt(i,l),Ct(a,u),Array.isArray(d)||g("group must be an array"),r.length&&typeof r=="object"?Dt(r,c?.associations):r&&typeof r!="object"&&g("include must be an array"),vt({page:s,perPage:n}),true};var {object:B,string:h,number:pt,any:Kt,array:x,alternatives:Ht}=m.types(),Ut=Jt(),Bt=B.keys({query:B,attributes:x.items(h),order:x.items(h),page:pt,perPage:pt,include:x.items(Kt),searchTerm:h,group:x.items(h),enrichments:Ht.try(x.items(h),B.pattern(h,{exclude:x.items(h)})),jsonAttributes:m.object({select:m.array().items(m.object({columnName:m.string().required(),keys:m.array().items(m.string().required()).required(),alias:m.string().optional()})).default([]),computed:m.array().items(m.object({columnName:m.string().required(),action:m.string().valid(...Object.values(J)).required(),alias:m.string().required()})).default([])}).default({})}),X=(t,e,o={})=>{let{query:r,attributes:s,order:n,page:i,perPage:d,include:a,group:c,enrichments:l,jsonAttributes:u}=e,p=Bt.validate(e);if(p.error)throw new BadRequest([p.error],null);U({query:r,attributes:s,order:n,page:i,perPage:d,include:a,enrichments:l,group:c,jsonAttributes:u},t,o);},Xt=(t,e={},o="body")=>async(r,s,n)=>{try{X(t,r[o],e),n();}catch(i){let{query:d,attributes:a,order:c}=r[o];handleError(i,s,{logger:e.logger||Ut,message:"error in query middleware",payload:{error:i,query:d,attributes:a,order:c}});}},z=(t,e,o={})=>{let{order:r,page:s,perPage:n,include:i,query:d,attributes:a,searchTerm:c,jsonAttributes:l}=e,{query:u,externalQueryValues:p,order:_,page:P,perPage:F,include:$,scopes:T,attributes:E}=dt({query:d,order:r,page:s,perPage:n,include:i,attributes:a,searchTerm:c,jsonAttributes:l},t,o);e.query=u,e.externalQueryValues=p,e.order=_,e.attributes=E,e.page=P,e.perPage=F,e.include=$,e.scopes=T,o.includeRawPayload&&(e.rawPayload={order:r,page:s,perPage:n,include:i,query:d,attributes:a,searchTerm:c});},zt=(t,e={},o="body")=>async(r,s,n)=>{z(t,r[o],e),n();};var Zt=({model:t,logger:e,validationOptions:o,formatOptions:r,modelName:s=t.constructor?.name,additionalScopes:n=[],modifyQueryValues:i,onRowsRetrieved:d})=>async(a,c)=>{try{X(t,a.body,{...o,logger:e});}catch(l){let u=D(a.body,["query","order","attributes"]);handleError(l,c,{logger:e,message:"error in query endpoint",payload:u});return}try{e.info("BEFORE queryFormat - req.body:",{body:a.body}),z(t,a.body,r),e.info("AFTER queryFormat - req.body:",{body:a.body});let l=Object.assign(D(a.body,["query","externalQueryValues","order","attributes","page","perPage","include","scopes","enrichments"]),{distinct:!0});e.info("queryValues after pick:",{queryValues:l});let u=i?.(l)??l;e.info("modifiedQuery:",{modifiedQuery:u});let{scopes:p=[],query:_,perPage:P,page:F,enrichments:$,externalQueryValues:T,...E}=u,L={where:_,limit:P,offset:(F-1)*P,...E};e.info("Sequelize query object:",{sequelizeQuery:L,scopes:[...n,...p]});let w=await t.scope([...n,...p]).findAndCountAll(L);if(!w.rows.length||!d){c.json(w);return}let N=await d(w,u);c.json(N);}catch(l){e.error("Raw error caught in queryHandler:",{error:l,errorMessage:l.message,errorStack:l.stack,errorName:l.name,originalRequestBody:a.body}),handleError(new UnexpectedError(l),c,{logger:e,message:`Error while querying ${s}`,payload:{query:a.body}});}};export{bt as formatOperators,ct as generateFilterReplacements,zt as queryFormatMiddleware,Zt as queryHandler,Xt as queryValidationMiddleware,U as validatePayload};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["DefaultOp","Op","order","replacements: Record<string, string>","replacementMap: Record<string, string>","formattedOrders: SequelizeOrder[]","formattedQuery: Record<string, unknown>","externalQueryValues: Record<string, unknown>","formatPayload"],"sources":["../src/operators/index.ts","../src/utils.ts","../src/formatter/jsonAttributesFormater.ts","../src/formatter/index.ts","../src/validations/index.ts","../src/middleware/index.ts","../src/handler/index.ts"],"sourcesContent":["import { Op as DefaultOp } from 'sequelize';\n\nexport const OPERATORS = [\n 'eq',\n 'ne',\n 'gte',\n 'gt',\n 'lte',\n 'lt',\n 'not',\n 'in',\n 'notIn',\n 'is',\n 'like',\n 'iLike',\n 'notLike',\n 'between',\n 'and',\n 'or',\n 'overlap',\n 'contains',\n] as const;\n\nexport const OPERATOR_PREFIX = '$';\n\nexport const OPERATORS_TO_SQL = {\n $eq: '=',\n $ne: '!=',\n $gte: '>=',\n $gt: '>',\n $lte: '<=',\n $lt: '<',\n $not: 'NOT',\n $in: 'IN',\n $notIn: 'NOT IN',\n $is: 'IS',\n $like: 'LIKE',\n $iLike: 'ILIKE',\n $notLike: 'NOT LIKE',\n $and: 'AND',\n $or: 'OR',\n};\n\nexport const formatOperators = (sequelize: { Op: typeof DefaultOp; } = { Op: DefaultOp }): Record<string, symbol> => {\n const { Op } = sequelize;\n return Object.fromEntries(OPERATORS.map(o => [`${OPERATOR_PREFIX + o}`, Op[o]]));\n};\n","import { randomInt } from 'node:crypto';\nimport { BadRequest } from '@autofleet/errors';\nimport { OPERATOR_PREFIX } from './operators';\n\nexport const ORDER_PREFIX = '-';\nexport const ASSOCIATION_PREFIX = '.';\nexport const ASSOCIATION_PATH_WRAPPER = '$';\nexport const PER_PAGE_DEFAULT = 20;\nexport const PAGE_DEFAULT = 1;\nexport const PER_PAGE_MAX_LIMIT = 100;\nexport const PER_PAGE_MIN_LIMIT = 1;\nexport const PAGE_MIN = 1;\n\nexport const wrapAttributeWithOperator = (attribute: string) => `${OPERATOR_PREFIX}${attribute}${OPERATOR_PREFIX}`;\nexport const isAttributeByAssociation = (attributeName: string, associatedModels: string[]): boolean => attributeName.includes(ASSOCIATION_PREFIX)\n && associatedModels.includes(attributeName.split(ASSOCIATION_PREFIX, 1)[0]);\n\nexport const extractAttributeNameFromOrder = (order: string, associationModels: string[]): string => {\n let formattedOrder = order;\n if (order.includes(ORDER_PREFIX)) {\n [, formattedOrder] = formattedOrder.split(ORDER_PREFIX, 2);\n }\n if (isAttributeByAssociation(formattedOrder, associationModels)) {\n [formattedOrder] = formattedOrder.split(ASSOCIATION_PREFIX, 1);\n }\n return formattedOrder;\n};\n\nexport const isOrderDesc = (order: string): boolean => order.includes(ORDER_PREFIX);\n\nexport const throwBadRequestError = (message: string): never => {\n throw new BadRequest([new Error(message)]);\n};\n\nexport const extractAssociatedAttributeNameFromOrder = (order: string): string => order.split(ASSOCIATION_PREFIX, 2)[1];\n\nexport const generateRandomString = (length = 5): string => {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n return Array.from({ length }, () => characters.charAt(randomInt(characters.length))).join('');\n};\n\nexport const pick = <T extends object, K extends keyof T = keyof T>(\n obj: T,\n keys: K[],\n): Pick<T, K> => Object.fromEntries(keys.map(key => [key, obj[key]])) as Pick<T, K>;\n","import { literal } from 'sequelize';\n\nexport const ComputedActions = {\n length: 'length',\n} as const;\n\ninterface JsonSelectAttribute {\n columnName: string;\n keys: string[];\n alias?: string;\n}\n\ninterface JsonComputedAttribute {\n columnName: string;\n action: keyof typeof ComputedActions;\n alias: string;\n}\n\nexport interface JsonAttributes {\n select?: JsonSelectAttribute[];\n computed?: JsonComputedAttribute[];\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/(?!^)[A-Z]/g, letter => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Builds a computed attribute based on the action specified.\n * Currently, supports 'length' action which calculates the length of a JSON array.\n *\n * @param {JsonComputedAttribute} computedAttribute - The computed attribute definition.\n * @returns {Array} An array containing the SQL literal and the alias for the computed attribute.\n */\nfunction buildComputedAttribute(computedAttribute: JsonComputedAttribute) {\n switch (computedAttribute.action) {\n case ComputedActions.length: {\n // Generates: jsonb_array_length(column)\n // Returns the length of the JSON array (e.g., [\"a\", \"b\"] -> 2)\n // Note: Expects the column to be a JSON array\n const sql = `jsonb_array_length(${toSnakeCase(computedAttribute.columnName)})`;\n return [literal(sql), computedAttribute.alias];\n }\n default:\n computedAttribute.action satisfies never;\n return [];\n }\n}\n\nfunction buildComputedAttributes(computed: JsonComputedAttribute[]) {\n return computed.map(attr => buildComputedAttribute(attr));\n}\n\n/**\n * Builds a list of SQL select attributes using json_build_object\n * to extract specific keys from a JSONB column.\n *\n * Example output:\n * SELECT json_build_object('a', column -> 'a', 'b', column -> 'b') AS alias\n */\nfunction buildSelectAttributes(select: JsonSelectAttribute[]) {\n return select.map((attr) => {\n const columnNameSnake = toSnakeCase(attr.columnName);\n const sql = `json_build_object(${attr.keys\n .map(k => `'${k}', ${columnNameSnake} -> '${k}'`)\n .join(', ')})`;\n const alias = attr.alias || attr.columnName;\n return [literal(sql), alias];\n });\n}\n\n/**\n * Return a single array combining selected and computed attributes.\n * Format: [[literal, alias], [literal, alias], ...]\n */\nexport default function buildJsonAttributes({ select = [], computed = [] }: JsonAttributes = {}): (string | ReturnType<typeof literal>)[][] {\n const selectAttributes = buildSelectAttributes(select);\n const computedAttributes = buildComputedAttributes(computed);\n\n return [...selectAttributes, ...computedAttributes];\n}\n","import type { literal } from 'sequelize';\nimport { customFields } from '@autofleet/common-types';\nimport {\n extractAssociatedAttributeNameFromOrder,\n extractAttributeNameFromOrder, generateRandomString,\n isAttributeByAssociation,\n isOrderDesc, ORDER_PREFIX,\n PAGE_DEFAULT,\n PER_PAGE_DEFAULT, wrapAttributeWithOperator,\n} from '../utils';\nimport type { LiteralAttribute } from '../middleware';\nimport { OPERATORS_TO_SQL } from '../operators';\nimport buildJsonAttributes, { type JsonAttributes } from './jsonAttributesFormater';\n\nconst DEFAULT_ORDER = 'id';\nconst DESCENDING_KEY = 'DESC';\nconst ASCENDING_KEY = 'ASC';\nconst CUSTOM_FIELDS_QUERY_PREFIX = 'customFields.';\nconst { CUSTOM_FIELDS_FILTER_SCOPE, CUSTOM_FIELDS_SORT_SCOPE } = customFields;\ntype OrderItem = string | [string, string];\ntype SequelizeOrder = string | OrderItem[];\nexport interface FormatPayloadOptions {\n includeRawPayload?: boolean;\n literalAttributes?: LiteralAttribute[];\n DBFormatter?: typeof literal;\n skipSearchTermFormat?: boolean;\n additionalAllowedAttributes?: string[];\n}\n\ninterface ConditionWithOperator {\n operator: string;\n value: string;\n}\nexport type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];\n\nconst parseCustomFieldScopeQueryValue = (value: unknown) => {\n if (['string', 'number'].includes(typeof value) || Array.isArray(value)) {\n return value;\n }\n return Object.entries(value as object).map(([operator, conditionValue]) => ({\n operator: OPERATORS_TO_SQL[operator as keyof typeof OPERATORS_TO_SQL],\n value: conditionValue,\n }));\n};\n\nconst getAttributeFromOrder = (order: SequelizeOrder[], options: FormatPayloadOptions = {}): [(SequelizeOrder | Literal)[], SequelizeOrder[]] => {\n const { literalAttributes = [], DBFormatter = undefined } = options;\n const [formattedOrder, attributes] = order.reduce<[(SequelizeOrder | Literal)[], SequelizeOrder[]]>((acc, o) => {\n const [item, orderStyle = 'ASC'] = Array.isArray(o) ? o : [o];\n const found = literalAttributes?.find(obj => obj.attribute === item);\n if (found) {\n const order = DBFormatter ? DBFormatter(`\"${found.attribute}\" ${orderStyle as string}`) : `${found.attribute} ${orderStyle as string}`;\n acc[1].push(found.literal);\n acc[0].push([order as string]);\n } else {\n acc[0].push(o);\n }\n return acc;\n }, [[], []]);\n\n return [formattedOrder, attributes];\n};\n\n/**\n * Generates replacements for the given conditions.\n *\n * @param conditions - The conditions to generate replacements for.\n * @returns The replacements object.\n */\nexport const generateFilterReplacements = (conditions: Record<string, ConditionValue>): Record<string, string> => {\n const replacements: Record<string, string> = {};\n\n Object.entries(conditions).forEach(([key, condition]) => {\n const replacementKey = generateRandomString();\n replacements[replacementKey] = key.split(CUSTOM_FIELDS_QUERY_PREFIX, 2)[1];\n\n if (Array.isArray(condition)) {\n condition.forEach((value) => {\n const valueKey = generateRandomString();\n replacements[valueKey] = typeof value === 'string' ? value : value.value;\n });\n } else if (typeof condition === 'string' || typeof condition === 'number') {\n const conditionKey = generateRandomString();\n replacements[conditionKey] = condition;\n } else if (condition?.operator) {\n const operatorKey = generateRandomString();\n replacements[operatorKey] = condition.value;\n }\n });\n\n return replacements;\n};\n\n/**\n * Generates replacements for the given order array.\n *\n * @param order - The order array to generate replacements for.\n * @returns The replacements object.\n */\nexport const generateOrderReplacements = (order: string[]): Record<string, string> => {\n const replacementMap: Record<string, string> = {};\n order.forEach((o) => {\n if (o.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n const rand = generateRandomString();\n replacementMap[rand] = o.split(CUSTOM_FIELDS_QUERY_PREFIX, 2)[1];\n } else if (o.substring(1).startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n const rand = generateRandomString();\n replacementMap[rand] = o.substring(1).split(CUSTOM_FIELDS_QUERY_PREFIX, 2)[1];\n }\n });\n return replacementMap;\n};\n\n/**\n * Creates a combined replacement map from order and query.\n *\n * @param order - The order array.\n * @param query - The query object.\n * @returns The combined replacements object.\n */\nconst createReplacementMap = (order: string[], query: Record<string, ConditionValue>): Record<string, string> => ({\n ...generateOrderReplacements(order),\n ...generateFilterReplacements(query),\n});\n\nconst formatOrder = ({\n order,\n associationModels = [],\n replacementsMap = {},\n}: { order: string[]; associationModels?: string[]; replacementsMap?: Record<string, string>; }): {\n formattedOrders: SequelizeOrder[];\n orderScopes: (string | { method: [string, { replacementsMap: Record<string, string>; scopeValue: Record<string, 'DESC' | 'ASC'>; }]; })[];\n replacementsMap: Record<string, string>;\n} => {\n const formattedOrders: SequelizeOrder[] = [];\n const orderScopesMap = new Map<string, Record<string, 'DESC' | 'ASC'>>();\n order.forEach((o) => {\n if ([o, o.substring(1)].some(t => t.startsWith(CUSTOM_FIELDS_QUERY_PREFIX))) {\n if (!orderScopesMap.has(CUSTOM_FIELDS_SORT_SCOPE)) {\n orderScopesMap.set(CUSTOM_FIELDS_SORT_SCOPE, {});\n }\n const scopeKey = o.split(CUSTOM_FIELDS_QUERY_PREFIX, 2)[1];\n orderScopesMap.get(CUSTOM_FIELDS_SORT_SCOPE)![scopeKey] = (isOrderDesc(o) ? DESCENDING_KEY : ASCENDING_KEY);\n return;\n }\n const formattedOrder = [extractAttributeNameFromOrder(o, associationModels)];\n const isOrderDescOrder = isOrderDesc(o);\n const isOrderAssociation = isAttributeByAssociation(isOrderDescOrder\n ? o.split(ORDER_PREFIX, 2)[1]\n : o, associationModels);\n if (isOrderAssociation) {\n formattedOrder.push(extractAssociatedAttributeNameFromOrder(o));\n }\n if (isOrderDescOrder) {\n formattedOrder.push(DESCENDING_KEY);\n }\n formattedOrders.push(formattedOrder);\n });\n return {\n formattedOrders,\n replacementsMap,\n orderScopes: Array.from(orderScopesMap.entries()).map(([scopeName, scopeValue]) => {\n /* v8 ignore next 3 */\n if (!scopeValue) {\n return scopeName;\n }\n return {\n method: [scopeName, {\n replacementsMap,\n scopeValue,\n }],\n };\n }),\n };\n};\n\nconst formatPage = (page?: number) => page || PAGE_DEFAULT;\n\nconst formatPerPage = (perPage?: number) => perPage || PER_PAGE_DEFAULT;\n\ninterface Include {\n association?: string;\n model?: string;\n required?: boolean;\n include?: Include[];\n}\n\nconst formatInclude = (include: (string | Include)[], associationsMap: Record<string, any> = {}) => {\n let formattedInclude = include.map((i): any => {\n const includedAssociation = associationsMap[typeof i === 'string' ? i : (i.association || i.model!)];\n return {\n ...(typeof i !== 'string' && i),\n association: includedAssociation,\n required: typeof i === 'string' || i.required !== false,\n ...(typeof i !== 'string' && i.include && {\n include: formatInclude(i.include, includedAssociation?.target?.associations),\n }),\n };\n });\n formattedInclude = formattedInclude.map(({ model: _model, ...i }) => i);\n return formattedInclude;\n};\nconst formatQuery = (query: Record<string, unknown>, associationModels: string[], replacementsMap: Record<string, string>, additionalAllowedAttributes: string[] = []) => {\n const formattedQuery: Record<string, unknown> = {};\n const externalQueryValues: Record<string, unknown> = {};\n const formattedScopeMap = new Map<string, any>();\n\n Object.entries(query).forEach(([queryItemKey, queryItemValue]) => {\n if (queryItemKey.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n if (!formattedScopeMap.has(CUSTOM_FIELDS_FILTER_SCOPE)) {\n formattedScopeMap.set(CUSTOM_FIELDS_FILTER_SCOPE, {});\n }\n const scopeKey = queryItemKey.split(CUSTOM_FIELDS_QUERY_PREFIX, 2)[1];\n formattedScopeMap.get(CUSTOM_FIELDS_FILTER_SCOPE)[scopeKey] = parseCustomFieldScopeQueryValue(queryItemValue);\n return;\n }\n if (additionalAllowedAttributes.includes(queryItemKey)) {\n externalQueryValues[queryItemKey] = queryItemValue;\n return;\n }\n const key = isAttributeByAssociation(queryItemKey, associationModels)\n ? wrapAttributeWithOperator(queryItemKey)\n : queryItemKey;\n formattedQuery[key] = queryItemValue;\n });\n\n const formattedScopes = Array.from(formattedScopeMap.entries()).map(([scopeName, scopeValue]) => {\n /* v8 ignore next 3 */\n if (!scopeValue) {\n return scopeName;\n }\n return {\n method: [scopeName, {\n replacementsMap,\n scopeValue,\n }],\n };\n });\n\n return {\n formattedQuery,\n externalQueryValues,\n formattedScopes,\n };\n};\n\nconst formatSearchTerm = (searchTerm: string, attributesToSend: string[], rawAttributes: Record<string, any>) => ({\n $and: searchTerm.split(' ').map(term => ({\n $or: attributesToSend.filter(attrKey => rawAttributes[attrKey].type.key === 'STRING').map(attr => ({\n [attr]: {\n $iLike: `%${term}%`,\n },\n })),\n })),\n});\n\ninterface FormatPayloadData {\n order?: string[];\n page?: number;\n perPage?: number;\n include?: (string | Include)[];\n query?: Record<string, unknown>;\n attributes?: string[] | null;\n searchTerm?: string | null;\n jsonAttributes?: JsonAttributes;\n}\ntype Literal = ReturnType<typeof literal>;\n\ninterface FormattedPayload {\n query: Record<string, unknown>;\n\n externalQueryValues?: Record<string, unknown>;\n attributes: (SequelizeOrder | (string | Literal)[])[] | {\n include: (SequelizeOrder | (string | Literal)[])[];\n };\n order: (SequelizeOrder | Literal)[];\n page: number;\n perPage: number;\n include: any;\n scopes: (string | {\n method: (string | {\n replacementsMap: Record<string, string>;\n scopeValue: any;\n })[];\n })[];\n}\n\nconst formatPayload = ({\n order = [],\n page = PAGE_DEFAULT,\n perPage = PER_PAGE_DEFAULT,\n include = [],\n query = {},\n attributes = null,\n searchTerm = null,\n jsonAttributes = {},\n}: FormatPayloadData, model?: any, options?: FormatPayloadOptions): FormattedPayload => {\n const replacementsMap = createReplacementMap(order, query as Record<string, ConditionValue>);\n const associationModels = Object.keys(model?.associations || {});\n const { formattedOrders, orderScopes } = formatOrder({\n order: [...order, DEFAULT_ORDER],\n associationModels,\n replacementsMap,\n });\n const [filteredFormattedOrder, filteredLiteralAttributes] = getAttributeFromOrder(\n formattedOrders,\n options,\n );\n\n const formattedJsonAttributes = buildJsonAttributes(jsonAttributes);\n const allAttributes = [...filteredLiteralAttributes, ...(attributes ?? []), ...formattedJsonAttributes];\n const formattedAttribute = attributes?.length ? allAttributes : { include: allAttributes };\n\n const formattedInclude = formatInclude(include, model?.associations);\n const formattedPage = formatPage(page);\n const formattedPerPage = formatPerPage(perPage);\n const result = formatQuery(query, associationModels, replacementsMap, options?.additionalAllowedAttributes);\n const { formattedScopes: queryScopes, externalQueryValues } = result;\n let { formattedQuery } = result;\n if (searchTerm && !options?.skipSearchTermFormat) {\n const attributesToSend = attributes?.length ? attributes : Object.keys(model.rawAttributes || {});\n const queryWithSearchTerm = formatSearchTerm(searchTerm, attributesToSend, model.rawAttributes);\n formattedQuery = !formattedQuery || Object.keys(formattedQuery).length === 0 ? queryWithSearchTerm : {\n $and: [\n formattedQuery,\n queryWithSearchTerm,\n ],\n };\n }\n return {\n query: formattedQuery,\n order: filteredFormattedOrder,\n page: formattedPage,\n perPage: formattedPerPage,\n include: formattedInclude,\n scopes: [...queryScopes, ...orderScopes],\n ...(formattedAttribute && { attributes: formattedAttribute }),\n ...(Object.keys(externalQueryValues).length > 0 && { externalQueryValues }),\n };\n};\n\nexport default formatPayload;\n","import {\n ORDER_PREFIX,\n extractAttributeNameFromOrder,\n isOrderDesc,\n throwBadRequestError,\n PAGE_DEFAULT,\n PER_PAGE_DEFAULT,\n PAGE_MIN,\n PER_PAGE_MAX_LIMIT,\n PER_PAGE_MIN_LIMIT,\n isAttributeByAssociation,\n ASSOCIATION_PREFIX,\n ASSOCIATION_PATH_WRAPPER,\n} from '../utils';\nimport { OPERATORS, OPERATOR_PREFIX } from '../operators';\nimport type { MiddlewareValidationOption } from '../middleware';\nimport type { JsonAttributes } from '../formatter/jsonAttributesFormater';\n\nconst validateOperator = (operator: string): boolean => OPERATORS.includes(operator.split(OPERATOR_PREFIX, 2)[1] as typeof OPERATORS[number]);\n\nconst validateQueryAttribute = (\n rawAttribute: string,\n modelAttributes: string[] = [],\n associationModels: string[] = [],\n additionalAllowedAttributes: string[] = [],\n): boolean => {\n const attribute = (rawAttribute.startsWith(\n ASSOCIATION_PATH_WRAPPER,\n ) && rawAttribute.endsWith(\n ASSOCIATION_PATH_WRAPPER,\n )) ? rawAttribute.slice(1, -1) : rawAttribute;\n return [...modelAttributes, ...associationModels].includes(attribute.includes(ASSOCIATION_PREFIX)\n ? attribute.split(ASSOCIATION_PREFIX, 1)[0] : attribute)\n || additionalAllowedAttributes.includes(attribute);\n};\n\nconst validateSingleOrder = (\n currentOrder: string,\n rawAttributes: string[],\n associationModels: string[],\n options: MiddlewareValidationOption = {},\n): void => {\n const isOrderDescOrder = isOrderDesc(currentOrder);\n if (isOrderDescOrder && !currentOrder.startsWith(ORDER_PREFIX)) {\n throwBadRequestError(`${ORDER_PREFIX} must be only at the beginning of the word`);\n }\n const orderStringWithoutDesc = isOrderDescOrder ? currentOrder.split(ORDER_PREFIX, 2)[1] : currentOrder;\n const isOrderAssociation = isAttributeByAssociation(orderStringWithoutDesc, associationModels);\n let formattedOrderString = extractAttributeNameFromOrder(currentOrder, associationModels);\n const isLiteralAttribute = options?.literalAttributes?.map(la => la.attribute)?.includes(orderStringWithoutDesc);\n\n if (!isOrderAssociation && formattedOrderString.includes(ASSOCIATION_PREFIX)) {\n [formattedOrderString] = formattedOrderString.split(ASSOCIATION_PREFIX, 1);\n }\n\n if (!(rawAttributes.includes(formattedOrderString) || isOrderAssociation || isLiteralAttribute)) {\n throwBadRequestError(`${currentOrder} is invalid. isLiteralAttribute: ${isLiteralAttribute}`);\n }\n};\n\nconst validateSingleAttribute = (currentAttribute: string, rawAttributes: string[]): void => {\n if (!rawAttributes.includes(currentAttribute)) {\n throwBadRequestError(`${currentAttribute} is invalid`);\n }\n};\n\nconst validateOrderAttributes = (\n order: string[],\n rawAttributes: string[],\n associationModels: string[] = [],\n options: MiddlewareValidationOption = {},\n): void => {\n order.forEach(o => validateSingleOrder(o, rawAttributes, associationModels, options));\n};\n\nconst validateAttributes = (attributes: string[], rawAttributes: string[]): void => {\n attributes.forEach(a => validateSingleAttribute(a, rawAttributes));\n};\n\nconst validateJsonAttributes = (jsonAttributes: JsonAttributes, rawAttributes: string[]): void => {\n const allAttributes = [\n ...(jsonAttributes.select?.map(s => s.columnName) ?? []),\n ...(jsonAttributes.computed?.map(c => c.columnName) ?? []),\n ];\n\n validateAttributes(allAttributes, rawAttributes);\n};\n\n// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style\nconst validateEnrichments = (enrichments: string[] | { [enrichmentName: string]: { exclude?: string[]; }; }, options?: MiddlewareValidationOption): void => {\n const enrichmentKeys = Array.isArray(enrichments) ? enrichments : Object.keys(enrichments);\n if (!enrichmentKeys?.length) {\n return;\n }\n const invalidEnrichment = enrichmentKeys.find(enrichment => !options?.enrichmentAttributes?.includes(enrichment));\n if (invalidEnrichment) {\n throwBadRequestError(`enrichment attribute ${invalidEnrichment} is invalid`);\n }\n};\n\nconst validateQueryPayload = (query: object, rawAttributes: string[], associationModels: string[] = [], additionalAllowedAttributes: string[] = []): void => {\n Object.entries(query).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n if (value[0] && typeof value[0] === 'object') {\n value.map(v => validateQueryPayload(v, rawAttributes, associationModels, additionalAllowedAttributes));\n }\n } else if (validateOperator(key) || validateQueryAttribute(key, rawAttributes, associationModels, additionalAllowedAttributes)) {\n if (value && typeof value === 'object') {\n validateQueryPayload(value, rawAttributes, [], additionalAllowedAttributes);\n }\n } else {\n throwBadRequestError(`invalid key: ${key}`);\n }\n });\n};\n\nconst validatePagination = ({\n page,\n perPage,\n}: { page: number; perPage: number; }) => {\n if (page < PAGE_MIN) {\n throwBadRequestError('Page must be greater than 0');\n }\n\n if (perPage > PER_PAGE_MAX_LIMIT || perPage < PER_PAGE_MIN_LIMIT) {\n throwBadRequestError(`PerPage must be between ${PER_PAGE_MIN_LIMIT} to ${PER_PAGE_MAX_LIMIT}`);\n }\n};\n\nconst validateIncludePayload = (include: any[], associations: Record<string, any>): void => {\n const associationsKeys = Object.keys(associations);\n include.forEach((i) => {\n validateQueryAttribute(i.model, associationsKeys);\n const target = associations[i.model]?.target;\n if (!target) {\n throwBadRequestError('model not found in associations');\n }\n\n const { rawAttributes } = target;\n const attributeKeys = Object.keys(rawAttributes);\n if (i.where) {\n validateQueryPayload(i.where, attributeKeys);\n }\n if (i.order) {\n validateOrderAttributes(i.order, attributeKeys);\n }\n if (i.attributes) {\n validateAttributes(i.attributes, attributeKeys);\n }\n if (![null, undefined, true, false].includes(i.required)) {\n throwBadRequestError('include.required must be a boolean');\n }\n });\n};\n\ninterface PayloadValidationData {\n query?: object;\n order?: string[];\n attributes?: string[];\n include?: any[];\n page?: number;\n perPage?: number;\n // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style\n enrichments?: string[] | { [enrichmentName: string]: { exclude?: string[]; }; };\n group?: string[];\n jsonAttributes?: {\n select?: { columnName: string; keys: string[]; alias?: string; }[];\n computed?: { columnName: string; action: 'length'; alias: string; }[];\n };\n}\n\nexport const validatePayload = (\n {\n query = {},\n order = [],\n attributes = [],\n include = [],\n page = PAGE_DEFAULT,\n perPage = PER_PAGE_DEFAULT,\n enrichments = [],\n group = [],\n jsonAttributes = {},\n }: PayloadValidationData,\n model?: any,\n options: MiddlewareValidationOption = {},\n): boolean => {\n const rawAttributes = Object.keys(model.rawAttributes);\n const associationModels = Object.keys(model?.associations || {});\n if (!attributes || attributes.length === 0) {\n attributes = rawAttributes;\n } else {\n validateAttributes(attributes, rawAttributes);\n }\n\n validateOrderAttributes(order, rawAttributes, associationModels, options);\n validateQueryPayload(query, rawAttributes, associationModels, options.additionalAllowedAttributes);\n validateEnrichments(enrichments, options);\n validateJsonAttributes(jsonAttributes, rawAttributes);\n\n if (!Array.isArray(group)) {\n throwBadRequestError('group must be an array');\n }\n if (include.length && typeof include === 'object') {\n validateIncludePayload(include, model?.associations);\n } else if (include && typeof include !== 'object') {\n throwBadRequestError('include must be an array');\n }\n\n validatePagination({\n page,\n perPage,\n });\n return true;\n};\n","import type { Handler } from 'express';\nimport Logger, { type LoggerInstanceManager } from '@autofleet/logger';\nimport { BadRequest, handleError } from '@autofleet/errors';\nimport Joi from 'joi';\nimport formatPayload, { type FormatPayloadOptions } from '../formatter';\nimport { validatePayload } from '../validations';\nimport { ComputedActions } from '../formatter/jsonAttributesFormater';\n\nconst {\n object, string, number, any, array, alternatives,\n} = Joi.types();\nconst fallbackLogger = Logger();\n\nconst querySchema = object.keys({\n query: object,\n attributes: array.items(string),\n order: array.items(string),\n page: number,\n perPage: number,\n include: array.items(any),\n searchTerm: string,\n group: array.items(string),\n enrichments: alternatives.try(array.items(string), object.pattern(string, { exclude: array.items(string) })),\n jsonAttributes: Joi.object({\n select: Joi.array().items(\n Joi.object({\n columnName: Joi.string().required(),\n keys: Joi.array().items(Joi.string().required()).required(),\n alias: Joi.string().optional(),\n }),\n ).default([]),\n computed: Joi.array().items(\n Joi.object({\n columnName: Joi.string().required(),\n action: Joi.string().valid(...Object.values(ComputedActions)).required(),\n alias: Joi.string().required(),\n }),\n ).default([]),\n }).default({}),\n});\n\ntype literal = any;\ntype LiteralQuery = (literal | string)[] | literal;\nexport interface LiteralAttribute { attribute: string; literal: LiteralQuery; }\nexport interface MiddlewareValidationOption {\n literalAttributes?: LiteralAttribute[];\n enrichmentAttributes?: string[];\n additionalAllowedAttributes?: string[];\n logger?: LoggerInstanceManager;\n}\n\ntype ReqKeys = 'body' | 'query';\n\nexport const queryValidation = (model: any, data: any, options: MiddlewareValidationOption = {}): void => {\n const {\n query,\n attributes,\n order,\n page,\n perPage,\n include,\n group,\n enrichments,\n jsonAttributes,\n } = data;\n\n const result = querySchema.validate(data);\n if (result.error) {\n throw new BadRequest([result.error]);\n }\n validatePayload({\n query,\n attributes,\n order,\n page,\n perPage,\n include,\n enrichments,\n group,\n jsonAttributes,\n }, model, options);\n};\n\n/** consider using @see {@link queryHandler} directly */\nexport const queryValidationMiddleware = (model: any, options: MiddlewareValidationOption = {}, inner: ReqKeys = 'body'): Handler => (req, res, next): void => {\n try {\n queryValidation(model, req[inner], options);\n next();\n } catch (error) {\n const { query, attributes, order } = req[inner];\n handleError(error as Error, res, {\n logger: options.logger ?? fallbackLogger,\n message: 'error in query middleware',\n payload: {\n error,\n query,\n attributes,\n order,\n },\n });\n }\n};\n\nexport const queryFormat = (model: any, data: any, options: FormatPayloadOptions = {}): void => {\n const {\n order, page, perPage, include, query, attributes, searchTerm, jsonAttributes,\n } = data;\n\n const {\n query: formattedQuery,\n externalQueryValues,\n order: formattedOrder,\n page: formattedPage,\n perPage: formattedPerPage,\n include: formattedInclude,\n scopes: formattedScopes,\n attributes: formattedAttribute,\n } = formatPayload({\n query, order, page, perPage, include, attributes, searchTerm, jsonAttributes,\n }, model, options);\n\n data.query = formattedQuery;\n data.externalQueryValues = externalQueryValues;\n data.order = formattedOrder;\n data.attributes = formattedAttribute;\n data.page = formattedPage;\n data.perPage = formattedPerPage;\n data.include = formattedInclude;\n data.scopes = formattedScopes;\n if (options.includeRawPayload) {\n data.rawPayload = {\n order,\n page,\n perPage,\n include,\n query,\n attributes,\n searchTerm,\n };\n }\n};\n\n/** consider using @see {@link queryHandler} directly */\nexport const queryFormatMiddleware = (model: any, options: FormatPayloadOptions = {}, inner: ReqKeys = 'body'): Handler => (req, _res, next): void => {\n queryFormat(model, req[inner], options);\n next();\n};\n","import type { Handler } from 'express';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport { UnexpectedError, handleError } from '@autofleet/errors';\nimport type formatPayload from '../formatter';\nimport type { FormatPayloadOptions } from '../formatter';\nimport { pick } from '../utils';\nimport { type MiddlewareValidationOption, queryFormat, queryValidation } from '../middleware';\n\ninterface QueryValues extends ReturnType<typeof formatPayload> {\n enrichments?: string[] | Record<string, { exclude: string[]; }>;\n distinct: boolean;\n searchTerm?: string;\n}\n\ninterface QueryHandlerOptions {\n /** The sequelize model too which querying abilities are added. */\n model: any;\n /** Optional settings for validation. */\n validationOptions?: Omit<MiddlewareValidationOption, 'logger'>;\n /** Optional settings for payload formatting */\n formatOptions?: FormatPayloadOptions;\n logger: LoggerInstanceManager;\n /** The name of model to be printed in logs. defaults to `model`s constructor name. */\n modelName?: string;\n /** Sequelize scopes of the model to be used within the query. @example ['userScope'] */\n additionalScopes?: string[];\n /** Callback to allow modifying the query values prior to querying the DB */\n modifyQueryValues?: (queryValues: QueryValues) => QueryValues;\n /** Optional callback to modify endpoint's response based on the DBs response. */\n onRowsRetrieved?: (data: { rows: any[]; count: number; }, queryValues: QueryValues) => any;\n}\n\ntype Asyncify<T extends (...a: any[]) => any> = (...a: Parameters<T>) => Promise<Awaited<ReturnType<T>>>;\n\nexport const queryHandler = ({\n model, logger, validationOptions, formatOptions, modelName = model.constructor?.name, additionalScopes = [], modifyQueryValues, onRowsRetrieved,\n}: QueryHandlerOptions): Asyncify<Handler> => async (req, res) => {\n try {\n queryValidation(model, req.body, { ...validationOptions, logger });\n } catch (error) {\n const payload = pick(req.body as QueryValues, ['query', 'order', 'attributes'] as const);\n handleError(error as Error, res, { logger, message: 'error in query endpoint', payload });\n return;\n }\n try {\n queryFormat(model, req.body, formatOptions);\n\n const queryValues = Object.assign(\n pick(req.body as QueryValues, ['query', 'externalQueryValues', 'order', 'attributes', 'page', 'perPage', 'include', 'scopes', 'enrichments'] as const),\n { distinct: true },\n );\n\n logger.info(`querying ${modelName}`, { queryValues });\n\n const modifiedQuery = modifyQueryValues?.(queryValues) ?? queryValues;\n const {\n scopes = [],\n query: where,\n perPage: limit,\n page,\n enrichments: _enrichments,\n externalQueryValues: _externalQueryValues,\n ...rest\n } = modifiedQuery;\n\n const result = await model.scope([...additionalScopes, ...scopes]).findAndCountAll({\n where,\n limit,\n offset: (page - 1) * limit,\n ...rest,\n });\n\n if (!result.rows.length || !onRowsRetrieved) {\n res.json(result);\n return;\n }\n\n const enrichmentResult = await onRowsRetrieved(result, modifiedQuery);\n\n res.json(enrichmentResult);\n } catch (error) {\n handleError(new UnexpectedError(error as Error), res, { logger, message: `Error while querying ${modelName}`, payload: { query: req.body } });\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/operators/index.ts","../src/utils.ts","../src/formatter/jsonAttributesFormater.ts","../src/formatter/index.ts","../src/validations/index.ts","../src/middleware/index.ts","../src/handler/index.ts"],"names":["OPERATORS","OPERATOR_PREFIX","OPERATORS_TO_SQL","formatOperators","Sequelize","Op","map","o","randomInt","max","ORDER_PREFIX","ASSOCIATION_PREFIX","ASSOCIATION_PATH_WRAPPER","PER_PAGE_DEFAULT","PAGE_DEFAULT","PER_PAGE_MAX_LIMIT","PER_PAGE_MIN_LIMIT","PAGE_MIN","wrapAttributeWithOperator","attribute","isAttributeByAssociation","attributeName","associatedModels","extractAttributeNameFromOrder","order","associationModels","formattedOrder","isOrderDesc","throwBadRequestError","message","BadRequest","extractAssociatedAttributeNameFromOrder","generateRandomString","length","characters","pick","obj","keys","key","ComputedActions","toSnakeCase","str","letter","buildComputedAttribute","computedAttribute","sql","literal","buildComputedAttributes","computed","attr","buildSelectAttributes","select","columnNameSnake","k","alias","buildJsonAttributes","selectAttributes","computedAttributes","DEFAULT_ORDER","DESCENDING_KEY","ASCENDING_KEY","CUSTOM_FIELDS_QUERY_PREFIX","CUSTOM_FIELDS_FILTER_SCOPE","CUSTOM_FIELDS_SORT_SCOPE","customFields","parseCustomFieldScopeQueryValue","value","operator","conditionValue","getAttributeFromOrder","options","literalAttributes","DBFormatter","attributes","acc","item","orderStyle","found","generateFilterReplacements","conditions","replacements","condition","replacementKey","valueKey","conditionKey","operatorKey","generateOrderReplacements","replacementMap","rand","createReplacementMap","query","formatOrder","replacementsMap","formattedOrders","orderScopesMap","t","scopeKey","isOrderDescOrder","scopeName","scopeValue","formatPage","page","formatPerPage","perPage","formatInclude","include","associationsMap","formattedInclude","i","includedAssociation","_model","formatQuery","additionalAllowedAttributes","formattedQuery","externalQueryValues","formattedScopeMap","queryItemKey","queryItemValue","formattedScopes","formatSearchTerm","searchTerm","attributesToSend","rawAttributes","stringAttributes","attrKey","searchQuery","term","formatPayload","jsonAttributes","model","orderScopes","filteredFormattedOrder","filteredLiteralAttributes","formattedJsonAttributes","allAttributes","formattedAttribute","formattedPage","formattedPerPage","result","queryScopes","queryWithSearchTerm","formatter_default","validateOperator","validateQueryAttribute","rawAttribute","modelAttributes","validateSingleOrder","currentOrder","orderStringWithoutDesc","isOrderAssociation","formattedOrderString","isLiteralAttribute","la","validateSingleAttribute","currentAttribute","validateOrderAttributes","validateAttributes","a","validateJsonAttributes","s","c","validateEnrichments","enrichments","enrichmentKeys","invalidEnrichment","enrichment","validateQueryPayload","v","validatePagination","validateIncludePayload","associations","associationsKeys","target","attributeKeys","validatePayload","group","object","string","number","any","array","alternatives","Joi","fallbackLogger","Logger","querySchema","queryValidation","data","queryValidationMiddleware","inner","req","res","next","error","handleError","queryFormat","queryFormatMiddleware","queryHandler","logger","validationOptions","formatOptions","modelName","additionalScopes","modifyQueryValues","onRowsRetrieved","payload","queryValues","modifiedQuery","scopes","where","limit","_enrichments","_externalQueryValues","rest","sequelizeQuery","enrichmentResult","UnexpectedError"],"mappings":"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","file":"index.js","sourcesContent":["export const OPERATORS = [\n 'eq',\n 'ne',\n 'gte',\n 'gt',\n 'lte',\n 'lt',\n 'not',\n 'in',\n 'notIn',\n 'is',\n 'like',\n 'iLike',\n 'notLike',\n 'between',\n 'and',\n 'or',\n 'overlap',\n 'contains',\n];\n\nexport const OPERATOR_PREFIX = '$';\n\nexport const OPERATORS_TO_SQL = {\n $eq: '=',\n $ne: '!=',\n $gte: '>=',\n $gt: '>',\n $lte: '<=',\n $lt: '<',\n $not: 'NOT',\n $in: 'IN',\n $notIn: 'NOT IN',\n $is: 'IS',\n $like: 'LIKE',\n $iLike: 'ILIKE',\n $notLike: 'NOT LIKE',\n $and: 'AND',\n $or: 'OR',\n};\n\nexport const formatOperators = (Sequelize) => {\n const { Op } = Sequelize;\n return OPERATORS.reduce((map, o) => {\n // eslint-disable-next-line no-param-reassign\n map[`${OPERATOR_PREFIX + o}`] = Op[o];\n return map;\n }, {});\n};\n","import { BadRequest } from '@autofleet/errors';\nimport { OPERATOR_PREFIX } from './operators';\n\nconst randomInt = (max: number) => Math.floor(Math.random() * Math.floor(max));\n\nexport const ORDER_PREFIX = '-';\nexport const ASSOCIATION_PREFIX = '.';\nexport const ASSOCIATION_PATH_WRAPPER = '$';\nexport const PER_PAGE_DEFAULT = 20;\nexport const PAGE_DEFAULT = 1;\nexport const PER_PAGE_MAX_LIMIT = 100;\nexport const PER_PAGE_MIN_LIMIT = 1;\nexport const PAGE_MIN = 1;\n\nexport const wrapAttributeWithOperator = (attribute: string) => `${OPERATOR_PREFIX}${attribute}${OPERATOR_PREFIX}`;\nexport const isAttributeByAssociation = (attributeName: string, associatedModels: string[]): boolean => attributeName.includes(ASSOCIATION_PREFIX)\n && associatedModels.includes(attributeName.split(ASSOCIATION_PREFIX)[0]);\n\nexport const extractAttributeNameFromOrder = (order: string, associationModels: string[]): string => {\n let formattedOrder = order;\n if (order.includes(ORDER_PREFIX)) {\n // eslint-disable-next-line prefer-destructuring\n formattedOrder = formattedOrder.split(ORDER_PREFIX)[1];\n }\n if (isAttributeByAssociation(formattedOrder, associationModels)) {\n [formattedOrder] = formattedOrder.split(ASSOCIATION_PREFIX);\n }\n return formattedOrder;\n};\n\nexport const isOrderDesc = (order: string): boolean => order.includes(ORDER_PREFIX);\n\nexport const throwBadRequestError = (message: string) => {\n throw new BadRequest([new Error(message)]);\n};\n\nexport const extractAssociatedAttributeNameFromOrder = (order: string): string => order.split(ASSOCIATION_PREFIX)[1];\n\nexport const generateRandomString = (length = 5): string => {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n return Array.from({ length }, () => characters.charAt(randomInt(characters.length))).join('');\n};\n\nexport const pick = <T extends object, K extends keyof T = keyof T>(\n obj: T,\n keys: K[],\n): Pick<T, K> => Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick<T, K>;\n","import { literal } from 'sequelize';\n\nexport const ComputedActions = {\n length: 'length',\n} as const;\n\ntype JsonSelectAttribute = {\n columnName: string;\n keys: string[];\n alias?: string;\n};\n\ntype JsonComputedAttribute = {\n columnName: string;\n action: keyof typeof ComputedActions;\n alias: string;\n};\n\nexport type JsonAttributes = {\n select?: JsonSelectAttribute[];\n computed?: JsonComputedAttribute[];\n};\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/(?!^)[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Builds a computed attribute based on the action specified.\n * Currently, supports 'length' action which calculates the length of a JSON array.\n *\n * @param {JsonComputedAttribute} computedAttribute - The computed attribute definition.\n * @returns {Array} An array containing the SQL literal and the alias for the computed attribute.\n */\nfunction buildComputedAttribute(computedAttribute: JsonComputedAttribute) {\n switch (computedAttribute.action) {\n case ComputedActions.length: {\n // Generates: jsonb_array_length(column)\n // Returns the length of the JSON array (e.g., [\"a\", \"b\"] -> 2)\n // Note: Expects the column to be a JSON array\n const sql = `jsonb_array_length(${toSnakeCase(computedAttribute.columnName)})`;\n return [literal(sql), computedAttribute.alias];\n }\n default:\n computedAttribute.action satisfies never;\n return [];\n }\n}\n\nfunction buildComputedAttributes(computed: JsonComputedAttribute[]) {\n return computed.map((attr) => buildComputedAttribute(attr));\n}\n\n/**\n * Builds a list of SQL select attributes using json_build_object\n * to extract specific keys from a JSONB column.\n *\n * Example output:\n * SELECT json_build_object('a', column -> 'a', 'b', column -> 'b') AS alias\n */\nfunction buildSelectAttributes(select: JsonSelectAttribute[]) {\n return select.map((attr) => {\n const columnNameSnake = toSnakeCase(attr.columnName);\n const sql = `json_build_object(${attr.keys\n .map((k) => `'${k}', ${columnNameSnake} -> '${k}'`)\n .join(', ')})`;\n const alias = attr.alias || attr.columnName;\n return [literal(sql), alias];\n });\n}\n\n/**\n * Return a single array combining selected and computed attributes.\n * Format: [[literal, alias], [literal, alias], ...]\n */\nexport default function buildJsonAttributes({ select = [], computed = [] }: JsonAttributes = {}) {\n const selectAttributes = buildSelectAttributes(select);\n const computedAttributes = buildComputedAttributes(computed);\n\n return [...selectAttributes, ...computedAttributes];\n}\n","import { customFields } from '@autofleet/common-types';\nimport {\n extractAssociatedAttributeNameFromOrder,\n extractAttributeNameFromOrder, generateRandomString,\n isAttributeByAssociation,\n isOrderDesc, ORDER_PREFIX,\n PAGE_DEFAULT,\n PER_PAGE_DEFAULT, wrapAttributeWithOperator,\n} from '../utils';\nimport type { LiteralAttribute } from '../middleware';\nimport { OPERATORS_TO_SQL } from '../operators';\nimport buildJsonAttributes from './jsonAttributesFormater';\n\nconst DEFAULT_ORDER = 'id';\nconst DESCENDING_KEY = 'DESC';\nconst ASCENDING_KEY = 'ASC';\nconst CUSTOM_FIELDS_QUERY_PREFIX = 'customFields.';\nconst { CUSTOM_FIELDS_FILTER_SCOPE, CUSTOM_FIELDS_SORT_SCOPE } = customFields;\ntype OrderItem = string | [string, string]\ntype SequelizeOrder = string | OrderItem[];\nexport type FormatPayloadOptions = {\n includeRawPayload?: boolean;\n literalAttributes?: LiteralAttribute[];\n DBFormatter?: any;\n skipSearchTermFormat?: boolean;\n additionalAllowedAttributes?: string[];\n};\n\ntype ConditionWithOperator = {\n operator: string;\n value: string;\n};\nexport type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];\n\nconst parseCustomFieldScopeQueryValue = (value) => {\n if (['string', 'number'].includes(typeof value) || Array.isArray(value)) {\n return value;\n }\n return Object.entries(value).map(([operator, conditionValue]) => ({\n operator: OPERATORS_TO_SQL[operator],\n value: conditionValue,\n }));\n};\n\nconst getAttributeFromOrder = (order: SequelizeOrder[], options: FormatPayloadOptions = {}): [SequelizeOrder[], SequelizeOrder[]] => {\n const { literalAttributes = [], DBFormatter = undefined } = options;\n const [formattedOrder, attributes] = order.reduce((acc, o) => {\n const [item, orderStyle = 'ASC'] = Array.isArray(o) ? o : [o];\n const found = literalAttributes?.find((obj) => obj.attribute === item);\n if (found) {\n acc[1].push(found.literal);\n acc[0].push([DBFormatter ? DBFormatter(`\"${found.attribute}\" ${orderStyle}`) : `${found.attribute} ${orderStyle}`]);\n } else {\n acc[0].push(o);\n }\n return acc;\n }, [[], []]);\n\n return [formattedOrder, attributes];\n};\n\n/**\n * Generates replacements for the given conditions.\n *\n * @param conditions - The conditions to generate replacements for.\n * @returns The replacements object.\n */\nexport const generateFilterReplacements = (conditions: Record<string, ConditionValue>): Record<string, string> => {\n const replacements: Record<string, string> = {};\n\n Object.entries(conditions).forEach(([key, condition]) => {\n const replacementKey = generateRandomString();\n // eslint-disable-next-line prefer-destructuring\n replacements[replacementKey] = key.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];\n\n if (Array.isArray(condition)) {\n condition.forEach((value) => {\n const valueKey = generateRandomString();\n replacements[valueKey] = typeof value === 'string' ? value : value.value;\n });\n } else if (typeof condition === 'string' || typeof condition === 'number') {\n const conditionKey = generateRandomString();\n replacements[conditionKey] = condition;\n } else if (condition?.operator) {\n const operatorKey = generateRandomString();\n replacements[operatorKey] = condition.value;\n }\n });\n\n return replacements;\n};\n\n/**\n * Generates replacements for the given order array.\n *\n * @param order - The order array to generate replacements for.\n * @returns The replacements object.\n */\nexport const generateOrderReplacements = (order: string[]): Record<string, string> => {\n const replacementMap = {};\n order.forEach((o) => {\n if (o.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n const rand = generateRandomString();\n // eslint-disable-next-line prefer-destructuring\n replacementMap[rand] = o.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];\n } else if (o.substring(1).startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n const rand = generateRandomString();\n // eslint-disable-next-line prefer-destructuring\n replacementMap[rand] = o.substring(1).split(CUSTOM_FIELDS_QUERY_PREFIX)[1];\n }\n });\n return replacementMap;\n};\n\n/**\n * Creates a combined replacement map from order and query.\n *\n * @param order - The order array.\n * @param query - The query object.\n * @returns The combined replacements object.\n */\nconst createReplacementMap = (order: string[], query: Record<string, ConditionValue>): Record<string, string> => ({\n ...generateOrderReplacements(order),\n ...generateFilterReplacements(query),\n});\n\nconst formatOrder = ({\n order,\n associationModels = [],\n replacementsMap = {},\n}: { order: string[]; associationModels?: string[]; replacementsMap?: Record<string, string>; }): {\n formattedOrders: SequelizeOrder[];\n orderScopes: (string | { method: [string, { replacementsMap: Record<string, string>; scopeValue: Record<string, 'DESC' | 'ASC'>; }] })[];\n replacementsMap: Record<string, string>;\n} => {\n const formattedOrders = [];\n const orderScopesMap = new Map<string, Record<string, 'DESC' | 'ASC'>>();\n order.forEach((o: string) => {\n if ([o, o.substring(1)].some((t) => t.startsWith(CUSTOM_FIELDS_QUERY_PREFIX))) {\n if (!orderScopesMap.has(CUSTOM_FIELDS_SORT_SCOPE)) {\n orderScopesMap.set(CUSTOM_FIELDS_SORT_SCOPE, {});\n }\n const scopeKey = o.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];\n orderScopesMap.get(CUSTOM_FIELDS_SORT_SCOPE)[scopeKey] = (isOrderDesc(o) ? DESCENDING_KEY : ASCENDING_KEY);\n return;\n }\n const formattedOrder = [extractAttributeNameFromOrder(o, associationModels)];\n const isOrderDescOrder = isOrderDesc(o);\n const isOrderAssociation = isAttributeByAssociation(isOrderDescOrder\n ? o.split(ORDER_PREFIX)[1]\n : o, associationModels);\n if (isOrderAssociation) {\n formattedOrder.push(extractAssociatedAttributeNameFromOrder(o));\n }\n if (isOrderDescOrder) {\n formattedOrder.push(DESCENDING_KEY);\n }\n formattedOrders.push(formattedOrder);\n });\n return {\n formattedOrders,\n replacementsMap,\n orderScopes: Array.from(orderScopesMap.entries()).map(([scopeName, scopeValue]) => {\n if (!scopeValue) {\n return scopeName;\n }\n return {\n method: [scopeName, {\n replacementsMap,\n scopeValue,\n }],\n };\n }),\n };\n};\n\nconst formatPage = (page?: number) => page || PAGE_DEFAULT;\n\nconst formatPerPage = (perPage?: number) => perPage || PER_PAGE_DEFAULT;\n\ninterface Include {\n association?: string;\n model?: string;\n required?: boolean;\n include?: Include[];\n}\n\nconst formatInclude = (include: (string | Include)[], associationsMap = {}) => {\n let formattedInclude = include.map((i) => {\n const includedAssociation = associationsMap[typeof i === 'string' ? i : (i.association || i.model)];\n return {\n ...(typeof i !== 'string' && i),\n association: includedAssociation,\n required: typeof i === 'string' || i.required !== false,\n ...(typeof i !== 'string' && i.include && {\n include: formatInclude(i.include, includedAssociation?.target?.associations),\n }),\n };\n });\n formattedInclude = formattedInclude.map(({ model: _model, ...i }) => i);\n return formattedInclude;\n};\nconst formatQuery = (query, associationModels, replacementsMap: Record<string, string>, additionalAllowedAttributes: string[] = []) => {\n console.log('formatQuery - input query:', JSON.stringify(query, null, 2));\n console.log('formatQuery - associationModels:', associationModels);\n \n const formattedQuery: Record<string, unknown> = {};\n const externalQueryValues: Record<string, unknown> = {};\n const formattedScopeMap = new Map<string, any>();\n\n Object.entries(query).forEach(([queryItemKey, queryItemValue]) => {\n console.log('formatQuery - processing field:', { queryItemKey, queryItemValue });\n if (queryItemKey.startsWith(CUSTOM_FIELDS_QUERY_PREFIX)) {\n if (!formattedScopeMap.has(CUSTOM_FIELDS_FILTER_SCOPE)) {\n formattedScopeMap.set(CUSTOM_FIELDS_FILTER_SCOPE, {});\n }\n const scopeKey = queryItemKey.split(CUSTOM_FIELDS_QUERY_PREFIX)[1];\n formattedScopeMap.get(CUSTOM_FIELDS_FILTER_SCOPE)[scopeKey] = parseCustomFieldScopeQueryValue(queryItemValue);\n return;\n }\n if (additionalAllowedAttributes.includes(queryItemKey)) {\n externalQueryValues[queryItemKey] = queryItemValue;\n return;\n }\n const key = isAttributeByAssociation(queryItemKey, associationModels)\n ? wrapAttributeWithOperator(queryItemKey)\n : queryItemKey;\n console.log('formatQuery - final key assignment:', { original: queryItemKey, final: key });\n formattedQuery[key] = queryItemValue;\n });\n\n const formattedScopes = Array.from(formattedScopeMap.entries()).map(([scopeName, scopeValue]) => {\n if (!scopeValue) {\n return scopeName;\n }\n return {\n method: [scopeName, {\n replacementsMap,\n scopeValue,\n }],\n };\n });\n\n console.log('formatQuery - final result:', { formattedQuery, externalQueryValues, formattedScopes });\n \n return {\n formattedQuery,\n externalQueryValues,\n formattedScopes,\n };\n};\n\nconst formatSearchTerm = (searchTerm: string, attributesToSend: string[], rawAttributes) => {\n console.log('formatSearchTerm - inputs:', { searchTerm, attributesToSend, rawAttributesKeys: Object.keys(rawAttributes) });\n \n const stringAttributes = attributesToSend.filter((attrKey) => rawAttributes[attrKey].type.key === 'STRING');\n console.log('formatSearchTerm - stringAttributes:', stringAttributes);\n \n const searchQuery = {\n $and: searchTerm.split(' ').map((term) => ({\n $or: stringAttributes.map((attr) => ({\n [attr]: {\n $iLike: `%${term}%`,\n },\n })),\n })),\n };\n \n console.log('formatSearchTerm - generated query:', JSON.stringify(searchQuery, null, 2));\n return searchQuery;\n};\n\nconst formatPayload = ({\n order = [],\n page = PAGE_DEFAULT,\n perPage = PER_PAGE_DEFAULT,\n include = [],\n query = {},\n attributes = null,\n searchTerm = null,\n jsonAttributes = {},\n}, model?, options?: FormatPayloadOptions) => {\n const replacementsMap = createReplacementMap(order, query);\n const associationModels = Object.keys(model?.associations || {});\n const { formattedOrders, orderScopes } = formatOrder({\n order: [...order, DEFAULT_ORDER],\n associationModels,\n replacementsMap,\n });\n const [filteredFormattedOrder, filteredLiteralAttributes] = getAttributeFromOrder(\n formattedOrders,\n options,\n );\n\n const formattedJsonAttributes = buildJsonAttributes(jsonAttributes);\n const allAttributes = [...filteredLiteralAttributes, ...(attributes || []), ...formattedJsonAttributes];\n const formattedAttribute = attributes?.length ? allAttributes : { include: allAttributes };\n\n const formattedInclude = formatInclude(include, model?.associations);\n const formattedPage = formatPage(page);\n const formattedPerPage = formatPerPage(perPage);\n const result = formatQuery(query, associationModels, replacementsMap, options?.additionalAllowedAttributes);\n const { formattedScopes: queryScopes, externalQueryValues } = result;\n let { formattedQuery } = result;\n if (searchTerm && !options?.skipSearchTermFormat) {\n console.log('Processing searchTerm in formatPayload:', { searchTerm, skipSearchTermFormat: options?.skipSearchTermFormat });\n const attributesToSend = attributes?.length ? attributes : Object.keys(model.rawAttributes);\n console.log('formatPayload - formattedQuery before searchTerm processing:', JSON.stringify(formattedQuery, null, 2));\n \n const queryWithSearchTerm = formatSearchTerm(searchTerm, attributesToSend, model.rawAttributes);\n formattedQuery = !formattedQuery || Object.keys(formattedQuery).length === 0 ? queryWithSearchTerm : {\n $and: [\n formattedQuery,\n queryWithSearchTerm,\n ],\n };\n \n console.log('formatPayload - formattedQuery after searchTerm processing:', JSON.stringify(formattedQuery, null, 2));\n }\n return {\n query: formattedQuery,\n order: filteredFormattedOrder,\n page: formattedPage,\n perPage: formattedPerPage,\n include: formattedInclude,\n scopes: [...queryScopes, ...orderScopes],\n ...(formattedAttribute && { attributes: formattedAttribute }),\n ...(Object.keys(externalQueryValues).length > 0 && { externalQueryValues }),\n };\n};\n\nexport default formatPayload;\n","import {\n ORDER_PREFIX,\n extractAttributeNameFromOrder,\n isOrderDesc,\n throwBadRequestError,\n PAGE_DEFAULT,\n PER_PAGE_DEFAULT,\n PAGE_MIN,\n PER_PAGE_MAX_LIMIT,\n PER_PAGE_MIN_LIMIT,\n isAttributeByAssociation,\n ASSOCIATION_PREFIX,\n ASSOCIATION_PATH_WRAPPER,\n} from '../utils';\nimport { OPERATORS, OPERATOR_PREFIX } from '../operators';\nimport type { MiddlewareValidationOption } from '../middleware';\nimport type { JsonAttributes } from '../formatter/jsonAttributesFormater';\n\nconst validateOperator = (operator: string): boolean => OPERATORS.includes(operator.split(OPERATOR_PREFIX)[1]);\n\nconst validateQueryAttribute = (\n rawAttribute: string,\n modelAttributes: string[] = [],\n associationModels: string[] = [],\n additionalAllowedAttributes: string[] = [],\n): boolean => {\n const attribute = (rawAttribute.startsWith(\n ASSOCIATION_PATH_WRAPPER,\n ) && rawAttribute.endsWith(\n ASSOCIATION_PATH_WRAPPER,\n )) ? rawAttribute.slice(1, -1) : rawAttribute;\n return [...modelAttributes, ...associationModels].includes(attribute.includes(ASSOCIATION_PREFIX)\n ? attribute.split(ASSOCIATION_PREFIX)[0] : attribute)\n || additionalAllowedAttributes.includes(attribute);\n};\n\nconst validateSingleOrder = (\n currentOrder: string,\n rawAttributes: string[],\n associationModels: string[],\n options: MiddlewareValidationOption = {},\n): void => {\n const isOrderDescOrder = isOrderDesc(currentOrder);\n if (isOrderDescOrder && currentOrder[0] !== ORDER_PREFIX) {\n throwBadRequestError(`${ORDER_PREFIX} must be only at the beginning of the word`);\n }\n const orderStringWithoutDesc = isOrderDescOrder ? currentOrder.split(ORDER_PREFIX)[1] : currentOrder;\n const isOrderAssociation = isAttributeByAssociation(orderStringWithoutDesc, associationModels);\n let formattedOrderString = extractAttributeNameFromOrder(currentOrder, associationModels);\n const isLiteralAttribute = options?.literalAttributes?.map((la) => la.attribute)?.includes(orderStringWithoutDesc);\n\n if (!isOrderAssociation && formattedOrderString.includes(ASSOCIATION_PREFIX)) {\n [formattedOrderString] = formattedOrderString.split(ASSOCIATION_PREFIX);\n }\n\n if (!(rawAttributes.includes(formattedOrderString) || isOrderAssociation || isLiteralAttribute)) {\n throwBadRequestError(`${currentOrder} is invalid. isLiteralAttribute: ${isLiteralAttribute}`);\n }\n};\n\nconst validateSingleAttribute = (currentAttribute: string, rawAttributes: string[]): void => {\n if (!rawAttributes.includes(currentAttribute)) {\n throwBadRequestError(`${currentAttribute} is invalid`);\n }\n};\n\nconst validateOrderAttributes = (\n order: string[],\n rawAttributes: string[],\n associationModels: string[] = [],\n options: MiddlewareValidationOption = {},\n): void => {\n order.forEach((o) => validateSingleOrder(o, rawAttributes, associationModels, options));\n};\n\nconst validateAttributes = (attributes: string[], rawAttributes: string[]): void => {\n attributes.forEach((a) => validateSingleAttribute(a, rawAttributes));\n};\n\nconst validateJsonAttributes = (jsonAttributes: JsonAttributes, rawAttributes: string[]):\n void => {\n const allAttributes = [\n ...(jsonAttributes.select?.map((s) => s.columnName) || []),\n ...(jsonAttributes.computed?.map((c) => c.columnName) || []),\n ];\n\n validateAttributes(allAttributes, rawAttributes);\n};\n\nconst validateEnrichments = (enrichments: string[] | { [enrichmentName: string]: { exclude?: string[]; } }, options?: MiddlewareValidationOption): void => {\n const enrichmentKeys = Array.isArray(enrichments) ? enrichments : Object.keys(enrichments);\n if (!enrichmentKeys?.length) { return; }\n const invalidEnrichment = enrichmentKeys.find((enrichment) => !options?.enrichmentAttributes?.includes(enrichment));\n if (invalidEnrichment) {\n throwBadRequestError(`enrichment attribute ${invalidEnrichment} is invalid`);\n }\n};\n\nconst validateQueryPayload = (query, rawAttributes: string[], associationModels: string[] = [], additionalAllowedAttributes: string[] = []): void => {\n Object.entries(query).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n if (value[0] && typeof value[0] === 'object') {\n value.map((v) => validateQueryPayload(v, rawAttributes, associationModels, additionalAllowedAttributes));\n }\n } else if (validateOperator(key) || validateQueryAttribute(key, rawAttributes, associationModels, additionalAllowedAttributes)) {\n if (value && typeof value === 'object') {\n validateQueryPayload(value, rawAttributes, [], additionalAllowedAttributes);\n }\n } else {\n throwBadRequestError(`invalid key: ${key}`);\n }\n });\n};\n\nconst validatePagination = ({\n page,\n perPage,\n}) => {\n if (page < PAGE_MIN) {\n throwBadRequestError('Page must be greater than 0');\n }\n\n if (perPage > PER_PAGE_MAX_LIMIT || perPage < PER_PAGE_MIN_LIMIT) {\n throwBadRequestError(`PerPage must be between ${PER_PAGE_MIN_LIMIT} to ${PER_PAGE_MAX_LIMIT}`);\n }\n};\n\nconst validateIncludePayload = (include, associations): void => {\n const associationsKeys = Object.keys(associations);\n include.forEach((i) => {\n validateQueryAttribute(i.model, associationsKeys);\n const target = associations[i.model]?.target;\n if (!target) {\n throwBadRequestError('model not found in associations');\n }\n\n const { rawAttributes } = target;\n const attributeKeys = Object.keys(rawAttributes);\n if (i.where) {\n validateQueryPayload(i.where, attributeKeys);\n }\n if (i.order) {\n validateOrderAttributes(i.order, attributeKeys);\n }\n if (i.attributes) {\n validateAttributes(i.attributes, attributeKeys);\n }\n if (![null, undefined, true, false].includes(i.required)) {\n throwBadRequestError('include.required must be a boolean');\n }\n });\n};\n\nexport const validatePayload = (\n {\n query = {},\n order = [],\n attributes = [],\n include = [],\n page = PAGE_DEFAULT,\n perPage = PER_PAGE_DEFAULT,\n enrichments = [],\n group = [],\n jsonAttributes = {},\n },\n model?,\n options: MiddlewareValidationOption = {},\n): boolean => {\n const rawAttributes = Object.keys(model.rawAttributes);\n const associationModels = Object.keys(model?.associations || {});\n if (!attributes || attributes.length === 0) {\n // eslint-disable-next-line no-param-reassign\n attributes = rawAttributes;\n } else {\n validateAttributes(attributes, rawAttributes);\n }\n\n validateOrderAttributes(order, rawAttributes, associationModels, options);\n validateQueryPayload(query, rawAttributes, associationModels, options.additionalAllowedAttributes);\n validateEnrichments(enrichments, options);\n validateJsonAttributes(jsonAttributes, rawAttributes);\n\n if (!Array.isArray(group)) {\n throwBadRequestError('group must be an array');\n }\n if (include.length && typeof include === 'object') {\n validateIncludePayload(include, model?.associations);\n } else if (include && typeof include !== 'object') {\n throwBadRequestError('include must be an array');\n }\n\n validatePagination({\n page,\n perPage,\n });\n return true;\n};\n","import type { Handler } from 'express';\nimport Logger, { type LoggerInstanceManager } from '@autofleet/logger';\nimport { BadRequest, handleError } from '@autofleet/errors';\nimport Joi from 'joi';\nimport formatPayload, { type FormatPayloadOptions } from '../formatter';\nimport { validatePayload } from '../validations';\nimport { ComputedActions } from '../formatter/jsonAttributesFormater';\n\nconst {\n object, string, number, any, array, alternatives,\n} = Joi.types();\nconst fallbackLogger = Logger();\n\nconst querySchema = object.keys({\n query: object,\n attributes: array.items(string),\n order: array.items(string),\n page: number,\n perPage: number,\n include: array.items(any),\n searchTerm: string,\n group: array.items(string),\n enrichments: alternatives.try(array.items(string), object.pattern(string, { exclude: array.items(string) })),\n jsonAttributes: Joi.object({\n select: Joi.array().items(\n Joi.object({\n columnName: Joi.string().required(),\n keys: Joi.array().items(Joi.string().required()).required(),\n alias: Joi.string().optional(),\n }),\n ).default([]),\n computed: Joi.array().items(\n Joi.object({\n columnName: Joi.string().required(),\n action: Joi.string().valid(...Object.values(ComputedActions)).required(),\n alias: Joi.string().required(),\n }),\n ).default([]),\n }).default({}),\n});\n\ntype literal = any;\ntype LiteralQuery = (literal | string)[] | literal;\nexport type LiteralAttribute = { attribute: string; literal: LiteralQuery };\nexport type MiddlewareValidationOption = {\n literalAttributes?: LiteralAttribute[];\n enrichmentAttributes?: string[];\n additionalAllowedAttributes?: string[];\n logger?: LoggerInstanceManager;\n};\n\ntype ReqKeys = 'body' | 'query';\n\nexport const queryValidation = (model: any, data: any, options: MiddlewareValidationOption = {}) => {\n const {\n query,\n attributes,\n order,\n page,\n perPage,\n include,\n group,\n enrichments,\n jsonAttributes,\n } = data;\n\n const result = querySchema.validate(data);\n if (result.error) {\n throw new BadRequest([result.error], null);\n }\n validatePayload({\n query,\n attributes,\n order,\n page,\n perPage,\n include,\n enrichments,\n group,\n jsonAttributes,\n }, model, options);\n};\n\n/** consider using @see {@link queryHandler} directly */\nexport const queryValidationMiddleware = (model: any, options: MiddlewareValidationOption = {}, inner: ReqKeys = 'body'): Handler => async (req, res, next): Promise<void> => {\n try {\n queryValidation(model, req[inner], options);\n next();\n } catch (error) {\n const { query, attributes, order } = req[inner];\n handleError(error, res, {\n logger: options.logger || fallbackLogger,\n message: 'error in query middleware',\n payload: {\n error,\n query,\n attributes,\n order,\n },\n });\n }\n};\n\nexport const queryFormat = (model: any, data: any, options: FormatPayloadOptions = {}) => {\n const {\n order, page, perPage, include, query, attributes, searchTerm, jsonAttributes,\n } = data;\n\n const {\n query: formattedQuery,\n externalQueryValues,\n order: formattedOrder,\n page: formattedPage,\n perPage: formattedPerPage,\n include: formattedInclude,\n scopes: formattedScopes,\n attributes: formattedAttribute,\n } = formatPayload({\n query, order, page, perPage, include, attributes, searchTerm, jsonAttributes,\n }, model, options);\n\n /* eslint-disable no-param-reassign */\n data.query = formattedQuery;\n data.externalQueryValues = externalQueryValues;\n data.order = formattedOrder;\n data.attributes = formattedAttribute;\n data.page = formattedPage;\n data.perPage = formattedPerPage;\n data.include = formattedInclude;\n data.scopes = formattedScopes;\n if (options.includeRawPayload) {\n data.rawPayload = {\n order,\n page,\n perPage,\n include,\n query,\n attributes,\n searchTerm,\n };\n }\n /* eslint-enable no-param-reassign */\n};\n\n/** consider using @see {@link queryHandler} directly */\nexport const queryFormatMiddleware = (model: any, options: FormatPayloadOptions = {}, inner: ReqKeys = 'body'): Handler => async (req, res, next): Promise<void> => {\n queryFormat(model, req[inner], options);\n next();\n};\n","import type { Handler } from 'express';\nimport { type LoggerInstanceManager } from '@autofleet/logger';\nimport { UnexpectedError, handleError } from '@autofleet/errors';\nimport formatPayload, { type FormatPayloadOptions } from '../formatter';\nimport { pick } from '../utils';\nimport { type MiddlewareValidationOption, queryFormat, queryValidation } from '../middleware';\n\ninterface QueryValues extends ReturnType<typeof formatPayload> {\n enrichments?: string[] | Record<string, { exclude: string[] }>;\n distinct: boolean;\n}\n\ninterface QueryHandlerOptions {\n /** The sequelize model too which querying abilities are added. */\n model: any;\n /** Optional settings for validation. */\n validationOptions?: Omit<MiddlewareValidationOption, 'logger'>;\n /** Optional settings for payload formatting */\n formatOptions?: FormatPayloadOptions;\n logger: LoggerInstanceManager;\n /** The name of model to be printed in logs. defaults to `model`s constructor name. */\n modelName?: string;\n /** Sequelize scopes of the model to be used within the query. @example ['userScope'] */\n additionalScopes?: string[];\n /** Callback to allow modifying the query values prior to querying the DB */\n modifyQueryValues?: (queryValues: QueryValues) => QueryValues;\n /** Optional callback to modify endpoint's response based on the DBs response. */\n onRowsRetrieved?: (data: { rows: any[]; count: number; }, queryValues: QueryValues) => any;\n}\n\nexport const queryHandler = ({\n model, logger, validationOptions, formatOptions, modelName = model.constructor?.name, additionalScopes = [], modifyQueryValues, onRowsRetrieved,\n}: QueryHandlerOptions): Handler => async (req, res) => {\n try {\n queryValidation(model, req.body, { ...validationOptions, logger });\n } catch (error) {\n const payload = pick(req.body as QueryValues, ['query', 'order', 'attributes'] as const);\n handleError(error, res, { logger, message: 'error in query endpoint', payload });\n return;\n }\n try {\n logger.info(`BEFORE queryFormat - req.body:`, { body: req.body });\n queryFormat(model, req.body, formatOptions);\n logger.info(`AFTER queryFormat - req.body:`, { body: req.body });\n\n const queryValues = Object.assign(\n pick(req.body as QueryValues, ['query', 'externalQueryValues', 'order', 'attributes', 'page', 'perPage', 'include', 'scopes', 'enrichments'] as const),\n { distinct: true },\n );\n\n logger.info(`queryValues after pick:`, { queryValues });\n\n const modifiedQuery = modifyQueryValues?.(queryValues) ?? queryValues;\n logger.info(`modifiedQuery:`, { modifiedQuery });\n const {\n scopes = [],\n query: where,\n perPage: limit,\n page,\n enrichments: _enrichments,\n externalQueryValues: _externalQueryValues,\n ...rest\n } = modifiedQuery;\n\n const sequelizeQuery = {\n where,\n limit,\n offset: (page - 1) * limit,\n ...rest,\n };\n logger.info(`Sequelize query object:`, { sequelizeQuery, scopes: [...additionalScopes, ...scopes] });\n \n const result = await model.scope([...additionalScopes, ...scopes]).findAndCountAll(sequelizeQuery);\n\n if (!result.rows.length || !onRowsRetrieved) {\n res.json(result);\n return;\n }\n\n const enrichmentResult = await onRowsRetrieved(result, modifiedQuery);\n\n res.json(enrichmentResult);\n } catch (error) {\n logger.error(`Raw error caught in queryHandler:`, { \n error, \n errorMessage: error.message, \n errorStack: error.stack,\n errorName: error.name,\n originalRequestBody: req.body \n });\n handleError(new UnexpectedError(error), res, { logger, message: `Error while querying ${modelName}`, payload: { query: req.body } });\n }\n};\n"]}
|