@flancer32/teq-web 0.10.0 → 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 +30 -14
- package/ai/abstractions.md +9 -3
- package/ai/examples/minimal-server.md +31 -23
- package/ai/overview.md +1 -1
- package/ai/rules.md +3 -1
- package/package.json +2 -2
- package/src/Back/Api/Handler.mjs +4 -3
- package/src/Back/Config/Runtime/Tls.mjs +16 -6
- package/src/Back/Config/Runtime.mjs +10 -8
- package/src/Back/Dto/Info.mjs +4 -3
- package/src/Back/Dto/RequestContext.mjs +4 -2
- package/src/Back/Dto/Source.mjs +4 -3
- package/src/Back/Enum/Server/Type.mjs +4 -2
- package/src/Back/Enum/Stage.mjs +4 -2
- package/src/Back/Handler/Pre/Log.mjs +5 -4
- package/src/Back/Handler/Static/A/Config.mjs +16 -3
- package/src/Back/Handler/Static/A/Fallback.mjs +4 -2
- package/src/Back/Handler/Static/A/FileService.mjs +5 -3
- package/src/Back/Handler/Static/A/Registry.mjs +12 -3
- package/src/Back/Handler/Static/A/Resolver.mjs +5 -3
- package/src/Back/Handler/Static.mjs +5 -4
- package/src/Back/Helper/Cast.mjs +4 -2
- package/src/Back/Helper/Mime.mjs +4 -2
- package/src/Back/Helper/Order/Kahn.mjs +4 -2
- package/src/Back/Helper/Respond.mjs +4 -2
- package/src/Back/Logger.mjs +4 -2
- package/src/Back/PipelineEngine.mjs +11 -6
- package/src/Back/Server.mjs +4 -2
- package/types.d.ts +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.0] - 2026-07-04 - Pipeline locking and transport contract alignment
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Added unit and integration coverage for direct request execution with an unlocked pipeline.
|
|
7
|
+
- Added unit coverage for the request-context DTO contract.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Stopped pipeline processing when the response is no longer writable.
|
|
11
|
+
- Required explicit handler locking before direct `PipelineEngine` request execution.
|
|
12
|
+
- Clarified the transport model as plain HTTP plus secure web transport and aligned AI-facing documentation with the current server behavior.
|
|
13
|
+
- Clarified that runtime-isolation guarantees apply to separate Node.js processes, not to multiple containers within one process.
|
|
14
|
+
- Updated package version metadata to `0.12.0`.
|
|
15
|
+
|
|
16
|
+
## [0.11.0] - 2026-04-01 - TeqFW spec alignment and runtime contract updates
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- Added TeqFW specification documents for DI usage, ES module conventions, and package metadata expectations.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Reworked runtime configuration docs and examples to follow the current spec-level contract.
|
|
23
|
+
- Tightened runtime configuration implementation and unit tests to match the updated contract.
|
|
24
|
+
- Replaced legacy TeqFW convention documents with the current spec-oriented documentation layout.
|
|
25
|
+
- Updated package version metadata to `0.11.0`.
|
|
26
|
+
|
|
3
27
|
## [0.10.0] - 2026-03-31 - Validator conformance and release preparation
|
|
4
28
|
|
|
5
29
|
### Changed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Infrastructure web server and deterministic request pipeline for TeqFW packages.
|
|
|
4
4
|
|
|
5
5
|
`@flancer32/teq-web` is an infrastructural component of the **Tequila Framework (TeqFW)** platform.
|
|
6
6
|
|
|
7
|
-
The package provides a deterministic **request lifecycle pipeline** and a built-in **Node.js web server** that other TeqFW packages can use as the runtime environment for processing
|
|
7
|
+
The package provides a deterministic **request lifecycle pipeline** and a built-in **Node.js web server** that other TeqFW packages can use as the runtime environment for processing web requests.
|
|
8
8
|
|
|
9
9
|
Within the TeqFW ecosystem, this package plays a role similar to how **Express** or **Fastify** are used in typical Node.js applications: it acts as the **web runtime layer** used by higher-level packages.
|
|
10
10
|
|
|
@@ -96,6 +96,12 @@ Supported server types:
|
|
|
96
96
|
- `http2`
|
|
97
97
|
- `https`
|
|
98
98
|
|
|
99
|
+
Mode meaning:
|
|
100
|
+
|
|
101
|
+
- `http` is plain HTTP
|
|
102
|
+
- `http2` is cleartext HTTP/2
|
|
103
|
+
- `https` is secure web transport using the Node.js secure HTTP/2 server with HTTP/1.1 fallback when negotiated by the client
|
|
104
|
+
|
|
99
105
|
The server locks the handler pipeline before entering the execution phase.
|
|
100
106
|
|
|
101
107
|
### Handlers
|
|
@@ -113,14 +119,14 @@ Handlers do not coordinate with each other directly. Execution order is derived
|
|
|
113
119
|
## Example (TeqFW Style)
|
|
114
120
|
|
|
115
121
|
```javascript
|
|
116
|
-
//
|
|
122
|
+
// src/Handler/Hello.mjs
|
|
117
123
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
/**
|
|
125
|
+
* @namespace App_Web_Handler_Hello
|
|
126
|
+
* @description Example PROCESS handler
|
|
127
|
+
*/
|
|
122
128
|
|
|
123
|
-
export default class
|
|
129
|
+
export default class Hello {
|
|
124
130
|
constructor({ dtoInfoFactory, STAGE }) {
|
|
125
131
|
const info = dtoInfoFactory.create({
|
|
126
132
|
name: "App_Web_Handler_Hello",
|
|
@@ -139,18 +145,22 @@ export default class App_Web_Handler_Hello {
|
|
|
139
145
|
};
|
|
140
146
|
}
|
|
141
147
|
}
|
|
148
|
+
|
|
149
|
+
export const __deps__ = Object.freeze({
|
|
150
|
+
dtoInfoFactory: "Fl32_Web_Back_Dto_Info__Factory$",
|
|
151
|
+
STAGE: "Fl32_Web_Back_Enum_Stage$",
|
|
152
|
+
});
|
|
142
153
|
```
|
|
143
154
|
|
|
144
155
|
```javascript
|
|
145
|
-
//
|
|
156
|
+
// src/Server/Start.mjs
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
158
|
+
/**
|
|
159
|
+
* @namespace App_Web_Server_Start
|
|
160
|
+
* @description Example application entry service
|
|
161
|
+
*/
|
|
152
162
|
|
|
153
|
-
export default class
|
|
163
|
+
export default class Start {
|
|
154
164
|
constructor({ pipeline, server, helloHandler }) {
|
|
155
165
|
this.execute = async function () {
|
|
156
166
|
pipeline.addHandler(helloHandler);
|
|
@@ -162,6 +172,12 @@ export default class App_Web_Server_Start {
|
|
|
162
172
|
};
|
|
163
173
|
}
|
|
164
174
|
}
|
|
175
|
+
|
|
176
|
+
export const __deps__ = Object.freeze({
|
|
177
|
+
pipeline: "Fl32_Web_Back_PipelineEngine$",
|
|
178
|
+
server: "Fl32_Web_Back_Server$",
|
|
179
|
+
helloHandler: "App_Web_Handler_Hello$",
|
|
180
|
+
});
|
|
165
181
|
```
|
|
166
182
|
|
|
167
183
|
Application entry point:
|
package/ai/abstractions.md
CHANGED
|
@@ -10,7 +10,7 @@ Main methods:
|
|
|
10
10
|
|
|
11
11
|
- `addHandler(handler)` or `registerHandler(handler)` registers a handler before the pipeline is locked;
|
|
12
12
|
- `lockHandlers()` freezes handler order explicitly;
|
|
13
|
-
- `onEventRequest(req, res)` or `handleRequest(req, res)` executes one request lifecycle.
|
|
13
|
+
- `onEventRequest(req, res)` or `handleRequest(req, res)` executes one request lifecycle after the pipeline has been locked.
|
|
14
14
|
|
|
15
15
|
## Server
|
|
16
16
|
|
|
@@ -22,7 +22,13 @@ Default transport settings come from flat fields of `Fl32_Web_Back_Config_Runtim
|
|
|
22
22
|
- `http2`
|
|
23
23
|
- `https`
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Mode meaning:
|
|
26
|
+
|
|
27
|
+
- `http` is plain HTTP.
|
|
28
|
+
- `http2` is cleartext HTTP/2.
|
|
29
|
+
- `https` is secure web transport implemented through the Node.js secure `http2` server and may negotiate `HTTP/2` or fall back to `HTTP/1.1`.
|
|
30
|
+
|
|
31
|
+
`https` requires `config.tls` to contain both `key` and `cert`.
|
|
26
32
|
|
|
27
33
|
## Handler Contract
|
|
28
34
|
|
|
@@ -63,7 +69,7 @@ Only `PROCESS` handlers may mark the request as completed.
|
|
|
63
69
|
|
|
64
70
|
## Built-in Static Handler
|
|
65
71
|
|
|
66
|
-
`Fl32_Web_Back_Handler_Static$` is a PROCESS-stage handler for static file delivery. Before use, call `init({sources})` with source DTOs created by `
|
|
72
|
+
`Fl32_Web_Back_Handler_Static$` is a PROCESS-stage handler for static file delivery. Before use, call `init({sources})` with source DTOs created by `Fl32_Web_Back_Dto_Source__Factory$`.
|
|
67
73
|
|
|
68
74
|
Each source describes:
|
|
69
75
|
|
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
This example shows the preferred TeqFW-style usage path: external code resolves one application service from the container, and that service receives web infrastructure through constructor injection.
|
|
4
4
|
|
|
5
5
|
```js
|
|
6
|
-
//
|
|
6
|
+
// src/Handler/Hello.mjs
|
|
7
7
|
// @ts-check
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/**
|
|
10
|
+
* @namespace App_Web_Handler_Hello
|
|
11
|
+
* @description Example PROCESS handler
|
|
12
|
+
*/
|
|
13
13
|
|
|
14
|
-
export default class
|
|
14
|
+
export default class Hello {
|
|
15
15
|
/**
|
|
16
|
-
* @param {
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* }} deps
|
|
16
|
+
* @param {object} deps
|
|
17
|
+
* @param {Fl32_Web_Back_Dto_Info$Factory} deps.dtoInfoFactory
|
|
18
|
+
* @param {Fl32_Web_Back_Enum_Stage} deps.STAGE
|
|
20
19
|
*/
|
|
21
20
|
constructor({dtoInfoFactory, STAGE}) {
|
|
22
21
|
const info = dtoInfoFactory.create({
|
|
@@ -34,25 +33,28 @@ export default class App_Web_Handler_Hello {
|
|
|
34
33
|
};
|
|
35
34
|
}
|
|
36
35
|
}
|
|
36
|
+
|
|
37
|
+
export const __deps__ = Object.freeze({
|
|
38
|
+
dtoInfoFactory: 'Fl32_Web_Back_Dto_Info__Factory$',
|
|
39
|
+
STAGE: 'Fl32_Web_Back_Enum_Stage$',
|
|
40
|
+
});
|
|
37
41
|
```
|
|
38
42
|
|
|
39
43
|
```js
|
|
40
|
-
//
|
|
44
|
+
// src/Server/Start.mjs
|
|
41
45
|
// @ts-check
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
};
|
|
47
|
+
/**
|
|
48
|
+
* @namespace App_Web_Server_Start
|
|
49
|
+
* @description Example application entry service
|
|
50
|
+
*/
|
|
48
51
|
|
|
49
|
-
export default class
|
|
52
|
+
export default class Start {
|
|
50
53
|
/**
|
|
51
|
-
* @param {
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* }} deps
|
|
54
|
+
* @param {object} deps
|
|
55
|
+
* @param {Fl32_Web_Back_PipelineEngine} deps.pipeline
|
|
56
|
+
* @param {Fl32_Web_Back_Server} deps.server
|
|
57
|
+
* @param {App_Web_Handler_Hello} deps.helloHandler
|
|
56
58
|
*/
|
|
57
59
|
constructor({pipeline, server, helloHandler}) {
|
|
58
60
|
this.execute = async function () {
|
|
@@ -61,6 +63,12 @@ export default class App_Web_Server_Start {
|
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
}
|
|
66
|
+
|
|
67
|
+
export const __deps__ = Object.freeze({
|
|
68
|
+
pipeline: 'Fl32_Web_Back_PipelineEngine$',
|
|
69
|
+
server: 'Fl32_Web_Back_Server$',
|
|
70
|
+
helloHandler: 'App_Web_Handler_Hello$',
|
|
71
|
+
});
|
|
64
72
|
```
|
|
65
73
|
|
|
66
74
|
```js
|
|
@@ -75,5 +83,5 @@ Consumer notes:
|
|
|
75
83
|
- Application modules do not construct collaborators directly and do not call `new` for DI-managed handlers or infrastructure services.
|
|
76
84
|
- `server.start()` locks handler registration for the runtime lifetime of that server instance.
|
|
77
85
|
- Built-in server defaults may also be supplied through `Fl32_Web_Back_Config_Runtime__Factory$` as `{port, type, tls}`, where `tls` is owned by the runtime component `Fl32_Web_Back_Config_Runtime_Tls$`.
|
|
78
|
-
- If your application already has its own transport layer, inject `Fl32_Web_Back_PipelineEngine
|
|
86
|
+
- If your application already has its own transport layer, inject `Fl32_Web_Back_PipelineEngine$`, call `pipeline.lockHandlers()` during startup, and only then call `pipeline.onEventRequest(req, res)` from that adapter.
|
|
79
87
|
- A correct PROCESS handler ends the response and then marks the context completed.
|
package/ai/overview.md
CHANGED
|
@@ -10,7 +10,7 @@ Runtime startup configuration is exposed through `Fl32_Web_Back_Config_Runtime$`
|
|
|
10
10
|
|
|
11
11
|
Use this package when external code needs one of these roles:
|
|
12
12
|
|
|
13
|
-
- accept HTTP
|
|
13
|
+
- accept plain HTTP requests or secure web requests with the built-in server;
|
|
14
14
|
- run request handlers through a fixed three-stage lifecycle;
|
|
15
15
|
- register multiple independent handlers with deterministic ordering;
|
|
16
16
|
- serve static files through the built-in PROCESS-stage handler.
|
package/ai/rules.md
CHANGED
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
- Runtime is Node.js 20 or newer.
|
|
33
33
|
- The package is intended for long-running server processes.
|
|
34
34
|
- Process supervision, restart, scaling, reverse proxying, and load balancing are external concerns.
|
|
35
|
-
-
|
|
35
|
+
- Independent deployment instances should run as separate Node.js processes and must not rely on shared in-memory state between processes.
|
|
36
|
+
- The package does not guarantee isolated runtime-configuration state for multiple containers or runtime assemblies inside the same process.
|
|
36
37
|
|
|
37
38
|
## DI Usage Rules
|
|
38
39
|
|
|
@@ -42,3 +43,4 @@
|
|
|
42
43
|
- TLS startup configuration belongs to the dedicated runtime component `Fl32_Web_Back_Config_Runtime_Tls$`, even though consumers read it through `config.tls`.
|
|
43
44
|
- Configure runtime values during startup only; once the runtime configuration is frozen for use, consumers must treat `Fl32_Web_Back_Config_Runtime$` and `Fl32_Web_Back_Config_Runtime_Tls$` as immutable read-only state.
|
|
44
45
|
- Treat helper internals under deep implementation paths as non-essential unless the task specifically requires them. Preferred consumer entry points are the Pipeline Engine, Server, handler API, DTO factories, enums, and built-in handlers.
|
|
46
|
+
- Use `Object.freeze({})` for `__deps__` declarations in examples and application code that is meant to be container-managed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flancer32/teq-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Server-side web request coordination infrastructure for TeqFW modular monolith applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
]
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@teqfw/di": "^2.
|
|
44
|
+
"@teqfw/di": "^2.6.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.4.0"
|
package/src/Back/Api/Handler.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Api_Handler
|
|
5
|
+
* @description Interface for web request handlers used by the Pipeline Engine.
|
|
4
6
|
* @interface
|
|
5
7
|
*/
|
|
6
|
-
// @ts-check
|
|
7
8
|
export default class Fl32_Web_Back_Api_Handler {
|
|
8
9
|
constructor() {
|
|
9
10
|
/**
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Config_Runtime_Tls
|
|
5
|
+
* @description TLS runtime configuration wrapper and factory wiring.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
|
|
6
8
|
export class Data {
|
|
7
9
|
/** @type {string|undefined} */
|
|
@@ -12,6 +14,15 @@ export class Data {
|
|
|
12
14
|
key;
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
export class Params {
|
|
18
|
+
/** @type {unknown|undefined} */
|
|
19
|
+
ca;
|
|
20
|
+
/** @type {unknown|undefined} */
|
|
21
|
+
cert;
|
|
22
|
+
/** @type {unknown|undefined} */
|
|
23
|
+
key;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
/** @type {Fl32_Web_Back_Config_Runtime_Tls} */
|
|
16
27
|
const cfg = new Data();
|
|
17
28
|
let frozen = false;
|
|
@@ -52,7 +63,7 @@ export class Factory {
|
|
|
52
63
|
*/
|
|
53
64
|
constructor({cast}) {
|
|
54
65
|
/**
|
|
55
|
-
* @param {
|
|
66
|
+
* @param {Fl32_Web_Back_Config_Runtime_Tls__Params} [params]
|
|
56
67
|
*/
|
|
57
68
|
this.configure = function (params = {}) {
|
|
58
69
|
if (frozen) throw new Error('Runtime configuration is frozen.');
|
|
@@ -86,8 +97,7 @@ export class Factory {
|
|
|
86
97
|
* `Factory` is the DI-managed component described by `__deps__`.
|
|
87
98
|
*/
|
|
88
99
|
export const __deps__ = Object.freeze({
|
|
89
|
-
|
|
90
|
-
Factory: {
|
|
100
|
+
Factory: Object.freeze({
|
|
91
101
|
cast: 'Fl32_Web_Back_Helper_Cast$',
|
|
92
|
-
},
|
|
102
|
+
}),
|
|
93
103
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Config_Runtime
|
|
5
|
+
* @description Runtime configuration wrapper and factory wiring.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
|
|
6
8
|
export class Data {
|
|
7
9
|
/** @type {number|undefined} */
|
|
@@ -50,7 +52,7 @@ export class Factory {
|
|
|
50
52
|
* @param {object} deps
|
|
51
53
|
* @param {Fl32_Web_Back_Helper_Cast} deps.cast
|
|
52
54
|
* @param {Fl32_Web_Back_Enum_Server_Type} deps.SERVER_TYPE
|
|
53
|
-
* @param {
|
|
55
|
+
* @param {Fl32_Web_Back_Config_Runtime_Tls__Factory} deps.tlsFactory
|
|
54
56
|
*/
|
|
55
57
|
constructor({cast, SERVER_TYPE, tlsFactory}) {
|
|
56
58
|
/**
|
|
@@ -70,10 +72,10 @@ export class Factory {
|
|
|
70
72
|
};
|
|
71
73
|
|
|
72
74
|
/**
|
|
73
|
-
* @returns {
|
|
75
|
+
* @returns {Fl32_Web_Back_Config_Runtime}
|
|
74
76
|
*/
|
|
75
77
|
this.freeze = function () {
|
|
76
|
-
if (frozen) return;
|
|
78
|
+
if (frozen) return proxy;
|
|
77
79
|
if (cfg.port === undefined) cfg.port = 3000;
|
|
78
80
|
if (cfg.type === undefined) cfg.type = SERVER_TYPE.HTTP;
|
|
79
81
|
const tls = tlsFactory.freeze();
|
|
@@ -86,6 +88,7 @@ export class Factory {
|
|
|
86
88
|
}
|
|
87
89
|
Object.freeze(cfg);
|
|
88
90
|
frozen = true;
|
|
91
|
+
return proxy;
|
|
89
92
|
};
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -97,10 +100,9 @@ export class Factory {
|
|
|
97
100
|
* `Factory` is the DI-managed component described by `__deps__`.
|
|
98
101
|
*/
|
|
99
102
|
export const __deps__ = Object.freeze({
|
|
100
|
-
|
|
101
|
-
Factory: {
|
|
103
|
+
Factory: Object.freeze({
|
|
102
104
|
cast: 'Fl32_Web_Back_Helper_Cast$',
|
|
103
105
|
SERVER_TYPE: 'Fl32_Web_Back_Enum_Server_Type$',
|
|
104
106
|
tlsFactory: 'Fl32_Web_Back_Config_Runtime_Tls__Factory$',
|
|
105
|
-
},
|
|
107
|
+
}),
|
|
106
108
|
});
|
package/src/Back/Dto/Info.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Dto_Info
|
|
5
|
+
* @description DTO describing handler registration and ordering metadata.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Dto_Info {
|
|
6
8
|
/**
|
|
7
9
|
* Handlers to run before this one.
|
|
@@ -56,7 +58,6 @@ export class Factory {
|
|
|
56
58
|
* DTO dependencies.
|
|
57
59
|
*/
|
|
58
60
|
export const __deps__ = Object.freeze({
|
|
59
|
-
default: {},
|
|
60
61
|
Factory: {
|
|
61
62
|
cast: 'Fl32_Web_Back_Helper_Cast$',
|
|
62
63
|
STAGE: 'Fl32_Web_Back_Enum_Stage$',
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Dto_RequestContext
|
|
5
|
+
* @description Request context passed through the pipeline lifecycle.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Dto_RequestContext {
|
|
6
8
|
constructor() {
|
|
7
9
|
/** @type {Fl32_Web_Node_Http_IncomingMessage|Fl32_Web_Node_Http2_ServerRequest} */
|
package/src/Back/Dto/Source.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Dto_Source
|
|
5
|
+
* @description Source DTO for static handler configuration.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Dto_Source {
|
|
6
8
|
/** @type {string} */
|
|
7
9
|
root;
|
|
@@ -43,7 +45,6 @@ export class Factory {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
export const __deps__ = Object.freeze({
|
|
46
|
-
default: {},
|
|
47
48
|
Factory: {
|
|
48
49
|
cast: 'Fl32_Web_Back_Helper_Cast$',
|
|
49
50
|
},
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Enum_Server_Type
|
|
5
|
+
* @description Enum-like DTO for built-in server transport modes.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Enum_Server_Type {
|
|
6
8
|
constructor() {
|
|
7
9
|
this.HTTP2 = 'http2';
|
package/src/Back/Enum/Stage.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Enum_Stage
|
|
5
|
+
* @description Enum-like DTO for web request processing stages.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Enum_Stage {
|
|
6
8
|
constructor() {
|
|
7
9
|
this.INIT = 'INIT';
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Pre_Log
|
|
5
|
+
* @description Logs basic request information at the beginning of the request lifecycle.
|
|
4
6
|
* @implements Fl32_Web_Back_Api_Handler
|
|
5
7
|
*/
|
|
6
|
-
// @ts-check
|
|
7
8
|
export default class Fl32_Web_Back_Handler_Pre_Log {
|
|
8
9
|
/**
|
|
9
10
|
* @param {object} deps
|
|
10
11
|
* @param {Fl32_Web_Back_Logger} deps.logger
|
|
11
|
-
* @param {
|
|
12
|
+
* @param {Fl32_Web_Back_Dto_Info__Factory} deps.dtoInfoFactory
|
|
12
13
|
* @param {Fl32_Web_Back_Enum_Stage} deps.STAGE
|
|
13
14
|
*/
|
|
14
15
|
constructor({logger, dtoInfoFactory, STAGE}) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static_A_Config
|
|
5
|
+
* @description Static asset config factory.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Handler_Static_A_Config {
|
|
6
8
|
static DEFAULT_FILES = ['index.html', 'index.htm', 'index.txt'];
|
|
7
9
|
/**
|
|
@@ -14,7 +16,7 @@ export default class Fl32_Web_Back_Handler_Static_A_Config {
|
|
|
14
16
|
* Normalize DTO fields into configuration object.
|
|
15
17
|
*
|
|
16
18
|
* @param {Fl32_Web_Back_Dto_Source} dto
|
|
17
|
-
* @returns {
|
|
19
|
+
* @returns {Fl32_Web_Back_Handler_Static_A_Config__Value}
|
|
18
20
|
* @throws {Error} When required fields are missing or invalid.
|
|
19
21
|
*/
|
|
20
22
|
this.create = (dto) => {
|
|
@@ -56,6 +58,17 @@ export default class Fl32_Web_Back_Handler_Static_A_Config {
|
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
export class Value {
|
|
62
|
+
/** @type {string} */
|
|
63
|
+
root;
|
|
64
|
+
/** @type {string} */
|
|
65
|
+
prefix;
|
|
66
|
+
/** @type {Record<string, string[]>|undefined} */
|
|
67
|
+
allow;
|
|
68
|
+
/** @type {string[]} */
|
|
69
|
+
defaults;
|
|
70
|
+
}
|
|
71
|
+
|
|
59
72
|
/**
|
|
60
73
|
* Dependencies for the static config factory.
|
|
61
74
|
*/
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static_A_Fallback
|
|
5
|
+
* @description Static asset fallback helper.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Handler_Static_A_Fallback {
|
|
6
8
|
/**
|
|
7
9
|
* @param {object} deps
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static_A_FileService
|
|
5
|
+
* @description Static file service.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Handler_Static_A_FileService {
|
|
6
8
|
/**
|
|
7
9
|
* @param {object} deps
|
|
@@ -19,7 +21,7 @@ export default class Fl32_Web_Back_Handler_Static_A_FileService {
|
|
|
19
21
|
/**
|
|
20
22
|
* Serve a file for given config and relative path.
|
|
21
23
|
*
|
|
22
|
-
* @param {
|
|
24
|
+
* @param {Fl32_Web_Back_Handler_Static_A_Config__Value} config
|
|
23
25
|
* @param {string} rel
|
|
24
26
|
* @param {Fl32_Web_Node_Http_IncomingMessage|Fl32_Web_Node_Http2_ServerRequest} req
|
|
25
27
|
* @param {Fl32_Web_Back_Response_Target} res
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static_A_Registry
|
|
5
|
+
* @description Static configuration registry.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Handler_Static_A_Registry {
|
|
6
8
|
/**
|
|
7
9
|
* @param {object} deps
|
|
@@ -34,7 +36,7 @@ export default class Fl32_Web_Back_Handler_Static_A_Registry {
|
|
|
34
36
|
* Find configuration by matching URL prefix.
|
|
35
37
|
*
|
|
36
38
|
* @param {string} url
|
|
37
|
-
* @returns {
|
|
39
|
+
* @returns {Fl32_Web_Back_Handler_Static_A_Registry__Match|null}
|
|
38
40
|
*/
|
|
39
41
|
this.find = function (url) {
|
|
40
42
|
for (const cfg of _configs) {
|
|
@@ -48,6 +50,13 @@ export default class Fl32_Web_Back_Handler_Static_A_Registry {
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
export class Match {
|
|
54
|
+
/** @type {Fl32_Web_Back_Handler_Static_A_Config__Value} */
|
|
55
|
+
config;
|
|
56
|
+
/** @type {string} */
|
|
57
|
+
rel;
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
/**
|
|
52
61
|
* Dependencies for the static registry helper.
|
|
53
62
|
*/
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static_A_Resolver
|
|
5
|
+
* @description Static path resolver.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Handler_Static_A_Resolver {
|
|
6
8
|
/**
|
|
7
9
|
* @param {object} deps
|
|
@@ -12,7 +14,7 @@ export default class Fl32_Web_Back_Handler_Static_A_Resolver {
|
|
|
12
14
|
* Resolve a filesystem path for given config and relative URL part.
|
|
13
15
|
* Applies allow rules and prevents path traversal.
|
|
14
16
|
*
|
|
15
|
-
* @param {
|
|
17
|
+
* @param {Fl32_Web_Back_Handler_Static_A_Config__Value} config
|
|
16
18
|
* @param {string} rel
|
|
17
19
|
* @returns {string|null}
|
|
18
20
|
* @throws {Error} On traversal or absolute rel paths.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Handler_Static
|
|
5
|
+
* @description Universal static-file PROCESS handler.
|
|
4
6
|
* @implements Fl32_Web_Back_Api_Handler
|
|
5
7
|
*/
|
|
6
|
-
// @ts-check
|
|
7
8
|
export default class Fl32_Web_Back_Handler_Static {
|
|
8
9
|
/**
|
|
9
10
|
* @param {object} deps
|
|
@@ -11,7 +12,7 @@ export default class Fl32_Web_Back_Handler_Static {
|
|
|
11
12
|
* @param {Fl32_Web_Back_Handler_Static_A_FileService} deps.fileService
|
|
12
13
|
* @param {Fl32_Web_Back_Helper_Respond} deps.respond
|
|
13
14
|
* @param {Fl32_Web_Back_Logger} deps.logger
|
|
14
|
-
* @param {
|
|
15
|
+
* @param {Fl32_Web_Back_Dto_Info__Factory} deps.dtoInfoFactory
|
|
15
16
|
* @param {Fl32_Web_Back_Enum_Stage} deps.STAGE
|
|
16
17
|
*/
|
|
17
18
|
constructor({registry, fileService, respond, logger, dtoInfoFactory, STAGE}) {
|
package/src/Back/Helper/Cast.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Helper_Cast
|
|
5
|
+
* @description Cast helper used by runtime configuration and DTO factories.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Helper_Cast {
|
|
6
8
|
constructor() {
|
|
7
9
|
/**
|
package/src/Back/Helper/Mime.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Helper_Mime
|
|
5
|
+
* @description MIME type helper with built-in mapping for common file extensions.
|
|
3
6
|
* Can be replaced or extended by the application via the DI container.
|
|
4
7
|
*/
|
|
5
|
-
// @ts-check
|
|
6
8
|
export default class Fl32_Web_Back_Helper_Mime {
|
|
7
9
|
constructor() {
|
|
8
10
|
/**
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Helper_Order_Kahn
|
|
5
|
+
* @description Sorts named handlers by relative `before` / `after` constraints using Kahn's algorithm.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Helper_Order_Kahn {
|
|
6
8
|
constructor() {
|
|
7
9
|
/**
|
package/src/Back/Logger.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Logger
|
|
5
|
+
* @description Simple logger implementation that delegates to the native console.
|
|
3
6
|
*/
|
|
4
|
-
// @ts-check
|
|
5
7
|
export default class Fl32_Web_Back_Logger {
|
|
6
8
|
constructor() {
|
|
7
9
|
/**
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `INIT -> PROCESS -> FINALIZE`.
|
|
4
|
+
* @namespace Fl32_Web_Back_PipelineEngine
|
|
5
|
+
* @description Pipeline Engine is the single request-lifecycle coordination component.
|
|
6
|
+
* It executes handlers in three deterministic stages: `INIT -> PROCESS -> FINALIZE`.
|
|
5
7
|
*/
|
|
6
|
-
// @ts-check
|
|
7
8
|
|
|
8
9
|
const KEY_STAGE = Symbol('stage');
|
|
9
10
|
|
|
@@ -11,7 +12,7 @@ export default class Fl32_Web_Back_PipelineEngine {
|
|
|
11
12
|
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
12
13
|
/**
|
|
13
14
|
* @param {object} params
|
|
14
|
-
* @param {
|
|
15
|
+
* @param {Fl32_Web_Back_Dto_RequestContext__Factory} params.dtoRequestContextFactory
|
|
15
16
|
* @param {Fl32_Web_Back_Logger} params.logger
|
|
16
17
|
* @param {Fl32_Web_Back_Helper_Respond} params.respond
|
|
17
18
|
* @param {Fl32_Web_Back_Helper_Order_Kahn} params.helpOrder
|
|
@@ -144,7 +145,7 @@ export default class Fl32_Web_Back_PipelineEngine {
|
|
|
144
145
|
*/
|
|
145
146
|
this.onEventRequest = async function (req, res) {
|
|
146
147
|
if (!isLocked) {
|
|
147
|
-
|
|
148
|
+
throw new Error('Pipeline handlers must be locked before request execution');
|
|
148
149
|
}
|
|
149
150
|
/** @type {Fl32_Web_Back_Dto_RequestContext & {[KEY_STAGE]: string|null}} */
|
|
150
151
|
const context = createRequestContext(req, res);
|
|
@@ -162,6 +163,10 @@ export default class Fl32_Web_Back_PipelineEngine {
|
|
|
162
163
|
if (context.isCompleted()) {
|
|
163
164
|
break;
|
|
164
165
|
}
|
|
166
|
+
if (!respond.isWritable(res)) {
|
|
167
|
+
context.completed = true;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
165
170
|
try {
|
|
166
171
|
await runHandler(handler, STAGE.PROCESS, context);
|
|
167
172
|
} catch (error) {
|
package/src/Back/Server.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* @namespace Fl32_Web_Back_Server
|
|
5
|
+
* @description Web server implementation supporting HTTP/1 and HTTP/2 protocols.
|
|
3
6
|
* Handles incoming requests and delegates them to the Pipeline Engine.
|
|
4
7
|
*/
|
|
5
|
-
// @ts-check
|
|
6
8
|
export default class Fl32_Web_Back_Server {
|
|
7
9
|
/**
|
|
8
10
|
* @param {object} deps
|
package/types.d.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
declare global {
|
|
2
2
|
type Fl32_Web_Back_Api_Handler = import("./src/Back/Api/Handler.mjs").default;
|
|
3
3
|
type Fl32_Web_Back_Config_Runtime = import("./src/Back/Config/Runtime.mjs").Data;
|
|
4
|
-
type
|
|
4
|
+
type Fl32_Web_Back_Config_Runtime__Factory = import("./src/Back/Config/Runtime.mjs").Factory;
|
|
5
5
|
type Fl32_Web_Back_Config_Runtime_Tls = import("./src/Back/Config/Runtime/Tls.mjs").Data;
|
|
6
|
-
type
|
|
7
|
-
type
|
|
6
|
+
type Fl32_Web_Back_Config_Runtime_Tls__Factory = import("./src/Back/Config/Runtime/Tls.mjs").Factory;
|
|
7
|
+
type Fl32_Web_Back_Config_Runtime_Tls__Params = import("./src/Back/Config/Runtime/Tls.mjs").Params;
|
|
8
8
|
type Fl32_Web_Back_Dto_Info = import("./src/Back/Dto/Info.mjs").default;
|
|
9
|
-
type
|
|
9
|
+
type Fl32_Web_Back_Dto_Info__Factory = import("./src/Back/Dto/Info.mjs").Factory;
|
|
10
10
|
type Fl32_Web_Back_Dto_RequestContext = import("./src/Back/Dto/RequestContext.mjs").default;
|
|
11
|
-
type
|
|
11
|
+
type Fl32_Web_Back_Dto_RequestContext__Factory = import("./src/Back/Dto/RequestContext.mjs").Factory;
|
|
12
12
|
type Fl32_Web_Back_Dto_Source = import("./src/Back/Dto/Source.mjs").default;
|
|
13
|
-
type
|
|
13
|
+
type Fl32_Web_Back_Dto_Source__Factory = import("./src/Back/Dto/Source.mjs").Factory;
|
|
14
14
|
type Fl32_Web_Back_Enum_Server_Type = import("./src/Back/Enum/Server/Type.mjs").default;
|
|
15
15
|
type Fl32_Web_Back_Enum_Stage = import("./src/Back/Enum/Stage.mjs").default;
|
|
16
16
|
type Fl32_Web_Back_Handler_Pre_Log = import("./src/Back/Handler/Pre/Log.mjs").default;
|
|
17
17
|
type Fl32_Web_Back_Handler_Static = import("./src/Back/Handler/Static.mjs").default;
|
|
18
18
|
type Fl32_Web_Back_Handler_Static_A_Config = import("./src/Back/Handler/Static/A/Config.mjs").default;
|
|
19
|
-
type
|
|
19
|
+
type Fl32_Web_Back_Handler_Static_A_Config__Value = import("./src/Back/Handler/Static/A/Config.mjs").Value;
|
|
20
20
|
type Fl32_Web_Back_Handler_Static_A_Fallback = import("./src/Back/Handler/Static/A/Fallback.mjs").default;
|
|
21
21
|
type Fl32_Web_Back_Handler_Static_A_FileService = import("./src/Back/Handler/Static/A/FileService.mjs").default;
|
|
22
|
-
type
|
|
22
|
+
type Fl32_Web_Back_Handler_Static_A_Registry__Match = import("./src/Back/Handler/Static/A/Registry.mjs").Match;
|
|
23
23
|
type Fl32_Web_Back_Handler_Static_A_Registry = import("./src/Back/Handler/Static/A/Registry.mjs").default;
|
|
24
24
|
type Fl32_Web_Back_Handler_Static_A_Resolver = import("./src/Back/Handler/Static/A/Resolver.mjs").default;
|
|
25
25
|
type Fl32_Web_Back_Helper_Cast = import("./src/Back/Helper/Cast.mjs").default;
|