tablevu 0.2.21 → 0.3.0-beta.1
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/README.md +60 -109
- package/dist/array.d.ts +14 -0
- package/dist/index.d.ts +7 -0
- package/dist/odata.d.ts +40 -0
- package/dist/table.d.ts +173 -0
- package/dist/tablevu-index.esm.js +1076 -0
- package/dist/tablevu-index.umd.cjs.js +1087 -0
- package/dist/tablevu-odata.esm.js +508 -0
- package/dist/tablevu-odata.umd.cjs.js +519 -0
- package/dist/tablevu-table.esm.js +551 -0
- package/dist/tablevu-table.umd.cjs.js +560 -0
- package/dist/tablevu-webapi.esm.js +19 -0
- package/dist/tablevu-webapi.umd.cjs.js +29 -0
- package/dist/webapi.d.ts +15 -0
- package/package.json +43 -24
- package/LICENSE +0 -21
- package/dist/array.js +0 -1
- package/dist/get.js +0 -1
- package/dist/odata.js +0 -1
- package/dist/table.js +0 -1
- package/dist/webapi.js +0 -1
- package/index.js +0 -5
- package/src/array.js +0 -78
- package/src/get.js +0 -28
- package/src/odata.js +0 -179
- package/src/table.js +0 -609
- package/src/webapi.js +0 -33
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.tablevu = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/* ==========================================================================
|
|
8
|
+
* OData DataTable Query Builder
|
|
9
|
+
* ========================================================================== */
|
|
10
|
+
/* ==========================================================================
|
|
11
|
+
* Value
|
|
12
|
+
* ========================================================================== */
|
|
13
|
+
function formatValue(value) {
|
|
14
|
+
if (value === null)
|
|
15
|
+
return 'null';
|
|
16
|
+
if (typeof value === 'string')
|
|
17
|
+
return `'${escapeODataString(value)}'`;
|
|
18
|
+
if (typeof value === 'number') {
|
|
19
|
+
if (!Number.isFinite(value))
|
|
20
|
+
throw new Error('Invalid numeric value.');
|
|
21
|
+
return String(value);
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === 'boolean')
|
|
24
|
+
return value ? 'true' : 'false';
|
|
25
|
+
if (value instanceof Date)
|
|
26
|
+
return value.toISOString();
|
|
27
|
+
/*
|
|
28
|
+
* Backward compatibility with:
|
|
29
|
+
*
|
|
30
|
+
* {
|
|
31
|
+
* func: 'now',
|
|
32
|
+
* params: []
|
|
33
|
+
* }
|
|
34
|
+
*/
|
|
35
|
+
if (typeof value === 'object' &&
|
|
36
|
+
value !== null &&
|
|
37
|
+
'func' in value &&
|
|
38
|
+
'params' in value) {
|
|
39
|
+
const funcValue = value;
|
|
40
|
+
return (funcValue.func +
|
|
41
|
+
'(' +
|
|
42
|
+
funcValue.params
|
|
43
|
+
.map(m => formatValue(m))
|
|
44
|
+
.join(',') +
|
|
45
|
+
')');
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Unsupported OData value type: ${typeof value}`);
|
|
48
|
+
}
|
|
49
|
+
function escapeODataString(value) {
|
|
50
|
+
/*
|
|
51
|
+
* OData escapes a single quote by doubling it.
|
|
52
|
+
*
|
|
53
|
+
* O'Reilly
|
|
54
|
+
* ↓
|
|
55
|
+
* 'O''Reilly'
|
|
56
|
+
*/
|
|
57
|
+
return value.replace(/'/g, "''");
|
|
58
|
+
}
|
|
59
|
+
/* ==========================================================================
|
|
60
|
+
* Filter
|
|
61
|
+
* ========================================================================== */
|
|
62
|
+
function toODataFilter(filter) {
|
|
63
|
+
return buildFilter(filter);
|
|
64
|
+
}
|
|
65
|
+
function buildFilter(filter) {
|
|
66
|
+
if (!filter)
|
|
67
|
+
throw new Error('Invalid filter.');
|
|
68
|
+
/*
|
|
69
|
+
* Backward compatibility:
|
|
70
|
+
*
|
|
71
|
+
* {
|
|
72
|
+
* func: 'contains',
|
|
73
|
+
* params: [...]
|
|
74
|
+
* }
|
|
75
|
+
*/
|
|
76
|
+
if (filter.func) {
|
|
77
|
+
return buildFunctionObject(filter);
|
|
78
|
+
}
|
|
79
|
+
switch (filter.operator) {
|
|
80
|
+
/* ------------------------------------------------------------------ */
|
|
81
|
+
/* Logical */
|
|
82
|
+
/* ------------------------------------------------------------------ */
|
|
83
|
+
case 'and':
|
|
84
|
+
return buildLogical(filter, 'and');
|
|
85
|
+
case 'or':
|
|
86
|
+
return buildLogical(filter, 'or');
|
|
87
|
+
case 'not':
|
|
88
|
+
return buildNot(filter);
|
|
89
|
+
/* ------------------------------------------------------------------ */
|
|
90
|
+
/* Comparison */
|
|
91
|
+
/* ------------------------------------------------------------------ */
|
|
92
|
+
case 'eq':
|
|
93
|
+
case 'ne':
|
|
94
|
+
case 'gt':
|
|
95
|
+
case 'ge':
|
|
96
|
+
case 'lt':
|
|
97
|
+
case 'le':
|
|
98
|
+
return buildComparison(filter);
|
|
99
|
+
/* ------------------------------------------------------------------ */
|
|
100
|
+
/* String */
|
|
101
|
+
/* ------------------------------------------------------------------ */
|
|
102
|
+
case 'contains':
|
|
103
|
+
return buildFunction(filter, 'contains');
|
|
104
|
+
case 'startsWith':
|
|
105
|
+
return buildFunction(filter, 'startswith');
|
|
106
|
+
case 'endsWith':
|
|
107
|
+
return buildFunction(filter, 'endswith');
|
|
108
|
+
/* ------------------------------------------------------------------ */
|
|
109
|
+
/* Value */
|
|
110
|
+
/* ------------------------------------------------------------------ */
|
|
111
|
+
case 'in':
|
|
112
|
+
return buildIn(filter);
|
|
113
|
+
case 'between':
|
|
114
|
+
return buildBetween(filter);
|
|
115
|
+
case 'isNull':
|
|
116
|
+
return `${getColumn(filter)} eq null`;
|
|
117
|
+
case 'isNotNull':
|
|
118
|
+
return `${getColumn(filter)} ne null`;
|
|
119
|
+
/* ------------------------------------------------------------------ */
|
|
120
|
+
/* Collection */
|
|
121
|
+
/* ------------------------------------------------------------------ */
|
|
122
|
+
case 'any':
|
|
123
|
+
return buildAny(filter);
|
|
124
|
+
case 'all':
|
|
125
|
+
return buildAll(filter);
|
|
126
|
+
/* ------------------------------------------------------------------ */
|
|
127
|
+
/* Collection count */
|
|
128
|
+
/* ------------------------------------------------------------------ */
|
|
129
|
+
case 'countGt':
|
|
130
|
+
case 'countGe':
|
|
131
|
+
case 'countLt':
|
|
132
|
+
case 'countLe':
|
|
133
|
+
return buildCount(filter);
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(`Unsupported OData operator: ${filter.operator}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/* ==========================================================================
|
|
139
|
+
* Logical
|
|
140
|
+
* ========================================================================== */
|
|
141
|
+
function buildLogical(filter, operator) {
|
|
142
|
+
const filters = requireFilters(filter);
|
|
143
|
+
if (filters.length === 0)
|
|
144
|
+
throw new Error(`Operator '${filter.operator}' requires at least one filter.`);
|
|
145
|
+
return filters
|
|
146
|
+
.map(buildFilter)
|
|
147
|
+
.map(expression => `(${expression})`)
|
|
148
|
+
.join(` ${operator} `);
|
|
149
|
+
}
|
|
150
|
+
function buildNot(filter) {
|
|
151
|
+
const filters = requireFilters(filter);
|
|
152
|
+
if (filters.length !== 1)
|
|
153
|
+
throw new Error("Operator 'not' requires exactly one filter.");
|
|
154
|
+
return `not (${buildFilter(filters[0])})`;
|
|
155
|
+
}
|
|
156
|
+
/* ==========================================================================
|
|
157
|
+
* Comparison
|
|
158
|
+
* ========================================================================== */
|
|
159
|
+
function buildComparison(filter) {
|
|
160
|
+
const column = getColumn(filter);
|
|
161
|
+
return (`${column} ` +
|
|
162
|
+
`${filter.operator} ` +
|
|
163
|
+
`${formatValue(filter.value)}`);
|
|
164
|
+
}
|
|
165
|
+
/* ==========================================================================
|
|
166
|
+
* String functions
|
|
167
|
+
* ========================================================================== */
|
|
168
|
+
function buildFunction(filter, functionName) {
|
|
169
|
+
const column = getColumn(filter);
|
|
170
|
+
return (`${functionName}(` +
|
|
171
|
+
`${column},` +
|
|
172
|
+
`${formatValue(filter.value)}` +
|
|
173
|
+
`)`);
|
|
174
|
+
}
|
|
175
|
+
/* ==========================================================================
|
|
176
|
+
* Function object
|
|
177
|
+
*
|
|
178
|
+
* Backward compatibility with the old:
|
|
179
|
+
*
|
|
180
|
+
* {
|
|
181
|
+
* func: 'contains',
|
|
182
|
+
* params: [...]
|
|
183
|
+
* }
|
|
184
|
+
* ========================================================================== */
|
|
185
|
+
function buildFunctionObject(filter) {
|
|
186
|
+
if (!filter.func)
|
|
187
|
+
throw new Error('Function is required.');
|
|
188
|
+
return (filter.func +
|
|
189
|
+
'(' +
|
|
190
|
+
(filter.params ?? [])
|
|
191
|
+
.map(m => formatValue(m))
|
|
192
|
+
.join(',') +
|
|
193
|
+
')');
|
|
194
|
+
}
|
|
195
|
+
/* ==========================================================================
|
|
196
|
+
* IN
|
|
197
|
+
* ========================================================================== */
|
|
198
|
+
function buildIn(filter) {
|
|
199
|
+
const column = getColumn(filter);
|
|
200
|
+
if (!Array.isArray(filter.value))
|
|
201
|
+
throw new Error("Operator 'in' requires an array value.");
|
|
202
|
+
if (filter.value.length === 0)
|
|
203
|
+
throw new Error("Operator 'in' requires at least one value.");
|
|
204
|
+
return (`${column} in (` +
|
|
205
|
+
filter.value
|
|
206
|
+
.map(formatValue)
|
|
207
|
+
.join(',') +
|
|
208
|
+
`)`);
|
|
209
|
+
}
|
|
210
|
+
/* ==========================================================================
|
|
211
|
+
* BETWEEN
|
|
212
|
+
* ========================================================================== */
|
|
213
|
+
function buildBetween(filter) {
|
|
214
|
+
const column = getColumn(filter);
|
|
215
|
+
if (!Array.isArray(filter.value) ||
|
|
216
|
+
filter.value.length !== 2) {
|
|
217
|
+
throw new Error("Operator 'between' requires exactly two values.");
|
|
218
|
+
}
|
|
219
|
+
const [min, max] = filter.value;
|
|
220
|
+
return (`(${column} ge ${formatValue(min)} ` +
|
|
221
|
+
`and ${column} le ${formatValue(max)})`);
|
|
222
|
+
}
|
|
223
|
+
/* ==========================================================================
|
|
224
|
+
* ANY
|
|
225
|
+
* ========================================================================== */
|
|
226
|
+
function buildAny(filter) {
|
|
227
|
+
const column = getColumn(filter);
|
|
228
|
+
/*
|
|
229
|
+
* orders/any()
|
|
230
|
+
*/
|
|
231
|
+
if (!filter.filters?.length)
|
|
232
|
+
return `${column}/any()`;
|
|
233
|
+
if (filter.filters.length !== 1)
|
|
234
|
+
throw new Error("Operator 'any' requires exactly one filter.");
|
|
235
|
+
return (`${column}/any(x: ` +
|
|
236
|
+
`${buildLambdaFilter(filter.filters[0], 'x')}` +
|
|
237
|
+
`)`);
|
|
238
|
+
}
|
|
239
|
+
/* ==========================================================================
|
|
240
|
+
* ALL
|
|
241
|
+
* ========================================================================== */
|
|
242
|
+
function buildAll(filter) {
|
|
243
|
+
const column = getColumn(filter);
|
|
244
|
+
const filters = requireFilters(filter);
|
|
245
|
+
if (filters.length !== 1)
|
|
246
|
+
throw new Error("Operator 'all' requires exactly one filter.");
|
|
247
|
+
return (`${column}/all(x: ` +
|
|
248
|
+
`${buildLambdaFilter(filters[0], 'x')}` +
|
|
249
|
+
`)`);
|
|
250
|
+
}
|
|
251
|
+
/* ==========================================================================
|
|
252
|
+
* Lambda filter
|
|
253
|
+
* ========================================================================== */
|
|
254
|
+
function buildLambdaFilter(filter, variable) {
|
|
255
|
+
/*
|
|
256
|
+
* Logical
|
|
257
|
+
*/
|
|
258
|
+
if (filter.operator === 'and')
|
|
259
|
+
return buildLambdaLogical(filter, variable, 'and');
|
|
260
|
+
if (filter.operator === 'or')
|
|
261
|
+
return buildLambdaLogical(filter, variable, 'or');
|
|
262
|
+
if (filter.operator === 'not') {
|
|
263
|
+
const filters = requireFilters(filter);
|
|
264
|
+
if (filters.length !== 1)
|
|
265
|
+
throw new Error("Operator 'not' requires exactly one filter.");
|
|
266
|
+
return (`not (` +
|
|
267
|
+
`${buildLambdaFilter(filters[0], variable)}` +
|
|
268
|
+
`)`);
|
|
269
|
+
}
|
|
270
|
+
/*
|
|
271
|
+
* Comparison
|
|
272
|
+
*/
|
|
273
|
+
switch (filter.operator) {
|
|
274
|
+
case 'eq':
|
|
275
|
+
case 'ne':
|
|
276
|
+
case 'gt':
|
|
277
|
+
case 'ge':
|
|
278
|
+
case 'lt':
|
|
279
|
+
case 'le':
|
|
280
|
+
return (`${variable}/${getColumn(filter)} ` +
|
|
281
|
+
`${filter.operator} ` +
|
|
282
|
+
`${formatValue(filter.value)}`);
|
|
283
|
+
/*
|
|
284
|
+
* String
|
|
285
|
+
*/
|
|
286
|
+
case 'contains':
|
|
287
|
+
return (`contains(` +
|
|
288
|
+
`${getLambdaColumn(filter, variable)},` +
|
|
289
|
+
`${formatValue(filter.value)}` +
|
|
290
|
+
`)`);
|
|
291
|
+
case 'startsWith':
|
|
292
|
+
return (`startswith(` +
|
|
293
|
+
`${getLambdaColumn(filter, variable)},` +
|
|
294
|
+
`${formatValue(filter.value)}` +
|
|
295
|
+
`)`);
|
|
296
|
+
case 'endsWith':
|
|
297
|
+
return (`endswith(` +
|
|
298
|
+
`${getLambdaColumn(filter, variable)},` +
|
|
299
|
+
`${formatValue(filter.value)}` +
|
|
300
|
+
`)`);
|
|
301
|
+
/*
|
|
302
|
+
* Null
|
|
303
|
+
*/
|
|
304
|
+
case 'isNull':
|
|
305
|
+
return (`${getLambdaColumn(filter, variable)} eq null`);
|
|
306
|
+
case 'isNotNull':
|
|
307
|
+
return (`${getLambdaColumn(filter, variable)} ne null`);
|
|
308
|
+
default:
|
|
309
|
+
throw new Error(`Operator '${filter.operator}' ` +
|
|
310
|
+
`is not supported inside any/all.`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function buildLambdaLogical(filter, variable, operator) {
|
|
314
|
+
const filters = requireFilters(filter);
|
|
315
|
+
if (filters.length === 0)
|
|
316
|
+
throw new Error(`Operator '${filter.operator}' requires at least one filter.`);
|
|
317
|
+
return filters
|
|
318
|
+
.map(item => buildLambdaFilter(item, variable))
|
|
319
|
+
.map(expression => `(${expression})`)
|
|
320
|
+
.join(` ${operator} `);
|
|
321
|
+
}
|
|
322
|
+
/* ==========================================================================
|
|
323
|
+
* Collection count
|
|
324
|
+
* ========================================================================== */
|
|
325
|
+
function buildCount(filter) {
|
|
326
|
+
const column = getColumn(filter);
|
|
327
|
+
const operators = {
|
|
328
|
+
countGt: 'gt',
|
|
329
|
+
countGe: 'ge',
|
|
330
|
+
countLt: 'lt',
|
|
331
|
+
countLe: 'le'
|
|
332
|
+
};
|
|
333
|
+
return (`${column}/$count ` +
|
|
334
|
+
`${operators[filter.operator]} ` +
|
|
335
|
+
`${formatValue(filter.value)}`);
|
|
336
|
+
}
|
|
337
|
+
/* ==========================================================================
|
|
338
|
+
* Helpers
|
|
339
|
+
* ========================================================================== */
|
|
340
|
+
function getColumn(filter) {
|
|
341
|
+
if (!filter.column ||
|
|
342
|
+
filter.column.trim().length === 0) {
|
|
343
|
+
throw new Error(`Operator '${filter.operator}' requires a column.`);
|
|
344
|
+
}
|
|
345
|
+
/*
|
|
346
|
+
* Allow:
|
|
347
|
+
*
|
|
348
|
+
* customer.name
|
|
349
|
+
* customer.address.city
|
|
350
|
+
*
|
|
351
|
+
* to become:
|
|
352
|
+
*
|
|
353
|
+
* customer/name
|
|
354
|
+
* customer/address/city
|
|
355
|
+
*/
|
|
356
|
+
return filter.column.replace(/\./g, '/');
|
|
357
|
+
}
|
|
358
|
+
function getLambdaColumn(filter, variable) {
|
|
359
|
+
return (`${variable}/` +
|
|
360
|
+
`${getColumn(filter)}`);
|
|
361
|
+
}
|
|
362
|
+
function requireFilters(filter) {
|
|
363
|
+
if (!filter.filters)
|
|
364
|
+
throw new Error(`Operator '${filter.operator}' requires filters.`);
|
|
365
|
+
return filter.filters;
|
|
366
|
+
}
|
|
367
|
+
/* ==========================================================================
|
|
368
|
+
* OData Request
|
|
369
|
+
* ========================================================================== */
|
|
370
|
+
function odata(options, props = {}) {
|
|
371
|
+
const url = new URL(options.url);
|
|
372
|
+
/* ---------------------------------------------------------------------- */
|
|
373
|
+
/* Paging */
|
|
374
|
+
/* ---------------------------------------------------------------------- */
|
|
375
|
+
if (props.pageSize &&
|
|
376
|
+
props.pageSize > 0) {
|
|
377
|
+
const currPage = props.currPage && props.currPage > 0
|
|
378
|
+
? props.currPage
|
|
379
|
+
: 1;
|
|
380
|
+
const skip = props.pageSize * (currPage - 1);
|
|
381
|
+
url.searchParams.set('$skip', String(skip));
|
|
382
|
+
url.searchParams.set('$top', String(props.pageSize));
|
|
383
|
+
}
|
|
384
|
+
/* ---------------------------------------------------------------------- */
|
|
385
|
+
/* Count */
|
|
386
|
+
/* ---------------------------------------------------------------------- */
|
|
387
|
+
if (options.count === true) {
|
|
388
|
+
url.searchParams.set('$count', 'true');
|
|
389
|
+
}
|
|
390
|
+
/* ---------------------------------------------------------------------- */
|
|
391
|
+
/* Select */
|
|
392
|
+
/* ---------------------------------------------------------------------- */
|
|
393
|
+
if (options.select &&
|
|
394
|
+
options.select.length > 0) {
|
|
395
|
+
url.searchParams.set('$select', options.select
|
|
396
|
+
.map(m => m.replace(/\./g, '/'))
|
|
397
|
+
.join(','));
|
|
398
|
+
}
|
|
399
|
+
/* ---------------------------------------------------------------------- */
|
|
400
|
+
/* Expand */
|
|
401
|
+
/* ---------------------------------------------------------------------- */
|
|
402
|
+
if (options.expand &&
|
|
403
|
+
options.expand.length > 0) {
|
|
404
|
+
const expand = options.expand
|
|
405
|
+
.map(expand => {
|
|
406
|
+
const name = expand.name.replace(/\./g, '/');
|
|
407
|
+
if (expand.select &&
|
|
408
|
+
expand.select.length > 0) {
|
|
409
|
+
return (`${name}` +
|
|
410
|
+
`($select=` +
|
|
411
|
+
`${expand.select
|
|
412
|
+
.map(m => m.replace(/\./g, '/'))
|
|
413
|
+
.join(',')}` +
|
|
414
|
+
`)`);
|
|
415
|
+
}
|
|
416
|
+
return name;
|
|
417
|
+
})
|
|
418
|
+
.join(',');
|
|
419
|
+
url.searchParams.set('$expand', expand);
|
|
420
|
+
}
|
|
421
|
+
/* ---------------------------------------------------------------------- */
|
|
422
|
+
/* Filter */
|
|
423
|
+
/* ---------------------------------------------------------------------- */
|
|
424
|
+
const filters = [];
|
|
425
|
+
/*
|
|
426
|
+
* Static filter from options
|
|
427
|
+
*/
|
|
428
|
+
if (options.filter &&
|
|
429
|
+
(options.filter.filters ||
|
|
430
|
+
options.filter.column ||
|
|
431
|
+
options.filter.func)) {
|
|
432
|
+
const expression = toODataFilter(options.filter);
|
|
433
|
+
if (expression)
|
|
434
|
+
filters.push(`(${expression})`);
|
|
435
|
+
}
|
|
436
|
+
/*
|
|
437
|
+
* Runtime filter from DataTable
|
|
438
|
+
*/
|
|
439
|
+
if (props.filter &&
|
|
440
|
+
(props.filter.filters ||
|
|
441
|
+
props.filter.column ||
|
|
442
|
+
props.filter.func)) {
|
|
443
|
+
const expression = toODataFilter(props.filter);
|
|
444
|
+
if (expression)
|
|
445
|
+
filters.push(`(${expression})`);
|
|
446
|
+
}
|
|
447
|
+
/* ---------------------------------------------------------------------- */
|
|
448
|
+
/* Search */
|
|
449
|
+
/* ---------------------------------------------------------------------- */
|
|
450
|
+
if (props.search &&
|
|
451
|
+
props.search.trim() &&
|
|
452
|
+
props.cols &&
|
|
453
|
+
props.cols.length > 0) {
|
|
454
|
+
const searchValue = escapeODataString(props.search.trim());
|
|
455
|
+
const searchExpressions = props.cols
|
|
456
|
+
.filter(column => column.searchable === undefined ||
|
|
457
|
+
column.searchable === true)
|
|
458
|
+
.map(column => {
|
|
459
|
+
const name = column.name.replace(/\./g, '/');
|
|
460
|
+
return (`contains(` +
|
|
461
|
+
`${name},` +
|
|
462
|
+
`'${searchValue}'` +
|
|
463
|
+
`)`);
|
|
464
|
+
});
|
|
465
|
+
if (searchExpressions.length > 0) {
|
|
466
|
+
filters.push(`(${searchExpressions.join(' or ')})`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
/*
|
|
470
|
+
* Combine all filters with AND.
|
|
471
|
+
*/
|
|
472
|
+
if (filters.length > 0) {
|
|
473
|
+
url.searchParams.set('$filter', filters.join(' and '));
|
|
474
|
+
}
|
|
475
|
+
/* ---------------------------------------------------------------------- */
|
|
476
|
+
/* Order By */
|
|
477
|
+
/* ---------------------------------------------------------------------- */
|
|
478
|
+
if (props.sort &&
|
|
479
|
+
props.sort.length > 0) {
|
|
480
|
+
const orderBy = props.sort
|
|
481
|
+
.map(sort => {
|
|
482
|
+
let column;
|
|
483
|
+
if (sort.index !== undefined &&
|
|
484
|
+
sort.index >= 0) {
|
|
485
|
+
if (!props.cols ||
|
|
486
|
+
!props.cols[sort.index]) {
|
|
487
|
+
throw new Error(`Invalid sort column index: ${sort.index}`);
|
|
488
|
+
}
|
|
489
|
+
column =
|
|
490
|
+
props.cols[sort.index].name;
|
|
491
|
+
}
|
|
492
|
+
else if (sort.name) {
|
|
493
|
+
column = sort.name;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
throw new Error('Sort requires either index or name.');
|
|
497
|
+
}
|
|
498
|
+
column =
|
|
499
|
+
column.replace(/\./g, '/');
|
|
500
|
+
return (column +
|
|
501
|
+
(sort.dir
|
|
502
|
+
? ` ${sort.dir}`
|
|
503
|
+
: ''));
|
|
504
|
+
})
|
|
505
|
+
.join(',');
|
|
506
|
+
url.searchParams.set('$orderby', orderBy);
|
|
507
|
+
}
|
|
508
|
+
/* ---------------------------------------------------------------------- */
|
|
509
|
+
/* Request */
|
|
510
|
+
/* ---------------------------------------------------------------------- */
|
|
511
|
+
return new Request(url, options.header);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
exports.default = odata;
|
|
515
|
+
exports.toODataFilter = toODataFilter;
|
|
516
|
+
|
|
517
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
518
|
+
|
|
519
|
+
}));
|