@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.
@@ -1,5 +1,3 @@
1
- import { Route, } from "linebridge/classes/Route/index";
2
- import { HandlerKind } from "linebridge/classes/Handler/index";
3
1
  /**
4
2
  * Registers a route with the engine's uWS app.
5
3
  *
@@ -11,57 +9,25 @@ export default function (route) {
11
9
  if (!this.uws) {
12
10
  throw new Error("Engine is not initialized");
13
11
  }
14
- let routeInstance;
15
- // support passing a class constructor or an already-constructed instance
16
- if (typeof route === "function") {
17
- try {
18
- routeInstance = new route();
19
- }
20
- catch (err) {
21
- console.error(`Failed to construct route class:\n`, err);
22
- return;
23
- }
24
- }
25
- else if (route instanceof Route) {
26
- routeInstance = route;
27
- }
28
- else if (typeof route.fn === "function") {
29
- routeInstance = new Route();
30
- routeInstance.kind = HandlerKind.http;
31
- routeInstance.path = route.path ?? "/";
32
- routeInstance.method = route.method ?? "get";
33
- routeInstance.useContexts = route.useContexts ?? [];
34
- routeInstance.useMiddlewares = route.useMiddlewares ?? [];
35
- routeInstance.fn = route.fn;
36
- }
37
- else {
38
- throw new Error("Invalid route provided");
39
- }
40
- // try to initialize the route
41
- try {
42
- routeInstance._initialize(this.server);
43
- }
44
- catch (err) {
45
- console.error(`Failed to initialize route:\n`, err);
46
- return;
47
- }
48
12
  // normalize DELETE method for uWS compatibility (uWS uses "del" internally)
49
- if (routeInstance.method === "delete") {
50
- routeInstance.method = "del";
13
+ if (route.method === "delete") {
14
+ route.method = "del";
51
15
  }
52
16
  // verify the method is a valid uWS route method before registering
53
- if (typeof this.uws[routeInstance.method] !== "function") {
54
- console.warn(`Invalid method (${routeInstance.method}) for route handler [${routeInstance.path}]\nSkipping route..`);
17
+ if (typeof this.uws[route.method] !== "function") {
18
+ console.warn(`Invalid method (${route.method}) for route handler [${route.path}]\nSkipping route..`);
55
19
  return;
56
20
  }
57
21
  this.registers.add({
58
- kind: routeInstance.kind,
59
- method: routeInstance.method,
60
- path: routeInstance.path,
61
- useContexts: routeInstance.useContexts,
62
- useMiddlewares: routeInstance.useMiddlewares,
63
- _source_file: routeInstance._source_file,
64
- handler: routeInstance.handler,
22
+ kind: route.kind,
23
+ method: route.method,
24
+ path: route.path,
25
+ useContexts: route.useContexts,
26
+ useMiddlewares: route.useMiddlewares,
27
+ _source_file: route._source_file,
28
+ handler: route.handler,
65
29
  });
66
- this.uws[routeInstance.method](routeInstance.path, (res, req) => this.on_request(req, res, routeInstance));
30
+ if (route.kind === "http") {
31
+ this.uws[route.method](route.path, (res, req) => this.on_request(req, res, route));
32
+ }
67
33
  }
package/lib/utils.d.ts CHANGED
@@ -10,5 +10,5 @@ declare function wrap_object(original: any, target: any): void;
10
10
  * @param {BufferEncoding} encoding
11
11
  * @returns {String} String
12
12
  */
13
- declare function array_buffer_to_string(array_buffer: ArrayBuffer, encoding?: BufferEncoding): any;
13
+ declare function array_buffer_to_string(array_buffer: ArrayBuffer, encoding?: BufferEncoding): string;
14
14
  export { array_buffer_to_string, wrap_object };
@@ -1,173 +1,125 @@
1
1
  import { EventEmitter } from "tseep/lib/ee-safe.js";
2
- import { Readable, Writable } from "stream";
3
- export default class Websocket extends EventEmitter {
2
+ import { Readable, Writable } from "node:stream";
3
+ import type { uWebsockets } from "../uws.js";
4
+ /** Any payload accepted by uWebSockets or produced by streams. */
5
+ export type WebsocketMessage = string | Buffer | ArrayBuffer | ArrayBufferView;
6
+ /** Events emitted by the websocket polyfill. */
7
+ export type WebsocketEventMap = {
8
+ [event in string | symbol]: (...args: any[]) => void;
9
+ } & {
10
+ message: (message: WebsocketMessage, is_binary: boolean) => void;
11
+ close: (code: number, message: WebsocketMessage) => void;
12
+ drain: () => void;
13
+ ping: (message: WebsocketMessage) => void;
14
+ pong: (message: WebsocketMessage) => void;
15
+ };
16
+ /**
17
+ * Raw uws websocket with the context and polyfill attached by the engine.
18
+ * The native wrapper merges the upgrade user data into the socket object.
19
+ */
20
+ export interface WebsocketRaw<TContext = Record<string, any>> extends uWebsockets.WebSocket<{
21
+ context?: TContext;
22
+ }> {
23
+ context?: TContext;
24
+ poly?: Websocket<TContext>;
25
+ }
26
+ declare const FRAGMENTS: {
27
+ readonly FIRST: "FIRST";
28
+ readonly MIDDLE: "MIDDLE";
29
+ readonly LAST: "LAST";
30
+ };
31
+ type Fragment = (typeof FRAGMENTS)[keyof typeof FRAGMENTS];
32
+ export default class Websocket<TContext = Record<string, any>> extends EventEmitter<WebsocketEventMap> {
4
33
  #private;
5
- constructor(ws: any);
6
- /**
7
- * Binds an event listener to this `Websocket` instance.
8
- * See the Node.js `EventEmitter` documentation for more details on this extended method.
9
- * @param {('message'|'close'|'drain'|'ping'|'pong')} eventName
10
- * @param {Function} listener
11
- * @returns {Websocket}
12
- */
13
- on(eventName: ('message' | 'close' | 'drain' | 'ping' | 'pong'), listener: Function): Websocket;
14
- /**
15
- * Binds a `one-time` event listener to this `Websocket` instance.
16
- * See the Node.js `EventEmitter` documentation for more details on this extended method.
17
- * @param {('message'|'close'|'drain'|'ping'|'pong')} eventName
18
- * @param {Function} listener
19
- * @returns {Websocket}
20
- */
21
- once(eventName: ('message' | 'close' | 'drain' | 'ping' | 'pong'), listener: Function): Websocket;
34
+ constructor(ws: WebsocketRaw<TContext>);
22
35
  /**
23
- * Alias of uWS.cork() method. Accepts a callback with multiple operations for network efficiency.
24
- *
25
- * @param {Function} callback
26
- * @returns {Websocket}
36
+ * Alias of uws cork, used to batch multiple operations for efficiency.
27
37
  */
28
- atomic(callback: Function): Websocket;
38
+ atomic(callback: () => void): Websocket<TContext> | uWebsockets.WebSocket<{
39
+ context?: TContext;
40
+ }>;
29
41
  /**
30
- * Sends a message to websocket connection.
31
- * Returns true if message was sent successfully.
32
- * Returns false if message was not sent due to buil up backpressure.
33
- *
34
- * @param {String|Buffer|ArrayBuffer} message
35
- * @param {Boolean=} is_binary
36
- * @param {Boolean=} compress
37
- * @returns {Boolean}
42
+ * Sends a message over the connection.
43
+ * Returns the uws send status, or false when the socket is closed.
38
44
  */
39
- send(message: string | Buffer | ArrayBuffer, is_binary?: boolean | undefined, compress?: boolean | undefined): boolean;
45
+ send(message: WebsocketMessage, is_binary?: boolean, compress?: boolean): number | false;
40
46
  /**
41
47
  * Sends a ping control message.
42
- * Returns Boolean depending on backpressure similar to send().
43
- *
44
- * @param {String|Buffer|ArrayBuffer=} message
45
- * @returns {Boolean}
46
48
  */
47
- ping(message?: (string | Buffer | ArrayBuffer) | undefined): boolean;
49
+ ping(message?: WebsocketMessage): number | false;
48
50
  /**
49
- * Destroys this polyfill Websocket component and derefernces the underlying ws object
51
+ * Destroys this polyfill and dereferences the underlying socket.
50
52
  * @private
51
53
  */
52
- private _destroy;
54
+ _destroy(): void;
53
55
  /**
54
- * Gracefully closes websocket connection by sending specified code and short message.
55
- *
56
- * @param {Number=} code
57
- * @param {(String|Buffer|ArrayBuffer)=} message
56
+ * Gracefully closes the connection, sending an optional code and message.
58
57
  */
59
- close(code?: number | undefined, message?: (string | Buffer | ArrayBuffer) | undefined): void;
58
+ close(code?: number, message?: WebsocketMessage): void;
60
59
  /**
61
- * Forcefully closes websocket connection.
62
- * No websocket close code/message is sent.
63
- * This will immediately emit the 'close' event.
60
+ * Forcefully closes the connection without a close message.
64
61
  */
65
62
  destroy(): void;
66
63
  /**
67
- * Returns whether this `Websocket` is subscribed to the specified topic.
68
- *
69
- * @param {String} topic
70
- * @returns {Boolean}
64
+ * Returns whether this connection is subscribed to the topic.
71
65
  */
72
66
  is_subscribed(topic: string): boolean;
73
67
  /**
74
- * Subscribe to a topic in MQTT syntax.
75
- * MQTT syntax includes things like "root/child/+/grandchild" where "+" is a wildcard and "root/#" where "#" is a terminating wildcard.
76
- *
77
- * @param {String} topic
78
- * @returns {Boolean}
68
+ * Subscribes to a topic in mqtt syntax.
79
69
  */
80
70
  subscribe(topic: string): boolean;
81
71
  /**
82
- * Unsubscribe from a topic.
83
- * Returns true on success, if the WebSocket was subscribed.
84
- *
85
- * @param {String} topic
86
- * @returns {Boolean}
72
+ * Unsubscribes from a topic.
87
73
  */
88
74
  unsubscribe(topic: string): boolean;
89
75
  /**
90
- * Publish a message to a topic in MQTT syntax.
91
- * You cannot publish using wildcards, only fully specified topics.
92
- *
93
- * @param {String} topic
94
- * @param {String|Buffer|ArrayBuffer} message
95
- * @param {Boolean=} is_binary
96
- * @param {Boolean=} compress
76
+ * Publishes a message to a topic in mqtt syntax.
97
77
  */
98
- publish(topic: string, message: string | Buffer | ArrayBuffer, is_binary?: boolean | undefined, compress?: boolean | undefined): any;
78
+ publish(topic: string, message: WebsocketMessage, is_binary?: boolean, compress?: boolean): boolean;
99
79
  /**
100
- * Buffers the provided fragment and returns the last buffered fragment.
101
- *
102
- * @param {String|Buffer|ArrayBuffer} fragment
103
- * @returns {String|Buffer|ArrayBuffer|undefined}
80
+ * Buffers the provided fragment and returns the previously buffered one.
104
81
  */
105
- _buffer_fragment(fragment: string | Buffer | ArrayBuffer): string | Buffer | ArrayBuffer | undefined;
82
+ _buffer_fragment(fragment?: WebsocketMessage): WebsocketMessage | undefined;
106
83
  /**
107
- * Initiates fragment based message writing with uWS and writes appropriate chunk based on provided type parameter.
108
- *
109
- * @param {String} type
110
- * @param {String|Buffer|ArrayBuffer} chunk
111
- * @param {Boolean=} is_binary
112
- * @param {Boolean=} compress
113
- * @param {Function=} callback
114
- * @returns {Boolean}
84
+ * Writes a fragment using the appropriate uws fragment method.
115
85
  */
116
- _write(type: string, chunk: string | Buffer | ArrayBuffer, is_binary?: boolean | undefined, compress?: boolean | undefined, callback?: Function | undefined): boolean;
86
+ _write(type: Fragment, chunk: WebsocketMessage, is_binary?: boolean, compress?: boolean, callback?: () => void): number;
117
87
  /**
118
- * Streams the provided chunk while pausing the stream being consumed during backpressure.
119
- *
120
- * @param {Readable} stream
121
- * @param {String} type
122
- * @param {Buffer|ArrayBuffer} chunk
123
- * @param {Boolean} is_binary
88
+ * Streams a chunk, pausing the source stream while under backpressure.
124
89
  */
125
- _stream_chunk(stream: Readable, type: string, chunk: Buffer | ArrayBuffer, is_binary: boolean): void;
90
+ _stream_chunk(stream: Readable, type: Fragment, chunk: WebsocketMessage, is_binary: boolean): void;
126
91
  /**
127
- * This method is used to stream a message to the receiver.
128
- * Note! The data is by default streamed as Binary due to how partial fragments are sent.
129
- * This is done to prevent processing errors depending on client's receiver's incoming fragment processing strategy.
130
- *
131
- * @param {Readable} readable A Readable stream which will be consumed as message
132
- * @param {Boolean=} is_binary Whether data being streamed is in binary. Default: true
133
- * @returns {Promise}
92
+ * Streams a readable as a single fragmented message.
134
93
  */
135
- stream(readable: Readable, is_binary?: boolean | undefined): Promise<any>;
94
+ stream(readable: Readable, is_binary?: boolean): Promise<void>;
136
95
  /**
137
- * Underlying uWS.Websocket object
96
+ * Underlying uws websocket object.
138
97
  */
139
- get raw(): any;
98
+ get raw(): WebsocketRaw<TContext> | null;
140
99
  /**
141
- * Returns IP address of this websocket connection.
142
- * @returns {String}
100
+ * Remote ip address of this connection.
143
101
  */
144
102
  get ip(): string;
145
103
  /**
146
- * Returns context values from the response.update(context) connection upgrade call.
147
- * @returns {Object}
104
+ * Context values attached during the upgrade.
148
105
  */
149
- get context(): Object;
106
+ get context(): TContext;
150
107
  /**
151
- * Returns whether is websocket connection is closed.
152
- * @returns {Boolean}
108
+ * Whether this connection is closed.
153
109
  */
154
110
  get closed(): boolean;
155
111
  /**
156
- * Returns the bytes buffered in backpressure.
157
- * This is similar to the bufferedAmount property in the browser counterpart.
158
- * @returns {Number}
112
+ * Bytes currently buffered in backpressure.
159
113
  */
160
114
  get buffered(): number;
161
115
  /**
162
- * Returns a list of topics this websocket is subscribed to.
163
- * @returns {Array<String>}
116
+ * Topics this connection is subscribed to.
164
117
  */
165
- get topics(): Array<string>;
118
+ get topics(): string[];
166
119
  /**
167
- * Returns a Writable stream associated with this response to be used for piping streams.
168
- * Note! You can only retrieve/use only one writable at any given time.
169
- *
170
- * @returns {Writable}
120
+ * Writable stream bound to this connection for piping.
121
+ * Only one writable can be used at a time.
171
122
  */
172
123
  get writable(): Writable;
173
124
  }
125
+ export {};