@kurdel/runtime-node 0.1.0-beta.1

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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/lib/http/index.d.ts +2 -0
  4. package/lib/http/index.js +3 -0
  5. package/lib/http/index.js.map +1 -0
  6. package/lib/http/native-http-server-adapter.d.ts +29 -0
  7. package/lib/http/native-http-server-adapter.js +65 -0
  8. package/lib/http/native-http-server-adapter.js.map +1 -0
  9. package/lib/http/native-req-res-adapters.d.ts +27 -0
  10. package/lib/http/native-req-res-adapters.js +136 -0
  11. package/lib/http/native-req-res-adapters.js.map +1 -0
  12. package/lib/http/render-node-action-result.d.ts +7 -0
  13. package/lib/http/render-node-action-result.js +48 -0
  14. package/lib/http/render-node-action-result.js.map +1 -0
  15. package/lib/index.d.ts +2 -0
  16. package/lib/index.js +3 -0
  17. package/lib/index.js.map +1 -0
  18. package/lib/middlewares/index.d.ts +1 -0
  19. package/lib/middlewares/index.js +2 -0
  20. package/lib/middlewares/index.js.map +1 -0
  21. package/lib/middlewares/serve-static-middleware.d.ts +12 -0
  22. package/lib/middlewares/serve-static-middleware.js +50 -0
  23. package/lib/middlewares/serve-static-middleware.js.map +1 -0
  24. package/lib/modules/index.d.ts +2 -0
  25. package/lib/modules/index.js +3 -0
  26. package/lib/modules/index.js.map +1 -0
  27. package/lib/modules/node-platform-module.d.ts +7 -0
  28. package/lib/modules/node-platform-module.js +26 -0
  29. package/lib/modules/node-platform-module.js.map +1 -0
  30. package/lib/modules/static-files-module.d.ts +21 -0
  31. package/lib/modules/static-files-module.js +24 -0
  32. package/lib/modules/static-files-module.js.map +1 -0
  33. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Andrii Sorokin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @kurdel/runtime-node
2
+
3
+ Native **Node.js HTTP adapter** for Kurdel runtime.
4
+ Implements the `ServerAdapter` interface using the built-in `http` module.
5
+
6
+ ---
7
+
8
+ ## 📦 Installation
9
+
10
+ ```bash
11
+ npm install @kurdel/runtime-node
12
+ ```
13
+
14
+ ---
15
+
16
+ ## 🧠 Responsibilities
17
+
18
+ * Create and manage a native Node HTTP server
19
+ * Adapt Node’s `IncomingMessage` / `ServerResponse` to Kurdel `HttpRequest` / `HttpResponse`
20
+ * Dispatch incoming requests to the runtime handler
21
+
22
+ ---
23
+
24
+ ## 🔧 Example
25
+
26
+ ```ts
27
+ import { createNodeApplication } from '@kurdel/facade';
28
+ const app = await createNodeApplication({ modules: [] });
29
+ app.listen(3000);
30
+ ```
31
+
32
+ ---
33
+
34
+ ## 📄 License
35
+
36
+ MIT © Andrii Sorokin
@@ -0,0 +1,2 @@
1
+ export * from './native-http-server-adapter.js';
2
+ export * from './native-req-res-adapters.js';
@@ -0,0 +1,3 @@
1
+ export * from './native-http-server-adapter.js';
2
+ export * from './native-req-res-adapters.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Server } from 'node:http';
2
+ import type { HttpRequest, HttpResponse } from '@kurdel/common';
3
+ import type { ServerAdapter } from '@kurdel/core/http';
4
+ /**
5
+ * Node.js implementation of ServerAdapter.
6
+ *
7
+ * Responsibilities:
8
+ * - Listen for native HTTP requests
9
+ * - Adapt Node's IncomingMessage / ServerResponse into
10
+ * framework-agnostic HttpRequest / HttpResponse
11
+ * - Delegate execution to the runtime handler
12
+ */
13
+ export declare class NativeHttpServerAdapter implements ServerAdapter<HttpRequest, HttpResponse> {
14
+ private readonly server;
15
+ private handler?;
16
+ constructor();
17
+ /** Core dispatch: adapt and delegate to the framework handler. */
18
+ private dispatch;
19
+ /** Minimal fallback when handler throws unexpectedly. */
20
+ private handleDispatchError;
21
+ /** Register the runtime handler invoked for every request. */
22
+ on(cb: (req: HttpRequest, res: HttpResponse) => void | Promise<void>): void;
23
+ /** Start listening for HTTP connections. */
24
+ listen(port: number, hostOrCb?: string | (() => void), cb?: () => void): void;
25
+ /** Gracefully close the underlying HTTP server. */
26
+ close(): Promise<void>;
27
+ /** Expose the raw Node.js server (used by the runtime). */
28
+ raw<T = Server>(): T;
29
+ }
@@ -0,0 +1,65 @@
1
+ import { createServer } from 'node:http';
2
+ import { adaptNodeRequest, adaptNodeResponse } from '../http/native-req-res-adapters.js';
3
+ /**
4
+ * Node.js implementation of ServerAdapter.
5
+ *
6
+ * Responsibilities:
7
+ * - Listen for native HTTP requests
8
+ * - Adapt Node's IncomingMessage / ServerResponse into
9
+ * framework-agnostic HttpRequest / HttpResponse
10
+ * - Delegate execution to the runtime handler
11
+ */
12
+ export class NativeHttpServerAdapter {
13
+ constructor() {
14
+ // Delegate each incoming request to the unified dispatch method
15
+ this.server = createServer((req, res) => this.dispatch(req, res));
16
+ }
17
+ /** Core dispatch: adapt and delegate to the framework handler. */
18
+ async dispatch(req, res) {
19
+ if (!this.handler) {
20
+ res.statusCode = 404;
21
+ res.end('Not Found');
22
+ return;
23
+ }
24
+ try {
25
+ const request = await adaptNodeRequest(req);
26
+ const response = adaptNodeResponse(res);
27
+ await Promise.resolve(this.handler(request, response));
28
+ }
29
+ catch (err) {
30
+ this.handleDispatchError(res, err);
31
+ }
32
+ }
33
+ /** Minimal fallback when handler throws unexpectedly. */
34
+ handleDispatchError(res, err) {
35
+ console.error('Unhandled request error:', err);
36
+ if (res.headersSent)
37
+ return;
38
+ const status = err?.status ?? 500;
39
+ const message = err?.message ?? 'Internal Server Error';
40
+ res.statusCode = status;
41
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
42
+ res.end(`${status}: ${message}`);
43
+ }
44
+ /** Register the runtime handler invoked for every request. */
45
+ on(cb) {
46
+ this.handler = cb;
47
+ }
48
+ /** Start listening for HTTP connections. */
49
+ listen(port, hostOrCb, cb) {
50
+ const done = (typeof hostOrCb === 'function' ? hostOrCb : cb) ?? (() => { });
51
+ if (typeof hostOrCb === 'string')
52
+ this.server.listen(port, hostOrCb, done);
53
+ else
54
+ this.server.listen(port, done);
55
+ }
56
+ /** Gracefully close the underlying HTTP server. */
57
+ async close() {
58
+ await new Promise((resolve, reject) => this.server.close(err => (err ? reject(err) : resolve())));
59
+ }
60
+ /** Expose the raw Node.js server (used by the runtime). */
61
+ raw() {
62
+ return this.server;
63
+ }
64
+ }
65
+ //# sourceMappingURL=native-http-server-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-http-server-adapter.js","sourceRoot":"","sources":["../../src/http/native-http-server-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAE1F;;;;;;;;GAQG;AACH,MAAM,OAAO,uBAAuB;IAIlC;QACE,gEAAgE;QAChE,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,kEAAkE;IAC1D,KAAK,CAAC,QAAQ,CAAC,GAAoB,EAAE,GAAmB;QAC9D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAExC,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,yDAAyD;IACjD,mBAAmB,CAAC,GAAmB,EAAE,GAAY;QAC3D,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;QAE/C,IAAI,GAAG,CAAC,WAAW;YAAE,OAAO;QAE5B,MAAM,MAAM,GAAI,GAAW,EAAE,MAAM,IAAI,GAAG,CAAC;QAC3C,MAAM,OAAO,GAAI,GAAW,EAAE,OAAO,IAAI,uBAAuB,CAAC;QAEjE,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;QACxB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,8DAA8D;IAC9D,EAAE,CAAC,EAAiE;QAClE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,4CAA4C;IAC5C,MAAM,CAAC,IAAY,EAAE,QAAgC,EAAE,EAAe;QACpE,MAAM,IAAI,GAAG,CAAC,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5E,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;;YACtE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,mDAAmD;IACnD,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,GAAG;QACD,OAAO,IAAI,CAAC,MAAsB,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { HttpRequest, HttpResponseWithHeaders } from '@kurdel/common';
3
+ /**
4
+ * Adapts a native Node.js `IncomingMessage` into a platform-neutral `HttpRequest`.
5
+ *
6
+ * Responsibilities:
7
+ * - Read the request body (as text)
8
+ * - Parse JSON if `Content-Type` is `application/json`
9
+ * - Normalize headers into a consistent object
10
+ * - Extract query parameters from URL
11
+ *
12
+ * @param req - The native Node.js HTTP request object
13
+ * @returns A platform-agnostic {@link HttpRequest} used by Kurdel runtime
14
+ */
15
+ export declare function adaptNodeRequest(req: IncomingMessage): Promise<HttpRequest>;
16
+ /**
17
+ * Adapts a native Node.js `ServerResponse` into a framework-agnostic `HttpResponse`.
18
+ *
19
+ * Responsibilities:
20
+ * - Provide a unified API (`status()`, `send()`, `json()`, etc.)
21
+ * - Automatically manage headers and content types
22
+ * - Support streaming and manual writes (`write()` / `end()`)
23
+ *
24
+ * @param res - The native Node.js ServerResponse instance
25
+ * @returns Wrapped {@link HttpResponseWithHeaders} compatible with Kurdel runtime
26
+ */
27
+ export declare function adaptNodeResponse(res: ServerResponse): HttpResponseWithHeaders;
@@ -0,0 +1,136 @@
1
+ import { DEFAULT_INTERNAL_BASE } from '@kurdel/common';
2
+ /**
3
+ * Adapts a native Node.js `IncomingMessage` into a platform-neutral `HttpRequest`.
4
+ *
5
+ * Responsibilities:
6
+ * - Read the request body (as text)
7
+ * - Parse JSON if `Content-Type` is `application/json`
8
+ * - Normalize headers into a consistent object
9
+ * - Extract query parameters from URL
10
+ *
11
+ * @param req - The native Node.js HTTP request object
12
+ * @returns A platform-agnostic {@link HttpRequest} used by Kurdel runtime
13
+ */
14
+ export async function adaptNodeRequest(req) {
15
+ const chunks = [];
16
+ // Collect request body (streamed)
17
+ if (Symbol.asyncIterator in req) {
18
+ for await (const chunk of req) {
19
+ chunks.push(chunk);
20
+ }
21
+ }
22
+ const rawBody = Buffer.concat(chunks).toString('utf8').trim();
23
+ // Normalize headers
24
+ const nodeHeaders = req.headers ?? {};
25
+ const headers = {};
26
+ for (const [key, value] of Object.entries(nodeHeaders)) {
27
+ if (value !== undefined)
28
+ headers[key] = value;
29
+ }
30
+ // Parse JSON body if applicable
31
+ const contentType = (req.headers?.['content-type'] ?? '').toString();
32
+ let parsedBody;
33
+ if (contentType.includes('application/json')) {
34
+ try {
35
+ parsedBody = rawBody ? JSON.parse(rawBody) : undefined;
36
+ }
37
+ catch {
38
+ parsedBody = undefined;
39
+ }
40
+ }
41
+ // Build absolute URL using default internal base (e.g., http://internal.local)
42
+ const url = new URL(req.url ?? '/', DEFAULT_INTERNAL_BASE);
43
+ // Extract query parameters
44
+ const query = {};
45
+ url.searchParams.forEach((value, key) => {
46
+ if (key in query) {
47
+ const prev = query[key];
48
+ query[key] = Array.isArray(prev) ? [...prev, value] : [prev, value];
49
+ }
50
+ else {
51
+ query[key] = value;
52
+ }
53
+ });
54
+ // Return normalized HttpRequest
55
+ return {
56
+ method: req.method ?? 'GET',
57
+ url: req.url ?? '/',
58
+ headers,
59
+ body: parsedBody,
60
+ query,
61
+ params: {},
62
+ };
63
+ }
64
+ /**
65
+ * Adapts a native Node.js `ServerResponse` into a framework-agnostic `HttpResponse`.
66
+ *
67
+ * Responsibilities:
68
+ * - Provide a unified API (`status()`, `send()`, `json()`, etc.)
69
+ * - Automatically manage headers and content types
70
+ * - Support streaming and manual writes (`write()` / `end()`)
71
+ *
72
+ * @param res - The native Node.js ServerResponse instance
73
+ * @returns Wrapped {@link HttpResponseWithHeaders} compatible with Kurdel runtime
74
+ */
75
+ export function adaptNodeResponse(res) {
76
+ const response = {
77
+ get sent() {
78
+ return res.writableEnded || res.destroyed;
79
+ },
80
+ raw: res,
81
+ status(code) {
82
+ res.statusCode = code;
83
+ return this;
84
+ },
85
+ send(body) {
86
+ if (body == null) {
87
+ res.end();
88
+ return this;
89
+ }
90
+ const content = typeof body === 'object' ? JSON.stringify(body) : String(body);
91
+ if (!res.getHeader('Content-Type')) {
92
+ res.setHeader('Content-Type', typeof body === 'object' ? 'application/json; charset=utf-8' : 'text/plain; charset=utf-8');
93
+ }
94
+ res.end(content);
95
+ return this;
96
+ },
97
+ json(body) {
98
+ res.statusCode = res.statusCode || 200;
99
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
100
+ res.end(JSON.stringify(body));
101
+ return this;
102
+ },
103
+ redirect(code, location) {
104
+ res.statusCode = code;
105
+ res.setHeader('Location', location);
106
+ res.end();
107
+ return this;
108
+ },
109
+ setHeader(name, value) {
110
+ res.setHeader(name, value);
111
+ return this;
112
+ },
113
+ getHeader(name) {
114
+ const value = res.getHeader(name);
115
+ return typeof value === 'string'
116
+ ? value
117
+ : Array.isArray(value)
118
+ ? value.join(', ')
119
+ : undefined;
120
+ },
121
+ type(mime) {
122
+ this.setHeader('Content-Type', mime);
123
+ return this;
124
+ },
125
+ write(chunk) {
126
+ res.write(chunk);
127
+ return this;
128
+ },
129
+ end(chunk) {
130
+ res.end(chunk);
131
+ return this;
132
+ },
133
+ };
134
+ return response;
135
+ }
136
+ //# sourceMappingURL=native-req-res-adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-req-res-adapters.js","sourceRoot":"","sources":["../../src/http/native-req-res-adapters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HttpResponse } from '@kurdel/common';
2
+ import type { ActionResult } from '@kurdel/core/http';
3
+ /**
4
+ * Node-specific renderer for ActionResult.
5
+ * Handles JSON, text, HTML, redirects, empties and stream bodies.
6
+ */
7
+ export declare function renderNodeActionResult(res: HttpResponse, r: ActionResult): void;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Node-specific renderer for ActionResult.
3
+ * Handles JSON, text, HTML, redirects, empties and stream bodies.
4
+ */
5
+ export function renderNodeActionResult(res, r) {
6
+ switch (r.kind) {
7
+ case 'json':
8
+ res.status(r.status).json(r.body);
9
+ break;
10
+ case 'text':
11
+ res.status(r.status).send(r.body);
12
+ break;
13
+ case 'html': {
14
+ const withHeaders = res;
15
+ withHeaders.setHeader?.('Content-Type', r.contentType ?? 'text/html; charset=utf-8');
16
+ res.status(r.status).send(r.body);
17
+ break;
18
+ }
19
+ case 'redirect':
20
+ res.redirect(r.status, r.location);
21
+ break;
22
+ case 'empty':
23
+ res.status(r.status).send('');
24
+ break;
25
+ case 'stream': {
26
+ const s = r;
27
+ const withHeaders = res;
28
+ const nodeRes = res.raw;
29
+ if (s.contentType)
30
+ withHeaders.setHeader?.('Content-Type', s.contentType);
31
+ if (s.contentLength)
32
+ withHeaders.setHeader?.('Content-Length', String(s.contentLength));
33
+ res.status(s.status);
34
+ const stream = s.body;
35
+ if (stream && typeof stream.pipe === 'function' && typeof nodeRes.write === 'function') {
36
+ // ✅ Pipe directly into native Node response
37
+ stream.pipe(nodeRes);
38
+ }
39
+ else {
40
+ res.status(500).send('Invalid stream body');
41
+ }
42
+ break;
43
+ }
44
+ default:
45
+ res.status(500).send('Unsupported response type');
46
+ }
47
+ }
48
+ //# sourceMappingURL=render-node-action-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-node-action-result.js","sourceRoot":"","sources":["../../src/http/render-node-action-result.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAiB,EAAE,CAAe;IACvE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,MAAM;YACT,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QAER,KAAK,MAAM;YACT,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QAER,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,WAAW,GAAG,GAA8B,CAAC;YACnD,WAAW,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,WAAW,IAAI,0BAA0B,CAAC,CAAC;YACrF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM;QACR,CAAC;QAED,KAAK,UAAU;YACb,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM;QAER,KAAK,OAAO;YACV,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9B,MAAM;QAER,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,CAAC,GAAG,CAAwC,CAAC;YACnD,MAAM,WAAW,GAAG,GAA8B,CAAC;YACnD,MAAM,OAAO,GAAG,GAAG,CAAC,GAAgC,CAAC;YAErD,IAAI,CAAC,CAAC,WAAW;gBAAE,WAAW,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;YAC1E,IAAI,CAAC,CAAC,aAAa;gBAAE,WAAW,CAAC,SAAS,EAAE,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAExF,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAErB,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;YAEtB,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACvF,4CAA4C;gBAC5C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAC9C,CAAC;YACD,MAAM;QACR,CAAC;QAED;YACE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * as http from './http/index.js';
2
+ export * as modules from './modules/index.js';
package/lib/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * as http from './http/index.js';
2
+ export * as modules from './modules/index.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { Middleware } from '@kurdel/core/http';
2
+ /**
3
+ * @kurdel
4
+ * Node.js static file middleware.
5
+ *
6
+ * Responsibilities:
7
+ * - Serve static files from a configured directory
8
+ * - Prevent directory traversal
9
+ * - Set correct MIME type
10
+ * - Fallback to `next()` if file not found
11
+ */
12
+ export declare function serveStaticMiddleware(rootDir: string): Middleware<unknown, NodeJS.ReadableStream>;
@@ -0,0 +1,50 @@
1
+ import { createReadStream, promises as fs } from 'node:fs';
2
+ import { extname, join, normalize } from 'node:path';
3
+ import mime from 'mime-types';
4
+ /**
5
+ * @kurdel
6
+ * Node.js static file middleware.
7
+ *
8
+ * Responsibilities:
9
+ * - Serve static files from a configured directory
10
+ * - Prevent directory traversal
11
+ * - Set correct MIME type
12
+ * - Fallback to `next()` if file not found
13
+ */
14
+ export function serveStaticMiddleware(rootDir) {
15
+ return async (ctx, next) => {
16
+ try {
17
+ // Normalize path to prevent traversal (`..`)
18
+ const urlPath = decodeURIComponent(ctx.url.pathname ?? '/');
19
+ const safePath = normalize(join(rootDir, urlPath)).replace(/\\/g, '/');
20
+ if (!safePath.startsWith(rootDir.replace(/\\/g, '/'))) {
21
+ // Security guard — attempt to escape root directory
22
+ return next();
23
+ }
24
+ let filePath = safePath;
25
+ // If it's a directory, try to serve index.html
26
+ const stat = await fs.stat(filePath).catch(() => null);
27
+ if (stat?.isDirectory()) {
28
+ filePath = join(filePath, 'index.html');
29
+ }
30
+ const finalStat = await fs.stat(filePath).catch(() => null);
31
+ if (!finalStat?.isFile()) {
32
+ return next();
33
+ }
34
+ const extension = extname(filePath);
35
+ const mimeType = mime.lookup(extension) || 'application/octet-stream';
36
+ const stream = createReadStream(filePath);
37
+ return {
38
+ kind: 'stream',
39
+ status: 200,
40
+ body: stream,
41
+ contentType: mimeType,
42
+ contentLength: finalStat.size,
43
+ };
44
+ }
45
+ catch {
46
+ return next();
47
+ }
48
+ };
49
+ }
50
+ //# sourceMappingURL=serve-static-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-static-middleware.js","sourceRoot":"","sources":["../../src/middlewares/serve-static-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,IAAI,MAAM,YAAY,CAAC;AAG9B;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,KAAK,EAAE,GAAgB,EAAE,IAAI,EAAuD,EAAE;QAC3F,IAAI,CAAC;YACH,6CAA6C;YAC7C,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAEvE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;gBACtD,oDAAoD;gBACpD,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,IAAI,QAAQ,GAAG,QAAQ,CAAC;YAExB,+CAA+C;YAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACvD,IAAI,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;gBACzB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YAED,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,0BAA0B,CAAC;YAEtE,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAE1C,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,QAAQ;gBACrB,aAAa,EAAE,SAAS,CAAC,IAAI;aAC9B,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './node-platform-module.js';
2
+ export * from './static-files-module.js';
@@ -0,0 +1,3 @@
1
+ export * from './node-platform-module.js';
2
+ export * from './static-files-module.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { AppModule } from '@kurdel/core/app';
2
+ /**
3
+ * Provides Node.js platform-level services:
4
+ * - native ServerAdapter
5
+ * - platform-aware ResponseRenderer
6
+ */
7
+ export declare const NodePlatformModule: AppModule;
@@ -0,0 +1,26 @@
1
+ import { ModulePriority } from '@kurdel/core/app';
2
+ import { TOKENS } from '@kurdel/core/tokens';
3
+ import { RuntimeResponseRenderer } from '@kurdel/runtime/http';
4
+ import { renderNodeActionResult } from '../http/render-node-action-result.js';
5
+ import { NativeHttpServerAdapter } from '../http/native-http-server-adapter.js';
6
+ /**
7
+ * Provides Node.js platform-level services:
8
+ * - native ServerAdapter
9
+ * - platform-aware ResponseRenderer
10
+ */
11
+ export const NodePlatformModule = {
12
+ priority: ModulePriority.Platform,
13
+ providers: [
14
+ {
15
+ provide: TOKENS.ServerAdapter,
16
+ useFactory: () => new NativeHttpServerAdapter(),
17
+ singleton: true,
18
+ },
19
+ {
20
+ provide: TOKENS.ResponseRenderer,
21
+ useFactory: () => new RuntimeResponseRenderer(renderNodeActionResult),
22
+ singleton: true,
23
+ },
24
+ ],
25
+ };
26
+ //# sourceMappingURL=node-platform-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-platform-module.js","sourceRoot":"","sources":["../../src/modules/node-platform-module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAc;IAC3C,QAAQ,EAAE,cAAc,CAAC,QAAQ;IACjC,SAAS,EAAE;QACT;YACE,OAAO,EAAE,MAAM,CAAC,aAAa;YAC7B,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,EAAE;YAC/C,SAAS,EAAE,IAAI;SAChB;QACD;YACE,OAAO,EAAE,MAAM,CAAC,gBAAgB;YAChC,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,uBAAuB,CAAC,sBAAsB,CAAC;YACrE,SAAS,EAAE,IAAI;SAChB;KACF;CACF,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { AppConfig } from '@kurdel/core/app';
2
+ import type { HttpModule } from '@kurdel/core/http';
3
+ /**
4
+ * StaticFilesModule
5
+ *
6
+ * HTTP module that provides a global middleware
7
+ * for serving static files from a specified directory.
8
+ *
9
+ * @example:
10
+ * ```ts
11
+ * export const AppModule: HttpModule = {
12
+ * imports: [StaticFilesModule.forRoot('public')],
13
+ * };
14
+ * ```
15
+ */
16
+ export declare class StaticFilesModule implements HttpModule<AppConfig, NodeJS.ReadableStream> {
17
+ private readonly baseDir;
18
+ readonly middlewares: import("@kurdel/core/http").Middleware<unknown, NodeJS.ReadableStream>[];
19
+ constructor(baseDir: string);
20
+ static forRoot(baseDir: string): StaticFilesModule;
21
+ }
@@ -0,0 +1,24 @@
1
+ import { serveStaticMiddleware } from '../middlewares/serve-static-middleware.js';
2
+ /**
3
+ * StaticFilesModule
4
+ *
5
+ * HTTP module that provides a global middleware
6
+ * for serving static files from a specified directory.
7
+ *
8
+ * @example:
9
+ * ```ts
10
+ * export const AppModule: HttpModule = {
11
+ * imports: [StaticFilesModule.forRoot('public')],
12
+ * };
13
+ * ```
14
+ */
15
+ export class StaticFilesModule {
16
+ constructor(baseDir) {
17
+ this.baseDir = baseDir;
18
+ this.middlewares = [serveStaticMiddleware(baseDir)];
19
+ }
20
+ static forRoot(baseDir) {
21
+ return new StaticFilesModule(baseDir);
22
+ }
23
+ }
24
+ //# sourceMappingURL=static-files-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-files-module.js","sourceRoot":"","sources":["../../src/modules/static-files-module.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAEnF;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,iBAAiB;IAG5B,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QAC1C,IAAI,CAAC,WAAW,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,OAAe;QAC5B,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@kurdel/runtime-node",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Node.js HTTP runtime adapter for Kurdel",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./lib/index.js",
8
+ "./http": "./lib/http/index.js",
9
+ "./modules": "./lib/modules/index.js"
10
+ },
11
+ "main": "./lib/index.js",
12
+ "types": "./lib/index.d.ts",
13
+ "files": [
14
+ "lib"
15
+ ],
16
+ "scripts": {
17
+ "prepack": "npm run build",
18
+ "test": "vitest run",
19
+ "test:ui": "vitest",
20
+ "test:watch": "vitest --watch",
21
+ "coverage": "vitest run --coverage",
22
+ "clean": "rimraf lib ../../.cache/tsconfig.runtime-node.build.tsbuildinfo",
23
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
24
+ "build:force": "npm run clean && tsc -p tsconfig.build.json --force && tsc-alias -p tsconfig.build.json"
25
+ },
26
+ "keywords": [
27
+ "kurdel",
28
+ "node",
29
+ "http",
30
+ "adapter",
31
+ "framework"
32
+ ],
33
+ "author": "Andrii Sorokin",
34
+ "license": "MIT",
35
+ "engines": {
36
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/ignorantic/kurdel.git",
41
+ "directory": "packages/runtime-node"
42
+ },
43
+ "homepage": "https://github.com/ignorantic/kurdel/tree/main/packages/runtime-node#readme",
44
+ "bugs": {
45
+ "url": "https://github.com/ignorantic/kurdel/issues"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "tag": "beta"
50
+ },
51
+ "devDependencies": {
52
+ "@types/mime-types": "^3.0.1",
53
+ "@types/node": "^20.9.0",
54
+ "@types/supertest": "^6.0.3",
55
+ "@vitest/coverage-v8": "^3.2.4",
56
+ "rimraf": "^6.0.1",
57
+ "supertest": "^7.1.4",
58
+ "tsc-alias": "^1.8.16"
59
+ },
60
+ "dependencies": {
61
+ "@kurdel/common": "0.1.0-beta.1",
62
+ "@kurdel/core": "0.1.0-beta.1",
63
+ "@kurdel/runtime": "0.1.0-beta.1"
64
+ }
65
+ }