quidproquo-dev-server 0.0.228
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/README.md +3 -0
- package/lib/commonjs/allServiceConfig.d.ts +3 -0
- package/lib/commonjs/allServiceConfig.js +44 -0
- package/lib/commonjs/dynamicModuleLoader/dynamicModuleLoader.d.ts +3 -0
- package/lib/commonjs/dynamicModuleLoader/dynamicModuleLoader.js +17 -0
- package/lib/commonjs/dynamicModuleLoader/index.d.ts +1 -0
- package/lib/commonjs/dynamicModuleLoader/index.js +17 -0
- package/lib/commonjs/entry/index.d.ts +1 -0
- package/lib/commonjs/entry/index.js +17 -0
- package/lib/commonjs/entry/route.d.ts +3 -0
- package/lib/commonjs/entry/route.js +64 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventAutoRespondActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventAutoRespondActionProcessor.js +31 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventGetRecordsActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventGetRecordsActionProcessor.js +34 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventGetStorySessionActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventGetStorySessionActionProcessor.js +22 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventMatchStoryActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventMatchStoryActionProcessor.js +55 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventTransformResponseResultActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/getEventTransformResponseResultActionProcessor.js +60 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/index.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/index.js +21 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/types.d.ts +8 -0
- package/lib/commonjs/getActionProcessor/core/event/express/api/types.js +2 -0
- package/lib/commonjs/getActionProcessor/core/event/express/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/core/event/express/index.js +17 -0
- package/lib/commonjs/getActionProcessor/core/event/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/core/event/index.js +17 -0
- package/lib/commonjs/getActionProcessor/core/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/core/index.js +17 -0
- package/lib/commonjs/getActionProcessor/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/index.js +17 -0
- package/lib/commonjs/index.d.ts +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/main.d.ts +2 -0
- package/lib/commonjs/main.js +143 -0
- package/lib/commonjs/types/DevServerConfig.d.ts +4 -0
- package/lib/commonjs/types/DevServerConfig.js +2 -0
- package/lib/commonjs/types/ExpressEvent.d.ts +26 -0
- package/lib/commonjs/types/ExpressEvent.js +2 -0
- package/lib/commonjs/types/index.d.ts +2 -0
- package/lib/commonjs/types/index.js +18 -0
- package/lib/esm/allServiceConfig.d.ts +3 -0
- package/lib/esm/allServiceConfig.js +40 -0
- package/lib/esm/dynamicModuleLoader/dynamicModuleLoader.d.ts +3 -0
- package/lib/esm/dynamicModuleLoader/dynamicModuleLoader.js +6 -0
- package/lib/esm/dynamicModuleLoader/index.d.ts +1 -0
- package/lib/esm/dynamicModuleLoader/index.js +1 -0
- package/lib/esm/entry/index.d.ts +1 -0
- package/lib/esm/entry/index.js +1 -0
- package/lib/esm/entry/route.d.ts +3 -0
- package/lib/esm/entry/route.js +52 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventAutoRespondActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventAutoRespondActionProcessor.js +16 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventGetRecordsActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventGetRecordsActionProcessor.js +19 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventGetStorySessionActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventGetStorySessionActionProcessor.js +7 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventMatchStoryActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventMatchStoryActionProcessor.js +40 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventTransformResponseResultActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/getEventTransformResponseResultActionProcessor.js +48 -0
- package/lib/esm/getActionProcessor/core/event/express/api/index.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/event/express/api/index.js +12 -0
- package/lib/esm/getActionProcessor/core/event/express/api/types.d.ts +8 -0
- package/lib/esm/getActionProcessor/core/event/express/api/types.js +1 -0
- package/lib/esm/getActionProcessor/core/event/express/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/core/event/express/index.js +1 -0
- package/lib/esm/getActionProcessor/core/event/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/core/event/index.js +1 -0
- package/lib/esm/getActionProcessor/core/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/core/index.js +1 -0
- package/lib/esm/getActionProcessor/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/index.js +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/main.d.ts +2 -0
- package/lib/esm/main.js +127 -0
- package/lib/esm/types/DevServerConfig.d.ts +4 -0
- package/lib/esm/types/DevServerConfig.js +1 -0
- package/lib/esm/types/ExpressEvent.d.ts +26 -0
- package/lib/esm/types/ExpressEvent.js +1 -0
- package/lib/esm/types/index.d.ts +2 -0
- package/lib/esm/types/index.js +2 -0
- package/package.json +41 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.spinUpService = void 0;
|
|
17
|
+
/* eslint-disable no-console */
|
|
18
|
+
const body_parser_1 = __importDefault(require("body-parser"));
|
|
19
|
+
const express_1 = __importDefault(require("express"));
|
|
20
|
+
const multer_1 = __importDefault(require("multer"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
const quidproquo_1 = require("quidproquo");
|
|
23
|
+
const route_1 = require("./entry/route");
|
|
24
|
+
const allServiceConfig_1 = require("./allServiceConfig");
|
|
25
|
+
const dynamicModuleLoader_1 = require("./dynamicModuleLoader");
|
|
26
|
+
const getServiceBaseDomain = (qpqConfig, devServerConfig) => quidproquo_1.qpqWebServerUtils.getDomainRoot(`${devServerConfig.serverDomain}:${devServerConfig.serverPort}`, quidproquo_1.qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig), quidproquo_1.qpqCoreUtils.getApplicationModuleFeature(qpqConfig));
|
|
27
|
+
const getApiDomainsFromConfig = (qpqConfig, devServerConfig) => {
|
|
28
|
+
const baseDomain = getServiceBaseDomain(qpqConfig, devServerConfig);
|
|
29
|
+
const serviceName = quidproquo_1.qpqCoreUtils.getApplicationModuleName(qpqConfig);
|
|
30
|
+
// Get apis
|
|
31
|
+
const apiConfigs = quidproquo_1.qpqWebServerUtils.getApiConfigs(qpqConfig);
|
|
32
|
+
const apiDomains = apiConfigs.map((apiConfig) => ({
|
|
33
|
+
apiName: apiConfig.apiName,
|
|
34
|
+
service: serviceName,
|
|
35
|
+
qpqConfig,
|
|
36
|
+
domain: `${apiConfig.apiSubdomain}.${baseDomain}`,
|
|
37
|
+
devDomain: baseDomain,
|
|
38
|
+
devPath: `/${apiConfig.apiSubdomain}/${serviceName}`,
|
|
39
|
+
}));
|
|
40
|
+
return apiDomains;
|
|
41
|
+
};
|
|
42
|
+
const getDynamicModuleLoader = (qpqConfig) => {
|
|
43
|
+
const serviceName = quidproquo_1.qpqCoreUtils.getApplicationModuleName(qpqConfig);
|
|
44
|
+
return (runtime) => __awaiter(void 0, void 0, void 0, function* () { return (0, dynamicModuleLoader_1.dynamicModuleLoader)(serviceName, runtime); });
|
|
45
|
+
};
|
|
46
|
+
const spinUpService = (devServerConfig) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const allServiceConfig = yield (0, allServiceConfig_1.getAllServiceConfigs)(devServerConfig);
|
|
48
|
+
const app = (0, express_1.default)();
|
|
49
|
+
app.use((0, multer_1.default)().any());
|
|
50
|
+
app.use(body_parser_1.default.json({ limit: '50mb' }));
|
|
51
|
+
const apiConfigs = allServiceConfig.map((qpqConfig) => getApiDomainsFromConfig(qpqConfig, devServerConfig)).flat();
|
|
52
|
+
const adminFrontend = path_1.default.join(__dirname, '../../..', 'node_modules', 'quidproquo-web-admin', 'lib');
|
|
53
|
+
// Admin page
|
|
54
|
+
app.use('/admin', express_1.default.static(adminFrontend));
|
|
55
|
+
app.get('/admin/service/log/list', (req, res) => {
|
|
56
|
+
// Manually set CORS headers
|
|
57
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
58
|
+
res.header('Access-Control-Allow-Methods', '*');
|
|
59
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
60
|
+
res.header('Access-Control-Allow-Credentials', 'false');
|
|
61
|
+
const serviceList = allServiceConfig.map((qpqConfig) => quidproquo_1.qpqCoreUtils.getApplicationModuleName(qpqConfig)).map((name) => `api/${name}`);
|
|
62
|
+
res.json(serviceList);
|
|
63
|
+
});
|
|
64
|
+
app.use(express_1.default.json());
|
|
65
|
+
app.options('/admin/service/log/execute', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
// Manually set CORS headers
|
|
67
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
68
|
+
res.header('Access-Control-Allow-Methods', '*');
|
|
69
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
70
|
+
res.header('Access-Control-Allow-Credentials', 'false');
|
|
71
|
+
res.json({ done: true });
|
|
72
|
+
}));
|
|
73
|
+
app.get('/mf-manifest-location.json', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
+
// Manually set CORS headers
|
|
75
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
76
|
+
res.header('Access-Control-Allow-Methods', '*');
|
|
77
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
78
|
+
res.header('Access-Control-Allow-Credentials', 'false');
|
|
79
|
+
res.json({ location: 'http://localhost:3005/mf-manifest.json' });
|
|
80
|
+
}));
|
|
81
|
+
app.post('/admin/service/log/execute', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
// Manually set CORS headers
|
|
83
|
+
res.header('Access-Control-Allow-Headers', '*');
|
|
84
|
+
res.header('Access-Control-Allow-Methods', '*');
|
|
85
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
86
|
+
res.header('Access-Control-Allow-Credentials', 'false');
|
|
87
|
+
// TODO: Get list of services from config dynamically
|
|
88
|
+
const serviceLog = req.body;
|
|
89
|
+
let runtimeModule = quidproquo_1.askProcessEvent;
|
|
90
|
+
if (serviceLog.runtimeType === quidproquo_1.QpqRuntimeType.EXECUTE_STORY) {
|
|
91
|
+
const [srcEntry, module] = serviceLog.tags[0].split('::');
|
|
92
|
+
const loadedModule = yield (0, dynamicModuleLoader_1.dynamicModuleLoader)(serviceLog.moduleName, srcEntry);
|
|
93
|
+
runtimeModule = loadedModule[module];
|
|
94
|
+
}
|
|
95
|
+
const result = yield (0, quidproquo_1.qpqExecuteLog)(serviceLog, runtimeModule);
|
|
96
|
+
res.json(result);
|
|
97
|
+
}));
|
|
98
|
+
// Proxy for all services
|
|
99
|
+
app.all('*', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
100
|
+
const apiConfig = apiConfigs.find((c) => req.url.startsWith(`${c.devPath}/`));
|
|
101
|
+
if (apiConfig) {
|
|
102
|
+
console.log(`[${req.method}::${req.socket.remoteAddress}]: ${req.protocol}://${req.get('host')}${req.url}`);
|
|
103
|
+
const event = {
|
|
104
|
+
protocol: req.protocol,
|
|
105
|
+
host: req.get('host') || devServerConfig.serverDomain,
|
|
106
|
+
path: req.url.substring(apiConfig.devPath.length).split('?')[0],
|
|
107
|
+
ip: req.socket.remoteAddress || '127.0.0.1',
|
|
108
|
+
query: req.query,
|
|
109
|
+
correlation: '',
|
|
110
|
+
headers: req.headers,
|
|
111
|
+
method: req.method,
|
|
112
|
+
isBase64Encoded: false,
|
|
113
|
+
body: typeof req.body === 'object' ? JSON.stringify(req.body) : req.body,
|
|
114
|
+
};
|
|
115
|
+
if (req.files) {
|
|
116
|
+
event.files = req.files.map((file) => ({
|
|
117
|
+
base64Data: file.buffer.toString('base64'),
|
|
118
|
+
filename: file.originalname,
|
|
119
|
+
mimetype: file.mimetype,
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
const response = yield (0, route_1.route)(event, apiConfig.qpqConfig, getDynamicModuleLoader(apiConfig.qpqConfig));
|
|
123
|
+
for (const [header, value] of Object.entries(response.headers)) {
|
|
124
|
+
res.set(header, value);
|
|
125
|
+
}
|
|
126
|
+
if (response.isBase64Encoded) {
|
|
127
|
+
res.status(response.statusCode).send(Buffer.from(response.body, 'base64'));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
res.status(response.statusCode).send(response.body);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`NotFound::[${req.method}::${req.socket.remoteAddress}]: ${req.protocol}://${req.get('host')}${req.url}`);
|
|
135
|
+
res.status(500).send({ message: 'resource does not exist' });
|
|
136
|
+
}
|
|
137
|
+
}));
|
|
138
|
+
app.listen(devServerConfig.serverPort, '0.0.0.0', () => {
|
|
139
|
+
const baseDomain = getServiceBaseDomain(allServiceConfig[0], devServerConfig);
|
|
140
|
+
console.log(`⚡️⚡️⚡️[Qpq - Dev Server]⚡️⚡️⚡️: Server is running at [http://${baseDomain}]`);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
exports.spinUpService = spinUpService;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { QPQBinaryData } from 'quidproquo';
|
|
2
|
+
export interface ExpressEvent {
|
|
3
|
+
protocol: string;
|
|
4
|
+
host: string;
|
|
5
|
+
path: string;
|
|
6
|
+
ip: string;
|
|
7
|
+
method: string;
|
|
8
|
+
query: {
|
|
9
|
+
[key: string]: undefined | string | string[];
|
|
10
|
+
};
|
|
11
|
+
correlation: string;
|
|
12
|
+
isBase64Encoded: boolean;
|
|
13
|
+
body: any;
|
|
14
|
+
headers: {
|
|
15
|
+
[key: string]: undefined | string;
|
|
16
|
+
};
|
|
17
|
+
files?: QPQBinaryData[];
|
|
18
|
+
}
|
|
19
|
+
export interface ExpressEventResponse {
|
|
20
|
+
statusCode: number;
|
|
21
|
+
body: string;
|
|
22
|
+
headers: {
|
|
23
|
+
[key: string]: undefined | string;
|
|
24
|
+
};
|
|
25
|
+
isBase64Encoded: boolean;
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./DevServerConfig"), exports);
|
|
18
|
+
__exportStar(require("./ExpressEvent"), exports);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { qpqCoreUtils, qpqWebServerUtils } from 'quidproquo';
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
3
|
+
// @ts-ignore - Special webpack loader
|
|
4
|
+
import { qpqConfigs } from 'quidproquo-dynamic-loader';
|
|
5
|
+
// Create an async function to fetch all services
|
|
6
|
+
export function getAllServiceConfigs(devServerConfig) {
|
|
7
|
+
// Iterate over each enum value and dynamically import the corresponding infrastructure
|
|
8
|
+
const allServices = qpqConfigs;
|
|
9
|
+
const rootDomain = `${devServerConfig.serverDomain}:${devServerConfig.serverPort}`;
|
|
10
|
+
// TODO: Make this pure
|
|
11
|
+
// Overload the domain settings to represent the local env
|
|
12
|
+
// This is kind of gross, mutating it, but this is just dev.
|
|
13
|
+
for (const qpqConfig of allServices) {
|
|
14
|
+
// Make it a production build
|
|
15
|
+
// const appSettings = qpqCoreUtils.getApplicationModuleSetting(qpqConfig);
|
|
16
|
+
// appSettings.feature = undefined;
|
|
17
|
+
// appSettings.environment = 'production';
|
|
18
|
+
const baseDomain = qpqWebServerUtils.getDomainRoot(rootDomain, qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig), qpqCoreUtils.getApplicationModuleFeature(qpqConfig));
|
|
19
|
+
// Change the domain
|
|
20
|
+
const dnsConfigs = qpqWebServerUtils.getDnsConfigs(qpqConfig);
|
|
21
|
+
for (const dnsConfig of dnsConfigs) {
|
|
22
|
+
dnsConfig.dnsBase = rootDomain;
|
|
23
|
+
}
|
|
24
|
+
// Expose global cors headers
|
|
25
|
+
const defaultRouteSettings = qpqWebServerUtils.getDefaultRouteSettings(qpqConfig);
|
|
26
|
+
for (const getDefaultRouteSetting of defaultRouteSettings) {
|
|
27
|
+
getDefaultRouteSetting.routeOptions.allowedOrigins = [
|
|
28
|
+
...(getDefaultRouteSetting.routeOptions.allowedOrigins || []),
|
|
29
|
+
`http://${baseDomain}`,
|
|
30
|
+
'*',
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
// Expose global cors headers
|
|
34
|
+
const routes = qpqWebServerUtils.getAllRoutes(qpqConfig);
|
|
35
|
+
for (const route of routes) {
|
|
36
|
+
route.options.allowedOrigins = [...(route.options.allowedOrigins || []), `http://${baseDomain}`, '*'];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return allServices;
|
|
40
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { qpqConfigs, qpqDynamicModuleLoaderForService,
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
3
|
+
// @ts-ignore - Special webpack loader
|
|
4
|
+
} from 'quidproquo-dynamic-loader';
|
|
5
|
+
export const dynamicModuleLoader = async (serviceName, runtime) => qpqDynamicModuleLoaderForService(serviceName, runtime);
|
|
6
|
+
export const getQpqConfigs = () => qpqConfigs;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dynamicModuleLoader';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dynamicModuleLoader';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './route';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './route';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DynamicModuleLoader, QPQConfig } from 'quidproquo';
|
|
2
|
+
import { ExpressEvent, ExpressEventResponse } from '../types';
|
|
3
|
+
export declare const route: (expressEvent: ExpressEvent, qpqConfig: QPQConfig, dynamicModuleLoader: DynamicModuleLoader) => Promise<ExpressEventResponse>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { askProcessEvent, createRuntime, ErrorTypeEnum, qpqCoreUtils, QpqRuntimeType, qpqWebServerUtils, } from 'quidproquo';
|
|
3
|
+
import { getAwsActionProcessors, getLogger } from 'quidproquo-actionprocessor-awslambda';
|
|
4
|
+
import { getExpressApiEventEventProcessor } from '../getActionProcessor';
|
|
5
|
+
// TODO: Make this a util or something based on server time or something..
|
|
6
|
+
const getDateNow = () => new Date().toISOString();
|
|
7
|
+
const ErrorTypeHttpResponseMap = {
|
|
8
|
+
[ErrorTypeEnum.BadRequest]: 400,
|
|
9
|
+
[ErrorTypeEnum.Unauthorized]: 401,
|
|
10
|
+
[ErrorTypeEnum.PaymentRequired]: 402,
|
|
11
|
+
[ErrorTypeEnum.Forbidden]: 403,
|
|
12
|
+
[ErrorTypeEnum.NotFound]: 404,
|
|
13
|
+
[ErrorTypeEnum.TimeOut]: 408,
|
|
14
|
+
[ErrorTypeEnum.Conflict]: 409,
|
|
15
|
+
[ErrorTypeEnum.UnsupportedMediaType]: 415,
|
|
16
|
+
[ErrorTypeEnum.OutOfResources]: 500,
|
|
17
|
+
[ErrorTypeEnum.GenericError]: 500,
|
|
18
|
+
[ErrorTypeEnum.NotImplemented]: 501,
|
|
19
|
+
[ErrorTypeEnum.NoContent]: 204,
|
|
20
|
+
[ErrorTypeEnum.Invalid]: 422,
|
|
21
|
+
};
|
|
22
|
+
export const route = async (expressEvent, qpqConfig, dynamicModuleLoader) => {
|
|
23
|
+
const serviceName = qpqCoreUtils.getApplicationModuleName(qpqConfig);
|
|
24
|
+
const resolveStory = createRuntime(qpqConfig, {
|
|
25
|
+
depth: 0,
|
|
26
|
+
accessToken: qpqWebServerUtils.getAccessTokenFromHeaders(expressEvent.headers),
|
|
27
|
+
context: {},
|
|
28
|
+
}, async () => ({
|
|
29
|
+
...(await getAwsActionProcessors(qpqConfig, dynamicModuleLoader)),
|
|
30
|
+
...(await getExpressApiEventEventProcessor(qpqConfig, dynamicModuleLoader)),
|
|
31
|
+
}), getDateNow, getLogger(qpqConfig), `${serviceName}::${randomUUID()}`, QpqRuntimeType.API, dynamicModuleLoader, []);
|
|
32
|
+
const result = await resolveStory(askProcessEvent, [expressEvent]);
|
|
33
|
+
// Run the callback
|
|
34
|
+
if (!result.error) {
|
|
35
|
+
const response = {
|
|
36
|
+
statusCode: result.result.statusCode,
|
|
37
|
+
body: result.result.body,
|
|
38
|
+
headers: result.result.headers,
|
|
39
|
+
isBase64Encoded: result.result.isBase64Encoded,
|
|
40
|
+
};
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
const code = ErrorTypeHttpResponseMap[result.error.errorType];
|
|
44
|
+
return {
|
|
45
|
+
statusCode: code || 500,
|
|
46
|
+
body: JSON.stringify(result.error),
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
},
|
|
50
|
+
isBase64Encoded: false,
|
|
51
|
+
};
|
|
52
|
+
};
|
package/lib/esm/getActionProcessor/core/event/express/api/getEventAutoRespondActionProcessor.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { actionResult, EventActionType, } from 'quidproquo-core';
|
|
2
|
+
import { qpqWebServerUtils } from 'quidproquo-webserver';
|
|
3
|
+
const getProcessAutoRespond = (qpqConfig) => async ({ qpqEventRecord, matchResult }) => {
|
|
4
|
+
if (qpqEventRecord.method === 'OPTIONS') {
|
|
5
|
+
return actionResult({
|
|
6
|
+
status: 200,
|
|
7
|
+
isBase64Encoded: false,
|
|
8
|
+
body: '',
|
|
9
|
+
headers: qpqWebServerUtils.getCorsHeaders(qpqConfig, matchResult.config || {}, qpqEventRecord.headers),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return actionResult(null);
|
|
13
|
+
};
|
|
14
|
+
export const getEventAutoRespondActionProcessor = async (qpqConfig) => ({
|
|
15
|
+
[EventActionType.AutoRespond]: getProcessAutoRespond(qpqConfig),
|
|
16
|
+
});
|
package/lib/esm/getActionProcessor/core/event/express/api/getEventGetRecordsActionProcessor.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { actionResult, EventActionType, } from 'quidproquo-core';
|
|
2
|
+
const getProcessGetRecords = (_qpqConfig) => async ({ eventParams: [expressEvent] }) => {
|
|
3
|
+
const path = expressEvent.path || '';
|
|
4
|
+
const internalEventRecord = {
|
|
5
|
+
path,
|
|
6
|
+
query: expressEvent.query,
|
|
7
|
+
body: expressEvent.body,
|
|
8
|
+
headers: expressEvent.headers,
|
|
9
|
+
method: expressEvent.method,
|
|
10
|
+
correlation: expressEvent.correlation,
|
|
11
|
+
sourceIp: expressEvent.ip,
|
|
12
|
+
isBase64Encoded: expressEvent.isBase64Encoded,
|
|
13
|
+
files: expressEvent.files,
|
|
14
|
+
};
|
|
15
|
+
return actionResult([internalEventRecord]);
|
|
16
|
+
};
|
|
17
|
+
export const getEventGetRecordsActionProcessor = async (qpqConfig) => ({
|
|
18
|
+
[EventActionType.GetRecords]: getProcessGetRecords(qpqConfig),
|
|
19
|
+
});
|
package/lib/esm/getActionProcessor/core/event/express/api/getEventGetStorySessionActionProcessor.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* eslint-disable no-void */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
+
import { actionResult, EventActionType, } from 'quidproquo-core';
|
|
4
|
+
const getProcessGetStorySession = (qpqConfig) => async ({ qpqEventRecord, eventParams }) => actionResult(void 0);
|
|
5
|
+
export const getEventGetStorySessionActionProcessor = async (qpqConfig) => ({
|
|
6
|
+
[EventActionType.GetStorySession]: getProcessGetStorySession(qpqConfig),
|
|
7
|
+
});
|
package/lib/esm/getActionProcessor/core/event/express/api/getEventMatchStoryActionProcessor.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { awsLambdaUtils } from 'quidproquo-actionprocessor-awslambda';
|
|
3
|
+
import { actionResult, actionResultError, ErrorTypeEnum, EventActionType, } from 'quidproquo-core';
|
|
4
|
+
import { qpqWebServerUtils, } from 'quidproquo-webserver';
|
|
5
|
+
const getProcessMatchStory = (qpqConfig) => {
|
|
6
|
+
const routes = qpqWebServerUtils.getAllRoutes(qpqConfig);
|
|
7
|
+
return async ({ qpqEventRecord }) => {
|
|
8
|
+
// Sort the routes by string length
|
|
9
|
+
// Note: We may need to filter variable routes out {} as the variables are length independent
|
|
10
|
+
const sortedRoutes = routes
|
|
11
|
+
.filter((r) => r.method === qpqEventRecord.method ||
|
|
12
|
+
qpqEventRecord.method === 'OPTIONS')
|
|
13
|
+
.sort((a, b) => {
|
|
14
|
+
if (a.path.length < b.path.length)
|
|
15
|
+
return -1;
|
|
16
|
+
if (a.path.length > b.path.length)
|
|
17
|
+
return 1;
|
|
18
|
+
return 0;
|
|
19
|
+
});
|
|
20
|
+
// Find the most relevant match
|
|
21
|
+
const matchedRoute = sortedRoutes
|
|
22
|
+
.map((r) => ({
|
|
23
|
+
match: awsLambdaUtils.matchUrl(r.path, qpqEventRecord.path),
|
|
24
|
+
route: r,
|
|
25
|
+
}))
|
|
26
|
+
.find((m) => m.match.didMatch);
|
|
27
|
+
if (!matchedRoute) {
|
|
28
|
+
return actionResultError(ErrorTypeEnum.NotFound, `route not found [${qpqEventRecord.path}] - [${qpqWebServerUtils.getHeaderValue('user-agent', qpqEventRecord.headers)}]`);
|
|
29
|
+
}
|
|
30
|
+
return actionResult({
|
|
31
|
+
runtime: matchedRoute.route.runtime,
|
|
32
|
+
runtimeOptions: matchedRoute.match.params || {},
|
|
33
|
+
// TODO: Make this aware of the API that we are eventing
|
|
34
|
+
config: qpqWebServerUtils.mergeAllRouteOptions('api', matchedRoute.route, qpqConfig),
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export const getEventMatchStoryActionProcessor = async (qpqConfig) => ({
|
|
39
|
+
[EventActionType.MatchStory]: getProcessMatchStory(qpqConfig),
|
|
40
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { actionResult, ErrorTypeEnum, EventActionType, } from 'quidproquo-core';
|
|
2
|
+
import { qpqWebServerUtils } from 'quidproquo-webserver';
|
|
3
|
+
const ErrorTypeHttpResponseMap = {
|
|
4
|
+
[ErrorTypeEnum.BadRequest]: 400,
|
|
5
|
+
[ErrorTypeEnum.Unauthorized]: 401,
|
|
6
|
+
[ErrorTypeEnum.PaymentRequired]: 402,
|
|
7
|
+
[ErrorTypeEnum.Forbidden]: 403,
|
|
8
|
+
[ErrorTypeEnum.NotFound]: 404,
|
|
9
|
+
[ErrorTypeEnum.TimeOut]: 408,
|
|
10
|
+
[ErrorTypeEnum.Conflict]: 409,
|
|
11
|
+
[ErrorTypeEnum.UnsupportedMediaType]: 415,
|
|
12
|
+
[ErrorTypeEnum.OutOfResources]: 500,
|
|
13
|
+
[ErrorTypeEnum.GenericError]: 500,
|
|
14
|
+
[ErrorTypeEnum.NotImplemented]: 501,
|
|
15
|
+
[ErrorTypeEnum.NoContent]: 204,
|
|
16
|
+
[ErrorTypeEnum.Invalid]: 422,
|
|
17
|
+
};
|
|
18
|
+
const getResponseFromErrorResult = (error) => {
|
|
19
|
+
const statusCode = ErrorTypeHttpResponseMap[error.errorType] || 500;
|
|
20
|
+
return qpqWebServerUtils.toJsonEventResponse({
|
|
21
|
+
errorType: error.errorType,
|
|
22
|
+
errorText: error.errorText,
|
|
23
|
+
}, statusCode);
|
|
24
|
+
};
|
|
25
|
+
const getProcessTransformResponseResult = (qpqConfig) =>
|
|
26
|
+
// We might need to JSON.stringify the body.
|
|
27
|
+
async ({ eventParams, qpqEventRecordResponses }) => {
|
|
28
|
+
const [record] = qpqEventRecordResponses;
|
|
29
|
+
const [expressEvent] = eventParams;
|
|
30
|
+
// If we have an error, we need to transform it to a response, otherwise we can just use the record as is
|
|
31
|
+
const successRecord = record.success
|
|
32
|
+
? record.result
|
|
33
|
+
: getResponseFromErrorResult(record.error);
|
|
34
|
+
const recordHeaders = successRecord.headers || {};
|
|
35
|
+
const headers = {
|
|
36
|
+
...qpqWebServerUtils.getCorsHeaders(qpqConfig, {}, expressEvent.headers),
|
|
37
|
+
...recordHeaders,
|
|
38
|
+
};
|
|
39
|
+
return actionResult({
|
|
40
|
+
statusCode: successRecord.status,
|
|
41
|
+
body: successRecord.body || '',
|
|
42
|
+
isBase64Encoded: successRecord.isBase64Encoded,
|
|
43
|
+
headers,
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
export const getEventTransformResponseResultActionProcessor = async (qpqConfig) => ({
|
|
47
|
+
[EventActionType.TransformResponseResult]: getProcessTransformResponseResult(qpqConfig),
|
|
48
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getEventAutoRespondActionProcessor } from './getEventAutoRespondActionProcessor';
|
|
2
|
+
import { getEventGetRecordsActionProcessor } from './getEventGetRecordsActionProcessor';
|
|
3
|
+
import { getEventGetStorySessionActionProcessor } from './getEventGetStorySessionActionProcessor';
|
|
4
|
+
import { getEventMatchStoryActionProcessor } from './getEventMatchStoryActionProcessor';
|
|
5
|
+
import { getEventTransformResponseResultActionProcessor } from './getEventTransformResponseResultActionProcessor';
|
|
6
|
+
export const getExpressApiEventEventProcessor = async (qpqConfig, dynamicModuleLoader) => ({
|
|
7
|
+
...(await getEventAutoRespondActionProcessor(qpqConfig, dynamicModuleLoader)),
|
|
8
|
+
...(await getEventGetRecordsActionProcessor(qpqConfig, dynamicModuleLoader)),
|
|
9
|
+
...(await getEventGetStorySessionActionProcessor(qpqConfig, dynamicModuleLoader)),
|
|
10
|
+
...(await getEventMatchStoryActionProcessor(qpqConfig, dynamicModuleLoader)),
|
|
11
|
+
...(await getEventTransformResponseResultActionProcessor(qpqConfig, dynamicModuleLoader)),
|
|
12
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MatchStoryResult } from 'quidproquo-core';
|
|
2
|
+
import { HTTPEvent, HTTPEventResponse, HttpEventRouteParams, RouteOptions } from 'quidproquo-webserver';
|
|
3
|
+
import { ExpressEvent, ExpressEventResponse } from '../../../../../types/ExpressEvent';
|
|
4
|
+
export type EventInput = [ExpressEvent];
|
|
5
|
+
export type EventOutput = ExpressEventResponse;
|
|
6
|
+
export type InternalEventRecord = HTTPEvent;
|
|
7
|
+
export type InternalEventOutput = HTTPEventResponse;
|
|
8
|
+
export type MatchResult = MatchStoryResult<HttpEventRouteParams, RouteOptions>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './api';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './api';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './express';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './express';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './event';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './event';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './main';
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './main';
|