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/src/edit.ts CHANGED
@@ -1,13 +1,13 @@
1
- import {Response} from 'express';
2
- import {Attribute, ErrorMessage} from './metadata';
3
- import {handleError} from './response';
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?: number|string;
7
- not_found?: number|string;
8
- success?: number|string;
6
+ duplicate_key: number|string;
7
+ not_found: number|string;
8
+ success: number|string;
9
9
  version_error?: number|string;
10
- validation_error?: number|string;
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: StatusConfig): StatusConfig {
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
- export function checkId<T, ID>(obj: T, id: ID, keys: Attribute[]): boolean {
33
- let n = 'id';
34
- if (keys && keys.length === 1) {
35
- n = keys[0].name;
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 = obj[n];
39
+ const v = o[n]
39
40
  if (!v) {
40
- obj[n] = id;
41
- return true;
41
+ o[n] = i
42
+ return true
42
43
  }
43
44
  // tslint:disable-next-line:triple-equals
44
- if (v != id) {
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(id);
50
+ const ks = Object.keys(i)
50
51
  for (const k of ks) {
51
- const v = obj[k];
52
+ const v = o[k]
52
53
  if (!v) {
53
- obj[k] = id[k];
54
+ o[k] = i[k]
54
55
  } else {
55
56
  // tslint:disable-next-line:triple-equals
56
- if (v != id[k]) {
57
- return false;
57
+ if (v != i[k]) {
58
+ return false
58
59
  }
59
60
  }
60
- obj[k] = id[k];
61
+ o[k] = i[k]
61
62
  }
62
- return true;
63
+ return true
63
64
  }
64
- export function create<T>(res: Response, status: StatusConfig, obj: T, insert: (obj: T, ctx?: any) => Promise<number|ResultInfo<T>>, log: (msg: string, ctx?: any) => void): void {
65
- insert(obj).then(result => {
66
- if (typeof result === 'number') {
67
- if (result >= 1) {
68
- const r: ResultInfo<T> = {status: status.success, value: obj};
69
- res.status(201).json(r);
70
- } else if (result === 0) {
71
- const r: ResultInfo<T> = {status: status.duplicate_key};
72
- res.status(201).json(r);
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.status(500).end('Internal Server Error');
80
+ res
81
+ .status(201)
82
+ .json(returnNumber ? result : obj)
83
+ .end()
75
84
  }
76
- } else {
77
- res.status(200).json(result);
78
- }
79
- }).catch(err => handleError(err, res, log));
85
+ })
86
+ .catch((err) => handleError(err, res))
80
87
  }
81
- export function update<T>(res: Response, status: StatusConfig, obj: T, save: (obj: T, ctx?: any) => Promise<number|ResultInfo<T>>, log: (msg: string, ctx?: any) => void): void {
82
- save(obj).then(result => {
83
- if (typeof result === 'number') {
84
- if (result >= 1) {
85
- const r: ResultInfo<T> = {status: status.success, value: obj};
86
- res.status(201).json(r);
87
- } else if (result === 0) {
88
- const r: ResultInfo<T> = {status: status.not_found};
89
- res.status(404).json(r);
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
- const r: ResultInfo<T> = {status: status.not_found};
92
- res.status(409).json(r);
105
+ res
106
+ .status(200)
107
+ .json(returnNumber ? result : obj)
108
+ .end()
93
109
  }
94
- } else {
95
- res.status(200).json(result);
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 (c === 'string' || c === 'number' || c === 'date' || c === 'boolean') {
106
- return true;
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 = 'UP' | 'DOWN';
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 check(checkers: HealthChecker[]): Promise<Health> {
20
- const p: Health = {
21
- status: 'UP',
22
- details: {} as HealthMap,
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: 'UP'};
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 = 'DOWN';
41
- p.status = 'DOWN';
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
+ }