libmodulor 0.22.0 → 0.23.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 +4 -0
- package/README.md +1 -1
- package/dist/esm/apps/Helper/src/lib/project.js +3 -3
- package/dist/esm/index.react.d.ts +1 -1
- package/dist/esm/index.react.js +1 -1
- package/dist/esm/std/JWTManager.d.ts +16 -1
- package/dist/esm/std/impl/JoseJWTManager.d.ts +3 -2
- package/dist/esm/std/impl/JoseJWTManager.js +4 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +4 -2
- package/dist/esm/target/lib/client/consts.js +1 -0
- package/dist/esm/target/lib/react/UCPanel.d.ts +7 -8
- package/dist/esm/target/lib/react/useUC.js +11 -1
- package/dist/esm/target/lib/server/ServerManager.d.ts +1 -0
- package/dist/esm/target/lib/server/consts.js +1 -0
- package/dist/esm/target/lib/server-express/funcs.js +3 -2
- package/dist/esm/target/lib/server-node/funcs.d.ts +2 -2
- package/dist/esm/target/lib/server-node/funcs.js +11 -1
- package/dist/esm/target/lib/server-node/types.d.ts +1 -0
- package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +2 -2
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +2 -1
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +2 -2
- package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +2 -1
- package/dist/esm/testing/impl/newNodeAppTester.js +3 -2
- package/dist/esm/utils/http/NDJSONStreamManager.d.ts +2 -1
- package/dist/esm/utils/http/NDJSONStreamManager.js +4 -1
- package/dist/esm/utils/http/SSEStreamManager.d.ts +2 -1
- package/dist/esm/utils/http/SSEStreamManager.js +4 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -81,13 +81,13 @@ export const PACKAGE_JSON = (name) => `{
|
|
|
81
81
|
"test": "tsc && vitest run --passWithNoTests"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"inversify": "^7.10.
|
|
84
|
+
"inversify": "^7.10.4",
|
|
85
85
|
"libmodulor": "latest",
|
|
86
86
|
"reflect-metadata": "^0.2.2"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@biomejs/biome": "^2.
|
|
90
|
-
"@types/node": "^24.
|
|
89
|
+
"@biomejs/biome": "^2.3.4",
|
|
90
|
+
"@types/node": "^24.10.0",
|
|
91
91
|
"@vitest/coverage-v8": "^3.2.4",
|
|
92
92
|
"buffer": "^6.0.3",
|
|
93
93
|
"cookie-parser": "^1.4.7",
|
|
@@ -6,7 +6,7 @@ export type { RenderUCEntrypointTouchable, RenderUCExecTouchable, UCEntrypointTo
|
|
|
6
6
|
export { UCContainer } from './target/lib/react/UCContainer.js';
|
|
7
7
|
export { UCEntrypoint } from './target/lib/react/UCEntrypoint.js';
|
|
8
8
|
export { type Props as UCOutputFieldValueFragmentProps, UCOutputFieldValueFragment, } from './target/lib/react/UCOutputFieldValueFragment.js';
|
|
9
|
-
export { UCPanel } from './target/lib/react/UCPanel.js';
|
|
9
|
+
export { type Props as UCPanelProps, UCPanel, } from './target/lib/react/UCPanel.js';
|
|
10
10
|
export { type UseActionOpts, useAction, } from './target/lib/react/useAction.js';
|
|
11
11
|
export { type CloneFunc, type DivertFunc, type RefillFunc, useUC, } from './target/lib/react/useUC.js';
|
|
12
12
|
export { type AppendFunc, type RemoveFunc, type UpdateFunc, useUCOR, } from './target/lib/react/useUCOR.js';
|
package/dist/esm/index.react.js
CHANGED
|
@@ -3,7 +3,7 @@ export { StyleContext, StyleContextProvider, styleDef, useStyleContext, } from '
|
|
|
3
3
|
export { UCContainer } from './target/lib/react/UCContainer.js';
|
|
4
4
|
export { UCEntrypoint } from './target/lib/react/UCEntrypoint.js';
|
|
5
5
|
export { UCOutputFieldValueFragment, } from './target/lib/react/UCOutputFieldValueFragment.js';
|
|
6
|
-
export { UCPanel } from './target/lib/react/UCPanel.js';
|
|
6
|
+
export { UCPanel, } from './target/lib/react/UCPanel.js';
|
|
7
7
|
export { useAction, } from './target/lib/react/useAction.js';
|
|
8
8
|
export { useUC, } from './target/lib/react/useUC.js';
|
|
9
9
|
export { useUCOR, } from './target/lib/react/useUCOR.js';
|
|
@@ -41,6 +41,19 @@ export interface JWTManager {
|
|
|
41
41
|
* @param opts
|
|
42
42
|
*/
|
|
43
43
|
decode<T extends JWTManagerPayload>(value: JWT, opts?: JWTManagerDecodeOpts): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Decode the token without checking the signature
|
|
46
|
+
*
|
|
47
|
+
* IMPORTANT : IT DOES NOT CHECK THE SIGNATURE
|
|
48
|
+
*
|
|
49
|
+
* The main purpose of this method is to be used client side to decode the JWT in order to update some state including :
|
|
50
|
+
* - displaying the firstname in the UI
|
|
51
|
+
* - set the payload in some state
|
|
52
|
+
* - etc.
|
|
53
|
+
*
|
|
54
|
+
* @param value
|
|
55
|
+
*/
|
|
56
|
+
decodeUnsafe<T extends JWTManagerPayload>(value: JWT): Promise<T>;
|
|
44
57
|
/**
|
|
45
58
|
* Encode the payload
|
|
46
59
|
*
|
|
@@ -53,7 +66,9 @@ export interface JWTManager {
|
|
|
53
66
|
/**
|
|
54
67
|
* Check whether the token is usable or not
|
|
55
68
|
*
|
|
56
|
-
*
|
|
69
|
+
* IMPORTANT : IT DOES NOT CHECK THE SIGNATURE
|
|
70
|
+
*
|
|
71
|
+
* The main purpose of this method is to be used client side to save some requests (e.g. when the token is expired).
|
|
57
72
|
* In this case, no need to send a request that will trigger an error. Better to renew the token at the client's initiative.
|
|
58
73
|
*/
|
|
59
74
|
isUsable(value: JWT): Promise<boolean>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JWT } from '../../dt/index.js';
|
|
2
2
|
import type { ClockManager } from '../ClockManager.js';
|
|
3
|
-
import type { JWTManager, JWTManagerDecodeOpts, JWTManagerEncodeOpts, JWTManagerSettings } from '../JWTManager.js';
|
|
3
|
+
import type { JWTManager, JWTManagerDecodeOpts, JWTManagerEncodeOpts, JWTManagerPayload, JWTManagerSettings } from '../JWTManager.js';
|
|
4
4
|
import type { SettingsManager } from '../SettingsManager.js';
|
|
5
5
|
export type S = Omit<JWTManagerSettings, 'jwt_manager_invalidate_issued_before'>;
|
|
6
6
|
export declare class JoseJWTManager implements JWTManager {
|
|
@@ -8,7 +8,8 @@ export declare class JoseJWTManager implements JWTManager {
|
|
|
8
8
|
private settingsManager;
|
|
9
9
|
constructor(clockManager: ClockManager, settingsManager: SettingsManager<S>);
|
|
10
10
|
s(): S;
|
|
11
|
-
decode<T extends
|
|
11
|
+
decode<T extends JWTManagerPayload>(value: JWT, opts?: JWTManagerDecodeOpts): Promise<T>;
|
|
12
|
+
decodeUnsafe<T extends JWTManagerPayload>(value: JWT): Promise<T>;
|
|
12
13
|
encode<T extends object>(payload: T, opts?: JWTManagerEncodeOpts): Promise<JWT>;
|
|
13
14
|
isUsable(value: JWT): Promise<boolean>;
|
|
14
15
|
}
|
|
@@ -54,6 +54,10 @@ let JoseJWTManager = class JoseJWTManager {
|
|
|
54
54
|
}
|
|
55
55
|
throw new Error(`Unsupported alg ${alg}`);
|
|
56
56
|
}
|
|
57
|
+
async decodeUnsafe(value) {
|
|
58
|
+
const decoded = decodeJwt(value);
|
|
59
|
+
return decoded;
|
|
60
|
+
}
|
|
57
61
|
async encode(payload, opts) {
|
|
58
62
|
const alg = opts?.alg ?? this.s().jwt_manager_algorithm;
|
|
59
63
|
const aud = opts?.aud ?? this.s().jwt_manager_audience;
|
|
@@ -90,7 +90,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
90
90
|
});
|
|
91
91
|
const { ok, redirected } = response;
|
|
92
92
|
if (ok || redirected) {
|
|
93
|
-
return this.processResGood({ opts, outputBuilder, stream }, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response);
|
|
93
|
+
return this.processResGood({ opts, outputBuilder, stream }, abortController, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response);
|
|
94
94
|
}
|
|
95
95
|
const message = await this.processResBad({ errBuilder, opts }, isJSON, isXML, response);
|
|
96
96
|
this.throwError(message ?? unknownErrorMessage, status);
|
|
@@ -173,13 +173,14 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
173
173
|
return JSON.stringify(error);
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
-
async processResGood({ opts, outputBuilder, stream, }, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response) {
|
|
176
|
+
async processResGood({ opts, outputBuilder, stream, }, abortController, isFormURLEncoded, isJSON, isNDJSON, isSSE, isXML, response) {
|
|
177
177
|
let payload;
|
|
178
178
|
if (isNDJSON && stream) {
|
|
179
179
|
if (!response.body) {
|
|
180
180
|
throw new Error(ERR_STREAM_UNAVAILABLE);
|
|
181
181
|
}
|
|
182
182
|
await this.ndJSONStreamManager.exec({
|
|
183
|
+
abortController,
|
|
183
184
|
onData: async (data) => {
|
|
184
185
|
if (outputBuilder) {
|
|
185
186
|
stream.onData(await outputBuilder(data));
|
|
@@ -196,6 +197,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
196
197
|
throw new Error(ERR_STREAM_UNAVAILABLE);
|
|
197
198
|
}
|
|
198
199
|
await this.sseStreamManager.exec({
|
|
200
|
+
abortController,
|
|
199
201
|
onData: async (data) => {
|
|
200
202
|
if (outputBuilder) {
|
|
201
203
|
stream.onData(await outputBuilder(data));
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* @see TARGET_DEFAULT_SERVER_MANAGER_SETTINGS
|
|
3
3
|
*/
|
|
4
4
|
export const TARGET_DEFAULT_SERVER_CLIENT_MANAGER_SETTINGS = {
|
|
5
|
+
server_cookies_name_auth: 'auth',
|
|
5
6
|
server_public_api_key: 'PublicApiKeyToBeChangedWhenDeploying',
|
|
6
7
|
server_public_api_key_header_name: 'X-API-Key',
|
|
7
8
|
server_public_url: 'http://localhost:7443',
|
|
@@ -6,17 +6,16 @@ import type { RenderUCForm } from './form.js';
|
|
|
6
6
|
import type { RenderUCAutoExecLoader } from './loader.js';
|
|
7
7
|
import type { UCPanelCtx, UCPanelOnDone, UCPanelOnError, UCPanelOnInit, UCPanelOnStartSubmitting } from './panel.js';
|
|
8
8
|
import type { RenderUCExecTouchable } from './touchable.js';
|
|
9
|
-
type Props<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = Pick<UCPanelCtx<I, OPI0, OPI1>, 'clearAfterExec' | 'uc'> & {
|
|
10
|
-
autoExec?: boolean;
|
|
11
|
-
onDone?: UCPanelOnDone<I, OPI0, OPI1
|
|
12
|
-
onInit?: UCPanelOnInit<I, OPI0, OPI1
|
|
13
|
-
onError?: UCPanelOnError;
|
|
14
|
-
onStartSubmitting?: UCPanelOnStartSubmitting;
|
|
9
|
+
export type Props<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = Pick<UCPanelCtx<I, OPI0, OPI1>, 'clearAfterExec' | 'uc'> & {
|
|
10
|
+
autoExec?: boolean | undefined;
|
|
11
|
+
onDone?: UCPanelOnDone<I, OPI0, OPI1> | undefined;
|
|
12
|
+
onInit?: UCPanelOnInit<I, OPI0, OPI1> | undefined;
|
|
13
|
+
onError?: UCPanelOnError | undefined;
|
|
14
|
+
onStartSubmitting?: UCPanelOnStartSubmitting | undefined;
|
|
15
15
|
renderAutoExecLoader: RenderUCAutoExecLoader;
|
|
16
16
|
renderExecTouchable: RenderUCExecTouchable<I, OPI0, OPI1>;
|
|
17
17
|
renderForm: RenderUCForm<I, OPI0, OPI1>;
|
|
18
|
-
sleepInMs?: UIntDuration;
|
|
18
|
+
sleepInMs?: UIntDuration | undefined;
|
|
19
19
|
stream?: StreamConfig<UCOutputReader<I, OPI0, OPI1>> | undefined;
|
|
20
20
|
};
|
|
21
21
|
export declare function UCPanel<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ autoExec, clearAfterExec, onDone, onError, onInit, onStartSubmitting, renderAutoExecLoader, renderForm, renderExecTouchable, sleepInMs, stream, uc, }: Props<I, OPI0, OPI1>): ReactElement;
|
|
22
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { UC, } from '../../../uc/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* This hook provides utilities to init a use case and perform actions on it in a React way
|
|
@@ -21,6 +21,16 @@ export function useUC(appManifest, def, auth, opts) {
|
|
|
21
21
|
}
|
|
22
22
|
return v;
|
|
23
23
|
});
|
|
24
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(appManifest): avoid infinite re-rendering
|
|
25
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(def): avoid infinite re-rendering
|
|
26
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies(opts?.fillWith): avoid infinite re-rendering
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const v = new UC(appManifest, def, auth);
|
|
29
|
+
if (opts?.fillWith) {
|
|
30
|
+
v.fill(opts?.fillWith);
|
|
31
|
+
}
|
|
32
|
+
setUC(v);
|
|
33
|
+
}, [auth]);
|
|
24
34
|
/**
|
|
25
35
|
* Get a new `UC` based on the initial one
|
|
26
36
|
* @param i
|
|
@@ -27,6 +27,7 @@ export interface ServerManagerSettings extends ServerManagerAuthSettings, Settin
|
|
|
27
27
|
server_ssl_fullchain_path: FilePath | null;
|
|
28
28
|
server_ssl_key_path: FilePath | null;
|
|
29
29
|
server_static_dir_path: DirPath | null;
|
|
30
|
+
server_stop_mode: 'aggressive' | 'patient';
|
|
30
31
|
server_tmp_path: FilePath;
|
|
31
32
|
}
|
|
32
33
|
export interface ServerManager extends Initializable {
|
|
@@ -14,7 +14,9 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
|
|
|
14
14
|
case 'stream': {
|
|
15
15
|
execOpts = {
|
|
16
16
|
stream: {
|
|
17
|
-
onClose: async () => {
|
|
17
|
+
onClose: async () => {
|
|
18
|
+
throw new Error('execOpts.stream.onClose needs to be set in the UC ServerMain');
|
|
19
|
+
},
|
|
18
20
|
onData: async (output) => {
|
|
19
21
|
if (!output) {
|
|
20
22
|
return;
|
|
@@ -31,7 +33,6 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
|
|
|
31
33
|
}
|
|
32
34
|
res.flushHeaders();
|
|
33
35
|
res.on('close', async () => {
|
|
34
|
-
res.end();
|
|
35
36
|
await execOpts?.stream?.onClose();
|
|
36
37
|
});
|
|
37
38
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Logger, SettingsManager } from '../../../std/index.js';
|
|
2
2
|
import type { EntrypointsBuilder } from '../server/EntrypointsBuilder.js';
|
|
3
|
-
import type { ListenSettings, Server } from './types.js';
|
|
3
|
+
import type { ListenSettings, Server, StopSettings } from './types.js';
|
|
4
4
|
export declare function listen(server: Server, entrypointsBuilder: EntrypointsBuilder, logger: Logger, settingsManager: SettingsManager<ListenSettings>): void;
|
|
5
|
-
export declare function stop(server: Server): Promise<void>;
|
|
5
|
+
export declare function stop(server: Server, settingsManager: SettingsManager<StopSettings>): Promise<void>;
|
|
@@ -5,16 +5,26 @@ export function listen(server, entrypointsBuilder, logger, settingsManager) {
|
|
|
5
5
|
logger.info(`Listening on ${entrypointsBuilder.exec().http}`);
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
|
-
export async function stop(server) {
|
|
8
|
+
export async function stop(server, settingsManager) {
|
|
9
9
|
if (!server?.listening) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
+
const mode = settingsManager.get()('server_stop_mode');
|
|
12
13
|
// As stated in the docs of `close`, only awaiting `.close` is not enough to make sure all the connections are closed.
|
|
13
14
|
// Hence the wrapping in a promise, where the callback is called when the 'close' event is emitted.
|
|
14
15
|
return new Promise((resolve, reject) => {
|
|
15
16
|
if (!server) {
|
|
16
17
|
return resolve();
|
|
17
18
|
}
|
|
19
|
+
switch (mode) {
|
|
20
|
+
case 'aggressive':
|
|
21
|
+
server.closeAllConnections();
|
|
22
|
+
break;
|
|
23
|
+
case 'patient':
|
|
24
|
+
break;
|
|
25
|
+
default:
|
|
26
|
+
((_) => { })(mode);
|
|
27
|
+
}
|
|
18
28
|
server.close((err) => {
|
|
19
29
|
if (err) {
|
|
20
30
|
return reject(err);
|
|
@@ -3,3 +3,4 @@ import type https from 'node:https';
|
|
|
3
3
|
import type { ServerManagerSettings } from '../server/ServerManager.js';
|
|
4
4
|
export type Server = http.Server | https.Server;
|
|
5
5
|
export type ListenSettings = Pick<ServerManagerSettings, 'server_binding_host' | 'server_binding_port'>;
|
|
6
|
+
export type StopSettings = Pick<ServerManagerSettings, 'server_stop_mode'>;
|
|
@@ -8,8 +8,8 @@ import type { ServerManager, ServerManagerSettings } from '../lib/server/ServerM
|
|
|
8
8
|
import { ServerRequestHandler } from '../lib/server/ServerRequestHandler.js';
|
|
9
9
|
import { ServerSSLCertLoader } from '../lib/server/ServerSSLCertLoader.js';
|
|
10
10
|
import { HelmetMiddlewareBuilder } from '../lib/server-express/HelmetMiddlewareBuilder.js';
|
|
11
|
-
import type { ListenSettings } from '../lib/server-node/types.js';
|
|
12
|
-
type S = ListenSettings & Pick<LoggerSettings, 'logger_level'> & Pick<ServerManagerSettings, 'server_tmp_path'
|
|
11
|
+
import type { ListenSettings, StopSettings } from '../lib/server-node/types.js';
|
|
12
|
+
type S = ListenSettings & Pick<LoggerSettings, 'logger_level'> & Pick<ServerManagerSettings, 'server_tmp_path'> & StopSettings;
|
|
13
13
|
export declare class NodeExpressServerManager implements Configurable<S>, ServerManager {
|
|
14
14
|
private entrypointsBuilder;
|
|
15
15
|
protected environmentManager: EnvironmentManager;
|
|
@@ -47,6 +47,7 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
47
47
|
logger_level: this.settingsManager.get()('logger_level'),
|
|
48
48
|
server_binding_host: this.settingsManager.get()('server_binding_host'),
|
|
49
49
|
server_binding_port: this.settingsManager.get()('server_binding_port'),
|
|
50
|
+
server_stop_mode: this.settingsManager.get()('server_stop_mode'),
|
|
50
51
|
server_tmp_path: this.settingsManager.get()('server_tmp_path'),
|
|
51
52
|
};
|
|
52
53
|
}
|
|
@@ -79,7 +80,7 @@ let NodeExpressServerManager = class NodeExpressServerManager {
|
|
|
79
80
|
listen(this.server, this.entrypointsBuilder, this.logger, this.settingsManager);
|
|
80
81
|
}
|
|
81
82
|
async stop() {
|
|
82
|
-
await stop(this.server);
|
|
83
|
+
await stop(this.server, this.settingsManager);
|
|
83
84
|
}
|
|
84
85
|
async warmUp() {
|
|
85
86
|
// Nothing to do
|
|
@@ -7,8 +7,8 @@ import { EntrypointsBuilder } from '../lib/server/EntrypointsBuilder.js';
|
|
|
7
7
|
import type { ServerManager } from '../lib/server/ServerManager.js';
|
|
8
8
|
import { ServerRequestHandler } from '../lib/server/ServerRequestHandler.js';
|
|
9
9
|
import { ServerSSLCertLoader } from '../lib/server/ServerSSLCertLoader.js';
|
|
10
|
-
import type { ListenSettings } from '../lib/server-node/types.js';
|
|
11
|
-
type S = ListenSettings;
|
|
10
|
+
import type { ListenSettings, StopSettings } from '../lib/server-node/types.js';
|
|
11
|
+
type S = ListenSettings & StopSettings;
|
|
12
12
|
export declare class NodeHonoServerManager implements Configurable<S>, ServerManager {
|
|
13
13
|
private entrypointsBuilder;
|
|
14
14
|
protected environmentManager: EnvironmentManager;
|
|
@@ -44,6 +44,7 @@ let NodeHonoServerManager = class NodeHonoServerManager {
|
|
|
44
44
|
return {
|
|
45
45
|
server_binding_host: this.settingsManager.get()('server_binding_host'),
|
|
46
46
|
server_binding_port: this.settingsManager.get()('server_binding_port'),
|
|
47
|
+
server_stop_mode: this.settingsManager.get()('server_stop_mode'),
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
getRuntime() {
|
|
@@ -75,7 +76,7 @@ let NodeHonoServerManager = class NodeHonoServerManager {
|
|
|
75
76
|
listen(this.server, this.entrypointsBuilder, this.logger, this.settingsManager);
|
|
76
77
|
}
|
|
77
78
|
async stop() {
|
|
78
|
-
await stop(this.server);
|
|
79
|
+
await stop(this.server, this.settingsManager);
|
|
79
80
|
}
|
|
80
81
|
async warmUp() {
|
|
81
82
|
// Nothing to do
|
|
@@ -18,8 +18,8 @@ export async function newNodeAppTester(serverPortRangeStart, idx, args) {
|
|
|
18
18
|
const settings = {
|
|
19
19
|
...STD_DEFAULT_JWT_MANAGER_SETTINGS,
|
|
20
20
|
...TARGET_DEFAULT_SERVER_MANAGER_SETTINGS,
|
|
21
|
-
jwt_manager_audience: '
|
|
22
|
-
jwt_manager_issuer: '
|
|
21
|
+
jwt_manager_audience: 'libmodulor-test',
|
|
22
|
+
jwt_manager_issuer: 'libmodulor-test',
|
|
23
23
|
jwt_manager_secret: new TPassword().example(),
|
|
24
24
|
logger_level,
|
|
25
25
|
server_basic_auth_entries: {
|
|
@@ -28,6 +28,7 @@ export async function newNodeAppTester(serverPortRangeStart, idx, args) {
|
|
|
28
28
|
server_binding_port: serverPortRangeStart + idx,
|
|
29
29
|
server_private_api_key_entries: [new TApiKey().example()],
|
|
30
30
|
server_public_api_key_entries: [new TApiKey().example()],
|
|
31
|
+
server_stop_mode: 'aggressive',
|
|
31
32
|
};
|
|
32
33
|
const container = new Container(CONTAINER_OPTS);
|
|
33
34
|
bindCommon(container, () => settings);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { HTTPAPICallExecutorResBody, Worker } from '../../std/index.js';
|
|
2
2
|
type Encoding = 'utf-8';
|
|
3
3
|
interface I<D extends object = object> {
|
|
4
|
+
abortController: AbortController;
|
|
4
5
|
encoding?: Encoding | undefined;
|
|
5
6
|
onData: (data: D) => Promise<void>;
|
|
6
7
|
reader: ReturnType<HTTPAPICallExecutorResBody['getReader']>;
|
|
7
8
|
}
|
|
8
9
|
export declare class NDJSONStreamManager implements Worker<I, Promise<void>> {
|
|
9
10
|
private static DEFAULT_ENCODING;
|
|
10
|
-
exec({ encoding, onData, reader, }: I): Promise<void>;
|
|
11
|
+
exec({ abortController, encoding, onData, reader, }: I): Promise<void>;
|
|
11
12
|
}
|
|
12
13
|
export {};
|
|
@@ -10,10 +10,13 @@ import { NDJSON_DATA_SEP } from './nd-json.js';
|
|
|
10
10
|
let NDJSONStreamManager = class NDJSONStreamManager {
|
|
11
11
|
static { NDJSONStreamManager_1 = this; }
|
|
12
12
|
static DEFAULT_ENCODING = 'utf-8';
|
|
13
|
-
async exec({ encoding = NDJSONStreamManager_1.DEFAULT_ENCODING, onData, reader, }) {
|
|
13
|
+
async exec({ abortController, encoding = NDJSONStreamManager_1.DEFAULT_ENCODING, onData, reader, }) {
|
|
14
14
|
const decoder = new TextDecoder(encoding);
|
|
15
15
|
let buffer = '';
|
|
16
16
|
while (true) {
|
|
17
|
+
if (abortController.signal.aborted) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
17
20
|
const { done, value } = await reader.read();
|
|
18
21
|
if (done) {
|
|
19
22
|
return;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { HTTPAPICallExecutorResBody, Worker } from '../../std/index.js';
|
|
2
2
|
type Encoding = 'utf-8';
|
|
3
3
|
interface I<D extends object = object> {
|
|
4
|
+
abortController: AbortController;
|
|
4
5
|
encoding?: Encoding | undefined;
|
|
5
6
|
onData: (data: D) => Promise<void>;
|
|
6
7
|
reader: ReturnType<HTTPAPICallExecutorResBody['getReader']>;
|
|
7
8
|
}
|
|
8
9
|
export declare class SSEStreamManager implements Worker<I, Promise<void>> {
|
|
9
10
|
private static DEFAULT_ENCODING;
|
|
10
|
-
exec({ encoding, onData, reader, }: I): Promise<void>;
|
|
11
|
+
exec({ abortController, encoding, onData, reader, }: I): Promise<void>;
|
|
11
12
|
}
|
|
12
13
|
export {};
|
|
@@ -11,10 +11,13 @@ import { isSSEError, parseDataLine, SSE_DATA_SEP, SSE_MSG_SEP } from './sse.js';
|
|
|
11
11
|
let SSEStreamManager = class SSEStreamManager {
|
|
12
12
|
static { SSEStreamManager_1 = this; }
|
|
13
13
|
static DEFAULT_ENCODING = 'utf-8';
|
|
14
|
-
async exec({ encoding = SSEStreamManager_1.DEFAULT_ENCODING, onData, reader, }) {
|
|
14
|
+
async exec({ abortController, encoding = SSEStreamManager_1.DEFAULT_ENCODING, onData, reader, }) {
|
|
15
15
|
const decoder = new TextDecoder(encoding);
|
|
16
16
|
let buffer = '';
|
|
17
17
|
while (true) {
|
|
18
|
+
if (abortController.signal.aborted) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
18
21
|
const { done, value } = await reader.read();
|
|
19
22
|
if (done) {
|
|
20
23
|
return;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libmodulor",
|
|
3
3
|
"description": "A TypeScript library to create platform-agnostic applications",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.0",
|
|
5
5
|
"license": "LGPL-3.0",
|
|
6
6
|
"author": "Chafik H'nini <chafik.hnini@gmail.com>",
|
|
7
7
|
"homepage": "https://libmodulor.c100k.eu",
|
|
@@ -81,11 +81,11 @@
|
|
|
81
81
|
"lint:ci": "biome check"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@biomejs/biome": "^2.
|
|
84
|
+
"@biomejs/biome": "^2.3.4"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
|
-
"@hono/node-server": "^1.19.
|
|
88
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
87
|
+
"@hono/node-server": "^1.19.6",
|
|
88
|
+
"@modelcontextprotocol/sdk": "^1.21.0",
|
|
89
89
|
"@stricli/core": "^1.2.4",
|
|
90
90
|
"buffer": "^6.0.3",
|
|
91
91
|
"cookie-parser": "^1.4.7",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
"express-fileupload": "^1.5.2",
|
|
94
94
|
"fast-check": "^4.3.0",
|
|
95
95
|
"helmet": "^8.1.0",
|
|
96
|
-
"hono": "^4.10.
|
|
97
|
-
"inversify": "^7.10.
|
|
96
|
+
"hono": "^4.10.4",
|
|
97
|
+
"inversify": "^7.10.4",
|
|
98
98
|
"jose": "^6.1.0",
|
|
99
99
|
"knex": "^3.1.0",
|
|
100
100
|
"next": "^15.5.6",
|