@flancer32/teq-web 0.4.0 → 0.5.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 +20 -0
- package/README.md +236 -127
- package/ai/AGENTS.md +36 -0
- package/ai/abstractions.md +75 -0
- package/ai/examples/minimal-server.md +78 -0
- package/ai/overview.md +27 -0
- package/ai/rules.md +41 -0
- package/package.json +43 -37
- package/src/Back/Api/Handler.mjs +26 -0
- package/src/Back/{Defaults.js → Defaults.mjs} +6 -1
- package/src/Back/Dto/Info.mjs +66 -0
- package/src/Back/Dto/{Handler/Source.js → Source.mjs} +26 -23
- package/src/Back/Enum/Server/Type.mjs +13 -0
- package/src/Back/Enum/Stage.mjs +13 -0
- package/src/Back/Handler/Pre/Log.mjs +59 -0
- package/src/Back/Handler/Static/A/{Config.js → Config.mjs} +14 -3
- package/src/Back/Handler/Static/A/{Fallback.js → Fallback.mjs} +16 -4
- package/src/Back/Handler/Static/A/{FileService.js → FileService.mjs} +31 -14
- package/src/Back/Handler/Static/A/{Registry.js → Registry.mjs} +18 -6
- package/src/Back/Handler/Static/A/{Resolver.js → Resolver.mjs} +13 -2
- package/src/Back/Handler/Static.mjs +83 -0
- package/src/Back/Helper/Cast.mjs +116 -0
- package/src/Back/Helper/{Mime.js → Mime.mjs} +2 -0
- package/src/Back/Helper/Order/Kahn.mjs +69 -0
- package/src/Back/Helper/{Respond.js → Respond.mjs} +14 -3
- package/src/Back/Logger.mjs +57 -0
- package/src/Back/PipelineEngine.mjs +228 -0
- package/src/Back/Server/Config/{Tls.js → Tls.mjs} +35 -33
- package/src/Back/Server/Config.mjs +69 -0
- package/src/Back/{Server.js → Server.mjs} +35 -24
- package/types.d.ts +27 -22
- package/src/AGENTS.md +0 -108
- package/src/Back/Api/Handler.js +0 -26
- package/src/Back/Dispatcher.js +0 -115
- package/src/Back/Dto/Handler/Info.js +0 -68
- package/src/Back/Enum/Server/Type.js +0 -12
- package/src/Back/Enum/Stage.js +0 -10
- package/src/Back/Handler/Pre/Log.js +0 -45
- package/src/Back/Handler/Static.js +0 -63
- package/src/Back/Helper/Cast.js +0 -114
- package/src/Back/Helper/Order/Kahn.js +0 -66
- package/src/Back/Logger.js +0 -53
- package/src/Back/Server/Config.js +0 -69
- package/teqfw.json +0 -8
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const __deps__ = Object.freeze({
|
|
4
|
+
cast: 'Fl32_Web_Back_Helper_Cast$',
|
|
5
|
+
SERVER_TYPE: 'Fl32_Web_Back_Enum_Server_Type$',
|
|
6
|
+
tlsFactory: 'Fl32_Web_Back_Server_Config_Tls__Factory$',
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {object} Fl32_Web_Back_Server_ConfigFactoryParams
|
|
11
|
+
* @property {Fl32_Web_Back_Helper_Cast} cast
|
|
12
|
+
* @property {Fl32_Web_Back_Enum_Server_Type} SERVER_TYPE
|
|
13
|
+
* @property {Fl32_Web_Back_Server_Config_Tls$Factory} tlsFactory
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export default class Fl32_Web_Back_Server_Config {
|
|
17
|
+
/**
|
|
18
|
+
* Port to listening (3000).
|
|
19
|
+
*
|
|
20
|
+
* @type {number}
|
|
21
|
+
*/
|
|
22
|
+
port;
|
|
23
|
+
/**
|
|
24
|
+
* @type {string}
|
|
25
|
+
* @see Fl32_Web_Back_Enum_Server_Type
|
|
26
|
+
*/
|
|
27
|
+
type;
|
|
28
|
+
/**
|
|
29
|
+
* TLS configuration for HTTPS server.
|
|
30
|
+
* @type {Fl32_Web_Back_Server_Config_Tls|undefined}
|
|
31
|
+
*/
|
|
32
|
+
tls;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class Factory {
|
|
36
|
+
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
37
|
+
/**
|
|
38
|
+
* @param {Fl32_Web_Back_Server_ConfigFactoryParams} params
|
|
39
|
+
*/
|
|
40
|
+
constructor(
|
|
41
|
+
{
|
|
42
|
+
cast,
|
|
43
|
+
SERVER_TYPE,
|
|
44
|
+
tlsFactory,
|
|
45
|
+
}
|
|
46
|
+
) {
|
|
47
|
+
/* eslint-enable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
48
|
+
/**
|
|
49
|
+
* @param {Fl32_Web_Back_Server_Config|object} [data]
|
|
50
|
+
* @returns {Fl32_Web_Back_Server_Config}
|
|
51
|
+
*/
|
|
52
|
+
this.create = function (data) {
|
|
53
|
+
const res = new Fl32_Web_Back_Server_Config();
|
|
54
|
+
if (data) {
|
|
55
|
+
res.port = cast.int(data.port);
|
|
56
|
+
res.type = cast.enum(data.type, SERVER_TYPE, {lower: true});
|
|
57
|
+
|
|
58
|
+
if (data.tls) {
|
|
59
|
+
res.tls = tlsFactory.create(data.tls);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (res.type === SERVER_TYPE.HTTPS && !res.tls) {
|
|
63
|
+
throw new Error('TLS configuration is required for HTTPS server type');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return Object.freeze(res);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,35 +1,47 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Web server implementation supporting HTTP/1 and HTTP/2 protocols.
|
|
3
|
-
* Handles incoming requests and delegates them to the
|
|
4
|
-
*
|
|
5
|
-
* @property {function(): module:http.Server} getInstance - Returns the server instance.
|
|
6
|
-
* @property {function(Fl32_Web_Back_Server_Config.Dto): Promise<void>} start - Starts the server with given configuration.
|
|
7
|
-
* @property {function(): Promise<void>} stop - Stops the server.
|
|
5
|
+
* Handles incoming requests and delegates them to the Pipeline Engine.
|
|
8
6
|
*/
|
|
7
|
+
export const __deps__ = Object.freeze({
|
|
8
|
+
http: 'node_http',
|
|
9
|
+
http2: 'node_http2',
|
|
10
|
+
DEF: 'Fl32_Web_Back_Defaults$',
|
|
11
|
+
logger: 'Fl32_Web_Back_Logger$',
|
|
12
|
+
pipelineEngine: 'Fl32_Web_Back_PipelineEngine$',
|
|
13
|
+
SERVER_TYPE: 'Fl32_Web_Back_Enum_Server_Type$',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} Fl32_Web_Back_ServerConstructorParams
|
|
18
|
+
* @property {typeof import('node:http')} http
|
|
19
|
+
* @property {typeof import('node:http2')} http2
|
|
20
|
+
* @property {import('./Defaults.mjs').default} DEF
|
|
21
|
+
* @property {Fl32_Web_Back_Logger} logger
|
|
22
|
+
* @property {Fl32_Web_Back_PipelineEngine} pipelineEngine
|
|
23
|
+
* @property {Fl32_Web_Back_Enum_Server_Type} SERVER_TYPE
|
|
24
|
+
*/
|
|
25
|
+
|
|
9
26
|
export default class Fl32_Web_Back_Server {
|
|
10
27
|
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
11
28
|
/**
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {typeof import('node:http2')} http2
|
|
14
|
-
* @param {Fl32_Web_Back_Defaults} DEF
|
|
15
|
-
* @param {Fl32_Web_Back_Logger} logger
|
|
16
|
-
* @param {Fl32_Web_Back_Dispatcher} dispatcher
|
|
17
|
-
* @param {typeof Fl32_Web_Back_Enum_Server_Type} SERVER_TYPE
|
|
29
|
+
* @param {Fl32_Web_Back_ServerConstructorParams} deps
|
|
18
30
|
*/
|
|
19
31
|
constructor(
|
|
20
32
|
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
http,
|
|
34
|
+
http2,
|
|
35
|
+
DEF,
|
|
36
|
+
logger,
|
|
37
|
+
pipelineEngine,
|
|
38
|
+
SERVER_TYPE,
|
|
27
39
|
}
|
|
28
40
|
) {
|
|
29
41
|
/* eslint-enable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
30
42
|
// VARS
|
|
31
|
-
const {createServer} = http;
|
|
32
|
-
const {createServer: createServerH2, createSecureServer} = http2;
|
|
43
|
+
const { createServer } = http;
|
|
44
|
+
const { createServer: createServerH2, createSecureServer } = http2;
|
|
33
45
|
/** @type {module:http.Server} */
|
|
34
46
|
let _instance;
|
|
35
47
|
|
|
@@ -41,12 +53,11 @@ export default class Fl32_Web_Back_Server {
|
|
|
41
53
|
|
|
42
54
|
/**
|
|
43
55
|
* Starts the server with optional configuration.
|
|
44
|
-
* @param {Fl32_Web_Back_Server_Config
|
|
56
|
+
* @param {Fl32_Web_Back_Server_Config} [cfg]
|
|
45
57
|
* @returns {Promise<void>}
|
|
46
58
|
*/
|
|
47
59
|
this.start = async function (cfg) {
|
|
48
|
-
|
|
49
|
-
dispatcher.orderHandlers();
|
|
60
|
+
pipelineEngine.lockHandlers();
|
|
50
61
|
// create server
|
|
51
62
|
const port = cfg?.port ?? DEF.PORT;
|
|
52
63
|
const type = cfg?.type ?? SERVER_TYPE.HTTP;
|
|
@@ -69,7 +80,7 @@ export default class Fl32_Web_Back_Server {
|
|
|
69
80
|
throw new Error(`Server type '${type}' is not supported`);
|
|
70
81
|
}
|
|
71
82
|
|
|
72
|
-
_instance.on('request',
|
|
83
|
+
_instance.on('request', pipelineEngine.handleRequest);
|
|
73
84
|
_instance.listen(port);
|
|
74
85
|
};
|
|
75
86
|
|
|
@@ -89,4 +100,4 @@ export default class Fl32_Web_Back_Server {
|
|
|
89
100
|
}
|
|
90
101
|
};
|
|
91
102
|
}
|
|
92
|
-
}
|
|
103
|
+
}
|
package/types.d.ts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
declare global {
|
|
2
|
-
type Fl32_Web_Back_Api_Handler = import("./src/Back/Api/Handler.
|
|
3
|
-
type Fl32_Web_Back_Defaults = import("./src/Back/Defaults.
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
type
|
|
8
|
-
type
|
|
9
|
-
type
|
|
10
|
-
type
|
|
11
|
-
type
|
|
12
|
-
type
|
|
13
|
-
type
|
|
14
|
-
type
|
|
15
|
-
type
|
|
16
|
-
type
|
|
17
|
-
type
|
|
18
|
-
type
|
|
19
|
-
type
|
|
20
|
-
type
|
|
21
|
-
type
|
|
22
|
-
type
|
|
23
|
-
type
|
|
2
|
+
type Fl32_Web_Back_Api_Handler = import("./src/Back/Api/Handler.mjs").default;
|
|
3
|
+
type Fl32_Web_Back_Defaults = import("./src/Back/Defaults.mjs").default;
|
|
4
|
+
type Fl32_Web_Back_Dto_Info = import("./src/Back/Dto/Info.mjs").default;
|
|
5
|
+
type Fl32_Web_Back_Dto_Info$Factory = import("./src/Back/Dto/Info.mjs").Factory;
|
|
6
|
+
type Fl32_Web_Back_Dto_Source = import("./src/Back/Dto/Source.mjs").default;
|
|
7
|
+
type Fl32_Web_Back_Dto_Source$Factory = import("./src/Back/Dto/Source.mjs").Factory;
|
|
8
|
+
type Fl32_Web_Back_Enum_Server_Type = import("./src/Back/Enum/Server/Type.mjs").default;
|
|
9
|
+
type Fl32_Web_Back_Enum_Stage = import("./src/Back/Enum/Stage.mjs").default;
|
|
10
|
+
type Fl32_Web_Back_Handler_Pre_Log = import("./src/Back/Handler/Pre/Log.mjs").default;
|
|
11
|
+
type Fl32_Web_Back_Handler_Static = import("./src/Back/Handler/Static.mjs").default;
|
|
12
|
+
type Fl32_Web_Back_Handler_Static_A_Config = import("./src/Back/Handler/Static/A/Config.mjs").default;
|
|
13
|
+
type Fl32_Web_Back_Handler_Static_A_Fallback = import("./src/Back/Handler/Static/A/Fallback.mjs").default;
|
|
14
|
+
type Fl32_Web_Back_Handler_Static_A_FileService = import("./src/Back/Handler/Static/A/FileService.mjs").default;
|
|
15
|
+
type Fl32_Web_Back_Handler_Static_A_Registry = import("./src/Back/Handler/Static/A/Registry.mjs").default;
|
|
16
|
+
type Fl32_Web_Back_Handler_Static_A_Resolver = import("./src/Back/Handler/Static/A/Resolver.mjs").default;
|
|
17
|
+
type Fl32_Web_Back_Helper_Cast = import("./src/Back/Helper/Cast.mjs").default;
|
|
18
|
+
type Fl32_Web_Back_Helper_Mime = import("./src/Back/Helper/Mime.mjs").default;
|
|
19
|
+
type Fl32_Web_Back_Helper_Order_Kahn = import("./src/Back/Helper/Order/Kahn.mjs").default;
|
|
20
|
+
type Fl32_Web_Back_Helper_Respond = import("./src/Back/Helper/Respond.mjs").default;
|
|
21
|
+
type Fl32_Web_Back_Logger = import("./src/Back/Logger.mjs").default;
|
|
22
|
+
type Fl32_Web_Back_PipelineEngine = import("./src/Back/PipelineEngine.mjs").default;
|
|
23
|
+
type Fl32_Web_Back_Server = import("./src/Back/Server.mjs").default;
|
|
24
|
+
type Fl32_Web_Back_Server_Config = import("./src/Back/Server/Config.mjs").default;
|
|
25
|
+
type Fl32_Web_Back_Server_Config$Factory = import("./src/Back/Server/Config.mjs").Factory;
|
|
26
|
+
type Fl32_Web_Back_Server_Config_Tls = import("./src/Back/Server/Config/Tls.mjs").default;
|
|
27
|
+
type Fl32_Web_Back_Server_Config_Tls$Factory = import("./src/Back/Server/Config/Tls.mjs").Factory;
|
|
24
28
|
}
|
|
29
|
+
|
|
25
30
|
export {};
|
package/src/AGENTS.md
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# AI Agents Configuration for Source Directory
|
|
2
|
-
|
|
3
|
-
This document defines **long-term, project-agnostic** conventions that AI agents must follow when reading, creating, refactoring, or testing code under any `src/` directory. These guidelines are **permanent** and apply to **all** tasks in this area.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Directory & File Organization
|
|
8
|
-
|
|
9
|
-
* **AZ-structuring**
|
|
10
|
-
|
|
11
|
-
* **A-struct**: decompose a single “root” module into its private implementation parts under an `A/` subfolder.
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
src/Feature/Component.js
|
|
15
|
-
src/Feature/Component/A/Part1.js
|
|
16
|
-
src/Feature/Component/A/Part2.js
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Files under `A/` are private to their parent.
|
|
20
|
-
* **Z-struct**: helper modules whose changes do not affect siblings live under a `Z/` subfolder.
|
|
21
|
-
|
|
22
|
-
* **Visibility boundaries**: anything **outside** `A/` or `Z/` is public API.
|
|
23
|
-
|
|
24
|
-
* **Role → Feature layering**
|
|
25
|
-
|
|
26
|
-
* First level: by architectural layer (e.g. `Back/`, `Front/`, `Shared/`).
|
|
27
|
-
* Second level: by business feature or component.
|
|
28
|
-
|
|
29
|
-
* **Mirror in tests**
|
|
30
|
-
|
|
31
|
-
* For every `src/.../X.js` there must be a matching `test/unit/.../X.test.mjs` with the same relative path and filename.
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 2. Class Naming (FQN)
|
|
36
|
-
|
|
37
|
-
* Map file path to fully qualified class name (FQN). Example:
|
|
38
|
-
|
|
39
|
-
```text
|
|
40
|
-
src/Back/Handler/Static/A/Config.js => class Back_Handler_Static_A_Config
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## 3. Dependency Injection, `this` & Closures
|
|
46
|
-
|
|
47
|
-
* **DI Container**
|
|
48
|
-
|
|
49
|
-
* Inject all external services (file system, path, network, helpers, loggers, factories, enums) via a DI container.
|
|
50
|
-
* **Private state via closure**
|
|
51
|
-
|
|
52
|
-
* Do **not** assign injected dependencies to `this`.
|
|
53
|
-
* Capture each in a `const` inside the constructor and expose only public methods.
|
|
54
|
-
|
|
55
|
-
```js
|
|
56
|
-
class Example {
|
|
57
|
-
constructor({helperService, logger}) {
|
|
58
|
-
this.handle = (req, res) => {
|
|
59
|
-
if (!helperService.isWritable(res)) return false;
|
|
60
|
-
logger.info('Processing');
|
|
61
|
-
return true;
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## 4. Comments & Annotations
|
|
70
|
-
|
|
71
|
-
* **Language**: all comments and JSDoc must be in **English**.
|
|
72
|
-
* **JSDoc**: use `@param {Type}` and `@returns {Type}` on every public method.
|
|
73
|
-
* **Class annotation**: annotate all classes with a JSDoc `@class` tag and description.
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 5. Error Handling
|
|
78
|
-
|
|
79
|
-
* **Module-level**
|
|
80
|
-
|
|
81
|
-
* Do **not** catch all exceptions in each module.
|
|
82
|
-
* Catch only **expected, domain-specific** errors when a meaningful fallback exists.
|
|
83
|
-
* **Top-level handler**
|
|
84
|
-
|
|
85
|
-
* Wrap the entire pipeline in a single `try/catch` at the entry point.
|
|
86
|
-
* In that catch, use `logger.exception(error)` and return a safe default (`false`, `null`, or `[]`).
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## 6. Testing Conventions
|
|
91
|
-
|
|
92
|
-
Refer to the [AI Agent Unit Testing Instructions](../test/unit/AGENTS.md) for project-specific testing guidelines.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## 7. Ongoing Responsibilities
|
|
97
|
-
|
|
98
|
-
AI agents must always:
|
|
99
|
-
|
|
100
|
-
1. **Enforce AZ-structuring** when adding or refactoring code.
|
|
101
|
-
2. **Preserve FQN mapping** between file paths and class names.
|
|
102
|
-
3. **Use DI + closures**—never attach injected services to `this`.
|
|
103
|
-
4. **Write English JSDoc** for every new or modified public API, including `@class` on all classes.
|
|
104
|
-
5. **Catch and log errors** at the top level; handle known cases locally.
|
|
105
|
-
6. **Generate or update unit tests** with full coverage for every behavior change (see unit testing guidelines).
|
|
106
|
-
7. **Maintain test-source mirror** so no source file exists without a corresponding test.
|
|
107
|
-
|
|
108
|
-
These policies are **permanent** and must be validated on every code change.
|
package/src/Back/Api/Handler.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface for web request handlers used by the dispatcher in this plugin.
|
|
3
|
-
* Defines the structure and behavior of a handler.
|
|
4
|
-
*
|
|
5
|
-
* @interface
|
|
6
|
-
*/
|
|
7
|
-
export default class Fl32_Web_Back_Api_Handler {
|
|
8
|
-
/* eslint-disable no-unused-vars */
|
|
9
|
-
/**
|
|
10
|
-
* Handles the incoming web request.
|
|
11
|
-
* @param {module:http.IncomingMessage|module:http2.Http2ServerRequest} req - The incoming HTTP request object.
|
|
12
|
-
* @param {module:http.ServerResponse|module:http2.Http2ServerResponse} res - The HTTP response object.
|
|
13
|
-
* @returns {Promise<boolean>} - Returns true if the request was handled, false otherwise.
|
|
14
|
-
*/
|
|
15
|
-
async handle(req, res) {
|
|
16
|
-
throw new Error('Method not implemented');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Provides metadata for dispatcher registration.
|
|
21
|
-
* @returns {Fl32_Web_Back_Dto_Handler_Info.Dto}
|
|
22
|
-
*/
|
|
23
|
-
getRegistrationInfo() {
|
|
24
|
-
throw new Error('Method not implemented');
|
|
25
|
-
}
|
|
26
|
-
}
|
package/src/Back/Dispatcher.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dispatcher for HTTP(S) requests with three-stage handler execution: pre, process, post.
|
|
3
|
-
*
|
|
4
|
-
* Handlers are registered via `addHandler()` and activated by `orderHandlers()`.
|
|
5
|
-
* On each request, pre-handlers run first, then process-handlers (until one returns true),
|
|
6
|
-
* and finally post-handlers are always executed.
|
|
7
|
-
*
|
|
8
|
-
* If no process handler responds, a 404 is sent. If one throws, a 500 is returned.
|
|
9
|
-
*/
|
|
10
|
-
export default class Fl32_Web_Back_Dispatcher {
|
|
11
|
-
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
12
|
-
/**
|
|
13
|
-
* @param {Fl32_Web_Back_Logger} logger
|
|
14
|
-
* @param {Fl32_Web_Back_Helper_Respond} respond
|
|
15
|
-
* @param {Fl32_Web_Back_Helper_Order_Kahn} helpOrder
|
|
16
|
-
* @param {typeof Fl32_Web_Back_Enum_Stage} STAGE
|
|
17
|
-
*/
|
|
18
|
-
constructor(
|
|
19
|
-
{
|
|
20
|
-
Fl32_Web_Back_Logger$: logger,
|
|
21
|
-
Fl32_Web_Back_Helper_Respond$: respond,
|
|
22
|
-
Fl32_Web_Back_Helper_Order_Kahn$: helpOrder,
|
|
23
|
-
Fl32_Web_Back_Enum_Stage$: STAGE,
|
|
24
|
-
}
|
|
25
|
-
) {
|
|
26
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
27
|
-
// VARS
|
|
28
|
-
/** @type {Map<string, Fl32_Web_Back_Api_Handler>} */
|
|
29
|
-
const _handlers = new Map();
|
|
30
|
-
|
|
31
|
-
/** @type {Fl32_Web_Back_Api_Handler[]} */
|
|
32
|
-
let _pre = [], _process = [], _post = [];
|
|
33
|
-
|
|
34
|
-
// MAIN
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Registers a handler. Requires a unique name and stage.
|
|
38
|
-
*
|
|
39
|
-
* @param {Fl32_Web_Back_Api_Handler} handler
|
|
40
|
-
*/
|
|
41
|
-
this.addHandler = function (handler) {
|
|
42
|
-
const info = handler.getRegistrationInfo();
|
|
43
|
-
_handlers.set(info.name, handler);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Executes registered handlers for one HTTP request.
|
|
48
|
-
*
|
|
49
|
-
* @param {module:http.IncomingMessage|module:http2.Http2ServerRequest} req
|
|
50
|
-
* @param {module:http.ServerResponse|module:http2.Http2ServerResponse} res
|
|
51
|
-
* @returns {Promise<void>}
|
|
52
|
-
*/
|
|
53
|
-
this.onEventRequest = async function (req, res) {
|
|
54
|
-
try {
|
|
55
|
-
// Execute all pre-handlers (errors are isolated)
|
|
56
|
-
for (const h of _pre) {
|
|
57
|
-
try {
|
|
58
|
-
await h.handle(req, res);
|
|
59
|
-
} catch (e) {
|
|
60
|
-
logger.exception(e);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Execute process-handlers (stop at first successful)
|
|
65
|
-
let handled = false;
|
|
66
|
-
for (const h of _process) {
|
|
67
|
-
try {
|
|
68
|
-
handled = await h.handle(req, res);
|
|
69
|
-
if (handled) break;
|
|
70
|
-
} catch (e) {
|
|
71
|
-
logger.exception(e);
|
|
72
|
-
respond.code500_InternalServerError({res, body: e?.message});
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// If not handled at all and no error occurred
|
|
78
|
-
if (respond.isWritable(res)) {
|
|
79
|
-
logger.error(`404 Not Found: ${req.url}`);
|
|
80
|
-
respond.code404_NotFound({res});
|
|
81
|
-
}
|
|
82
|
-
} finally {
|
|
83
|
-
// Always run all post-handlers (errors are isolated)
|
|
84
|
-
for (const h of _post) {
|
|
85
|
-
try {
|
|
86
|
-
await h.handle(req, res);
|
|
87
|
-
} catch (e) {
|
|
88
|
-
logger.exception(e);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Sorts registered handlers by stage.
|
|
96
|
-
*/
|
|
97
|
-
this.orderHandlers = function () {
|
|
98
|
-
const pre = [], process = [], post = [];
|
|
99
|
-
|
|
100
|
-
for (const handler of _handlers.values()) {
|
|
101
|
-
const dto = handler.getRegistrationInfo();
|
|
102
|
-
if (dto.stage === STAGE.PRE) {
|
|
103
|
-
pre.push(handler);
|
|
104
|
-
} else if (dto.stage === STAGE.PROCESS) {
|
|
105
|
-
process.push(handler);
|
|
106
|
-
} else if (dto.stage === STAGE.POST) post.push(handler);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
_pre = helpOrder.sort(pre);
|
|
110
|
-
_process = helpOrder.sort(process);
|
|
111
|
-
_post = helpOrder.sort(post);
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Factory for dispatcher handler registration metadata.
|
|
3
|
-
*
|
|
4
|
-
* Produces validated DTOs for registering web request handlers.
|
|
5
|
-
*
|
|
6
|
-
* @see TeqFw_Core_Shared_Api_Factory
|
|
7
|
-
*/
|
|
8
|
-
export default class Fl32_Web_Back_Dto_Handler_Info {
|
|
9
|
-
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
10
|
-
/**
|
|
11
|
-
* @param {Fl32_Web_Back_Helper_Cast} cast
|
|
12
|
-
* @param {typeof Fl32_Web_Back_Enum_Stage} STAGE
|
|
13
|
-
*/
|
|
14
|
-
constructor(
|
|
15
|
-
{
|
|
16
|
-
Fl32_Web_Back_Helper_Cast$: cast,
|
|
17
|
-
Fl32_Web_Back_Enum_Stage$: STAGE,
|
|
18
|
-
}
|
|
19
|
-
) {
|
|
20
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
21
|
-
/**
|
|
22
|
-
* Create a validated DTO for handler registration.
|
|
23
|
-
*
|
|
24
|
-
* @param {*} [data] - Optional raw object.
|
|
25
|
-
* @returns {Dto}
|
|
26
|
-
*/
|
|
27
|
-
this.create = function (data) {
|
|
28
|
-
const res = (data && typeof data === 'object' && !Array.isArray(data))
|
|
29
|
-
? Object.assign(new Dto(), data)
|
|
30
|
-
: new Dto();
|
|
31
|
-
res.after = cast.array(data?.after, cast.string);
|
|
32
|
-
res.before = cast.array(data?.before, cast.string);
|
|
33
|
-
res.name = cast.string(data?.name);
|
|
34
|
-
res.stage = cast.enum(data?.stage, STAGE, {lower: true});
|
|
35
|
-
return res;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @memberOf Fl32_Web_Back_Dto_Handler_Info
|
|
42
|
-
*/
|
|
43
|
-
class Dto {
|
|
44
|
-
/**
|
|
45
|
-
* Handlers to run before this one.
|
|
46
|
-
* @type {string[]}
|
|
47
|
-
*/
|
|
48
|
-
after;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Handlers to run after this one.
|
|
52
|
-
* @type {string[]}
|
|
53
|
-
*/
|
|
54
|
-
before;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Unique handler name for ordering.
|
|
58
|
-
* @type {string}
|
|
59
|
-
*/
|
|
60
|
-
name;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Execution stage: 'pre', 'process', or 'post'.
|
|
64
|
-
* @type {string}
|
|
65
|
-
* @see Fl32_Web_Back_Enum_Stage
|
|
66
|
-
*/
|
|
67
|
-
stage;
|
|
68
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enum for server types used to configure built-in web server.
|
|
3
|
-
* - 'http': HTTP/1.1
|
|
4
|
-
* - 'http2': HTTP/2 without TLS (cleartext)
|
|
5
|
-
* - 'https': HTTP/2 over TLS (via http2.createSecureServer)
|
|
6
|
-
*/
|
|
7
|
-
const Fl32_Web_Back_Enum_Server_Type = {
|
|
8
|
-
HTTP2: 'http2',
|
|
9
|
-
HTTP: 'http',
|
|
10
|
-
HTTPS: 'https'
|
|
11
|
-
};
|
|
12
|
-
export default Fl32_Web_Back_Enum_Server_Type;
|
package/src/Back/Enum/Stage.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enum for web request processing stages in this plugin.
|
|
3
|
-
* Used to define processing phases in the web dispatcher specific to this plugin.
|
|
4
|
-
*/
|
|
5
|
-
const Fl32_Web_Back_Enum_Stage = {
|
|
6
|
-
PRE: 'pre', // Pre-processing stage: initial request handling (e.g., logging, authentication)
|
|
7
|
-
PROCESS: 'process', // Main processing stage: routing and core logic
|
|
8
|
-
POST: 'post' // Post-processing stage: final actions (e.g., logging response, cleanup)
|
|
9
|
-
};
|
|
10
|
-
export default Fl32_Web_Back_Enum_Stage;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logs basic request information at the beginning of the request lifecycle.
|
|
3
|
-
* @implements Fl32_Web_Back_Api_Handler
|
|
4
|
-
*/
|
|
5
|
-
export default class Fl32_Web_Back_Handler_Pre_Log {
|
|
6
|
-
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
7
|
-
/**
|
|
8
|
-
* @param {Fl32_Web_Back_Logger} logger
|
|
9
|
-
* @param {Fl32_Web_Back_Dto_Handler_Info} dtoInfo
|
|
10
|
-
* @param {typeof Fl32_Web_Back_Enum_Stage} STAGE
|
|
11
|
-
*/
|
|
12
|
-
constructor(
|
|
13
|
-
{
|
|
14
|
-
Fl32_Web_Back_Logger$: logger,
|
|
15
|
-
Fl32_Web_Back_Dto_Handler_Info$: dtoInfo,
|
|
16
|
-
Fl32_Web_Back_Enum_Stage$: STAGE,
|
|
17
|
-
}
|
|
18
|
-
) {
|
|
19
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
20
|
-
// VARS
|
|
21
|
-
const _info = dtoInfo.create();
|
|
22
|
-
_info.name = this.constructor.name;
|
|
23
|
-
_info.stage = STAGE.PRE;
|
|
24
|
-
Object.freeze(_info);
|
|
25
|
-
|
|
26
|
-
// MAIN
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Log request method and URL.
|
|
30
|
-
*
|
|
31
|
-
* @param {module:http.IncomingMessage|module:http2.Http2ServerRequest} req
|
|
32
|
-
* @returns {Promise<void>}
|
|
33
|
-
*/
|
|
34
|
-
this.handle = async function (req) {
|
|
35
|
-
logger.debug(`${req.method} ${req.url}`);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Return handler registration info.
|
|
40
|
-
*
|
|
41
|
-
* @returns {Fl32_Web_Back_Dto_Handler_Info.Dto}
|
|
42
|
-
*/
|
|
43
|
-
this.getRegistrationInfo = () => _info;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Universal file handler serving files from multiple sources using helper modules.
|
|
3
|
-
*
|
|
4
|
-
* @implements Fl32_Web_Back_Api_Handler
|
|
5
|
-
*/
|
|
6
|
-
export default class Fl32_Web_Back_Handler_Static {
|
|
7
|
-
/* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
|
|
8
|
-
/**
|
|
9
|
-
* @param {Fl32_Web_Back_Handler_Static_A_Registry} registry
|
|
10
|
-
* @param {Fl32_Web_Back_Handler_Static_A_FileService} fileService
|
|
11
|
-
* @param {Fl32_Web_Back_Helper_Respond} respond
|
|
12
|
-
* @param {Fl32_Web_Back_Logger} logger
|
|
13
|
-
* @param {Fl32_Web_Back_Dto_Handler_Info} dtoInfo
|
|
14
|
-
* @param {typeof Fl32_Web_Back_Enum_Stage} STAGE
|
|
15
|
-
*/
|
|
16
|
-
constructor(
|
|
17
|
-
{
|
|
18
|
-
Fl32_Web_Back_Handler_Static_A_Registry$: registry,
|
|
19
|
-
Fl32_Web_Back_Handler_Static_A_FileService$: fileService,
|
|
20
|
-
Fl32_Web_Back_Helper_Respond$: respond,
|
|
21
|
-
Fl32_Web_Back_Logger$: logger,
|
|
22
|
-
Fl32_Web_Back_Dto_Handler_Info$: dtoInfo,
|
|
23
|
-
Fl32_Web_Back_Enum_Stage$: STAGE,
|
|
24
|
-
}
|
|
25
|
-
) {
|
|
26
|
-
/* eslint-enable jsdoc/check-param-names */
|
|
27
|
-
|
|
28
|
-
const _info = dtoInfo.create();
|
|
29
|
-
_info.name = this.constructor.name;
|
|
30
|
-
_info.stage = STAGE.PROCESS;
|
|
31
|
-
Object.freeze(_info);
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Initialize registry with provided sources.
|
|
35
|
-
*
|
|
36
|
-
* @param {{sources: Fl32_Web_Back_Dto_Handler_Source.Dto[]}} params
|
|
37
|
-
* @returns {Promise<void>}
|
|
38
|
-
*/
|
|
39
|
-
this.init = async ({sources = []} = {}) => {
|
|
40
|
-
registry.addConfigs(sources);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Attempt to handle incoming request.
|
|
45
|
-
*
|
|
46
|
-
* @param {module:http.IncomingMessage|module:http2.Http2ServerRequest} req
|
|
47
|
-
* @param {module:http.ServerResponse|module:http2.Http2ServerResponse} res
|
|
48
|
-
* @returns {Promise<boolean>} True if file served
|
|
49
|
-
*/
|
|
50
|
-
this.handle = async (req, res) => {
|
|
51
|
-
if (!respond.isWritable(res)) return false;
|
|
52
|
-
const urlPath = decodeURIComponent(req.url.split('?')[0]);
|
|
53
|
-
const match = registry.find(urlPath);
|
|
54
|
-
if (!match) return false;
|
|
55
|
-
return fileService.serve(match.config, match.rel, req, res);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @returns {Fl32_Web_Back_Dto_Handler_Info.Dto}
|
|
60
|
-
*/
|
|
61
|
-
this.getRegistrationInfo = () => _info;
|
|
62
|
-
}
|
|
63
|
-
}
|