@flancer32/teq-web 0.4.0 → 0.6.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +236 -127
  3. package/ai/AGENTS.md +36 -0
  4. package/ai/abstractions.md +75 -0
  5. package/ai/examples/minimal-server.md +79 -0
  6. package/ai/overview.md +29 -0
  7. package/ai/rules.md +44 -0
  8. package/package.json +43 -37
  9. package/src/Back/Api/Handler.mjs +26 -0
  10. package/src/Back/Config/Runtime/Tls.mjs +89 -0
  11. package/src/Back/Config/Runtime.mjs +114 -0
  12. package/src/Back/Dto/Info.mjs +62 -0
  13. package/src/Back/Dto/RequestContext.mjs +33 -0
  14. package/src/Back/Dto/{Handler/Source.js → Source.mjs} +24 -25
  15. package/src/Back/Enum/Server/Type.mjs +13 -0
  16. package/src/Back/Enum/Stage.mjs +13 -0
  17. package/src/Back/Handler/Pre/Log.mjs +55 -0
  18. package/src/Back/Handler/Static/A/{Config.js → Config.mjs} +11 -4
  19. package/src/Back/Handler/Static/A/{Fallback.js → Fallback.mjs} +12 -4
  20. package/src/Back/Handler/Static/A/{FileService.js → FileService.mjs} +30 -17
  21. package/src/Back/Handler/Static/A/{Registry.js → Registry.mjs} +15 -7
  22. package/src/Back/Handler/Static/A/{Resolver.js → Resolver.mjs} +10 -3
  23. package/src/Back/Handler/Static.mjs +79 -0
  24. package/src/Back/Helper/Cast.mjs +116 -0
  25. package/src/Back/Helper/{Mime.js → Mime.mjs} +2 -0
  26. package/src/Back/Helper/Order/Kahn.mjs +69 -0
  27. package/src/Back/Helper/{Respond.js → Respond.mjs} +14 -7
  28. package/src/Back/Logger.mjs +57 -0
  29. package/src/Back/PipelineEngine.mjs +216 -0
  30. package/src/Back/{Server.js → Server.mjs} +38 -30
  31. package/types.d.ts +45 -22
  32. package/src/AGENTS.md +0 -108
  33. package/src/Back/Api/Handler.js +0 -26
  34. package/src/Back/Defaults.js +0 -6
  35. package/src/Back/Dispatcher.js +0 -115
  36. package/src/Back/Dto/Handler/Info.js +0 -68
  37. package/src/Back/Enum/Server/Type.js +0 -12
  38. package/src/Back/Enum/Stage.js +0 -10
  39. package/src/Back/Handler/Pre/Log.js +0 -45
  40. package/src/Back/Handler/Static.js +0 -63
  41. package/src/Back/Helper/Cast.js +0 -114
  42. package/src/Back/Helper/Order/Kahn.js +0 -66
  43. package/src/Back/Logger.js +0 -53
  44. package/src/Back/Server/Config/Tls.js +0 -55
  45. package/src/Back/Server/Config.js +0 -69
  46. package/teqfw.json +0 -8
package/ai/rules.md ADDED
@@ -0,0 +1,44 @@
1
+ # Usage Rules
2
+
3
+ ## Structural Rules
4
+
5
+ - The Pipeline Engine is the only request-lifecycle coordinator.
6
+ - Request processing always uses the fixed stage sequence `INIT -> PROCESS -> FINALIZE`.
7
+ - Handlers are registered during setup and must not be added, removed, or reordered after startup.
8
+ - Handler ordering is declarative and derived from `name`, `before`, and `after`.
9
+
10
+ ## Completion Rules
11
+
12
+ - Request completion is a monotonic flag for one request.
13
+ - Only `PROCESS` handlers may call `context.complete()` or set completion to `true`.
14
+ - `INIT` and `FINALIZE` handlers must never mark the request completed.
15
+ - Completion cannot be reset once set.
16
+
17
+ ## Response Rules
18
+
19
+ - Exactly one terminal HTTP response must result from each request.
20
+ - If no `PROCESS` handler completes the request and the response is still writable, the Pipeline Engine returns `404 Not Found`.
21
+ - If a `PROCESS` handler throws and the response is still writable, the Pipeline Engine returns `500 Internal Server Error` and stops further PROCESS handlers.
22
+ - Exceptions in `INIT` and `FINALIZE` handlers are isolated and do not abort the pipeline.
23
+
24
+ ## Transport Boundary
25
+
26
+ - Handlers work on request context and response specification only.
27
+ - Handlers must not perform transport-level transmission or socket management.
28
+ - Actual network response transmission belongs to the built-in `Server` or to the external transport framework that called the Pipeline Engine.
29
+
30
+ ## Environment Assumptions
31
+
32
+ - Runtime is Node.js 20 or newer.
33
+ - The package is intended for long-running server processes.
34
+ - Process supervision, restart, scaling, reverse proxying, and load balancing are external concerns.
35
+ - Multiple instances may run concurrently, but they are independent and must not rely on shared in-memory state.
36
+
37
+ ## DI Usage Rules
38
+
39
+ - The package is designed for `@teqfw/di`.
40
+ - Consumer code should resolve package modules through the `Fl32_Web_` namespace mapped to the package `src/` path.
41
+ - Startup configuration for the built-in server should be supplied through `Fl32_Web_Back_Config_Runtime__Factory$` using the hierarchical configuration shape `{server: {...}}`.
42
+ - TLS startup configuration belongs to the dedicated runtime component `Fl32_Web_Back_Config_Runtime_Tls$`, even though consumers read it through `config.server.tls`.
43
+ - 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
+ - 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.
package/package.json CHANGED
@@ -1,57 +1,63 @@
1
1
  {
2
2
  "name": "@flancer32/teq-web",
3
- "version": "0.4.0",
4
- "description": "Node.js web plugin supporting Express and Fastify integration, with built-in server for standalone operation",
3
+ "version": "0.6.0",
4
+ "description": "Server-side web request coordination infrastructure for TeqFW modular monolith applications.",
5
5
  "type": "module",
6
- "types": "types.d.ts",
7
- "keywords": [
8
- "es6+",
9
- "teqfw",
10
- "tequila framework",
11
- "web applications"
12
- ],
13
- "homepage": "https://github.com/flancer32/teq-web#readme",
14
- "bugs": {
15
- "url": "https://github.com/flancer32/teq-web/issues"
16
- },
17
6
  "license": "Apache-2.0",
18
7
  "author": {
19
8
  "name": "Alex Gusev",
20
9
  "email": "alex@flancer64.com",
21
10
  "url": "https://github.com/flancer64"
22
11
  },
23
- "files": [
24
- "src/",
25
- "CHANGELOG.md",
26
- "LICENSE",
27
- "README.md",
28
- "teqfw.json",
29
- "types.d.ts"
30
- ],
31
12
  "repository": {
32
13
  "type": "git",
33
14
  "url": "git+https://github.com/flancer32/teq-web.git"
34
15
  },
35
- "scripts": {
36
- "eslint": "./node_modules/.bin/eslint ./src/",
37
- "test:accept": "node --test $(find ./test/accept -name '*.test.mjs')",
38
- "test:unit": "node --test $(find ./test/unit -name '*.test.mjs')"
16
+ "homepage": "https://github.com/flancer32/teq-web",
17
+ "bugs": {
18
+ "url": "https://github.com/flancer32/teq-web/issues"
19
+ },
20
+ "keywords": [
21
+ "teqfw",
22
+ "tequila-framework",
23
+ "web",
24
+ "dispatcher",
25
+ "request-pipeline",
26
+ "dependency-injection",
27
+ "modular-monolith",
28
+ "nodejs"
29
+ ],
30
+ "types": "types.d.ts",
31
+ "engines": {
32
+ "node": ">=20"
33
+ },
34
+ "teqfw": {
35
+ "namespaces": [
36
+ {
37
+ "prefix": "Fl32_Web_",
38
+ "path": "./src",
39
+ "ext": ".mjs"
40
+ }
41
+ ]
39
42
  },
40
43
  "dependencies": {
41
- "@teqfw/di": "^1.1.3"
44
+ "@teqfw/di": "^2.1.0"
42
45
  },
43
46
  "devDependencies": {
44
- "@eslint/js": "^9.25.0",
45
- "eslint": "^9.25.0",
46
- "eslint-plugin-jsdoc": "^50.6.8",
47
- "express": "^4.18.2",
48
- "fastify": "^4.27.2"
47
+ "@types/node": "^25.4.0",
48
+ "eslint": "^10.0.3"
49
49
  },
50
- "engines": {
51
- "node": ">=20"
50
+ "scripts": {
51
+ "test:unit": "find test/unit -name '*.test.mjs' -print0 | xargs -0 node --test",
52
+ "test:integration": "find test/integration -name '*.test.mjs' -print0 | xargs -0 node --test",
53
+ "test": "npm run test:unit && npm run test:integration"
52
54
  },
53
- "funding": {
54
- "type": "individual",
55
- "url": "https://github.com/sponsors/teqfw"
56
- }
55
+ "files": [
56
+ "ai/",
57
+ "src/",
58
+ "CHANGELOG.md",
59
+ "LICENSE",
60
+ "README.md",
61
+ "types.d.ts"
62
+ ]
57
63
  }
@@ -0,0 +1,26 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Interface for web request handlers used by the Pipeline Engine.
5
+ *
6
+ * @interface
7
+ */
8
+ export default class Fl32_Web_Back_Api_Handler {
9
+ /* eslint-disable no-unused-vars */
10
+ /**
11
+ * Handles one request context in a pipeline stage.
12
+ * @param {Fl32_Web_Back_Dto_RequestContext} context
13
+ * @returns {Promise<void>}
14
+ */
15
+ async handle(context) {
16
+ throw new Error('Method not implemented');
17
+ }
18
+
19
+ /**
20
+ * Provides metadata for pipeline registration.
21
+ * @returns {Fl32_Web_Back_Dto_Info}
22
+ */
23
+ getRegistrationInfo() {
24
+ throw new Error('Method not implemented');
25
+ }
26
+ }
@@ -0,0 +1,89 @@
1
+ // @ts-check
2
+
3
+ export const __deps__ = Object.freeze({
4
+ cast: 'Fl32_Web_Back_Helper_Cast$',
5
+ });
6
+
7
+ /**
8
+ * TLS runtime configuration.
9
+ */
10
+ export class Data {
11
+ /** @type {string|undefined} */
12
+ ca;
13
+ /** @type {string|undefined} */
14
+ cert;
15
+ /** @type {string|undefined} */
16
+ key;
17
+ }
18
+
19
+ /** @type {Fl32_Web_Back_Config_Runtime_Tls} */
20
+ const cfg = new Data();
21
+ let frozen = false;
22
+
23
+ /** @type {Fl32_Web_Back_Config_Runtime_Tls} */
24
+ const proxy = new Proxy(cfg, {
25
+ get(target, prop) {
26
+ const isServiceProp = (prop === 'then') || (typeof prop === 'symbol');
27
+ if (!frozen && !isServiceProp) throw new Error('Runtime configuration is not initialized.');
28
+ return target[prop];
29
+ },
30
+ set() {
31
+ throw new Error('Runtime configuration is immutable.');
32
+ },
33
+ defineProperty(target, prop, descriptor) {
34
+ const current = Object.getOwnPropertyDescriptor(target, prop);
35
+ const isFreezeStep = current
36
+ && (descriptor?.configurable === false)
37
+ && (!('writable' in descriptor) || descriptor.writable === false)
38
+ && (!('value' in descriptor) || descriptor.value === current.value);
39
+ if (isFreezeStep) {
40
+ return Reflect.defineProperty(target, prop, descriptor);
41
+ }
42
+ throw new Error('Runtime configuration is immutable.');
43
+ },
44
+ deleteProperty() {
45
+ throw new Error('Runtime configuration is immutable.');
46
+ },
47
+ });
48
+
49
+ export default class Wrapper {
50
+ constructor() {
51
+ return proxy;
52
+ }
53
+ }
54
+
55
+ export class Factory {
56
+ /**
57
+ * @param {object} params
58
+ * @param {Fl32_Web_Back_Helper_Cast} params.cast
59
+ */
60
+ constructor({cast}) {
61
+ /**
62
+ * @param {Fl32_Web_Back_Config_Runtime_Tls_Params} [params]
63
+ * @returns {Fl32_Web_Back_Config_Runtime_Tls}
64
+ */
65
+ this.configure = function (params = {}) {
66
+ if (frozen) throw new Error('Runtime configuration is frozen.');
67
+ if (cfg.ca === undefined && params.ca !== undefined) {
68
+ cfg.ca = cast.string(params.ca);
69
+ }
70
+ if (cfg.cert === undefined && params.cert !== undefined) {
71
+ cfg.cert = cast.string(params.cert);
72
+ }
73
+ if (cfg.key === undefined && params.key !== undefined) {
74
+ cfg.key = cast.string(params.key);
75
+ }
76
+ return proxy;
77
+ };
78
+
79
+ /**
80
+ * @returns {Fl32_Web_Back_Config_Runtime_Tls}
81
+ */
82
+ this.freeze = function () {
83
+ if (frozen) return proxy;
84
+ Object.freeze(cfg);
85
+ frozen = true;
86
+ return proxy;
87
+ };
88
+ }
89
+ }
@@ -0,0 +1,114 @@
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_Config_Runtime_Tls__Factory$',
7
+ });
8
+
9
+ /**
10
+ * Backend runtime configuration.
11
+ */
12
+ export class Data {
13
+ /** @type {Fl32_Web_Back_Config_Runtime_Server|undefined} */
14
+ server;
15
+ }
16
+
17
+ /**
18
+ * Built-in server runtime configuration subtree.
19
+ */
20
+ export class Server {
21
+ /** @type {number|undefined} */
22
+ port;
23
+ /** @type {string|undefined} */
24
+ type;
25
+ /** @type {Fl32_Web_Back_Config_Runtime_Tls|undefined} */
26
+ tls;
27
+ }
28
+
29
+ /** @type {Fl32_Web_Back_Config_Runtime} */
30
+ const cfg = new Data();
31
+ let frozen = false;
32
+
33
+ /** @type {Fl32_Web_Back_Config_Runtime} */
34
+ const proxy = new Proxy(cfg, {
35
+ get(target, prop) {
36
+ const isServiceProp = (prop === 'then') || (typeof prop === 'symbol');
37
+ if (!frozen && !isServiceProp) throw new Error('Runtime configuration is not initialized.');
38
+ return target[prop];
39
+ },
40
+ set() {
41
+ throw new Error('Runtime configuration is immutable.');
42
+ },
43
+ defineProperty(target, prop, descriptor) {
44
+ const current = Object.getOwnPropertyDescriptor(target, prop);
45
+ const isFreezeStep = current
46
+ && (descriptor?.configurable === false)
47
+ && (!('writable' in descriptor) || descriptor.writable === false)
48
+ && (!('value' in descriptor) || descriptor.value === current.value);
49
+ if (isFreezeStep) {
50
+ return Reflect.defineProperty(target, prop, descriptor);
51
+ }
52
+ throw new Error('Runtime configuration is immutable.');
53
+ },
54
+ deleteProperty() {
55
+ throw new Error('Runtime configuration is immutable.');
56
+ },
57
+ });
58
+
59
+ export default class Wrapper {
60
+ constructor() {
61
+ return proxy;
62
+ }
63
+ }
64
+
65
+ export class Factory {
66
+ /**
67
+ * @param {object} params
68
+ * @param {Fl32_Web_Back_Helper_Cast} params.cast
69
+ * @param {Fl32_Web_Back_Enum_Server_Type} params.SERVER_TYPE
70
+ * @param {Fl32_Web_Back_Config_Runtime_Tls$Factory} params.tlsFactory
71
+ */
72
+ constructor({ cast, SERVER_TYPE, tlsFactory }) {
73
+ /**
74
+ * @param {Fl32_Web_Back_Config_Runtime_Params} [params]
75
+ * @returns {Fl32_Web_Back_Config_Runtime}
76
+ */
77
+ this.configure = function (params = {}) {
78
+ if (frozen) throw new Error('Runtime configuration is frozen.');
79
+ if (cfg.server === undefined) cfg.server = new Server();
80
+ if (cfg.server.port === undefined && params.server?.port !== undefined) {
81
+ cfg.server.port = cast.int(params.server.port);
82
+ }
83
+ if (cfg.server.type === undefined && params.server?.type !== undefined) {
84
+ cfg.server.type = cast.enum(params.server.type, SERVER_TYPE, { lower: true });
85
+ }
86
+ if (params.server?.tls !== undefined) {
87
+ tlsFactory.configure(params.server.tls);
88
+ }
89
+ return proxy;
90
+ };
91
+
92
+ /**
93
+ * @returns {Fl32_Web_Back_Config_Runtime}
94
+ */
95
+ this.freeze = function () {
96
+ if (frozen) return proxy;
97
+ if (cfg.server === undefined) cfg.server = new Server();
98
+ if (cfg.server.port === undefined) cfg.server.port = 3000;
99
+ if (cfg.server.type === undefined) cfg.server.type = SERVER_TYPE.HTTP;
100
+ const tls = tlsFactory.freeze();
101
+ if (cfg.server.tls === undefined) cfg.server.tls = tls;
102
+ if (cfg.server.type === SERVER_TYPE.HTTPS && cfg.server.tls === undefined) {
103
+ throw new Error('TLS configuration is required for HTTPS server type');
104
+ }
105
+ if (cfg.server.type === SERVER_TYPE.HTTPS && (!cfg.server.tls.key || !cfg.server.tls.cert)) {
106
+ throw new Error('TLS configuration is required for HTTPS server type');
107
+ }
108
+ Object.freeze(cfg.server);
109
+ Object.freeze(cfg);
110
+ frozen = true;
111
+ return proxy;
112
+ };
113
+ }
114
+ }
@@ -0,0 +1,62 @@
1
+ // @ts-check
2
+
3
+ export const __deps__ = Object.freeze({
4
+ cast: 'Fl32_Web_Back_Helper_Cast$',
5
+ STAGE: 'Fl32_Web_Back_Enum_Stage$',
6
+ });
7
+
8
+ export default class Fl32_Web_Back_Dto_Info {
9
+ /**
10
+ * Handlers to run before this one.
11
+ * @type {string[]}
12
+ */
13
+ after = [];
14
+
15
+ /**
16
+ * Handlers to run after this one.
17
+ * @type {string[]}
18
+ */
19
+ before = [];
20
+
21
+ /**
22
+ * Unique handler name for ordering.
23
+ * @type {string|undefined}
24
+ */
25
+ name;
26
+
27
+ /**
28
+ * Execution stage: `INIT`, `PROCESS`, or `FINALIZE`.
29
+ * @type {string|undefined}
30
+ * @see Fl32_Web_Back_Enum_Stage
31
+ */
32
+ stage;
33
+ }
34
+
35
+ export class Factory {
36
+ /* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
37
+ /**
38
+ * @param {object} params
39
+ * @param {Fl32_Web_Back_Helper_Cast} params.cast
40
+ * @param {Fl32_Web_Back_Enum_Stage} params.STAGE
41
+ */
42
+ constructor(
43
+ {
44
+ cast,
45
+ STAGE,
46
+ }
47
+ ) {
48
+ /* eslint-enable jsdoc/check-param-names */
49
+ /**
50
+ * @param {*} [data]
51
+ * @returns {Fl32_Web_Back_Dto_Info}
52
+ */
53
+ this.create = function (data) {
54
+ const res = new Fl32_Web_Back_Dto_Info();
55
+ res.after = cast.array(data?.after, cast.string);
56
+ res.before = cast.array(data?.before, cast.string);
57
+ res.name = cast.string(data?.name);
58
+ res.stage = cast.enum(data?.stage, STAGE, {upper: true});
59
+ return Object.freeze(res);
60
+ };
61
+ }
62
+ }
@@ -0,0 +1,33 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Request context passed through the pipeline lifecycle.
5
+ */
6
+ export default class Fl32_Web_Back_Dto_RequestContext {
7
+ /** @type {Fl32_Web_Node_Http_IncomingMessage|Fl32_Web_Node_Http2_ServerRequest} */
8
+ request;
9
+
10
+ /** @type {Fl32_Web_Back_Response_Target} */
11
+ response;
12
+
13
+ /** @type {Record<string, unknown>} */
14
+ data = {};
15
+
16
+ /** @type {boolean} */
17
+ completed = false;
18
+
19
+ /** @type {() => void} */
20
+ complete;
21
+
22
+ /** @type {() => boolean} */
23
+ isCompleted;
24
+ }
25
+
26
+ export class Factory {
27
+ /**
28
+ * @returns {Fl32_Web_Back_Dto_RequestContext}
29
+ */
30
+ create() {
31
+ return new Fl32_Web_Back_Dto_RequestContext();
32
+ }
33
+ }
@@ -1,46 +1,45 @@
1
- /**
2
- * Factory for file source configuration DTO used by Static handler.
3
- */
4
- export default class Fl32_Web_Back_Dto_Handler_Source {
1
+ // @ts-check
2
+
3
+ export const __deps__ = Object.freeze({
4
+ cast: 'Fl32_Web_Back_Helper_Cast$',
5
+ });
6
+
7
+ export default class Fl32_Web_Back_Dto_Source {
8
+ /** @type {string} */
9
+ root;
10
+ /** @type {string} */
11
+ prefix;
12
+ /** @type {{[key: string]: string[]}} */
13
+ allow = {};
14
+ /** @type {string[]} */
15
+ defaults = [];
16
+ }
17
+
18
+ export class Factory {
5
19
  /* eslint-disable jsdoc/require-param-description */
6
20
  /**
7
- * @param {Fl32_Web_Back_Helper_Cast} cast
21
+ * @param {object} params
22
+ * @param {Fl32_Web_Back_Helper_Cast} params.cast
8
23
  */
9
24
  constructor(
10
25
  {
11
- Fl32_Web_Back_Helper_Cast$: cast,
26
+ cast,
12
27
  }
13
28
  ) {
14
29
  /* eslint-enable jsdoc/require-param-description */
15
30
  /**
16
- * Create validated DTO for source configuration.
17
- *
18
31
  * @param {*} [data]
19
- * @returns {Dto}
32
+ * @returns {Fl32_Web_Back_Dto_Source}
20
33
  */
21
34
  this.create = function (data) {
22
- const res = new Dto();
35
+ const res = new Fl32_Web_Back_Dto_Source();
23
36
  if (data) {
24
37
  res.root = cast.string(data.root);
25
38
  res.prefix = cast.string(data.prefix);
26
39
  res.allow = cast.stringArrayMap(data.allow);
27
40
  res.defaults = cast.array(data.defaults, cast.string);
28
41
  }
29
- return res;
42
+ return Object.freeze(res);
30
43
  };
31
44
  }
32
45
  }
33
-
34
- /**
35
- * @memberOf Fl32_Web_Back_Dto_Handler_Source
36
- */
37
- class Dto {
38
- /** @type {string} */
39
- root;
40
- /** @type {string} */
41
- prefix;
42
- /** @type {{[key: string]: string[]}} */
43
- allow = {};
44
- /** @type {string[]} */
45
- defaults = [];
46
- }
@@ -0,0 +1,13 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Enum-like DTO for built-in server transport modes.
5
+ */
6
+ export default class Fl32_Web_Back_Enum_Server_Type {
7
+ constructor() {
8
+ this.HTTP2 = 'http2';
9
+ this.HTTP = 'http';
10
+ this.HTTPS = 'https';
11
+ Object.freeze(this);
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Enum-like DTO for web request processing stages.
5
+ */
6
+ export default class Fl32_Web_Back_Enum_Stage {
7
+ constructor() {
8
+ this.INIT = 'INIT';
9
+ this.PROCESS = 'PROCESS';
10
+ this.FINALIZE = 'FINALIZE';
11
+ Object.freeze(this);
12
+ }
13
+ }
@@ -0,0 +1,55 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Logs basic request information at the beginning of the request lifecycle.
5
+ *
6
+ * @implements Fl32_Web_Back_Api_Handler
7
+ */
8
+ export const __deps__ = Object.freeze({
9
+ logger: 'Fl32_Web_Back_Logger$',
10
+ dtoInfoFactory: 'Fl32_Web_Back_Dto_Info__Factory$',
11
+ STAGE: 'Fl32_Web_Back_Enum_Stage$',
12
+ });
13
+
14
+ export default class Fl32_Web_Back_Handler_Pre_Log {
15
+ /* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
16
+ /**
17
+ * @param {object} params
18
+ * @param {Fl32_Web_Back_Logger} params.logger
19
+ * @param {Fl32_Web_Back_Dto_Info$Factory} params.dtoInfoFactory
20
+ * @param {Fl32_Web_Back_Enum_Stage} params.STAGE
21
+ */
22
+ constructor(
23
+ {
24
+ logger,
25
+ dtoInfoFactory,
26
+ STAGE,
27
+ }
28
+ ) {
29
+ /* eslint-enable jsdoc/check-param-names */
30
+ // VARS
31
+ const _info = dtoInfoFactory.create({
32
+ name: this.constructor.name,
33
+ stage: STAGE.INIT,
34
+ });
35
+
36
+ // MAIN
37
+
38
+ /**
39
+ * Log request method and URL.
40
+ *
41
+ * @param {Fl32_Web_Back_Dto_RequestContext} context
42
+ * @returns {Promise<void>}
43
+ */
44
+ this.handle = async function (context) {
45
+ logger.debug(`${context.request.method} ${context.request.url}`);
46
+ };
47
+
48
+ /**
49
+ * Return handler registration info.
50
+ *
51
+ * @returns {Fl32_Web_Back_Dto_Info}
52
+ */
53
+ this.getRegistrationInfo = () => _info;
54
+ }
55
+ }
@@ -1,12 +1,19 @@
1
+ // @ts-check
2
+
3
+ export const __deps__ = Object.freeze({
4
+ path: 'node_path',
5
+ });
6
+
1
7
  export default class Fl32_Web_Back_Handler_Static_A_Config {
2
8
  static DEFAULT_FILES = ['index.html', 'index.htm', 'index.txt'];
3
9
  /* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
4
10
  /**
5
- * @param {typeof import('node:path')} path
11
+ * @param {object} params
12
+ * @param {Fl32_Web_Node_Path} params.path
6
13
  */
7
14
  constructor(
8
15
  {
9
- 'node:path': path,
16
+ path,
10
17
  }
11
18
  ) {
12
19
  /* eslint-enable jsdoc/check-param-names */
@@ -14,8 +21,8 @@ export default class Fl32_Web_Back_Handler_Static_A_Config {
14
21
  /**
15
22
  * Normalize DTO fields into configuration object.
16
23
  *
17
- * @param {Fl32_Web_Back_Dto_Handler_Source.Dto} dto
18
- * @returns {{root:string,prefix:string,allow?:Record<string,string[]>,defaults:string[]}}
24
+ * @param {Fl32_Web_Back_Dto_Source} dto
25
+ * @returns {Fl32_Web_Back_Handler_Static_A_Config_Value}
19
26
  * @throws {Error} When required fields are missing or invalid.
20
27
  */
21
28
  this.create = (dto) => {
@@ -1,13 +1,21 @@
1
+ // @ts-check
2
+
3
+ export const __deps__ = Object.freeze({
4
+ fs: 'node_fs',
5
+ path: 'node_path',
6
+ });
7
+
1
8
  export default class Fl32_Web_Back_Handler_Static_A_Fallback {
2
9
  /* eslint-disable jsdoc/require-param-description,jsdoc/check-param-names */
3
10
  /**
4
- * @param {typeof import('node:fs')} fs
5
- * @param {typeof import('node:path')} path
11
+ * @param {object} params
12
+ * @param {Fl32_Web_Node_Fs} params.fs
13
+ * @param {Fl32_Web_Node_Path} params.path
6
14
  */
7
15
  constructor(
8
16
  {
9
- 'node:fs': fs,
10
- 'node:path': path,
17
+ fs,
18
+ path,
11
19
  }
12
20
  ) {
13
21
  /* eslint-enable jsdoc/check-param-names */