corecdtl 0.1.7 → 0.1.9

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.
@@ -60,5 +60,5 @@ exports.contentParserTable = {
60
60
  "application/json": JSON.parse,
61
61
  "application/x-www-form-urlencoded": formParse,
62
62
  "multipart/form-data": multipartParser,
63
- "text/plain": (b) => decoder.decode
63
+ "text/plain": (b) => decoder.decode(b)
64
64
  };
@@ -42,7 +42,7 @@ class ApiContext extends HttpContext_1.default {
42
42
  return;
43
43
  // --- NOT FOUND ---
44
44
  case http_1.Http.RetFlagBits.FLAG_NOT_FOUND:
45
- if (this.enableCors) {
45
+ if (this.isEnableCors) {
46
46
  socket.write(this.errorRespMap.RESP_204);
47
47
  }
48
48
  else {
@@ -2,7 +2,7 @@ import { Http } from "../../http";
2
2
  import { type IHttpCore, type ICPool } from "../../hypernode";
3
3
  import net from "net";
4
4
  import { createAccumulators } from "../factory/accumulator";
5
- declare abstract class HttpContext {
5
+ declare abstract class HttpContext implements Http.HttpContext {
6
6
  protected MODE: "web" | "api";
7
7
  protected abstract contentDecoding: Http.ContentDecoding;
8
8
  protected abstract contentEncoding: Http.ContentEncoding;
@@ -15,7 +15,7 @@ declare abstract class HttpContext {
15
15
  protected accumulators: ReturnType<typeof createAccumulators>;
16
16
  protected abstract parseInitial: Http.ParseInitialFn;
17
17
  protected state: Http.ServerState;
18
- protected enableCors: boolean;
18
+ protected isEnableCors: boolean;
19
19
  protected httpCore: IHttpCore;
20
20
  protected setHttpCore(mode: "web" | "api"): void;
21
21
  private bootstrapPoolChunkProgressionFn?;
@@ -25,7 +25,7 @@ declare abstract class HttpContext {
25
25
  protected initRuntime(): void;
26
26
  protected registerRouters(mainRoute: Http.Route): void;
27
27
  private buildRoute;
28
- enabledCors(cfg: Http.CorsConfig): void;
28
+ enableCors(cfg: Http.CorsConfig): this;
29
29
  setTimeout(timeout: number): void;
30
30
  setRequestQuerySize(requestQuerySize: number): void;
31
31
  setMaxHeaderNameSize(maxHeaderNameSize: number): void;
@@ -24,7 +24,7 @@ class HttpContext {
24
24
  RESP_414: Buffer.from("HTTP/1.1 414 Request-URI Too Large\r\nContent-Length: 0\r\n\r\n"),
25
25
  RESP_204: Buffer.from("HTTP/1.1 204 No Content\r\n\r\n")
26
26
  };
27
- this.enableCors = false;
27
+ this.isEnableCors = false;
28
28
  this.state = {
29
29
  corsHeaders: "",
30
30
  maxHeaderSize: opts?.maxHeaderSize || 10 * 1024,
@@ -157,7 +157,7 @@ class HttpContext {
157
157
  throw new Error("Building Route Tree");
158
158
  this.routePipes = routePipes;
159
159
  }
160
- enabledCors(cfg) {
160
+ enableCors(cfg) {
161
161
  function toHeaderValue(v) {
162
162
  if (!v)
163
163
  return undefined;
@@ -186,7 +186,8 @@ class HttpContext {
186
186
  this.errorRespMap.RESP_204 = Buffer.from("HTTP/1.1 404 Not Found\r\n" +
187
187
  this.state.corsHeaders + "\r\n" +
188
188
  "Content-Length: 0\r\n\r\n");
189
- this.enableCors = true;
189
+ this.isEnableCors = true;
190
+ return this;
190
191
  }
191
192
  setTimeout(timeout) {
192
193
  timeout > 0 ? this.state.timeout = timeout : null;
@@ -97,7 +97,7 @@ class WebContext extends HttpContext_1.default {
97
97
  return;
98
98
  // --- NOT FOUND ---
99
99
  case http_1.Http.RetFlagBits.FLAG_NOT_FOUND:
100
- if (this.enableCors) {
100
+ if (this.isEnableCors) {
101
101
  socket.write(this.errorRespMap.RESP_204);
102
102
  }
103
103
  else {
@@ -197,7 +197,7 @@ class WebContext extends HttpContext_1.default {
197
197
  _data = fs_1.default.readFileSync(this.spaRootPath);
198
198
  }
199
199
  catch (error) {
200
- console.error(error);
200
+ console.error("SPA file not found:", this.spaRootPath, error);
201
201
  return;
202
202
  }
203
203
  const __resp = Buffer.from("HTTP/1.1 200 OK\r\n" +
@@ -279,27 +279,34 @@ class WebContext extends HttpContext_1.default {
279
279
  }
280
280
  setAllAssets() {
281
281
  const walk = (dir, baseUrl) => {
282
- const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
283
- for (const entry of entries) {
284
- const fullPath = path_1.default.join(dir, entry.name);
285
- const urlPath = path_1.default.posix.join(baseUrl, entry.name);
286
- if (entry.isDirectory()) {
287
- walk(fullPath, urlPath);
288
- continue;
282
+ try {
283
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
284
+ for (const entry of entries) {
285
+ const fullPath = path_1.default.join(dir, entry.name);
286
+ const urlPath = path_1.default.posix.join(baseUrl, entry.name);
287
+ if (entry.isDirectory()) {
288
+ walk(fullPath, urlPath);
289
+ continue;
290
+ }
291
+ if (!entry.isFile())
292
+ continue;
293
+ const asset = this.loadAsset(urlPath);
294
+ if (!asset)
295
+ continue;
296
+ this.assetCache.set(urlPath, asset);
289
297
  }
290
- if (!entry.isFile())
291
- continue;
292
- const asset = this.loadAsset(urlPath);
293
- if (!asset)
294
- continue;
295
- this.assetCache.set(urlPath, asset);
298
+ }
299
+ catch (error) {
300
+ console.log("Asset load failed", dir, error);
301
+ return;
296
302
  }
297
303
  };
298
304
  walk(this.publicRoutePathName, "");
299
305
  }
300
306
  loadAsset(assetPath) {
307
+ let fullPath = "";
301
308
  try {
302
- const fullPath = path_1.default.join(this.publicRoutePathName, assetPath);
309
+ fullPath = path_1.default.join(this.publicRoutePathName, assetPath);
303
310
  const body = fs_1.default.readFileSync(fullPath);
304
311
  const size = body.length;
305
312
  const ext = path_1.default.extname(assetPath).toLowerCase();
@@ -316,7 +323,8 @@ class WebContext extends HttpContext_1.default {
316
323
  const payload = Buffer.concat([headers, body]);
317
324
  return { headers, body, size, payload };
318
325
  }
319
- catch {
326
+ catch (err) {
327
+ console.error("Asset load failed:", fullPath, err);
320
328
  return undefined;
321
329
  }
322
330
  }
@@ -1,31 +1,112 @@
1
- import { IHttpResponseBase } from "./HttpResponseBase";
1
+ import { Http } from "../../http";
2
2
  /**
3
- * @class PipeResponseBase
4
- * @description The base Response class used by Http.
5
- * This class manages the HTTP response status code, headers, and body.
6
- * Developers can inherit this class and override methods (e.g., `json`, `getResp`) to create custom response types.
3
+ * Base HTTP response implementation used internally by the server.
4
+ *
5
+ * Responsible for:
6
+ * - managing status code
7
+ * - storing headers
8
+ * - writing body
9
+ * - optional compression
10
+ * - serializing everything into a raw HTTP Buffer
11
+ *
12
+ * This class is optimized for performance and object pooling.
13
+ *
14
+ * You may extend this class to implement custom helpers
15
+ * (e.g. html(), stream(), file(), etc.).
7
16
  */
8
- export declare class PipeResponseBase implements IHttpResponseBase {
17
+ export declare class PipeResponseBase implements Http.IHttpResponseBase {
18
+ /**
19
+ * Raw response body stored as UTF-8 string.
20
+ */
9
21
  protected body: string;
22
+ /**
23
+ * HTTP status code.
24
+ * @default 200
25
+ */
10
26
  protected status: number;
27
+ /**
28
+ * Response headers map.
29
+ * Uses Object.create(null) for maximum performance and safety.
30
+ */
11
31
  protected headers: Record<string, string>;
32
+ /**
33
+ * Marks whether response has been finalized (send/json/redirect called).
34
+ */
12
35
  protected finishedFlag: boolean;
36
+ /**
37
+ * Compression function lookup table.
38
+ * Example: { gzip: fn, br: fn }
39
+ */
13
40
  protected contentEncodingTable: Record<string, Function>;
41
+ /**
42
+ * Selected compression type.
43
+ */
14
44
  protected compression: "gzip" | "br" | "deflate" | null;
45
+ /**
46
+ * Object pool identifier.
47
+ */
15
48
  protected objId: number;
49
+ /**
50
+ * Reference to response object pool.
51
+ */
16
52
  protected cPool: any;
17
53
  constructor();
54
+ /**
55
+ * Attaches this response to an object pool.
56
+ */
18
57
  setCPool(cPool: any, objId: number): void;
58
+ /**
59
+ * Resets state and returns object back to the pool.
60
+ */
19
61
  freeCPool(): void;
62
+ /** Returns current HTTP status code. */
20
63
  getStatus(): number;
64
+ /** Returns response headers object. */
21
65
  getHeaders(): Record<string, string>;
66
+ /** Returns response body as string. */
22
67
  getBody(): string;
68
+ /**
69
+ * Sets HTTP status code.
70
+ */
23
71
  setStatus(code: number): this;
72
+ /**
73
+ * Sets a single response header.
74
+ */
24
75
  setHeader(key: string, value: string): this;
76
+ /**
77
+ * Merges multiple headers.
78
+ */
25
79
  setHeaders(obj: Record<string, string>): this;
80
+ /**
81
+ * Sends plain text payload.
82
+ * Marks response as finished.
83
+ */
26
84
  send(payload: string): void;
85
+ /**
86
+ * Sends JSON response.
87
+ * Automatically sets Content-Type: application/json.
88
+ */
27
89
  json(obj: unknown): void;
90
+ /**
91
+ * Redirects client to another URL.
92
+ * @default code 302
93
+ */
28
94
  redirect(url: string, code?: number): void;
95
+ /**
96
+ * Enables response compression.
97
+ * Automatically sets Content-Encoding header.
98
+ */
29
99
  setCompression(enc: "gzip" | "br" | "deflate"): this;
100
+ /**
101
+ * Serializes the response into a raw HTTP/1.1 buffer.
102
+ *
103
+ * Includes:
104
+ * - status line
105
+ * - headers
106
+ * - optional compression
107
+ * - content-length
108
+ *
109
+ * This is the final step before writing to the socket.
110
+ */
30
111
  getResp(): Buffer;
31
112
  }
@@ -2,20 +2,49 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PipeResponseBase = void 0;
4
4
  /**
5
- * @class PipeResponseBase
6
- * @description The base Response class used by Http.
7
- * This class manages the HTTP response status code, headers, and body.
8
- * Developers can inherit this class and override methods (e.g., `json`, `getResp`) to create custom response types.
5
+ * Base HTTP response implementation used internally by the server.
6
+ *
7
+ * Responsible for:
8
+ * - managing status code
9
+ * - storing headers
10
+ * - writing body
11
+ * - optional compression
12
+ * - serializing everything into a raw HTTP Buffer
13
+ *
14
+ * This class is optimized for performance and object pooling.
15
+ *
16
+ * You may extend this class to implement custom helpers
17
+ * (e.g. html(), stream(), file(), etc.).
9
18
  */
10
19
  class PipeResponseBase {
11
20
  constructor() {
21
+ /**
22
+ * Raw response body stored as UTF-8 string.
23
+ */
12
24
  this.body = "";
25
+ /**
26
+ * HTTP status code.
27
+ * @default 200
28
+ */
13
29
  this.status = 200;
30
+ /**
31
+ * Response headers map.
32
+ * Uses Object.create(null) for maximum performance and safety.
33
+ */
14
34
  this.headers = Object.create(null);
35
+ /**
36
+ * Marks whether response has been finalized (send/json/redirect called).
37
+ */
15
38
  this.finishedFlag = false;
39
+ /**
40
+ * Selected compression type.
41
+ */
16
42
  this.compression = null;
43
+ /**
44
+ * Object pool identifier.
45
+ */
17
46
  this.objId = -1;
18
- // JIT / inline safety
47
+ // Bind once for JIT/inline stability and faster hot path calls
19
48
  Object.defineProperty(this, "getResp", {
20
49
  value: this.getResp.bind(this),
21
50
  writable: false,
@@ -26,10 +55,16 @@ class PipeResponseBase {
26
55
  /* ===================== */
27
56
  /* ===== POOL API ====== */
28
57
  /* ===================== */
58
+ /**
59
+ * Attaches this response to an object pool.
60
+ */
29
61
  setCPool(cPool, objId) {
30
62
  this.objId = objId;
31
63
  this.cPool = cPool;
32
64
  }
65
+ /**
66
+ * Resets state and returns object back to the pool.
67
+ */
33
68
  freeCPool() {
34
69
  this.body = "";
35
70
  this.status = 200;
@@ -41,26 +76,38 @@ class PipeResponseBase {
41
76
  /* ===================== */
42
77
  /* ===== GETTERS ======= */
43
78
  /* ===================== */
79
+ /** Returns current HTTP status code. */
44
80
  getStatus() {
45
81
  return this.status;
46
82
  }
83
+ /** Returns response headers object. */
47
84
  getHeaders() {
48
85
  return this.headers;
49
86
  }
87
+ /** Returns response body as string. */
50
88
  getBody() {
51
89
  return this.body;
52
90
  }
53
91
  /* ===================== */
54
92
  /* ===== MUTATORS ====== */
55
93
  /* ===================== */
94
+ /**
95
+ * Sets HTTP status code.
96
+ */
56
97
  setStatus(code) {
57
98
  this.status = code | 0;
58
99
  return this;
59
100
  }
101
+ /**
102
+ * Sets a single response header.
103
+ */
60
104
  setHeader(key, value) {
61
105
  this.headers[key] = value;
62
106
  return this;
63
107
  }
108
+ /**
109
+ * Merges multiple headers.
110
+ */
64
111
  setHeaders(obj) {
65
112
  for (const k in obj)
66
113
  this.headers[k] = obj[k];
@@ -69,21 +116,37 @@ class PipeResponseBase {
69
116
  /* ===================== */
70
117
  /* ===== SEND API ====== */
71
118
  /* ===================== */
119
+ /**
120
+ * Sends plain text payload.
121
+ * Marks response as finished.
122
+ */
72
123
  send(payload) {
73
124
  this.body = payload;
74
125
  this.finishedFlag = true;
75
126
  }
127
+ /**
128
+ * Sends JSON response.
129
+ * Automatically sets Content-Type: application/json.
130
+ */
76
131
  json(obj) {
77
132
  this.setHeader("Content-Type", "application/json");
78
133
  this.body = JSON.stringify(obj);
79
134
  this.finishedFlag = true;
80
135
  }
136
+ /**
137
+ * Redirects client to another URL.
138
+ * @default code 302
139
+ */
81
140
  redirect(url, code = 302) {
82
141
  this.status = code | 0;
83
142
  this.headers["Location"] = url;
84
143
  this.body = "";
85
144
  this.finishedFlag = true;
86
145
  }
146
+ /**
147
+ * Enables response compression.
148
+ * Automatically sets Content-Encoding header.
149
+ */
87
150
  setCompression(enc) {
88
151
  this.compression = enc;
89
152
  this.headers["Content-Encoding"] = enc;
@@ -92,6 +155,17 @@ class PipeResponseBase {
92
155
  /* ===================== */
93
156
  /* ===== FINALIZE ====== */
94
157
  /* ===================== */
158
+ /**
159
+ * Serializes the response into a raw HTTP/1.1 buffer.
160
+ *
161
+ * Includes:
162
+ * - status line
163
+ * - headers
164
+ * - optional compression
165
+ * - content-length
166
+ *
167
+ * This is the final step before writing to the socket.
168
+ */
95
169
  getResp() {
96
170
  const hdr = { ...this.headers };
97
171
  let bodyBuf = Buffer.from(this.body, "utf-8");
package/dist/http.d.ts CHANGED
@@ -104,148 +104,67 @@ export declare namespace Http {
104
104
  FLAG_SMUGGING_TE_CL = 24576
105
105
  }
106
106
  /**
107
- * @interface Server
108
- * @description Defines the public methods and properties of the Http server instance.
109
- * It is used to configure and manage the server settings and lifecycle.
107
+ * @interface HttpContext
108
+ * @description Public API surface of the HTTP runtime context.
109
+ * Wraps Node.js `net.Server` and provides HTTP features such as
110
+ * routing, pooling, limits, CORS and lifecycle management.
110
111
  */
111
- export interface Server {
112
+ export interface HttpContext {
112
113
  /**
113
- * @method enableCors
114
- * @description Enables and configures Cross-Origin Resource Sharing (CORS) for the server.
115
- * @param {CorsConfig} opts - CORS configuration options.
116
- * @returns {this} The server instance for chaining.
114
+ * Underlying raw Node.js server instance.
115
+ * Can be used for low-level socket/event access when needed.
117
116
  */
118
- enableCors(opts: CorsConfig): this;
117
+ readonly server: net.Server;
119
118
  /**
120
- * @method setTimeout
121
- * @description Sets the connection timeout value.
122
- * @param {number} timeout - Timeout duration in milliseconds. Must be greater than 0.
119
+ * Enables and configures Cross-Origin Resource Sharing (CORS).
120
+ *
121
+ * Automatically injects CORS headers into responses.
122
+ *
123
+ * @returns {this} Context instance (chainable)
123
124
  */
124
- setTimeout(timeout: number): void;
125
+ enableCors(cfg: CorsConfig): this;
125
126
  /**
126
- * @method setRequestQuerySize
127
- * @description Sets the maximum allowed size for the request query string.
128
- * @param {number} requestQuerySize - Maximum query string size in bytes. Must be greater than 0.
127
+ * Sets the connection timeout.
128
+ * @default 3000 ms
129
129
  */
130
- setRequestQuerySize(requestQuerySize: number): void;
130
+ setTimeout(timeout: number): void;
131
131
  /**
132
- * @method setMaxHeaderSize
133
- * @description Sets the maximum allowed size for request headers.
134
- * @param {number} maxHeaderSize - Maximum header size in bytes. Must be greater than 0.
132
+ * Sets the maximum allowed query string size.
133
+ * @default 2048 bytes
135
134
  */
136
- setMaxHeaderSize(maxHeaderSize: number): void;
135
+ setRequestQuerySize(requestQuerySize: number): void;
137
136
  /**
138
- * @method setMaxContentSize
139
- * @description Sets the maximum allowed size for the request body (content/payload).
140
- * @param {number} maxContentSize - Maximum content size in bytes. Must be greater than 0.
137
+ * Sets the maximum allowed request body (payload) size.
138
+ * @default 3145728 bytes (3MB)
141
139
  */
142
140
  setMaxContentSize(maxContentSize: number): void;
143
141
  /**
144
- * @method getTimeout
145
- * @description Gets the current connection timeout value.
146
- * @returns {number} The timeout duration in milliseconds.
142
+ * Sets the max header name size.
143
+ * @default 512 bytes
147
144
  */
148
- getTimeout(): number;
145
+ setMaxHeaderNameSize(maxHeaderNameSize: number): void;
149
146
  /**
150
- * @method getRequestQuerySize
151
- * @description Gets the current maximum request query string size.
152
- * @returns {number} The maximum query string size in bytes.
147
+ * Sets the max header value size.
148
+ * @default 1024 bytes
153
149
  */
150
+ setMaxHeaderValueSize(maxHeaderValueSize: number): void;
151
+ getTimeout(): number;
154
152
  getRequestQuerySize(): number;
155
- /**
156
- * @method getMaxHeaderSize
157
- * @description Gets the current maximum request header size.
158
- * @returns {number} The maximum header size in bytes.
159
- */
160
- getMaxHeaderSize(): number;
161
- /**
162
- * @method getMaxContentSize
163
- * @description Gets the current maximum request content size.
164
- * @returns {number} The maximum content size in bytes.
165
- */
153
+ getMaxHeaderNameSize(): number;
154
+ getMaxHeaderValueSize(): number;
166
155
  getMaxContentSize(): number;
167
156
  /**
168
- * @property {boolean} listening
169
- * @description A boolean indicating whether or not the server is listening for connections.
170
- */
171
- listening: boolean;
172
- /**
173
- * @method listen
174
- * @description Starts the server listening for connections.
175
- * @param {number} [port] - The port to listen on.
176
- * @param {string} [hostname] - The host name or IP address to listen on.
177
- * @param {() => void} [listeningListener] - Callback function once the server starts listening.
178
- * @param {number} [backlog] - The maximum length of the queue of pending connections.
179
- * @returns {this} The server instance for chaining.
180
- */
181
- listen(port?: number, hostname?: string, listeningListener?: () => void, backlog?: number): this;
182
- /**
183
- * @method address
184
- * @description Returns the bound address, address family name, and port of the server.
185
- * @returns {net.AddressInfo | string | null} The address info.
186
- */
187
- address(): net.AddressInfo | string | null;
188
- /**
189
- * @method setMaxRequests
190
- * @description Sets the maximum number of concurrent requests the server can handle by resizing internal pools.
191
- * @param {number} n - The maximum number of concurrent requests. Must be 1 or greater.
192
- * @returns {boolean} Returns `true` if the pools were successfully resized, `false` otherwise.
193
- */
194
- setMaxRequests: (n: number) => boolean;
195
- /**
196
- * @method getMaxListeners
197
- * @description Gets the current maximum listener value.
198
- * @returns {number} The maximum number of listeners.
157
+ * Starts listening for incoming connections.
158
+ * @returns {this} Context instance (chainable)
199
159
  */
200
- getMaxListeners(): number;
160
+ listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
201
161
  /**
202
- * @method setMaxListeners
203
- * @description Sets the max number of listeners.
204
- * @param {number} n - The maximum number of listeners.
205
- * @returns {this} The server instance for chaining.
162
+ * Sets maximum number of concurrent requests.
163
+ * Resizes internal pools.
164
+ *
165
+ * @default 5000
206
166
  */
207
- setMaxListeners(n: number): this;
208
- /**
209
- * @method on
210
- * @description Registers an event listener for the 'close' event.
211
- */
212
- on(event: 'close', listener: () => void): this;
213
- /**
214
- * @method on
215
- * @description Registers an event listener for the 'connection' event.
216
- */
217
- on(event: 'connection', listener: (socket: net.Socket) => void): this;
218
- /**
219
- * @method on
220
- * @description Registers an event listener for the 'error' event.
221
- */
222
- on(event: 'error', listener: (err: Error) => void): this;
223
- /**
224
- * @method on
225
- * @description Registers an event listener for the 'listening' event.
226
- */
227
- on(event: 'listening', listener: () => void): this;
228
- /**
229
- * @method on
230
- * @description Registers a listener for any specified event.
231
- * @param {string} event - The name of the event.
232
- * @param {Function} listener - The callback function.
233
- */
234
- on(event: string, listener: (...args: any[]) => void): this;
235
- /**
236
- * @method off
237
- * @description Removes a registered listener for the specified event.
238
- * @param {string} event - The name of the event.
239
- * @param {Function} listener - The callback function to remove.
240
- */
241
- off(event: string, listener: (...args: any[]) => void): this;
242
- /**
243
- * @method close
244
- * @description Stops the server from accepting new connections and keeps existing connections.
245
- * @param {(err?: Error) => void} [callback] - Called when the server has closed.
246
- * @returns {this} The server instance for chaining.
247
- */
248
- close(callback?: (err?: Error) => void): this;
167
+ setMaxRequests(n: number): boolean;
249
168
  }
250
169
  /**
251
170
  * @description Represents a map of pre-defined HTTP response buffers for common errors and status codes.
@@ -304,31 +223,70 @@ export declare namespace Http {
304
223
  maxAge?: number;
305
224
  }
306
225
  /**
307
- * @interface ServerOptions
308
- * @description Options used to configure the behavior of the Http server.
309
- * @property {net.ServerOpts} netServerOptions - Options passed to the underlying Node.js net.Server structure.
310
- * @property {number} [maxHeaderSize=2048] - The maximum allowed request header size (bytes). (Recommended: 2048 - 4096)
311
- * @property {number} [maxContentSize=3145728] - The maximum allowed request content/payload size (bytes). (Recommended: 1MB - 10MB)
312
- * @property {number} [timeout=0] - Socket timeout duration (milliseconds). (3000: No timeout)
313
- * @property {boolean} [untilEnd=false] - Determines if the server should wait for the end of the stream when Content-Length or Transfer-Encoding are not specified.
314
- * If `false` and these headers are missing, the request is closed immediately and ignored (Default behavior).
315
- * If `true`, it waits until the end of the stream.
316
- * @property {number} [maxRequests=5000] - The maximum number of simultaneous requests/connections that can be processed. Also determines the pool size. (Recommended: 5000 - 10000)
317
- * @property {typeof PipeResponseBase} ResponseCtor - The constructor function for the custom Response class to be used for requests.
318
- * Can be used by extending `PipeResponseBase` to add your own custom response types (e.g., for JSON, XML, etc.).
319
- * @property {number} [requestQuerySize=2048] - The maximum allowed request query string size (bytes). (Recommended: 1024 - 4096)
320
- */
226
+ * Configuration options used to initialize the HTTP context/server.
227
+ */
321
228
  export interface ServerOptions {
229
+ /**
230
+ * Options forwarded directly to the underlying Node.js `net.Server`.
231
+ */
322
232
  netServerOptions?: net.ServerOpts;
233
+ /**
234
+ * Maximum total header size in bytes.
235
+ * @default 2048
236
+ * @recommended 2048 – 4096
237
+ */
323
238
  maxHeaderSize?: number;
239
+ /**
240
+ * Maximum allowed header name size in bytes.
241
+ * @default 256
242
+ */
324
243
  maxHeaderNameSize?: number;
244
+ /**
245
+ * Maximum allowed header value size in bytes.
246
+ * @default 2048
247
+ */
325
248
  maxHeaderValueSize?: number;
249
+ /**
250
+ * Maximum allowed request body (payload) size in bytes.
251
+ * @default 3145728 (3MB)
252
+ * @recommended 1MB – 10MB
253
+ */
326
254
  maxContentSize?: number;
255
+ /**
256
+ * Socket timeout duration in milliseconds.
257
+ * 0 disables timeout.
258
+ * @default 3000
259
+ */
327
260
  timeout?: number;
261
+ /**
262
+ * Determines behavior when `Content-Length` or `Transfer-Encoding` is missing.
263
+ *
264
+ * false → close immediately
265
+ * true → wait until stream ends
266
+ *
267
+ * @default false
268
+ */
328
269
  untilEnd?: boolean;
270
+ /**
271
+ * Maximum number of concurrent requests/connections.
272
+ * Also defines internal pool size.
273
+ * @default 5000
274
+ * @recommended 5000 – 10000
275
+ */
329
276
  maxRequests?: number;
277
+ /**
278
+ * Custom response constructor.
279
+ * Extend `PipeResponseBase` to implement JSON/XML/custom responses.
280
+ */
330
281
  ResponseCtor?: typeof PipeResponseBase;
282
+ /**
283
+ * Callback triggered when a new pool chunk is created during bootstrap.
284
+ */
331
285
  bootstrapPoolChunkProgression?: (createdChunkProgression: ChunkProgression) => void;
286
+ /**
287
+ * Maximum allowed request query string size in bytes.
288
+ * @default 2048
289
+ */
332
290
  requestQuerySize?: number;
333
291
  }
334
292
  /**
@@ -360,42 +318,122 @@ export declare namespace Http {
360
318
  handle: MiddlewareHandleFn;
361
319
  }
362
320
  export type AccumulateHandleFn = (socket: net.Socket, p: ChunkProgression) => void;
321
+ /**
322
+ * Represents a single HTTP endpoint bound to a specific route + method.
323
+ * Contains handler, middleware chain and per-endpoint limits.
324
+ */
363
325
  export interface Endpoint {
326
+ /**
327
+ * URL path segment of the endpoint.
328
+ * Example: "/users", "/:id"
329
+ */
364
330
  url: string;
331
+ /**
332
+ * HTTP method handled by this endpoint.
333
+ */
365
334
  method: HttpMethod;
335
+ /**
336
+ * Optional content configuration (type/encoding rules).
337
+ */
366
338
  ct?: ContentConfig;
339
+ /**
340
+ * Optional custom accumulate handler used during request parsing.
341
+ * Overrides default accumulation behavior.
342
+ */
367
343
  accumulateHandle?: AccumulateHandleFn;
344
+ /**
345
+ * Middleware chain executed before the main handler.
346
+ */
368
347
  middlewares: Middleware[];
348
+ /**
349
+ * Adds a middleware to this endpoint.
350
+ * @returns {Endpoint} same endpoint (chainable)
351
+ */
369
352
  addMiddleware(mw: Middleware): Endpoint;
353
+ /**
354
+ * Main request handler function.
355
+ */
370
356
  handle: EndpointHandleFn | any;
357
+ /**
358
+ * If true, waits until stream end even if
359
+ * `Content-Length` / `Transfer-Encoding` is missing.
360
+ *
361
+ * Overrides global server setting.
362
+ * @default false
363
+ */
371
364
  untilEnd?: boolean;
365
+ /**
366
+ * Maximum request body size allowed for this endpoint.
367
+ * Overrides global server limit.
368
+ */
372
369
  maxContentSize?: number;
370
+ /**
371
+ * Maximum header size allowed for this endpoint.
372
+ * Overrides global server limit.
373
+ */
373
374
  maxHeaderSize?: number;
374
375
  }
376
+ /**
377
+ * Optional per-endpoint configuration overrides.
378
+ * Used when creating endpoints to customize limits locally.
379
+ */
375
380
  export interface EndpointOpt {
381
+ /**
382
+ * Overrides global `untilEnd` behavior.
383
+ * @default false
384
+ */
376
385
  untilEnd?: boolean;
386
+ /**
387
+ * Overrides global maximum content size.
388
+ */
377
389
  maxContentSize?: number;
390
+ /**
391
+ * Overrides global maximum header size.
392
+ */
378
393
  maxHeaderSize?: number;
379
394
  }
380
395
  /**
381
- * @interface Route
382
- * @description Defines a routing structure for the Http server.
383
- * It is the basic building block of the routing tree.
384
- * @property {string} url - The URL path segment this route will match (e.g., '/users').
385
- * @property {Endpoint[]} endpoints - Endpoints corresponding to HTTP methods for this route.
386
- * @property {Middleware[]} middlewares - Middleware functions to run for requests to this route and its sub-routes.
387
- * @property {Route[]} routes - Nested sub-routes under this route.
388
- * @method addRoute - Adds a new sub-route.
389
- * @method addEndpoint - Adds a new endpoint.
390
- * @method addMiddleware - Adds a new middleware.
396
+ * Represents a routing node in the HTTP routing tree.
397
+ *
398
+ * A route can:
399
+ * - contain endpoints
400
+ * - contain middlewares
401
+ * - contain nested sub-routes
402
+ *
403
+ * Works similar to Express/Fastify router groups.
391
404
  */
392
405
  export interface Route {
406
+ /**
407
+ * Base URL path segment for this route.
408
+ * Example: "/users"
409
+ */
393
410
  url: string;
411
+ /**
412
+ * Endpoints registered for this route.
413
+ */
394
414
  endpoints: Endpoint[];
415
+ /**
416
+ * Middlewares applied to this route and all child routes.
417
+ */
395
418
  middlewares: Middleware[];
419
+ /**
420
+ * Nested child routes.
421
+ */
396
422
  routes: Route[];
423
+ /**
424
+ * Adds a child route.
425
+ * @returns {Route} same route (chainable)
426
+ */
397
427
  addRoute(r: Route): Route;
428
+ /**
429
+ * Adds an endpoint to this route.
430
+ * @returns {Route} same route (chainable)
431
+ */
398
432
  addEndpoint(ep: Endpoint): Route;
433
+ /**
434
+ * Adds a middleware to this route.
435
+ * @returns {Route} same route (chainable)
436
+ */
399
437
  addMiddleware(mw: Middleware): Route;
400
438
  }
401
439
  export interface BuildedRoute {
@@ -440,26 +478,100 @@ export declare namespace Http {
440
478
  br = "br",
441
479
  deflate = "deflate"
442
480
  }
481
+ /**
482
+ * Defines content negotiation and parsing rules for an endpoint.
483
+ *
484
+ * Controls how request bodies are interpreted and decoded
485
+ * based on Content-Type and Content-Encoding headers.
486
+ */
443
487
  export interface ContentConfig {
444
- type: ContentTypeTables | null | undefined;
445
- encoding: ContentEncodingTables | null | undefined;
488
+ /**
489
+ * Expected content type of the request body.
490
+ *
491
+ * If undefined → any type is accepted.
492
+ */
493
+ type?: ContentTypeTables | null;
494
+ /**
495
+ * Expected content encoding (gzip, br, deflate, etc.).
496
+ *
497
+ * If undefined → no decoding is applied.
498
+ */
499
+ encoding?: ContentEncodingTables | null;
446
500
  }
501
+ /**
502
+ * Internal compiled route representation used at runtime.
503
+ *
504
+ * Created after the routing tree is built.
505
+ * Contains fully prepared handlers, middleware chain and limits
506
+ * for fast request dispatching.
507
+ */
447
508
  export interface RoutePipe {
509
+ /**
510
+ * Function responsible for accumulating and parsing
511
+ * incoming socket data into a request.
512
+ */
448
513
  accumulateHandler(socket: net.Socket, chunkProgression: ChunkProgression): void;
514
+ /**
515
+ * Full normalized route URL.
516
+ * Example: "/users/:id"
517
+ */
449
518
  url: string;
519
+ /**
520
+ * Optional content configuration for this route.
521
+ */
450
522
  ct?: ContentConfig;
523
+ /**
524
+ * Precompiled pipeline handler (middlewares + endpoint handler).
525
+ */
451
526
  pipeHandler: Function;
527
+ /**
528
+ * Ordered middleware handlers executed before the endpoint.
529
+ */
452
530
  mws: Http.MiddlewareHandleFn[];
531
+ /**
532
+ * Response constructor used to create response objects
533
+ * for this route.
534
+ */
453
535
  ResponseCtor: typeof PipeResponseBase;
536
+ /**
537
+ * Internal route identifier (used for fast lookup/dispatch).
538
+ */
454
539
  routeId: number;
540
+ /**
541
+ * Determines whether to wait for stream end when
542
+ * Content-Length / Transfer-Encoding is missing.
543
+ */
455
544
  untilEnd: boolean;
545
+ /**
546
+ * Maximum allowed request body size in bytes for this route.
547
+ */
456
548
  maxContentSize: number;
549
+ /**
550
+ * Maximum allowed header size in bytes for this route.
551
+ */
457
552
  maxHeaderSize: number;
458
553
  }
459
554
  export type ParseInitialFn = (socket: net.Socket, chunk: Buffer, p: Http.ChunkProgression) => void;
555
+ /**
556
+ * Configuration options for the Web HTTP context.
557
+ */
460
558
  export interface WebContextState {
559
+ /**
560
+ * Physical folder name where static files are served from.
561
+ * @default "dist"
562
+ * @example "./dist", "./build", "./public"
563
+ */
461
564
  publicStaticPath?: string;
565
+ /**
566
+ * URL route prefix for static assets.
567
+ * @default "/public"
568
+ * @example "/assets" -> http://host/assets/logo.png
569
+ */
462
570
  publicStaticRoute?: string;
571
+ /**
572
+ * Entry HTML file for SPA fallback (used when route not found).
573
+ * @default "dist/index.html"
574
+ */
463
575
  spaRootPath?: string;
464
576
  }
465
577
  /**
@@ -563,5 +675,29 @@ export declare namespace Http {
563
675
  */
564
676
  chunkParser: ChunkParser;
565
677
  }
678
+ /**
679
+ * Minimal public contract for a response object.
680
+ *
681
+ * Allows setting headers, status and sending content,
682
+ * then serializing into a raw HTTP buffer.
683
+ */
684
+ export interface IHttpResponseBase {
685
+ /** Sets HTTP status code. */
686
+ setStatus(code: number): this;
687
+ /** Sets a single header. */
688
+ setHeader(key: string, value: string): this;
689
+ /** Sets multiple headers at once. */
690
+ setHeaders(obj: Record<string, string>): this;
691
+ /** Sends plain text payload. */
692
+ send(payload: string): void;
693
+ /** Sends JSON payload. */
694
+ json(obj: unknown): void;
695
+ /** Sends redirect response. */
696
+ redirect(url: string, code?: number): void;
697
+ /** Produces raw HTTP buffer for socket write. */
698
+ getResp(): Buffer;
699
+ /** Releases object back to pool. */
700
+ freeCPool(): void;
701
+ }
566
702
  export {};
567
703
  }
package/dist/index.d.ts CHANGED
@@ -7,3 +7,13 @@ declare function createServer(opts?: Http.ServerOptions): {
7
7
  };
8
8
  export { createServer };
9
9
  export * from "./http";
10
+ export * as Factory from "./http/factory/factory";
11
+ export * as Pipeline from "./http/factory/pipeline";
12
+ export * as Accumulator from "./http/factory/accumulator";
13
+ export * as Content from "./http/content/encoding";
14
+ export { contentParserTable } from "./http/content/parser";
15
+ export * as Chunker from "./http/chunker/ChunkParser";
16
+ export * as ChunkProgression from "./http/chunker/ChunkProgression";
17
+ export * as Streaming from "./http/chunker/StreamingChunkedParser";
18
+ export * as Fixed from "./http/chunker/FixedChunkedParser";
19
+ export * as UntilEnd from "./http/chunker/UntilEndChunkerParser";
package/dist/index.js CHANGED
@@ -10,13 +10,36 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
16
38
  var __importDefault = (this && this.__importDefault) || function (mod) {
17
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
40
  };
19
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.UntilEnd = exports.Fixed = exports.Streaming = exports.ChunkProgression = exports.Chunker = exports.contentParserTable = exports.Content = exports.Accumulator = exports.Pipeline = exports.Factory = void 0;
20
43
  exports.createServer = createServer;
21
44
  const WebContext_1 = __importDefault(require("./http/context/WebContext"));
22
45
  const ApiContext_1 = __importDefault(require("./http/context/ApiContext"));
@@ -36,4 +59,27 @@ function createServer(opts) {
36
59
  }
37
60
  };
38
61
  }
62
+ // ================================
63
+ // Core types (main public API)
64
+ // ================================
39
65
  __exportStar(require("./http"), exports);
66
+ // ================================
67
+ // Factories / Builders
68
+ // ================================
69
+ exports.Factory = __importStar(require("./http/factory/factory"));
70
+ exports.Pipeline = __importStar(require("./http/factory/pipeline"));
71
+ exports.Accumulator = __importStar(require("./http/factory/accumulator"));
72
+ // ================================
73
+ // Content layer
74
+ // ================================
75
+ exports.Content = __importStar(require("./http/content/encoding"));
76
+ var parser_1 = require("./http/content/parser");
77
+ Object.defineProperty(exports, "contentParserTable", { enumerable: true, get: function () { return parser_1.contentParserTable; } });
78
+ // ================================
79
+ // Low-level engine (advanced users)
80
+ // ================================
81
+ exports.Chunker = __importStar(require("./http/chunker/ChunkParser"));
82
+ exports.ChunkProgression = __importStar(require("./http/chunker/ChunkProgression"));
83
+ exports.Streaming = __importStar(require("./http/chunker/StreamingChunkedParser"));
84
+ exports.Fixed = __importStar(require("./http/chunker/FixedChunkedParser"));
85
+ exports.UntilEnd = __importStar(require("./http/chunker/UntilEndChunkerParser"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corecdtl",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "High-performance customizable HTTP engine",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -13,12 +13,15 @@
13
13
  "engine",
14
14
  "native",
15
15
  "addon",
16
- "low-level"
16
+ "low-level",
17
+ "fast",
18
+ "corecdtl"
17
19
  ],
18
20
  "scripts": {
19
21
  "build": "node-gyp rebuild && rm -rf dist && tsc",
20
22
  "install": "node-gyp-build",
21
23
  "prebuild": "prebuildify --napi --strip",
24
+ "build-ts": "tsc",
22
25
  "test": "vitest run",
23
26
  "benchmark": "node benchmark/e2e/run.js",
24
27
  "prepublishOnly": "npm run build",
@@ -56,5 +59,5 @@
56
59
  "bugs": {
57
60
  "url": "https://github.com/DirikTi/corecdtl/issues"
58
61
  },
59
- "homepage": "https://github.com/DirikTi/corecdtl#readme"
62
+ "homepage": "https://github.com/DirikTi/corecdtl#quickstart"
60
63
  }
Binary file
@@ -1,10 +0,0 @@
1
- export interface IHttpResponseBase {
2
- setStatus(code: number): this;
3
- setHeader(key: string, value: string): this;
4
- setHeaders(obj: Record<string, string>): this;
5
- send(payload: string): void;
6
- json(obj: unknown): void;
7
- redirect(url: string, code?: number): void;
8
- getResp(): Buffer;
9
- freeCPool(): void;
10
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });