libmodulor 0.11.1 → 0.13.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/CHANGELOG.md +34 -0
- package/README.md +1 -7
- package/dist/esm/apps/Helper/src/lib/project.js +7 -7
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.nextjs.d.ts +3 -0
- package/dist/esm/index.nextjs.js +3 -0
- package/dist/esm/index.node-hono.d.ts +2 -0
- package/dist/esm/index.node-hono.js +2 -0
- package/dist/esm/products/Helper/index.js +1 -1
- package/dist/esm/std/FSManager.d.ts +1 -1
- package/dist/esm/std/impl/FakeFSManager.d.ts +3 -3
- package/dist/esm/std/impl/NodeFSManager.d.ts +1 -1
- package/dist/esm/std/impl/NodeFSManager.js +2 -2
- package/dist/esm/std/impl/WebFSManager.d.ts +1 -1
- package/dist/esm/target/lib/react/DIContextProvider.js +1 -1
- package/dist/esm/target/lib/react/UCContainer.js +1 -1
- package/dist/esm/target/lib/server/AuthCookieCreator.d.ts +28 -0
- package/dist/esm/target/lib/server/AuthCookieCreator.js +56 -0
- package/dist/esm/target/lib/server/AuthenticationChecker.d.ts +2 -2
- package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +4 -3
- package/dist/esm/target/lib/server/ServerBooter.d.ts +5 -3
- package/dist/esm/target/lib/server/ServerBooter.js +29 -22
- package/dist/esm/target/lib/server/ServerRequestHandler.d.ts +71 -0
- package/dist/esm/target/lib/server/ServerRequestHandler.js +202 -0
- package/dist/esm/target/lib/server/ServerSSLCertLoader.d.ts +18 -0
- package/dist/esm/target/lib/server/ServerSSLCertLoader.js +45 -0
- package/dist/esm/target/lib/server-node/stop.d.ts +2 -0
- package/dist/esm/target/lib/server-node/stop.js +18 -0
- package/dist/esm/target/lib/server-node/types.d.ts +3 -0
- package/dist/esm/target/lib/server-node/types.js +1 -0
- package/dist/esm/target/nextjs-server/NextJSAPIRouteHandler.d.ts +23 -0
- package/dist/esm/target/nextjs-server/NextJSAPIRouteHandler.js +82 -0
- package/dist/esm/target/nextjs-server/NextJSServerManager.d.ts +13 -0
- package/dist/esm/target/nextjs-server/NextJSServerManager.js +34 -0
- package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +10 -16
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +94 -81
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +2 -1
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +35 -0
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +169 -0
- package/dist/esm/testing/AppTester.js +2 -2
- package/dist/esm/testing/impl/newNodeAppTester.js +1 -1
- package/dist/esm/uc/impl/SimpleUCManager.d.ts +2 -2
- package/dist/esm/uc/utils/ucHTTPContract.js +1 -1
- package/dist/esm/uc/workers/UCExecChecker.d.ts +2 -2
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +9 -6
- package/dist/esm/utils/http/HTTPRequestBuilder.js +3 -3
- package/dist/esm/utils/http/form-data.d.ts +4 -0
- package/dist/esm/utils/http/form-data.js +20 -0
- package/dist/esm/utils/http/json.d.ts +3 -0
- package/dist/esm/utils/http/json.js +3 -0
- package/dist/esm/utils/http/query-params.d.ts +3 -0
- package/dist/esm/utils/http/query-params.js +20 -0
- package/dist/esm/utils/index.d.ts +3 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/ioc/bindNodeCLI.js +1 -1
- package/dist/esm/utils/ioc/bindNodeCore.js +1 -1
- package/dist/esm/utils/ioc/bindProduct.js +2 -2
- package/dist/esm/utils/ioc/bindProvider.js +1 -1
- package/dist/esm/utils/ioc/bindWeb.js +1 -1
- package/dist/esm/utils/ioc/container.d.ts +2 -2
- package/dist/esm/utils/ioc/container.js +2 -3
- package/dist/esm/utils/ioc/types.d.ts +2 -2
- package/package.json +21 -11
|
@@ -16,42 +16,29 @@ import cookieParser from 'cookie-parser';
|
|
|
16
16
|
import express, {} from 'express';
|
|
17
17
|
import fileUpload from 'express-fileupload';
|
|
18
18
|
import { inject, injectable } from 'inversify';
|
|
19
|
+
import { stop } from '../lib/server-node/stop.js';
|
|
19
20
|
import { EntrypointsBuilder } from '../lib/server/EntrypointsBuilder.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { ServerRequestHandler, } from '../lib/server/ServerRequestHandler.js';
|
|
22
|
+
import { ServerSSLCertLoader } from '../lib/server/ServerSSLCertLoader.js';
|
|
22
23
|
import { HelmetMiddlewareBuilder } from './middlewares/HelmetMiddlewareBuilder.js';
|
|
23
|
-
import { PublicApiKeyCheckerMiddlewareBuilder } from './middlewares/PublicApiKeyCheckerMiddlewareBuilder.js';
|
|
24
|
-
import { RequestCheckerMiddlewareBuilder } from './middlewares/RequestCheckerMiddlewareBuilder.js';
|
|
25
|
-
import { RequestHandlerMiddlewareBuilder } from './middlewares/RequestHandlerMiddlewareBuilder.js';
|
|
26
|
-
import { RequestLoggerMiddlewareBuilder } from './middlewares/RequestLoggerMiddlewareBuilder.js';
|
|
27
24
|
let NodeExpressServerManager = class NodeExpressServerManager {
|
|
28
|
-
authenticationCheckerMB;
|
|
29
25
|
entrypointsBuilder;
|
|
30
26
|
environmentManager;
|
|
31
|
-
errorMB;
|
|
32
|
-
fsManager;
|
|
33
27
|
helmetMB;
|
|
34
28
|
logger;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
requestHandlerMB;
|
|
38
|
-
requestLoggerMB;
|
|
29
|
+
serverRequestHandler;
|
|
30
|
+
serverSSLCertLoader;
|
|
39
31
|
settingsManager;
|
|
40
32
|
ucManager;
|
|
41
33
|
runtime;
|
|
42
34
|
server;
|
|
43
|
-
constructor(
|
|
44
|
-
this.authenticationCheckerMB = authenticationCheckerMB;
|
|
35
|
+
constructor(entrypointsBuilder, environmentManager, helmetMB, logger, serverRequestHandler, serverSSLCertLoader, settingsManager, ucManager) {
|
|
45
36
|
this.entrypointsBuilder = entrypointsBuilder;
|
|
46
37
|
this.environmentManager = environmentManager;
|
|
47
|
-
this.errorMB = errorMB;
|
|
48
|
-
this.fsManager = fsManager;
|
|
49
38
|
this.helmetMB = helmetMB;
|
|
50
39
|
this.logger = logger;
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
this.requestHandlerMB = requestHandlerMB;
|
|
54
|
-
this.requestLoggerMB = requestLoggerMB;
|
|
40
|
+
this.serverRequestHandler = serverRequestHandler;
|
|
41
|
+
this.serverSSLCertLoader = serverSSLCertLoader;
|
|
55
42
|
this.settingsManager = settingsManager;
|
|
56
43
|
this.ucManager = ucManager;
|
|
57
44
|
}
|
|
@@ -60,8 +47,6 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
60
47
|
logger_level: this.settingsManager.get()('logger_level'),
|
|
61
48
|
server_binding_host: this.settingsManager.get()('server_binding_host'),
|
|
62
49
|
server_binding_port: this.settingsManager.get()('server_binding_port'),
|
|
63
|
-
server_ssl_fullchain_path: this.settingsManager.get()('server_ssl_fullchain_path'),
|
|
64
|
-
server_ssl_key_path: this.settingsManager.get()('server_ssl_key_path'),
|
|
65
50
|
server_tmp_path: this.settingsManager.get()('server_tmp_path'),
|
|
66
51
|
};
|
|
67
52
|
}
|
|
@@ -88,29 +73,29 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
88
73
|
this.runtime.use(express.json());
|
|
89
74
|
this.runtime.use(express.urlencoded({ extended: true }));
|
|
90
75
|
this.runtime.use(cookieParser());
|
|
91
|
-
this.runtime.use(this.requestLoggerMB.exec({}));
|
|
92
|
-
this.runtime.use(this.requestCheckerMB.exec({}));
|
|
93
76
|
await this.createServer();
|
|
94
77
|
}
|
|
95
78
|
async mount(appManifest, ucd, contract) {
|
|
96
|
-
const { sec } = ucd;
|
|
97
79
|
const { envelope, method, path, pathAliases } = contract;
|
|
98
80
|
const httpMethod = method.toLowerCase();
|
|
99
|
-
const
|
|
100
|
-
this.
|
|
101
|
-
checkType: sec?.publicApiKeyCheckType,
|
|
102
|
-
}),
|
|
103
|
-
this.authenticationCheckerMB.exec({ appManifest, ucd }),
|
|
104
|
-
this.requestHandlerMB.exec({
|
|
81
|
+
const handler = async (req, res) => {
|
|
82
|
+
const { body, status } = await this.serverRequestHandler.exec({
|
|
105
83
|
appManifest,
|
|
106
84
|
envelope,
|
|
85
|
+
req: this.toReq(req),
|
|
86
|
+
res: this.toRes(res),
|
|
107
87
|
ucd,
|
|
108
88
|
ucManager: this.ucManager,
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
|
|
89
|
+
});
|
|
90
|
+
if (!body) {
|
|
91
|
+
res.status(status).send();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
res.status(status).send(body);
|
|
95
|
+
};
|
|
96
|
+
this.runtime[httpMethod](path, handler);
|
|
112
97
|
for (const pathAlias of pathAliases) {
|
|
113
|
-
this.runtime[httpMethod](pathAlias,
|
|
98
|
+
this.runtime[httpMethod](pathAlias, handler);
|
|
114
99
|
}
|
|
115
100
|
}
|
|
116
101
|
async mountStaticDir(dirPath) {
|
|
@@ -124,26 +109,10 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
124
109
|
});
|
|
125
110
|
}
|
|
126
111
|
async stop() {
|
|
127
|
-
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
// As stated in the docs of `close`, only awaiting `.close` is not enough to make sure all the connections are closed.
|
|
131
|
-
// Hence the wrapping in a promise, where the callback is called when the 'close' event is emitted.
|
|
132
|
-
return new Promise((resolve, reject) => {
|
|
133
|
-
if (!this.server) {
|
|
134
|
-
return resolve();
|
|
135
|
-
}
|
|
136
|
-
this.server.close((err) => {
|
|
137
|
-
if (err) {
|
|
138
|
-
return reject(err);
|
|
139
|
-
}
|
|
140
|
-
resolve();
|
|
141
|
-
});
|
|
142
|
-
});
|
|
112
|
+
await stop(this.server);
|
|
143
113
|
}
|
|
144
114
|
async warmUp() {
|
|
145
|
-
//
|
|
146
|
-
this.runtime.use(this.errorMB.exec({}));
|
|
115
|
+
// Nothing to do
|
|
147
116
|
}
|
|
148
117
|
async createServer() {
|
|
149
118
|
const port = this.s().server_binding_port;
|
|
@@ -153,37 +122,81 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
153
122
|
return;
|
|
154
123
|
}
|
|
155
124
|
this.logger.info('Creating HTTPS server', { port });
|
|
156
|
-
const
|
|
157
|
-
const keyPath = this.s().server_ssl_key_path;
|
|
158
|
-
if (!fullchainPath || !keyPath) {
|
|
159
|
-
throw new Error('You must provide server_ssl_fullchain_path and server_ssl_key_path to start on secure port 443');
|
|
160
|
-
}
|
|
161
|
-
const credentials = {
|
|
162
|
-
cert: await this.fsManager.cat(fullchainPath),
|
|
163
|
-
key: await this.fsManager.cat(keyPath),
|
|
164
|
-
};
|
|
125
|
+
const credentials = await this.serverSSLCertLoader.exec(undefined);
|
|
165
126
|
this.server = https.createServer(credentials, this.runtime);
|
|
166
127
|
}
|
|
128
|
+
toFile(f) {
|
|
129
|
+
return {
|
|
130
|
+
name: f.name,
|
|
131
|
+
path: f.tempFilePath,
|
|
132
|
+
type: f.mimetype,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
toReq(req) {
|
|
136
|
+
return {
|
|
137
|
+
bodyFromFormData: async () => {
|
|
138
|
+
// Since express v5, if the request contains only a file, the `req.body` returns `undefined`
|
|
139
|
+
const input = req.body ?? {};
|
|
140
|
+
// files is present when using express-fileupload
|
|
141
|
+
if ('files' in req && req.files) {
|
|
142
|
+
for (const [field, value] of Object.entries(req.files)) {
|
|
143
|
+
input[field] = Array.isArray(value)
|
|
144
|
+
? value.map(this.toFile)
|
|
145
|
+
: this.toFile(value);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const [k, v] of Object.entries(input)) {
|
|
149
|
+
const isMultiple = k.endsWith('[]'); // e.g. 'tags[]': 'Electronic'
|
|
150
|
+
const key = isMultiple ? k.replaceAll('[]', '') : k;
|
|
151
|
+
if (isMultiple) {
|
|
152
|
+
input[key] = Array.isArray(v) ? v : [v];
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
input[key] = v;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return input;
|
|
159
|
+
},
|
|
160
|
+
bodyFromJSON: async () => req.body,
|
|
161
|
+
bodyFromQueryParams: async () => req.query,
|
|
162
|
+
bodyRaw: req.body,
|
|
163
|
+
cookie: (name) => req.cookies[name],
|
|
164
|
+
header: async (name) => {
|
|
165
|
+
const h = req.headers[name.toLowerCase()];
|
|
166
|
+
if (Array.isArray(h)) {
|
|
167
|
+
this.logger.warn(`Multiple headers found for ${name}. Returning the first one.`);
|
|
168
|
+
return h[0];
|
|
169
|
+
}
|
|
170
|
+
return h;
|
|
171
|
+
},
|
|
172
|
+
method: req.method,
|
|
173
|
+
secure: req.secure,
|
|
174
|
+
url: req.url,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
toRes(res) {
|
|
178
|
+
return {
|
|
179
|
+
clearCookie: async (name) => {
|
|
180
|
+
res.clearCookie(name);
|
|
181
|
+
},
|
|
182
|
+
redirect: async (location) => res.redirect(location),
|
|
183
|
+
setCookie: async ({ name, opts, val }) => {
|
|
184
|
+
res.cookie(name, val, opts);
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
167
188
|
};
|
|
168
189
|
NodeExpressServerManager = __decorate([
|
|
169
190
|
injectable(),
|
|
170
|
-
__param(0, inject(
|
|
171
|
-
__param(1, inject(
|
|
172
|
-
__param(2, inject(
|
|
173
|
-
__param(3, inject(
|
|
174
|
-
__param(4, inject(
|
|
175
|
-
__param(5, inject(
|
|
176
|
-
__param(6, inject('
|
|
177
|
-
__param(7, inject(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
__param(10, inject(RequestLoggerMiddlewareBuilder)),
|
|
181
|
-
__param(11, inject('SettingsManager')),
|
|
182
|
-
__param(12, inject('UCManager')),
|
|
183
|
-
__metadata("design:paramtypes", [AuthenticationCheckerMiddlewareBuilder,
|
|
184
|
-
EntrypointsBuilder, Object, ErrorMiddlewareBuilder, Object, HelmetMiddlewareBuilder, Object, PublicApiKeyCheckerMiddlewareBuilder,
|
|
185
|
-
RequestCheckerMiddlewareBuilder,
|
|
186
|
-
RequestHandlerMiddlewareBuilder,
|
|
187
|
-
RequestLoggerMiddlewareBuilder, Object, Object])
|
|
191
|
+
__param(0, inject(EntrypointsBuilder)),
|
|
192
|
+
__param(1, inject('EnvironmentManager')),
|
|
193
|
+
__param(2, inject(HelmetMiddlewareBuilder)),
|
|
194
|
+
__param(3, inject('Logger')),
|
|
195
|
+
__param(4, inject(ServerRequestHandler)),
|
|
196
|
+
__param(5, inject(ServerSSLCertLoader)),
|
|
197
|
+
__param(6, inject('SettingsManager')),
|
|
198
|
+
__param(7, inject('UCManager')),
|
|
199
|
+
__metadata("design:paramtypes", [EntrypointsBuilder, Object, HelmetMiddlewareBuilder, Object, ServerRequestHandler,
|
|
200
|
+
ServerSSLCertLoader, Object, Object])
|
|
188
201
|
], NodeExpressServerManager);
|
|
189
202
|
export { NodeExpressServerManager };
|
|
@@ -78,7 +78,8 @@ let RequestHandlerMiddlewareBuilder = class RequestHandlerMiddlewareBuilder {
|
|
|
78
78
|
fillUCFromReq(req, envelope, uc) {
|
|
79
79
|
switch (envelope) {
|
|
80
80
|
case 'form-data': {
|
|
81
|
-
|
|
81
|
+
// Since express v5, if the request contains only a file, the `req.body` returns `undefined`
|
|
82
|
+
const input = req.body ?? {};
|
|
82
83
|
// files is present when using express-fileupload
|
|
83
84
|
if ('files' in req && req.files) {
|
|
84
85
|
for (const [field, value] of Object.entries(req.files)) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { AppManifest } from '../../app/index.js';
|
|
3
|
+
import type { DirPath } from '../../dt/index.js';
|
|
4
|
+
import type { Configurable, EnvironmentManager, Logger, SettingsManager } from '../../std/index.js';
|
|
5
|
+
import type { UCDef, UCHTTPContract, UCInput, UCManager, UCOPIBase } from '../../uc/index.js';
|
|
6
|
+
import { EntrypointsBuilder } from '../lib/server/EntrypointsBuilder.js';
|
|
7
|
+
import type { ServerManager, ServerManagerSettings } from '../lib/server/ServerManager.js';
|
|
8
|
+
import { ServerRequestHandler } from '../lib/server/ServerRequestHandler.js';
|
|
9
|
+
import { ServerSSLCertLoader } from '../lib/server/ServerSSLCertLoader.js';
|
|
10
|
+
type S = Pick<ServerManagerSettings, 'server_binding_host' | 'server_binding_port'>;
|
|
11
|
+
export declare class NodeHonoServerManager implements Configurable<S>, ServerManager {
|
|
12
|
+
private entrypointsBuilder;
|
|
13
|
+
protected environmentManager: EnvironmentManager;
|
|
14
|
+
private logger;
|
|
15
|
+
private serverRequestHandler;
|
|
16
|
+
private serverSSLCertLoader;
|
|
17
|
+
private settingsManager;
|
|
18
|
+
private ucManager;
|
|
19
|
+
protected runtime: Hono;
|
|
20
|
+
private server;
|
|
21
|
+
constructor(entrypointsBuilder: EntrypointsBuilder, environmentManager: EnvironmentManager, logger: Logger, serverRequestHandler: ServerRequestHandler, serverSSLCertLoader: ServerSSLCertLoader, settingsManager: SettingsManager<S>, ucManager: UCManager);
|
|
22
|
+
s(): S;
|
|
23
|
+
getRuntime(): Hono;
|
|
24
|
+
overrideUCManager(ucManager: UCManager): void;
|
|
25
|
+
init(): Promise<void>;
|
|
26
|
+
mount<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: AppManifest, ucd: UCDef<I, OPI0, OPI1>, contract: UCHTTPContract): Promise<void>;
|
|
27
|
+
mountStaticDir(dirPath: DirPath): Promise<void>;
|
|
28
|
+
start(): Promise<void>;
|
|
29
|
+
stop(): Promise<void>;
|
|
30
|
+
warmUp(): Promise<void>;
|
|
31
|
+
private createServer;
|
|
32
|
+
private toReq;
|
|
33
|
+
private toRes;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import http from 'node:http';
|
|
14
|
+
import https from 'node:https';
|
|
15
|
+
import { createAdaptorServer, } from '@hono/node-server';
|
|
16
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
17
|
+
import { Hono } from 'hono';
|
|
18
|
+
import { deleteCookie, getCookie, setCookie } from 'hono/cookie';
|
|
19
|
+
import { logger } from 'hono/logger';
|
|
20
|
+
import { secureHeaders } from 'hono/secure-headers';
|
|
21
|
+
import { inject, injectable } from 'inversify';
|
|
22
|
+
import { fromFormData } from '../../utils/index.js';
|
|
23
|
+
import { stop } from '../lib/server-node/stop.js';
|
|
24
|
+
import { EntrypointsBuilder } from '../lib/server/EntrypointsBuilder.js';
|
|
25
|
+
import { ServerRequestHandler, } from '../lib/server/ServerRequestHandler.js';
|
|
26
|
+
import { ServerSSLCertLoader } from '../lib/server/ServerSSLCertLoader.js';
|
|
27
|
+
let NodeHonoServerManager = class NodeHonoServerManager {
|
|
28
|
+
entrypointsBuilder;
|
|
29
|
+
environmentManager;
|
|
30
|
+
logger;
|
|
31
|
+
serverRequestHandler;
|
|
32
|
+
serverSSLCertLoader;
|
|
33
|
+
settingsManager;
|
|
34
|
+
ucManager;
|
|
35
|
+
runtime;
|
|
36
|
+
server;
|
|
37
|
+
constructor(entrypointsBuilder, environmentManager, logger, serverRequestHandler, serverSSLCertLoader, settingsManager, ucManager) {
|
|
38
|
+
this.entrypointsBuilder = entrypointsBuilder;
|
|
39
|
+
this.environmentManager = environmentManager;
|
|
40
|
+
this.logger = logger;
|
|
41
|
+
this.serverRequestHandler = serverRequestHandler;
|
|
42
|
+
this.serverSSLCertLoader = serverSSLCertLoader;
|
|
43
|
+
this.settingsManager = settingsManager;
|
|
44
|
+
this.ucManager = ucManager;
|
|
45
|
+
}
|
|
46
|
+
s() {
|
|
47
|
+
return {
|
|
48
|
+
server_binding_host: this.settingsManager.get()('server_binding_host'),
|
|
49
|
+
server_binding_port: this.settingsManager.get()('server_binding_port'),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
getRuntime() {
|
|
53
|
+
if (this.environmentManager.isProd()) {
|
|
54
|
+
throw new Error('Do not use getRuntime() in production !');
|
|
55
|
+
}
|
|
56
|
+
return this.runtime;
|
|
57
|
+
}
|
|
58
|
+
overrideUCManager(ucManager) {
|
|
59
|
+
this.ucManager = ucManager;
|
|
60
|
+
}
|
|
61
|
+
async init() {
|
|
62
|
+
this.runtime = new Hono();
|
|
63
|
+
this.runtime.use(secureHeaders());
|
|
64
|
+
this.runtime.use(logger());
|
|
65
|
+
this.runtime.notFound((c) => {
|
|
66
|
+
return c.json({}, 404);
|
|
67
|
+
});
|
|
68
|
+
await this.createServer();
|
|
69
|
+
}
|
|
70
|
+
async mount(appManifest, ucd, contract) {
|
|
71
|
+
const { envelope, method, path, pathAliases } = contract;
|
|
72
|
+
const httpMethod = method.toLowerCase();
|
|
73
|
+
if (httpMethod === 'connect' ||
|
|
74
|
+
httpMethod === 'head' ||
|
|
75
|
+
httpMethod === 'trace') {
|
|
76
|
+
throw new Error(`Unsupported HTTP method : ${httpMethod}`);
|
|
77
|
+
}
|
|
78
|
+
const handler = async (c) => {
|
|
79
|
+
const { body, status } = await this.serverRequestHandler.exec({
|
|
80
|
+
appManifest,
|
|
81
|
+
envelope,
|
|
82
|
+
req: this.toReq(c),
|
|
83
|
+
res: this.toRes(c),
|
|
84
|
+
ucd,
|
|
85
|
+
ucManager: this.ucManager,
|
|
86
|
+
});
|
|
87
|
+
if (!body) {
|
|
88
|
+
return c.newResponse(null, status);
|
|
89
|
+
}
|
|
90
|
+
return c.json(body, status);
|
|
91
|
+
};
|
|
92
|
+
this.runtime[httpMethod](path, handler);
|
|
93
|
+
for (const pathAlias of pathAliases) {
|
|
94
|
+
this.runtime[httpMethod](pathAlias, handler);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async mountStaticDir(dirPath) {
|
|
98
|
+
this.runtime.use(serveStatic({ root: dirPath }));
|
|
99
|
+
}
|
|
100
|
+
async start() {
|
|
101
|
+
const host = this.s().server_binding_host;
|
|
102
|
+
const port = this.s().server_binding_port;
|
|
103
|
+
this.server.listen(port, host, () => {
|
|
104
|
+
this.logger.info(`Listening on ${this.entrypointsBuilder.exec().http}`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async stop() {
|
|
108
|
+
await stop(this.server);
|
|
109
|
+
}
|
|
110
|
+
async warmUp() {
|
|
111
|
+
// Nothing to do
|
|
112
|
+
}
|
|
113
|
+
async createServer() {
|
|
114
|
+
const host = this.s().server_binding_host;
|
|
115
|
+
const port = this.s().server_binding_port;
|
|
116
|
+
const opts = {
|
|
117
|
+
fetch: this.runtime.fetch,
|
|
118
|
+
hostname: host,
|
|
119
|
+
port,
|
|
120
|
+
};
|
|
121
|
+
if (port !== 443) {
|
|
122
|
+
this.logger.info('Creating HTTP server', { port });
|
|
123
|
+
opts.createServer = http.createServer;
|
|
124
|
+
this.server = createAdaptorServer(opts);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
this.logger.info('Creating HTTPS server', { port });
|
|
128
|
+
opts.createServer = https.createServer;
|
|
129
|
+
opts.serverOptions = await this.serverSSLCertLoader.exec(undefined);
|
|
130
|
+
this.server = createAdaptorServer(opts);
|
|
131
|
+
}
|
|
132
|
+
toReq(c) {
|
|
133
|
+
return {
|
|
134
|
+
bodyFromFormData: async () => fromFormData(await c.req.formData()),
|
|
135
|
+
bodyFromJSON: () => c.req.json(),
|
|
136
|
+
bodyFromQueryParams: async () => c.req.queries(),
|
|
137
|
+
bodyRaw: c.req.raw,
|
|
138
|
+
cookie: async (name) => getCookie(c, name),
|
|
139
|
+
header: async (name) => c.req.header(name),
|
|
140
|
+
method: c.req.method,
|
|
141
|
+
secure: c.req.url.startsWith('https://'),
|
|
142
|
+
url: c.req.url,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
toRes(c) {
|
|
146
|
+
return {
|
|
147
|
+
clearCookie: async (name) => {
|
|
148
|
+
deleteCookie(c, name);
|
|
149
|
+
},
|
|
150
|
+
redirect: async (location) => {
|
|
151
|
+
c.redirect(location);
|
|
152
|
+
},
|
|
153
|
+
setCookie: async ({ name, opts, val }) => setCookie(c, name, val, opts),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
NodeHonoServerManager = __decorate([
|
|
158
|
+
injectable(),
|
|
159
|
+
__param(0, inject(EntrypointsBuilder)),
|
|
160
|
+
__param(1, inject('EnvironmentManager')),
|
|
161
|
+
__param(2, inject('Logger')),
|
|
162
|
+
__param(3, inject(ServerRequestHandler)),
|
|
163
|
+
__param(4, inject(ServerSSLCertLoader)),
|
|
164
|
+
__param(5, inject('SettingsManager')),
|
|
165
|
+
__param(6, inject('UCManager')),
|
|
166
|
+
__metadata("design:paramtypes", [EntrypointsBuilder, Object, Object, ServerRequestHandler,
|
|
167
|
+
ServerSSLCertLoader, Object, Object])
|
|
168
|
+
], NodeHonoServerManager);
|
|
169
|
+
export { NodeHonoServerManager };
|
|
@@ -307,13 +307,13 @@ let AppTester = class AppTester {
|
|
|
307
307
|
...appI18n[l],
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
|
-
container.rebind('I18n').toConstantValue(productI18n);
|
|
310
|
+
(await container.rebind('I18n')).toConstantValue(productI18n);
|
|
311
311
|
}
|
|
312
312
|
async bindServerClientSettings(serverClientSettings) {
|
|
313
313
|
const { container } = this.ctx;
|
|
314
314
|
const opts = optsAllSet(this.ctx.opts);
|
|
315
315
|
const existingSettings = container.get('Settings');
|
|
316
|
-
container.rebind('Settings').toConstantValue({
|
|
316
|
+
(await container.rebind('Settings')).toConstantValue({
|
|
317
317
|
...existingSettings,
|
|
318
318
|
...serverClientSettings,
|
|
319
319
|
logger_level: opts.logger_level,
|
|
@@ -41,7 +41,7 @@ export async function newNodeAppTester(serverPortRangeStart, idx, args) {
|
|
|
41
41
|
container
|
|
42
42
|
.bind('UCDefASTParser')
|
|
43
43
|
.to(TypeScriptLibUCDefASTParser);
|
|
44
|
-
const tester = container.
|
|
44
|
+
const tester = container.get(AppTester);
|
|
45
45
|
const jwtManager = container.get('JWTManager');
|
|
46
46
|
const apiKey = settings.server_private_api_key_entries[0];
|
|
47
47
|
const [basicAuth] = Object.entries(settings.server_basic_auth_entries);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Provider } from 'inversify';
|
|
2
2
|
import type { ClockManager, CryptoManager, Logger } from '../../std/index.js';
|
|
3
3
|
import type { UC } from '../UC.js';
|
|
4
4
|
import type { UCClientConfirmManager } from '../client.js';
|
|
@@ -26,7 +26,7 @@ export declare class SimpleUCManager implements UCManager {
|
|
|
26
26
|
private ucInitProvider;
|
|
27
27
|
private ucMainProvider;
|
|
28
28
|
private tx?;
|
|
29
|
-
constructor(ucClientConfirmManager: UCClientConfirmManager, clockManager: ClockManager, cryptoManager: CryptoManager, logger: Logger, ucDataStore: UCDataStore, ucExecChecker: UCExecChecker, ucInputFilesProcessor: UCInputFilesProcessor, ucInputValidator: UCInputValidator, ucInitProvider:
|
|
29
|
+
constructor(ucClientConfirmManager: UCClientConfirmManager, clockManager: ClockManager, cryptoManager: CryptoManager, logger: Logger, ucDataStore: UCDataStore, ucExecChecker: UCExecChecker, ucInputFilesProcessor: UCInputFilesProcessor, ucInputValidator: UCInputValidator, ucInitProvider: Provider<UCInit>, ucMainProvider: Provider<UCMain>);
|
|
30
30
|
commitTx(): Promise<void>;
|
|
31
31
|
confirmClient<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<boolean>;
|
|
32
32
|
execClient<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): Promise<UCOutputReader<I, OPI0, OPI1>>;
|
|
@@ -7,7 +7,7 @@ const ACTION_HTTP_METHOD_MAPPING = {
|
|
|
7
7
|
Update: 'PUT',
|
|
8
8
|
View: 'GET',
|
|
9
9
|
};
|
|
10
|
-
const METHODS_WITH_NO_BODY = ['GET'];
|
|
10
|
+
const METHODS_WITH_NO_BODY = ['GET', 'HEAD'];
|
|
11
11
|
export function ucHTTPContract(uc, pathPrefix = '/api/v1') {
|
|
12
12
|
const { ext, metadata } = uc.def;
|
|
13
13
|
const { action } = metadata;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Provider } from 'inversify';
|
|
2
2
|
import type { ProductManifest } from '../../product/index.js';
|
|
3
3
|
import type { Configurable, SettingsManager, Worker } from '../../std/index.js';
|
|
4
4
|
import type { UC } from '../UC.js';
|
|
@@ -17,7 +17,7 @@ export declare class UCExecChecker implements Configurable<S>, Worker<Input, Pro
|
|
|
17
17
|
private productManifest;
|
|
18
18
|
private settingsManager;
|
|
19
19
|
private ucPolicyProvider;
|
|
20
|
-
constructor(productManifest: ProductManifest, settingsManager: SettingsManager<S>, ucPolicyProvider:
|
|
20
|
+
constructor(productManifest: ProductManifest, settingsManager: SettingsManager<S>, ucPolicyProvider: Provider<UCPolicy>);
|
|
21
21
|
s(): S;
|
|
22
22
|
exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ lifecycle, uc }: Input<I, OPI0, OPI1>): Promise<Output>;
|
|
23
23
|
}
|
|
@@ -61,12 +61,15 @@ let UCInputFilesProcessor = class UCInputFilesProcessor {
|
|
|
61
61
|
const prefix = this.clockManager.nowToKey();
|
|
62
62
|
const fileName = `${prefix}-${this.cryptoManager.randomUUID()}.${extension}`; // => 20230110143732-155eb8d3-9af5-430e-b856-248007859df1.jpg
|
|
63
63
|
const fileNameRef = `${this.s().uc_file_ref_prefix}${fileName}`; // => $ref:20230110143732-155eb8d3-9af5-430e-b856-248007859df1.jpg
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
const destPath = this.fsManager.path(this.s().uc_files_directory_path, fileName); // => /path/to/files/20230110143732-155eb8d3-9af5-430e-b856-248007859df1.jpg
|
|
65
|
+
if (file instanceof File) {
|
|
66
|
+
await this.fsManager.touch(destPath, await file.arrayBuffer());
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const { path } = file;
|
|
70
|
+
await this.fsManager.cp(path, destPath);
|
|
71
|
+
await this.fsManager.rm(path);
|
|
72
|
+
}
|
|
70
73
|
return fileNameRef;
|
|
71
74
|
}
|
|
72
75
|
};
|
|
@@ -11,9 +11,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { inject, injectable } from 'inversify';
|
|
14
|
-
import { toFormData } from './
|
|
15
|
-
import { toJSON } from './
|
|
16
|
-
import { toQueryParams } from './
|
|
14
|
+
import { toFormData } from './form-data.js';
|
|
15
|
+
import { toJSON } from './json.js';
|
|
16
|
+
import { toQueryParams } from './query-params.js';
|
|
17
17
|
let HTTPRequestBuilder = class HTTPRequestBuilder {
|
|
18
18
|
formDataBuilder;
|
|
19
19
|
constructor(formDataBuilder) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FormDataBuilder } from '../../std/index.js';
|
|
2
|
+
import type { HTTPReqData } from './types.js';
|
|
3
|
+
export declare function fromFormData<T extends HTTPReqData>(fd: FormData): Promise<T>;
|
|
4
|
+
export declare function toFormData<T extends HTTPReqData>(data: T | undefined | null, fd: FormData, formDataBuilder: FormDataBuilder): Promise<void>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { appendData } from './appendData.js';
|
|
2
|
+
export async function fromFormData(fd) {
|
|
3
|
+
// biome-ignore lint/suspicious/noExplicitAny: can be anything
|
|
4
|
+
const data = {};
|
|
5
|
+
for (const [k, v] of fd) {
|
|
6
|
+
const isMultiple = k.endsWith('[]'); // e.g. 'tags[]': 'Electronic'
|
|
7
|
+
const key = isMultiple ? k.replaceAll('[]', '') : k;
|
|
8
|
+
const value = data[key];
|
|
9
|
+
if (value === undefined) {
|
|
10
|
+
data[key] = isMultiple ? [v] : v;
|
|
11
|
+
}
|
|
12
|
+
else if (Array.isArray(value)) {
|
|
13
|
+
value.push(v);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
export async function toFormData(data, fd, formDataBuilder) {
|
|
19
|
+
await appendData(data, (k, v) => formDataBuilder.append(fd, k, v));
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { appendData } from './appendData.js';
|
|
2
|
+
export async function fromQueryParams(url) {
|
|
3
|
+
// biome-ignore lint/suspicious/noExplicitAny: can be anything
|
|
4
|
+
const data = {};
|
|
5
|
+
for (const [k, v] of url.searchParams) {
|
|
6
|
+
const isMultiple = k.endsWith('[]');
|
|
7
|
+
const key = isMultiple ? k.replaceAll('[]', '') : k;
|
|
8
|
+
const value = data[key];
|
|
9
|
+
if (value === undefined) {
|
|
10
|
+
data[key] = isMultiple ? [v] : v;
|
|
11
|
+
}
|
|
12
|
+
else if (Array.isArray(value)) {
|
|
13
|
+
value.push(v);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
export async function toQueryParams(data, url) {
|
|
19
|
+
await appendData(data, async (k, v) => url.searchParams.append(k, v));
|
|
20
|
+
}
|
|
@@ -2,7 +2,10 @@ export { sleep } from './async/sleep.js';
|
|
|
2
2
|
export type { Clearable } from './concerns/Clearable.js';
|
|
3
3
|
export type { Initializable } from './concerns/Initializable.js';
|
|
4
4
|
export type { SrcImporter } from './esm/srcImporter.js';
|
|
5
|
+
export { fromFormData, toFormData } from './http/form-data.js';
|
|
5
6
|
export { HTTPRequestBuilder } from './http/HTTPRequestBuilder.js';
|
|
7
|
+
export { toJSON } from './http/json.js';
|
|
8
|
+
export { fromQueryParams, toQueryParams } from './http/query-params.js';
|
|
6
9
|
export type { HTTPDataEnvelope, HTTPReqData } from './http/types.js';
|
|
7
10
|
export { bindProvider } from './ioc/bindProvider.js';
|
|
8
11
|
export { CONTAINER_OPTS } from './ioc/container.js';
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { sleep } from './async/sleep.js';
|
|
2
|
+
export { fromFormData, toFormData } from './http/form-data.js';
|
|
2
3
|
export { HTTPRequestBuilder } from './http/HTTPRequestBuilder.js';
|
|
4
|
+
export { toJSON } from './http/json.js';
|
|
5
|
+
export { fromQueryParams, toQueryParams } from './http/query-params.js';
|
|
3
6
|
export { bindProvider } from './ioc/bindProvider.js';
|
|
4
7
|
export { CONTAINER_OPTS } from './ioc/container.js';
|
|
5
8
|
export { fmt as fmtNumber } from './numbers/fmt.js';
|