express-ext 0.2.6 → 0.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/GenericController.js +89 -66
- package/lib/GenericSearchController.js +2 -3
- package/lib/LoadSearchController.js +4 -5
- package/lib/LowCodeController.js +4 -5
- package/lib/SearchController.js +1 -1
- package/lib/edit.js +58 -34
- package/lib/index.js +6 -1
- package/lib/resources.js +9 -0
- package/lib/search.js +92 -48
- package/package.json +1 -1
- package/src/GenericController.ts +92 -41
- package/src/GenericSearchController.ts +4 -4
- package/src/LoadSearchController.ts +3 -4
- package/src/LowCodeController.ts +6 -6
- package/src/SearchController.ts +1 -1
- package/src/edit.ts +65 -31
- package/src/index.ts +5 -1
- package/src/resources.ts +12 -1
- package/src/search.ts +98 -20
- package/lib/search_func.js +0 -22
- package/src/search_func.ts +0 -22
package/src/edit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {Response} from 'express';
|
|
2
|
-
import {handleError} from './http';
|
|
3
|
-
import {Attribute, ErrorMessage} from './metadata';
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { handleError } from './http';
|
|
3
|
+
import { Attribute, ErrorMessage } from './metadata';
|
|
4
4
|
/*
|
|
5
5
|
export interface StatusConfig {
|
|
6
6
|
duplicate_key: number|string;
|
|
@@ -32,7 +32,7 @@ export function initializeStatus(s?: StatusConfig): StatusConfig {
|
|
|
32
32
|
}
|
|
33
33
|
*/
|
|
34
34
|
export function checkId<T, ID>(obj: T, id: ID, keys?: Attribute[]): boolean {
|
|
35
|
-
const n: string =
|
|
35
|
+
const n: string = keys && keys.length === 1 && keys[0].name ? keys[0].name : 'id';
|
|
36
36
|
const o: any = obj;
|
|
37
37
|
const i: any = id;
|
|
38
38
|
if (!keys || keys.length === 1) {
|
|
@@ -62,37 +62,59 @@ export function checkId<T, ID>(obj: T, id: ID, keys?: Attribute[]): boolean {
|
|
|
62
62
|
}
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
|
-
export function create<T>(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
export function create<T>(
|
|
66
|
+
res: Response,
|
|
67
|
+
obj: T,
|
|
68
|
+
insert: (obj: T, ctx?: any) => Promise<number | T | ErrorMessage[]>,
|
|
69
|
+
log: (msg: string, ctx?: any) => void,
|
|
70
|
+
returnNumber?: boolean,
|
|
71
|
+
): void {
|
|
72
|
+
insert(obj)
|
|
73
|
+
.then((result) => {
|
|
74
|
+
if (typeof result === 'number') {
|
|
75
|
+
if (result >= 1) {
|
|
76
|
+
res
|
|
77
|
+
.status(201)
|
|
78
|
+
.json(returnNumber ? result : obj)
|
|
79
|
+
.end();
|
|
80
|
+
} else {
|
|
81
|
+
res.status(409).json(result).end();
|
|
82
|
+
}
|
|
83
|
+
} else if (Array.isArray(result)) {
|
|
84
|
+
res.status(422).json(result).end();
|
|
70
85
|
} else {
|
|
71
|
-
res.status(
|
|
86
|
+
res.status(201).json(result).end();
|
|
72
87
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
} else {
|
|
76
|
-
res.status(201).json(result).end();
|
|
77
|
-
}
|
|
78
|
-
}).catch(err => handleError(err, res, log));
|
|
88
|
+
})
|
|
89
|
+
.catch((err) => handleError(err, res, log));
|
|
79
90
|
}
|
|
80
|
-
export function update<T>(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
export function update<T>(
|
|
92
|
+
res: Response,
|
|
93
|
+
obj: T,
|
|
94
|
+
save: (obj: T, ctx?: any) => Promise<number | T | ErrorMessage[]>,
|
|
95
|
+
log: (msg: string, ctx?: any) => void,
|
|
96
|
+
returnNumber?: boolean,
|
|
97
|
+
): void {
|
|
98
|
+
save(obj)
|
|
99
|
+
.then((result) => {
|
|
100
|
+
if (typeof result === 'number') {
|
|
101
|
+
if (result >= 1) {
|
|
102
|
+
res
|
|
103
|
+
.status(200)
|
|
104
|
+
.json(returnNumber ? result : obj)
|
|
105
|
+
.end();
|
|
106
|
+
} else if (result === 0) {
|
|
107
|
+
res.status(404).json(result).end();
|
|
108
|
+
} else {
|
|
109
|
+
res.status(409).json(result).end();
|
|
110
|
+
}
|
|
111
|
+
} else if (Array.isArray(result)) {
|
|
112
|
+
res.status(422).json(result).end();
|
|
87
113
|
} else {
|
|
88
|
-
res.status(
|
|
114
|
+
res.status(200).json(result).end();
|
|
89
115
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
} else {
|
|
93
|
-
res.status(200).json(result).end();
|
|
94
|
-
}
|
|
95
|
-
}).catch(err => handleError(err, res, log));
|
|
116
|
+
})
|
|
117
|
+
.catch((err) => handleError(err, res, log));
|
|
96
118
|
}
|
|
97
119
|
export function isTypeError(errs: ErrorMessage[]): boolean {
|
|
98
120
|
if (!errs) {
|
|
@@ -100,7 +122,19 @@ export function isTypeError(errs: ErrorMessage[]): boolean {
|
|
|
100
122
|
}
|
|
101
123
|
for (const err of errs) {
|
|
102
124
|
const c = err.code;
|
|
103
|
-
if (
|
|
125
|
+
if (
|
|
126
|
+
c === 'type' ||
|
|
127
|
+
c === 'string' ||
|
|
128
|
+
c === 'number' ||
|
|
129
|
+
c === 'date' ||
|
|
130
|
+
c === 'boolean' ||
|
|
131
|
+
c === 'strings' ||
|
|
132
|
+
c === 'numbers' ||
|
|
133
|
+
c === 'integers' ||
|
|
134
|
+
c === 'dates' ||
|
|
135
|
+
c === 'datetimes' ||
|
|
136
|
+
c === 'booleans'
|
|
137
|
+
) {
|
|
104
138
|
return true;
|
|
105
139
|
}
|
|
106
140
|
}
|
package/src/index.ts
CHANGED
|
@@ -36,7 +36,6 @@ export * from './LowCodeController';
|
|
|
36
36
|
export * from './metadata';
|
|
37
37
|
export * from './resources';
|
|
38
38
|
export * from './search';
|
|
39
|
-
export * from './search_func';
|
|
40
39
|
export * from './SearchController';
|
|
41
40
|
export * from './view';
|
|
42
41
|
|
|
@@ -291,3 +290,8 @@ export class UserReactionController {
|
|
|
291
290
|
}
|
|
292
291
|
export const ReactController = UserReactionController;
|
|
293
292
|
export const ReactionController = UserReactionController;
|
|
293
|
+
export function addDays(d: Date, n: number): Date {
|
|
294
|
+
const newDate = new Date(d);
|
|
295
|
+
newDate.setDate(newDate.getDate() + n);
|
|
296
|
+
return newDate;
|
|
297
|
+
}
|
package/src/resources.ts
CHANGED
|
@@ -4,18 +4,29 @@ import * as http from 'http';
|
|
|
4
4
|
import * as https from 'https';
|
|
5
5
|
import { Attributes, ErrorMessage } from './metadata';
|
|
6
6
|
|
|
7
|
+
export interface StringMap {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
}
|
|
7
10
|
// tslint:disable-next-line:class-name
|
|
8
11
|
export class resources {
|
|
12
|
+
static limits = [12, 24, 60, 100, 120, 180, 300, 600];
|
|
13
|
+
static component = 'page';
|
|
9
14
|
static page = 'page';
|
|
15
|
+
static limit = 'limit';
|
|
16
|
+
static defaultLimit = 12;
|
|
10
17
|
static sort = 'sort';
|
|
11
18
|
static partial = 'partial';
|
|
12
19
|
static createValidator?: <T>(attributes: Attributes, allowUndefined?: boolean, max?: number) => Validator<T>;
|
|
13
20
|
static check: (obj: any, attributes: Attributes, allowUndefined?: boolean, patch?: boolean) => ErrorMessage[];
|
|
14
21
|
static encoding?: BufferEncoding = 'utf-8';
|
|
15
22
|
}
|
|
23
|
+
export function getView(req: Request, view: string): string {
|
|
24
|
+
const partial = req.query[resources.partial];
|
|
25
|
+
return partial == 'true' ? resources.component + '/' + view : view;
|
|
26
|
+
}
|
|
16
27
|
|
|
17
28
|
export interface Validator<T> {
|
|
18
|
-
validate(obj: T, patch?: boolean): Promise<ErrorMessage[]>;
|
|
29
|
+
validate(obj: T, resource?: StringMap, patch?: boolean): Promise<ErrorMessage[]>;
|
|
19
30
|
}
|
|
20
31
|
|
|
21
32
|
// tslint:disable-next-line:max-classes-per-file
|
package/src/search.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
2
|
import { minimizeArray, query } from './http';
|
|
3
|
+
import { ViewService } from './LoadController';
|
|
3
4
|
import { Attribute, Attributes } from './metadata';
|
|
4
5
|
import { resources } from './resources';
|
|
5
6
|
|
|
6
7
|
const et = '';
|
|
7
8
|
|
|
8
9
|
export interface Filter {
|
|
10
|
+
page?: number;
|
|
11
|
+
limit?: number;
|
|
12
|
+
|
|
9
13
|
fields?: string[];
|
|
10
14
|
sort?: string;
|
|
11
15
|
|
|
@@ -170,6 +174,53 @@ export function buildSortSearch(search: string, fields: string[], sort: Sort): S
|
|
|
170
174
|
}
|
|
171
175
|
return sorts;
|
|
172
176
|
}
|
|
177
|
+
export function clone(obj: any): any {
|
|
178
|
+
if (!obj) {
|
|
179
|
+
return obj;
|
|
180
|
+
}
|
|
181
|
+
if (obj instanceof Date) {
|
|
182
|
+
return new Date(obj.getTime());
|
|
183
|
+
}
|
|
184
|
+
if (typeof obj !== 'object') {
|
|
185
|
+
return obj;
|
|
186
|
+
}
|
|
187
|
+
if (Array.isArray(obj)) {
|
|
188
|
+
const arr = [];
|
|
189
|
+
for (const sub of obj) {
|
|
190
|
+
const c = clone(sub);
|
|
191
|
+
arr.push(c);
|
|
192
|
+
}
|
|
193
|
+
return arr;
|
|
194
|
+
}
|
|
195
|
+
const x: any = {};
|
|
196
|
+
const keys = Object.keys(obj);
|
|
197
|
+
for (const k of keys) {
|
|
198
|
+
const v = obj[k];
|
|
199
|
+
if (v instanceof Date) {
|
|
200
|
+
x[k] = new Date(v.getTime());
|
|
201
|
+
} else {
|
|
202
|
+
switch (typeof v) {
|
|
203
|
+
case 'object':
|
|
204
|
+
x[k] = clone(v);
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
x[k] = v;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return x;
|
|
213
|
+
}
|
|
214
|
+
export function cloneFilter<F extends Filter>(obj: F, page: number, limit: number): F {
|
|
215
|
+
const f = clone(obj);
|
|
216
|
+
if (!obj.hasOwnProperty(resources.page)) {
|
|
217
|
+
(obj as any)[resources.page] = page;
|
|
218
|
+
}
|
|
219
|
+
if (!obj.hasOwnProperty(resources.limit)) {
|
|
220
|
+
(obj as any)[resources.limit] = limit;
|
|
221
|
+
}
|
|
222
|
+
return f;
|
|
223
|
+
}
|
|
173
224
|
|
|
174
225
|
export function jsonResult<T>(res: Response, result: SearchResult<T>, quick?: boolean, fields?: string[], config?: SearchConfig): void {
|
|
175
226
|
if (quick && fields && fields.length > 0) {
|
|
@@ -354,10 +405,10 @@ const setKey = (_object: any, _isArrayKey: boolean, _key: string, _nextValue: an
|
|
|
354
405
|
};
|
|
355
406
|
export interface Limit {
|
|
356
407
|
limit?: number;
|
|
357
|
-
|
|
408
|
+
page?: number;
|
|
358
409
|
nextPageToken?: string;
|
|
359
410
|
fields?: string[];
|
|
360
|
-
|
|
411
|
+
pageOrNextPageToken?: string | number;
|
|
361
412
|
}
|
|
362
413
|
export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
363
414
|
const o: any = obj;
|
|
@@ -382,16 +433,18 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
382
433
|
const ipageSize = Math.floor(parseFloat(pageSize));
|
|
383
434
|
if (ipageSize > 0) {
|
|
384
435
|
r.limit = ipageSize;
|
|
436
|
+
/*
|
|
385
437
|
const skip = o['skip'];
|
|
386
438
|
if (skip && !isNaN(skip)) {
|
|
387
439
|
const iskip = Math.floor(parseFloat(skip));
|
|
388
440
|
if (iskip >= 0) {
|
|
389
|
-
r.
|
|
390
|
-
r.
|
|
441
|
+
r.page = iskip;
|
|
442
|
+
r.pageOrNextPageToken = r.page;
|
|
391
443
|
deletePageInfo(o);
|
|
392
444
|
return r;
|
|
393
445
|
}
|
|
394
446
|
}
|
|
447
|
+
*/
|
|
395
448
|
let pageIndex = o['page'];
|
|
396
449
|
if (!pageIndex) {
|
|
397
450
|
pageIndex = o['pageIndex'];
|
|
@@ -404,6 +457,7 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
404
457
|
if (ipageIndex < 1) {
|
|
405
458
|
ipageIndex = 1;
|
|
406
459
|
}
|
|
460
|
+
/*
|
|
407
461
|
let firstPageSize = o['firstLimit'];
|
|
408
462
|
if (!firstPageSize) {
|
|
409
463
|
firstPageSize = o['firstPageSize'];
|
|
@@ -414,27 +468,28 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
414
468
|
if (firstPageSize && !isNaN(firstPageSize)) {
|
|
415
469
|
const ifirstPageSize = Math.floor(parseFloat(firstPageSize));
|
|
416
470
|
if (ifirstPageSize > 0) {
|
|
417
|
-
r.
|
|
418
|
-
r.
|
|
471
|
+
r.page = ipageIndex;
|
|
472
|
+
r.pageOrNextPageToken = r.page;
|
|
419
473
|
deletePageInfo(o);
|
|
420
474
|
return r;
|
|
421
475
|
}
|
|
422
476
|
}
|
|
423
|
-
|
|
424
|
-
r.
|
|
477
|
+
*/
|
|
478
|
+
r.page = ipageIndex;
|
|
479
|
+
r.pageOrNextPageToken = r.page;
|
|
425
480
|
deletePageInfo(o);
|
|
426
481
|
return r;
|
|
427
482
|
}
|
|
428
|
-
r.
|
|
483
|
+
r.page = 1;
|
|
429
484
|
if (r.nextPageToken && r.nextPageToken.length > 0) {
|
|
430
|
-
r.
|
|
485
|
+
r.pageOrNextPageToken = r.nextPageToken;
|
|
431
486
|
}
|
|
432
487
|
deletePageInfo(o);
|
|
433
488
|
return r;
|
|
434
489
|
}
|
|
435
490
|
}
|
|
436
491
|
if (r.nextPageToken && r.nextPageToken.length > 0) {
|
|
437
|
-
r.
|
|
492
|
+
r.pageOrNextPageToken = r.nextPageToken;
|
|
438
493
|
}
|
|
439
494
|
deletePageInfo(o);
|
|
440
495
|
return r;
|
|
@@ -474,8 +529,8 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
474
529
|
if (skip && !isNaN(skip)) {
|
|
475
530
|
const iskip = Math.floor(parseFloat(skip));
|
|
476
531
|
if (iskip >= 0) {
|
|
477
|
-
r.
|
|
478
|
-
r.
|
|
532
|
+
r.page = iskip;
|
|
533
|
+
r.pageOrNextPageToken = r.page;
|
|
479
534
|
deletePageInfo(o, arr);
|
|
480
535
|
return r;
|
|
481
536
|
}
|
|
@@ -498,27 +553,27 @@ export function getParameters<T>(obj: T, config?: SearchConfig): Limit {
|
|
|
498
553
|
if (firstPageSize && !isNaN(firstPageSize)) {
|
|
499
554
|
const ifirstPageSize = Math.floor(parseFloat(firstPageSize));
|
|
500
555
|
if (ifirstPageSize > 0) {
|
|
501
|
-
r.
|
|
502
|
-
r.
|
|
556
|
+
r.page = ipageSize * (ipageIndex - 2) + ifirstPageSize;
|
|
557
|
+
r.pageOrNextPageToken = r.page;
|
|
503
558
|
deletePageInfo(o, arr);
|
|
504
559
|
return r;
|
|
505
560
|
}
|
|
506
561
|
}
|
|
507
|
-
r.
|
|
508
|
-
r.
|
|
562
|
+
r.page = ipageSize * (ipageIndex - 1);
|
|
563
|
+
r.pageOrNextPageToken = r.page;
|
|
509
564
|
deletePageInfo(o, arr);
|
|
510
565
|
return r;
|
|
511
566
|
}
|
|
512
|
-
r.
|
|
567
|
+
r.page = 0;
|
|
513
568
|
if (r.nextPageToken && r.nextPageToken.length > 0) {
|
|
514
|
-
r.
|
|
569
|
+
r.pageOrNextPageToken = r.nextPageToken;
|
|
515
570
|
}
|
|
516
571
|
deletePageInfo(o, arr);
|
|
517
572
|
return r;
|
|
518
573
|
}
|
|
519
574
|
}
|
|
520
575
|
if (r.nextPageToken && r.nextPageToken.length > 0) {
|
|
521
|
-
r.
|
|
576
|
+
r.pageOrNextPageToken = r.nextPageToken;
|
|
522
577
|
}
|
|
523
578
|
deletePageInfo(o, arr);
|
|
524
579
|
return r;
|
|
@@ -741,3 +796,26 @@ export function format<T>(obj: T, dates?: string[], nums?: string[]): T {
|
|
|
741
796
|
}
|
|
742
797
|
return o;
|
|
743
798
|
}
|
|
799
|
+
export function getMetadataFunc<T, ID>(
|
|
800
|
+
viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>),
|
|
801
|
+
dates?: string[],
|
|
802
|
+
numbers?: string[],
|
|
803
|
+
keys?: Attributes | Attribute[] | string[],
|
|
804
|
+
): Metadata | undefined {
|
|
805
|
+
const m: Metadata = { dates, numbers };
|
|
806
|
+
if ((m.dates && m.dates.length > 0) || (m.numbers && m.numbers.length > 0)) {
|
|
807
|
+
return m;
|
|
808
|
+
}
|
|
809
|
+
if (keys) {
|
|
810
|
+
if (!Array.isArray(keys)) {
|
|
811
|
+
return buildMetadata(keys);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
if (typeof viewService !== 'function' && viewService.metadata) {
|
|
815
|
+
const metadata = viewService.metadata();
|
|
816
|
+
if (metadata) {
|
|
817
|
+
return buildMetadata(metadata);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
package/lib/search_func.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var search_1 = require("./search");
|
|
4
|
-
function getMetadataFunc(viewService, dates, numbers, keys) {
|
|
5
|
-
var m = { dates: dates, numbers: numbers };
|
|
6
|
-
if (m.dates && m.dates.length > 0 || m.numbers && m.numbers.length > 0) {
|
|
7
|
-
return m;
|
|
8
|
-
}
|
|
9
|
-
if (keys) {
|
|
10
|
-
if (!Array.isArray(keys)) {
|
|
11
|
-
return search_1.buildMetadata(keys);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
if (typeof viewService !== 'function' && viewService.metadata) {
|
|
15
|
-
var metadata = viewService.metadata();
|
|
16
|
-
if (metadata) {
|
|
17
|
-
return search_1.buildMetadata(metadata);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
exports.getMetadataFunc = getMetadataFunc;
|
package/src/search_func.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {ViewService} from './LoadController';
|
|
2
|
-
import {Attribute, Attributes} from './metadata';
|
|
3
|
-
import {buildMetadata, Metadata} from './search';
|
|
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 | undefined {
|
|
6
|
-
const m: Metadata = { dates, numbers };
|
|
7
|
-
if (m.dates && m.dates.length > 0 || m.numbers && m.numbers.length > 0) {
|
|
8
|
-
return m;
|
|
9
|
-
}
|
|
10
|
-
if (keys) {
|
|
11
|
-
if (!Array.isArray(keys)) {
|
|
12
|
-
return buildMetadata(keys);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
if (typeof viewService !== 'function' && viewService.metadata) {
|
|
16
|
-
const metadata = viewService.metadata();
|
|
17
|
-
if (metadata) {
|
|
18
|
-
return buildMetadata(metadata);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|