@linebridge/engine-neo 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@ The official, high-performance HTTP and WebSocket engine for [Linebridge](https:
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @linebridge/engine-neo
8
+ pnpm add @linebridge/engine-neo
9
9
  ```
10
10
 
11
11
  ## Usage
@@ -22,5 +22,4 @@ import "@linebridge/engine-neo"
22
22
 
23
23
  This project is licensed under the **MIT License**.
24
24
 
25
- It includes software developed by uNetworking AB and uWebSockets.js contributors, which is licensed under the **Apache License 2.0**.
26
- See the [LICENSE](./LICENSE) file for more details.
25
+ It includes software developed by uNetworking AB and uWebSockets.js contributors, which is licensed under the **Apache License 2.0**. See the [LICENSE](./LICENSE) file for more details.
package/lib/engine.d.ts CHANGED
@@ -15,6 +15,8 @@ import uws_wrapper, { type uWebsockets } from "./uws.js";
15
15
  import RTEngine from "linebridge/classes/RtEngine/index";
16
16
  import { EngineAdaptor } from "linebridge/classes/EngineAdaptor/index";
17
17
  import { Route } from "linebridge/classes/Route/index";
18
+ import route_register from "./route_register.js";
19
+ import middleware_register from "./register_middleware.js";
18
20
  /**
19
21
  * Options that control the engine's behaviour.
20
22
  */
@@ -76,9 +78,9 @@ export declare class NeoEngine extends EngineAdaptor {
76
78
  /** Gracefully shuts down the server. Bound to the engine instance. */
77
79
  close: () => Promise<boolean>;
78
80
  /** Registers a route (HTTP method + path + handler). */
79
- register: (route: import("linebridge/classes/Route/index").RouteAlike) => void;
81
+ register: OmitThisParameter<typeof route_register>;
80
82
  /** Registers a global middleware that runs before every route handler. */
81
- register_middleware: (middleware: any) => void;
83
+ register_middleware: OmitThisParameter<typeof middleware_register>;
82
84
  /**
83
85
  * Publish a message to a topic in MQTT syntax to all WebSocket connections on this Server instance.
84
86
  * You cannot publish using wildcards, only fully specified topics.
@@ -91,7 +93,7 @@ export declare class NeoEngine extends EngineAdaptor {
91
93
  /** Incoming HTTP request handler. Bound to the engine instance. */
92
94
  on_request: (native_req: uWebsockets.HttpRequest, native_res: uWebsockets.HttpResponse, route: Route<any, "server"[]>, socket?: uWebsockets.us_socket_context_t | null | undefined) => any;
93
95
  /** Middleware/route iteration loop. Bound to the engine instance. */
94
- request_iterator: (request: Request<any>, response: Response<any>, route: Route<Server<"neo">, "server"[]>, allMiddlewares: Handler<HandlerKind>[], cursor?: number | undefined) => Promise<void>;
96
+ request_iterator: (request: Request<any>, response: Response<any>, route: Route<Server<"neo">, "server"[]>, allMiddlewares: Handler<HandlerKind.middleware>[], cursor?: number | undefined) => Promise<void>;
95
97
  /**
96
98
  * Decrements the pending request counter and fires the zero-handler
97
99
  * when no requests remain in flight.
package/lib/engine.js CHANGED
@@ -14,7 +14,7 @@ import toBoolean from "linebridge/utils/toBoolean";
14
14
  import RTEngine from "linebridge/classes/RtEngine/index";
15
15
  import { EngineAdaptor } from "linebridge/classes/EngineAdaptor/index";
16
16
  import { Route } from "linebridge/classes/Route/index";
17
- import WebsocketPolyfill from "./ws/Websocket.js";
17
+ import Websocket from "./ws/Websocket.js";
18
18
  import route_register from "./route_register.js";
19
19
  import middleware_register from "./register_middleware.js";
20
20
  import listen from "./listen.js";
@@ -128,7 +128,7 @@ export class NeoEngine extends EngineAdaptor {
128
128
  upgrade: (res, req, _context) => this.ws.handleUpgrade(req, res),
129
129
  // wrap raw uWS websocket with the polyfill so RTEngine gets EventEmitter + helpers
130
130
  open: (ws) => {
131
- const poly = new WebsocketPolyfill(ws);
131
+ const poly = new Websocket(ws);
132
132
  ws.poly = poly;
133
133
  //@ts-ignore polyfill context is Object vs RtEngineSocket's typed shape, but runtime is correct
134
134
  this.ws.handleConnection(poly);
@@ -151,12 +151,15 @@ export class NeoEngine extends EngineAdaptor {
151
151
  // @ts-ignore
152
152
  global.websockets = this.ws;
153
153
  }
154
- // create the default route
155
- const defaultRoute = new Route();
156
- defaultRoute.method = "any";
157
- defaultRoute.path = "/*";
158
- defaultRoute.fn = this._defaultResponse;
159
- this.register(defaultRoute);
154
+ if (!toBoolean(process.env.LB_SOCKET_MODE)) {
155
+ // create the default route
156
+ const defaultRoute = new Route();
157
+ defaultRoute.method = "any";
158
+ defaultRoute.path = "/*";
159
+ defaultRoute.fn = this._defaultResponse;
160
+ defaultRoute._initialize(this.server);
161
+ this.register(defaultRoute);
162
+ }
160
163
  };
161
164
  /** Starts the server. Bound to the engine instance. */
162
165
  listen = listen.bind(this);
@@ -200,7 +203,9 @@ export class NeoEngine extends EngineAdaptor {
200
203
  * Default handler for unmatched routes. Responds with a 404 JSON body.
201
204
  */
202
205
  _defaultResponse(req, res) {
203
- res.status(404).json({ error: "Not found" });
206
+ res.status(404)
207
+ .setHeader("content-type", "application/json")
208
+ ._sendFast(`{"error":"Not found"}`);
204
209
  }
205
210
  }
206
211
  export { uws_wrapper as uWebsockets };
package/lib/listen.js CHANGED
@@ -25,7 +25,9 @@ export default async function () {
25
25
  this.listen_socket = listen_socket;
26
26
  // optionally register process-exit listeners for graceful shutdown
27
27
  if (this.options.auto_close) {
28
- EXIT_EVENTS.forEach((type) => process.once(type, () => this.close()));
28
+ EXIT_EVENTS.forEach((type) => process.once(type, () => {
29
+ void this.server._fireClose();
30
+ }));
29
31
  }
30
32
  resolve();
31
33
  }
@@ -9,7 +9,7 @@ import type Engine from "./engine.js";
9
9
  import type Request from "./request.js";
10
10
  import type Response from "./response.js";
11
11
  import type { Route } from "linebridge/classes/Route/index";
12
- import type { Handler } from "linebridge/classes/Handler/index";
12
+ import type { Handler, HandlerKind } from "linebridge/classes/Handler/index";
13
13
  /**
14
14
  * Recursively iterates the middleware chain, then calls the route handler.
15
15
  *
@@ -19,4 +19,4 @@ import type { Handler } from "linebridge/classes/Handler/index";
19
19
  *
20
20
  * @param cursor - Zero-based index into the middleware array. Increments on each recursion.
21
21
  */
22
- export default function (this: Engine, request: Request<any>, response: Response<any>, route: Route<typeof this.server>, allMiddlewares: Handler[], cursor?: number): Promise<void>;
22
+ export default function (this: Engine, request: Request<any>, response: Response<any>, route: Route<typeof this.server>, allMiddlewares: Handler<HandlerKind.middleware>[], cursor?: number): Promise<void>;
package/lib/response.d.ts CHANGED
@@ -43,6 +43,10 @@ export default class Response<TServer = Server<any>> implements BaseHttpResponse
43
43
  _status_code: number;
44
44
  /** Custom status message (overrides the default from STATUS_CODES). */
45
45
  _status_message: string | null;
46
+ /** Cached engine reference to avoid walking route.server on every response. */
47
+ _engine: EngineAdaptor | null;
48
+ /** Whether at least one header was queued. Avoids enumerating an empty object. */
49
+ _has_headers: boolean;
46
50
  /** Response headers (key → value or key → string[]). */
47
51
  _headers: Record<string, string | string[]>;
48
52
  /** Set-Cookie headers (name → serialized cookie string). */
@@ -141,11 +145,16 @@ export default class Response<TServer = Server<any>> implements BaseHttpResponse
141
145
  * Must return `true` if the chunk was successfully written.
142
146
  */
143
147
  drain(handler: (offset: number) => boolean): void;
148
+ /**
149
+ * Marks the response as completed and fires the lifecycle listeners.
150
+ * Used by every path that finishes a response, including streaming.
151
+ */
152
+ _mark_completed(): void;
144
153
  /**
145
154
  * Sends the response body and marks the response as completed.
146
155
  *
147
- * Supports corked (batched) and uncorked paths, streaming mode, and
148
- * `endWithoutBody` when a custom `content-length` header is set.
156
+ * All uWS writes are wrapped in a single cork callback so status,
157
+ * headers and body are flushed atomically.
149
158
  *
150
159
  * Fires `finish` and `close` event listeners.
151
160
  */
@@ -178,7 +187,7 @@ export default class Response<TServer = Server<any>> implements BaseHttpResponse
178
187
  redirect(url: string): boolean;
179
188
  /**
180
189
  * Fast-path send used by the `_invokeHandler`.
181
- * Skips cork/uncork logic and writes directly.
190
+ * Corks the writes so status, headers and body are flushed atomically.
182
191
  */
183
192
  _sendFast(body: any): void;
184
193
  /**
package/lib/response.js CHANGED
@@ -46,6 +46,10 @@ export default class Response {
46
46
  _status_code;
47
47
  /** Custom status message (overrides the default from STATUS_CODES). */
48
48
  _status_message;
49
+ /** Cached engine reference to avoid walking route.server on every response. */
50
+ _engine;
51
+ /** Whether at least one header was queued. Avoids enumerating an empty object. */
52
+ _has_headers;
49
53
  /** Response headers (key → value or key → string[]). */
50
54
  _headers;
51
55
  /** Set-Cookie headers (name → serialized cookie string). */
@@ -79,26 +83,36 @@ export default class Response {
79
83
  const res = new Response();
80
84
  res._raw_response = raw_response;
81
85
  res.route = route;
86
+ res._engine = route.engine ?? null;
82
87
  res._wrapped_request = request;
83
88
  res._upgrade_socket = socket || null;
84
- res._headers = {};
89
+ res._headers = Object.create(null);
90
+ res._has_headers = false;
91
+ res._cookies = null;
92
+ res._events = null;
93
+ res._streaming = false;
94
+ res._cork = false;
95
+ res._corked = false;
96
+ res._drain_handler = null;
85
97
  res._status_code = 200;
98
+ res._status_message = null;
86
99
  res._middleware_cursor = -1;
87
100
  // handle uWS abort (client disconnects before response is sent)
88
101
  raw_response.onAborted(() => {
89
102
  if (res.completed)
90
103
  return;
91
104
  res.completed = true;
92
- res.route?.server.engine._resolve_pending_request();
105
+ res._engine?._resolve_pending_request();
93
106
  //res._wrapped_request.pause()
94
- if (res._events?.abort) {
95
- for (let i = 0; i < res._events.abort.length; i++) {
96
- res._events.abort[i](res._wrapped_request, res);
107
+ const events = res._events;
108
+ if (events?.abort) {
109
+ for (let i = 0; i < events.abort.length; i++) {
110
+ events.abort[i](res._wrapped_request, res);
97
111
  }
98
112
  }
99
- if (res._events?.close) {
100
- for (let i = 0; i < res._events.close.length; i++) {
101
- res._events.close[i](res._wrapped_request, res);
113
+ if (events?.close) {
114
+ for (let i = 0; i < events.close.length; i++) {
115
+ events.close[i](res._wrapped_request, res);
102
116
  }
103
117
  }
104
118
  });
@@ -187,6 +201,7 @@ export default class Response {
187
201
  }
188
202
  this._headers["content-type"] =
189
203
  mime_types.contentType(mime_type) || "text/plain";
204
+ this._has_headers = true;
190
205
  return this;
191
206
  }
192
207
  /**
@@ -197,6 +212,7 @@ export default class Response {
197
212
  name = name.toLowerCase();
198
213
  if (overwrite || this._headers[name] === undefined) {
199
214
  this._headers[name] = value;
215
+ this._has_headers = true;
200
216
  return this;
201
217
  }
202
218
  const existing = this._headers[name];
@@ -269,7 +285,7 @@ export default class Response {
269
285
  // perform the uWS upgrade with the stored socket handle
270
286
  this._raw_response.upgrade({ context }, headers["sec-websocket-key"], headers["sec-websocket-protocol"], headers["sec-websocket-extensions"], this._upgrade_socket);
271
287
  this.completed = true;
272
- this.engine?._resolve_pending_request();
288
+ this._engine?._resolve_pending_request();
273
289
  }
274
290
  /**
275
291
  * Writes the status line and all accumulated headers to the uWS response.
@@ -281,31 +297,34 @@ export default class Response {
281
297
  return false;
282
298
  this.initiated = true;
283
299
  const raw = this._raw_response;
284
- if (this._status_message) {
285
- raw.writeStatus(`${this._status_code} ${this._status_message}`);
286
- }
287
- else {
288
- raw.writeStatus(STATUS_CACHE[this._status_code] || `${this._status_code} OK`);
289
- }
290
- const headerKeys = Object.keys(this._headers);
291
- for (let i = 0; i < headerKeys.length; i++) {
292
- const name = headerKeys[i];
293
- if (name === "content-length")
294
- continue;
295
- const values = this._headers[name];
296
- if (Array.isArray(values)) {
297
- for (let j = 0; j < values.length; j++) {
298
- raw.writeHeader(name, values[j]);
300
+ const status_code = this._status_code;
301
+ const status_message = this._status_message;
302
+ if (status_message) {
303
+ raw.writeStatus(`${status_code} ${status_message}`);
304
+ }
305
+ else if (status_code !== 200) {
306
+ raw.writeStatus(STATUS_CACHE[status_code] || `${status_code} OK`);
307
+ }
308
+ if (this._has_headers) {
309
+ const headers = this._headers;
310
+ for (const name in headers) {
311
+ if (name === "content-length")
312
+ continue;
313
+ const values = headers[name];
314
+ if (Array.isArray(values)) {
315
+ for (let j = 0; j < values.length; j++) {
316
+ raw.writeHeader(name, values[j]);
317
+ }
318
+ }
319
+ else {
320
+ raw.writeHeader(name, values);
299
321
  }
300
- }
301
- else {
302
- raw.writeHeader(name, values);
303
322
  }
304
323
  }
305
324
  if (this._cookies) {
306
- const cookieKeys = Object.keys(this._cookies);
307
- for (let i = 0; i < cookieKeys.length; i++) {
308
- raw.writeHeader("set-cookie", this._cookies[cookieKeys[i]]);
325
+ const cookies = this._cookies;
326
+ for (const name in cookies) {
327
+ raw.writeHeader("set-cookie", cookies[name]);
309
328
  }
310
329
  }
311
330
  return true;
@@ -329,71 +348,64 @@ export default class Response {
329
348
  });
330
349
  }
331
350
  }
351
+ /**
352
+ * Marks the response as completed and fires the lifecycle listeners.
353
+ * Used by every path that finishes a response, including streaming.
354
+ */
355
+ _mark_completed() {
356
+ if (this.completed)
357
+ return;
358
+ const events = this._events;
359
+ if (!events) {
360
+ this.completed = true;
361
+ this._engine?._resolve_pending_request();
362
+ return;
363
+ }
364
+ const finish = events.finish;
365
+ if (!this._streaming && finish) {
366
+ for (let i = 0; i < finish.length; i++) {
367
+ finish[i](this._wrapped_request, this);
368
+ }
369
+ }
370
+ this.completed = true;
371
+ this._engine?._resolve_pending_request();
372
+ const close = events.close;
373
+ if (close) {
374
+ for (let i = 0; i < close.length; i++) {
375
+ close[i](this._wrapped_request, this);
376
+ }
377
+ }
378
+ }
332
379
  /**
333
380
  * Sends the response body and marks the response as completed.
334
381
  *
335
- * Supports corked (batched) and uncorked paths, streaming mode, and
336
- * `endWithoutBody` when a custom `content-length` header is set.
382
+ * All uWS writes are wrapped in a single cork callback so status,
383
+ * headers and body are flushed atomically.
337
384
  *
338
385
  * Fires `finish` and `close` event listeners.
339
386
  */
340
387
  send(body, close_connection) {
341
388
  if (this.completed)
342
389
  return this;
343
- if (this._cork && !this._corked) {
344
- this._corked = true;
345
- this._raw_response.cork(() => {
346
- this._initiate_response();
347
- if (body !== undefined || this._streaming) {
348
- this._raw_response.end(body, close_connection);
349
- }
350
- else {
351
- const custom_length = this._headers["content-length"];
352
- if (custom_length) {
353
- const content_length = typeof custom_length === "string"
354
- ? custom_length
355
- : custom_length[custom_length.length - 1];
356
- this._raw_response.endWithoutBody(content_length, close_connection);
357
- }
358
- else {
359
- this._raw_response.end(body, close_connection);
360
- }
361
- }
362
- });
363
- }
364
- else {
390
+ const raw = this._raw_response;
391
+ raw.cork(() => {
365
392
  this._initiate_response();
366
- const raw = this._raw_response;
367
393
  if (body !== undefined || this._streaming) {
368
394
  raw.end(body, close_connection);
395
+ return;
369
396
  }
370
- else {
371
- const custom_length = this._headers["content-length"];
372
- if (custom_length) {
373
- const content_length = typeof custom_length === "string"
374
- ? custom_length
375
- : custom_length[custom_length.length - 1];
376
- raw.endWithoutBody(content_length, close_connection);
377
- }
378
- else {
379
- raw.end(body, close_connection);
380
- }
381
- }
382
- }
383
- if (!this._streaming && this.listenerCount("finish") > 0) {
384
- const handlers = this._events.finish;
385
- for (let i = 0; i < handlers.length; i++) {
386
- handlers[i](this._wrapped_request, this);
387
- }
388
- }
389
- this.completed = true;
390
- this.engine?._resolve_pending_request();
391
- if (this.listenerCount("close") > 0) {
392
- const handlers = this._events.close;
393
- for (let i = 0; i < handlers.length; i++) {
394
- handlers[i](this._wrapped_request, this);
397
+ const custom_length = this._headers["content-length"];
398
+ if (!custom_length) {
399
+ raw.end(body, close_connection);
400
+ return;
395
401
  }
396
- }
402
+ const content_length = typeof custom_length === "string"
403
+ ? custom_length
404
+ : custom_length[custom_length.length - 1];
405
+ raw.endWithoutBody(content_length, close_connection);
406
+ });
407
+ this._corked = true;
408
+ this._mark_completed();
397
409
  return this;
398
410
  }
399
411
  _uws_write_chunk(chunk, total_size) {
@@ -407,17 +419,16 @@ export default class Response {
407
419
  * Initiates headers if not yet sent. Returns false under backpressure.
408
420
  */
409
421
  write(chunk) {
410
- if (this._cork && !this._corked) {
411
- this._corked = true;
412
- let ok = false;
413
- this._raw_response.cork(() => {
414
- this._initiate_response();
415
- ok = this._raw_response.write(chunk);
416
- });
417
- return ok;
418
- }
419
- this._initiate_response();
420
- return this._raw_response.write(chunk);
422
+ if (this.completed)
423
+ return false;
424
+ const raw = this._raw_response;
425
+ let ok = false;
426
+ raw.cork(() => {
427
+ this._initiate_response();
428
+ ok = raw.write(chunk);
429
+ });
430
+ this._corked = true;
431
+ return ok;
421
432
  }
422
433
  /**
423
434
  * Streams a single chunk with backpressure support.
@@ -427,30 +438,44 @@ export default class Response {
427
438
  if (this.completed)
428
439
  return Promise.resolve();
429
440
  return new Promise((resolve) => {
430
- if (this._cork && !this._corked) {
431
- this._corked = true;
432
- this._raw_response.cork(() => this._initiate_response());
433
- }
434
- else {
441
+ const raw = this._raw_response;
442
+ let sent = false;
443
+ let responded = false;
444
+ let write_offset = 0;
445
+ raw.cork(() => {
435
446
  this._initiate_response();
436
- }
437
- if (this.completed)
447
+ write_offset = raw.getWriteOffset();
448
+ [sent, responded] = this._uws_write_chunk(chunk, total_size);
449
+ if (sent || responded)
450
+ return;
451
+ this.drain((offset) => {
452
+ if (this.completed || !total_size) {
453
+ resolve();
454
+ return true;
455
+ }
456
+ const remaining = chunk.slice(offset - write_offset);
457
+ let flushed = false;
458
+ let has_responded = false;
459
+ raw.cork(() => {
460
+ ;
461
+ [flushed, has_responded] = this._uws_write_chunk(remaining, total_size);
462
+ });
463
+ if (has_responded) {
464
+ this._mark_completed();
465
+ resolve();
466
+ return true;
467
+ }
468
+ if (flushed)
469
+ resolve();
470
+ return flushed;
471
+ });
472
+ });
473
+ if (responded) {
474
+ this._mark_completed();
438
475
  return resolve();
439
- const write_offset = this._raw_response.getWriteOffset();
440
- const [sent] = this._uws_write_chunk(chunk, total_size);
476
+ }
441
477
  if (sent)
442
- return resolve();
443
- this.drain((offset) => {
444
- if (this.completed || !total_size) {
445
- resolve();
446
- return true;
447
- }
448
- const remaining = chunk.slice(offset - write_offset);
449
- const [flushed] = this._uws_write_chunk(remaining, total_size);
450
- if (flushed)
451
- resolve();
452
- return flushed;
453
- });
478
+ resolve();
454
479
  });
455
480
  }
456
481
  /**
@@ -483,7 +508,7 @@ export default class Response {
483
508
  }
484
509
  if (!this.completed) {
485
510
  if (total_size)
486
- this.engine?._resolve_pending_request();
511
+ this._engine?._resolve_pending_request();
487
512
  else
488
513
  this.send();
489
514
  }
@@ -495,7 +520,7 @@ export default class Response {
495
520
  if (this.completed)
496
521
  return;
497
522
  this.completed = true;
498
- this.engine?._resolve_pending_request();
523
+ this._engine?._resolve_pending_request();
499
524
  //this._wrapped_request.pause()
500
525
  this._raw_response.close();
501
526
  }
@@ -509,24 +534,18 @@ export default class Response {
509
534
  }
510
535
  /**
511
536
  * Fast-path send used by the `_invokeHandler`.
512
- * Skips cork/uncork logic and writes directly.
537
+ * Corks the writes so status, headers and body are flushed atomically.
513
538
  */
514
539
  _sendFast(body) {
540
+ if (this.completed)
541
+ return;
542
+ const raw = this._raw_response;
543
+ raw.cork(() => {
544
+ this._initiate_response();
545
+ raw.end(body);
546
+ });
515
547
  this._corked = true;
516
- this._initiate_response();
517
- this._raw_response.end(body);
518
- this.completed = true;
519
- this.engine?._resolve_pending_request();
520
- if (this._events?.finish) {
521
- for (let i = 0; i < this._events.finish.length; i++) {
522
- this._events.finish[i](this._wrapped_request, this);
523
- }
524
- }
525
- if (this._events?.close) {
526
- for (let i = 0; i < this._events.close.length; i++) {
527
- this._events.close[i](this._wrapped_request, this);
528
- }
529
- }
548
+ this._mark_completed();
530
549
  }
531
550
  /**
532
551
  * Sends a JSON response. Sets `Content-Type: application/json` and
@@ -534,6 +553,7 @@ export default class Response {
534
553
  */
535
554
  json(body) {
536
555
  this._headers["content-type"] = "application/json";
556
+ this._has_headers = true;
537
557
  return this.send(stringify(body));
538
558
  }
539
559
  /**
@@ -541,6 +561,7 @@ export default class Response {
541
561
  */
542
562
  html(body) {
543
563
  this._headers["content-type"] = "text/html";
564
+ this._has_headers = true;
544
565
  return this.send(body);
545
566
  }
546
567
  /**
@@ -711,6 +732,7 @@ export default class Response {
711
732
  */
712
733
  location(path) {
713
734
  this._headers["location"] = path;
735
+ this._has_headers = true;
714
736
  return this;
715
737
  }
716
738
  /**
@@ -737,6 +759,7 @@ export default class Response {
737
759
  */
738
760
  vary(name) {
739
761
  this._headers["vary"] = name;
762
+ this._has_headers = true;
740
763
  return this;
741
764
  }
742
765
  }
@@ -1,5 +1,5 @@
1
- import type Engine from "./engine.js";
2
- import { RouteAlike } from "linebridge/classes/Route/index";
1
+ import type { Route } from "linebridge/classes/Route/index";
2
+ import type { NeoEngine } from "./engine.js";
3
3
  /**
4
4
  * Registers a route with the engine's uWS app.
5
5
  *
@@ -7,4 +7,4 @@ import { RouteAlike } from "linebridge/classes/Route/index";
7
7
  *
8
8
  * @throws {Error} If the engine is not initialized or the route is invalid.
9
9
  */
10
- export default function (this: Engine, route: RouteAlike): void;
10
+ export default function (this: NeoEngine, route: Route): void;