@seriousme/opifex 1.6.2 → 1.7.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 (128) hide show
  1. package/README.md +6 -7
  2. package/bin/conformanceServer.ts +67 -16
  3. package/bin/demoServer.ts +69 -14
  4. package/bin/mqtt.ts +30 -0
  5. package/client/ConnectionState.ts +12 -0
  6. package/client/client.ts +56 -2
  7. package/client/context.ts +5 -0
  8. package/client/handlers/handleConnack.ts +6 -0
  9. package/client/handlers/handlePacket.ts +7 -0
  10. package/client/handlers/handlePuback.ts +8 -2
  11. package/client/handlers/handlePubcomp.ts +10 -4
  12. package/client/handlers/handlePublish.ts +6 -2
  13. package/client/handlers/handlePubrec.ts +13 -6
  14. package/client/handlers/handlePubrel.ts +16 -6
  15. package/client/handlers/handleSuback.ts +9 -6
  16. package/client/handlers/handleUnsuback.ts +10 -3
  17. package/client/store/memoryStore.ts +25 -0
  18. package/client/store/store.ts +39 -0
  19. package/deno/tcpServer.test.ts +137 -2
  20. package/node/tcpServer.test.ts +61 -6
  21. package/node/tcpServer.ts +9 -2
  22. package/node/wrapNodeSocket.ts +13 -2
  23. package/package.json +13 -3
  24. package/persistence/memory/memoryPersistence.test.ts +2 -1
  25. package/persistence/memory/memoryPersistence.ts +1 -0
  26. package/persistence/store.ts +1 -0
  27. package/server/handlers/handleConnect.ts +49 -6
  28. package/server/handlers/handleDisconnect.ts +5 -0
  29. package/server/handlers/handlePacket.ts +7 -0
  30. package/server/handlers/handlePingreq.ts +6 -0
  31. package/server/handlers/handlePuback.ts +9 -2
  32. package/server/handlers/handlePubcomp.ts +8 -3
  33. package/server/handlers/handlePublish.ts +13 -0
  34. package/server/handlers/handlePubrec.ts +11 -3
  35. package/server/handlers/handlePubrel.ts +12 -4
  36. package/server/handlers/handleSubscribe.ts +28 -5
  37. package/server/handlers/handleUnsubscribe.ts +6 -0
  38. package/utils/asyncQueue.ts +2 -1
  39. package/utils/nextTick.ts +13 -1
  40. package/.github/workflows/closeStale.yml +0 -15
  41. package/.github/workflows/codeql-analysis.yml +0 -71
  42. package/.github/workflows/deno-ci.yml +0 -16
  43. package/.github/workflows/nodejs-ci.yml +0 -23
  44. package/.github/workflows/publish.yml +0 -16
  45. package/.github/workflows/update-license-year.sh +0 -14
  46. package/.github/workflows/update-license-year.yml +0 -13
  47. package/CHANGELOG.md +0 -74
  48. package/deno.json +0 -15
  49. package/deno.lock +0 -34
  50. package/dist/bin/conformanceServer.js +0 -51
  51. package/dist/bin/demoServer.js +0 -46
  52. package/dist/bin/mqtt.js +0 -227
  53. package/dist/client/ConnectionState.js +0 -7
  54. package/dist/client/client.js +0 -132
  55. package/dist/client/context.js +0 -148
  56. package/dist/client/deps.js +0 -5
  57. package/dist/client/handlers/handleConnack.js +0 -18
  58. package/dist/client/handlers/handlePacket.js +0 -50
  59. package/dist/client/handlers/handlePuback.js +0 -6
  60. package/dist/client/handlers/handlePubcomp.js +0 -9
  61. package/dist/client/handlers/handlePublish.js +0 -28
  62. package/dist/client/handlers/handlePubrec.js +0 -17
  63. package/dist/client/handlers/handlePubrel.js +0 -19
  64. package/dist/client/handlers/handleSuback.js +0 -9
  65. package/dist/client/handlers/handleUnsuback.js +0 -7
  66. package/dist/client/mod.js +0 -5
  67. package/dist/client/store/deps.js +0 -1
  68. package/dist/client/store/memoryStore.js +0 -36
  69. package/dist/client/store/store.js +0 -1
  70. package/dist/mqttConn/mqttConn.js +0 -104
  71. package/dist/mqttPacket/AuthenticationResult.js +0 -16
  72. package/dist/mqttPacket/BitMask.js +0 -10
  73. package/dist/mqttPacket/PacketType.js +0 -18
  74. package/dist/mqttPacket/connack.js +0 -27
  75. package/dist/mqttPacket/connect.js +0 -115
  76. package/dist/mqttPacket/decoder.js +0 -89
  77. package/dist/mqttPacket/disconnect.js +0 -14
  78. package/dist/mqttPacket/encoder.js +0 -56
  79. package/dist/mqttPacket/length.js +0 -43
  80. package/dist/mqttPacket/mod.js +0 -76
  81. package/dist/mqttPacket/pingreq.js +0 -15
  82. package/dist/mqttPacket/pingres.js +0 -14
  83. package/dist/mqttPacket/puback.js +0 -20
  84. package/dist/mqttPacket/pubcomp.js +0 -20
  85. package/dist/mqttPacket/publish.js +0 -51
  86. package/dist/mqttPacket/pubrec.js +0 -20
  87. package/dist/mqttPacket/pubrel.js +0 -20
  88. package/dist/mqttPacket/suback.js +0 -29
  89. package/dist/mqttPacket/subscribe.js +0 -52
  90. package/dist/mqttPacket/types.js +0 -1
  91. package/dist/mqttPacket/unsuback.js +0 -20
  92. package/dist/mqttPacket/unsubscribe.js +0 -36
  93. package/dist/mqttPacket/validators.js +0 -15
  94. package/dist/node/tcpClient.js +0 -81
  95. package/dist/node/tcpServer.js +0 -43
  96. package/dist/node/wrapNodeSocket.js +0 -47
  97. package/dist/persistence/deps.js +0 -3
  98. package/dist/persistence/memory/memoryPersistence.js +0 -117
  99. package/dist/persistence/persistence.js +0 -1
  100. package/dist/persistence/store.js +0 -1
  101. package/dist/server/context.js +0 -100
  102. package/dist/server/deps.js +0 -5
  103. package/dist/server/handlers/handleConnect.js +0 -46
  104. package/dist/server/handlers/handleDisconnect.js +0 -4
  105. package/dist/server/handlers/handlePacket.js +0 -58
  106. package/dist/server/handlers/handlePingreq.js +0 -6
  107. package/dist/server/handlers/handlePuback.js +0 -8
  108. package/dist/server/handlers/handlePubcomp.js +0 -8
  109. package/dist/server/handlers/handlePublish.js +0 -41
  110. package/dist/server/handlers/handlePubrec.js +0 -15
  111. package/dist/server/handlers/handlePubrel.js +0 -18
  112. package/dist/server/handlers/handleSubscribe.js +0 -33
  113. package/dist/server/handlers/handleUnsubscribe.js +0 -12
  114. package/dist/server/mod.js +0 -7
  115. package/dist/server/server.js +0 -47
  116. package/dist/socket/socket.js +0 -36
  117. package/dist/timer/timer.js +0 -40
  118. package/dist/trie/trie.js +0 -95
  119. package/dist/tsconfig.tsbuildinfo +0 -1
  120. package/dist/utils/args.js +0 -75
  121. package/dist/utils/assert.js +0 -20
  122. package/dist/utils/asyncQueue.js +0 -67
  123. package/dist/utils/deferred.js +0 -14
  124. package/dist/utils/logger.js +0 -58
  125. package/dist/utils/mod.js +0 -11
  126. package/dist/utils/nextTick.js +0 -6
  127. package/dist/utils/platform.js +0 -7
  128. package/tsconfig.json +0 -22
@@ -1,46 +0,0 @@
1
- import { AuthenticationResult, logger, PacketType, Timer, } from "../deps.js";
2
- function isAuthenticated(ctx, packet) {
3
- if (ctx.handlers.isAuthenticated) {
4
- return ctx.handlers.isAuthenticated(ctx, packet.clientId || "", packet.username || "", packet.password || new Uint8Array(0));
5
- }
6
- return AuthenticationResult.ok;
7
- }
8
- function validateConnect(ctx, packet) {
9
- if (packet.protocolLevel !== 4) {
10
- return AuthenticationResult.unacceptableProtocol;
11
- }
12
- return isAuthenticated(ctx, packet);
13
- }
14
- export function handleConnect(ctx, packet) {
15
- const clientId = packet.clientId || `Opifex-${crypto.randomUUID()}`;
16
- const returnCode = validateConnect(ctx, packet);
17
- // connect is ok
18
- if (returnCode === AuthenticationResult.ok) {
19
- if (packet.will) {
20
- ctx.will = {
21
- type: PacketType.publish,
22
- qos: packet.will.qos,
23
- retain: packet.will.retain,
24
- topic: packet.will.topic,
25
- payload: packet.will.payload,
26
- };
27
- }
28
- ctx.connect(clientId, packet.clean || false);
29
- const keepAlive = packet.keepAlive || 0;
30
- if (keepAlive > 0) {
31
- logger.debug(`Setting keepalive to ${keepAlive * 1500} ms`);
32
- ctx.timer = new Timer(() => {
33
- ctx.close();
34
- }, Math.floor(keepAlive * 1500));
35
- }
36
- }
37
- const sessionPresent = false;
38
- ctx.send({
39
- type: PacketType.connack,
40
- sessionPresent,
41
- returnCode,
42
- });
43
- if (returnCode !== AuthenticationResult.ok) {
44
- ctx.close();
45
- }
46
- }
@@ -1,4 +0,0 @@
1
- export function handleDisconnect(ctx) {
2
- ctx.will = undefined;
3
- ctx.close();
4
- }
@@ -1,58 +0,0 @@
1
- import { PacketNameByType, PacketType, } from "../deps.js";
2
- import { handleConnect } from "./handleConnect.js";
3
- import { handlePingreq } from "./handlePingreq.js";
4
- import { handlePublish } from "./handlePublish.js";
5
- import { handlePuback } from "./handlePuback.js";
6
- import { handlePubrec } from "./handlePubrec.js";
7
- import { handlePubrel } from "./handlePubrel.js";
8
- import { handlePubcomp } from "./handlePubcomp.js";
9
- import { handleSubscribe } from "./handleSubscribe.js";
10
- import { handleUnsubscribe } from "./handleUnsubscribe.js";
11
- import { handleDisconnect } from "./handleDisconnect.js";
12
- import { logger } from "../deps.js";
13
- export async function handlePacket(ctx, packet) {
14
- logger.debug("handling", PacketNameByType[packet.type]);
15
- logger.debug(JSON.stringify(packet, null, 2));
16
- if (!ctx.connected) {
17
- if (packet.type === PacketType.connect) {
18
- handleConnect(ctx, packet);
19
- }
20
- else {
21
- throw new Error(`Received ${PacketNameByType[packet.type]} packet before connect`);
22
- }
23
- }
24
- else {
25
- switch (packet.type) {
26
- case PacketType.pingreq:
27
- await handlePingreq(ctx);
28
- break;
29
- case PacketType.publish:
30
- await handlePublish(ctx, packet);
31
- break;
32
- case PacketType.puback:
33
- handlePuback(ctx, packet);
34
- break;
35
- case PacketType.pubrel:
36
- await handlePubrel(ctx, packet);
37
- break;
38
- case PacketType.pubrec:
39
- await handlePubrec(ctx, packet);
40
- break;
41
- case PacketType.pubcomp:
42
- handlePubcomp(ctx, packet);
43
- break;
44
- case PacketType.subscribe:
45
- await handleSubscribe(ctx, packet);
46
- break;
47
- case PacketType.unsubscribe:
48
- await handleUnsubscribe(ctx, packet);
49
- break;
50
- case PacketType.disconnect:
51
- handleDisconnect(ctx);
52
- break;
53
- default:
54
- throw new Error(`Received unexpected ${PacketNameByType[packet.type]} packet after connect`);
55
- }
56
- ctx.timer?.reset();
57
- }
58
- }
@@ -1,6 +0,0 @@
1
- import { PacketType } from "../deps.js";
2
- export async function handlePingreq(ctx) {
3
- await ctx.send({
4
- type: PacketType.pingres,
5
- });
6
- }
@@ -1,8 +0,0 @@
1
- // A PUBACK Packet is the response to a PUBLISH Packet with QoS level 1.
2
- export function handlePuback(ctx, packet) {
3
- // qos 1 only
4
- const id = packet.id;
5
- if (ctx.store?.pendingOutgoing.has(id)) {
6
- ctx.store.pendingOutgoing.delete(id);
7
- }
8
- }
@@ -1,8 +0,0 @@
1
- // The PUBCOMP Packet is the response to a PUBREL Packet.
2
- // It is the fourth and final packet of the QoS 2 protocol exchange.
3
- export function handlePubcomp(ctx, packet) {
4
- const id = packet.id;
5
- if (ctx.store?.pendingAckOutgoing.has(id)) {
6
- ctx.store.pendingAckOutgoing.delete(id);
7
- }
8
- }
@@ -1,41 +0,0 @@
1
- import { SysPrefix } from "../context.js";
2
- import { PacketType } from "../deps.js";
3
- function authorizedToPublish(ctx, topic) {
4
- if (topic.startsWith(SysPrefix)) {
5
- return false;
6
- }
7
- if (ctx.handlers.isAuthorizedToPublish) {
8
- return ctx.handlers.isAuthorizedToPublish(ctx, topic);
9
- }
10
- return true;
11
- }
12
- export async function handlePublish(ctx, packet) {
13
- if (!authorizedToPublish(ctx, packet.topic)) {
14
- return;
15
- }
16
- const qos = packet.qos || 0;
17
- if (qos === 0) {
18
- ctx.persistence.publish(packet.topic, packet);
19
- return;
20
- }
21
- if (packet.id !== undefined) {
22
- // qos 1
23
- if (qos === 1) {
24
- const id = packet.id; // retain the id
25
- ctx.persistence.publish(packet.topic, packet);
26
- await ctx.send({
27
- type: PacketType.puback,
28
- id,
29
- });
30
- return;
31
- }
32
- // qos 2
33
- if (ctx.store) {
34
- ctx.store.pendingIncoming.set(packet.id, packet);
35
- await ctx.send({
36
- type: PacketType.pubrec,
37
- id: packet.id,
38
- });
39
- }
40
- }
41
- }
@@ -1,15 +0,0 @@
1
- import { PacketType } from "../deps.js";
2
- // qos 2
3
- // Discard message, Store PUBREC received <Packet Identifier>
4
- // send PUBREL <Packet Identifier>
5
- export async function handlePubrec(ctx, packet) {
6
- const id = packet.id;
7
- if (ctx.store?.pendingOutgoing.has(id)) {
8
- ctx.store.pendingOutgoing.delete(id);
9
- ctx.store.pendingAckOutgoing.add(id);
10
- await ctx.send({
11
- type: PacketType.pubrel,
12
- id,
13
- });
14
- }
15
- }
@@ -1,18 +0,0 @@
1
- import { PacketType } from "../deps.js";
2
- // qos 2 only
3
- // Method A, Initiate onward delivery of the Application Message1 then discard message
4
- // Send PUBCOMP <Packet Identifier>
5
- export async function handlePubrel(ctx, packet) {
6
- const id = packet.id;
7
- if (ctx.store?.pendingIncoming.has(id)) {
8
- const storedPacket = ctx.store.pendingIncoming.get(id);
9
- if (storedPacket) {
10
- ctx.persistence.publish(storedPacket.topic, storedPacket);
11
- ctx.store.pendingIncoming.delete(id);
12
- await ctx.send({
13
- type: PacketType.pubcomp,
14
- id,
15
- });
16
- }
17
- }
18
- }
@@ -1,33 +0,0 @@
1
- import { PacketType, } from "../deps.js";
2
- const SubscriptionFailure = 0x80;
3
- function authorizedToSubscribe(ctx, topicFilter) {
4
- if (ctx.handlers.isAuthorizedToSubscribe) {
5
- return ctx.handlers.isAuthorizedToSubscribe(ctx, topicFilter);
6
- }
7
- return true;
8
- }
9
- export async function handleSubscribe(ctx, packet) {
10
- // The order of return codes in the SUBACK Packet MUST match the order of
11
- // Topic Filters in the SUBSCRIBE Packet [MQTT-3.9.3-1].
12
- const validSubscriptions = [];
13
- const returnCodes = packet.subscriptions.map((sub) => {
14
- if (ctx.store) {
15
- if (!authorizedToSubscribe(ctx, sub.topicFilter)) {
16
- return SubscriptionFailure;
17
- }
18
- ctx.persistence.subscribe(ctx.store, sub.topicFilter, sub.qos);
19
- validSubscriptions.push(sub);
20
- return sub.qos;
21
- }
22
- return SubscriptionFailure; // failure
23
- });
24
- await ctx.send({
25
- type: PacketType.suback,
26
- id: packet.id,
27
- returnCodes: returnCodes,
28
- });
29
- // send any retained messages that match these subscriptions
30
- if (ctx.store) {
31
- ctx.persistence.handleRetained(ctx.store.clientId);
32
- }
33
- }
@@ -1,12 +0,0 @@
1
- import { PacketType } from "../deps.js";
2
- export async function handleUnsubscribe(ctx, packet) {
3
- for (const topic of packet.topicFilters) {
4
- if (ctx.store) {
5
- ctx.persistence.unsubscribe(ctx.store, topic);
6
- }
7
- }
8
- await ctx.send({
9
- type: PacketType.unsuback,
10
- id: packet.id,
11
- });
12
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * This module provides an MQTT Server interface see the /bin folder for examples
3
- * @module
4
- */
5
- export { AuthenticationResult } from "./deps.js";
6
- export { MqttServer } from "./server.js";
7
- export { Context } from "./context.js";
@@ -1,47 +0,0 @@
1
- import { Context } from "./context.js";
2
- import { AuthenticationResult, logger, MemoryPersistence, } from "./deps.js";
3
- import { handlePacket } from "./handlers/handlePacket.js";
4
- const defaultIsAuthenticated = (_ctx, _clientId, _username, _password) => AuthenticationResult.ok;
5
- const defaultIsAuthorized = (_ctx, _topic) => true;
6
- /** The MqttServer class provides a MQTT server with configurable persistence and
7
- * authentication/authorization handlers.
8
- *
9
- * The default handlers are:
10
- * - isAuthenticated: always returns ok
11
- * - isAuthorizedToPublish: always returns true
12
- * - isAuthorizedToSubscribe: always returns true
13
- *
14
- * To customize the handlers, pass in a Handlers object.
15
- * To customize the persistence, pass in a Persistence object.
16
- */
17
- export class MqttServer {
18
- handlers;
19
- persistence;
20
- constructor({ persistence, handlers, }) {
21
- this.persistence = persistence || new MemoryPersistence();
22
- this.handlers = {
23
- isAuthenticated: handlers?.isAuthenticated || defaultIsAuthenticated,
24
- isAuthorizedToPublish: handlers?.isAuthorizedToPublish ||
25
- defaultIsAuthorized,
26
- isAuthorizedToSubscribe: handlers?.isAuthorizedToSubscribe ||
27
- defaultIsAuthorized,
28
- };
29
- }
30
- async serve(conn) {
31
- const ctx = new Context(this.persistence, conn, this.handlers);
32
- if (conn.remoteAddr?.transport === "tcp") {
33
- logger.debug(`socket connected from ${conn.remoteAddr.hostname}`);
34
- }
35
- try {
36
- for await (const packet of ctx.mqttConn) {
37
- handlePacket(ctx, packet);
38
- }
39
- }
40
- catch (err) {
41
- logger.debug(`Error while serving:${err}`);
42
- }
43
- finally {
44
- ctx.close();
45
- }
46
- }
47
- }
@@ -1,36 +0,0 @@
1
- export class Conn {
2
- reader;
3
- writer;
4
- closed;
5
- remoteAddr;
6
- closer;
7
- constructor(sockConn) {
8
- this.closed = false;
9
- this.reader = sockConn.readable.getReader({ mode: "byob" });
10
- this.writer = sockConn.writable.getWriter();
11
- // this.writer.closed.then(() => this.closed = true);
12
- this.closer = sockConn.close.bind(sockConn);
13
- this.remoteAddr = sockConn.remoteAddr;
14
- }
15
- async read(buff) {
16
- const buff2 = new Uint8Array(buff.length);
17
- const result = await this.reader.read(buff2);
18
- if (!result.done) {
19
- buff.set(result.value);
20
- }
21
- return result.value?.byteLength || null;
22
- }
23
- write(data) {
24
- if (this.closed) {
25
- return Promise.reject();
26
- }
27
- this.writer.write(data);
28
- return new Promise((resolve) => resolve(data.length));
29
- }
30
- close() {
31
- if (!this.closed) {
32
- this.closed = true;
33
- this.closer();
34
- }
35
- }
36
- }
@@ -1,40 +0,0 @@
1
- export class Timer {
2
- delay; // delay in microseconds
3
- // deno-lint-ignore ban-types
4
- action; // function to perform when timer expires
5
- timer;
6
- end = 0;
7
- running = false;
8
- // deno-lint-ignore ban-types
9
- constructor(action, delay, wait = false) {
10
- this.delay = delay;
11
- this.action = action;
12
- if (!wait) {
13
- this.reset();
14
- }
15
- }
16
- startTimer(delay) {
17
- this.running = true;
18
- this.timer = setTimeout(() => this.ring(), delay);
19
- }
20
- ring() {
21
- const timeLeft = this.end - Date.now();
22
- // check if delay has passed, else execute action
23
- if (timeLeft > 0) {
24
- this.startTimer(timeLeft);
25
- return;
26
- }
27
- this.running = false;
28
- this.action();
29
- }
30
- reset() {
31
- this.end = Date.now() + this.delay;
32
- if (!this.running) {
33
- this.startTimer(this.delay);
34
- }
35
- }
36
- clear() {
37
- clearTimeout(this.timer);
38
- this.running = false;
39
- }
40
- }
package/dist/trie/trie.js DELETED
@@ -1,95 +0,0 @@
1
- export class Trie {
2
- #value;
3
- #children;
4
- separator = "/";
5
- wildcardOne = "+";
6
- wildcardSubtree = "#";
7
- reservedPrefix = "$";
8
- looseCompare;
9
- constructor(looseCompare = false) {
10
- this.#value = [];
11
- this.#children = new Map();
12
- this.looseCompare = looseCompare;
13
- }
14
- matchChild(child, parts) {
15
- const childNode = this.#children.get(child);
16
- return childNode ? childNode._match(parts) : [];
17
- }
18
- match(key) {
19
- const parts = key.split(this.separator);
20
- // toplevel wildcards are not allowed to match toplevel reserved topics
21
- if (parts.length > 0 && parts[0].charAt(0) === this.reservedPrefix) {
22
- return this._matchPrefix(parts);
23
- }
24
- return this._match(parts);
25
- }
26
- _matchPrefix(parts) {
27
- if (parts.length === 0) {
28
- return this.#value ? this.#value : [];
29
- }
30
- const [first, ...rest] = parts;
31
- return this.matchChild(first, rest);
32
- }
33
- _match(parts) {
34
- if (parts.length === 0) {
35
- return this.#value ? this.#value : [];
36
- }
37
- const [first, ...rest] = parts;
38
- const exact = this.matchChild(first, rest);
39
- const single = this.matchChild(this.wildcardOne, rest);
40
- const subtree = this.matchChild(this.wildcardSubtree, []);
41
- const results = exact.concat(single, subtree);
42
- return results;
43
- }
44
- add(key, value) {
45
- return this._add(key.split(this.separator), value);
46
- }
47
- _add(parts, value) {
48
- if (parts.length === 0) {
49
- this.#value = this.#value.concat(value);
50
- return;
51
- }
52
- const [first, ...rest] = parts;
53
- const child = this.#children.get(first);
54
- if (child instanceof Trie) {
55
- child._add(rest, value);
56
- }
57
- else {
58
- const node = new Trie(this.looseCompare);
59
- this.#children.set(first, node);
60
- node._add(rest, value);
61
- }
62
- return;
63
- }
64
- remove(key, value) {
65
- return this._remove(key.split(this.separator), value);
66
- }
67
- _remove(parts, value) {
68
- if (parts.length === 0) {
69
- const arr = this.#value || [];
70
- this.#value = arr.filter(this.filter(value));
71
- return;
72
- }
73
- const [first, ...rest] = parts;
74
- const node = this.#children.get(first);
75
- if (node) {
76
- node._remove(rest, value);
77
- if (node.#value.length === 0 && this.#children.size === 0) {
78
- this.#children.delete(first);
79
- }
80
- }
81
- }
82
- filter(value) {
83
- if (this.looseCompare && typeof value === "object") {
84
- return (item) => {
85
- for (const key in value) {
86
- if (value[key] !== item[key]) {
87
- return true;
88
- }
89
- }
90
- return false;
91
- };
92
- }
93
- return (item) => item !== value;
94
- }
95
- }
@@ -1 +0,0 @@
1
- {"root":["../bin/conformanceServer.ts","../bin/demoServer.ts","../bin/mqtt.ts"],"version":"5.7.3"}
@@ -1,75 +0,0 @@
1
- function formatValue(key, value, boolean, string) {
2
- if (key === "__proto__" || key === "constructor") {
3
- throw new Error(`Invalid argument: ${key}`);
4
- }
5
- if (boolean.includes(key)) {
6
- if (value !== "false") {
7
- return true;
8
- }
9
- return false;
10
- }
11
- if (!string.includes(key)) {
12
- const num = Number(value);
13
- if (!Number.isNaN(num)) {
14
- return num;
15
- }
16
- }
17
- return value;
18
- }
19
- function parseKeyValue(arg, alias) {
20
- if (arg.startsWith("--no-")) {
21
- const key = arg.slice(5);
22
- return [key, false];
23
- }
24
- if (arg.startsWith("--")) {
25
- const [key, value] = arg.slice(2).split("=", 2);
26
- return [key, value];
27
- }
28
- if (arg.startsWith("-")) {
29
- const [flag, value] = arg.slice(1).split("=", 2);
30
- const key = alias[flag] || flag;
31
- return [key, value];
32
- }
33
- return ["_", arg];
34
- }
35
- /**
36
- * a parser for command line arguments
37
- * @param args the arguments to parse
38
- * @param opts the options for the parser
39
- * @returns the parsed arguments
40
- *
41
- * @example
42
- * const args = parseArgs(args, {
43
- * alias: { h: "help" },
44
- * boolean: ["help"],
45
- * string: ["port"],
46
- * default: { port: 3000 },
47
- * });
48
- */
49
- export function parseArgs(args, opts = {}) {
50
- const { alias = {}, boolean = [], string = [], default: defaults = {} } = opts;
51
- const result = { ...defaults };
52
- result["_"] = [];
53
- for (let i = 0; i < args.length; i++) {
54
- const [key, value] = parseKeyValue(args[i], alias);
55
- if (key === "_") {
56
- result["_"].push(formatValue(key, value, boolean, string));
57
- continue;
58
- }
59
- if (value === undefined) {
60
- const nextArg = args[i + 1];
61
- if (nextArg !== undefined &&
62
- !nextArg.startsWith("-") &&
63
- !boolean.includes(key)) {
64
- result[key] = formatValue(key, nextArg, boolean, string);
65
- i++;
66
- }
67
- else {
68
- result[key] = formatValue(key, value, boolean, string);
69
- }
70
- continue;
71
- }
72
- result[key] = formatValue(key, value, boolean, string);
73
- }
74
- return result;
75
- }
@@ -1,20 +0,0 @@
1
- export class AssertionError extends Error {
2
- /** Constructs a new instance. */
3
- constructor(message) {
4
- super(message);
5
- this.name = "AssertionError";
6
- }
7
- }
8
- /** assert(expr, msg) throws AssertionError if expr is falsy. */
9
- export function assert(expr, msg = "") {
10
- if (!expr) {
11
- throw new AssertionError(msg);
12
- }
13
- }
14
- export function assertArrayIncludes(actual, expected, msg) {
15
- const actualArr = Array.from(actual);
16
- const expectedArr = Array.from(expected);
17
- for (const item of expectedArr) {
18
- assert(actualArr.includes(item), msg + `\nExpected: ${expectedArr}\nActual: ${actualArr}`);
19
- }
20
- }
@@ -1,67 +0,0 @@
1
- import { nextTick } from "./nextTick.js";
2
- /**
3
- * An Async Queue is a queue that can be used to push items to it and then wait
4
- * for them to be consumed.
5
- *
6
- * @example
7
- * const queue = new AsyncQueue<string>();
8
- * queue.push("hello");
9
- * for await (const item of queue) {
10
- * console.log(item); // "hello"
11
- * }
12
- */
13
- export class AsyncQueue {
14
- queue = [];
15
- maxQueueLength = Infinity;
16
- nextResolve = (_value) => { };
17
- nextReject = (_reason) => { };
18
- done = false;
19
- hasNext = false;
20
- constructor(maxQueueLength) {
21
- if (maxQueueLength) {
22
- this.maxQueueLength = maxQueueLength;
23
- }
24
- }
25
- async next() {
26
- await nextTick();
27
- if (this.done && this.queue.length === 0) {
28
- return Promise.reject("Closed");
29
- }
30
- return new Promise((resolve, reject) => {
31
- if (this.queue.length > 0) {
32
- const item = this.queue.shift();
33
- if (item) {
34
- return resolve(item);
35
- }
36
- }
37
- this.nextResolve = resolve;
38
- this.nextReject = reject;
39
- this.hasNext = true;
40
- });
41
- }
42
- close(reason = "closed") {
43
- this.done = true;
44
- if (this.hasNext) {
45
- this.nextReject(reason);
46
- }
47
- }
48
- async *[Symbol.asyncIterator]() {
49
- while (true) {
50
- yield this.next();
51
- }
52
- }
53
- push(item) {
54
- if (this.hasNext) {
55
- this.nextResolve(item);
56
- this.hasNext = false;
57
- return;
58
- }
59
- if (this.queue.length > this.maxQueueLength) {
60
- this.queue.shift();
61
- }
62
- this.queue.push(item);
63
- }
64
- get isDone() {
65
- return this.done;
66
- }
67
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Create a promise that can be resolved/rejected later
3
- */
4
- export class Deferred {
5
- promise;
6
- resolve;
7
- reject;
8
- constructor() {
9
- this.promise = new Promise((resolve, reject) => {
10
- this.resolve = resolve;
11
- this.reject = reject;
12
- });
13
- }
14
- }