@creator.co/wapi 1.2.2 → 1.2.3
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/.eslintrc.cjs +29 -22
- package/.github/workflows/npmpublish.yml +1 -1
- package/.github/workflows/prs.yml +1 -1
- package/index.ts +12 -10
- package/jest.config.ts +19 -19
- package/package.json +1 -1
- package/src/API/Request.ts +17 -35
- package/src/API/Response.ts +24 -42
- package/src/API/Utils.ts +5 -7
- package/src/BaseEvent/EventProcessor.ts +16 -24
- package/src/BaseEvent/Process.ts +7 -12
- package/src/BaseEvent/Transaction.ts +25 -43
- package/src/Config/Configuration.ts +8 -14
- package/src/Config/EnvironmentVar.ts +10 -20
- package/src/Crypto/Crypto.ts +10 -10
- package/src/Crypto/JWT.ts +4 -10
- package/src/Globals.ts +19 -25
- package/src/Logger/Logger.ts +36 -51
- package/src/Mailer/Mailer.ts +19 -31
- package/src/Publisher/Publisher.ts +7 -12
- package/src/Server/RouteResolver.ts +5 -6
- package/src/Server/Router.ts +7 -12
- package/src/Server/lib/ContainerServer.ts +5 -5
- package/src/Server/lib/Server.ts +26 -38
- package/src/Server/lib/container/GenericHandler.ts +8 -13
- package/src/Server/lib/container/GenericHandlerEvent.ts +21 -35
- package/src/Server/lib/container/HealthHandler.ts +2 -2
- package/src/Server/lib/container/Proxy.ts +26 -38
- package/src/Server/lib/container/Utils.ts +2 -2
- package/src/Validation/Validator.ts +6 -6
- package/tests/API/Request.test.ts +107 -111
- package/tests/API/Response.test.ts +86 -91
- package/tests/API/Utils.test.ts +64 -64
- package/tests/BaseEvent/EventProcessor.test.ts +68 -84
- package/tests/BaseEvent/Process.test.ts +11 -11
- package/tests/BaseEvent/Transaction.test.ts +44 -53
- package/tests/Config/Config.test.ts +50 -50
- package/tests/Config/EnvironmentVar.test.ts +50 -59
- package/tests/Crypto/Crypto.test.ts +20 -22
- package/tests/Crypto/JWT.test.ts +40 -40
- package/tests/Logger/Logger.test.ts +24 -36
- package/tests/Mailer/Mailer.test.ts +21 -29
- package/tests/Publisher/Publisher.test.ts +18 -18
- package/tests/Server/RouteResolver.test.ts +56 -59
- package/tests/Server/Router.test.ts +16 -16
- package/tests/Server/lib/ContainerServer.test.ts +83 -85
- package/tests/Server/lib/Server.test.ts +4 -4
- package/tests/Server/lib/container/GenericHandler.test.ts +31 -41
- package/tests/Server/lib/container/GenericHandlerEvent.test.ts +35 -36
- package/tests/Server/lib/container/HealthHandler.test.ts +7 -7
- package/tests/Server/lib/container/Proxy.test.ts +66 -79
- package/tests/Server/lib/container/Utils.test.ts +16 -17
- package/tests/Test.utils.ts +9 -9
- package/tests/Validation/Validator.test.ts +28 -40
- package/tests/main.test.ts +2 -2
package/src/Logger/Logger.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as abind from
|
|
2
|
-
import * as stringify from
|
|
3
|
-
import * as stackTrace from
|
|
1
|
+
import * as abind from 'abind'
|
|
2
|
+
import * as stringify from 'json-stringify-safe'
|
|
3
|
+
import * as stackTrace from 'stack-trace'
|
|
4
4
|
|
|
5
5
|
//
|
|
6
|
-
import Utils from
|
|
6
|
+
import Utils from '../API/Utils'
|
|
7
7
|
//
|
|
8
8
|
/**
|
|
9
9
|
* ${1:Description placeholder}
|
|
@@ -12,17 +12,17 @@ import Utils from "../API/Utils"
|
|
|
12
12
|
* @enum {number}
|
|
13
13
|
*/
|
|
14
14
|
export enum LOG_LEVELS {
|
|
15
|
-
DEBUG =
|
|
16
|
-
INFO =
|
|
17
|
-
WARN =
|
|
18
|
-
ERROR =
|
|
15
|
+
DEBUG = 'DEBUG',
|
|
16
|
+
INFO = 'INFO',
|
|
17
|
+
WARN = 'WARN',
|
|
18
|
+
ERROR = 'ERROR',
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* ${1:Description placeholder}
|
|
22
22
|
*
|
|
23
23
|
* @type {*}
|
|
24
24
|
*/
|
|
25
|
-
const PURE_CONSOLE = console[
|
|
25
|
+
const PURE_CONSOLE = console['notGlobalLogger'] ? console['origin'] : console
|
|
26
26
|
/**
|
|
27
27
|
* ${1:Description placeholder}
|
|
28
28
|
*
|
|
@@ -36,18 +36,18 @@ const DEFAULT_LOG_FUNCTION = PURE_CONSOLE.log.bind(PURE_CONSOLE)
|
|
|
36
36
|
* @type {{}\}
|
|
37
37
|
*/
|
|
38
38
|
const blacklist = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
'password',
|
|
40
|
+
'phonenumber' /*,'code'*/,
|
|
41
|
+
'resetCode',
|
|
42
|
+
'recaptchaToken',
|
|
43
|
+
'token',
|
|
44
|
+
'mfa',
|
|
45
|
+
'REFRESH_TOKEN',
|
|
46
|
+
'SECRET_HASH',
|
|
47
|
+
'SecretHash',
|
|
48
|
+
'AccessToken',
|
|
49
|
+
'UserCode',
|
|
50
|
+
'paymentMethodNonce',
|
|
51
51
|
]
|
|
52
52
|
//
|
|
53
53
|
/**
|
|
@@ -129,8 +129,8 @@ export default class Logger {
|
|
|
129
129
|
//
|
|
130
130
|
this._setupBindings()
|
|
131
131
|
//
|
|
132
|
-
this.log(
|
|
133
|
-
this.debug(
|
|
132
|
+
this.log('Using logger with level: ' + this._LOG_LEVEL.toString())
|
|
133
|
+
this.debug('logger config: ', this._config)
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* ${1:Description placeholder}
|
|
@@ -231,22 +231,14 @@ export default class Logger {
|
|
|
231
231
|
* @param {string} caller
|
|
232
232
|
* @returns {string}
|
|
233
233
|
*/
|
|
234
|
-
private _formattedLog(
|
|
235
|
-
level: LOG_LEVELS,
|
|
236
|
-
msg: Array<string>,
|
|
237
|
-
caller: string,
|
|
238
|
-
): string {
|
|
234
|
+
private _formattedLog(level: LOG_LEVELS, msg: Array<string>, caller: string): string {
|
|
239
235
|
if (Utils.isHybridlessContainer() && this._transactionID) {
|
|
240
236
|
return (
|
|
241
237
|
`${this._transactionID}` +
|
|
242
|
-
` [${level.toString()}] [${caller}] ${msg
|
|
243
|
-
.map(this._suppressSensitiveInfo)
|
|
244
|
-
.join(" ")}`
|
|
238
|
+
` [${level.toString()}] [${caller}] ${msg.map(this._suppressSensitiveInfo).join(' ')}`
|
|
245
239
|
)
|
|
246
240
|
} else {
|
|
247
|
-
return `[${level.toString()}] [${caller}] ${msg
|
|
248
|
-
.map(this._suppressSensitiveInfo)
|
|
249
|
-
.join(" ")}`
|
|
241
|
+
return `[${level.toString()}] [${caller}] ${msg.map(this._suppressSensitiveInfo).join(' ')}`
|
|
250
242
|
}
|
|
251
243
|
}
|
|
252
244
|
/**
|
|
@@ -263,12 +255,12 @@ export default class Logger {
|
|
|
263
255
|
? stackTrace.get()[safeIndex].getTypeName()
|
|
264
256
|
: null
|
|
265
257
|
if (!callerName) {
|
|
266
|
-
callerName = stackTrace?.get()?.[safeIndex]?.getFileName()?.split(
|
|
267
|
-
callerName = callerName?.slice(callerName?.indexOf(
|
|
258
|
+
callerName = stackTrace?.get()?.[safeIndex]?.getFileName()?.split('/')
|
|
259
|
+
callerName = callerName?.slice(callerName?.indexOf('src'))?.join('/')
|
|
268
260
|
}
|
|
269
|
-
return callerName +
|
|
261
|
+
return callerName + ':' + stackTrace?.get()?.[safeIndex]?.getLineNumber()
|
|
270
262
|
}
|
|
271
|
-
return
|
|
263
|
+
return ''
|
|
272
264
|
}
|
|
273
265
|
/* Helpers (core functionality) */
|
|
274
266
|
/**
|
|
@@ -284,9 +276,7 @@ export default class Logger {
|
|
|
284
276
|
const msg: Array<string> = []
|
|
285
277
|
for (const arg of args) {
|
|
286
278
|
const fMsg =
|
|
287
|
-
typeof arg ===
|
|
288
|
-
? stringify(arg, null, 2)
|
|
289
|
-
: arg
|
|
279
|
+
typeof arg === 'object' && !(arg instanceof Error) ? stringify(arg, null, 2) : arg
|
|
290
280
|
msg.push(fMsg)
|
|
291
281
|
}
|
|
292
282
|
//push into logs stack
|
|
@@ -304,15 +294,12 @@ export default class Logger {
|
|
|
304
294
|
//format message
|
|
305
295
|
const msg: Array<string> = []
|
|
306
296
|
//push exeception
|
|
307
|
-
msg.push(exception.toString() +
|
|
297
|
+
msg.push(exception.toString() + ' -')
|
|
308
298
|
//get args
|
|
309
299
|
for (const arg of args) if (arg != exception) msg.push(arg)
|
|
310
300
|
if (exception.stack) msg.push(exception.stack) //push Exeception stack at the end
|
|
311
301
|
//push into logs stack
|
|
312
|
-
this._pushLog(
|
|
313
|
-
LOG_LEVELS.ERROR,
|
|
314
|
-
this._formattedLog(LOG_LEVELS.ERROR, msg, this._callerName(3)),
|
|
315
|
-
)
|
|
302
|
+
this._pushLog(LOG_LEVELS.ERROR, this._formattedLog(LOG_LEVELS.ERROR, msg, this._callerName(3)))
|
|
316
303
|
}
|
|
317
304
|
/**
|
|
318
305
|
* ${1:Description placeholder}
|
|
@@ -337,16 +324,14 @@ export default class Logger {
|
|
|
337
324
|
private _suppressSensitiveInfo(value: any): string {
|
|
338
325
|
//realy false
|
|
339
326
|
if (!this._filterBlacklist) return value
|
|
340
|
-
if (typeof value ==
|
|
327
|
+
if (typeof value == 'string') {
|
|
341
328
|
//content based replacement
|
|
342
329
|
if (this._filterBlacklist) {
|
|
343
330
|
this._filterBlacklist.forEach(() => {
|
|
344
331
|
const match = this._filterBlacklist
|
|
345
|
-
? this._filterBlacklist.find((f)
|
|
346
|
-
value.toLowerCase().includes(f.toLowerCase()),
|
|
347
|
-
)
|
|
332
|
+
? this._filterBlacklist.find(f => value.toLowerCase().includes(f.toLowerCase()))
|
|
348
333
|
: false
|
|
349
|
-
if (match) value =
|
|
334
|
+
if (match) value = '**SUPPRESSED_SENSITIVE_DATA**'
|
|
350
335
|
})
|
|
351
336
|
}
|
|
352
337
|
return value
|
package/src/Mailer/Mailer.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as SES from
|
|
2
|
-
import { defaultProvider } from
|
|
3
|
-
import * as Email from
|
|
4
|
-
import * as nodemailer from
|
|
5
|
-
import type * as SESTransport from
|
|
1
|
+
import * as SES from '@aws-sdk/client-ses'
|
|
2
|
+
import { defaultProvider } from '@aws-sdk/credential-provider-node'
|
|
3
|
+
import * as Email from 'email-templates'
|
|
4
|
+
import * as nodemailer from 'nodemailer'
|
|
5
|
+
import type * as SESTransport from 'nodemailer/lib/ses-transport'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* ${1:Description placeholder}
|
|
@@ -27,7 +27,7 @@ export default class Mailer {
|
|
|
27
27
|
* @readonly
|
|
28
28
|
* @type {string}
|
|
29
29
|
*/
|
|
30
|
-
private readonly templateDefaultFile: string =
|
|
30
|
+
private readonly templateDefaultFile: string = 'html'
|
|
31
31
|
/**
|
|
32
32
|
* ${1:Description placeholder}
|
|
33
33
|
*
|
|
@@ -53,7 +53,7 @@ export default class Mailer {
|
|
|
53
53
|
SES: {
|
|
54
54
|
ses: new SES.SESClient({
|
|
55
55
|
credentials: defaultProvider(),
|
|
56
|
-
apiVersion:
|
|
56
|
+
apiVersion: '2010-12-01',
|
|
57
57
|
region,
|
|
58
58
|
}),
|
|
59
59
|
aws: SES,
|
|
@@ -85,7 +85,7 @@ export default class Mailer {
|
|
|
85
85
|
optionalReplyTo?: string,
|
|
86
86
|
// TODO: improve attachment type -> Attachment
|
|
87
87
|
optionalAttachments?: any[],
|
|
88
|
-
optionalTransport?: Email.NodeMailerTransportOptions
|
|
88
|
+
optionalTransport?: Email.NodeMailerTransportOptions
|
|
89
89
|
) {
|
|
90
90
|
//Generate emails
|
|
91
91
|
const email = new Email({
|
|
@@ -105,9 +105,9 @@ export default class Mailer {
|
|
|
105
105
|
let resp = null
|
|
106
106
|
try {
|
|
107
107
|
resp = await email.send()
|
|
108
|
-
console.debug(
|
|
108
|
+
console.debug('Mailer resp:', resp)
|
|
109
109
|
} catch (e) {
|
|
110
|
-
console.error(
|
|
110
|
+
console.error('Mailer error:', e)
|
|
111
111
|
throw e
|
|
112
112
|
}
|
|
113
113
|
return resp
|
|
@@ -136,7 +136,7 @@ export default class Mailer {
|
|
|
136
136
|
optionalReplyTo?: string,
|
|
137
137
|
// TODO: improve attachment type -> Attachment
|
|
138
138
|
optionalAttachments?: any[],
|
|
139
|
-
optionalTransport?: Email.NodeMailerTransportOptions
|
|
139
|
+
optionalTransport?: Email.NodeMailerTransportOptions
|
|
140
140
|
) {
|
|
141
141
|
//Generate emails
|
|
142
142
|
const email = new Email({
|
|
@@ -155,9 +155,9 @@ export default class Mailer {
|
|
|
155
155
|
try {
|
|
156
156
|
const chosenTemplate = await this.chooseTemplate(templates, data)
|
|
157
157
|
resp = await email.send({ template: chosenTemplate, locals: data })
|
|
158
|
-
console.debug(
|
|
158
|
+
console.debug('Mailer resp:', resp)
|
|
159
159
|
} catch (e) {
|
|
160
|
-
console.error(
|
|
160
|
+
console.error('Mailer error:', e)
|
|
161
161
|
throw e
|
|
162
162
|
}
|
|
163
163
|
return resp
|
|
@@ -176,7 +176,7 @@ export default class Mailer {
|
|
|
176
176
|
host: string,
|
|
177
177
|
portNumber: number,
|
|
178
178
|
user: string,
|
|
179
|
-
password: string
|
|
179
|
+
password: string
|
|
180
180
|
): Email.NodeMailerTransportOptions {
|
|
181
181
|
const smtpTransporter = nodemailer.createTransport({
|
|
182
182
|
host: host,
|
|
@@ -200,10 +200,7 @@ export default class Mailer {
|
|
|
200
200
|
* @param {object} data
|
|
201
201
|
* @returns {Promise<string>}
|
|
202
202
|
*/
|
|
203
|
-
private async chooseTemplate(
|
|
204
|
-
templates: string | Array<string>,
|
|
205
|
-
data: object,
|
|
206
|
-
): Promise<string> {
|
|
203
|
+
private async chooseTemplate(templates: string | Array<string>, data: object): Promise<string> {
|
|
207
204
|
if (Array.isArray(templates)) {
|
|
208
205
|
//For each template check if can render it
|
|
209
206
|
for (const template of templates) {
|
|
@@ -214,7 +211,7 @@ export default class Mailer {
|
|
|
214
211
|
}
|
|
215
212
|
throw new Error(
|
|
216
213
|
`Could not render email with template ${templates} and following data. Please, check logs above! ` +
|
|
217
|
-
JSON.stringify(data, null, 2)
|
|
214
|
+
JSON.stringify(data, null, 2)
|
|
218
215
|
)
|
|
219
216
|
}
|
|
220
217
|
/**
|
|
@@ -226,22 +223,13 @@ export default class Mailer {
|
|
|
226
223
|
* @param {object} data
|
|
227
224
|
* @returns {Promise<boolean>}
|
|
228
225
|
*/
|
|
229
|
-
private async canRenderTemplate(
|
|
230
|
-
template: string,
|
|
231
|
-
data: object,
|
|
232
|
-
): Promise<boolean> {
|
|
226
|
+
private async canRenderTemplate(template: string, data: object): Promise<boolean> {
|
|
233
227
|
let validRenderResp = null
|
|
234
228
|
try {
|
|
235
229
|
const email = new Email()
|
|
236
|
-
validRenderResp = await email.render(
|
|
237
|
-
`${template}/${this.templateDefaultFile}`,
|
|
238
|
-
data,
|
|
239
|
-
)
|
|
230
|
+
validRenderResp = await email.render(`${template}/${this.templateDefaultFile}`, data)
|
|
240
231
|
} catch (e) {
|
|
241
|
-
console.log(
|
|
242
|
-
`Error while checking renderability of email template ${template}`,
|
|
243
|
-
e,
|
|
244
|
-
)
|
|
232
|
+
console.log(`Error while checking renderability of email template ${template}`, e)
|
|
245
233
|
}
|
|
246
234
|
return validRenderResp != null
|
|
247
235
|
}
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
PublishCommand,
|
|
4
4
|
PublishCommandOutput,
|
|
5
5
|
PublishCommandInput,
|
|
6
|
-
} from
|
|
7
|
-
import * as sha1 from
|
|
6
|
+
} from '@aws-sdk/client-sns'
|
|
7
|
+
import * as sha1 from 'sha1'
|
|
8
8
|
//reusable client
|
|
9
9
|
// eslint-disable-next-line no-var
|
|
10
10
|
/**
|
|
@@ -71,7 +71,7 @@ export default class Publisher {
|
|
|
71
71
|
async publishOnTopic(
|
|
72
72
|
messageObject: any,
|
|
73
73
|
topic: string,
|
|
74
|
-
additionalProps?: object
|
|
74
|
+
additionalProps?: object
|
|
75
75
|
): Promise<PublishCommandOutput> {
|
|
76
76
|
let resp: null | PublishCommandOutput = null
|
|
77
77
|
try {
|
|
@@ -84,11 +84,9 @@ export default class Publisher {
|
|
|
84
84
|
}
|
|
85
85
|
resp = await PUBLISHER_CONN.send(new PublishCommand(params))
|
|
86
86
|
} catch (e) {
|
|
87
|
-
console.error(
|
|
88
|
-
`Error while publishing into topic ${topic} with error: ${e}`,
|
|
89
|
-
)
|
|
87
|
+
console.error(`Error while publishing into topic ${topic} with error: ${e}`)
|
|
90
88
|
}
|
|
91
|
-
console.debug(
|
|
89
|
+
console.debug('Publisher resp', resp)
|
|
92
90
|
return resp
|
|
93
91
|
}
|
|
94
92
|
/* Private */
|
|
@@ -96,12 +94,9 @@ export default class Publisher {
|
|
|
96
94
|
* ${1:Description placeholder}
|
|
97
95
|
*/
|
|
98
96
|
_connect() {
|
|
99
|
-
if (
|
|
100
|
-
(!PUBLISHER_CONN && !PUBLISHER_CONN_HASH) ||
|
|
101
|
-
PUBLISHER_CONN_HASH != sha1(this.region)
|
|
102
|
-
) {
|
|
97
|
+
if ((!PUBLISHER_CONN && !PUBLISHER_CONN_HASH) || PUBLISHER_CONN_HASH != sha1(this.region)) {
|
|
103
98
|
PUBLISHER_CONN = new SNSClient({
|
|
104
|
-
apiVersion:
|
|
99
|
+
apiVersion: '2010-03-31',
|
|
105
100
|
region: this.region,
|
|
106
101
|
})
|
|
107
102
|
PUBLISHER_CONN_HASH = sha1(this.region).toString()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Route, RouterConfig } from
|
|
1
|
+
import { Route, RouterConfig } from './Router'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ${1:Description placeholder}
|
|
@@ -48,7 +48,7 @@ class Routes {
|
|
|
48
48
|
public addRoute(route: Route, parts: string[]): void {
|
|
49
49
|
const first = parts.shift()
|
|
50
50
|
if (first) {
|
|
51
|
-
if (first.startsWith(
|
|
51
|
+
if (first.startsWith(':')) {
|
|
52
52
|
this.variable = this.variable || new Routes()
|
|
53
53
|
this.variable.addRoute(route, parts)
|
|
54
54
|
} else {
|
|
@@ -56,8 +56,7 @@ class Routes {
|
|
|
56
56
|
this.next[first].addRoute(route, parts)
|
|
57
57
|
}
|
|
58
58
|
} else {
|
|
59
|
-
if (this.current)
|
|
60
|
-
throw new Error(`Duplicate route: ${route.method}: ${route.path}`)
|
|
59
|
+
if (this.current) throw new Error(`Duplicate route: ${route.method}: ${route.path}`)
|
|
61
60
|
|
|
62
61
|
this.current = route
|
|
63
62
|
}
|
|
@@ -119,7 +118,7 @@ export default class RouteResolver {
|
|
|
119
118
|
*/
|
|
120
119
|
public resolveRoute(method: string, path: string): Route | undefined {
|
|
121
120
|
method = method.toLowerCase()
|
|
122
|
-
const parts = path.split(
|
|
121
|
+
const parts = path.split('/').filter(p => p.length)
|
|
123
122
|
|
|
124
123
|
return this.routes[method]?.resolveRoute(parts)
|
|
125
124
|
}
|
|
@@ -133,7 +132,7 @@ export default class RouteResolver {
|
|
|
133
132
|
private buildRoutes(config: RouterConfig): void {
|
|
134
133
|
for (const route of config.routes) {
|
|
135
134
|
const method = route.method.toLowerCase()
|
|
136
|
-
const parts = route.path.split(
|
|
135
|
+
const parts = route.path.split('/').filter(p => p.length)
|
|
137
136
|
|
|
138
137
|
this.routes[method] = this.routes[method] || new Routes()
|
|
139
138
|
this.routes[method].addRoute(route, parts)
|
package/src/Server/Router.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { z } from
|
|
1
|
+
import { z } from 'zod'
|
|
2
2
|
|
|
3
|
-
import ContainerServer from
|
|
4
|
-
import Server from
|
|
5
|
-
import { ResponseErrorType } from
|
|
6
|
-
import Utils from
|
|
7
|
-
import Transaction, {
|
|
8
|
-
TransactionConfig,
|
|
9
|
-
TransactionExecution,
|
|
10
|
-
} from "../BaseEvent/Transaction"
|
|
3
|
+
import ContainerServer from './lib/ContainerServer'
|
|
4
|
+
import Server from './lib/Server'
|
|
5
|
+
import { ResponseErrorType } from '../API/Response'
|
|
6
|
+
import Utils from '../API/Utils'
|
|
7
|
+
import Transaction, { TransactionConfig, TransactionExecution } from '../BaseEvent/Transaction'
|
|
11
8
|
|
|
12
9
|
// Route
|
|
13
10
|
/**
|
|
@@ -110,9 +107,7 @@ export default class Router {
|
|
|
110
107
|
*/
|
|
111
108
|
constructor(config: RouterConfig) {
|
|
112
109
|
this.config = config
|
|
113
|
-
this.server = this.isContainer()
|
|
114
|
-
? new ContainerServer(config)
|
|
115
|
-
: new Server(config)
|
|
110
|
+
this.server = this.isContainer() ? new ContainerServer(config) : new Server(config)
|
|
116
111
|
}
|
|
117
112
|
/**
|
|
118
113
|
* Description placeholder
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import Proxy from
|
|
2
|
-
import Server from
|
|
3
|
-
import { RouterConfig } from
|
|
1
|
+
import Proxy from './container/Proxy'
|
|
2
|
+
import Server from './Server'
|
|
3
|
+
import { RouterConfig } from '../Router'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* ${1:Description placeholder}
|
|
@@ -71,7 +71,7 @@ export default class ContainerServer extends Server {
|
|
|
71
71
|
*/
|
|
72
72
|
private listenProcessEvents() {
|
|
73
73
|
// start process listeners
|
|
74
|
-
process.on(
|
|
75
|
-
process.on(
|
|
74
|
+
process.on('unhandledRejection', this.stop.bind(this)) // listen to exceptions
|
|
75
|
+
process.on('SIGINT', this.stop.bind(this)) // listen on SIGINT signal and gracefully stop the server
|
|
76
76
|
}
|
|
77
77
|
}
|
package/src/Server/lib/Server.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { APIGatewayProxyEvent, Context } from
|
|
2
|
-
import * as pathToRegexp from
|
|
1
|
+
import { APIGatewayProxyEvent, Context } from 'aws-lambda'
|
|
2
|
+
import * as pathToRegexp from 'path-to-regexp'
|
|
3
3
|
|
|
4
|
-
import Request from
|
|
5
|
-
import Response from
|
|
6
|
-
import Transaction from
|
|
7
|
-
import Validator from
|
|
8
|
-
import { RouterConfig } from
|
|
9
|
-
import RouteResolver from
|
|
4
|
+
import Request from '../../API/Request'
|
|
5
|
+
import Response from '../../API/Response'
|
|
6
|
+
import Transaction from '../../BaseEvent/Transaction'
|
|
7
|
+
import Validator from '../../Validation/Validator'
|
|
8
|
+
import { RouterConfig } from '../Router'
|
|
9
|
+
import RouteResolver from '../RouteResolver'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* ${1:Description placeholder}
|
|
@@ -63,38 +63,26 @@ export default class Server {
|
|
|
63
63
|
* @param {Context} context
|
|
64
64
|
* @returns {*}
|
|
65
65
|
*/
|
|
66
|
-
public async handleServerlessEvent(
|
|
67
|
-
event: APIGatewayProxyEvent,
|
|
68
|
-
context: Context,
|
|
69
|
-
) {
|
|
66
|
+
public async handleServerlessEvent(event: APIGatewayProxyEvent, context: Context) {
|
|
70
67
|
// init transaction
|
|
71
|
-
await new Transaction(event, context, this.config).execute(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// Validate input
|
|
81
|
-
if (route.inputSchema) {
|
|
82
|
-
const validationResp = Validator.validateSchema(
|
|
83
|
-
request.getBody(),
|
|
84
|
-
route.inputSchema,
|
|
85
|
-
)
|
|
86
|
-
if (validationResp && validationResp instanceof Response)
|
|
87
|
-
return validationResp
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.parsePathParams(request, route.path)
|
|
91
|
-
// Continue to route handler
|
|
92
|
-
return await route.handler(transaction)
|
|
68
|
+
await new Transaction(event, context, this.config).execute(async transaction => {
|
|
69
|
+
const request = transaction.request
|
|
70
|
+
const route = this.routeResolver.resolveRoute(request.getMethod(), request.getPath())
|
|
71
|
+
if (route) {
|
|
72
|
+
transaction.logger.log('Router accepted route:', route.path)
|
|
73
|
+
// Validate input
|
|
74
|
+
if (route.inputSchema) {
|
|
75
|
+
const validationResp = Validator.validateSchema(request.getBody(), route.inputSchema)
|
|
76
|
+
if (validationResp && validationResp instanceof Response) return validationResp
|
|
93
77
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
78
|
+
|
|
79
|
+
this.parsePathParams(request, route.path)
|
|
80
|
+
// Continue to route handler
|
|
81
|
+
return await route.handler(transaction)
|
|
82
|
+
}
|
|
83
|
+
//No route found :/
|
|
84
|
+
return new Response(404, { err: 'Route not found!' })
|
|
85
|
+
})
|
|
98
86
|
}
|
|
99
87
|
|
|
100
88
|
/**
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { Request, Response } from
|
|
1
|
+
import { Request, Response } from 'express'
|
|
2
2
|
|
|
3
|
-
import GenericHandlerEvent, {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import Globals from "../../../Globals"
|
|
8
|
-
import Server from "../Server"
|
|
3
|
+
import GenericHandlerEvent, { GenericHandlerEventResponse } from './GenericHandlerEvent'
|
|
4
|
+
import Utils from '../../../API/Utils'
|
|
5
|
+
import Globals from '../../../Globals'
|
|
6
|
+
import Server from '../Server'
|
|
9
7
|
|
|
10
|
-
export default (serverlessHandler: Server[
|
|
8
|
+
export default (serverlessHandler: Server['handleServerlessEvent']) => {
|
|
11
9
|
return async (request: Request, res: Response) => {
|
|
12
10
|
const startTime = Date.now()
|
|
13
11
|
try {
|
|
@@ -18,7 +16,7 @@ export default (serverlessHandler: Server["handleServerlessEvent"]) => {
|
|
|
18
16
|
// Respond
|
|
19
17
|
processServerlessResponse(invokationResp, res)
|
|
20
18
|
} catch (e) {
|
|
21
|
-
console.error(
|
|
19
|
+
console.error('[Proxy] - Exception during execution!', e)
|
|
22
20
|
console.error(e.stack)
|
|
23
21
|
res.status(Globals.Resp_STATUSCODE_EXCEPTION).json({
|
|
24
22
|
...e,
|
|
@@ -33,10 +31,7 @@ export default (serverlessHandler: Server["handleServerlessEvent"]) => {
|
|
|
33
31
|
* ${1:Description placeholder}
|
|
34
32
|
*
|
|
35
33
|
**/
|
|
36
|
-
const processServerlessResponse = (
|
|
37
|
-
invokation: GenericHandlerEventResponse,
|
|
38
|
-
res: Response,
|
|
39
|
-
) => {
|
|
34
|
+
const processServerlessResponse = (invokation: GenericHandlerEventResponse, res: Response) => {
|
|
40
35
|
// translate answer to http layer
|
|
41
36
|
if (invokation && invokation.err) {
|
|
42
37
|
// err came
|