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.
@@ -1,65 +1,95 @@
1
- import {Request, Response} from 'express';
2
- import {Attribute, Attributes, Model} from './metadata';
3
- import {handleError} from './response';
4
- import {buildId, buildKeys} from './view';
1
+ import { Request, Response } from "express"
2
+ import { attrs, handleError, minimize, queryNumber, respondModel } from "./http"
3
+ import { Attribute, Attributes } from "./metadata"
4
+ import { buildAndCheckId, buildKeys } from "./view"
5
5
 
6
6
  export interface ViewService<T, ID> {
7
- metadata?(): Model;
8
- load(id: ID, ctx?: any): Promise<T>;
7
+ metadata?(): Attributes | undefined
8
+ load(id: ID, ctx?: any): Promise<T | null>
9
9
  }
10
- function getViewFunc<T, ID>(viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>)): (id: ID, ctx?: any) => Promise<T> {
11
- if (typeof viewService === 'function') {
12
- return viewService;
10
+ export type Load<T, ID> = (id: ID, ctx?: any) => Promise<T | null>
11
+ function getViewFunc<T, ID>(viewService: ViewService<T, ID> | Load<T, ID>): (id: ID, ctx?: any) => Promise<T | null> {
12
+ if (typeof viewService === "function") {
13
+ return viewService
13
14
  }
14
- return viewService.load;
15
+ return viewService.load
15
16
  }
16
- function getKeysFunc<T, ID>(viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>), keys?: Attributes|Attribute[]|string[]): Attribute[] {
17
+ function getKeysFunc<T, ID>(viewService: ViewService<T, ID> | Load<T, ID>, keys?: Attributes | Attribute[] | string[]): Attribute[] | undefined {
17
18
  if (keys) {
18
19
  if (Array.isArray(keys)) {
19
20
  if (keys.length > 0) {
20
- if (typeof keys[0] === 'string') {
21
- const attrs: Attribute[] = [];
22
- for (const str of keys) {
23
- const attr: Attribute = {name: str as string, type: 'string'};
24
- attrs.push(attr);
25
- }
26
- return attrs;
21
+ if (typeof keys[0] === "string") {
22
+ return attrs(keys as string[])
27
23
  } else {
28
- return keys as Attribute[];
24
+ return keys as Attribute[]
29
25
  }
30
26
  }
31
- return undefined;
27
+ return undefined
32
28
  } else {
33
- return buildKeys(keys as Attributes);
29
+ return buildKeys(keys as Attributes)
34
30
  }
35
31
  }
36
- if (typeof viewService !== 'function' && viewService.metadata) {
37
- const metadata = viewService.metadata();
32
+ if (typeof viewService !== "function" && viewService.metadata) {
33
+ const metadata = viewService.metadata()
38
34
  if (metadata) {
39
- return buildKeys(metadata.attributes);
35
+ return buildKeys(metadata)
40
36
  }
41
37
  }
42
- return undefined;
38
+ return undefined
43
39
  }
44
40
  export class LoadController<T, ID> {
45
- protected keys?: Attribute[];
46
- protected view: (id: ID, ctx?: any) => Promise<T>;
47
- constructor(protected log: (msg: any, ctx?: any) => void, viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>), keys?: Attributes|Attribute[]|string[]) {
48
- this.load = this.load.bind(this);
49
- this.view = getViewFunc(viewService);
50
- this.keys = getKeysFunc(viewService, keys);
41
+ protected keys?: Attribute[]
42
+ protected view: Load<T, ID>
43
+ constructor(viewService: ViewService<T, ID> | Load<T, ID>, keys?: Attributes | Attribute[] | string[]) {
44
+ this.load = this.load.bind(this)
45
+ this.view = getViewFunc(viewService)
46
+ this.keys = getKeysFunc(viewService, keys)
51
47
  }
52
- load(req: Request, res: Response) {
53
- const id = buildId<ID>(req, this.keys);
54
- if (!id) {
55
- return res.status(400).end('invalid parameters');
48
+ load(req: Request, res: Response): void {
49
+ const id = buildAndCheckId<ID>(req, res, this.keys)
50
+ if (id) {
51
+ this.view(id)
52
+ .then((obj) => respondModel(minimize(obj), res))
53
+ .catch((err) => handleError(err, res))
56
54
  }
57
- this.view(id).then(obj => {
58
- if (obj) {
59
- res.status(200).json(obj);
55
+ }
56
+ }
57
+ // tslint:disable-next-line:max-classes-per-file
58
+ export class ItemController<T> {
59
+ constructor(
60
+ private loadData: (keyword: string, max?: number) => Promise<T>,
61
+ name?: string,
62
+ protected param?: boolean,
63
+ max?: number,
64
+ maxName?: string,
65
+ ) {
66
+ this.name = name && name.length > 0 ? name : "keyword"
67
+ this.max = max && max > 0 ? max : 20
68
+ this.maxName = maxName && maxName.length > 0 ? maxName : "max"
69
+ this.load = this.load.bind(this)
70
+ this.query = this.query.bind(this)
71
+ }
72
+ name: string
73
+ max: number
74
+ maxName: string
75
+ query(req: Request, res: Response) {
76
+ return this.load(req, res)
77
+ }
78
+ load(req: Request, res: Response) {
79
+ const v = this.param ? req.params[this.name] : req.query[this.name]
80
+ if (!v) {
81
+ res.status(400).end(`'${this.name}' cannot be empty`)
82
+ } else {
83
+ const s = v.toString()
84
+ if (s.length === 0) {
85
+ res.status(400).end(`'${this.name}' cannot be empty`)
60
86
  } else {
61
- res.status(404).json(null);
87
+ const max = queryNumber(req, this.maxName, this.max)
88
+ this.loadData(s, max)
89
+ .then((result) => respondModel(minimize(result), res))
90
+ .catch((err) => handleError(err, res))
62
91
  }
63
- }).catch(err => handleError(err, res, this.log));
92
+ }
64
93
  }
65
94
  }
95
+ export { ItemController as ItemHandler }
@@ -1,31 +1,124 @@
1
- import {Request, Response} from 'express';
2
- import {LoadController, ViewService} from './LoadController';
3
- import {Attribute, Attributes} from './metadata';
4
- import {handleError} from './response';
5
- import {fromRequest, getLimit, initializeConfig, jsonResult, SearchConfig, SearchModel, SearchResult} from './search';
1
+ import { Request, Response } from "express"
2
+ import { handleError } from "./http"
3
+ import { LoadController, ViewService } from "./LoadController"
4
+ import { Attribute, Attributes } from "./metadata"
5
+ import { resources } from "./resources"
6
+ import { buildArray, Filter, format, fromRequest, getMetadataFunc, getParameters, initializeConfig, jsonResult, SearchConfig, SearchResult } from "./search"
6
7
 
7
- export class LoadSearchController<T, ID, S extends SearchModel> extends LoadController<T, ID> {
8
- config?: SearchConfig;
9
- csv?: boolean;
10
- constructor(log: (msg: any, ctx?: any) => void, public find: (s: S, limit?: number, skip?: number, refId?: string) => Promise<SearchResult<T>>, viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>), keys?: Attributes|Attribute[]|string[], config?: SearchConfig|boolean, public format?: (s: S) => S) {
11
- super(log, viewService, keys);
12
- this.search = this.search.bind(this);
8
+ export interface Search {
9
+ search(req: Request, res: Response): void
10
+ load(req: Request, res: Response): void
11
+ }
12
+ export interface Query<T, ID, S> extends ViewService<T, ID> {
13
+ search: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise<SearchResult<T>>
14
+ metadata?(): Attributes | undefined
15
+ load(id: ID, ctx?: any): Promise<T | null>
16
+ }
17
+ export interface SearchManager {
18
+ search(req: Request, res: Response): void
19
+ load(req: Request, res: Response): void
20
+ }
21
+ export function useSearchController<T, ID, S extends Filter>(
22
+ find: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise<SearchResult<T>>,
23
+ viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>),
24
+ array?: string[],
25
+ dates?: string[],
26
+ numbers?: string[],
27
+ keys?: Attributes | Attribute[] | string[],
28
+ config?: SearchConfig | boolean,
29
+ ): Search {
30
+ const c = new LoadSearchController(find, viewService, keys, config, dates, numbers)
31
+ c.array = array
32
+ return c
33
+ }
34
+ export const useSearchHandler = useSearchController
35
+ export const createSearchController = useSearchController
36
+ export const createSearchHandler = useSearchController
37
+ export class LoadSearchController<T, ID, S extends Filter> extends LoadController<T, ID> {
38
+ config?: SearchConfig
39
+ csv?: boolean
40
+ dates?: string[]
41
+ numbers?: string[]
42
+ excluding?: string
43
+ array?: string[]
44
+ constructor(
45
+ public find: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise<SearchResult<T>>,
46
+ viewService: ViewService<T, ID> | ((id: ID, ctx?: any) => Promise<T>),
47
+ keys?: Attributes | Attribute[] | string[],
48
+ config?: SearchConfig | boolean,
49
+ dates?: string[],
50
+ numbers?: string[],
51
+ ) {
52
+ super(viewService, keys)
53
+ this.search = this.search.bind(this)
13
54
  if (config) {
14
- if (typeof config === 'boolean') {
15
- this.csv = config;
55
+ if (typeof config === "boolean") {
56
+ this.csv = config
16
57
  } else {
17
- this.config = initializeConfig(config);
58
+ this.config = initializeConfig(config)
18
59
  if (this.config) {
19
- this.csv = this.config.csv;
60
+ this.csv = this.config.csv
61
+ this.excluding = this.config.excluding
20
62
  }
21
63
  }
22
64
  }
65
+ const m = getMetadataFunc(viewService, dates, numbers, keys)
66
+ if (m) {
67
+ this.dates = m.dates
68
+ this.numbers = m.numbers
69
+ }
70
+ }
71
+ search(req: Request, res: Response): void {
72
+ const s = fromRequest<S>(req, buildArray(this.array, resources.fields, this.excluding))
73
+ const l = getParameters(s)
74
+ const s2 = format(s, this.dates, this.numbers)
75
+ this.find(s2, l.limit, l.pageOrNextPageToken, l.fields)
76
+ .then((result) => jsonResult(res, result, this.csv, l.fields, this.config))
77
+ .catch((err) => handleError(err, res))
78
+ }
79
+ }
80
+ export class QueryController<T, ID, S extends Filter> extends LoadController<T, ID> {
81
+ config?: SearchConfig
82
+ csv?: boolean
83
+ dates?: string[]
84
+ numbers?: string[]
85
+ excluding?: string
86
+ array?: string[]
87
+ constructor(
88
+ protected query: Query<T, ID, S>,
89
+ config?: SearchConfig | boolean,
90
+ dates?: string[],
91
+ numbers?: string[],
92
+ array?: string[],
93
+ ) {
94
+ super(query)
95
+ this.search = this.search.bind(this)
96
+ this.array = array
97
+ if (config) {
98
+ if (typeof config === "boolean") {
99
+ this.csv = config
100
+ } else {
101
+ this.config = initializeConfig(config)
102
+ if (this.config) {
103
+ this.csv = this.config.csv
104
+ this.excluding = this.config.excluding
105
+ }
106
+ }
107
+ }
108
+ const m = getMetadataFunc(query, dates, numbers)
109
+ if (m) {
110
+ this.dates = m.dates
111
+ this.numbers = m.numbers
112
+ }
23
113
  }
24
- search(req: Request, res: Response) {
25
- const s = fromRequest<S>(req, this.format);
26
- const l = getLimit(s);
27
- this.find(s, l.limit, l.skip, l.refId)
28
- .then(result => jsonResult(res, result, this.csv, s.fields, this.config))
29
- .catch(err => handleError(err, res, this.log));
114
+ search(req: Request, res: Response): void {
115
+ const s = fromRequest<S>(req, buildArray(this.array, resources.fields, this.excluding))
116
+ const l = getParameters(s)
117
+ const s2 = format(s, this.dates, this.numbers)
118
+ this.query
119
+ .search(s2, l.limit, l.pageOrNextPageToken, l.fields)
120
+ .then((result) => jsonResult(res, result, this.csv, l.fields, this.config))
121
+ .catch((err) => handleError(err, res))
30
122
  }
31
123
  }
124
+ export { QueryController as QueryHandler }
@@ -0,0 +1,137 @@
1
+ import { Request, Response } from "express"
2
+ import { SimpleMap } from "./log"
3
+
4
+ export interface NumberMap {
5
+ [key: string]: number
6
+ }
7
+ export interface LogConfig {
8
+ level?: string
9
+ map?: LogMapConfig
10
+ constants?: SimpleMap
11
+ name?: Name
12
+ }
13
+ export interface LogMapConfig {
14
+ time?: string
15
+ level?: string
16
+ msg?: string
17
+ }
18
+ export interface LogMap {
19
+ time: string
20
+ level: string
21
+ msg: string
22
+ }
23
+ export interface Name {
24
+ trace: string
25
+ debug: string
26
+ info: string
27
+ warn: string
28
+ error: string
29
+ panic: string
30
+ fatal: string
31
+ }
32
+ export interface Logger {
33
+ name: Name
34
+ level: number
35
+ map: LogMap
36
+ constants?: SimpleMap
37
+ trace(msg: string, m?: SimpleMap, ctx?: any): void
38
+ debug(msg: string, m?: SimpleMap, ctx?: any): void
39
+ info(msg: string, m?: SimpleMap, ctx?: any): void
40
+ warn(msg: string, m?: SimpleMap, ctx?: any): void
41
+ error(msg: string, m?: SimpleMap, ctx?: any): void
42
+ panic(msg: string, m?: SimpleMap, ctx?: any): void
43
+ fatal(msg: string, m?: SimpleMap, ctx?: any): void
44
+ isLevelEnabled(level: number): boolean
45
+ isTraceEnabled(): boolean
46
+ isDebugEnabled(): boolean
47
+ isInfoEnabled(): boolean
48
+ isWarnEnabled(): boolean
49
+ isErrorEnabled(): boolean
50
+ isPanicEnabled(): boolean
51
+ isFatalEnabled(): boolean
52
+ }
53
+ export const map: NumberMap = {
54
+ TRACE: -2,
55
+ DEBUG: -1,
56
+ INFO: 0,
57
+ WARN: 1,
58
+ ERROR: 2,
59
+ PANIC: 3,
60
+ FATAL: 4,
61
+ }
62
+ export class LogController {
63
+ map: NumberMap
64
+ update: (logger: Logger, obj: LogConfig, mp: NumberMap) => boolean
65
+ constructor(public logger: Logger, updateL?: (logger: Logger, obj: LogConfig, mp: NumberMap) => boolean, mp?: NumberMap) {
66
+ this.map = mp ? mp : map
67
+ this.update = updateL ? updateL : updateLog
68
+ this.config = this.config.bind(this)
69
+ }
70
+ config(req: Request, res: Response) {
71
+ const obj: LogConfig = req.body
72
+ if (!this.logger) {
73
+ res.status(503).end("Logger is not available")
74
+ return
75
+ }
76
+ if (typeof obj.level === "string" && obj.level.length > 0) {
77
+ if (!this.map) {
78
+ res.status(503).end("Map is not available")
79
+ return
80
+ }
81
+ }
82
+ const changed = this.update(this.logger, obj, this.map)
83
+ if (changed) {
84
+ res.status(200).json(true).end()
85
+ } else {
86
+ res.status(204).json(false).end()
87
+ }
88
+ }
89
+ }
90
+ export function updateLog(logger: Logger, obj: LogConfig, mp: NumberMap): boolean {
91
+ let changed = false
92
+ if (typeof obj.level === "string" && obj.level.length > 0) {
93
+ const lv = mp[obj.level.toUpperCase()]
94
+ if (lv !== undefined) {
95
+ logger.level = lv
96
+ changed = true
97
+ }
98
+ }
99
+ if (obj.map) {
100
+ if (typeof obj.map.level === "string" && obj.map.level.length > 0) {
101
+ logger.map.level = obj.map.level
102
+ changed = true
103
+ }
104
+ if (typeof obj.map.time === "string" && obj.map.time.length > 0) {
105
+ logger.map.time = obj.map.time
106
+ changed = true
107
+ }
108
+ if (typeof obj.map.msg === "string" && obj.map.msg.length > 0) {
109
+ logger.map.msg = obj.map.msg
110
+ changed = true
111
+ }
112
+ }
113
+ if (obj.constants !== undefined && typeof obj.constants === "object") {
114
+ const ks = Object.keys(obj.constants)
115
+ if (ks.length > 0) {
116
+ logger.constants = obj.constants
117
+ } else {
118
+ logger.constants = undefined
119
+ }
120
+ changed = true
121
+ }
122
+ if (obj.name) {
123
+ if (
124
+ typeof obj.name.trace === "string" &&
125
+ typeof obj.name.debug === "string" &&
126
+ typeof obj.name.info === "string" &&
127
+ typeof obj.name.warn === "string" &&
128
+ typeof obj.name.error === "string" &&
129
+ typeof obj.name.panic === "string" &&
130
+ typeof obj.name.fatal === "string"
131
+ ) {
132
+ logger.name = obj.name
133
+ changed = true
134
+ }
135
+ }
136
+ return changed
137
+ }
@@ -0,0 +1,88 @@
1
+ import { Request, Response } from "express"
2
+ import { Build, GenericController, GenericService } from "./GenericController"
3
+ import { handleError, Log } from "./http"
4
+ import { ErrorMessage } from "./metadata"
5
+ import { resources, StringMap } from "./resources"
6
+ import { buildArray, Filter, format, fromRequest, getMetadataFunc, getParameters, initializeConfig, jsonResult, SearchConfig, SearchResult } from "./search"
7
+
8
+ export interface Service<T, ID, R, S extends Filter> extends GenericService<T, ID, R> {
9
+ search: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise<SearchResult<T>>
10
+ }
11
+ export class LowcodeController<T, ID, S extends Filter> extends GenericController<T, ID> {
12
+ config?: SearchConfig
13
+ csv?: boolean
14
+ dates?: string[]
15
+ numbers?: string[]
16
+ excluding?: string
17
+ array?: string[]
18
+ constructor(
19
+ public lowCodeService: Service<T, ID, number | ErrorMessage[], S>,
20
+ config?: SearchConfig,
21
+ build?: Build<T>,
22
+ validate?: (obj: T, resource?: StringMap, patch?: boolean) => Promise<ErrorMessage[]>,
23
+ dates?: string[],
24
+ numbers?: string[],
25
+ ) {
26
+ super(lowCodeService, build, validate)
27
+ this.search = this.search.bind(this)
28
+ this.config = initializeConfig(config)
29
+ if (this.config) {
30
+ this.csv = this.config.csv
31
+ this.excluding = this.config.excluding
32
+ }
33
+ const m = getMetadataFunc(lowCodeService, dates, numbers)
34
+ if (m) {
35
+ this.dates = m.dates
36
+ this.numbers = m.numbers
37
+ }
38
+ }
39
+ search(req: Request, res: Response) {
40
+ const s = fromRequest<S>(req, buildArray(this.array, resources.fields, this.excluding))
41
+ const l = getParameters(s)
42
+ const s2 = format(s, this.dates, this.numbers)
43
+ this.lowCodeService
44
+ .search(s2, l.limit, l.pageOrNextPageToken, l.fields)
45
+ .then((result) => jsonResult(res, result, this.csv, l.fields, this.config))
46
+ .catch((err) => handleError(err, res))
47
+ }
48
+ }
49
+ export { LowcodeController as LowcodeHandler }
50
+ export class Controller<T, ID, S extends Filter> extends GenericController<T, ID> {
51
+ config?: SearchConfig
52
+ csv?: boolean
53
+ dates?: string[]
54
+ numbers?: string[]
55
+ excluding?: string
56
+ array?: string[]
57
+ constructor(
58
+ log: Log,
59
+ public lowCodeService: Service<T, ID, number | T | ErrorMessage[], S>,
60
+ build?: Build<T>,
61
+ validate?: (obj: T, resource?: StringMap, patch?: boolean) => Promise<ErrorMessage[]>,
62
+ config?: SearchConfig,
63
+ dates?: string[],
64
+ numbers?: string[],
65
+ ) {
66
+ super(lowCodeService, build, validate)
67
+ this.search = this.search.bind(this)
68
+ this.config = initializeConfig(config)
69
+ if (this.config) {
70
+ this.csv = this.config.csv
71
+ this.excluding = this.config.excluding
72
+ }
73
+ const m = getMetadataFunc(lowCodeService, dates, numbers)
74
+ if (m) {
75
+ this.dates = m.dates
76
+ this.numbers = m.numbers
77
+ }
78
+ }
79
+ search(req: Request, res: Response) {
80
+ const s = fromRequest<S>(req, buildArray(this.array, resources.fields, this.excluding))
81
+ const l = getParameters(s)
82
+ const s2 = format(s, this.dates, this.numbers)
83
+ this.lowCodeService
84
+ .search(s2, l.limit, l.pageOrNextPageToken, l.fields)
85
+ .then((result) => jsonResult(res, result, this.csv, l.fields, this.config))
86
+ .catch((err) => handleError(err, res))
87
+ }
88
+ }
@@ -1,28 +1,39 @@
1
- import {Request, Response} from 'express';
2
- import {handleError} from './response';
3
- import {fromRequest, getLimit, initializeConfig, jsonResult, SearchConfig, SearchModel, SearchResult} from './search';
1
+ import { Request, Response } from "express"
2
+ import { handleError, Log } from "./http"
3
+ import { resources } from "./resources"
4
+ import { buildArray, Filter, format, fromRequest, getParameters, initializeConfig, jsonResult, SearchConfig, SearchResult } from "./search"
4
5
 
5
- export class SearchController<T, S extends SearchModel> {
6
- config?: SearchConfig;
7
- csv?: boolean;
8
- constructor(protected log: (msg: any, ctx?: any) => void, public find: (s: S, limit?: number, skip?: number, refId?: string) => Promise<SearchResult<T>>, config?: SearchConfig|boolean, public format?: (s: S) => S) {
9
- this.search = this.search.bind(this);
6
+ export class SearchController<T, S extends Filter> {
7
+ config?: SearchConfig
8
+ csv?: boolean
9
+ excluding?: string
10
+ array?: string[]
11
+ constructor(
12
+ protected log: Log,
13
+ public find: (s: S, limit: number, page?: number | string, fields?: string[]) => Promise<SearchResult<T>>,
14
+ config?: SearchConfig | boolean,
15
+ public dates?: string[],
16
+ public numbers?: string[],
17
+ ) {
18
+ this.search = this.search.bind(this)
10
19
  if (config) {
11
- if (typeof config === 'boolean') {
12
- this.csv = config;
20
+ if (typeof config === "boolean") {
21
+ this.csv = config
13
22
  } else {
14
- this.config = initializeConfig(config);
23
+ this.config = initializeConfig(config)
15
24
  if (this.config) {
16
- this.csv = this.config.csv;
25
+ this.csv = this.config.csv
26
+ this.excluding = this.config.excluding
17
27
  }
18
28
  }
19
29
  }
20
30
  }
21
31
  search(req: Request, res: Response) {
22
- const s = fromRequest<S>(req, this.format);
23
- const l = getLimit(s);
24
- this.find(s, l.limit, l.skip, l.refId)
25
- .then(result => jsonResult(res, result, this.csv, s.fields, this.config))
26
- .catch(err => handleError(err, res, this.log));
32
+ const s = fromRequest<S>(req, buildArray(this.array, resources.fields, this.excluding))
33
+ const l = getParameters(s)
34
+ const s2 = format(s, this.dates, this.numbers)
35
+ this.find(s2, l.limit, l.pageOrNextPageToken, l.fields)
36
+ .then((result) => jsonResult(res, result, this.csv, l.fields, this.config))
37
+ .catch((err) => handleError(err, res))
27
38
  }
28
39
  }
package/src/access.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { NextFunction, Request, Response } from "express"
2
+
3
+ export interface AccessConfig {
4
+ origin?: string | string[]
5
+ credentials?: string | string[]
6
+ methods?: string | string[]
7
+ headers: number | string | ReadonlyArray<string>
8
+ }
9
+ export type AccessControlAllowConfig = AccessConfig
10
+ export function allow(
11
+ access: AccessConfig,
12
+ ): (req: Request, res: Response, next: NextFunction) => void {
13
+ const ao = access.origin
14
+ if (typeof ao === "string") {
15
+ return (req: Request, res: Response, next: NextFunction) => {
16
+ res.header("Access-Control-Allow-Origin", access.origin)
17
+ res.header("Access-Control-Allow-Credentials", access.credentials)
18
+ res.header("Access-Control-Allow-Methods", access.methods)
19
+ res.setHeader("Access-Control-Allow-Headers", access.headers)
20
+ next()
21
+ }
22
+ } else if (Array.isArray(ao) && ao.length > 0) {
23
+ return (req: Request, res: Response, next: NextFunction) => {
24
+ const origin = req.headers.origin
25
+ if (origin) {
26
+ if (ao.includes(origin)) {
27
+ res.setHeader("Access-Control-Allow-Origin", origin)
28
+ }
29
+ }
30
+ res.header("Access-Control-Allow-Credentials", access.credentials)
31
+ res.header("Access-Control-Allow-Methods", access.methods)
32
+ res.setHeader("Access-Control-Allow-Headers", access.headers)
33
+ next()
34
+ }
35
+ }
36
+ return (req: Request, res: Response, next: NextFunction) => {
37
+ res.header("Access-Control-Allow-Credentials", access.credentials)
38
+ res.header("Access-Control-Allow-Methods", access.methods)
39
+ res.setHeader("Access-Control-Allow-Headers", access.headers)
40
+ next()
41
+ }
42
+ }
package/src/client.ts ADDED
@@ -0,0 +1,69 @@
1
+ import * as http from "http"
2
+ import * as https from "https"
3
+ import { AnyMap, HealthChecker } from "./health"
4
+
5
+ function getHealthSecure(url: string, timeout: number): Promise<AnyMap> {
6
+ return new Promise((resolve) => {
7
+ https
8
+ .get(url, { rejectUnauthorized: false }, (res: any) => {
9
+ let data = ""
10
+ res.on("data", (d: any) => {
11
+ data += d
12
+ })
13
+ res.on("end", () => {
14
+ resolve({ statusCode: res.statusCode, data, statusMessage: res.statusMessage })
15
+ })
16
+ })
17
+ .on("error", (e: any) => {
18
+ return { statusCode: 500, statusMessage: e }
19
+ })
20
+ setTimeout(() => resolve({ statusCode: 408, statusMessage: "Time out" }), timeout)
21
+ })
22
+ }
23
+ function getHealth(url: string, timeout: number): Promise<AnyMap> {
24
+ return new Promise((resolve) => {
25
+ http
26
+ .get(url, (res: any) => {
27
+ let data = ""
28
+ res.on("data", (d: any) => {
29
+ data += d
30
+ })
31
+ res.on("end", () => {
32
+ resolve({ statusCode: res.statusCode, data, statusMessage: res.statusMessage })
33
+ })
34
+ })
35
+ .on("error", (e: any) => {
36
+ return { statusCode: 500, statusMessage: e }
37
+ })
38
+ setTimeout(() => resolve({ statusCode: 408, statusMessage: "Time out" }), timeout)
39
+ })
40
+ }
41
+ export class ClientChecker implements HealthChecker {
42
+ timeout: number
43
+ constructor(private service: string, private url: string, timeout: number) {
44
+ this.timeout = timeout ? timeout : 4200
45
+ this.check = this.check.bind(this)
46
+ this.name = this.name.bind(this)
47
+ this.build = this.build.bind(this)
48
+ }
49
+ check(): Promise<AnyMap> {
50
+ let obj = {} as AnyMap
51
+ if (this.url.startsWith("https://")) {
52
+ return getHealthSecure(this.url, this.timeout).then((r) => (obj = r))
53
+ } else {
54
+ return getHealth(this.url, this.timeout).then((r) => (obj = r))
55
+ }
56
+ }
57
+ name(): string {
58
+ return this.service
59
+ }
60
+ build(data: AnyMap, err: any): AnyMap {
61
+ if (err) {
62
+ if (!data) {
63
+ data = {} as AnyMap
64
+ }
65
+ data["error"] = err
66
+ }
67
+ return data
68
+ }
69
+ }