minimonolith 0.1.4 → 0.2.0
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/index.js +5 -3
- package/package.json +3 -2
- package/src/apiHandler/apiHandler.js +6 -0
- package/src/apiHandler/createAPI.js +24 -0
- package/src/apiHandler/index.js +4 -0
- package/src/healthHandler/healthHandler.js +14 -0
- package/src/healthHandler/index.js +3 -0
- package/src/index.js +6 -18
- package/src/lambdaServer/index.js +3 -0
- package/src/lambdaServer/lambdaServer.js +12 -0
- package/src/lambdaServer/serverHandler.js +66 -0
- package/src/serviceHandler/index.js +1 -2
- package/src/healthCheck/index.js +0 -3
- package/src/todo/delete/handler.js +0 -10
- package/src/todo/delete/valid.js +0 -8
- package/src/todo/get/handler.js +0 -7
- package/src/todo/get/valid.js +0 -6
- package/src/todo/index.js +0 -5
- package/src/todo/model.js +0 -8
- package/src/todo/post/handler.js +0 -9
- package/src/todo/post/valid.js +0 -8
- package/test/serviceHandler/registerMethods.test.js +0 -34
- package/test/serviceHandler/serviceHandler.test.js +0 -95
- package/test/serviceHandler/testService/delete/handler.js +0 -3
- package/test/serviceHandler/testService/delete/valid.js +0 -3
- package/test/serviceHandler/testService/get/handler.js +0 -3
- package/test/serviceHandler/testService/get/valid.js +0 -3
- package/test/serviceHandler/testService/index.js +0 -3
- package/test/serviceHandler/testService/post/handler.js +0 -3
- package/test/serviceHandler/testService/post/valid.js +0 -3
package/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import createAPI from 'lambda-api';
|
|
2
1
|
import { z } from 'zod';
|
|
3
|
-
import { serviceHandler } from './src/serviceHandler/serviceHandler.js';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
import { serviceHandler } from './src/serviceHandler/index.js';
|
|
4
|
+
import { createAPI, apiHandler } from './src/apiHandler/index.js';
|
|
5
|
+
import { runLambdaServer } from './src/lambdaServer/index.js';
|
|
6
|
+
|
|
7
|
+
export { runLambdaServer, createAPI, apiHandler serviceHandler, z };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minimonolith",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
"zod": "^3.21.4"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"jest": "^29.5.0",
|
|
19
18
|
"@aws-sdk/client-s3": "^3.304.0",
|
|
20
19
|
"@aws-sdk/s3-request-presigner": "^3.304.0",
|
|
20
|
+
"dotenv": "^16.0.3",
|
|
21
|
+
"jest": "^29.5.0",
|
|
21
22
|
"sqlite3": "^5.1.6"
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import lambdaAPICreateAPI from 'lambda-api';
|
|
2
|
+
|
|
3
|
+
const addCORS = API => {
|
|
4
|
+
API.use((req, res, next) => { res.cors(); next(); });
|
|
5
|
+
API.use((err, req, res, next) => { res.cors(); next(); });
|
|
6
|
+
API.options('/*', (req, res) => {
|
|
7
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
8
|
+
res.header('Access-Control-Allow-Methods', 'OPTIONS, POST, GET, PUT, PATCH, DELETE');
|
|
9
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
10
|
+
res.header('Access-Control-Allow-Credentials', true);
|
|
11
|
+
console.log('OPTIONS_SUCCESS');
|
|
12
|
+
res.status(200).send({})
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const createAPI = () => {
|
|
17
|
+
const API = lambdaAPICreateAPI();
|
|
18
|
+
|
|
19
|
+
addCORS(API);
|
|
20
|
+
|
|
21
|
+
return API;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { createAPI };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const healthCheck = () => {
|
|
2
|
+
return "API running...";
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const healthHandler = API => {
|
|
6
|
+
API.get('/', async (req, res) => {
|
|
7
|
+
console.log('HEALTH_CHECK ENTERING');
|
|
8
|
+
const response = healthCheck();
|
|
9
|
+
console.log('HEALTH_CHECK SUCCESS');
|
|
10
|
+
return { response };
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { healthHandler };
|
package/src/index.js
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import createAPI from '
|
|
4
|
-
import
|
|
3
|
+
import { createAPI, apiHandler } from './apiHandler/index.js';
|
|
4
|
+
import { healthHandler } from './healthHandler/index.js';
|
|
5
5
|
import { serviceHandler } from './serviceHandler/index.js';
|
|
6
6
|
|
|
7
7
|
const API = createAPI();
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
API
|
|
11
|
-
|
|
12
|
-
const response = healthCheck();
|
|
13
|
-
console.log('HEALTH_CHECK SUCCESS');
|
|
14
|
-
return { response };
|
|
15
|
-
});
|
|
9
|
+
healthHandler(API);
|
|
10
|
+
serviceHandler(API, 'todo');
|
|
11
|
+
const lambdaAPIHandler = apiHandler(API);
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export const handler = async (e, context) => {
|
|
20
|
-
console.log({
|
|
21
|
-
EVENT_PATH: e.path,
|
|
22
|
-
EVENT_METHOD: e.httpMethod,
|
|
23
|
-
});
|
|
24
|
-
return await API.run(e, context);
|
|
25
|
-
};
|
|
13
|
+
export { lambdaAPIHandler };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
|
|
3
|
+
import './loadEnv.js';
|
|
4
|
+
import { serverHandlerContext } from './serverHandler.js';
|
|
5
|
+
|
|
6
|
+
const runLambdaServer = (lambdaAPIHandler, port) => {
|
|
7
|
+
const serverHandler = serverHandlerContext(lambdaAPIHandler);
|
|
8
|
+
const server = http.createServer(serverHandler);
|
|
9
|
+
server.listen(port);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { runLambdaServer };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import url from 'url';
|
|
4
|
+
|
|
5
|
+
const reqBodyPromise = req => {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
let data = ''; req.on('data', chunk => { data+=chunk; });
|
|
8
|
+
req.on('end', () => { data!==''? resolve(data):resolve(null); });
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const parseJWT = token => {
|
|
13
|
+
const tokenString = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
|
|
14
|
+
return tokenString;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const serverHandlerContext = lambdaAPIHandler => async (req, res) => {
|
|
18
|
+
try {
|
|
19
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
20
|
+
res.setHeader('Access-Control-Request-Method', '*');
|
|
21
|
+
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST,PUT,PATCH,DELETE');
|
|
22
|
+
res.setHeader('Access-Control-Allow-Headers', '*');
|
|
23
|
+
if (req.method === 'OPTIONS') {
|
|
24
|
+
res.writeHead(200);
|
|
25
|
+
res.end();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const token =
|
|
30
|
+
req.headers.authorization && req.headers.authorization.startsWith('Bearer ') ?
|
|
31
|
+
parseJWT(req.headers.authorization.split(" ")[1]) : null;
|
|
32
|
+
|
|
33
|
+
const tempQueryString = url.parse(req.url, true).query;
|
|
34
|
+
const queryString = tempQueryString? tempQueryString : undefined;
|
|
35
|
+
|
|
36
|
+
const tempBody = await reqBodyPromise(req);
|
|
37
|
+
const body = tempBody? tempBody : undefined;
|
|
38
|
+
|
|
39
|
+
const e = {
|
|
40
|
+
path: req.url,
|
|
41
|
+
httpMethod: req.method,
|
|
42
|
+
queryStringParameters: queryString,
|
|
43
|
+
requestContext: {
|
|
44
|
+
http: {
|
|
45
|
+
path: req.url,
|
|
46
|
+
method: req.method,
|
|
47
|
+
},
|
|
48
|
+
authorizer: {
|
|
49
|
+
jwt: { claims: token },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
headers: {
|
|
53
|
+
accept: req.headers.accept,
|
|
54
|
+
'User-Agent': req.headers['user-agent']
|
|
55
|
+
},
|
|
56
|
+
body,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const resL = await lambdaAPIHandler(e, null)
|
|
60
|
+
|
|
61
|
+
res.statusCode = resL.statusCode;
|
|
62
|
+
res.end(resL.body);
|
|
63
|
+
} catch(err) { console.log(err); }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { serverHandlerContext };
|
package/src/healthCheck/index.js
DELETED
package/src/todo/delete/valid.js
DELETED
package/src/todo/get/handler.js
DELETED
package/src/todo/get/valid.js
DELETED
package/src/todo/index.js
DELETED
package/src/todo/model.js
DELETED
package/src/todo/post/handler.js
DELETED
package/src/todo/post/valid.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import jest from 'jest-mock';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { registerMethods } from '../../src/serviceHandler/registerMethods';
|
|
4
|
-
|
|
5
|
-
describe('registerMethods', () => {
|
|
6
|
-
beforeAll(() => { process.env.TEST_ENVIRONMENT = true; });
|
|
7
|
-
afterAll(() => { delete process.env.TEST_ENVIRONMENT; });
|
|
8
|
-
|
|
9
|
-
test('should create methods object', async () => {
|
|
10
|
-
const methods = registerMethods([
|
|
11
|
-
'serviceHandler/testService/get',
|
|
12
|
-
'serviceHandler/testService/post',
|
|
13
|
-
'serviceHandler/testService/delete',
|
|
14
|
-
]);
|
|
15
|
-
|
|
16
|
-
const result = await methods(path.dirname(import.meta.url));
|
|
17
|
-
expect(result).toHaveProperty('serviceHandler/testService/get');
|
|
18
|
-
expect(result).toHaveProperty('serviceHandler/testService/post');
|
|
19
|
-
expect(result).toHaveProperty('serviceHandler/testService/delete');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('should throw error for invalid path', async () => {
|
|
23
|
-
const methods = registerMethods(['serviceHandler/testService/invalid']);
|
|
24
|
-
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
await methods(path.dirname(import.meta.url));
|
|
28
|
-
} catch (error) {
|
|
29
|
-
expect(error).toMatch(/Error importing handler or validator/);
|
|
30
|
-
expect(consoleSpy).toHaveBeenCalled()
|
|
31
|
-
consoleSpy.mockRestore();
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import jest from 'jest-mock';
|
|
2
|
-
import { serviceHandler } from '../../src/serviceHandler/serviceHandler.js';
|
|
3
|
-
|
|
4
|
-
// Mock API object to simulate the behavior of an API (e.g., Express)
|
|
5
|
-
const createMockAPI = () => {
|
|
6
|
-
const routes = {};
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
get: (path, handler) => (routes[path] = { method: 'get', handler }),
|
|
10
|
-
post: (path, handler) => (routes[path] = { method: 'post', handler }),
|
|
11
|
-
put: (path, handler) => (routes[path] = { method: 'put', handler }),
|
|
12
|
-
delete: (path, handler) => (routes[path] = { method: 'delete', handler }),
|
|
13
|
-
routes,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
describe('serviceHandler', () => {
|
|
18
|
-
beforeAll(() => { process.env.TEST_ENVIRONMENT = true; });
|
|
19
|
-
afterAll(() => { delete process.env.TEST_ENVIRONMENT; });
|
|
20
|
-
|
|
21
|
-
test('should add routes and methods to the API object', async () => {
|
|
22
|
-
const mockAPI = createMockAPI();
|
|
23
|
-
const serviceName = 'testService';
|
|
24
|
-
const SRC_FOLDER = 'test/serviceHandler';
|
|
25
|
-
|
|
26
|
-
await serviceHandler(mockAPI, serviceName, SRC_FOLDER);
|
|
27
|
-
|
|
28
|
-
// Check if routes are added to the API object
|
|
29
|
-
expect(mockAPI.routes).toHaveProperty(`/${serviceName}/get`);
|
|
30
|
-
expect(mockAPI.routes).toHaveProperty(`/${serviceName}/post`);
|
|
31
|
-
expect(mockAPI.routes).toHaveProperty(`/${serviceName}/delete`);
|
|
32
|
-
|
|
33
|
-
// Check if methods are added to the API object
|
|
34
|
-
expect(mockAPI.routes[`/${serviceName}/get`].method).toBe('get');
|
|
35
|
-
expect(mockAPI.routes[`/${serviceName}/post`].method).toBe('post');
|
|
36
|
-
expect(mockAPI.routes[`/${serviceName}/delete`].method).toBe('delete');
|
|
37
|
-
|
|
38
|
-
// Check if handlers are added to the API object
|
|
39
|
-
expect(mockAPI.routes[`/${serviceName}/get`].handler).toBeInstanceOf(Function);
|
|
40
|
-
expect(mockAPI.routes[`/${serviceName}/post`].handler).toBeInstanceOf(Function);
|
|
41
|
-
expect(mockAPI.routes[`/${serviceName}/delete`].handler).toBeInstanceOf(Function);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('should call handlers with the correct ROUTE_CODE, req, and res', async () => {
|
|
45
|
-
const mockAPI = createMockAPI();
|
|
46
|
-
const serviceName = 'testService';
|
|
47
|
-
const SRC_FOLDER = 'test/serviceHandler';
|
|
48
|
-
|
|
49
|
-
await serviceHandler(mockAPI, serviceName, SRC_FOLDER);
|
|
50
|
-
|
|
51
|
-
const mockReq = { foo: 'bar' };
|
|
52
|
-
const mockRes = {
|
|
53
|
-
status: jest.fn().mockReturnThis(),
|
|
54
|
-
json: jest.fn(),
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Call the GET handler
|
|
58
|
-
await mockAPI.routes[`/${serviceName}/get`].handler(mockReq, mockRes);
|
|
59
|
-
|
|
60
|
-
// Check if res.status and res.json are called with the correct values
|
|
61
|
-
expect(mockRes.status).toHaveBeenCalledWith(200);
|
|
62
|
-
expect(mockRes.json).toHaveBeenCalledWith('GET method');
|
|
63
|
-
|
|
64
|
-
// Call the POST handler
|
|
65
|
-
await mockAPI.routes[`/${serviceName}/post`].handler(mockReq, mockRes);
|
|
66
|
-
|
|
67
|
-
// Check if res.status and res.json are called with the correct values
|
|
68
|
-
expect(mockRes.status).toHaveBeenCalledWith(200);
|
|
69
|
-
expect(mockRes.json).toHaveBeenCalledWith('POST method');
|
|
70
|
-
|
|
71
|
-
// Call the DELETE handler
|
|
72
|
-
await mockAPI.routes[`/${serviceName}/delete`].handler(mockReq, mockRes);
|
|
73
|
-
|
|
74
|
-
// Check if res.status and res.json are called with the correct values
|
|
75
|
-
expect(mockRes.status).toHaveBeenCalledWith(200);
|
|
76
|
-
expect(mockRes.json).toHaveBeenCalledWith('DELETE method');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('should log an error if the serviceHandler fails', async () => {
|
|
80
|
-
const mockAPI = createMockAPI();
|
|
81
|
-
const serviceName = 'nonExistentService';
|
|
82
|
-
const SRC_FOLDER = 'test/serviceHandler';
|
|
83
|
-
|
|
84
|
-
// Spy on console.error to check if it's called
|
|
85
|
-
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
86
|
-
|
|
87
|
-
await serviceHandler(mockAPI, serviceName, SRC_FOLDER);
|
|
88
|
-
|
|
89
|
-
// Check if console.error is called
|
|
90
|
-
expect(consoleSpy).toHaveBeenCalled();
|
|
91
|
-
|
|
92
|
-
// Restore the original console.error implementation
|
|
93
|
-
consoleSpy.mockRestore();
|
|
94
|
-
});
|
|
95
|
-
});
|