core-express 0.1.0 → 0.1.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 +1 -1
- package/lib/GenericController.js +224 -131
- package/lib/GenericSearchController.js +58 -37
- package/lib/HealthController.js +16 -58
- package/lib/LoadController.js +71 -46
- package/lib/LoadSearchController.js +113 -41
- package/lib/LogController.js +89 -0
- package/lib/LowCodeController.js +100 -0
- package/lib/SearchController.js +32 -25
- package/lib/access.js +34 -0
- package/lib/client.js +80 -0
- package/lib/edit.js +99 -84
- package/lib/health.js +157 -76
- package/lib/http.js +316 -0
- package/lib/index.js +488 -16
- package/lib/log.js +242 -0
- package/lib/resources.js +106 -6
- package/lib/search.js +766 -160
- package/lib/view.js +48 -34
- package/package.json +8 -4
- package/src/GenericController.ts +217 -106
- package/src/GenericSearchController.ts +38 -21
- package/src/HealthController.ts +9 -9
- package/src/LoadController.ts +70 -40
- package/src/LoadSearchController.ts +114 -21
- package/src/LogController.ts +137 -0
- package/src/LowCodeController.ts +88 -0
- package/src/SearchController.ts +28 -17
- package/src/access.ts +42 -0
- package/src/client.ts +69 -0
- package/src/edit.ts +93 -61
- package/src/health.ts +27 -28
- package/src/http.ts +295 -0
- package/src/index.ts +464 -13
- package/src/log.ts +245 -0
- package/src/metadata.ts +34 -23
- package/src/resources.ts +143 -4
- package/src/search.ts +782 -198
- package/src/view.ts +44 -30
- package/tsconfig.json +1 -0
- package/lib/response.js +0 -12
- package/src/response.ts +0 -10
package/src/edit.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {Response} from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { Response } from "express"
|
|
2
|
+
import { handleError } from "./http"
|
|
3
|
+
import { Attribute, ErrorMessage } from "./metadata"
|
|
4
|
+
/*
|
|
5
5
|
export interface StatusConfig {
|
|
6
|
-
duplicate_key
|
|
7
|
-
not_found
|
|
8
|
-
success
|
|
6
|
+
duplicate_key: number|string;
|
|
7
|
+
not_found: number|string;
|
|
8
|
+
success: number|string;
|
|
9
9
|
version_error?: number|string;
|
|
10
|
-
validation_error
|
|
10
|
+
validation_error: number|string;
|
|
11
11
|
error?: number|string;
|
|
12
12
|
}
|
|
13
13
|
export interface ResultInfo<T> {
|
|
@@ -16,7 +16,7 @@ export interface ResultInfo<T> {
|
|
|
16
16
|
value?: T;
|
|
17
17
|
message?: string;
|
|
18
18
|
}
|
|
19
|
-
export function initializeStatus(s
|
|
19
|
+
export function initializeStatus(s?: StatusConfig): StatusConfig {
|
|
20
20
|
if (s) {
|
|
21
21
|
return s;
|
|
22
22
|
}
|
|
@@ -25,86 +25,118 @@ export function initializeStatus(s: StatusConfig): StatusConfig {
|
|
|
25
25
|
not_found: 0,
|
|
26
26
|
success: 1,
|
|
27
27
|
version_error: 2,
|
|
28
|
+
validation_error: 4,
|
|
28
29
|
error: 4
|
|
29
30
|
};
|
|
30
31
|
return s1;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
*/
|
|
34
|
+
export function checkId<T, ID>(obj: T, id: ID, keys?: Attribute[]): boolean {
|
|
35
|
+
const n: string = keys && keys.length === 1 && keys[0].name ? keys[0].name : "id"
|
|
36
|
+
const o: any = obj
|
|
37
|
+
const i: any = id
|
|
37
38
|
if (!keys || keys.length === 1) {
|
|
38
|
-
const v =
|
|
39
|
+
const v = o[n]
|
|
39
40
|
if (!v) {
|
|
40
|
-
|
|
41
|
-
return true
|
|
41
|
+
o[n] = i
|
|
42
|
+
return true
|
|
42
43
|
}
|
|
43
44
|
// tslint:disable-next-line:triple-equals
|
|
44
|
-
if (v !=
|
|
45
|
-
return false
|
|
45
|
+
if (v != i) {
|
|
46
|
+
return false
|
|
46
47
|
}
|
|
47
|
-
return true
|
|
48
|
+
return true
|
|
48
49
|
}
|
|
49
|
-
const ks = Object.keys(
|
|
50
|
+
const ks = Object.keys(i)
|
|
50
51
|
for (const k of ks) {
|
|
51
|
-
const v =
|
|
52
|
+
const v = o[k]
|
|
52
53
|
if (!v) {
|
|
53
|
-
|
|
54
|
+
o[k] = i[k]
|
|
54
55
|
} else {
|
|
55
56
|
// tslint:disable-next-line:triple-equals
|
|
56
|
-
if (v !=
|
|
57
|
-
return false
|
|
57
|
+
if (v != i[k]) {
|
|
58
|
+
return false
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
o[k] = i[k]
|
|
61
62
|
}
|
|
62
|
-
return true
|
|
63
|
+
return true
|
|
63
64
|
}
|
|
64
|
-
export function create<T>(res: Response,
|
|
65
|
-
insert(obj)
|
|
66
|
-
|
|
67
|
-
if (result
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
export function create<T>(res: Response, obj: T, insert: (obj: T, ctx?: any) => Promise<number | T | ErrorMessage[]>, returnNumber?: boolean): void {
|
|
66
|
+
insert(obj)
|
|
67
|
+
.then((result) => {
|
|
68
|
+
if (typeof result === "number") {
|
|
69
|
+
if (result >= 1) {
|
|
70
|
+
res
|
|
71
|
+
.status(201)
|
|
72
|
+
.json(returnNumber ? result : obj)
|
|
73
|
+
.end()
|
|
74
|
+
} else {
|
|
75
|
+
res.status(409).json(result).end()
|
|
76
|
+
}
|
|
77
|
+
} else if (Array.isArray(result)) {
|
|
78
|
+
res.status(422).json(result).end()
|
|
73
79
|
} else {
|
|
74
|
-
res
|
|
80
|
+
res
|
|
81
|
+
.status(201)
|
|
82
|
+
.json(returnNumber ? result : obj)
|
|
83
|
+
.end()
|
|
75
84
|
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}).catch(err => handleError(err, res, log));
|
|
85
|
+
})
|
|
86
|
+
.catch((err) => handleError(err, res))
|
|
80
87
|
}
|
|
81
|
-
export function update<T>(res: Response,
|
|
82
|
-
save(obj)
|
|
83
|
-
|
|
84
|
-
if (result
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
export function update<T>(res: Response, obj: T, save: (obj: T, ctx?: any) => Promise<number | T | ErrorMessage[]>, returnNumber?: boolean): void {
|
|
89
|
+
save(obj)
|
|
90
|
+
.then((result) => {
|
|
91
|
+
if (typeof result === "number") {
|
|
92
|
+
if (result >= 1) {
|
|
93
|
+
res
|
|
94
|
+
.status(200)
|
|
95
|
+
.json(returnNumber ? result : obj)
|
|
96
|
+
.end()
|
|
97
|
+
} else if (result === 0) {
|
|
98
|
+
res.status(404).json(result).end()
|
|
99
|
+
} else {
|
|
100
|
+
res.status(409).json(result).end()
|
|
101
|
+
}
|
|
102
|
+
} else if (Array.isArray(result)) {
|
|
103
|
+
res.status(422).json(result).end()
|
|
90
104
|
} else {
|
|
91
|
-
|
|
92
|
-
|
|
105
|
+
res
|
|
106
|
+
.status(200)
|
|
107
|
+
.json(returnNumber ? result : obj)
|
|
108
|
+
.end()
|
|
93
109
|
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
}).catch(err => handleError(err, res, log));
|
|
110
|
+
})
|
|
111
|
+
.catch((err) => handleError(err, res))
|
|
98
112
|
}
|
|
99
113
|
export function isTypeError(errs: ErrorMessage[]): boolean {
|
|
100
114
|
if (!errs) {
|
|
101
|
-
return false
|
|
115
|
+
return false
|
|
102
116
|
}
|
|
103
117
|
for (const err of errs) {
|
|
104
|
-
const c = err.code
|
|
105
|
-
if (
|
|
106
|
-
|
|
118
|
+
const c = err.code
|
|
119
|
+
if (
|
|
120
|
+
c === "type" ||
|
|
121
|
+
c === "string" ||
|
|
122
|
+
c === "number" ||
|
|
123
|
+
c === "date" ||
|
|
124
|
+
c === "boolean" ||
|
|
125
|
+
c === "strings" ||
|
|
126
|
+
c === "numbers" ||
|
|
127
|
+
c === "integers" ||
|
|
128
|
+
c === "dates" ||
|
|
129
|
+
c === "datetimes" ||
|
|
130
|
+
c === "booleans"
|
|
131
|
+
) {
|
|
132
|
+
return true
|
|
107
133
|
}
|
|
108
134
|
}
|
|
109
|
-
return false
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
export function getStatusCode(errs: ErrorMessage[]): number {
|
|
138
|
+
return isTypeError(errs) ? 400 : 422
|
|
139
|
+
}
|
|
140
|
+
export function respondError(res: Response, errors: ErrorMessage[]) {
|
|
141
|
+
res.status(getStatusCode(errors)).json(errors).end()
|
|
110
142
|
}
|
package/src/health.ts
CHANGED
|
@@ -1,51 +1,50 @@
|
|
|
1
|
-
export type HealthStatus =
|
|
1
|
+
export type HealthStatus = "UP" | "DOWN"
|
|
2
2
|
export interface HealthMap {
|
|
3
|
-
[key: string]: Health
|
|
3
|
+
[key: string]: Health
|
|
4
4
|
}
|
|
5
5
|
export interface Health {
|
|
6
|
-
status: HealthStatus
|
|
7
|
-
data?: AnyMap
|
|
8
|
-
details?: HealthMap
|
|
6
|
+
status: HealthStatus
|
|
7
|
+
data?: AnyMap
|
|
8
|
+
details?: HealthMap
|
|
9
9
|
}
|
|
10
10
|
export interface AnyMap {
|
|
11
|
-
[key: string]: any
|
|
11
|
+
[key: string]: any
|
|
12
12
|
}
|
|
13
13
|
export interface HealthChecker {
|
|
14
|
-
name(): string
|
|
15
|
-
build(data: AnyMap, error: any): AnyMap
|
|
16
|
-
check(): Promise<AnyMap
|
|
14
|
+
name(): string
|
|
15
|
+
build(data: AnyMap, error: any): AnyMap
|
|
16
|
+
check(): Promise<AnyMap>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export async function
|
|
20
|
-
const p: Health = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const total = checkers.length - 1;
|
|
25
|
-
let count = 0;
|
|
19
|
+
export async function health(checkers: HealthChecker[]): Promise<Health> {
|
|
20
|
+
const p: Health = { status: "UP" }
|
|
21
|
+
const total = checkers.length - 1
|
|
22
|
+
let count = 0
|
|
23
|
+
p.details = {} as HealthMap
|
|
26
24
|
for (const checker of checkers) {
|
|
27
|
-
const sub: Health = {status:
|
|
25
|
+
const sub: Health = { status: "UP" }
|
|
28
26
|
try {
|
|
29
|
-
const r = await checker.check()
|
|
27
|
+
const r = await checker.check()
|
|
30
28
|
if (r && Object.keys(r).length > 0) {
|
|
31
|
-
sub.data = r
|
|
29
|
+
sub.data = r
|
|
32
30
|
}
|
|
33
|
-
p.details[checker.name()] = sub
|
|
31
|
+
p.details[checker.name()] = sub
|
|
34
32
|
if (count >= total) {
|
|
35
|
-
return p
|
|
33
|
+
return p
|
|
36
34
|
} else {
|
|
37
|
-
count
|
|
35
|
+
count++
|
|
38
36
|
}
|
|
39
37
|
} catch (err) {
|
|
40
|
-
sub.status =
|
|
41
|
-
p.status =
|
|
42
|
-
sub.data = checker.build({} as AnyMap, err)
|
|
43
|
-
p.details[checker.name()] = sub
|
|
38
|
+
sub.status = "DOWN"
|
|
39
|
+
p.status = "DOWN"
|
|
40
|
+
sub.data = checker.build({} as AnyMap, err)
|
|
41
|
+
p.details[checker.name()] = sub
|
|
44
42
|
if (count >= total) {
|
|
45
|
-
return p
|
|
43
|
+
return p
|
|
46
44
|
} else {
|
|
47
|
-
count
|
|
45
|
+
count++
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
}
|
|
49
|
+
return p
|
|
51
50
|
}
|
package/src/http.ts
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { Request, Response } from "express"
|
|
2
|
+
import { Attribute } from "./metadata"
|
|
3
|
+
import { resources } from "./resources"
|
|
4
|
+
|
|
5
|
+
export type Log = (msg: string) => void
|
|
6
|
+
export type LogFunc = Log
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(Error.prototype, "toJSON", {
|
|
9
|
+
value() {
|
|
10
|
+
const alt: any = {}
|
|
11
|
+
Object.getOwnPropertyNames(this).forEach(function (key) {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
alt[key] = this[key]
|
|
14
|
+
}, this)
|
|
15
|
+
|
|
16
|
+
return alt
|
|
17
|
+
},
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
})
|
|
21
|
+
export function handleError(err: any, res: Response) {
|
|
22
|
+
if (resources.log) {
|
|
23
|
+
resources.log(toString(err))
|
|
24
|
+
res.status(500).end("Internal Server Error")
|
|
25
|
+
} else {
|
|
26
|
+
if (resources.returnServerError) {
|
|
27
|
+
res.status(500).end(toString(err))
|
|
28
|
+
} else {
|
|
29
|
+
console.error(toString(err))
|
|
30
|
+
res.status(500).end("Internal Server Error")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const error = handleError
|
|
35
|
+
export function toString(v: any): string {
|
|
36
|
+
if (typeof v === "string") {
|
|
37
|
+
return v
|
|
38
|
+
} else {
|
|
39
|
+
return JSON.stringify(v)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function attr(name: string): Attribute {
|
|
43
|
+
return { name, type: "string" }
|
|
44
|
+
}
|
|
45
|
+
export function attrs(keys: string[]): Attribute[] {
|
|
46
|
+
const atts: Attribute[] = []
|
|
47
|
+
for (const str of keys) {
|
|
48
|
+
const at: Attribute = { name: str as string, type: "string" }
|
|
49
|
+
atts.push(at)
|
|
50
|
+
}
|
|
51
|
+
return atts
|
|
52
|
+
}
|
|
53
|
+
export function respondModel<T>(obj: T, res: Response): void {
|
|
54
|
+
if (obj) {
|
|
55
|
+
res.status(200).json(obj).end()
|
|
56
|
+
} else {
|
|
57
|
+
res.status(404).json(null).end()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function queryRequiredParams(req: Request, res: Response, name: string, split?: string): string[] | undefined {
|
|
61
|
+
const v = req.query[name]
|
|
62
|
+
if (!v) {
|
|
63
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
64
|
+
return undefined
|
|
65
|
+
}
|
|
66
|
+
const v2 = v.toString()
|
|
67
|
+
if (v2.length === 0) {
|
|
68
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
if (!split) {
|
|
72
|
+
split = ","
|
|
73
|
+
}
|
|
74
|
+
return v2.split(split)
|
|
75
|
+
}
|
|
76
|
+
export function queryParams(req: Request, name: string, d?: string[], split?: string): string[] | undefined {
|
|
77
|
+
const q = req.query[name]
|
|
78
|
+
if (!q) {
|
|
79
|
+
return d
|
|
80
|
+
}
|
|
81
|
+
const v = q.toString()
|
|
82
|
+
if (!v || v.length === 0) {
|
|
83
|
+
return d
|
|
84
|
+
}
|
|
85
|
+
if (!split) {
|
|
86
|
+
split = ","
|
|
87
|
+
}
|
|
88
|
+
return v.split(split)
|
|
89
|
+
}
|
|
90
|
+
export function queryParam(req: Request, res: Response, name: string): string | undefined {
|
|
91
|
+
const v = req.query[name]
|
|
92
|
+
if (!v) {
|
|
93
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
94
|
+
return undefined
|
|
95
|
+
} else {
|
|
96
|
+
const v1 = v.toString()
|
|
97
|
+
if (v1.length === 0) {
|
|
98
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
99
|
+
return undefined
|
|
100
|
+
} else {
|
|
101
|
+
return v1
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function query(req: Request, name: string, d?: string): string | undefined {
|
|
106
|
+
const p = req.query[name]
|
|
107
|
+
if (!p || p.toString().length === 0) {
|
|
108
|
+
return d
|
|
109
|
+
}
|
|
110
|
+
return p.toString()
|
|
111
|
+
}
|
|
112
|
+
export function queryRequiredNumber(req: Request, res: Response, name: string): number | undefined {
|
|
113
|
+
const field = req.query[name]
|
|
114
|
+
if (!field) {
|
|
115
|
+
return undefined
|
|
116
|
+
}
|
|
117
|
+
const v = field.toString()
|
|
118
|
+
if (!v || v.length === 0) {
|
|
119
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
120
|
+
return undefined
|
|
121
|
+
}
|
|
122
|
+
if (isNaN(v as any)) {
|
|
123
|
+
res.status(400).end(`'${name}' is not a valid number`)
|
|
124
|
+
return undefined
|
|
125
|
+
}
|
|
126
|
+
const n = parseFloat(v as string)
|
|
127
|
+
return n
|
|
128
|
+
}
|
|
129
|
+
export function queryNumber(req: Request, name: string, d: number): number {
|
|
130
|
+
const field = req.query[name]
|
|
131
|
+
const v = field ? field.toString() : undefined
|
|
132
|
+
if (!v || v.length === 0) {
|
|
133
|
+
return d
|
|
134
|
+
}
|
|
135
|
+
if (isNaN(v as any)) {
|
|
136
|
+
return d
|
|
137
|
+
}
|
|
138
|
+
const n = parseFloat(v as string)
|
|
139
|
+
return n
|
|
140
|
+
}
|
|
141
|
+
export function queryRequiredDate(req: Request, res: Response, name: string): Date | undefined {
|
|
142
|
+
const field = req.query[name]
|
|
143
|
+
if (!field) {
|
|
144
|
+
return undefined
|
|
145
|
+
}
|
|
146
|
+
const v = field.toString()
|
|
147
|
+
if (!v || v.length === 0) {
|
|
148
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
149
|
+
return undefined
|
|
150
|
+
}
|
|
151
|
+
const date = new Date(v as string)
|
|
152
|
+
if (date.toString() === "Invalid Date") {
|
|
153
|
+
res.status(400).end(`'${name}' is not a valid date`)
|
|
154
|
+
return undefined
|
|
155
|
+
}
|
|
156
|
+
return date
|
|
157
|
+
}
|
|
158
|
+
export function queryDate(req: Request, name: string, d?: Date): Date | undefined {
|
|
159
|
+
const field = req.query[name]
|
|
160
|
+
if (field) {
|
|
161
|
+
const v = field.toString()
|
|
162
|
+
if (!v || v.length === 0) {
|
|
163
|
+
return d
|
|
164
|
+
}
|
|
165
|
+
const date = new Date(v as string)
|
|
166
|
+
if (date.toString() === "Invalid Date") {
|
|
167
|
+
return d
|
|
168
|
+
}
|
|
169
|
+
return date
|
|
170
|
+
}
|
|
171
|
+
return undefined
|
|
172
|
+
}
|
|
173
|
+
export function param(req: Request, res: Response, name: string): string | undefined {
|
|
174
|
+
const v = req.params[name]
|
|
175
|
+
if (!v || v.length === 0) {
|
|
176
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
177
|
+
return undefined
|
|
178
|
+
}
|
|
179
|
+
return v as string
|
|
180
|
+
}
|
|
181
|
+
export const getParam = param
|
|
182
|
+
export function params(req: Request, name: string, d?: string[], split?: string): string[] | undefined {
|
|
183
|
+
const v = req.params[name] as string
|
|
184
|
+
if (!v || v.length === 0) {
|
|
185
|
+
return d
|
|
186
|
+
}
|
|
187
|
+
if (!split) {
|
|
188
|
+
split = ","
|
|
189
|
+
}
|
|
190
|
+
return v.split(split)
|
|
191
|
+
}
|
|
192
|
+
export const getParams = params
|
|
193
|
+
export function getRequiredParameters(req: Request, res: Response, name: string, split?: string): string[] | undefined {
|
|
194
|
+
const v = req.params[name] as string
|
|
195
|
+
if (!v || v.length === 0) {
|
|
196
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
197
|
+
return undefined
|
|
198
|
+
}
|
|
199
|
+
if (!split) {
|
|
200
|
+
split = ","
|
|
201
|
+
}
|
|
202
|
+
return v.split(split)
|
|
203
|
+
}
|
|
204
|
+
export function getRequiredNumber(req: Request, res: Response, name: string): number | undefined {
|
|
205
|
+
const v = req.params[name]
|
|
206
|
+
if (!v || v.length === 0) {
|
|
207
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
208
|
+
return undefined
|
|
209
|
+
}
|
|
210
|
+
if (isNaN(v as any)) {
|
|
211
|
+
res.status(400).end(`'${name}' must be a number`)
|
|
212
|
+
return undefined
|
|
213
|
+
}
|
|
214
|
+
const n = parseFloat(v as string)
|
|
215
|
+
return n
|
|
216
|
+
}
|
|
217
|
+
export function getNumber(req: Request, name: string, d?: number): number | undefined {
|
|
218
|
+
const v = req.params[name]
|
|
219
|
+
if (!v || v.length === 0) {
|
|
220
|
+
return d
|
|
221
|
+
}
|
|
222
|
+
if (isNaN(v as any)) {
|
|
223
|
+
return d
|
|
224
|
+
}
|
|
225
|
+
const n = parseFloat(v as string)
|
|
226
|
+
return n
|
|
227
|
+
}
|
|
228
|
+
export function getInteger(req: Request, name: string, d?: number): number | undefined {
|
|
229
|
+
const v = req.params[name]
|
|
230
|
+
if (!v || v.length === 0) {
|
|
231
|
+
return d
|
|
232
|
+
}
|
|
233
|
+
if (isNaN(v as any)) {
|
|
234
|
+
return d
|
|
235
|
+
}
|
|
236
|
+
const n = parseFloat(v as string)
|
|
237
|
+
const s = n.toFixed(0)
|
|
238
|
+
return parseFloat(s)
|
|
239
|
+
}
|
|
240
|
+
export function getRequiredDate(req: Request, res: Response, name: string): Date | undefined {
|
|
241
|
+
const v = req.params[name]
|
|
242
|
+
if (!v || v.length === 0) {
|
|
243
|
+
res.status(400).end(`'${name}' cannot be empty`)
|
|
244
|
+
return undefined
|
|
245
|
+
}
|
|
246
|
+
const date = new Date(v as string)
|
|
247
|
+
if (date.toString() === "Invalid Date") {
|
|
248
|
+
res.status(400).end(`'${name}' must be a date`)
|
|
249
|
+
return undefined
|
|
250
|
+
}
|
|
251
|
+
return date
|
|
252
|
+
}
|
|
253
|
+
export function getDate(req: Request, name: string, d?: Date): Date | undefined {
|
|
254
|
+
const v = req.params[name]
|
|
255
|
+
if (!v || v.length === 0) {
|
|
256
|
+
return d
|
|
257
|
+
}
|
|
258
|
+
const date = new Date(v as string)
|
|
259
|
+
if (date.toString() === "Invalid Date") {
|
|
260
|
+
return d
|
|
261
|
+
}
|
|
262
|
+
return date
|
|
263
|
+
}
|
|
264
|
+
const o = "object"
|
|
265
|
+
export function minimize(obj: any): any {
|
|
266
|
+
if (!obj || typeof obj !== o) {
|
|
267
|
+
return obj
|
|
268
|
+
}
|
|
269
|
+
const keys = Object.keys(obj)
|
|
270
|
+
for (const key of keys) {
|
|
271
|
+
const v = obj[key]
|
|
272
|
+
if (v == null) {
|
|
273
|
+
delete obj[key]
|
|
274
|
+
} else if (Array.isArray(v) && v.length > 0) {
|
|
275
|
+
const v1 = v[0]
|
|
276
|
+
if (typeof v1 === o && !(v1 instanceof Date)) {
|
|
277
|
+
for (const item of v) {
|
|
278
|
+
minimize(item)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return obj
|
|
284
|
+
}
|
|
285
|
+
export function minimizeArray<T>(arrs: T[]): T[] {
|
|
286
|
+
if (!arrs) {
|
|
287
|
+
return arrs
|
|
288
|
+
}
|
|
289
|
+
if (arrs.length > 0) {
|
|
290
|
+
for (const obj of arrs) {
|
|
291
|
+
minimize(obj)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return arrs
|
|
295
|
+
}
|