libmodulor 0.11.1 → 0.12.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 +24 -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/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/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 +14 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.12.0 (2025-04-13)
|
|
4
|
+
|
|
5
|
+
**BREAKING**
|
|
6
|
+
|
|
7
|
+
- Upgrade to inversify 7 : In addition to bumping the dependency, checkout the [migration guide](https://inversify.io/docs/guides/migrating-from-v6) and this [discussion](https://github.com/inversify/InversifyJS/discussions/1765)
|
|
8
|
+
- In `FSManager`, add ability to `touch` file from `ArrayBuffer` : If you have a custom implementation, handle the new generic and handle both type of content
|
|
9
|
+
|
|
10
|
+
**Added**
|
|
11
|
+
|
|
12
|
+
- Introduce `ServerRequestHandler` : Used in `NodeExpressServerManager` and all the upcoming server targets, it contains everything needed to execute a use case on a server. You can use it to implement your own server (e.g. `Fastify` and so on)
|
|
13
|
+
- Introduce `NextJSServerManager` and `NextJSAPIRouteHandler` : Used to execute use cases within a [Next.js route handler](https://nextjs.org/docs/app/building-your-application/routing/route-handlers)
|
|
14
|
+
|
|
15
|
+
**Fixed**
|
|
16
|
+
|
|
17
|
+
- Handle body with only one file in `target/node-express-server`
|
|
18
|
+
|
|
19
|
+
**Misc**
|
|
20
|
+
|
|
21
|
+
- Showcase empty state and usage of more daisyUI components (e.g. loaders) in `examples/supertrader`
|
|
22
|
+
- Replace `path` by `parentPath` in `NodeFSManager`
|
|
23
|
+
- Prefix internal server error in dev mode
|
|
24
|
+
- Write uc input file instead of cp when in memory
|
|
25
|
+
- Create server tmp dir at startup if not present
|
|
26
|
+
|
|
3
27
|
## v0.11.1 (2025-04-03)
|
|
4
28
|
|
|
5
29
|
**Fixed**
|
package/README.md
CHANGED
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
A TypeScript library to create business oriented applications.
|
|
7
7
|
|
|
8
|
-
> [!WARNING]
|
|
9
|
-
> The project is still in active development. Although already used in pilot projects, it's not suitable for all production scenarios yet.
|
|
10
|
-
> Being developed by only one person, it may keep going for years or stop at any time.
|
|
11
|
-
> In the meantime, it's still a "research project" that needs improvement. Thus, it will be subject to BREAKING CHANGES as long as the version is not `1.0.0`.
|
|
12
|
-
> All that said, the end goal is really to have a **production-grade library** to help everyone build **quality projects faster**.
|
|
13
|
-
|
|
14
8
|
## 🚀 Getting Started
|
|
15
9
|
|
|
16
10
|
If you're discovering `libmodulor`, we recommend reading the [📖 Documentation](https://libmodulor.c100k.eu/docs) first. You'll find everything you need to get started : Concepts, Examples and Guides.
|
|
@@ -23,4 +17,4 @@ If you think you can help in any way, feel free to contact me (cf. `author` in `
|
|
|
23
17
|
|
|
24
18
|
## ⚖️ License
|
|
25
19
|
|
|
26
|
-
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.
|
|
20
|
+
[LGPL-3.0](https://github.com/c100k/libmodulor/blob/v0.12.0/LICENSE)
|
|
@@ -36,24 +36,24 @@ export const PACKAGE_JSON = (name) => `{
|
|
|
36
36
|
"test": "tsc && vitest run --passWithNoTests"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"inversify": "^
|
|
39
|
+
"inversify": "^7.5.0",
|
|
40
40
|
"libmodulor": "latest",
|
|
41
41
|
"reflect-metadata": "^0.2.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@biomejs/biome": "^1.9.4",
|
|
45
|
-
"@types/node": "^22.
|
|
46
|
-
"@vitest/coverage-v8": "^3.
|
|
45
|
+
"@types/node": "^22.14.0",
|
|
46
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
47
47
|
"buffer": "^6.0.3",
|
|
48
48
|
"cookie-parser": "^1.4.7",
|
|
49
49
|
"express": "^5.1.0",
|
|
50
50
|
"express-fileupload": "^1.5.1",
|
|
51
|
-
"fast-check": "^4.0
|
|
51
|
+
"fast-check": "^4.1.0",
|
|
52
52
|
"helmet": "^8.1.0",
|
|
53
53
|
"jose": "^6.0.10",
|
|
54
|
-
"typescript": "^5.8.
|
|
55
|
-
"vite": "^6.2.
|
|
56
|
-
"vitest": "^3.
|
|
54
|
+
"typescript": "^5.8.3",
|
|
55
|
+
"vite": "^6.2.5",
|
|
56
|
+
"vitest": "^3.1.1"
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
`;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export * from './target/lib/server/EntrypointsBuilder.js';
|
|
|
32
32
|
export * from './target/lib/server/JWTAuthenticationChecker.js';
|
|
33
33
|
export * from './target/lib/server/ServerBooter.js';
|
|
34
34
|
export * from './target/lib/server/ServerManager.js';
|
|
35
|
+
export * from './target/lib/server/ServerRequestHandler.js';
|
|
35
36
|
export * from './testing/index.js';
|
|
36
37
|
export * from './uc/impl/HTTPUCTransporter.js';
|
|
37
38
|
export * from './uc/impl/InMemoryUCDataStore.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export * from './target/lib/server/EntrypointsBuilder.js';
|
|
|
33
33
|
export * from './target/lib/server/JWTAuthenticationChecker.js';
|
|
34
34
|
export * from './target/lib/server/ServerBooter.js';
|
|
35
35
|
export * from './target/lib/server/ServerManager.js';
|
|
36
|
+
export * from './target/lib/server/ServerRequestHandler.js';
|
|
36
37
|
export * from './testing/index.js';
|
|
37
38
|
export * from './uc/impl/HTTPUCTransporter.js';
|
|
38
39
|
export * from './uc/impl/InMemoryUCDataStore.js';
|
|
@@ -8,7 +8,7 @@ await i18nManager.init();
|
|
|
8
8
|
// Before screaming, yes, this is not using any powerful CLI library.
|
|
9
9
|
// The goal is to reduce the usage of dependencies as much as possible.
|
|
10
10
|
// As long as the built-in Node.js API allows to build it without too many workarounds, let's keep it this way.
|
|
11
|
-
await container.
|
|
11
|
+
await container.get(NodeCoreCLIManager).handleCommand({
|
|
12
12
|
appsRootPath: container
|
|
13
13
|
.get('FSManager')
|
|
14
14
|
.path('..', '..', APPS_ROOT_DIR_NAME),
|
|
@@ -51,5 +51,5 @@ export interface FSManager {
|
|
|
51
51
|
path(...parts: Pathname[]): Pathname;
|
|
52
52
|
pickFiles(source: FSManagerFilePickerSource, opts?: FSManagerFilePickerOpts): Promise<File[]>;
|
|
53
53
|
rm(path: Pathname): Promise<void>;
|
|
54
|
-
touch<T extends string>(path: FilePath, content: T): Promise<void>;
|
|
54
|
+
touch<T extends ArrayBuffer | string>(path: FilePath, content: T): Promise<void>;
|
|
55
55
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { DirPath, File, FileExtension, FileName, FilePath
|
|
1
|
+
import type { DirPath, File, FileExtension, FileName, FilePath } from '../../dt/index.js';
|
|
2
2
|
import { type FSManager, type FSManagerCatOpts, type FSManagerChmodMode, type FSManagerItemInfo, type FSManagerLsItem, type FSManagerLsOpts, type Pathname } from '../FSManager.js';
|
|
3
3
|
export declare class FakeFSManager implements FSManager {
|
|
4
4
|
entries: Map<FilePath, {
|
|
5
|
-
content:
|
|
5
|
+
content: ArrayBuffer | string;
|
|
6
6
|
mode: FSManagerChmodMode;
|
|
7
7
|
}>;
|
|
8
8
|
constructor();
|
|
@@ -19,5 +19,5 @@ export declare class FakeFSManager implements FSManager {
|
|
|
19
19
|
path(...parts: Pathname[]): Pathname;
|
|
20
20
|
pickFiles(): Promise<File[]>;
|
|
21
21
|
rm(path: Pathname): Promise<void>;
|
|
22
|
-
touch<T extends string>(path: FilePath, content: T): Promise<void>;
|
|
22
|
+
touch<T extends ArrayBuffer | string>(path: FilePath, content: T): Promise<void>;
|
|
23
23
|
}
|
|
@@ -14,6 +14,6 @@ export declare class NodeFSManager implements FSManager {
|
|
|
14
14
|
path(...parts: Pathname[]): Pathname;
|
|
15
15
|
pickFiles(source: FSManagerFilePickerSource, opts?: FSManagerFilePickerOpts): Promise<File[]>;
|
|
16
16
|
rm(path: Pathname): Promise<void>;
|
|
17
|
-
touch<T extends string>(path: FilePath, content: T): Promise<void>;
|
|
17
|
+
touch<T extends ArrayBuffer | string>(path: FilePath, content: T): Promise<void>;
|
|
18
18
|
private determineType;
|
|
19
19
|
}
|
|
@@ -72,7 +72,7 @@ let NodeFSManager = class NodeFSManager {
|
|
|
72
72
|
});
|
|
73
73
|
return items.map((item) => ({
|
|
74
74
|
path: opts?.withFullPath
|
|
75
|
-
? this.path(item.
|
|
75
|
+
? this.path(item.parentPath, item.name)
|
|
76
76
|
: item.name,
|
|
77
77
|
type: this.determineType(item),
|
|
78
78
|
}));
|
|
@@ -118,7 +118,7 @@ let NodeFSManager = class NodeFSManager {
|
|
|
118
118
|
await rm(path, { recursive: true });
|
|
119
119
|
}
|
|
120
120
|
async touch(path, content) {
|
|
121
|
-
await writeFile(path, content);
|
|
121
|
+
await writeFile(path, content instanceof ArrayBuffer ? Buffer.from(content) : content);
|
|
122
122
|
}
|
|
123
123
|
determineType(stats) {
|
|
124
124
|
if (stats.isDirectory()) {
|
|
@@ -14,5 +14,5 @@ export declare class WebFSManager implements FSManager {
|
|
|
14
14
|
path(..._parts: Pathname[]): Pathname;
|
|
15
15
|
pickFiles(_source: FSManagerFilePickerSource, _opts?: FSManagerFilePickerOpts): Promise<File[]>;
|
|
16
16
|
rm(_path: Pathname): Promise<void>;
|
|
17
|
-
touch<T extends string>(_path: FilePath, _content: T): Promise<void>;
|
|
17
|
+
touch<T extends ArrayBuffer | string>(_path: FilePath, _content: T): Promise<void>;
|
|
18
18
|
}
|
|
@@ -10,7 +10,7 @@ export function useDIContext() {
|
|
|
10
10
|
}
|
|
11
11
|
export function DIContextProvider({ children, container, }) {
|
|
12
12
|
const [i18nManager] = useState(container.get('I18nManager'));
|
|
13
|
-
const [wordingManager] = useState(container.
|
|
13
|
+
const [wordingManager] = useState(container.get(WordingManager));
|
|
14
14
|
return (React.createElement(DIContext.Provider, { value: {
|
|
15
15
|
container,
|
|
16
16
|
i18nManager,
|
|
@@ -4,7 +4,7 @@ import { useDIContext } from './DIContextProvider.js';
|
|
|
4
4
|
export function UCContainer({ children, uc, }) {
|
|
5
5
|
const { container } = useDIContext();
|
|
6
6
|
const [isAllowed, setIsAllowed] = useState(undefined);
|
|
7
|
-
const [ucExecChecker] = useState(container.
|
|
7
|
+
const [ucExecChecker] = useState(container.get(UCExecChecker));
|
|
8
8
|
useEffect(() => {
|
|
9
9
|
(async () => {
|
|
10
10
|
const { allowed } = await ucExecChecker.exec({
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { JWT, Timestamp } from '../../../dt/index.js';
|
|
2
|
+
import type { JWTManager, SettingsManager, Worker } from '../../../std/index.js';
|
|
3
|
+
import type { ServerManagerSettings } from '../../lib/server/ServerManager.js';
|
|
4
|
+
export interface CookieOpts {
|
|
5
|
+
expires: Date;
|
|
6
|
+
httpOnly: boolean;
|
|
7
|
+
sameSite: 'strict';
|
|
8
|
+
secure: boolean;
|
|
9
|
+
signed: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface Input {
|
|
12
|
+
jwt: JWT;
|
|
13
|
+
}
|
|
14
|
+
export interface Output {
|
|
15
|
+
name: string;
|
|
16
|
+
opts: CookieOpts;
|
|
17
|
+
val: JWT;
|
|
18
|
+
}
|
|
19
|
+
type S = Pick<ServerManagerSettings, 'server_cookies_http_only' | 'server_cookies_name_auth' | 'server_cookies_same_site' | 'server_cookies_secure'>;
|
|
20
|
+
export declare class AuthCookieCreator implements Worker<Input, Promise<Output>> {
|
|
21
|
+
private jwtManager;
|
|
22
|
+
private settingsManager;
|
|
23
|
+
constructor(jwtManager: JWTManager, settingsManager: SettingsManager<S>);
|
|
24
|
+
s(): S;
|
|
25
|
+
exec({ jwt }: Input): Promise<Output>;
|
|
26
|
+
opts(exp?: Timestamp): CookieOpts;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
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 { inject, injectable } from 'inversify';
|
|
14
|
+
let AuthCookieCreator = class AuthCookieCreator {
|
|
15
|
+
jwtManager;
|
|
16
|
+
settingsManager;
|
|
17
|
+
constructor(jwtManager, settingsManager) {
|
|
18
|
+
this.jwtManager = jwtManager;
|
|
19
|
+
this.settingsManager = settingsManager;
|
|
20
|
+
}
|
|
21
|
+
s() {
|
|
22
|
+
return {
|
|
23
|
+
server_cookies_http_only: this.settingsManager.get()('server_cookies_http_only'),
|
|
24
|
+
server_cookies_name_auth: this.settingsManager.get()('server_cookies_name_auth'),
|
|
25
|
+
server_cookies_same_site: this.settingsManager.get()('server_cookies_same_site'),
|
|
26
|
+
server_cookies_secure: this.settingsManager.get()('server_cookies_secure'),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async exec({ jwt }) {
|
|
30
|
+
const { exp } = await this.jwtManager.decode(jwt);
|
|
31
|
+
return {
|
|
32
|
+
name: this.s().server_cookies_name_auth,
|
|
33
|
+
opts: this.opts(exp),
|
|
34
|
+
val: jwt,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
opts(exp) {
|
|
38
|
+
if (!exp) {
|
|
39
|
+
throw new Error('You need to define an exp for the cookie');
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
expires: new Date(exp * 1000),
|
|
43
|
+
httpOnly: this.s().server_cookies_http_only,
|
|
44
|
+
sameSite: this.s().server_cookies_same_site,
|
|
45
|
+
secure: this.s().server_cookies_secure,
|
|
46
|
+
signed: false, // Not signing to keep it simple and btw, the JWT is already signed
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
AuthCookieCreator = __decorate([
|
|
51
|
+
injectable(),
|
|
52
|
+
__param(0, inject('JWTManager')),
|
|
53
|
+
__param(1, inject('SettingsManager')),
|
|
54
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
55
|
+
], AuthCookieCreator);
|
|
56
|
+
export { AuthCookieCreator };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Provider } from 'inversify';
|
|
2
2
|
import type { AppManifest } from '../../../app/index.js';
|
|
3
3
|
import type { Logger, Worker } from '../../../std/index.js';
|
|
4
4
|
import { type UC, type UCAuth, type UCDef, type UCInput, type UCOPIBase, type UCPolicy } from '../../../uc/index.js';
|
|
@@ -24,7 +24,7 @@ export declare class AuthenticationChecker implements Worker<Input, Promise<Outp
|
|
|
24
24
|
private privateApiKeyAuthenticationChecker;
|
|
25
25
|
private logger;
|
|
26
26
|
private ucPolicyProvider;
|
|
27
|
-
constructor(basicAuthenticationChecker: BasicAuthenticationChecker, jwtAuthenticationChecker: JWTAuthenticationChecker, privateApiKeyAuthenticationChecker: PrivateApiKeyAuthenticationChecker, logger: Logger, ucPolicyProvider:
|
|
27
|
+
constructor(basicAuthenticationChecker: BasicAuthenticationChecker, jwtAuthenticationChecker: JWTAuthenticationChecker, privateApiKeyAuthenticationChecker: PrivateApiKeyAuthenticationChecker, logger: Logger, ucPolicyProvider: Provider<UCPolicy>);
|
|
28
28
|
exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ authCookie, authorizationHeader, uc, }: Input<I, OPI0, OPI1>): Promise<Output>;
|
|
29
29
|
}
|
|
30
30
|
export {};
|
|
@@ -29,10 +29,11 @@ let CustomerFacingErrorBuilder = class CustomerFacingErrorBuilder {
|
|
|
29
29
|
this.logger.error(error);
|
|
30
30
|
// Create a specific generic error to avoid leaking potentially sensitive error
|
|
31
31
|
// We all know the infamous "Cannot connect to MySQL database"...
|
|
32
|
+
const message = this.environmentManager.isProd()
|
|
33
|
+
? undefined
|
|
34
|
+
: `[DEV-mode] ${error.message}`;
|
|
32
35
|
return {
|
|
33
|
-
error: new InternalServerError(
|
|
34
|
-
? undefined
|
|
35
|
-
: error.message),
|
|
36
|
+
error: new InternalServerError(message),
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
};
|
|
@@ -4,8 +4,10 @@ import type { Configurable, EmailManager, FSManager, I18nManager, JobManager, Lo
|
|
|
4
4
|
import { type UCManager } from '../../../uc/index.js';
|
|
5
5
|
import { ServerInstaller } from './ServerInstaller.js';
|
|
6
6
|
import type { ServerManager, ServerManagerSettings } from './ServerManager.js';
|
|
7
|
-
type S = Pick<ServerManagerSettings, 'server_static_dir_path'>;
|
|
8
|
-
type Input = Pick<AppUCsLoaderInput, 'appsRootPath' | 'srcImporter'
|
|
7
|
+
type S = Pick<ServerManagerSettings, 'server_static_dir_path' | 'server_tmp_path'>;
|
|
8
|
+
type Input = Pick<AppUCsLoaderInput, 'appsRootPath' | 'srcImporter'> & {
|
|
9
|
+
autoMountUCs?: boolean;
|
|
10
|
+
};
|
|
9
11
|
export declare class ServerBooter implements Configurable<S>, Worker<Input, Promise<void>> {
|
|
10
12
|
private emailManager;
|
|
11
13
|
private fsManager;
|
|
@@ -19,6 +21,6 @@ export declare class ServerBooter implements Configurable<S>, Worker<Input, Prom
|
|
|
19
21
|
private ucManager;
|
|
20
22
|
constructor(emailManager: EmailManager, fsManager: FSManager, i18nManager: I18nManager, jobManager: JobManager, logger: Logger, productUCsLoader: ProductUCsLoader, serverManager: ServerManager, serverInstaller: ServerInstaller, settingsManager: SettingsManager<S>, ucManager: UCManager);
|
|
21
23
|
s(): S;
|
|
22
|
-
exec({ appsRootPath, srcImporter }: Input): Promise<void>;
|
|
24
|
+
exec({ appsRootPath, autoMountUCs, srcImporter, }: Input): Promise<void>;
|
|
23
25
|
}
|
|
24
26
|
export {};
|
|
@@ -40,9 +40,10 @@ let ServerBooter = class ServerBooter {
|
|
|
40
40
|
s() {
|
|
41
41
|
return {
|
|
42
42
|
server_static_dir_path: this.settingsManager.get()('server_static_dir_path'),
|
|
43
|
+
server_tmp_path: this.settingsManager.get()('server_tmp_path'),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
|
-
async exec({ appsRootPath, srcImporter }) {
|
|
46
|
+
async exec({ appsRootPath, autoMountUCs = true, srcImporter, }) {
|
|
46
47
|
this.logger.info('Initializing i18n manager');
|
|
47
48
|
await this.i18nManager.init();
|
|
48
49
|
this.logger.info('Installing');
|
|
@@ -54,29 +55,31 @@ let ServerBooter = class ServerBooter {
|
|
|
54
55
|
this.logger.info('Starting');
|
|
55
56
|
try {
|
|
56
57
|
await this.serverManager.init();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
server
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
if (autoMountUCs) {
|
|
59
|
+
const ucs = await this.productUCsLoader.exec({
|
|
60
|
+
appsRootPath,
|
|
61
|
+
srcImporter,
|
|
62
|
+
});
|
|
63
|
+
for await (const uc of ucs) {
|
|
64
|
+
const { lifecycle: { server }, sec, } = uc.def;
|
|
65
|
+
const contract = ucHTTPContract(uc);
|
|
66
|
+
const { mountingPoint } = contract;
|
|
67
|
+
if (typeof server !== 'object' ||
|
|
68
|
+
server.execMode === UCExecMode.AUTO) {
|
|
69
|
+
this.logger.debug(`Not mounting ${mountingPoint}`, {
|
|
70
|
+
reason: typeof server !== 'object'
|
|
71
|
+
? 'no ucd.lifecycle.server'
|
|
72
|
+
: 'execMode is AUTO',
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
this.logger.info(`Mounting ${mountingPoint}`, {
|
|
77
|
+
contract,
|
|
78
|
+
sec,
|
|
71
79
|
});
|
|
72
|
-
|
|
80
|
+
await this.ucManager.initServer(uc);
|
|
81
|
+
await this.serverManager.mount(uc.appManifest, uc.def, contract);
|
|
73
82
|
}
|
|
74
|
-
this.logger.info(`Mounting ${mountingPoint}`, {
|
|
75
|
-
contract,
|
|
76
|
-
sec,
|
|
77
|
-
});
|
|
78
|
-
await this.ucManager.initServer(uc);
|
|
79
|
-
await this.serverManager.mount(uc.appManifest, uc.def, contract);
|
|
80
83
|
}
|
|
81
84
|
const staticDirPath = this.s().server_static_dir_path;
|
|
82
85
|
if (staticDirPath) {
|
|
@@ -86,6 +89,10 @@ let ServerBooter = class ServerBooter {
|
|
|
86
89
|
this.logger.info('Mounting static dir', { staticDirPath });
|
|
87
90
|
await this.serverManager.mountStaticDir(staticDirPath);
|
|
88
91
|
}
|
|
92
|
+
const tmpDirPath = this.s().server_tmp_path;
|
|
93
|
+
if (!(await this.fsManager.exists(tmpDirPath))) {
|
|
94
|
+
await this.fsManager.mkdir(tmpDirPath);
|
|
95
|
+
}
|
|
89
96
|
await this.serverManager.warmUp();
|
|
90
97
|
await this.serverManager.start();
|
|
91
98
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { AppManifest } from '../../../app/index.js';
|
|
2
|
+
import type { HTTPMethod, HTTPStatusNumber, URL, URLPath } from '../../../dt/index.js';
|
|
3
|
+
import type { SettingsManager, Worker } from '../../../std/index.js';
|
|
4
|
+
import { UCBuilder, type UCDef, type UCInput, type UCManager, type UCOPIBase, type UCOutput } from '../../../uc/index.js';
|
|
5
|
+
import type { HTTPDataEnvelope, HTTPReqData } from '../../../utils/index.js';
|
|
6
|
+
import { AuthCookieCreator, type Output as AuthCookieCreatorOutput } from './AuthCookieCreator.js';
|
|
7
|
+
import { AuthenticationChecker } from './AuthenticationChecker.js';
|
|
8
|
+
import { CustomerFacingErrorBuilder } from './CustomerFacingErrorBuilder.js';
|
|
9
|
+
import { PublicApiKeyChecker } from './PublicApiKeyChecker.js';
|
|
10
|
+
import { RequestChecker } from './RequestChecker.js';
|
|
11
|
+
import { RequestLogger } from './RequestLogger.js';
|
|
12
|
+
import type { ServerManagerSettings } from './ServerManager.js';
|
|
13
|
+
export interface ServerRequestHandlerReq {
|
|
14
|
+
cookie: (name: string) => Promise<string | undefined>;
|
|
15
|
+
bodyFromFormData: () => Promise<HTTPReqData>;
|
|
16
|
+
bodyFromJSON: () => Promise<HTTPReqData>;
|
|
17
|
+
bodyFromQueryParams: () => Promise<HTTPReqData>;
|
|
18
|
+
bodyRaw: object | null;
|
|
19
|
+
method: HTTPMethod;
|
|
20
|
+
header: (name: string) => Promise<string | undefined>;
|
|
21
|
+
secure: boolean;
|
|
22
|
+
url: URL;
|
|
23
|
+
}
|
|
24
|
+
export interface ServerRequestHandlerRes {
|
|
25
|
+
clearCookie: (name: string) => Promise<void>;
|
|
26
|
+
redirect: (location: URL | URLPath) => Promise<void>;
|
|
27
|
+
setCookie: (info: AuthCookieCreatorOutput) => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
interface Input<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
|
|
30
|
+
appManifest: AppManifest;
|
|
31
|
+
envelope: HTTPDataEnvelope;
|
|
32
|
+
req: ServerRequestHandlerReq;
|
|
33
|
+
res: ServerRequestHandlerRes;
|
|
34
|
+
ucd: UCDef<I, OPI0, OPI1>;
|
|
35
|
+
/**
|
|
36
|
+
* It is not injected in the handler constructor because it must be the same as the one used in ServerManager.
|
|
37
|
+
*
|
|
38
|
+
* And in some cases, this latter is specific to a context : for instance in automated tests.
|
|
39
|
+
*/
|
|
40
|
+
ucManager: UCManager;
|
|
41
|
+
}
|
|
42
|
+
type BodylessStatus = 204 | 302;
|
|
43
|
+
type Output<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = {
|
|
44
|
+
body: undefined;
|
|
45
|
+
status: BodylessStatus;
|
|
46
|
+
} | {
|
|
47
|
+
body: UCOutput<OPI0, OPI1> | object;
|
|
48
|
+
status: Exclude<HTTPStatusNumber, BodylessStatus>;
|
|
49
|
+
};
|
|
50
|
+
type S = Pick<ServerManagerSettings, 'server_cookies_name_auth' | 'server_public_api_key_header_name'>;
|
|
51
|
+
export declare class ServerRequestHandler implements Worker<Input, Promise<Output>> {
|
|
52
|
+
private authCookieCreator;
|
|
53
|
+
private authenticationChecker;
|
|
54
|
+
private customerFacingErrorBuilder;
|
|
55
|
+
private publicApiKeyChecker;
|
|
56
|
+
private requestChecker;
|
|
57
|
+
private requestLogger;
|
|
58
|
+
private settingsManager;
|
|
59
|
+
private ucBuilder;
|
|
60
|
+
private static AUTHORIZATION_HEADER_NAME;
|
|
61
|
+
private static X_FORWARDED_PROTO_HEADER_NAME;
|
|
62
|
+
constructor(authCookieCreator: AuthCookieCreator, authenticationChecker: AuthenticationChecker, customerFacingErrorBuilder: CustomerFacingErrorBuilder, publicApiKeyChecker: PublicApiKeyChecker, requestChecker: RequestChecker, requestLogger: RequestLogger, settingsManager: SettingsManager<S>, ucBuilder: UCBuilder);
|
|
63
|
+
s(): S;
|
|
64
|
+
exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, envelope, req, res, ucd, ucManager, }: Input<I, OPI0, OPI1>): Promise<Output<OPI0, OPI1>>;
|
|
65
|
+
private fill;
|
|
66
|
+
private applySideEffects;
|
|
67
|
+
private applyClearAuthSideEffect;
|
|
68
|
+
private applyRedirectSideEffect;
|
|
69
|
+
private applySetAuthSideEffect;
|
|
70
|
+
}
|
|
71
|
+
export {};
|