@creator.co/wapi 1.2.1-beta6 → 1.2.2

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.
Files changed (127) hide show
  1. package/.github/workflows/npmpublish.yml +11 -19
  2. package/.github/workflows/prs.yml +13 -0
  3. package/jest.config.ts +39 -0
  4. package/package.json +15 -4
  5. package/src/API/Request.ts +120 -10
  6. package/src/API/Response.ts +236 -8
  7. package/src/API/Utils.ts +56 -1
  8. package/src/BaseEvent/EventProcessor.ts +84 -11
  9. package/src/BaseEvent/Process.ts +62 -1
  10. package/src/BaseEvent/Transaction.ts +5 -8
  11. package/src/Config/Configuration.ts +111 -5
  12. package/src/Config/EnvironmentVar.ts +90 -1
  13. package/src/Crypto/Crypto.ts +77 -18
  14. package/src/Crypto/JWT.ts +49 -3
  15. package/src/Globals.ts +141 -3
  16. package/src/Logger/Logger.ts +173 -19
  17. package/src/Mailer/Mailer.ts +95 -0
  18. package/src/Publisher/Publisher.ts +50 -4
  19. package/src/Server/RouteResolver.ts +142 -0
  20. package/src/Server/Router.ts +77 -0
  21. package/src/Server/lib/ContainerServer.ts +48 -1
  22. package/src/Server/lib/Server.ts +78 -38
  23. package/src/Server/lib/container/GenericHandler.ts +7 -5
  24. package/src/Server/lib/container/GenericHandlerEvent.ts +59 -17
  25. package/src/Server/lib/container/HealthHandler.ts +1 -1
  26. package/src/Server/lib/container/Proxy.ts +92 -11
  27. package/src/Server/lib/container/Utils.ts +16 -25
  28. package/src/Validation/Validator.ts +18 -2
  29. package/tests/API/Request.test.ts +263 -0
  30. package/tests/API/Response.test.ts +372 -0
  31. package/tests/API/Utils.test.ts +157 -0
  32. package/tests/BaseEvent/EventProcessor.test.ts +278 -0
  33. package/tests/BaseEvent/Process.test.ts +49 -0
  34. package/tests/BaseEvent/Transaction.test.ts +231 -0
  35. package/tests/Config/Config.test.ts +193 -0
  36. package/tests/Config/EnvironmentVar.test.ts +223 -0
  37. package/tests/Crypto/Crypto.test.ts +90 -0
  38. package/tests/Crypto/JWT.test.ts +92 -0
  39. package/tests/Logger/Logger.test.ts +108 -0
  40. package/tests/Mailer/Mailer.test.ts +67 -0
  41. package/tests/Publisher/Publisher.test.ts +60 -0
  42. package/tests/Server/RouteResolver.test.ts +106 -0
  43. package/tests/Server/Router.test.ts +38 -0
  44. package/tests/Server/lib/ContainerServer.test.ts +329 -0
  45. package/tests/Server/lib/Server.test.ts +12 -0
  46. package/tests/Server/lib/container/GenericHandler.test.ts +141 -0
  47. package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
  48. package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
  49. package/tests/Server/lib/container/Proxy.test.ts +278 -0
  50. package/tests/Server/lib/container/Utils.test.ts +48 -0
  51. package/tests/Test.utils.ts +95 -0
  52. package/tests/Validation/Validator.test.ts +88 -0
  53. package/tests/main.test.ts +15 -0
  54. package/tsconfig.json +1 -0
  55. package/dist/index.d.ts +0 -11
  56. package/dist/index.js +0 -24
  57. package/dist/index.js.map +0 -1
  58. package/dist/package.json +0 -53
  59. package/dist/src/API/Request.d.ts +0 -21
  60. package/dist/src/API/Request.js +0 -86
  61. package/dist/src/API/Request.js.map +0 -1
  62. package/dist/src/API/Response.d.ts +0 -39
  63. package/dist/src/API/Response.js +0 -232
  64. package/dist/src/API/Response.js.map +0 -1
  65. package/dist/src/API/Utils.d.ts +0 -8
  66. package/dist/src/API/Utils.js +0 -49
  67. package/dist/src/API/Utils.js.map +0 -1
  68. package/dist/src/BaseEvent/EventProcessor.d.ts +0 -13
  69. package/dist/src/BaseEvent/EventProcessor.js +0 -151
  70. package/dist/src/BaseEvent/EventProcessor.js.map +0 -1
  71. package/dist/src/BaseEvent/Process.d.ts +0 -12
  72. package/dist/src/BaseEvent/Process.js +0 -114
  73. package/dist/src/BaseEvent/Process.js.map +0 -1
  74. package/dist/src/BaseEvent/Transaction.d.ts +0 -29
  75. package/dist/src/BaseEvent/Transaction.js +0 -248
  76. package/dist/src/BaseEvent/Transaction.js.map +0 -1
  77. package/dist/src/Config/Configuration.d.ts +0 -34
  78. package/dist/src/Config/Configuration.js +0 -93
  79. package/dist/src/Config/Configuration.js.map +0 -1
  80. package/dist/src/Config/EnvironmentVar.d.ts +0 -17
  81. package/dist/src/Config/EnvironmentVar.js +0 -152
  82. package/dist/src/Config/EnvironmentVar.js.map +0 -1
  83. package/dist/src/Crypto/Crypto.d.ts +0 -8
  84. package/dist/src/Crypto/Crypto.js +0 -84
  85. package/dist/src/Crypto/Crypto.js.map +0 -1
  86. package/dist/src/Crypto/JWT.d.ts +0 -16
  87. package/dist/src/Crypto/JWT.js +0 -49
  88. package/dist/src/Crypto/JWT.js.map +0 -1
  89. package/dist/src/Globals.d.ts +0 -21
  90. package/dist/src/Globals.js +0 -35
  91. package/dist/src/Globals.js.map +0 -1
  92. package/dist/src/Logger/Logger.d.ts +0 -34
  93. package/dist/src/Logger/Logger.js +0 -345
  94. package/dist/src/Logger/Logger.js.map +0 -1
  95. package/dist/src/Mailer/Mailer.d.ts +0 -12
  96. package/dist/src/Mailer/Mailer.js +0 -234
  97. package/dist/src/Mailer/Mailer.js.map +0 -1
  98. package/dist/src/Publisher/Publisher.d.ts +0 -10
  99. package/dist/src/Publisher/Publisher.js +0 -109
  100. package/dist/src/Publisher/Publisher.js.map +0 -1
  101. package/dist/src/Server/Router.d.ts +0 -27
  102. package/dist/src/Server/Router.js +0 -22
  103. package/dist/src/Server/Router.js.map +0 -1
  104. package/dist/src/Server/lib/ContainerServer.d.ts +0 -11
  105. package/dist/src/Server/lib/ContainerServer.js +0 -103
  106. package/dist/src/Server/lib/ContainerServer.js.map +0 -1
  107. package/dist/src/Server/lib/Server.d.ts +0 -9
  108. package/dist/src/Server/lib/Server.js +0 -141
  109. package/dist/src/Server/lib/Server.js.map +0 -1
  110. package/dist/src/Server/lib/container/GenericHandler.d.ts +0 -4
  111. package/dist/src/Server/lib/container/GenericHandler.js +0 -136
  112. package/dist/src/Server/lib/container/GenericHandler.js.map +0 -1
  113. package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +0 -14
  114. package/dist/src/Server/lib/container/GenericHandlerEvent.js +0 -164
  115. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +0 -1
  116. package/dist/src/Server/lib/container/HealthHandler.d.ts +0 -3
  117. package/dist/src/Server/lib/container/HealthHandler.js +0 -44
  118. package/dist/src/Server/lib/container/HealthHandler.js.map +0 -1
  119. package/dist/src/Server/lib/container/Proxy.d.ts +0 -15
  120. package/dist/src/Server/lib/container/Proxy.js +0 -157
  121. package/dist/src/Server/lib/container/Proxy.js.map +0 -1
  122. package/dist/src/Server/lib/container/Utils.d.ts +0 -6
  123. package/dist/src/Server/lib/container/Utils.js +0 -109
  124. package/dist/src/Server/lib/container/Utils.js.map +0 -1
  125. package/dist/src/Validation/Validator.d.ts +0 -5
  126. package/dist/src/Validation/Validator.js +0 -31
  127. package/dist/src/Validation/Validator.js.map +0 -1
@@ -0,0 +1,141 @@
1
+ import { expect as j_expect } from "@jest/globals"
2
+ import { APIGatewayProxyEvent, Context } from "aws-lambda"
3
+ import { expect } from "chai"
4
+ import { Request, Response } from "express"
5
+
6
+ import Globals from "../../../../src/Globals"
7
+ import GenericHandler from "../../../../src/Server/lib/container/GenericHandler"
8
+
9
+ function observableResponse(): Response {
10
+ const resp = <Response>(<unknown>{
11
+ send: jest.fn(() => resp),
12
+ json: jest.fn(() => resp),
13
+ status: jest.fn(() => resp),
14
+ header: jest.fn(() => resp),
15
+ })
16
+ return resp
17
+ }
18
+
19
+ describe("GenericHandler success invocation path", () => {
20
+ test("Simple success", async () => {
21
+ const v = {
22
+ statusCode: 200,
23
+ body: JSON.stringify({ id: 123 }),
24
+ }
25
+ const handler = GenericHandler(
26
+ async (event: APIGatewayProxyEvent, context: Context) => {
27
+ context.succeed(v)
28
+ },
29
+ )
30
+ const resp = observableResponse()
31
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
32
+ //
33
+ expect(handlerResp).to.be.undefined
34
+ j_expect(resp.send).not.toBeCalled()
35
+ j_expect(resp.json).toBeCalledWith(JSON.parse(v.body))
36
+ j_expect(resp.status).toBeCalledWith(v.statusCode)
37
+ j_expect(resp.header).not.toBeCalled()
38
+ })
39
+
40
+ test("Simple success w/ headers", async () => {
41
+ const v = {
42
+ statusCode: 200,
43
+ body: JSON.stringify({ id: 123 }),
44
+ headers: { Authorization: 123 },
45
+ }
46
+ const handler = GenericHandler(
47
+ async (event: APIGatewayProxyEvent, context: Context) => {
48
+ context.succeed(v)
49
+ },
50
+ )
51
+ const resp = observableResponse()
52
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
53
+ //
54
+ expect(handlerResp).to.be.undefined
55
+ j_expect(resp.send).not.toBeCalled()
56
+ j_expect(resp.json).toBeCalledWith(JSON.parse(v.body))
57
+ j_expect(resp.status).toBeCalledWith(v.statusCode)
58
+ j_expect(resp.header).toBeCalledTimes(Object.keys(v.headers).length)
59
+ })
60
+
61
+ test("Simple success w/ null body", async () => {
62
+ const v = {
63
+ statusCode: 200,
64
+ headers: { Authorization: 123 },
65
+ }
66
+ const handler = GenericHandler(
67
+ async (event: APIGatewayProxyEvent, context: Context) => {
68
+ context.succeed(v)
69
+ },
70
+ )
71
+ const resp = observableResponse()
72
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
73
+ //
74
+ expect(handlerResp).to.be.undefined
75
+ j_expect(resp.send).not.toBeCalled()
76
+ j_expect(resp.json).toBeCalledWith({})
77
+ j_expect(resp.status).toBeCalledWith(v.statusCode)
78
+ j_expect(resp.header).toBeCalledTimes(Object.keys(v.headers).length)
79
+ })
80
+ })
81
+
82
+ describe("GenericHandler failure invocation path", () => {
83
+ test("Invalid response", async () => {
84
+ const handler = GenericHandler(
85
+ async (event: APIGatewayProxyEvent, context: Context) => {
86
+ context.succeed(null)
87
+ },
88
+ )
89
+ const resp = observableResponse()
90
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
91
+ //
92
+ expect(handlerResp).to.be.undefined
93
+ j_expect(resp.send).not.toBeCalled()
94
+ j_expect(resp.header).not.toBeCalled()
95
+ j_expect(resp.json).toBeCalledWith({
96
+ err: Globals.Resp_MSG_INVALIDRESP,
97
+ errCode: Globals.Resp_CODE_INVALIDRESP,
98
+ })
99
+ j_expect(resp.status).toBeCalledWith(Globals.Resp_STATUSCODE_INVALIDRESP)
100
+ })
101
+
102
+ test("Error response", async () => {
103
+ const err = new Error("Failed!")
104
+ const handler = GenericHandler(
105
+ async (event: APIGatewayProxyEvent, context: Context) => {
106
+ context.fail(err)
107
+ },
108
+ )
109
+ const resp = observableResponse()
110
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
111
+ //
112
+ expect(handlerResp).to.be.undefined
113
+ j_expect(resp.send).not.toBeCalled()
114
+ j_expect(resp.header).not.toBeCalled()
115
+ j_expect(resp.json).toBeCalledWith({
116
+ err,
117
+ })
118
+ j_expect(resp.status).toBeCalledWith(400)
119
+ })
120
+
121
+ test("Exception response", async () => {
122
+ const err = new Error("Failed!")
123
+ const handler = GenericHandler(async () => {
124
+ throw err
125
+ })
126
+ const resp = observableResponse()
127
+ const handlerResp = await handler(<Request>(<unknown>{}), resp)
128
+ //
129
+ expect(handlerResp).to.be.undefined
130
+ j_expect(resp.send).not.toBeCalled()
131
+ j_expect(resp.header).not.toBeCalled()
132
+ j_expect(resp.json).toBeCalledWith({
133
+ ...err,
134
+ err: Globals.Resp_MSG_EXCEPTION,
135
+ errCode: Globals.Resp_CODE_EXCEPTION,
136
+ })
137
+ j_expect(resp.status).toBeCalledWith(Globals.Resp_STATUSCODE_EXCEPTION)
138
+ })
139
+ })
140
+
141
+ export {}
@@ -0,0 +1,103 @@
1
+ import { APIGatewayProxyEvent, Context } from "aws-lambda"
2
+ import { expect } from "chai"
3
+ import { Request } from "express"
4
+
5
+ import GenericHandlerEvent from "../../../../src/Server/lib/container/GenericHandlerEvent"
6
+
7
+ describe("GenericHandlerEvent invocation paths", () => {
8
+ test("Simple success", async () => {
9
+ const event = new GenericHandlerEvent(
10
+ <Request>(<unknown>{
11
+ socket: { remoteAddress: "127.0.0.1" },
12
+ }),
13
+ async (event: APIGatewayProxyEvent, context: Context) => {
14
+ expect(context.getRemainingTimeInMillis()).to.not.be.null
15
+ context.succeed("Success")
16
+ },
17
+ )
18
+ const resp = await event.invoke()
19
+ expect(resp).to.not.be.null
20
+ expect(resp.err).to.be.null
21
+ expect(resp.data).to.be.equals("Success")
22
+ })
23
+
24
+ test("Simple failure", async () => {
25
+ const event = new GenericHandlerEvent(
26
+ <Request>(<unknown>{}),
27
+ async (event: APIGatewayProxyEvent, context: Context) => {
28
+ context.fail("Error!")
29
+ },
30
+ )
31
+ const resp = await event.invoke()
32
+ expect(resp).to.not.be.null
33
+ expect(resp.data).to.be.undefined
34
+ expect(resp.err).to.be.equals("Error!")
35
+ })
36
+
37
+ test("Simple done (errored)", async () => {
38
+ const event = new GenericHandlerEvent(
39
+ <Request>(<unknown>{}),
40
+ async (event: APIGatewayProxyEvent, context: Context) => {
41
+ context.done(new Error("Error!"))
42
+ },
43
+ )
44
+ const resp = await event.invoke()
45
+ expect(resp).to.not.be.null
46
+ expect(resp.data).to.be.undefined
47
+ expect(resp.err).to.be.an("Error")
48
+ if (resp.err instanceof Error)
49
+ expect(resp.err?.message).to.be.equals("Error!")
50
+ })
51
+
52
+ test("Simple done (success)", async () => {
53
+ const event = new GenericHandlerEvent(
54
+ <Request>(<unknown>{}),
55
+ async (event: APIGatewayProxyEvent, context: Context) => {
56
+ context.done(undefined, "Success!")
57
+ },
58
+ )
59
+ const resp = await event.invoke()
60
+ expect(resp).to.not.be.null
61
+ expect(resp.err).to.be.undefined
62
+ expect(resp.data).to.be.equals("Success!")
63
+ })
64
+
65
+ test("Exception on execution", async () => {
66
+ const event = new GenericHandlerEvent(<Request>(<unknown>{}), async () => {
67
+ throw new Error("Failed!")
68
+ })
69
+ let err: any = null,
70
+ resp: any = null
71
+ try {
72
+ resp = await event.invoke()
73
+ } catch (e) {
74
+ err = e
75
+ }
76
+ expect(resp).to.be.null
77
+ expect(err).to.not.be.null
78
+ expect(err).to.be.an("Error")
79
+ expect(err.message).to.be.equals("Failed!")
80
+ })
81
+ })
82
+
83
+ describe("GenericHandlerEvent event test", () => {
84
+ test("Simple event test", async () => {
85
+ const event = new GenericHandlerEvent(
86
+ <Request>(<unknown>{
87
+ headers: { Authorization: "123", "x-forwarded-for": "127.0.0.1" },
88
+ method: "get",
89
+ query: "/status?name=ryan",
90
+ }),
91
+ async (event: APIGatewayProxyEvent, context: Context) => {
92
+ expect(context.getRemainingTimeInMillis()).to.not.be.null
93
+ context.succeed("Success")
94
+ },
95
+ )
96
+ const resp = await event.invoke()
97
+ expect(resp).to.not.be.null
98
+ expect(resp.err).to.be.null
99
+ expect(resp.data).to.be.equals("Success")
100
+ })
101
+ })
102
+
103
+ export {}
@@ -0,0 +1,30 @@
1
+ import { expect as j_expect } from "@jest/globals"
2
+ import { expect } from "chai"
3
+ import { Request, Response } from "express"
4
+
5
+ import HealthHandler from "../../../../src/Server/lib/container/HealthHandler"
6
+
7
+ function observableResponse(): Response {
8
+ const resp = <Response>(<unknown>{
9
+ send: jest.fn(() => resp),
10
+ json: jest.fn(() => resp),
11
+ status: jest.fn(() => resp),
12
+ header: jest.fn(() => resp),
13
+ })
14
+ return resp
15
+ }
16
+
17
+ describe("HealthHandler invocation path", () => {
18
+ test("Simple", async () => {
19
+ const resp = observableResponse()
20
+ const handlerResp = await HealthHandler(<Request>(<unknown>{}), resp)
21
+ //
22
+ expect(handlerResp).to.be.undefined
23
+ j_expect(resp.send).toBeCalledWith("Healthy!")
24
+ j_expect(resp.json).not.toBeCalled()
25
+ j_expect(resp.status).not.toBeCalled()
26
+ j_expect(resp.header).not.toBeCalled()
27
+ })
28
+ })
29
+
30
+ export {}
@@ -0,0 +1,278 @@
1
+ import { expect as j_expect } from "@jest/globals"
2
+ import { APIGatewayProxyEvent, Context } from "aws-lambda"
3
+ import { expect } from "chai"
4
+ import * as request from "supertest"
5
+
6
+ import Globals from "../../../../src/Globals"
7
+ import Proxy from "../../../../src/Server/lib/container/Proxy"
8
+ import { defaultUrl } from "../../../Test.utils"
9
+
10
+ describe("Proxy configs", () => {
11
+ // @ts-ignore
12
+ let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
13
+ beforeAll(() => {
14
+ // @ts-ignore
15
+ mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
16
+ })
17
+ afterAll(() => {
18
+ mockExit.mockRestore()
19
+ })
20
+ beforeEach(() => {
21
+ mockExit.mockReset()
22
+ })
23
+
24
+ test("Empty config url & unload with error", async () => {
25
+ const proxy = new Proxy({ routes: [] }, async () => {})
26
+ await proxy.load()
27
+ await proxy.unload("Error")
28
+ j_expect(mockExit).toBeCalledWith(1)
29
+ })
30
+
31
+ test("Simple port config", async () => {
32
+ const proxy = new Proxy({ routes: [], port: 56562 }, async () => {})
33
+ await proxy.load()
34
+ await proxy.unload()
35
+ j_expect(mockExit).toBeCalledWith(0)
36
+ })
37
+
38
+ test("Simple timeout config", async () => {
39
+ const proxy = new Proxy({ routes: [], timeout: 1000 }, async () => {})
40
+ await proxy.load()
41
+ await proxy.unload()
42
+ j_expect(mockExit).toBeCalledWith(0)
43
+ })
44
+
45
+ test("Simple cors config", async () => {
46
+ const proxy = new Proxy(
47
+ {
48
+ routes: [],
49
+ cors: {
50
+ origin: "*",
51
+ headers: ["Authorization"],
52
+ allowCredentials: true,
53
+ },
54
+ },
55
+ async () => {},
56
+ )
57
+ await proxy.load()
58
+ await proxy.unload()
59
+ j_expect(mockExit).toBeCalledWith(0)
60
+ })
61
+
62
+ test("Empty cors config", async () => {
63
+ const proxy = new Proxy(
64
+ {
65
+ routes: [],
66
+ cors: {},
67
+ },
68
+ async () => {},
69
+ )
70
+ await proxy.load()
71
+ await proxy.unload()
72
+ j_expect(mockExit).toBeCalledWith(0)
73
+ })
74
+ })
75
+
76
+ describe("Proxy behaviour", () => {
77
+ // @ts-ignore
78
+ let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
79
+ beforeAll(() => {
80
+ // @ts-ignore
81
+ mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
82
+ })
83
+ afterAll(() => {
84
+ mockExit.mockRestore()
85
+ })
86
+ beforeEach(() => {
87
+ mockExit.mockReset()
88
+ })
89
+
90
+ test("Stop twice", async () => {
91
+ const proxy = new Proxy({ routes: [] }, async () => {})
92
+ await proxy.load()
93
+ await Promise.all([proxy.unload("Error"), proxy.unload("Error")])
94
+ j_expect(mockExit).toHaveBeenCalledTimes(1)
95
+ j_expect(mockExit).toBeCalledWith(1)
96
+ })
97
+ })
98
+
99
+ describe("Proxy routing", () => {
100
+ // @ts-ignore
101
+ let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
102
+ beforeAll(() => {
103
+ // @ts-ignore
104
+ mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
105
+ })
106
+ afterAll(() => {
107
+ mockExit.mockRestore()
108
+ })
109
+ beforeEach(() => {
110
+ mockExit.mockReset()
111
+ })
112
+
113
+ test("Health & Default handler", async () => {
114
+ let count = 0
115
+ const proxy = new Proxy(
116
+ { routes: [] },
117
+ async (event: APIGatewayProxyEvent, context: Context) => {
118
+ count++
119
+ context.succeed({
120
+ body: JSON.stringify({ name: "123" }),
121
+ statusCode: 200,
122
+ })
123
+ },
124
+ )
125
+ await proxy.load()
126
+ // Health check
127
+ const res = await request(defaultUrl)
128
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
129
+ .expect("Content-Type", "text/html; charset=utf-8")
130
+ .expect(200)
131
+ expect(res.text).to.be.equals("Healthy!")
132
+ // Generic handler
133
+ const resG = await request(defaultUrl)
134
+ .get(`/abc`)
135
+ .expect("Content-Type", "application/json; charset=utf-8")
136
+ .expect(200)
137
+ expect(resG.body).to.be.deep.equals({ name: "123" })
138
+ // Expected count
139
+ expect(count).to.be.equals(1)
140
+ // Unload
141
+ await proxy.unload("Error")
142
+ j_expect(mockExit).toHaveBeenCalledTimes(1)
143
+ j_expect(mockExit).toBeCalledWith(1)
144
+ })
145
+
146
+ test("Proxy on custom port", async () => {
147
+ let count = 0
148
+ const port = 56542
149
+ const url = defaultUrl.replace(
150
+ String(Globals.Listener_HTTP_DefaultPort),
151
+ String(port),
152
+ )
153
+ const proxy = new Proxy(
154
+ { routes: [], port },
155
+ async (event: APIGatewayProxyEvent, context: Context) => {
156
+ count++
157
+ context.succeed({
158
+ body: JSON.stringify({ name: "123" }),
159
+ statusCode: 200,
160
+ })
161
+ },
162
+ )
163
+ await proxy.load()
164
+ // Health check
165
+ const res = await request(url)
166
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
167
+ .expect("Content-Type", "text/html; charset=utf-8")
168
+ .expect(200)
169
+ expect(res.text).to.be.equals("Healthy!")
170
+ // Generic handler
171
+ const resG = await request(url)
172
+ .get(`/abc`)
173
+ .expect("Content-Type", "application/json; charset=utf-8")
174
+ .expect(200)
175
+ expect(resG.body).to.be.deep.equals({ name: "123" })
176
+ // Expected count
177
+ expect(count).to.be.equals(1)
178
+ // Unload
179
+ await proxy.unload()
180
+ j_expect(mockExit).toHaveBeenCalledTimes(1)
181
+ j_expect(mockExit).toBeCalledWith(0)
182
+ })
183
+
184
+ test("Proxy does timeout", async () => {
185
+ let count = 0
186
+ const timeout = 1000
187
+ const proxy = new Proxy(
188
+ { routes: [], timeout },
189
+ async (event: APIGatewayProxyEvent, context: Context) => {
190
+ count++
191
+ setTimeout(() => {
192
+ context.succeed({
193
+ body: JSON.stringify({ name: "123" }),
194
+ statusCode: 200,
195
+ })
196
+ }, timeout * 2)
197
+ },
198
+ )
199
+ await proxy.load()
200
+ // Health check
201
+ const res = await request(defaultUrl)
202
+ .get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
203
+ .expect("Content-Type", "text/html; charset=utf-8")
204
+ .expect(200)
205
+ expect(res.text).to.be.equals("Healthy!")
206
+ // Generic handler
207
+ let err: any = null
208
+ try {
209
+ await request(defaultUrl)
210
+ .get(`/abc`)
211
+ .expect("Content-Type", "application/json; charset=utf-8")
212
+ .expect(200)
213
+ } catch (e) {
214
+ err = e
215
+ }
216
+ expect(err?.message).to.be.equals("socket hang up")
217
+ // Expected count
218
+ expect(count).to.be.equals(1)
219
+ // Unload
220
+ await proxy.unload("Error")
221
+ j_expect(mockExit).toHaveBeenCalledTimes(1)
222
+ j_expect(mockExit).toBeCalledWith(1)
223
+ //
224
+ return new Promise((resolve) => {
225
+ setTimeout(resolve, timeout * 2)
226
+ })
227
+ })
228
+
229
+ test("Proxy respects cors", async () => {
230
+ let count = 0
231
+ const proxy = new Proxy(
232
+ {
233
+ routes: [],
234
+ cors: {
235
+ origin: "*",
236
+ headers: ["Authorization"],
237
+ allowCredentials: true,
238
+ },
239
+ },
240
+ async (event: APIGatewayProxyEvent, context: Context) => {
241
+ count++
242
+ context.succeed({
243
+ body: JSON.stringify({ name: "123" }),
244
+ statusCode: 200,
245
+ })
246
+ },
247
+ )
248
+ await proxy.load()
249
+ // White-listed header is allowed
250
+ const resWH = await request(defaultUrl)
251
+ .options(`/abc`)
252
+ .set("Authorization", 123)
253
+ .expect(204)
254
+ expect(resWH.header["access-control-allow-origin"]).to.equal("*")
255
+ expect(resWH.header["access-control-allow-credentials"]).to.equal("true")
256
+ expect(resWH.header["access-control-allow-headers"]).to.equal(
257
+ "Authorization",
258
+ )
259
+ // Non white-listed header is allowed
260
+ const resNWH = await request(defaultUrl)
261
+ .options(`/abc`)
262
+ .set("2Authorization2", 123)
263
+ .expect(204)
264
+ expect(resNWH.header["access-control-allow-origin"]).to.equal("*")
265
+ expect(resNWH.header["access-control-allow-credentials"]).to.equal("true")
266
+ expect(resNWH.header["access-control-allow-headers"]).to.equal(
267
+ "Authorization",
268
+ )
269
+ // Expected count
270
+ expect(count).to.be.equals(0)
271
+ // Unload
272
+ await proxy.unload()
273
+ j_expect(mockExit).toHaveBeenCalledTimes(1)
274
+ j_expect(mockExit).toBeCalledWith(0)
275
+ })
276
+ })
277
+
278
+ export {}
@@ -0,0 +1,48 @@
1
+ import { expect } from "chai"
2
+
3
+ import * as Utils from "../../../../src/Server/lib/container/Utils"
4
+
5
+ describe("parseQueryStringParameters", () => {
6
+ test("Null url", () => {
7
+ // @ts-ignore
8
+ const validationResult = Utils.parseQueryStringParameters(null)
9
+ expect(validationResult).to.be.deep.equals(null)
10
+ })
11
+
12
+ test("Empty url", () => {
13
+ const validationResult = Utils.parseQueryStringParameters("")
14
+ expect(validationResult).to.be.deep.equals(null)
15
+ })
16
+
17
+ test("Simple param", () => {
18
+ const validationResult =
19
+ Utils.parseQueryStringParameters("/status?name=ryan")
20
+ expect(validationResult).to.be.deep.equals({
21
+ name: "ryan",
22
+ })
23
+ })
24
+ })
25
+
26
+ describe("parseMultiValueQueryStringParameters", () => {
27
+ test("Null url", () => {
28
+ // @ts-ignore
29
+ const validationResult = Utils.parseMultiValueQueryStringParameters()
30
+ expect(validationResult).to.be.deep.equals({})
31
+ })
32
+
33
+ test("Empty url", () => {
34
+ const validationResult = Utils.parseMultiValueQueryStringParameters("")
35
+ expect(validationResult).to.be.deep.equals({})
36
+ })
37
+
38
+ test("Simple multivalue param", () => {
39
+ const validationResult = Utils.parseMultiValueQueryStringParameters(
40
+ "/status?name=ryan&name=ryan2",
41
+ )
42
+ expect(validationResult).to.be.deep.equals({
43
+ name: ["ryan", "ryan2"],
44
+ })
45
+ })
46
+ })
47
+
48
+ export {}
@@ -0,0 +1,95 @@
1
+ import { APIGatewayEvent, Context, SQSEvent } from "aws-lambda"
2
+ import { z } from "zod"
3
+
4
+ import Transaction from "../src/BaseEvent/Transaction"
5
+ import Globals from "../src/Globals"
6
+
7
+ export const defaultHeaders = {
8
+ "Access-Control-Allow-Credentials": true,
9
+ "Access-Control-Allow-Origin": "*",
10
+ "Content-Type": "application/json",
11
+ }
12
+
13
+ export const defaultUrl = `localhost:${Globals.Listener_HTTP_DefaultPort}`
14
+
15
+ export type SampleConfigSchema = {
16
+ PATH: {
17
+ isLocal: true
18
+ required: true
19
+ }
20
+ PATH_FALSY: {
21
+ isLocal: true
22
+ required: true
23
+ }
24
+ PATH123: {
25
+ isLocal: true
26
+ required: false
27
+ }
28
+ TOKEN_SECRET: {
29
+ isRemote: true
30
+ required: true
31
+ }
32
+ TOKEN_SECRET_FALSY: {
33
+ isRemote: true
34
+ required: false
35
+ }
36
+ }
37
+
38
+ export const SampleConfig: SampleConfigSchema = {
39
+ PATH: {
40
+ isLocal: true,
41
+ required: true,
42
+ },
43
+ PATH_FALSY: {
44
+ isLocal: true,
45
+ required: true,
46
+ },
47
+ PATH123: {
48
+ isLocal: true,
49
+ required: false,
50
+ },
51
+ TOKEN_SECRET: {
52
+ isRemote: true,
53
+ required: true,
54
+ },
55
+ TOKEN_SECRET_FALSY: {
56
+ isRemote: true,
57
+ required: false,
58
+ },
59
+ }
60
+ export function observableContext(data?: any) {
61
+ return <Context>(<unknown>{
62
+ done: jest.fn(),
63
+ fail: jest.fn(),
64
+ succeed: jest.fn(),
65
+ ...(data || {}),
66
+ })
67
+ }
68
+
69
+ export const privateKey = "tMHOuszBQmF6XtwgrUpvqpk07rh3RATX"
70
+
71
+ export const foreignToken =
72
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
73
+
74
+ export const ViewSchema = z.object({
75
+ id: z.string(),
76
+ content: z.string(),
77
+ createdAt: z.date(),
78
+ updatedAt: z.date(),
79
+ })
80
+
81
+ export type View = z.infer<typeof ViewSchema>
82
+
83
+ export function emptyEvent(data?: any) {
84
+ return <APIGatewayEvent>(<unknown>data || {})
85
+ }
86
+
87
+ export function emptyQueueEvent(data?: any) {
88
+ return <SQSEvent>(<unknown>data || {})
89
+ }
90
+
91
+ export function observableTransaction() {
92
+ const t = new Transaction(emptyEvent(), observableContext())
93
+ t.responseProxy = jest.fn()
94
+ return t
95
+ }