@j3r3mcdev/oast-server 1.1.12 → 1.1.14

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 (106) hide show
  1. package/dist/listeners/api/api.routes.js +31 -5
  2. package/package.json +4 -1
  3. package/.env.example +0 -0
  4. package/.github/workflows/ci.yml +0 -29
  5. package/.github/workflows/publish.yml +0 -31
  6. package/image.png +0 -0
  7. package/jest.config.js +0 -14
  8. package/sadmin list shadows +0 -9
  9. package/src/api/controllers/__tests__/tasks.controller.test.ts +0 -74
  10. package/src/api/controllers/events.controller.ts +0 -10
  11. package/src/api/controllers/health.controller.ts +0 -7
  12. package/src/api/controllers/index.ts +0 -0
  13. package/src/api/controllers/tasks.controller.ts +0 -41
  14. package/src/api/dto/__tests__/create-task.dto.test.ts +0 -41
  15. package/src/api/dto/__tests__/filter-tasks.dto.test.ts +0 -35
  16. package/src/api/dto/create-task.dto.ts +0 -33
  17. package/src/api/dto/filter-tasks.dto.ts +0 -33
  18. package/src/api/services/__tests__/events.service.test.ts +0 -41
  19. package/src/api/services/__tests__/tasks.service.test.ts +0 -41
  20. package/src/api/services/events.service.ts +0 -17
  21. package/src/api/services/tasks.service.ts +0 -79
  22. package/src/api/sse/events.stream.ts +0 -90
  23. package/src/bootstrap.ts +0 -89
  24. package/src/config/constants.ts +0 -0
  25. package/src/config/env.ts +0 -0
  26. package/src/core/__tests__/core-router.test.ts +0 -30
  27. package/src/core/__tests__/core-server.test.ts +0 -44
  28. package/src/core/__tests__/event.normalizer.test.ts +0 -56
  29. package/src/core/__tests__/event.router.test.ts +0 -89
  30. package/src/core/__tests__/logger.test.ts +0 -32
  31. package/src/core/__tests__/storage-manager.test.ts +0 -74
  32. package/src/core/event.normalizer.ts +0 -167
  33. package/src/core/event.router.ts +0 -13
  34. package/src/core/http/__tests__/adapter-node.test.ts +0 -52
  35. package/src/core/http/__tests__/body-parser-multipart.test.ts +0 -41
  36. package/src/core/http/__tests__/body-parser-raw.test.ts +0 -28
  37. package/src/core/http/__tests__/body-parser-text.test.ts +0 -28
  38. package/src/core/http/__tests__/compile-path.test.ts +0 -39
  39. package/src/core/http/__tests__/middleware-pipeline.test.ts +0 -51
  40. package/src/core/http/__tests__/request.test.ts +0 -34
  41. package/src/core/http/__tests__/response.test.ts +0 -35
  42. package/src/core/http/__tests__/router-match.test.ts +0 -171
  43. package/src/core/http/adapter-node.ts +0 -51
  44. package/src/core/http/buildRequest.ts +0 -18
  45. package/src/core/http/compile-path.ts +0 -32
  46. package/src/core/http/errors.ts +0 -37
  47. package/src/core/http/http-server.ts +0 -52
  48. package/src/core/http/index.ts +0 -0
  49. package/src/core/http/main.ts +0 -0
  50. package/src/core/http/middleware.ts +0 -160
  51. package/src/core/http/request.ts +0 -55
  52. package/src/core/http/response.ts +0 -93
  53. package/src/core/http/router.ts +0 -138
  54. package/src/core/http/utils.ts +0 -0
  55. package/src/core/id-generator.ts +0 -8
  56. package/src/core/logger.ts +0 -113
  57. package/src/core/router.ts +0 -44
  58. package/src/core/server.ts +0 -85
  59. package/src/core/storage.ts +0 -64
  60. package/src/index.ts +0 -14
  61. package/src/listeners/api/__tests__/api.controller.test.ts +0 -116
  62. package/src/listeners/api/__tests__/api.extractor.test.ts +0 -46
  63. package/src/listeners/api/__tests__/api.listener.test.ts +0 -82
  64. package/src/listeners/api/__tests__/api.routes.test.ts +0 -155
  65. package/src/listeners/api/__tests__/api.sse.test.ts +0 -105
  66. package/src/listeners/api/api.controllers.ts +0 -67
  67. package/src/listeners/api/api.extractor.ts +0 -43
  68. package/src/listeners/api/api.listener.ts +0 -50
  69. package/src/listeners/api/api.routes.ts +0 -76
  70. package/src/listeners/api/api.sse.ts +0 -38
  71. package/src/listeners/dns/__tests__/dns.test.ts +0 -118
  72. package/src/listeners/dns/dns.extractor.ts +0 -14
  73. package/src/listeners/dns/dns.listener.ts +0 -61
  74. package/src/listeners/http/__tests__/http.extractor.test.ts +0 -59
  75. package/src/listeners/http/__tests__/http.listener.test.ts +0 -133
  76. package/src/listeners/http/http.extractor.ts +0 -15
  77. package/src/listeners/http/http.listener.ts +0 -110
  78. package/src/listeners/listener.interface.ts +0 -4
  79. package/src/listeners/smtp/__tests__/smtp.extractor.test.ts +0 -69
  80. package/src/listeners/smtp/__tests__/smtp.listener.test.ts +0 -150
  81. package/src/listeners/smtp/smtp.extractor.ts +0 -18
  82. package/src/listeners/smtp/smtp.listener.ts +0 -78
  83. package/src/listeners/ssrf/__tests__/ssrf.extractor.test.ts +0 -41
  84. package/src/listeners/ssrf/__tests__/ssrf.listener.test.ts +0 -87
  85. package/src/listeners/ssrf/ssrf.extractor.ts +0 -14
  86. package/src/listeners/ssrf/ssrf.listener.ts +0 -37
  87. package/src/listeners/tcp/tcp.extractor.ts +0 -16
  88. package/src/listeners/tcp/tcp.listener.ts +0 -61
  89. package/src/listeners/webhook/__tests__/webhook.extractor.test.ts +0 -35
  90. package/src/listeners/webhook/__tests__/webhook.listener.test.ts +0 -122
  91. package/src/listeners/webhook/webhook.extractor.ts +0 -12
  92. package/src/listeners/webhook/webhook.listener.ts +0 -58
  93. package/src/listeners/websocket/__tests__/websocket.extractor.test.ts +0 -33
  94. package/src/listeners/websocket/__tests__/websocket.listener.test.ts +0 -90
  95. package/src/listeners/websocket/websocket.extractor.ts +0 -11
  96. package/src/listeners/websocket/websocket.listener.ts +0 -40
  97. package/src/storage-adapters/adapters/__tests__/memory.storage.test.ts +0 -75
  98. package/src/storage-adapters/adapters/memory.storage.ts +0 -64
  99. package/src/storage-adapters/adapters/redis.storage.ts +0 -0
  100. package/src/storage-adapters/adapters/sqlite.storage.ts +0 -0
  101. package/src/storage-adapters/storage.interface.ts +0 -26
  102. package/src/types/event.types.ts +0 -166
  103. package/src/utils/token.ts +0 -0
  104. package/src-api.txt +0 -0
  105. package/src-architecture.txt +0 -0
  106. package/tsconfig.json +0 -20
@@ -1,52 +0,0 @@
1
- import { NodeAdapter } from "../adapter-node";
2
- import { MiddlewarePipeline } from "../middleware";
3
- import { Router } from "../router";
4
- import { Request } from "../request";
5
- import { Response } from "../response";
6
- import { describe, it, expect, jest } from "@jest/globals";
7
- import * as Build from "../buildRequest";
8
-
9
- describe("NodeAdapter.handle", () => {
10
- it("appelle le handler quand la route match", async () => {
11
- const router = new Router();
12
- const pipeline = new MiddlewarePipeline();
13
-
14
- // mock buildRequest
15
- const buildRequestMock = jest
16
- .spyOn(Build, "buildRequest")
17
- .mockImplementation(
18
- (raw: any, params?: Record<string, string>) =>
19
- new Request({
20
- method: "GET",
21
- path: "/test",
22
- headers: {},
23
- params: params ?? {},
24
- }),
25
- );
26
-
27
- const handler = jest.fn();
28
-
29
- router.match = jest.fn(() => ({
30
- handler,
31
- params: { id: "42" },
32
- middlewares: [],
33
- })) as any;
34
-
35
- pipeline.run = jest.fn(async () => {}) as any;
36
-
37
- const res = {
38
- writableEnded: false,
39
- setHeader: jest.fn(),
40
- end: jest.fn(),
41
- statusCode: 200,
42
- };
43
-
44
- const adapter = new NodeAdapter(router, pipeline);
45
-
46
- await adapter.handle({ url: "/test", method: "GET", headers: {} }, res);
47
-
48
- expect(handler).toHaveBeenCalled();
49
- expect(pipeline.run).toHaveBeenCalled();
50
- expect(buildRequestMock).toHaveBeenCalledTimes(2);
51
- });
52
- });
@@ -1,41 +0,0 @@
1
- import { bodyParserMultipart } from "../middleware";
2
- import { Request } from "../request";
3
- import { Response } from "../response";
4
- import { describe, it, expect } from "@jest/globals";
5
-
6
- describe("bodyParserMultipart", () => {
7
- it("parse un champ texte et un fichier", async () => {
8
- const boundary = "----1234";
9
-
10
- const raw = {
11
- headers: { "content-type": `multipart/form-data; boundary=${boundary}` },
12
- [Symbol.asyncIterator]: async function* () {
13
- yield Buffer.from(
14
- `--${boundary}\r\n` +
15
- `Content-Disposition: form-data; name="username"\r\n\r\n` +
16
- `jeremy\r\n` +
17
- `--${boundary}\r\n` +
18
- `Content-Disposition: form-data; name="file"; filename="test.txt"\r\n` +
19
- `Content-Type: text/plain\r\n\r\n` +
20
- `Hello world\r\n` +
21
- `--${boundary}--`,
22
- );
23
- },
24
- };
25
-
26
- const req = new Request({
27
- method: "POST",
28
- path: "/upload",
29
- headers: raw.headers,
30
- raw,
31
- });
32
-
33
- const res = new Response({});
34
-
35
- await bodyParserMultipart(req, res);
36
-
37
- expect(req.form?.username).toBe("jeremy");
38
- expect(req.files?.[0].filename).toBe("test.txt");
39
- expect(req.files?.[0].data.toString()).toBe("Hello world");
40
- });
41
- });
@@ -1,28 +0,0 @@
1
- import { bodyParserRaw } from "../middleware";
2
- import { Request } from "../request";
3
- import { Response } from "../response";
4
- import { describe, it, expect } from "@jest/globals";
5
-
6
- describe("bodyParserRaw", () => {
7
- it("lit le body brut", async () => {
8
- const raw = {
9
- headers: { "content-type": "application/octet-stream" },
10
- [Symbol.asyncIterator]: async function* () {
11
- yield Buffer.from([1, 2, 3, 4]);
12
- },
13
- };
14
-
15
- const req = new Request({
16
- method: "POST",
17
- path: "/",
18
- headers: raw.headers,
19
- raw,
20
- });
21
-
22
- const res = new Response({});
23
-
24
- await bodyParserRaw(req, res);
25
-
26
- expect(req.bodyRaw).toEqual(Buffer.from([1, 2, 3, 4]));
27
- });
28
- });
@@ -1,28 +0,0 @@
1
- import { bodyParserText } from "../middleware";
2
- import { Request } from "../request";
3
- import { Response } from "../response";
4
- import { describe, it, expect } from "@jest/globals";
5
-
6
- describe("bodyParserText", () => {
7
- it("lit le body text", async () => {
8
- const raw = {
9
- headers: { "content-type": "text/plain" },
10
- [Symbol.asyncIterator]: async function* () {
11
- yield Buffer.from("Hello world");
12
- },
13
- };
14
-
15
- const req = new Request({
16
- method: "POST",
17
- path: "/",
18
- headers: raw.headers,
19
- raw,
20
- });
21
-
22
- const res = new Response({});
23
-
24
- await bodyParserText(req, res);
25
-
26
- expect(req.bodyText).toBe("Hello world");
27
- });
28
- });
@@ -1,39 +0,0 @@
1
- import { compilePath } from "../compile-path";
2
- import { describe, it, expect } from "@jest/globals";
3
-
4
- describe("compilePath", () => {
5
- it("compile un chemin simple avec segment statique", () => {
6
- const result = compilePath("/tasks");
7
-
8
- expect(result).toEqual([{ type: "static", value: "tasks" }]);
9
- });
10
-
11
- it("compile un chemin avec paramètre", () => {
12
- const result = compilePath("/tasks/:id");
13
-
14
- expect(result).toEqual([
15
- { type: "static", value: "tasks" },
16
- { type: "param", name: "id" },
17
- ]);
18
- });
19
-
20
- it("compile un chemin avec paramètre", () => {
21
- const result = compilePath("/tasks/:id");
22
-
23
- expect(result).toEqual([
24
- { type: "static", value: "tasks" },
25
- { type: "param", name: "id" },
26
- ]);
27
- });
28
-
29
- it("compile un chemin complexe avec static, param et wildcard", () => {
30
- const result = compilePath("/a/:b/*/c");
31
-
32
- expect(result).toEqual([
33
- { type: "static", value: "a" },
34
- { type: "param", name: "b" },
35
- { type: "wildcard" },
36
- { type: "static", value: "c" },
37
- ]);
38
- });
39
- });
@@ -1,51 +0,0 @@
1
- import { MiddlewarePipeline } from "../../http/middleware";
2
- import { Request } from "../../http/request";
3
- import { Response } from "../../http/response";
4
- import { describe, it, expect, jest } from "@jest/globals";
5
-
6
- describe("MiddlewarePipeline", () => {
7
- it("exécute les middlewares dans l'ordre", async () => {
8
- const pipeline = new MiddlewarePipeline();
9
-
10
- const calls: string[] = [];
11
-
12
- pipeline.use(async (req, res, next) => {
13
- calls.push("mw1");
14
- await next();
15
- });
16
-
17
- pipeline.use(async (req, res, next) => {
18
- calls.push("mw2");
19
- await next();
20
- });
21
-
22
- const req = new Request({ method: "GET", path: "/", headers: {} });
23
- const res = new Response({ setHeader: jest.fn(), end: jest.fn() });
24
-
25
- await pipeline.run(req, res);
26
-
27
- expect(calls).toEqual(["mw1", "mw2"]);
28
- });
29
-
30
- it("arrête la chaîne si next() n'est pas appelé", async () => {
31
- const pipeline = new MiddlewarePipeline();
32
-
33
- const calls: string[] = [];
34
-
35
- pipeline.use(async () => {
36
- calls.push("mw1");
37
- // pas de next()
38
- });
39
-
40
- pipeline.use(async () => {
41
- calls.push("mw2");
42
- });
43
-
44
- const req = new Request({ method: "GET", path: "/", headers: {} });
45
- const res = new Response({ setHeader: jest.fn(), end: jest.fn() });
46
-
47
- await pipeline.run(req, res);
48
-
49
- expect(calls).toEqual(["mw1"]);
50
- });
51
- });
@@ -1,34 +0,0 @@
1
- import { Request } from "../request";
2
- import { describe, it, expect } from "@jest/globals";
3
-
4
- describe("Request", () => {
5
- it("crée une requête immuable avec les bonnes propriétés", () => {
6
- const req = new Request({
7
- method: "GET",
8
- path: "/test",
9
- headers: { "content-type": "application/json" },
10
- query: { a: "1" },
11
- params: { id: "123" },
12
- body: { x: 1 },
13
- ip: "127.0.0.1",
14
- });
15
-
16
- expect(req.method).toBe("GET");
17
- expect(req.path).toBe("/test");
18
- expect(req.headers["content-type"]).toBe("application/json");
19
- expect(req.query.a).toBe("1");
20
- expect(req.params.id).toBe("123");
21
- expect(req.body.x).toBe(1);
22
- expect(req.ip).toBe("127.0.0.1");
23
- });
24
-
25
- it("retourne un header via header()", () => {
26
- const req = new Request({
27
- method: "GET",
28
- path: "/",
29
- headers: { "x-test": "ok" },
30
- });
31
-
32
- expect(req.header("x-test")).toBe("ok");
33
- });
34
- });
@@ -1,35 +0,0 @@
1
- import { Response } from "../../http/response";
2
- import { describe, it, expect, jest } from "@jest/globals";
3
-
4
- describe("Response", () => {
5
- it("enregistre le status et les headers", () => {
6
- const raw = {
7
- setHeader: jest.fn(),
8
- end: jest.fn(),
9
- };
10
-
11
- const res = new Response(raw);
12
-
13
- res.status(201).header("x-test", "ok").send("hello");
14
-
15
- expect(raw.setHeader).toHaveBeenCalledWith("x-test", "ok");
16
- expect(raw.end).toHaveBeenCalledWith("hello");
17
- });
18
-
19
- it("envoie du JSON", () => {
20
- const raw = {
21
- setHeader: jest.fn(),
22
- end: jest.fn(),
23
- };
24
-
25
- const res = new Response(raw);
26
-
27
- res.json({ a: 1 });
28
-
29
- expect(raw.setHeader).toHaveBeenCalledWith(
30
- "content-type",
31
- "application/json",
32
- );
33
- expect(raw.end).toHaveBeenCalledWith(JSON.stringify({ a: 1 }));
34
- });
35
- });
@@ -1,171 +0,0 @@
1
- import { Router } from "../router";
2
- import { describe, it, expect } from "@jest/globals";
3
-
4
- describe("Router.match", () => {
5
- it("match une route statique", () => {
6
- const router = new Router();
7
-
8
- router.register("GET", "/tasks", () => "ok");
9
-
10
- const result = router.match("GET", "/tasks");
11
-
12
- expect(result).not.toBeNull();
13
- expect(result?.handler()).toBe("ok");
14
- expect(result?.params).toEqual({});
15
- expect(result?.middlewares).toEqual([]);
16
- });
17
-
18
- it("match une route avec paramètre", () => {
19
- const router = new Router();
20
-
21
- router.register("GET", "/tasks/:id", () => "task");
22
-
23
- const result = router.match("GET", "/tasks/42");
24
-
25
- expect(result).not.toBeNull();
26
- expect(result?.handler()).toBe("task");
27
- expect(result?.params).toEqual({ id: "42" });
28
- expect(result?.middlewares).toEqual([]);
29
- });
30
-
31
- it("match une route avec wildcard", () => {
32
- const router = new Router();
33
-
34
- router.register("GET", "/files/*", () => "wild");
35
-
36
- const result = router.match("GET", "/files/any/path/here");
37
-
38
- expect(result).not.toBeNull();
39
- expect(result?.handler()).toBe("wild");
40
- expect(result?.params).toEqual({});
41
- expect(result?.middlewares).toEqual([]);
42
- });
43
-
44
- it("match un chemin complexe avec static, param et wildcard", () => {
45
- const router = new Router();
46
-
47
- router.register("GET", "/a/:b/*/c", () => "complex");
48
-
49
- const result = router.match("GET", "/a/hello/anything/here/c");
50
-
51
- expect(result).not.toBeNull();
52
- expect(result?.handler()).toBe("complex");
53
- expect(result?.params).toEqual({ b: "hello" });
54
- expect(result?.middlewares).toEqual([]);
55
- });
56
-
57
- it("ne match pas quand le chemin ne correspond pas", () => {
58
- const router = new Router();
59
-
60
- router.register("GET", "/tasks/:id", () => "ok");
61
-
62
- const result = router.match("GET", "/tasks");
63
-
64
- expect(result).toBeNull();
65
- });
66
-
67
- it("ne match pas quand le chemin est trop long", () => {
68
- const router = new Router();
69
-
70
- router.register("GET", "/tasks/:id", () => "ok");
71
-
72
- const result = router.match("GET", "/tasks/42/extra");
73
-
74
- expect(result).toBeNull();
75
- });
76
-
77
- it("ne match pas quand la méthode HTTP ne correspond pas", () => {
78
- const router = new Router();
79
-
80
- router.register("GET", "/tasks", () => "ok");
81
-
82
- const result = router.match("POST", "/tasks");
83
-
84
- expect(result).toBeNull();
85
- });
86
-
87
- it("match une route avec plusieurs paramètres", () => {
88
- const router = new Router();
89
-
90
- router.register("GET", "/users/:userId/tasks/:taskId", () => "multi");
91
-
92
- const result = router.match("GET", "/users/12/tasks/99");
93
-
94
- expect(result).not.toBeNull();
95
- expect(result?.handler()).toBe("multi");
96
- expect(result?.params).toEqual({
97
- userId: "12",
98
- taskId: "99",
99
- });
100
- expect(result?.middlewares).toEqual([]);
101
- });
102
-
103
- it("match une route complexe avec plusieurs paramètres et un wildcard", () => {
104
- const router = new Router();
105
-
106
- router.register("GET", "/users/:userId/*/tasks/:taskId", () => "mw");
107
-
108
- const result = router.match("GET", "/users/12/any/path/here/tasks/99");
109
-
110
- expect(result).not.toBeNull();
111
- expect(result?.handler()).toBe("mw");
112
- expect(result?.params).toEqual({
113
- userId: "12",
114
- taskId: "99",
115
- });
116
- expect(result?.middlewares).toEqual([]);
117
- });
118
-
119
- it("ne match pas un chemin complexe si la fin ne correspond pas", () => {
120
- const router = new Router();
121
-
122
- router.register("GET", "/users/:userId/*/tasks/:taskId", () => "mw");
123
-
124
- const result = router.match("GET", "/users/12/any/path/here/taskz/99");
125
-
126
- expect(result).toBeNull();
127
- });
128
-
129
- it("ne match pas si le paramètre final est manquant", () => {
130
- const router = new Router();
131
-
132
- router.register("GET", "/users/:userId/*/tasks/:taskId", () => "mw");
133
-
134
- const result = router.match("GET", "/users/12/any/path/here/tasks/");
135
-
136
- expect(result).toBeNull();
137
- });
138
-
139
- it("ne match pas si le paramètre du début est manquant", () => {
140
- const router = new Router();
141
-
142
- router.register("GET", "/users/:userId/*/tasks/:taskId", () => "mw");
143
-
144
- const result = router.match("GET", "/users//any/path/tasks/99");
145
-
146
- expect(result).toBeNull();
147
- });
148
-
149
- it("ne match pas si le wildcard est vide", () => {
150
- const router = new Router();
151
-
152
- router.register("GET", "/users/:userId/*/tasks/:taskId", () => "mw");
153
-
154
- const result = router.match("GET", "/users/12//tasks/99");
155
-
156
- expect(result).toBeNull();
157
- });
158
-
159
- it("match une route avec wildcard en fin de chemin", () => {
160
- const router = new Router();
161
-
162
- router.register("GET", "/files/*", () => "end");
163
-
164
- const result = router.match("GET", "/files/path/to/something");
165
-
166
- expect(result).not.toBeNull();
167
- expect(result?.handler()).toBe("end");
168
- expect(result?.params).toEqual({});
169
- expect(result?.middlewares).toEqual([]);
170
- });
171
- });
@@ -1,51 +0,0 @@
1
- // src/http/adapter-node.ts
2
-
3
- import { Request } from "./request";
4
- import { Response } from "./response";
5
- import { ErrorHandler } from "./errors";
6
- import { MiddlewarePipeline } from "./middleware";
7
- import { Router } from "./router";
8
- import { buildRequest } from "./buildRequest";
9
-
10
- export class NodeAdapter {
11
- constructor(
12
- private router: Router,
13
- private pipeline: MiddlewarePipeline,
14
- ) {}
15
-
16
- async handle(req: any, res: any) {
17
- try {
18
- // 1) Construire la Request SANS params
19
- const baseRequest = buildRequest(req);
20
-
21
- const response = new Response(res);
22
-
23
- // 2) Résoudre la route
24
- const match = this.router.match(baseRequest.method, baseRequest.path);
25
-
26
- if (!match) {
27
- response.status(404).json({ error: "Not Found" });
28
- return;
29
- }
30
-
31
- // 3) Construire la Request AVEC params
32
- const request = buildRequest(req, match.params);
33
-
34
- // 4) Middlewares par route
35
- for (const mw of match.middlewares ?? []) {
36
- if (res.writableEnded) return;
37
- await mw(request, response, async () => {});
38
- }
39
-
40
- // 5) Pipeline global
41
- await this.pipeline.run(request, response);
42
-
43
- // 6) Handler final
44
- if (!res.writableEnded) {
45
- await match.handler(request, response);
46
- }
47
- } catch (err) {
48
- ErrorHandler.handle(err, new Response(res));
49
- }
50
- }
51
- }
@@ -1,18 +0,0 @@
1
- import { Request } from "./request";
2
-
3
- export function buildRequest(
4
- raw: any,
5
- params: Record<string, string> = {},
6
- ): Request {
7
- const url = new URL(raw.url, `http://${raw.headers.host}`);
8
-
9
- return new Request({
10
- method: raw.method,
11
- path: url.pathname,
12
- headers: raw.headers,
13
- query: Object.fromEntries(url.searchParams.entries()),
14
- params,
15
- ip: raw.socket?.remoteAddress ?? null,
16
- raw,
17
- });
18
- }
@@ -1,32 +0,0 @@
1
- export function compilePath(path: string) {
2
- const segments = path.replace(/^\//, "").split("/");
3
- const compiled = [];
4
-
5
- for (const segment of segments) {
6
- // analyse ici
7
- if (segment !== "*" && !segment.startsWith(":")) {
8
- compiled.push({ type: "static", value: segment });
9
- continue;
10
- }
11
-
12
- if (segment.startsWith(":")) {
13
- compiled.push({
14
- type: "param",
15
- name: segment.slice(1),
16
- });
17
- continue;
18
- }
19
-
20
- if (segment === "*") {
21
- compiled.push({ type: "wildcard" });
22
- continue;
23
- }
24
-
25
- if (segment === "*") {
26
- compiled.push({ type: "wildcard" });
27
- continue;
28
- }
29
- }
30
-
31
- return compiled;
32
- }
@@ -1,37 +0,0 @@
1
- // src/http/error.ts
2
-
3
- export class HttpError extends Error {
4
- readonly status: number;
5
- readonly code: string;
6
- readonly details?: any;
7
-
8
- constructor(status: number, code: string, message: string, details?: any) {
9
- super(message);
10
- this.status = status;
11
- this.code = code;
12
- this.details = details;
13
- }
14
- }
15
-
16
- export class ErrorHandler {
17
- static handle(err: unknown, res: any) {
18
- if (err instanceof HttpError) {
19
- res.status(err.status).json({
20
- error: {
21
- code: err.code,
22
- message: err.message,
23
- details: err.details ?? null,
24
- },
25
- });
26
- return;
27
- }
28
-
29
- // Erreur inconnue → 500
30
- res.status(500).json({
31
- error: {
32
- code: "INTERNAL_ERROR",
33
- message: "An unexpected error occurred",
34
- },
35
- });
36
- }
37
- }
@@ -1,52 +0,0 @@
1
- // src/api/http/http-server.ts
2
-
3
- import http from "node:http";
4
- import { Router } from "./router";
5
-
6
- export class HttpServer {
7
- private server: http.Server | null = null;
8
-
9
- constructor(private router: Router) {}
10
-
11
- start(port: number) {
12
- this.server = http.createServer((req, res) => {
13
- const method = req.method || "GET";
14
- const url = req.url || "/";
15
-
16
- const match = this.router.match(method, url);
17
-
18
- if (!match) {
19
- res.statusCode = 404;
20
- res.end("Not found");
21
- return;
22
- }
23
-
24
- const result = match.handler({
25
- params: match.params,
26
- req,
27
- res,
28
- });
29
-
30
- if (!res.writableEnded) {
31
- res.end(result ?? "");
32
- }
33
- });
34
-
35
- this.server.listen(port, () => {
36
- console.log(`HTTP server running on port ${port}`);
37
- });
38
-
39
- // 🔥 Shutdown propre
40
- const shutdown = () => {
41
- console.log("Shutting down HTTP server gracefully...");
42
-
43
- this.server?.close(() => {
44
- console.log("HTTP server closed.");
45
- process.exit(0);
46
- });
47
- };
48
-
49
- process.on("SIGINT", shutdown);
50
- process.on("SIGTERM", shutdown);
51
- }
52
- }
File without changes
File without changes