@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.
- package/README.md +6 -7
- package/bin/conformanceServer.ts +67 -16
- package/bin/demoServer.ts +69 -14
- package/bin/mqtt.ts +30 -0
- package/client/ConnectionState.ts +12 -0
- package/client/client.ts +56 -2
- package/client/context.ts +5 -0
- package/client/handlers/handleConnack.ts +6 -0
- package/client/handlers/handlePacket.ts +7 -0
- package/client/handlers/handlePuback.ts +8 -2
- package/client/handlers/handlePubcomp.ts +10 -4
- package/client/handlers/handlePublish.ts +6 -2
- package/client/handlers/handlePubrec.ts +13 -6
- package/client/handlers/handlePubrel.ts +16 -6
- package/client/handlers/handleSuback.ts +9 -6
- package/client/handlers/handleUnsuback.ts +10 -3
- package/client/store/memoryStore.ts +25 -0
- package/client/store/store.ts +39 -0
- package/deno/tcpServer.test.ts +137 -2
- package/node/tcpServer.test.ts +61 -6
- package/node/tcpServer.ts +9 -2
- package/node/wrapNodeSocket.ts +13 -2
- package/package.json +13 -3
- package/persistence/memory/memoryPersistence.test.ts +2 -1
- package/persistence/memory/memoryPersistence.ts +1 -0
- package/persistence/store.ts +1 -0
- package/server/handlers/handleConnect.ts +49 -6
- package/server/handlers/handleDisconnect.ts +5 -0
- package/server/handlers/handlePacket.ts +7 -0
- package/server/handlers/handlePingreq.ts +6 -0
- package/server/handlers/handlePuback.ts +9 -2
- package/server/handlers/handlePubcomp.ts +8 -3
- package/server/handlers/handlePublish.ts +13 -0
- package/server/handlers/handlePubrec.ts +11 -3
- package/server/handlers/handlePubrel.ts +12 -4
- package/server/handlers/handleSubscribe.ts +28 -5
- package/server/handlers/handleUnsubscribe.ts +6 -0
- package/utils/asyncQueue.ts +2 -1
- package/utils/nextTick.ts +13 -1
- package/.github/workflows/closeStale.yml +0 -15
- package/.github/workflows/codeql-analysis.yml +0 -71
- package/.github/workflows/deno-ci.yml +0 -16
- package/.github/workflows/nodejs-ci.yml +0 -23
- package/.github/workflows/publish.yml +0 -16
- package/.github/workflows/update-license-year.sh +0 -14
- package/.github/workflows/update-license-year.yml +0 -13
- package/CHANGELOG.md +0 -74
- package/deno.json +0 -15
- package/deno.lock +0 -34
- package/dist/bin/conformanceServer.js +0 -51
- package/dist/bin/demoServer.js +0 -46
- package/dist/bin/mqtt.js +0 -227
- package/dist/client/ConnectionState.js +0 -7
- package/dist/client/client.js +0 -132
- package/dist/client/context.js +0 -148
- package/dist/client/deps.js +0 -5
- package/dist/client/handlers/handleConnack.js +0 -18
- package/dist/client/handlers/handlePacket.js +0 -50
- package/dist/client/handlers/handlePuback.js +0 -6
- package/dist/client/handlers/handlePubcomp.js +0 -9
- package/dist/client/handlers/handlePublish.js +0 -28
- package/dist/client/handlers/handlePubrec.js +0 -17
- package/dist/client/handlers/handlePubrel.js +0 -19
- package/dist/client/handlers/handleSuback.js +0 -9
- package/dist/client/handlers/handleUnsuback.js +0 -7
- package/dist/client/mod.js +0 -5
- package/dist/client/store/deps.js +0 -1
- package/dist/client/store/memoryStore.js +0 -36
- package/dist/client/store/store.js +0 -1
- package/dist/mqttConn/mqttConn.js +0 -104
- package/dist/mqttPacket/AuthenticationResult.js +0 -16
- package/dist/mqttPacket/BitMask.js +0 -10
- package/dist/mqttPacket/PacketType.js +0 -18
- package/dist/mqttPacket/connack.js +0 -27
- package/dist/mqttPacket/connect.js +0 -115
- package/dist/mqttPacket/decoder.js +0 -89
- package/dist/mqttPacket/disconnect.js +0 -14
- package/dist/mqttPacket/encoder.js +0 -56
- package/dist/mqttPacket/length.js +0 -43
- package/dist/mqttPacket/mod.js +0 -76
- package/dist/mqttPacket/pingreq.js +0 -15
- package/dist/mqttPacket/pingres.js +0 -14
- package/dist/mqttPacket/puback.js +0 -20
- package/dist/mqttPacket/pubcomp.js +0 -20
- package/dist/mqttPacket/publish.js +0 -51
- package/dist/mqttPacket/pubrec.js +0 -20
- package/dist/mqttPacket/pubrel.js +0 -20
- package/dist/mqttPacket/suback.js +0 -29
- package/dist/mqttPacket/subscribe.js +0 -52
- package/dist/mqttPacket/types.js +0 -1
- package/dist/mqttPacket/unsuback.js +0 -20
- package/dist/mqttPacket/unsubscribe.js +0 -36
- package/dist/mqttPacket/validators.js +0 -15
- package/dist/node/tcpClient.js +0 -81
- package/dist/node/tcpServer.js +0 -43
- package/dist/node/wrapNodeSocket.js +0 -47
- package/dist/persistence/deps.js +0 -3
- package/dist/persistence/memory/memoryPersistence.js +0 -117
- package/dist/persistence/persistence.js +0 -1
- package/dist/persistence/store.js +0 -1
- package/dist/server/context.js +0 -100
- package/dist/server/deps.js +0 -5
- package/dist/server/handlers/handleConnect.js +0 -46
- package/dist/server/handlers/handleDisconnect.js +0 -4
- package/dist/server/handlers/handlePacket.js +0 -58
- package/dist/server/handlers/handlePingreq.js +0 -6
- package/dist/server/handlers/handlePuback.js +0 -8
- package/dist/server/handlers/handlePubcomp.js +0 -8
- package/dist/server/handlers/handlePublish.js +0 -41
- package/dist/server/handlers/handlePubrec.js +0 -15
- package/dist/server/handlers/handlePubrel.js +0 -18
- package/dist/server/handlers/handleSubscribe.js +0 -33
- package/dist/server/handlers/handleUnsubscribe.js +0 -12
- package/dist/server/mod.js +0 -7
- package/dist/server/server.js +0 -47
- package/dist/socket/socket.js +0 -36
- package/dist/timer/timer.js +0 -40
- package/dist/trie/trie.js +0 -95
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/utils/args.js +0 -75
- package/dist/utils/assert.js +0 -20
- package/dist/utils/asyncQueue.js +0 -67
- package/dist/utils/deferred.js +0 -14
- package/dist/utils/logger.js +0 -58
- package/dist/utils/mod.js +0 -11
- package/dist/utils/nextTick.js +0 -6
- package/dist/utils/platform.js +0 -7
- 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,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,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
|
-
}
|
package/dist/server/mod.js
DELETED
package/dist/server/server.js
DELETED
|
@@ -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
|
-
}
|
package/dist/socket/socket.js
DELETED
|
@@ -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
|
-
}
|
package/dist/timer/timer.js
DELETED
|
@@ -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"}
|
package/dist/utils/args.js
DELETED
|
@@ -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
|
-
}
|
package/dist/utils/assert.js
DELETED
|
@@ -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
|
-
}
|
package/dist/utils/asyncQueue.js
DELETED
|
@@ -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
|
-
}
|
package/dist/utils/deferred.js
DELETED
|
@@ -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
|
-
}
|