@seriousme/opifex 1.8.1 → 1.9.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 +10 -10
- package/dist/mqttPacket/BitMask.d.ts +14 -10
- package/dist/mqttPacket/BitMask.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.js +13 -0
- package/dist/mqttPacket/BitMask.js.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts +6 -0
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/PacketType.js +6 -0
- package/dist/mqttPacket/PacketType.js.map +1 -1
- package/dist/mqttPacket/decoder.d.ts +71 -0
- package/dist/mqttPacket/decoder.d.ts.map +1 -1
- package/dist/mqttPacket/decoder.js +71 -0
- package/dist/mqttPacket/decoder.js.map +1 -1
- package/dist/mqttPacket/encoder.d.ts +52 -0
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +52 -0
- package/dist/mqttPacket/encoder.js.map +1 -1
- package/dist/mqttPacket/length.d.ts +21 -0
- package/dist/mqttPacket/length.d.ts.map +1 -1
- package/dist/mqttPacket/length.js +18 -0
- package/dist/mqttPacket/length.js.map +1 -1
- package/dist/mqttPacket/mod.d.ts +30 -3
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +30 -3
- package/dist/mqttPacket/mod.js.map +1 -1
- package/dist/node/wrapNodeSocket.d.ts.map +1 -1
- package/dist/node/wrapNodeSocket.js +1 -0
- package/dist/node/wrapNodeSocket.js.map +1 -1
- package/dist/persistence/memory/memoryPersistence.d.ts +1 -3
- package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
- package/dist/persistence/memory/memoryPersistence.js +3 -3
- package/dist/persistence/memory/memoryPersistence.js.map +1 -1
- package/dist/persistence/mod.d.ts +9 -0
- package/dist/persistence/mod.d.ts.map +1 -0
- package/dist/persistence/mod.js +2 -0
- package/dist/persistence/mod.js.map +1 -0
- package/dist/persistence/persistence.d.ts +5 -0
- package/dist/persistence/persistence.d.ts.map +1 -1
- package/dist/persistence/persistence.js +5 -1
- package/dist/persistence/persistence.js.map +1 -1
- package/dist/socket/socket.d.ts +7 -2
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js.map +1 -1
- package/mqttPacket/BitMask.ts +14 -1
- package/mqttPacket/PacketType.ts +6 -0
- package/mqttPacket/decoder.ts +73 -1
- package/mqttPacket/encoder.ts +52 -0
- package/mqttPacket/length.ts +21 -0
- package/mqttPacket/mod.ts +31 -3
- package/node/wrapNodeSocket.ts +3 -2
- package/package.json +5 -3
- package/persistence/memory/memoryPersistence.ts +15 -16
- package/persistence/mod.ts +20 -0
- package/persistence/persistence.ts +5 -0
- package/socket/socket.ts +8 -2
package/mqttPacket/encoder.ts
CHANGED
|
@@ -2,6 +2,9 @@ const utf8Encoder = new TextEncoder();
|
|
|
2
2
|
import type { Topic, TopicFilter } from "./types.ts";
|
|
3
3
|
import { invalidTopic, invalidTopicFilter } from "./validators.ts";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Custom error class for encoding operations
|
|
7
|
+
*/
|
|
5
8
|
export class EncoderError extends Error {
|
|
6
9
|
constructor(message: string) {
|
|
7
10
|
super(message);
|
|
@@ -9,24 +12,47 @@ export class EncoderError extends Error {
|
|
|
9
12
|
}
|
|
10
13
|
}
|
|
11
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Encoder class for MQTT packet encoding
|
|
17
|
+
*/
|
|
12
18
|
export class Encoder {
|
|
19
|
+
/** Internal buffer to store encoded bytes */
|
|
13
20
|
private buffer: number[];
|
|
14
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new Encoder instance
|
|
24
|
+
*/
|
|
15
25
|
constructor() {
|
|
16
26
|
this.buffer = [];
|
|
17
27
|
}
|
|
18
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Adds a single byte to the buffer
|
|
31
|
+
* @param value - Byte value to add (0-255)
|
|
32
|
+
* @returns The encoder instance for chaining
|
|
33
|
+
*/
|
|
19
34
|
setByte(value: number): this {
|
|
20
35
|
this.buffer.push(value);
|
|
21
36
|
return this;
|
|
22
37
|
}
|
|
23
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Adds a 16-bit integer to the buffer in big-endian format
|
|
41
|
+
* @param value - 16-bit integer value to add
|
|
42
|
+
* @returns The encoder instance for chaining
|
|
43
|
+
*/
|
|
24
44
|
setInt16(value: number): this {
|
|
25
45
|
this.setByte(value >> 8);
|
|
26
46
|
this.setByte(value & 0xff);
|
|
27
47
|
return this;
|
|
28
48
|
}
|
|
29
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Adds a byte array to the buffer with length prefix
|
|
52
|
+
* @param value - Byte array to add
|
|
53
|
+
* @throws {EncoderError} If array length exceeds 0xffff bytes
|
|
54
|
+
* @returns The encoder instance for chaining
|
|
55
|
+
*/
|
|
30
56
|
setByteArray(value: Uint8Array): this {
|
|
31
57
|
if (value.length > 0xffff) {
|
|
32
58
|
throw new EncoderError("More than 0xffff bytes of data");
|
|
@@ -36,11 +62,22 @@ export class Encoder {
|
|
|
36
62
|
return this;
|
|
37
63
|
}
|
|
38
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Adds a UTF-8 encoded string to the buffer with length prefix
|
|
67
|
+
* @param value - String to encode and add
|
|
68
|
+
* @returns The encoder instance for chaining
|
|
69
|
+
*/
|
|
39
70
|
setUtf8String(value: string): this {
|
|
40
71
|
this.setByteArray(utf8Encoder.encode(value));
|
|
41
72
|
return this;
|
|
42
73
|
}
|
|
43
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Adds an MQTT topic string to the buffer
|
|
77
|
+
* @param value - Topic string to add
|
|
78
|
+
* @throws {EncoderError} If topic is invalid
|
|
79
|
+
* @returns The encoder instance for chaining
|
|
80
|
+
*/
|
|
44
81
|
setTopic(value: Topic): this {
|
|
45
82
|
if (invalidTopic(value)) {
|
|
46
83
|
throw new EncoderError(
|
|
@@ -51,6 +88,12 @@ export class Encoder {
|
|
|
51
88
|
return this;
|
|
52
89
|
}
|
|
53
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Adds an MQTT topic filter string to the buffer
|
|
93
|
+
* @param value - Topic filter string to add
|
|
94
|
+
* @throws {EncoderError} If topic filter is invalid
|
|
95
|
+
* @returns The encoder instance for chaining
|
|
96
|
+
*/
|
|
54
97
|
setTopicFilter(value: TopicFilter): this {
|
|
55
98
|
if (invalidTopicFilter(value)) {
|
|
56
99
|
throw new EncoderError(
|
|
@@ -61,11 +104,20 @@ export class Encoder {
|
|
|
61
104
|
return this;
|
|
62
105
|
}
|
|
63
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Adds remaining bytes to the buffer without modification
|
|
109
|
+
* @param value - Array of bytes to add
|
|
110
|
+
* @returns The encoder instance for chaining
|
|
111
|
+
*/
|
|
64
112
|
setRemainder(value: Uint8Array | number[]): this {
|
|
65
113
|
this.buffer.push(...value);
|
|
66
114
|
return this;
|
|
67
115
|
}
|
|
68
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Returns the final encoded buffer
|
|
119
|
+
* @returns Array containing all encoded bytes
|
|
120
|
+
*/
|
|
69
121
|
done(): number[] {
|
|
70
122
|
return this.buffer;
|
|
71
123
|
}
|
package/mqttPacket/length.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encodes a number into a variable-length byte array using a modified base-128 encoding
|
|
3
|
+
* @param n The number to encode
|
|
4
|
+
* @returns Array of bytes representing the encoded number
|
|
5
|
+
* @throws Error if the encoded length is greater than 4 bytes
|
|
6
|
+
*/
|
|
1
7
|
export function encodeLength(n: number): number[] {
|
|
2
8
|
const output = [];
|
|
3
9
|
let x = n;
|
|
@@ -15,6 +21,13 @@ export function encodeLength(n: number): number[] {
|
|
|
15
21
|
return output;
|
|
16
22
|
}
|
|
17
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Decodes a variable-length encoded number from a byte array
|
|
26
|
+
* @param buf The byte array containing the encoded number
|
|
27
|
+
* @param start The starting position in the buffer to begin decoding
|
|
28
|
+
* @returns Object containing the decoded length and number of bytes used for encoding
|
|
29
|
+
* @throws Error if decoding fails
|
|
30
|
+
*/
|
|
18
31
|
export function decodeLength(
|
|
19
32
|
buf: Uint8Array,
|
|
20
33
|
start: number,
|
|
@@ -30,12 +43,20 @@ export function decodeLength(
|
|
|
30
43
|
throw Error("length decoding failed");
|
|
31
44
|
}
|
|
32
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Interface for the result returned by the length decoder
|
|
48
|
+
*/
|
|
33
49
|
export type LengthDecoderResult = {
|
|
34
50
|
done: boolean;
|
|
35
51
|
length: number;
|
|
36
52
|
numLengthBytes: number;
|
|
37
53
|
};
|
|
38
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Creates a stateful decoder function for processing variable-length encoded numbers
|
|
57
|
+
* @returns Function that processes one byte at a time and returns decoding status
|
|
58
|
+
* @throws Error if the encoded length is greater than 4 bytes
|
|
59
|
+
*/
|
|
39
60
|
export function getLengthDecoder(): (
|
|
40
61
|
encodedByte: number,
|
|
41
62
|
) => LengthDecoderResult {
|
package/mqttPacket/mod.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @module MQTT Packet Encoding/Decoding
|
|
3
|
+
* @description This module provides comprehensive encoding and decoding functionality for MQTT packets
|
|
4
|
+
* used in both server and client implementations. It handles all MQTT packet types and their
|
|
5
|
+
* transformations between binary and object representations.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import type {
|
|
@@ -99,6 +100,10 @@ export {
|
|
|
99
100
|
PacketType,
|
|
100
101
|
};
|
|
101
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Array mapping MQTT packet types to their corresponding encode/decode handlers
|
|
105
|
+
* Index corresponds to packet type number.
|
|
106
|
+
*/
|
|
102
107
|
export const packetsByType = [
|
|
103
108
|
null,
|
|
104
109
|
connect, // 1
|
|
@@ -117,6 +122,13 @@ export const packetsByType = [
|
|
|
117
122
|
disconnect, // 14
|
|
118
123
|
] as const;
|
|
119
124
|
|
|
125
|
+
/**
|
|
126
|
+
* @function encode
|
|
127
|
+
* @description Encodes an MQTT packet object into a binary Uint8Array format
|
|
128
|
+
* @param {AnyPacket} packet - The MQTT packet object to encode
|
|
129
|
+
* @returns {Uint8Array} The encoded packet as a binary buffer
|
|
130
|
+
* @throws {Error} If packet encoding fails
|
|
131
|
+
*/
|
|
120
132
|
export function encode(packet: AnyPacket): Uint8Array {
|
|
121
133
|
const packetType: number = packet.type;
|
|
122
134
|
// deno-lint-ignore no-explicit-any
|
|
@@ -133,6 +145,15 @@ export function encode(packet: AnyPacket): Uint8Array {
|
|
|
133
145
|
]);
|
|
134
146
|
}
|
|
135
147
|
|
|
148
|
+
/**
|
|
149
|
+
* @function decodePayload
|
|
150
|
+
* @description Decodes a packet payload from binary format into an MQTT packet object
|
|
151
|
+
* @param {number} firstByte - The first byte of the MQTT packet containing type and flags
|
|
152
|
+
* @param {Uint8Array} buffer - The binary buffer containing the packet payload
|
|
153
|
+
* @returns {AnyPacket} The decoded MQTT packet object
|
|
154
|
+
* @throws {Error} If packet decoding fails
|
|
155
|
+
*/
|
|
156
|
+
|
|
136
157
|
export function decodePayload(
|
|
137
158
|
firstByte: number,
|
|
138
159
|
buffer: Uint8Array,
|
|
@@ -146,6 +167,13 @@ export function decodePayload(
|
|
|
146
167
|
throw new Error("packet decoding failed");
|
|
147
168
|
}
|
|
148
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @function decode
|
|
172
|
+
* @description Decodes a complete MQTT packet from binary format into a packet object
|
|
173
|
+
* @param {Uint8Array} buffer - The binary buffer containing the complete MQTT packet
|
|
174
|
+
* @returns {AnyPacket} The decoded MQTT packet object
|
|
175
|
+
* @throws {DecoderError} If packet decoding fails due to invalid format or insufficient data
|
|
176
|
+
*/
|
|
149
177
|
export function decode(buffer: Uint8Array): AnyPacket {
|
|
150
178
|
if (buffer.length < 2) {
|
|
151
179
|
throw new DecoderError("Packet decoding failed");
|
package/node/wrapNodeSocket.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { Socket } from "node:net";
|
|
5
5
|
import { Writable } from "node:stream";
|
|
6
|
-
import type { SockConn } from "../socket/socket.ts";
|
|
6
|
+
import type { NetAddr, SockConn } from "../socket/socket.ts";
|
|
7
7
|
/**
|
|
8
8
|
* Closes a Node.js socket if it is not already closed
|
|
9
9
|
* @param sock - The Node.js socket to close
|
|
@@ -50,9 +50,10 @@ export function wrapNodeSocket(socket: Socket): SockConn {
|
|
|
50
50
|
},
|
|
51
51
|
);
|
|
52
52
|
const writable = Writable.toWeb(socket);
|
|
53
|
-
const remoteAddr = {
|
|
53
|
+
const remoteAddr: NetAddr = {
|
|
54
54
|
hostname: socket.remoteAddress || "",
|
|
55
55
|
port: socket.remotePort || 0,
|
|
56
|
+
transport: "tcp",
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
const conn: SockConn = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seriousme/opifex",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "MQTT client & server for Deno & NodeJS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"./tcpServer": "./dist/node/tcpServer.js",
|
|
37
37
|
"./server": "./dist/server/mod.js",
|
|
38
38
|
"./client": "./dist/client/mod.js",
|
|
39
|
-
"./
|
|
39
|
+
"./trie": "./dist/trie/trie.js",
|
|
40
|
+
"./persistence": "./dist/persistence/mod.js",
|
|
40
41
|
"./mqttConn": "./dist/mqttConn/mqttConn.js",
|
|
41
42
|
"./mqttPacket": "./dist/mqttPacket/mod.js",
|
|
42
43
|
"./utils": "./dist/utils/mod.js"
|
|
@@ -47,7 +48,8 @@
|
|
|
47
48
|
"./tcpServer": "./deno/tcpServer.ts",
|
|
48
49
|
"./server": "./server/mod.ts",
|
|
49
50
|
"./client": "./client/mod.ts",
|
|
50
|
-
"./
|
|
51
|
+
"./trie": "./trie/trie.ts",
|
|
52
|
+
"./persistence": "./persistence/mod.ts",
|
|
51
53
|
"./mqttConn": "./mqttConn/mqttConn.ts",
|
|
52
54
|
"./mqttPacket": "./mqttPacket/mod.ts",
|
|
53
55
|
"./utils": "./utils/mod.ts"
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ClientId,
|
|
3
|
-
type PacketId,
|
|
4
|
-
type PublishPacket,
|
|
5
|
-
type QoS,
|
|
6
|
-
type Topic,
|
|
7
|
-
type TopicFilter,
|
|
8
|
-
Trie,
|
|
9
|
-
} from "../deps.ts";
|
|
10
|
-
|
|
11
1
|
import type {
|
|
12
2
|
Client,
|
|
3
|
+
ClientId,
|
|
13
4
|
Handler,
|
|
14
5
|
IPersistence,
|
|
6
|
+
IStore,
|
|
7
|
+
PacketId,
|
|
8
|
+
PacketStore,
|
|
9
|
+
PublishPacket,
|
|
10
|
+
QoS,
|
|
15
11
|
RetainStore,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
SubscriptionStore,
|
|
13
|
+
Topic,
|
|
14
|
+
TopicFilter,
|
|
15
|
+
} from "../mod.ts";
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
import { maxPacketId } from "../mod.ts";
|
|
18
|
+
|
|
19
|
+
import { Trie } from "../deps.ts";
|
|
20
|
+
import { assert } from "../../utils/mod.ts";
|
|
22
21
|
|
|
23
22
|
type ClientSubscription = {
|
|
24
23
|
clientId: ClientId;
|
|
@@ -99,7 +98,7 @@ export class MemoryPersistence implements IPersistence {
|
|
|
99
98
|
unsubscribe(store: IStore, topicFilter: TopicFilter): void {
|
|
100
99
|
const clientId = store.clientId;
|
|
101
100
|
const qos = store.subscriptions.get(topicFilter);
|
|
102
|
-
if (qos) {
|
|
101
|
+
if (qos !== undefined) {
|
|
103
102
|
store.subscriptions.delete(topicFilter);
|
|
104
103
|
this.trie.remove(topicFilter, { clientId, qos });
|
|
105
104
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module persistence
|
|
3
|
+
* @description Module for handling MQTT message persistence and client management
|
|
4
|
+
*/
|
|
5
|
+
export type { IStore, PacketStore, SubscriptionStore } from "./store.ts";
|
|
6
|
+
export type {
|
|
7
|
+
ClientId,
|
|
8
|
+
PacketId,
|
|
9
|
+
PublishPacket,
|
|
10
|
+
QoS,
|
|
11
|
+
Topic,
|
|
12
|
+
TopicFilter,
|
|
13
|
+
} from "./deps.ts";
|
|
14
|
+
export type {
|
|
15
|
+
Client,
|
|
16
|
+
Handler,
|
|
17
|
+
IPersistence,
|
|
18
|
+
RetainStore,
|
|
19
|
+
} from "./persistence.ts";
|
|
20
|
+
export { maxPacketId } from "./persistence.ts";
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
import type { ClientId, PublishPacket, QoS, Topic } from "./deps.ts";
|
|
6
6
|
import type { IStore } from "./store.ts";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Maximum packet ID value for MQTT messages (0xffff/65535)
|
|
10
|
+
* @constant {number}
|
|
11
|
+
*/
|
|
12
|
+
export const maxPacketId = 0xffff;
|
|
8
13
|
/**
|
|
9
14
|
* Handler function type for processing publish packets
|
|
10
15
|
* @callback Handler
|
package/socket/socket.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export type SockAddr = NetAddr | UnixAddr |
|
|
1
|
+
export type SockAddr = NetAddr | UnixAddr | VsockAddr;
|
|
2
2
|
export interface NetAddr {
|
|
3
|
-
transport
|
|
3
|
+
transport: "tcp" | "udp";
|
|
4
4
|
hostname: string;
|
|
5
5
|
port: number;
|
|
6
6
|
}
|
|
@@ -10,6 +10,12 @@ export interface UnixAddr {
|
|
|
10
10
|
path: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export interface VsockAddr {
|
|
14
|
+
transport: "vsock";
|
|
15
|
+
cid: number;
|
|
16
|
+
port: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export type SockConn = {
|
|
14
20
|
readable: ReadableStream<Uint8Array>;
|
|
15
21
|
writable: WritableStream<Uint8Array>;
|