@flancer32/teq-web 0.3.1 → 0.4.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 +6 -1
- package/package.json +11 -2
- package/types.d.ts +25 -0
- package/.github/workflows/npm-publish.yml +0 -48
- package/AGENTS.md +0 -101
- package/eslint.config.js +0 -37
- package/test/accept/ExternalServer.test.mjs +0 -66
- package/test/accept/Server.test.mjs +0 -203
- package/test/certs/ca.pem +0 -19
- package/test/certs/cert.pem +0 -19
- package/test/certs/key.pem +0 -28
- package/test/dev/app/Plugin/Start.js +0 -40
- package/test/dev/app.mjs +0 -65
- package/test/dev/web/favicon.ico +0 -0
- package/test/dev/web/index.html +0 -11
- package/test/unit/AGENTS.md +0 -106
- package/test/unit/Back/Dispatcher.test.mjs +0 -150
- package/test/unit/Back/Dto/Handler/Source.test.mjs +0 -40
- package/test/unit/Back/Handler/Pre/Log.test.mjs +0 -22
- package/test/unit/Back/Handler/Static/A/Config.test.mjs +0 -52
- package/test/unit/Back/Handler/Static/A/Fallback.test.mjs +0 -60
- package/test/unit/Back/Handler/Static/A/FileService.test.mjs +0 -225
- package/test/unit/Back/Handler/Static/A/Registry.test.mjs +0 -83
- package/test/unit/Back/Handler/Static/A/Resolver.test.mjs +0 -73
- package/test/unit/Back/Handler/Static/Static.test.mjs +0 -235
- package/test/unit/Back/Helper/Order/Kahn.test.mjs +0 -59
- package/test/unit/Back/Helper/Respond.test.mjs +0 -83
- package/test/unit/Back/Server.test.mjs +0 -112
- package/test/unit/common.js +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.0] - 2025-12-20
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- TypeScript type declarations for the public API via `types.d.ts`.
|
|
7
|
+
- ADSM cognitive context in `ctx/`.
|
|
8
|
+
|
|
3
9
|
## [0.3.1] - 2025-08-21
|
|
4
10
|
|
|
5
11
|
### Added
|
|
@@ -35,4 +41,3 @@
|
|
|
35
41
|
- Basic Node.js HTTP server implementation for standalone use cases.
|
|
36
42
|
- Unified interfaces for registering request handlers from other teq-plugins.
|
|
37
43
|
- Modular architecture compatible with Tequila Framework philosophy.
|
|
38
|
-
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flancer32/teq-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Node.js web plugin supporting Express and Fastify integration, with built-in server for standalone operation",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"types": "types.d.ts",
|
|
6
7
|
"keywords": [
|
|
7
8
|
"es6+",
|
|
8
9
|
"teqfw",
|
|
@@ -19,6 +20,14 @@
|
|
|
19
20
|
"email": "alex@flancer64.com",
|
|
20
21
|
"url": "https://github.com/flancer64"
|
|
21
22
|
},
|
|
23
|
+
"files": [
|
|
24
|
+
"src/",
|
|
25
|
+
"CHANGELOG.md",
|
|
26
|
+
"LICENSE",
|
|
27
|
+
"README.md",
|
|
28
|
+
"teqfw.json",
|
|
29
|
+
"types.d.ts"
|
|
30
|
+
],
|
|
22
31
|
"repository": {
|
|
23
32
|
"type": "git",
|
|
24
33
|
"url": "git+https://github.com/flancer32/teq-web.git"
|
|
@@ -29,7 +38,7 @@
|
|
|
29
38
|
"test:unit": "node --test $(find ./test/unit -name '*.test.mjs')"
|
|
30
39
|
},
|
|
31
40
|
"dependencies": {
|
|
32
|
-
"@teqfw/di": "
|
|
41
|
+
"@teqfw/di": "^1.1.3"
|
|
33
42
|
},
|
|
34
43
|
"devDependencies": {
|
|
35
44
|
"@eslint/js": "^9.25.0",
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
type Fl32_Web_Back_Api_Handler = import("./src/Back/Api/Handler.js").default;
|
|
3
|
+
type Fl32_Web_Back_Defaults = import("./src/Back/Defaults.js").default;
|
|
4
|
+
type Fl32_Web_Back_Dispatcher = import("./src/Back/Dispatcher.js").default;
|
|
5
|
+
type Fl32_Web_Back_Dto_Handler_Info = import("./src/Back/Dto/Handler/Info.js").default;
|
|
6
|
+
type Fl32_Web_Back_Dto_Handler_Source = import("./src/Back/Dto/Handler/Source.js").default;
|
|
7
|
+
type Fl32_Web_Back_Enum_Server_Type = import("./src/Back/Enum/Server/Type.js").default;
|
|
8
|
+
type Fl32_Web_Back_Enum_Stage = import("./src/Back/Enum/Stage.js").default;
|
|
9
|
+
type Fl32_Web_Back_Handler_Pre_Log = import("./src/Back/Handler/Pre/Log.js").default;
|
|
10
|
+
type Fl32_Web_Back_Handler_Static = import("./src/Back/Handler/Static.js").default;
|
|
11
|
+
type Fl32_Web_Back_Handler_Static_A_Config = import("./src/Back/Handler/Static/A/Config.js").default;
|
|
12
|
+
type Fl32_Web_Back_Handler_Static_A_Fallback = import("./src/Back/Handler/Static/A/Fallback.js").default;
|
|
13
|
+
type Fl32_Web_Back_Handler_Static_A_FileService = import("./src/Back/Handler/Static/A/FileService.js").default;
|
|
14
|
+
type Fl32_Web_Back_Handler_Static_A_Registry = import("./src/Back/Handler/Static/A/Registry.js").default;
|
|
15
|
+
type Fl32_Web_Back_Handler_Static_A_Resolver = import("./src/Back/Handler/Static/A/Resolver.js").default;
|
|
16
|
+
type Fl32_Web_Back_Helper_Cast = import("./src/Back/Helper/Cast.js").default;
|
|
17
|
+
type Fl32_Web_Back_Helper_Mime = import("./src/Back/Helper/Mime.js").default;
|
|
18
|
+
type Fl32_Web_Back_Helper_Order_Kahn = import("./src/Back/Helper/Order/Kahn.js").default;
|
|
19
|
+
type Fl32_Web_Back_Helper_Respond = import("./src/Back/Helper/Respond.js").default;
|
|
20
|
+
type Fl32_Web_Back_Logger = import("./src/Back/Logger.js").default;
|
|
21
|
+
type Fl32_Web_Back_Server = import("./src/Back/Server.js").default;
|
|
22
|
+
type Fl32_Web_Back_Server_Config = import("./src/Back/Server/Config.js").default;
|
|
23
|
+
type Fl32_Web_Back_Server_Config_Tls = import("./src/Back/Server/Config/Tls.js").default;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
name: npm publication
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
release:
|
|
6
|
-
types: [created]
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
build:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
# Checkout repository code
|
|
13
|
-
- uses: actions/checkout@v4
|
|
14
|
-
|
|
15
|
-
# Setup Node.js environment
|
|
16
|
-
- uses: actions/setup-node@v4
|
|
17
|
-
with:
|
|
18
|
-
node-version: 20
|
|
19
|
-
|
|
20
|
-
# Install dependencies using package-lock.json
|
|
21
|
-
- run: npm ci
|
|
22
|
-
|
|
23
|
-
# Run unit tests
|
|
24
|
-
- run: npm run test:unit
|
|
25
|
-
|
|
26
|
-
# Run acceptance tests
|
|
27
|
-
- run: npm run test:accept
|
|
28
|
-
|
|
29
|
-
publish-npm:
|
|
30
|
-
needs: build
|
|
31
|
-
runs-on: ubuntu-latest
|
|
32
|
-
steps:
|
|
33
|
-
# Checkout repository code again for a separate job
|
|
34
|
-
- uses: actions/checkout@v4
|
|
35
|
-
|
|
36
|
-
# Setup Node.js and configure npm registry
|
|
37
|
-
- uses: actions/setup-node@v4
|
|
38
|
-
with:
|
|
39
|
-
node-version: 20
|
|
40
|
-
registry-url: https://registry.npmjs.org/
|
|
41
|
-
|
|
42
|
-
# Install dependencies again
|
|
43
|
-
- run: npm ci
|
|
44
|
-
|
|
45
|
-
# Publish package to npm registry with authentication token
|
|
46
|
-
- run: npm publish --access public
|
|
47
|
-
env:
|
|
48
|
-
NODE_AUTH_TOKEN: ${{ secrets.npm_token }}
|
package/AGENTS.md
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
## Project: @flancer32/teq-web
|
|
4
|
-
|
|
5
|
-
This project implements a request dispatcher plugin for Tequila Framework (TeqFW).
|
|
6
|
-
The plugin provides a multi-stage handler system (`pre`, `process`, `post`) and integrates directly with Node.js servers (`http`, `http2`, `https`) without external dependencies.
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Project Structure
|
|
11
|
-
|
|
12
|
-
| Directory | Description |
|
|
13
|
-
|----------------------------|----------------------------------------------------------------------------|
|
|
14
|
-
| `/src/Back/Api/Handler.js` | Interface for all request handlers. |
|
|
15
|
-
| `/src/Back/Dispatcher.js` | Core dispatcher that orchestrates handler execution. |
|
|
16
|
-
| `/src/Back/Handler/` | Built-in request handlers (`Pre_Log`, `Static`, `Source`, etc). |
|
|
17
|
-
| `/src/Back/Helper/` | Internal helpers (`Mime`, `Respond`, `Order_Kahn`, etc). |
|
|
18
|
-
| `/src/Back/Dto/` | DTO factories used to pass typed configuration and metadata. |
|
|
19
|
-
| `/src/Back/Server.js` | Standalone HTTP(S) server implementation using built-in Node.js libraries. |
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Execution Agents
|
|
24
|
-
|
|
25
|
-
### Dispatcher
|
|
26
|
-
|
|
27
|
-
- File: `Back/Dispatcher.js`
|
|
28
|
-
- Role: Core runtime coordinator for HTTP requests.
|
|
29
|
-
- Interface: uses `Fl32_Web_Back_Api_Handler` and topological ordering via `Order_Kahn`.
|
|
30
|
-
|
|
31
|
-
### Server
|
|
32
|
-
|
|
33
|
-
- File: `Back/Server.js`
|
|
34
|
-
- Role: HTTP/1.1, HTTP/2, or HTTPS web server.
|
|
35
|
-
- Launches `Dispatcher.onEventRequest()` on each request.
|
|
36
|
-
|
|
37
|
-
### Handlers
|
|
38
|
-
|
|
39
|
-
- Files: `Back/Handler/Pre_Log.js`, `.../Static.js`, `.../Source.js`
|
|
40
|
-
- Role: Modular request processors, registered via `Dispatcher.addHandler()`.
|
|
41
|
-
- Lifecycle: Initialized once, executed per request by dispatcher.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Code Style
|
|
46
|
-
|
|
47
|
-
- Language: Modern JavaScript (ES2022+).
|
|
48
|
-
- No static imports (uses DI-based module resolution).
|
|
49
|
-
- All comments and messages must be in English (strict rule).
|
|
50
|
-
- File naming: PascalCase with dot-separated exports, e.g. `Fl32_Web_Back_Enum_Stage`.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Testing
|
|
55
|
-
|
|
56
|
-
- Unit tests must be provided for all runtime agents (Dispatcher, Handlers).
|
|
57
|
-
- Test framework: `node:test`.
|
|
58
|
-
- Mocks: registered via custom `buildTestContainer()` helper.
|
|
59
|
-
- Location: colocated or `/test/` folder depending on iteration.
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Build & Execution
|
|
64
|
-
|
|
65
|
-
- This project is a TeqFW plugin. It is not compiled or bundled.
|
|
66
|
-
- Executed in-place by Tequila runtime.
|
|
67
|
-
- Requires a DI container to resolve dependencies at runtime.
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Contribution Rules (for AI Agents)
|
|
72
|
-
|
|
73
|
-
- When creating new Handlers, they **must** implement `Fl32_Web_Back_Api_Handler` and provide `getRegistrationInfo()`.
|
|
74
|
-
- Handlers must be registered with `Dispatcher.addHandler()` and ordered with `orderHandlers()`.
|
|
75
|
-
- All request-handling code **must** call `respond.isWritable(res)` before sending a response.
|
|
76
|
-
- Do not modify existing dispatcher logic directly — create a new handler or helper instead.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Conventions for AI Tools (Codex, etc.)
|
|
81
|
-
|
|
82
|
-
- Start by inspecting `Dispatcher.js` and `Handler/` folder to locate runtime behavior.
|
|
83
|
-
- DTOs are created via `*.create(data)` methods and used to validate configs.
|
|
84
|
-
- Use `getRegistrationInfo().stage` to determine when a handler runs (`pre`, `process`, `post`).
|
|
85
|
-
- Prefer composition over inheritance. Avoid using `extends`.
|
|
86
|
-
- Respect topological order defined via `before`/`after`.
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## CI/Automation
|
|
91
|
-
|
|
92
|
-
- No CI defined yet. Future CI will:
|
|
93
|
-
- Validate handler registration structure.
|
|
94
|
-
- Enforce code style and comment policy.
|
|
95
|
-
- Run full test suite before merge.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## License
|
|
100
|
-
|
|
101
|
-
This project is licensed under the Apache-2.0 license.
|
package/eslint.config.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js';
|
|
2
|
-
import jsdoc from 'eslint-plugin-jsdoc';
|
|
3
|
-
import {defineConfig} from 'eslint/config';
|
|
4
|
-
import globals from 'globals';
|
|
5
|
-
|
|
6
|
-
export default defineConfig([
|
|
7
|
-
{
|
|
8
|
-
files: ['**/*.js', '**/*.mjs'],
|
|
9
|
-
plugins: {
|
|
10
|
-
js,
|
|
11
|
-
jsdoc,
|
|
12
|
-
},
|
|
13
|
-
extends: ['js/recommended'],
|
|
14
|
-
languageOptions: {
|
|
15
|
-
ecmaVersion: 'latest',
|
|
16
|
-
sourceType: 'module',
|
|
17
|
-
globals: {
|
|
18
|
-
...globals.browser,
|
|
19
|
-
...globals.node,
|
|
20
|
-
myCustomGlobal: 'readonly',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
rules: {
|
|
24
|
-
// Recommended ESLint rules
|
|
25
|
-
'no-unused-vars': 'warn',
|
|
26
|
-
'no-console': 'off',
|
|
27
|
-
'eqeqeq': 'error',
|
|
28
|
-
'curly': ['error', 'multi-line'],
|
|
29
|
-
'semi': ['error', 'always'],
|
|
30
|
-
// Your JSDoc rules
|
|
31
|
-
'jsdoc/check-alignment': 'error',
|
|
32
|
-
'jsdoc/check-param-names': 'error',
|
|
33
|
-
'jsdoc/check-types': 'error',
|
|
34
|
-
'jsdoc/require-param-description': 'warn',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
]);
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {describe, it} from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import http from 'node:http';
|
|
4
|
-
import {buildTestContainer} from '../unit/common.js';
|
|
5
|
-
import Express from 'express';
|
|
6
|
-
import Fastify from 'fastify';
|
|
7
|
-
|
|
8
|
-
async function startExpress(port, dispatcher) {
|
|
9
|
-
const app = Express();
|
|
10
|
-
app.use(async (req, res) => {
|
|
11
|
-
await dispatcher.onEventRequest(req, res);
|
|
12
|
-
});
|
|
13
|
-
const server = await new Promise((resolve, reject) => {
|
|
14
|
-
const srv = app.listen(port, err => err ? reject(err) : resolve(srv));
|
|
15
|
-
});
|
|
16
|
-
return server;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function startFastify(port, dispatcher) {
|
|
20
|
-
const fastify = Fastify();
|
|
21
|
-
fastify.all('*', async (request, reply) => {
|
|
22
|
-
const req = request.raw;
|
|
23
|
-
const res = reply.raw;
|
|
24
|
-
await dispatcher.onEventRequest(req, res);
|
|
25
|
-
});
|
|
26
|
-
await fastify.listen({port});
|
|
27
|
-
return fastify;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
describe('Dispatcher integration with external servers', () => {
|
|
31
|
-
it('should respond via express', async () => {
|
|
32
|
-
const container = buildTestContainer();
|
|
33
|
-
const dispatcher = await container.get('Fl32_Web_Back_Dispatcher$');
|
|
34
|
-
const port = 3054;
|
|
35
|
-
const server = await startExpress(port, dispatcher);
|
|
36
|
-
|
|
37
|
-
const status = await new Promise((resolve, reject) => {
|
|
38
|
-
http.get(`http://localhost:${port}`, res => {
|
|
39
|
-
const {statusCode} = res;
|
|
40
|
-
res.resume();
|
|
41
|
-
res.on('end', () => resolve(statusCode));
|
|
42
|
-
}).on('error', reject);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
assert.strictEqual(status, 404);
|
|
46
|
-
await new Promise(resolve => server.close(resolve));
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should respond via fastify', async () => {
|
|
50
|
-
const container = buildTestContainer();
|
|
51
|
-
const dispatcher = await container.get('Fl32_Web_Back_Dispatcher$');
|
|
52
|
-
const port = 3055;
|
|
53
|
-
const fastify = await startFastify(port, dispatcher);
|
|
54
|
-
|
|
55
|
-
const status = await new Promise((resolve, reject) => {
|
|
56
|
-
http.get(`http://localhost:${port}`, res => {
|
|
57
|
-
const {statusCode} = res;
|
|
58
|
-
res.resume();
|
|
59
|
-
res.on('end', () => resolve(statusCode));
|
|
60
|
-
}).on('error', reject);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
assert.strictEqual(status, 404);
|
|
64
|
-
await fastify.close();
|
|
65
|
-
});
|
|
66
|
-
});
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import {describe, it} from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import {readFileSync} from 'node:fs';
|
|
4
|
-
import {join, dirname} from 'node:path';
|
|
5
|
-
import {fileURLToPath} from 'node:url';
|
|
6
|
-
import {buildTestContainer} from '../unit/common.js';
|
|
7
|
-
|
|
8
|
-
async function waitListening(server) {
|
|
9
|
-
if (!server.getInstance().listening) {
|
|
10
|
-
await new Promise(res => server.getInstance().once('listening', res));
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
describe('Fl32_Web_Back_Server', () => {
|
|
15
|
-
it('should start and respond in HTTP/1 mode', async () => {
|
|
16
|
-
const container = buildTestContainer();
|
|
17
|
-
const server = await container.get('Fl32_Web_Back_Server$');
|
|
18
|
-
const SERVER_TYPE = await container.get('Fl32_Web_Back_Enum_Server_Type$');
|
|
19
|
-
const Config = await container.get('Fl32_Web_Back_Server_Config$');
|
|
20
|
-
const http = await container.get('node:http');
|
|
21
|
-
|
|
22
|
-
const cfg = Config.create({ port: 3051, type: SERVER_TYPE.HTTP });
|
|
23
|
-
await server.start(cfg);
|
|
24
|
-
await waitListening(server);
|
|
25
|
-
|
|
26
|
-
const status = await new Promise((resolve, reject) => {
|
|
27
|
-
http.get(`http://localhost:${cfg.port}`, res => {
|
|
28
|
-
const {statusCode} = res;
|
|
29
|
-
res.resume();
|
|
30
|
-
res.on('end', () => resolve(statusCode));
|
|
31
|
-
}).on('error', reject);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
assert.strictEqual(status, 404);
|
|
35
|
-
await server.stop();
|
|
36
|
-
assert.strictEqual(server.getInstance(), undefined);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should start and respond in HTTP/2 mode', async () => {
|
|
40
|
-
const container = buildTestContainer();
|
|
41
|
-
const server = await container.get('Fl32_Web_Back_Server$');
|
|
42
|
-
const SERVER_TYPE = await container.get('Fl32_Web_Back_Enum_Server_Type$');
|
|
43
|
-
const Config = await container.get('Fl32_Web_Back_Server_Config$');
|
|
44
|
-
const http2 = await container.get('node:http2');
|
|
45
|
-
|
|
46
|
-
const cfg = Config.create({ port: 3052, type: SERVER_TYPE.HTTP2 });
|
|
47
|
-
await server.start(cfg);
|
|
48
|
-
await waitListening(server);
|
|
49
|
-
|
|
50
|
-
const status = await new Promise((resolve, reject) => {
|
|
51
|
-
const client = http2.connect(`http://localhost:${cfg.port}`);
|
|
52
|
-
client.on('error', reject);
|
|
53
|
-
const req = client.request({ ':path': '/' });
|
|
54
|
-
req.on('response', headers => {
|
|
55
|
-
resolve(headers[':status']);
|
|
56
|
-
});
|
|
57
|
-
req.on('end', () => client.close());
|
|
58
|
-
req.end();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
assert.strictEqual(status, 404);
|
|
62
|
-
await server.stop();
|
|
63
|
-
assert.strictEqual(server.getInstance(), undefined);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should start and respond in HTTPS mode', async () => {
|
|
67
|
-
const container = buildTestContainer();
|
|
68
|
-
const server = await container.get('Fl32_Web_Back_Server$');
|
|
69
|
-
const SERVER_TYPE = await container.get('Fl32_Web_Back_Enum_Server_Type$');
|
|
70
|
-
const Config = await container.get('Fl32_Web_Back_Server_Config$');
|
|
71
|
-
const http2 = await container.get('node:http2');
|
|
72
|
-
|
|
73
|
-
const dir = dirname(fileURLToPath(import.meta.url));
|
|
74
|
-
const certDir = join(dir, '..', 'certs');
|
|
75
|
-
const key = readFileSync(join(certDir, 'key.pem'), 'utf8');
|
|
76
|
-
const cert = readFileSync(join(certDir, 'cert.pem'), 'utf8');
|
|
77
|
-
let ca;
|
|
78
|
-
try { ca = readFileSync(join(certDir, 'ca.pem'), 'utf8'); } catch {}
|
|
79
|
-
|
|
80
|
-
const cfg = Config.create({
|
|
81
|
-
port: 3053,
|
|
82
|
-
type: SERVER_TYPE.HTTPS,
|
|
83
|
-
tls: {key, cert, ca}
|
|
84
|
-
});
|
|
85
|
-
await server.start(cfg);
|
|
86
|
-
await waitListening(server);
|
|
87
|
-
|
|
88
|
-
const status = await new Promise((resolve, reject) => {
|
|
89
|
-
const client = http2.connect(`https://localhost:${cfg.port}`, {
|
|
90
|
-
rejectUnauthorized: false,
|
|
91
|
-
});
|
|
92
|
-
client.on('error', reject);
|
|
93
|
-
const req = client.request({ ':path': '/' });
|
|
94
|
-
req.on('response', headers => {
|
|
95
|
-
resolve(headers[':status']);
|
|
96
|
-
});
|
|
97
|
-
req.on('end', () => client.close());
|
|
98
|
-
req.end();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
assert.strictEqual(status, 404);
|
|
102
|
-
await server.stop();
|
|
103
|
-
assert.strictEqual(server.getInstance(), undefined);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe('Fl32_Web_Back_Api_Handler', () => {
|
|
108
|
-
it('should serve allowed NPM file', async () => {
|
|
109
|
-
const container = buildTestContainer();
|
|
110
|
-
const dispatcher = await container.get('Fl32_Web_Back_Dispatcher$');
|
|
111
|
-
const handler = await container.get('Fl32_Web_Back_Handler_Static$');
|
|
112
|
-
const Cfg = await container.get('Fl32_Web_Back_Dto_Handler_Source$');
|
|
113
|
-
await handler.init({
|
|
114
|
-
sources: [Cfg.create({
|
|
115
|
-
root: 'node_modules',
|
|
116
|
-
prefix: '/npm/',
|
|
117
|
-
allow: {
|
|
118
|
-
'@teqfw/di/src': ['.'],
|
|
119
|
-
},
|
|
120
|
-
})],
|
|
121
|
-
});
|
|
122
|
-
dispatcher.addHandler(handler);
|
|
123
|
-
dispatcher.orderHandlers();
|
|
124
|
-
|
|
125
|
-
const server = await container.get('Fl32_Web_Back_Server$');
|
|
126
|
-
const SERVER_TYPE = await container.get('Fl32_Web_Back_Enum_Server_Type$');
|
|
127
|
-
const Config = await container.get('Fl32_Web_Back_Server_Config$');
|
|
128
|
-
const http = await container.get('node:http');
|
|
129
|
-
|
|
130
|
-
const cfg = Config.create({ port: 3056, type: SERVER_TYPE.HTTP });
|
|
131
|
-
await server.start(cfg);
|
|
132
|
-
await waitListening(server);
|
|
133
|
-
|
|
134
|
-
const result = await new Promise((resolve, reject) => {
|
|
135
|
-
const req = http.get({
|
|
136
|
-
hostname: 'localhost',
|
|
137
|
-
port: cfg.port,
|
|
138
|
-
path: '/npm/@teqfw/di/src/Api/Container/Parser/Chunk.js',
|
|
139
|
-
}, res => {
|
|
140
|
-
const chunks = [];
|
|
141
|
-
res.on('data', ch => chunks.push(ch));
|
|
142
|
-
res.on('end', () => {
|
|
143
|
-
resolve({ status: res.statusCode, body: Buffer.concat(chunks).toString() });
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
req.on('error', reject);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
assert.strictEqual(result.status, 200);
|
|
150
|
-
assert.match(result.body, /class TeqFw_Di_Api_Container_Parser_Chunk/);
|
|
151
|
-
|
|
152
|
-
await server.stop();
|
|
153
|
-
assert.strictEqual(server.getInstance(), undefined);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should serve allowed source file', async () => {
|
|
157
|
-
const container = buildTestContainer();
|
|
158
|
-
const dispatcher = await container.get('Fl32_Web_Back_Dispatcher$');
|
|
159
|
-
const handler = await container.get('Fl32_Web_Back_Handler_Static$');
|
|
160
|
-
const Cfg = await container.get('Fl32_Web_Back_Dto_Handler_Source$');
|
|
161
|
-
await handler.init({
|
|
162
|
-
sources: [Cfg.create({
|
|
163
|
-
root: 'src',
|
|
164
|
-
prefix: '/sources/',
|
|
165
|
-
allow: {
|
|
166
|
-
Back: ['Server.js'],
|
|
167
|
-
},
|
|
168
|
-
})],
|
|
169
|
-
});
|
|
170
|
-
dispatcher.addHandler(handler);
|
|
171
|
-
dispatcher.orderHandlers();
|
|
172
|
-
|
|
173
|
-
const server = await container.get('Fl32_Web_Back_Server$');
|
|
174
|
-
const SERVER_TYPE = await container.get('Fl32_Web_Back_Enum_Server_Type$');
|
|
175
|
-
const Config = await container.get('Fl32_Web_Back_Server_Config$');
|
|
176
|
-
const http = await container.get('node:http');
|
|
177
|
-
|
|
178
|
-
const cfg = Config.create({ port: 3057, type: SERVER_TYPE.HTTP });
|
|
179
|
-
await server.start(cfg);
|
|
180
|
-
await waitListening(server);
|
|
181
|
-
|
|
182
|
-
const result = await new Promise((resolve, reject) => {
|
|
183
|
-
const req = http.get({
|
|
184
|
-
hostname: 'localhost',
|
|
185
|
-
port: cfg.port,
|
|
186
|
-
path: '/sources/Back/Server.js',
|
|
187
|
-
}, res => {
|
|
188
|
-
const chunks = [];
|
|
189
|
-
res.on('data', ch => chunks.push(ch));
|
|
190
|
-
res.on('end', () => {
|
|
191
|
-
resolve({ status: res.statusCode, body: Buffer.concat(chunks).toString() });
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
req.on('error', reject);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
assert.strictEqual(result.status, 200);
|
|
198
|
-
assert.match(result.body, /class Fl32_Web_Back_Server/);
|
|
199
|
-
|
|
200
|
-
await server.stop();
|
|
201
|
-
assert.strictEqual(server.getInstance(), undefined);
|
|
202
|
-
});
|
|
203
|
-
});
|
package/test/certs/ca.pem
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIDCTCCAfGgAwIBAgIUBpZ2v9fA8XfqVF83Nw5byUa0ylswDQYJKoZIhvcNAQEL
|
|
3
|
-
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDYwODA5MDA1N1oXDTI2MDYw
|
|
4
|
-
ODA5MDA1N1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
|
|
5
|
-
AAOCAQ8AMIIBCgKCAQEAymikxJnbPFs3H/rRzetPjUdOPVuMOTfkz5oBDcP7s/2W
|
|
6
|
-
O7135UPbDGzClYyYJvwAZm9i1Vivzm6KrNDZR0lawqYVf6COGJSAtMrkzx+bFSh7
|
|
7
|
-
HWhuk4ByAdoZr6kFzpYBrxcfjSLU2oqaCyzb5vfksfrk1Yyr/i8DK6sw640OUlzP
|
|
8
|
-
1rtKTuRCpYm8We/wrxEvrcdzk7FVFYLCzQfGOZLPmZpoDI3pdUJ/wkY4tjPAPFLn
|
|
9
|
-
143L+07ZLN7Zuf0mpRAGpKve+MWzfId4xXoJ2XpGolLEkhJhfDNI9DCBjEZ3cYmJ
|
|
10
|
-
LYSkpevQuTJNQm/89ivPk3FV0p3H4KjKKgtvtUaOZQIDAQABo1MwUTAdBgNVHQ4E
|
|
11
|
-
FgQUjriVSWVYIJ/a21utkNLU2Cvjl1swHwYDVR0jBBgwFoAUjriVSWVYIJ/a21ut
|
|
12
|
-
kNLU2Cvjl1swDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkcHr
|
|
13
|
-
TPlqzehyG1KGGb7VAGwCoqhUJfz0Pd3z2p+UOoKq/EmC8b1FRgKDZxSQHk0hhQWE
|
|
14
|
-
M4f51tTbv2LgskfOF/S/tDoKBGnOwYS0oFmVqEstHuC2uto8ukj3FNvsZW58x4Q1
|
|
15
|
-
DOGLkUqlPj5vAh8Zhw8GWokorF11dZlnKdPTC3NCdqyPTWNQPeSqd2qGsFgMBB2i
|
|
16
|
-
q49QsUCNqiVc5ZfpbTBq+Jk1qHd1Pyf9Dlxm3Wi6RBguBcpHooZTAAYleSk+uhSa
|
|
17
|
-
xH9f8v9E2aeYAk/zsZQt2f3x9sZQCAfjHPDOzXydiv568FasLxACY12/GkMNGdvy
|
|
18
|
-
xlgkz6c0z3TS8kFxrQ==
|
|
19
|
-
-----END CERTIFICATE-----
|
package/test/certs/cert.pem
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIDCTCCAfGgAwIBAgIUBpZ2v9fA8XfqVF83Nw5byUa0ylswDQYJKoZIhvcNAQEL
|
|
3
|
-
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDYwODA5MDA1N1oXDTI2MDYw
|
|
4
|
-
ODA5MDA1N1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
|
|
5
|
-
AAOCAQ8AMIIBCgKCAQEAymikxJnbPFs3H/rRzetPjUdOPVuMOTfkz5oBDcP7s/2W
|
|
6
|
-
O7135UPbDGzClYyYJvwAZm9i1Vivzm6KrNDZR0lawqYVf6COGJSAtMrkzx+bFSh7
|
|
7
|
-
HWhuk4ByAdoZr6kFzpYBrxcfjSLU2oqaCyzb5vfksfrk1Yyr/i8DK6sw640OUlzP
|
|
8
|
-
1rtKTuRCpYm8We/wrxEvrcdzk7FVFYLCzQfGOZLPmZpoDI3pdUJ/wkY4tjPAPFLn
|
|
9
|
-
143L+07ZLN7Zuf0mpRAGpKve+MWzfId4xXoJ2XpGolLEkhJhfDNI9DCBjEZ3cYmJ
|
|
10
|
-
LYSkpevQuTJNQm/89ivPk3FV0p3H4KjKKgtvtUaOZQIDAQABo1MwUTAdBgNVHQ4E
|
|
11
|
-
FgQUjriVSWVYIJ/a21utkNLU2Cvjl1swHwYDVR0jBBgwFoAUjriVSWVYIJ/a21ut
|
|
12
|
-
kNLU2Cvjl1swDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkcHr
|
|
13
|
-
TPlqzehyG1KGGb7VAGwCoqhUJfz0Pd3z2p+UOoKq/EmC8b1FRgKDZxSQHk0hhQWE
|
|
14
|
-
M4f51tTbv2LgskfOF/S/tDoKBGnOwYS0oFmVqEstHuC2uto8ukj3FNvsZW58x4Q1
|
|
15
|
-
DOGLkUqlPj5vAh8Zhw8GWokorF11dZlnKdPTC3NCdqyPTWNQPeSqd2qGsFgMBB2i
|
|
16
|
-
q49QsUCNqiVc5ZfpbTBq+Jk1qHd1Pyf9Dlxm3Wi6RBguBcpHooZTAAYleSk+uhSa
|
|
17
|
-
xH9f8v9E2aeYAk/zsZQt2f3x9sZQCAfjHPDOzXydiv568FasLxACY12/GkMNGdvy
|
|
18
|
-
xlgkz6c0z3TS8kFxrQ==
|
|
19
|
-
-----END CERTIFICATE-----
|
package/test/certs/key.pem
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDKaKTEmds8Wzcf
|
|
3
|
-
+tHN60+NR049W4w5N+TPmgENw/uz/ZY7vXflQ9sMbMKVjJgm/ABmb2LVWK/Oboqs
|
|
4
|
-
0NlHSVrCphV/oI4YlIC0yuTPH5sVKHsdaG6TgHIB2hmvqQXOlgGvFx+NItTaipoL
|
|
5
|
-
LNvm9+Sx+uTVjKv+LwMrqzDrjQ5SXM/Wu0pO5EKlibxZ7/CvES+tx3OTsVUVgsLN
|
|
6
|
-
B8Y5ks+ZmmgMjel1Qn/CRji2M8A8UufXjcv7Ttks3tm5/SalEAakq974xbN8h3jF
|
|
7
|
-
egnZekaiUsSSEmF8M0j0MIGMRndxiYkthKSl69C5Mk1Cb/z2K8+TcVXSncfgqMoq
|
|
8
|
-
C2+1Ro5lAgMBAAECggEAEva0lUI6/aUoKC62Ox4++6QWIFPe8o9vjcRxMSp5qcvq
|
|
9
|
-
Uu+LTPzLXZclBfZAXSACzkDFAusbvEdeu8FCJ4EnvTvqoLoDW38yWH3367CbiuMa
|
|
10
|
-
NyT30zRXZMqxLw7ddJUDqbViEeA/uWKp+xO5Xfg/bNjDrtROsEe++szqY5n5dl2B
|
|
11
|
-
aJLPEtg2OQW7GWKF7PX9YyZmbZds+L7WFhTE+42zfO6MMQm5jaTr8er74u6FnEA2
|
|
12
|
-
ewrJmB7i9CS1DfYhCnJCwqOIxr9rPp9WMvRNfmL8wwqAr+4f1TidI7aKpA3vt2d0
|
|
13
|
-
HOrnNws+08tlcqQYHHyasLzBzsYGAZRTvCoCxjVd8wKBgQDkWjNxp9TmNxQXxvhB
|
|
14
|
-
J42lmo+9xBYzKUzmMMSvS7RoPFG8myf1s82qPTiwZZzGlpR6XIXfSZKQ45YhYz7S
|
|
15
|
-
8i8VbhjVtGyOmExBRYryI3y8pC1aVHk6bPQl8rATIkqsIGN8VHSiwCMeV+j6VWUP
|
|
16
|
-
ZYjb0iqS2zKhhXD9CVcXIT/SfwKBgQDi6lG64nI/ECjakXfrXa+J1T5NJE+OEP3J
|
|
17
|
-
AR9nqRiR/VcwAFMBiJwFfm07dv4WHLbfI1qdx+OU4aSsBohyLg3X9WO0Y8iGw2w4
|
|
18
|
-
V6GGiwGK009OfzdrwTM9QjVHhk23SlFeQFPib4uRGcRnjimMNY6M1E3qvXHpyVXV
|
|
19
|
-
rpvxyGElGwKBgGjcXwlPJ738BvcQQIoy7qHggyeCdytRSOXf+UICQrsnD+XLXiM/
|
|
20
|
-
SS9m47RlRQQQu+ggur0ZnPt590Qnvf7ChgqSP0dLjhpBJ6tFkxO0ZiB+R/FWH0FM
|
|
21
|
-
LSWL930h3yaBzQ2X/uOJ1damSe9C7aCPYLSJI1HC5NI1Y/hepKaTdypjAoGAEfkr
|
|
22
|
-
ZhkfoX0fL0jMbdkq2UkJuUSCBKe14mDzYtuS9aVSbZvo9zsh2JGOB2LCd2/o0D3V
|
|
23
|
-
pJ+7mARTbcjKr/iT4iIutpAcxwfdn4zZX3XNNnjMVFRhSGiyLUz8OWEa8MSzMzr3
|
|
24
|
-
Kf1Z2bFnzCgHhHKNivwZ+9jrl+/5m4ZMFdegUjcCgYEAu/cKxIBc3Lb4gVZx6nHp
|
|
25
|
-
bPr9flDbdCKQk20kpVPvNxq67FuVyKy3n0svRX+fZ9uPhuv20IWkTBue3yCGKpjD
|
|
26
|
-
kUJ2A9Y9FZGSwhU3LSo6grdEv3pIW1YLTl95nUO20bRWCWcwsoV5/GEhFkEZWq06
|
|
27
|
-
wZCQXFhIY78gzd4gk+qJQpg=
|
|
28
|
-
-----END PRIVATE KEY-----
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export default class App_Plugin_Start {
|
|
2
|
-
/**
|
|
3
|
-
* @param {typeof import('node:path')} path
|
|
4
|
-
* @param {typeof import('node:url')} url
|
|
5
|
-
* @param {Fl32_Web_Back_Dispatcher} dispatcher
|
|
6
|
-
* @param {Fl32_Web_Back_Handler_Pre_Log} hndlRequestLog
|
|
7
|
-
* @param {Fl32_Web_Back_Handler_Static} hndlStatic
|
|
8
|
-
* @param {Fl32_Web_Back_Dto_Handler_Source} dtoCfg
|
|
9
|
-
*/
|
|
10
|
-
constructor(
|
|
11
|
-
{
|
|
12
|
-
'node:path': path,
|
|
13
|
-
'node:url': url,
|
|
14
|
-
Fl32_Web_Back_Dispatcher$: dispatcher,
|
|
15
|
-
Fl32_Web_Back_Handler_Pre_Log$: hndlRequestLog,
|
|
16
|
-
Fl32_Web_Back_Handler_Static$: hndlStatic,
|
|
17
|
-
Fl32_Web_Back_Dto_Handler_Source$: dtoCfg,
|
|
18
|
-
}
|
|
19
|
-
) {
|
|
20
|
-
// VARS
|
|
21
|
-
const {dirname, join} = path;
|
|
22
|
-
const {fileURLToPath} = url;
|
|
23
|
-
|
|
24
|
-
// MAIN
|
|
25
|
-
/* Resolve a path to the root folder. */
|
|
26
|
-
const metaUrl = new URL(import.meta.url);
|
|
27
|
-
const script = fileURLToPath(metaUrl);
|
|
28
|
-
const cur = dirname(script);
|
|
29
|
-
const root = join(cur, '..', '..');
|
|
30
|
-
const webRoot = join(root, 'web');
|
|
31
|
-
|
|
32
|
-
return async function () {
|
|
33
|
-
const srcNpm = dtoCfg.create({root: 'node_modules', prefix: '/npm/', allow: {'@teqfw/di': ['src/Container.js']}});
|
|
34
|
-
const srcWeb = dtoCfg.create({root: webRoot, prefix: '/'});
|
|
35
|
-
await hndlStatic.init({sources: [srcNpm, srcWeb]});
|
|
36
|
-
dispatcher.addHandler(hndlRequestLog);
|
|
37
|
-
dispatcher.addHandler(hndlStatic);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|