express-ext 0.1.7 → 0.1.12
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/GenericController.js +16 -8
- package/lib/GenericSearchController.js +0 -1
- package/lib/HealthController.js +7 -49
- package/lib/LoadController.js +0 -1
- package/lib/LoadSearchController.js +0 -1
- package/lib/LogController.js +51 -0
- package/lib/LowCodeController.js +0 -1
- package/lib/SearchController.js +0 -1
- package/lib/edit.js +12 -13
- package/lib/health.js +5 -8
- package/lib/http.js +33 -7
- package/lib/index.js +2 -41
- package/lib/resources.js +2 -9
- package/lib/search.js +70 -58
- package/lib/search_func.js +0 -1
- package/lib/view.js +9 -7
- package/package.json +1 -1
- package/src/GenericController.ts +21 -13
- package/src/GenericSearchController.ts +3 -3
- package/src/HealthController.ts +1 -1
- package/src/LoadController.ts +6 -6
- package/src/LoadSearchController.ts +3 -3
- package/src/LogController.ts +70 -0
- package/src/LowCodeController.ts +4 -4
- package/src/SearchController.ts +3 -3
- package/src/edit.ts +18 -18
- package/src/health.ts +3 -4
- package/src/http.ts +46 -23
- package/src/index.ts +10 -0
- package/src/metadata.ts +2 -1
- package/src/search.ts +74 -62
- package/src/search_func.ts +1 -1
- package/src/view.ts +12 -9
- package/tsconfig.json +1 -0
package/src/search.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Request, Response} from 'express';
|
|
2
2
|
import {Attribute, Attributes} from './metadata';
|
|
3
3
|
|
|
4
|
-
export interface
|
|
4
|
+
export interface Filter {
|
|
5
5
|
fields?: string[];
|
|
6
6
|
sort?: string;
|
|
7
7
|
|
|
@@ -40,17 +40,21 @@ export function buildResult<T>(r: SearchResult<T>, conf?: SearchConfig): any {
|
|
|
40
40
|
return r;
|
|
41
41
|
}
|
|
42
42
|
const x: any = {};
|
|
43
|
-
|
|
44
|
-
x[
|
|
43
|
+
const li = (conf.list ? conf.list : 'list');
|
|
44
|
+
x[li] = r.list;
|
|
45
|
+
const to = (conf.total ? conf.total : 'total');
|
|
46
|
+
x[to] = r.total;
|
|
45
47
|
if (r.nextPageToken && r.nextPageToken.length > 0) {
|
|
46
|
-
|
|
48
|
+
const t = (conf.token ? conf.token : 'token');
|
|
49
|
+
x[t] = r.nextPageToken;
|
|
47
50
|
}
|
|
48
51
|
if (r.last) {
|
|
49
|
-
|
|
52
|
+
const l = (conf.last ? conf.last : 'last');
|
|
53
|
+
x[l] = r.last;
|
|
50
54
|
}
|
|
51
55
|
return x;
|
|
52
56
|
}
|
|
53
|
-
export function initializeConfig(conf
|
|
57
|
+
export function initializeConfig(conf?: SearchConfig): SearchConfig | undefined {
|
|
54
58
|
if (!conf) {
|
|
55
59
|
return undefined;
|
|
56
60
|
}
|
|
@@ -149,9 +153,9 @@ export function setValue<T>(obj: T, path: string, value: string): void {
|
|
|
149
153
|
export function setValue<T, V>(obj: T, path: string, value: V): void {
|
|
150
154
|
const paths = path.split('.');
|
|
151
155
|
if (paths.length === 1) {
|
|
152
|
-
obj[path] = value;
|
|
156
|
+
(obj as any)[path] = value;
|
|
153
157
|
} else {
|
|
154
|
-
let o = obj;
|
|
158
|
+
let o: any = obj;
|
|
155
159
|
const l = paths.length - 1;
|
|
156
160
|
for (let i = 0; i < l - 1; i++) {
|
|
157
161
|
const p = paths[i];
|
|
@@ -173,42 +177,43 @@ export interface Limit {
|
|
|
173
177
|
skipOrRefId?: string|number;
|
|
174
178
|
}
|
|
175
179
|
export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
180
|
+
const o: any = obj;
|
|
176
181
|
if (!config) {
|
|
177
182
|
const sfield = 'fields';
|
|
178
183
|
let fields;
|
|
179
|
-
const fs =
|
|
184
|
+
const fs = o[sfield];
|
|
180
185
|
if (fs && Array.isArray(fs)) {
|
|
181
186
|
fields = fs;
|
|
182
|
-
delete
|
|
187
|
+
delete o[sfield];
|
|
183
188
|
}
|
|
184
|
-
let refId =
|
|
189
|
+
let refId = o['refId'];
|
|
185
190
|
if (!refId) {
|
|
186
|
-
refId =
|
|
191
|
+
refId = o['nextPageToken'];
|
|
187
192
|
}
|
|
188
193
|
const r: Limit = {fields, refId};
|
|
189
|
-
let pageSize =
|
|
194
|
+
let pageSize = o['limit'];
|
|
190
195
|
if (!pageSize) {
|
|
191
|
-
pageSize =
|
|
196
|
+
pageSize = o['pageSize'];
|
|
192
197
|
}
|
|
193
198
|
if (pageSize && !isNaN(pageSize)) {
|
|
194
199
|
const ipageSize = Math.floor(parseFloat(pageSize));
|
|
195
200
|
if (ipageSize > 0) {
|
|
196
201
|
r.limit = ipageSize;
|
|
197
|
-
const skip =
|
|
202
|
+
const skip = o['skip'];
|
|
198
203
|
if (skip && !isNaN(skip)) {
|
|
199
204
|
const iskip = Math.floor(parseFloat(skip));
|
|
200
205
|
if (iskip >= 0) {
|
|
201
206
|
r.skip = iskip;
|
|
202
207
|
r.skipOrRefId = r.skip;
|
|
203
|
-
deletePageInfo(
|
|
208
|
+
deletePageInfo(o);
|
|
204
209
|
return r;
|
|
205
210
|
}
|
|
206
211
|
}
|
|
207
|
-
let pageIndex =
|
|
212
|
+
let pageIndex = o['page'];
|
|
208
213
|
if (!pageIndex) {
|
|
209
|
-
pageIndex =
|
|
214
|
+
pageIndex = o['pageIndex'];
|
|
210
215
|
if (!pageIndex) {
|
|
211
|
-
pageIndex =
|
|
216
|
+
pageIndex = o['pageNo'];
|
|
212
217
|
}
|
|
213
218
|
}
|
|
214
219
|
if (pageIndex && !isNaN(pageIndex)) {
|
|
@@ -216,39 +221,39 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
216
221
|
if (ipageIndex < 1) {
|
|
217
222
|
ipageIndex = 1;
|
|
218
223
|
}
|
|
219
|
-
let firstPageSize =
|
|
224
|
+
let firstPageSize = o['firstLimit'];
|
|
220
225
|
if (!firstPageSize) {
|
|
221
|
-
firstPageSize =
|
|
226
|
+
firstPageSize = o['firstPageSize'];
|
|
222
227
|
}
|
|
223
228
|
if (!firstPageSize) {
|
|
224
|
-
firstPageSize =
|
|
229
|
+
firstPageSize = o['initPageSize'];
|
|
225
230
|
}
|
|
226
231
|
if (firstPageSize && !isNaN(firstPageSize)) {
|
|
227
232
|
const ifirstPageSize = Math.floor(parseFloat(firstPageSize));
|
|
228
233
|
if (ifirstPageSize > 0) {
|
|
229
234
|
r.skip = ipageSize * (ipageIndex - 2) + ifirstPageSize;
|
|
230
235
|
r.skipOrRefId = r.skip;
|
|
231
|
-
deletePageInfo(
|
|
236
|
+
deletePageInfo(o);
|
|
232
237
|
return r;
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
r.skip = ipageSize * (ipageIndex - 1);
|
|
236
241
|
r.skipOrRefId = r.skip;
|
|
237
|
-
deletePageInfo(
|
|
242
|
+
deletePageInfo(o);
|
|
238
243
|
return r;
|
|
239
244
|
}
|
|
240
245
|
r.skip = 0;
|
|
241
246
|
if (r.refId && r.refId.length > 0) {
|
|
242
247
|
r.skipOrRefId = r.refId;
|
|
243
248
|
}
|
|
244
|
-
deletePageInfo(
|
|
249
|
+
deletePageInfo(o);
|
|
245
250
|
return r;
|
|
246
251
|
}
|
|
247
252
|
}
|
|
248
253
|
if (r.refId && r.refId.length > 0) {
|
|
249
254
|
r.skipOrRefId = r.refId;
|
|
250
255
|
}
|
|
251
|
-
deletePageInfo(
|
|
256
|
+
deletePageInfo(o);
|
|
252
257
|
return r;
|
|
253
258
|
} else {
|
|
254
259
|
let sfield = config.fields;
|
|
@@ -256,23 +261,23 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
256
261
|
sfield = 'fields';
|
|
257
262
|
}
|
|
258
263
|
let fields;
|
|
259
|
-
const fs =
|
|
264
|
+
const fs = o[sfield];
|
|
260
265
|
if (fs && Array.isArray(fs)) {
|
|
261
266
|
fields = fs;
|
|
262
|
-
delete
|
|
267
|
+
delete o[sfield];
|
|
263
268
|
}
|
|
264
269
|
let strRefId = config.refId;
|
|
265
270
|
if (!strRefId || strRefId.length === 0) {
|
|
266
271
|
strRefId = 'refId';
|
|
267
272
|
}
|
|
268
|
-
const refId =
|
|
273
|
+
const refId = o[strRefId];
|
|
269
274
|
const r: Limit = {fields, refId};
|
|
270
275
|
|
|
271
276
|
let strLimit = config.limit;
|
|
272
277
|
if (!strLimit || strLimit.length === 0) {
|
|
273
278
|
strLimit = 'limit';
|
|
274
279
|
}
|
|
275
|
-
const pageSize =
|
|
280
|
+
const pageSize = o[strLimit];
|
|
276
281
|
const arr = [config.page, config.limit, config.skip, config.refId, config.firstLimit];
|
|
277
282
|
if (pageSize && !isNaN(pageSize)) {
|
|
278
283
|
const ipageSize = Math.floor(parseFloat(pageSize));
|
|
@@ -282,13 +287,13 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
282
287
|
if (!strSkip || strSkip.length === 0) {
|
|
283
288
|
strSkip = 'skip';
|
|
284
289
|
}
|
|
285
|
-
const skip =
|
|
290
|
+
const skip = o[strSkip];
|
|
286
291
|
if (skip && !isNaN(skip)) {
|
|
287
292
|
const iskip = Math.floor(parseFloat(skip));
|
|
288
293
|
if (iskip >= 0) {
|
|
289
294
|
r.skip = iskip;
|
|
290
295
|
r.skipOrRefId = r.skip;
|
|
291
|
-
deletePageInfo(
|
|
296
|
+
deletePageInfo(o, arr);
|
|
292
297
|
return r;
|
|
293
298
|
}
|
|
294
299
|
}
|
|
@@ -296,7 +301,7 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
296
301
|
if (!strPage || strPage.length === 0) {
|
|
297
302
|
strPage = 'page';
|
|
298
303
|
}
|
|
299
|
-
const pageIndex =
|
|
304
|
+
const pageIndex = o[strPage];
|
|
300
305
|
if (pageIndex && !isNaN(pageIndex)) {
|
|
301
306
|
let ipageIndex = Math.floor(parseFloat(pageIndex));
|
|
302
307
|
if (ipageIndex < 1) {
|
|
@@ -306,37 +311,37 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
306
311
|
if (!strFirstLimit || strFirstLimit.length === 0) {
|
|
307
312
|
strFirstLimit = 'firstLimit';
|
|
308
313
|
}
|
|
309
|
-
const firstPageSize =
|
|
314
|
+
const firstPageSize = o[strFirstLimit];
|
|
310
315
|
if (firstPageSize && !isNaN(firstPageSize)) {
|
|
311
316
|
const ifirstPageSize = Math.floor(parseFloat(firstPageSize));
|
|
312
317
|
if (ifirstPageSize > 0) {
|
|
313
318
|
r.skip = ipageSize * (ipageIndex - 2) + ifirstPageSize;
|
|
314
319
|
r.skipOrRefId = r.skip;
|
|
315
|
-
deletePageInfo(
|
|
320
|
+
deletePageInfo(o, arr);
|
|
316
321
|
return r;
|
|
317
322
|
}
|
|
318
323
|
}
|
|
319
324
|
r.skip = ipageSize * (ipageIndex - 1);
|
|
320
325
|
r.skipOrRefId = r.skip;
|
|
321
|
-
deletePageInfo(
|
|
326
|
+
deletePageInfo(o, arr);
|
|
322
327
|
return r;
|
|
323
328
|
}
|
|
324
329
|
r.skip = 0;
|
|
325
330
|
if (r.refId && r.refId.length > 0) {
|
|
326
331
|
r.skipOrRefId = r.refId;
|
|
327
332
|
}
|
|
328
|
-
deletePageInfo(
|
|
333
|
+
deletePageInfo(o, arr);
|
|
329
334
|
return r;
|
|
330
335
|
}
|
|
331
336
|
}
|
|
332
337
|
if (r.refId && r.refId.length > 0) {
|
|
333
338
|
r.skipOrRefId = r.refId;
|
|
334
339
|
}
|
|
335
|
-
deletePageInfo(
|
|
340
|
+
deletePageInfo(o, arr);
|
|
336
341
|
return r;
|
|
337
342
|
}
|
|
338
343
|
}
|
|
339
|
-
export function deletePageInfo(obj: any, arr?: string[]): void {
|
|
344
|
+
export function deletePageInfo(obj: any, arr?: (string | undefined)[]): void {
|
|
340
345
|
if (!arr || arr.length === 0) {
|
|
341
346
|
delete obj['limit'];
|
|
342
347
|
delete obj['firstLimit'];
|
|
@@ -371,7 +376,7 @@ export function toCsv<T>(fields: string[], r: SearchResult<T>): string {
|
|
|
371
376
|
for (const item of r.list) {
|
|
372
377
|
const cols: string[] = [];
|
|
373
378
|
for (const name of fields) {
|
|
374
|
-
const v = item[name];
|
|
379
|
+
const v = (item as any)[name];
|
|
375
380
|
if (!v) {
|
|
376
381
|
cols.push(e);
|
|
377
382
|
} else {
|
|
@@ -439,8 +444,8 @@ export function buildMetadata(attributes: Attributes, includeDate?: boolean): Me
|
|
|
439
444
|
|
|
440
445
|
const _datereg = '/Date(';
|
|
441
446
|
const _re = /-?\d+/;
|
|
442
|
-
function toDate(v: any) {
|
|
443
|
-
if (!v
|
|
447
|
+
function toDate(v: any): Date | null | undefined {
|
|
448
|
+
if (!v) {
|
|
444
449
|
return null;
|
|
445
450
|
}
|
|
446
451
|
if (v instanceof Date) {
|
|
@@ -451,33 +456,39 @@ function toDate(v: any) {
|
|
|
451
456
|
const i = v.indexOf(_datereg);
|
|
452
457
|
if (i >= 0) {
|
|
453
458
|
const m = _re.exec(v);
|
|
454
|
-
|
|
455
|
-
|
|
459
|
+
if (m !== null) {
|
|
460
|
+
const d = parseInt(m[0], 10);
|
|
461
|
+
return new Date(d);
|
|
462
|
+
} else {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
456
465
|
} else {
|
|
457
466
|
if (isNaN(v)) {
|
|
458
467
|
return new Date(v);
|
|
459
468
|
} else {
|
|
460
|
-
const d = parseInt(v,
|
|
469
|
+
const d = parseInt(v, 10);
|
|
461
470
|
return new Date(d);
|
|
462
471
|
}
|
|
463
472
|
}
|
|
464
473
|
}
|
|
465
474
|
|
|
466
475
|
export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
476
|
+
const o: any = obj;
|
|
467
477
|
if (dates && dates.length > 0) {
|
|
468
478
|
for (const s of dates) {
|
|
469
|
-
const v =
|
|
479
|
+
const v = o[s];
|
|
470
480
|
if (v) {
|
|
471
481
|
if (v instanceof Date) {
|
|
472
482
|
continue;
|
|
473
483
|
}
|
|
474
484
|
if (typeof v === 'string' || typeof v === 'number') {
|
|
475
485
|
const d = toDate(v);
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
486
|
+
if (d) {
|
|
487
|
+
if (!(d instanceof Date) || d.toString() === 'Invalid Date') {
|
|
488
|
+
delete o[s];
|
|
489
|
+
} else {
|
|
490
|
+
o[s] = d;
|
|
491
|
+
}
|
|
481
492
|
}
|
|
482
493
|
} else if (typeof v === 'object') {
|
|
483
494
|
const keys = Object.keys(v);
|
|
@@ -488,11 +499,12 @@ export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
|
488
499
|
}
|
|
489
500
|
if (typeof v2 === 'string' || typeof v2 === 'number') {
|
|
490
501
|
const d2 = toDate(v2);
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
502
|
+
if (d2) {
|
|
503
|
+
if (!(d2 instanceof Date) || d2.toString() === 'Invalid Date') {
|
|
504
|
+
delete v[key];
|
|
505
|
+
} else {
|
|
506
|
+
v[key] = d2;
|
|
507
|
+
}
|
|
496
508
|
}
|
|
497
509
|
}
|
|
498
510
|
}
|
|
@@ -502,10 +514,10 @@ export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
|
502
514
|
}
|
|
503
515
|
if (nums && nums.length > 0) {
|
|
504
516
|
for (const s of nums) {
|
|
505
|
-
const v =
|
|
517
|
+
const v = o[s];
|
|
506
518
|
if (v) {
|
|
507
519
|
if (v instanceof Date) {
|
|
508
|
-
delete
|
|
520
|
+
delete o[s];
|
|
509
521
|
continue;
|
|
510
522
|
}
|
|
511
523
|
if (typeof v === 'number') {
|
|
@@ -513,18 +525,18 @@ export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
|
513
525
|
}
|
|
514
526
|
if (typeof v === 'string') {
|
|
515
527
|
if (!isNaN(v as any)) {
|
|
516
|
-
delete
|
|
528
|
+
delete o[s];
|
|
517
529
|
continue;
|
|
518
530
|
} else {
|
|
519
531
|
const i = parseFloat(v);
|
|
520
|
-
|
|
532
|
+
o[s] = i;
|
|
521
533
|
}
|
|
522
534
|
} else if (typeof v === 'object') {
|
|
523
535
|
const keys = Object.keys(v);
|
|
524
536
|
for (const key of keys) {
|
|
525
537
|
const v2 = v[key];
|
|
526
538
|
if (v2 instanceof Date) {
|
|
527
|
-
delete
|
|
539
|
+
delete o[key];
|
|
528
540
|
continue;
|
|
529
541
|
}
|
|
530
542
|
if (typeof v2 === 'number') {
|
|
@@ -543,5 +555,5 @@ export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
|
543
555
|
}
|
|
544
556
|
}
|
|
545
557
|
}
|
|
546
|
-
return
|
|
558
|
+
return o;
|
|
547
559
|
}
|
package/src/search_func.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {ViewService} from './LoadController';
|
|
|
2
2
|
import {Attribute, Attributes} from './metadata';
|
|
3
3
|
import {buildMetadata, Metadata} from './search';
|
|
4
4
|
|
|
5
|
-
export function getMetadataFunc<T, ID>(viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>), dates?: string[], numbers?: string[], keys?: Attributes|Attribute[]|string[]): Metadata {
|
|
5
|
+
export function getMetadataFunc<T, ID>(viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>), dates?: string[], numbers?: string[], keys?: Attributes|Attribute[]|string[]): Metadata | undefined {
|
|
6
6
|
const m: Metadata = { dates, numbers };
|
|
7
7
|
if (m.dates && m.dates.length > 0 || m.numbers && m.numbers.length > 0) {
|
|
8
8
|
return m;
|
package/src/view.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {Request, Response} from 'express';
|
|
2
2
|
import {Attribute, Attributes} from './metadata';
|
|
3
3
|
|
|
4
|
-
export function buildAndCheckId<ID>(req: Request, res: Response, keys?: Attribute[]) {
|
|
4
|
+
export function buildAndCheckId<ID>(req: Request, res: Response, keys?: Attribute[]): ID | undefined {
|
|
5
5
|
const id = buildId<ID>(req, keys);
|
|
6
6
|
if (!id) {
|
|
7
7
|
res.status(400).end('invalid parameters');
|
|
8
|
-
return
|
|
8
|
+
return undefined;
|
|
9
9
|
}
|
|
10
10
|
return id;
|
|
11
11
|
}
|
|
12
|
-
export function buildId<T>(req: Request, attrs?: Attribute[]): T {
|
|
13
|
-
if (!attrs) {
|
|
12
|
+
export function buildId<T>(req: Request, attrs?: Attribute[]): T | undefined {
|
|
13
|
+
if (!attrs || attrs.length === 0) {
|
|
14
14
|
const id = req.params['id'];
|
|
15
15
|
if (id && id.length > 0) {
|
|
16
16
|
return id as any;
|
|
17
17
|
}
|
|
18
|
-
return
|
|
18
|
+
return undefined;
|
|
19
19
|
}
|
|
20
20
|
if (attrs && attrs.length === 1) {
|
|
21
21
|
let id = req.params['id'];
|
|
@@ -26,7 +26,7 @@ export function buildId<T>(req: Request, attrs?: Attribute[]): T {
|
|
|
26
26
|
if (id && id.length > 0) {
|
|
27
27
|
if (attrs[0].type === 'integer' || attrs[0].type === 'number') {
|
|
28
28
|
if (isNaN(id as any)) {
|
|
29
|
-
return
|
|
29
|
+
return undefined;
|
|
30
30
|
}
|
|
31
31
|
const v = parseFloat(id);
|
|
32
32
|
return v as any;
|
|
@@ -36,13 +36,16 @@ export function buildId<T>(req: Request, attrs?: Attribute[]): T {
|
|
|
36
36
|
}
|
|
37
37
|
const ids: any = {};
|
|
38
38
|
for (const attr of attrs) {
|
|
39
|
+
if (!attr.name) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
39
42
|
const v = req.params[attr.name];
|
|
40
43
|
if (!v) {
|
|
41
|
-
return
|
|
44
|
+
return undefined;
|
|
42
45
|
}
|
|
43
46
|
if (attr.type === 'integer' || attr.type === 'number') {
|
|
44
47
|
if (isNaN(v as any)) {
|
|
45
|
-
return
|
|
48
|
+
return undefined;
|
|
46
49
|
}
|
|
47
50
|
ids[attr.name] = parseFloat(v);
|
|
48
51
|
} else {
|
|
@@ -51,7 +54,7 @@ export function buildId<T>(req: Request, attrs?: Attribute[]): T {
|
|
|
51
54
|
return ids;
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
|
-
export function buildKeys(attrs: Attributes): Attribute[] {
|
|
57
|
+
export function buildKeys(attrs: Attributes): Attribute[] | undefined {
|
|
55
58
|
if (!attrs) {
|
|
56
59
|
return undefined;
|
|
57
60
|
}
|