@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.
Files changed (55) hide show
  1. package/README.md +10 -10
  2. package/dist/mqttPacket/BitMask.d.ts +14 -10
  3. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  4. package/dist/mqttPacket/BitMask.js +13 -0
  5. package/dist/mqttPacket/BitMask.js.map +1 -1
  6. package/dist/mqttPacket/PacketType.d.ts +6 -0
  7. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  8. package/dist/mqttPacket/PacketType.js +6 -0
  9. package/dist/mqttPacket/PacketType.js.map +1 -1
  10. package/dist/mqttPacket/decoder.d.ts +71 -0
  11. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  12. package/dist/mqttPacket/decoder.js +71 -0
  13. package/dist/mqttPacket/decoder.js.map +1 -1
  14. package/dist/mqttPacket/encoder.d.ts +52 -0
  15. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  16. package/dist/mqttPacket/encoder.js +52 -0
  17. package/dist/mqttPacket/encoder.js.map +1 -1
  18. package/dist/mqttPacket/length.d.ts +21 -0
  19. package/dist/mqttPacket/length.d.ts.map +1 -1
  20. package/dist/mqttPacket/length.js +18 -0
  21. package/dist/mqttPacket/length.js.map +1 -1
  22. package/dist/mqttPacket/mod.d.ts +30 -3
  23. package/dist/mqttPacket/mod.d.ts.map +1 -1
  24. package/dist/mqttPacket/mod.js +30 -3
  25. package/dist/mqttPacket/mod.js.map +1 -1
  26. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  27. package/dist/node/wrapNodeSocket.js +1 -0
  28. package/dist/node/wrapNodeSocket.js.map +1 -1
  29. package/dist/persistence/memory/memoryPersistence.d.ts +1 -3
  30. package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
  31. package/dist/persistence/memory/memoryPersistence.js +3 -3
  32. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  33. package/dist/persistence/mod.d.ts +9 -0
  34. package/dist/persistence/mod.d.ts.map +1 -0
  35. package/dist/persistence/mod.js +2 -0
  36. package/dist/persistence/mod.js.map +1 -0
  37. package/dist/persistence/persistence.d.ts +5 -0
  38. package/dist/persistence/persistence.d.ts.map +1 -1
  39. package/dist/persistence/persistence.js +5 -1
  40. package/dist/persistence/persistence.js.map +1 -1
  41. package/dist/socket/socket.d.ts +7 -2
  42. package/dist/socket/socket.d.ts.map +1 -1
  43. package/dist/socket/socket.js.map +1 -1
  44. package/mqttPacket/BitMask.ts +14 -1
  45. package/mqttPacket/PacketType.ts +6 -0
  46. package/mqttPacket/decoder.ts +73 -1
  47. package/mqttPacket/encoder.ts +52 -0
  48. package/mqttPacket/length.ts +21 -0
  49. package/mqttPacket/mod.ts +31 -3
  50. package/node/wrapNodeSocket.ts +3 -2
  51. package/package.json +5 -3
  52. package/persistence/memory/memoryPersistence.ts +15 -16
  53. package/persistence/mod.ts +20 -0
  54. package/persistence/persistence.ts +5 -0
  55. package/socket/socket.ts +8 -2
@@ -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
  }
@@ -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
- * This module provides the encoding and decoding of MQTT packets
3
- * it is used by the server and client modules
4
- * @module
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");
@@ -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.8.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
- "./persistence": "./dist/persistence/persistence.js",
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
- "./persistence": "./persistence/persistence.ts",
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
- } from "../persistence.ts";
17
- import type { IStore, PacketStore, SubscriptionStore } from "../store.ts";
18
- import { assert } from "../../utils/mod.ts";
12
+ SubscriptionStore,
13
+ Topic,
14
+ TopicFilter,
15
+ } from "../mod.ts";
19
16
 
20
- const maxPacketId = 0xffff;
21
- // const maxQueueLength = 0xffff;
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 | undefined;
1
+ export type SockAddr = NetAddr | UnixAddr | VsockAddr;
2
2
  export interface NetAddr {
3
- transport?: "tcp" | "udp";
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>;