@@ -51,31 +51,20 @@ export type GroupBy<T> = {
51
51
transform ?: Transform < T > ;
52
52
}
53
53
54
- export type Value = {
55
- type : 'raw' | 'guid' | 'duration' | 'binary' | 'json' | 'alias' ;
56
- value : any ;
57
- }
58
-
59
- export type Alias = Value & {
60
- name : string ;
61
- handleName ( ) : string ;
62
- handleValue ( ) : string ;
63
- }
64
-
65
- export const raw = ( value : string ) : Value => ( { type : 'raw' , value} ) ;
66
- export const guid = ( value : string ) : Value => ( { type : 'guid' , value} ) ;
67
- export const duration = ( value : string ) : Value => ( { type : 'duration' , value} ) ;
68
- export const binary = ( value : string ) : Value => ( { type : 'binary' , value} ) ;
69
- export const json = ( value : PlainObject ) : Value => ( { type : 'json' , value} ) ;
70
- export const alias = ( name : string , value : PlainObject ) : Alias => ( {
71
- type : 'alias' , name, value,
72
- handleName ( ) {
73
- return `@${ this . name } ` ;
74
- } ,
75
- handleValue ( ) {
76
- return handleValue ( this . value ) ;
77
- }
78
- } ) ;
54
+ export type Raw = { type : 'raw' ; value : any ; }
55
+ export type Guid = { type : 'guid' ; value : any ; }
56
+ export type Duration = { type : 'duration' ; value : any ; }
57
+ export type Binary = { type : 'binary' ; value : any ; }
58
+ export type Json = { type : 'json' ; value : any ; }
59
+ export type Alias = { type : 'alias' ; name : string ; value : any ; }
60
+ export type Value = string | Date | number | boolean | Raw | Guid | Duration | Binary | Json | Alias ;
61
+
62
+ export const raw = ( value : string ) : Raw => ( { type : 'raw' , value } ) ;
63
+ export const guid = ( value : string ) : Guid => ( { type : 'guid' , value } ) ;
64
+ export const duration = ( value : string ) : Duration => ( { type : 'duration' , value } ) ;
65
+ export const binary = ( value : string ) : Binary => ( { type : 'binary' , value } ) ;
66
+ export const json = ( value : PlainObject ) : Json => ( { type : 'json' , value } ) ;
67
+ export const alias = ( name : string , value : PlainObject ) : Alias => ( { type : 'alias' , name, value } ) ;
79
68
80
69
export type QueryOptions < T > = ExpandOptions < T > & {
81
70
search : string ;
@@ -106,26 +95,20 @@ export default function <T>({
106
95
count,
107
96
expand,
108
97
action,
109
- func,
110
- aliases
98
+ func
111
99
} : Partial < QueryOptions < T > > = { } ) {
112
- let path = '' ;
100
+ let path : string = '' ;
101
+ let aliases : Alias [ ] = [ ] ;
113
102
114
103
const params : any = { } ;
115
104
116
- if ( key ) {
117
- if ( typeof key === 'object' ) {
118
- const keys = Object . keys ( key )
119
- . map ( k => `${ k } =${ key [ k ] } ` )
120
- . join ( ',' ) ;
121
- path += `(${ keys } )` ;
122
- } else {
123
- path += `(${ key } )` ;
105
+ // key is not (null, undefined)
106
+ if ( key != undefined ) {
107
+ path += `(${ handleValue ( key as Value , aliases ) } )` ;
124
108
}
125
- }
126
109
127
110
if ( filter || typeof count === 'object' )
128
- params . $filter = buildFilter ( typeof count === 'object' ? count : filter ) ;
111
+ params . $filter = buildFilter ( typeof count === 'object' ? count : filter , aliases ) ;
129
112
130
113
if ( transform )
131
114
params . $apply = buildTransforms ( transform ) ;
@@ -162,7 +145,7 @@ export default function <T>({
162
145
} else if ( typeof func === 'object' ) {
163
146
const [ funcName ] = Object . keys ( func ) ;
164
147
const funcArgs = Object . keys ( func [ funcName ] ) . reduce (
165
- ( acc : string [ ] , item ) => [ ...acc , `${ item } =${ handleValue ( func [ funcName ] [ item ] ) } ` ] ,
148
+ ( acc : string [ ] , item ) => [ ...acc , `${ item } =${ handleValue ( func [ funcName ] [ item ] , aliases ) } ` ] ,
166
149
[ ]
167
150
) ;
168
151
@@ -173,31 +156,32 @@ export default function <T>({
173
156
}
174
157
}
175
158
176
- if ( aliases ) {
177
- aliases
178
- . reduce ( ( acc , alias ) => Object . assign ( acc , { [ alias . handleName ( ) ] : alias . handleValue ( ) } ) , params ) ;
159
+ if ( aliases . length > 0 ) {
160
+ Object . assign ( params , aliases . reduce ( ( acc , alias ) =>
161
+ Object . assign ( acc , { [ `@${ alias . name } ` ] : handleValue ( alias . value ) } )
162
+ , { } ) ) ;
179
163
}
180
164
181
165
return buildUrl ( path , { $select, $search, $skiptoken, $format, ...params } ) ;
182
166
}
183
167
184
- function renderPrimitiveValue ( key : string , val : any ) {
185
- return `${ key } eq ${ handleValue ( val ) } `
168
+ function renderPrimitiveValue ( key : string , val : any , aliases : Alias [ ] = [ ] ) {
169
+ return `${ key } eq ${ handleValue ( val , aliases ) } `
186
170
}
187
171
188
- function buildFilter ( filters : Filter = { } , propPrefix = '' ) : string {
172
+ function buildFilter ( filters : Filter = { } , aliases : Alias [ ] = [ ] , propPrefix = '' ) : string {
189
173
return ( ( Array . isArray ( filters ) ? filters : [ filters ] )
190
174
. reduce ( ( acc : string [ ] , filter ) => {
191
175
if ( filter ) {
192
- const builtFilter = buildFilterCore ( filter , propPrefix ) ;
176
+ const builtFilter = buildFilterCore ( filter , aliases , propPrefix ) ;
193
177
if ( builtFilter ) {
194
178
acc . push ( builtFilter ) ;
195
179
}
196
180
}
197
181
return acc ;
198
182
} , [ ] ) as string [ ] ) . join ( ' and ' ) ;
199
183
200
- function buildFilterCore ( filter : Filter = { } , propPrefix = '' ) {
184
+ function buildFilterCore ( filter : Filter = { } , aliases : Alias [ ] = [ ] , propPrefix = '' ) {
201
185
let filterExpr = "" ;
202
186
if ( typeof filter === 'string' ) {
203
187
// Use raw filter string
@@ -233,11 +217,11 @@ function buildFilter(filters: Filter = {}, propPrefix = ''): string {
233
217
value === null
234
218
) {
235
219
// Simple key/value handled as equals operator
236
- result . push ( renderPrimitiveValue ( propName , value ) ) ;
220
+ result . push ( renderPrimitiveValue ( propName , value , aliases ) ) ;
237
221
} else if ( Array . isArray ( value ) ) {
238
222
const op = filterKey ;
239
223
const builtFilters = value
240
- . map ( v => buildFilter ( v , propPrefix ) )
224
+ . map ( v => buildFilter ( v , aliases , propPrefix ) )
241
225
. filter ( f => f )
242
226
. map ( f => ( LOGICAL_OPERATORS . indexOf ( op ) !== - 1 ? `(${ f } )` : f ) ) ;
243
227
if ( builtFilters . length ) {
@@ -265,29 +249,29 @@ function buildFilter(filters: Filter = {}, propPrefix = ''): string {
265
249
result . push ( `${ builtFilters . join ( ` ${ op } ` ) } ` ) ;
266
250
}
267
251
}
268
- } else if ( value instanceof Object ) {
252
+ } else if ( typeof value === 'object' ) {
269
253
if ( 'type' in value ) {
270
- result . push ( renderPrimitiveValue ( propName , value ) ) ;
254
+ result . push ( renderPrimitiveValue ( propName , value , aliases ) ) ;
271
255
} else {
272
256
const operators = Object . keys ( value ) ;
273
257
operators . forEach ( op => {
274
258
if ( COMPARISON_OPERATORS . indexOf ( op ) !== - 1 ) {
275
- result . push ( `${ propName } ${ op } ${ handleValue ( value [ op ] ) } ` ) ;
259
+ result . push ( `${ propName } ${ op } ${ handleValue ( value [ op ] , aliases ) } ` ) ;
276
260
} else if ( LOGICAL_OPERATORS . indexOf ( op ) !== - 1 ) {
277
261
if ( Array . isArray ( value [ op ] ) ) {
278
262
result . push (
279
263
value [ op ]
280
- . map ( ( v : any ) => '(' + buildFilterCore ( v , propName ) + ')' )
264
+ . map ( ( v : any ) => '(' + buildFilterCore ( v , aliases , propName ) + ')' )
281
265
. join ( ` ${ op } ` )
282
266
) ;
283
267
} else {
284
- result . push ( '(' + buildFilterCore ( value [ op ] , propName ) + ')' ) ;
268
+ result . push ( '(' + buildFilterCore ( value [ op ] , aliases , propName ) + ')' ) ;
285
269
}
286
270
} else if ( COLLECTION_OPERATORS . indexOf ( op ) !== - 1 ) {
287
271
const collectionClause = buildCollectionClause ( filterKey . toLowerCase ( ) , value [ op ] , op , propName ) ;
288
272
if ( collectionClause ) { result . push ( collectionClause ) ; }
289
273
} else if ( op === 'has' ) {
290
- result . push ( `${ propName } ${ op } ${ handleValue ( value [ op ] ) } ` ) ;
274
+ result . push ( `${ propName } ${ op } ${ handleValue ( value [ op ] , aliases ) } ` ) ;
291
275
} else if ( op === 'in' ) {
292
276
const resultingValues = Array . isArray ( value [ op ] )
293
277
? value [ op ]
@@ -297,14 +281,14 @@ function buildFilter(filters: Filter = {}, propPrefix = ''): string {
297
281
} ) ) ;
298
282
299
283
result . push (
300
- propName + ' in (' + resultingValues . map ( ( v : any ) => handleValue ( v ) ) . join ( ',' ) + ')'
284
+ propName + ' in (' + resultingValues . map ( ( v : any ) => handleValue ( v , aliases ) ) . join ( ',' ) + ')'
301
285
) ;
302
286
} else if ( BOOLEAN_FUNCTIONS . indexOf ( op ) !== - 1 ) {
303
287
// Simple boolean functions (startswith, endswith, contains)
304
- result . push ( `${ op } (${ propName } ,${ handleValue ( value [ op ] ) } )` ) ;
288
+ result . push ( `${ op } (${ propName } ,${ handleValue ( value [ op ] , aliases ) } )` ) ;
305
289
} else {
306
290
// Nested property
307
- const filter = buildFilterCore ( value , propName ) ;
291
+ const filter = buildFilterCore ( value , aliases , propName ) ;
308
292
if ( filter ) {
309
293
result . push ( filter ) ;
310
294
}
@@ -349,7 +333,7 @@ function buildFilter(filters: Filter = {}, propPrefix = ''): string {
349
333
return { ...acc , ...item }
350
334
} , { } ) : value ;
351
335
352
- const filter = buildFilterCore ( filterValue , lambdaParameter ) ;
336
+ const filter = buildFilterCore ( filterValue , aliases , lambdaParameter ) ;
353
337
clause = `${ propName } /${ op } (${ filter ? `${ lambdaParameter } :${ filter } ` : '' } )` ;
354
338
}
355
339
return clause ;
@@ -375,36 +359,40 @@ function escapeIllegalChars(string: string) {
375
359
return string ;
376
360
}
377
361
378
- function handleValue ( value : any ) {
362
+ function handleValue ( value : Value , aliases ?: Alias [ ] ) : any {
379
363
if ( typeof value === 'string' ) {
380
364
return `'${ escapeIllegalChars ( value ) } '` ;
381
365
} else if ( value instanceof Date ) {
382
366
return value . toISOString ( ) ;
383
- } else if ( value instanceof Number ) {
367
+ } else if ( typeof value === 'number' ) {
384
368
return value ;
385
369
} else if ( Array . isArray ( value ) ) {
386
- // Double quote strings to keep them after ` .join`
387
- const arr = value . map ( d => ( typeof d === 'string' ? `' ${ d } '` : d ) ) ;
388
- return `[ ${ arr . join ( ',' ) } ]` ;
389
- } else {
390
- // TODO: Figure out how best to specify types. See: https://github.com/devnixs/ODataAngularResources/blob/master/src/odatavalue.js
391
- switch ( value && value . type ) {
392
- case 'guid' :
370
+ return `[ ${ value . map ( d => handleValue ( d ) ) . join ( ',' ) } ]` ;
371
+ } else if ( value === null ) {
372
+ return value ;
373
+ } else if ( typeof value === 'object' ) {
374
+ if ( value . type === 'raw' ) {
375
+ return value . value ;
376
+ } else if ( value . type === 'guid' ) {
393
377
return value . value ;
394
- case 'duration' :
378
+ } else if ( value . type === 'duration' ) {
395
379
return `duration'${ value . value } '` ;
396
- case 'raw' :
397
- return value . value ;
398
- case 'binary' :
380
+ } else if ( value . type === 'binary' ) {
399
381
return `binary'${ value . value } '` ;
400
- case 'alias' :
401
- return ( value as Alias ) . handleName ( ) ;
402
- case 'json' :
382
+ } else if ( value . type === 'alias' ) {
383
+ // Store
384
+ if ( Array . isArray ( aliases ) )
385
+ aliases . push ( value as Alias ) ;
386
+ return `@${ ( value as Alias ) . name } ` ;
387
+ } else if ( value . type === 'json' ) {
403
388
return escape ( JSON . stringify ( value . value ) ) ;
389
+ } else {
390
+ return Object . keys ( value )
391
+ . map ( k => `${ k } =${ handleValue ( value [ k ] , aliases ) } ` ) . join ( ',' ) ;
392
+ }
404
393
}
405
394
return value ;
406
395
}
407
- }
408
396
409
397
function buildExpand < T > ( expands : Expand < T > ) : string {
410
398
if ( typeof expands === 'number' ) {
0 commit comments