@@ -24,6 +24,10 @@ import {
2424 TypeName ,
2525} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common' ;
2626
27+ import { randomBytes } from 'node:crypto' ;
28+
29+ import { FilterClause , FilterClauseVariable } from '../types/filterClause' ;
30+
2731type ProcessType = 'ProcessDefinition' | 'ProcessInstance' ;
2832
2933const supportedOperators = [
@@ -73,44 +77,88 @@ function handleLogicalFilter(
7377 introspection : IntrospectionField [ ] ,
7478 type : ProcessType ,
7579 filter : LogicalFilter ,
76- ) : string {
77- if ( ! filter . operator ) return '' ;
80+ ) : FilterClause {
81+ if ( ! filter . operator ) return { } as FilterClause ;
7882
7983 const subClauses = filter . filters . map ( f =>
8084 buildFilterCondition ( introspection , type , f ) ,
8185 ) ;
8286
83- return `${ filter . operator . toLowerCase ( ) } : {${ subClauses . join ( ', ' ) } }` ;
87+ const filterClause : FilterClause = {
88+ clause : `${ filter . operator . toLowerCase ( ) } : {${ subClauses . map ( cl => cl . clause ) . join ( ', ' ) } }` ,
89+ clauseVariable : subClauses . flatMap ( cl => cl . clauseVariable ) ,
90+ } ;
91+ return filterClause ;
8492}
8593
8694function handleNestedFilter (
8795 introspection : IntrospectionField [ ] ,
8896 type : ProcessType ,
8997 filter : NestedFilter ,
90- ) : string {
98+ ) : FilterClause {
9199 const subClauses = buildFilterCondition (
92100 introspection ,
93101 type ,
94102 filter . nested ,
95103 true ,
96104 ) ;
97105
98- return `${ filter . field } : {${ subClauses } }` ;
106+ const filterClause : FilterClause = {
107+ clauseVariable : subClauses . clauseVariable ,
108+ clause : `${ filter . field } : {${ subClauses . clause } }` ,
109+ } ;
110+
111+ return filterClause ;
99112}
100113
101- function handleBetweenOperator ( filter : FieldFilter ) : string {
114+ function handleBetweenOperator ( filter : FieldFilter ) : FilterClause {
102115 if ( ! Array . isArray ( filter . value ) || filter . value . length !== 2 ) {
103116 throw new Error ( 'Between operator requires an array of two elements' ) ;
104117 }
105- return `${ filter . field } : {${ getGraphQLOperator (
118+ const filterClauseVariableArray : FilterClauseVariable [ ] = [ ] ;
119+ const clauseVariableName1 = `clauseVariable${ nonSecureRandomAlphaNumeric ( ) } ` ;
120+ const filterClauseVariable1 : FilterClauseVariable = {
121+ clauseVariableName : clauseVariableName1 ,
122+ formattedValue : filter . value [ 0 ] ,
123+ clauseVariableType : 'String' ,
124+ } ;
125+
126+ const clauseVariableName2 = `clauseVariable${ nonSecureRandomAlphaNumeric ( ) } ` ;
127+ const filterClauseVariable2 : FilterClauseVariable = {
128+ clauseVariableName : clauseVariableName2 ,
129+ formattedValue : filter . value [ 1 ] ,
130+ clauseVariableType : 'String' ,
131+ } ;
132+
133+ const clause = `${ filter . field } : {${ getGraphQLOperator (
106134 FieldFilterOperatorEnum . Between ,
107- ) } : {from: "${ filter . value [ 0 ] } ", to: "${ filter . value [ 1 ] } "}}`;
135+ ) } : {from: $${ clauseVariableName1 } , to: $${ clauseVariableName2 } }}`;
136+ filterClauseVariableArray . push ( filterClauseVariable1 , filterClauseVariable2 ) ;
137+ const filterClause : FilterClause = {
138+ clause : clause ,
139+ clauseVariable : filterClauseVariableArray ,
140+ } ;
141+
142+ return filterClause ;
108143}
109144
110- function handleIsNullOperator ( filter : FieldFilter ) : string {
111- return `${ filter . field } : {${ getGraphQLOperator (
112- FieldFilterOperatorEnum . IsNull ,
113- ) } : ${ convertToBoolean ( filter . value ) } }`;
145+ function handleIsNullOperator ( filter : FieldFilter ) : FilterClause {
146+ const clauseVariableName = `clauseVariable${ nonSecureRandomAlphaNumeric ( ) } ` ;
147+ const clause = `${ filter . field } : {${ getGraphQLOperator ( FieldFilterOperatorEnum . IsNull ) } : $${ clauseVariableName } }` ;
148+
149+ const filterClauseVariable : FilterClauseVariable = {
150+ clauseVariableName : clauseVariableName ,
151+ formattedValue : convertToBoolean ( filter . value ) ,
152+ clauseVariableType : 'Boolean' ,
153+ } ;
154+ const filterClauseVariableArray : FilterClauseVariable [ ] = [ ] ;
155+ filterClauseVariableArray . push ( filterClauseVariable ) ;
156+ const clauseObject : FilterClause = {
157+ clauseVariable : filterClauseVariableArray ,
158+ clause,
159+ } ;
160+
161+ return clauseObject ;
114162}
115163
116164function isEnumFilter (
@@ -136,32 +184,58 @@ function handleBinaryOperator(
136184 binaryFilter : FieldFilter ,
137185 fieldDef : IntrospectionField | undefined ,
138186 type : 'ProcessDefinition' | 'ProcessInstance' ,
139- ) : string {
187+ ) : FilterClause {
140188 if ( isEnumFilter ( binaryFilter . field , type ) ) {
141189 if ( ! isValidEnumOperator ( binaryFilter . operator ) ) {
142190 throw new Error (
143191 `Invalid operator ${ binaryFilter . operator } for enum field ${ binaryFilter . field } filter` ,
144192 ) ;
145193 }
146194 }
147- const formattedValue = Array . isArray ( binaryFilter . value )
148- ? `[${ binaryFilter . value
149- . map ( v => formatValue ( binaryFilter . field , v , fieldDef , type ) )
150- . join ( ', ' ) } ]`
151- : formatValue ( binaryFilter . field , binaryFilter . value , fieldDef , type ) ;
152- return `${ binaryFilter . field } : {${ getGraphQLOperator (
153- binaryFilter . operator ,
154- ) } : ${ formattedValue } }`;
195+ let formattedValue : any ;
196+ let paramType : string ;
197+ if ( Array . isArray ( binaryFilter . value ) ) {
198+ formattedValue = binaryFilter . value . map ( v =>
199+ formatValue ( binaryFilter . field , v , fieldDef , type ) ,
200+ ) ;
201+ paramType = isEnumFilter ( binaryFilter . field , type )
202+ ? '[ProcessInstanceState!]'
203+ : '[String!]' ;
204+ } else {
205+ formattedValue = formatValue (
206+ binaryFilter . field ,
207+ binaryFilter . value ,
208+ fieldDef ,
209+ type ,
210+ ) ;
211+ paramType = 'String' ;
212+ }
213+
214+ const clauseVariableName = `clauseVariable${ nonSecureRandomAlphaNumeric ( ) } ` ;
215+ const clause = `${ binaryFilter . field } : {${ getGraphQLOperator ( binaryFilter . operator ) } : $${ clauseVariableName } }` ;
216+ const filterClauseVariable : FilterClauseVariable = {
217+ clauseVariableName : clauseVariableName ,
218+ formattedValue : formattedValue ,
219+ clauseVariableType : paramType ,
220+ } ;
221+ const filterClauseVariableArray : FilterClauseVariable [ ] = [ ] ;
222+ filterClauseVariableArray . push ( filterClauseVariable ) ;
223+ const clauseObject : FilterClause = {
224+ clauseVariable : filterClauseVariableArray ,
225+ clause,
226+ } ;
227+
228+ return clauseObject ;
155229}
156230
157231export function buildFilterCondition (
158232 introspection : IntrospectionField [ ] ,
159233 type : ProcessType ,
160234 filters ?: Filter ,
161235 isNested ?: boolean ,
162- ) : string {
236+ ) : FilterClause {
163237 if ( ! filters ) {
164- return '' ;
238+ return { } as FilterClause ;
165239 }
166240
167241 if ( isNestedFilter ( filters ) ) {
@@ -255,7 +329,7 @@ function formatValue(
255329 type : ProcessType ,
256330) : string {
257331 if ( ! fieldDef ) {
258- return `" ${ fieldValue } " ` ;
332+ return `${ fieldValue } ` ;
259333 }
260334
261335 if ( ! isFieldFilterSupported ) {
@@ -270,7 +344,7 @@ function formatValue(
270344 fieldDef . type . name === TypeName . Id ||
271345 fieldDef . type . name === TypeName . Date
272346 ) {
273- return `" ${ fieldValue } " ` ;
347+ return `${ fieldValue } ` ;
274348 }
275349 throw new Error (
276350 `Failed to format value for ${ fieldName } ${ fieldValue } with type ${ fieldDef . type . name } ` ,
@@ -301,3 +375,9 @@ function getGraphQLOperator(operator: FieldFilterOperatorEnum): string {
301375 throw new Error ( `Operation "${ operator } " not supported` ) ;
302376 }
303377}
378+
379+ // Function for getting 4 random digits to append to the clause variable name.
380+ // Not used for any secrets or anything
381+ function nonSecureRandomAlphaNumeric ( ) {
382+ return randomBytes ( 8 ) . toString ( 'hex' ) ;
383+ }
0 commit comments