aedes 0.51.3 → 1.0.1

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 (68) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.github/actions/sticky-pr-comment/action.yml +55 -0
  3. package/.github/workflows/benchmark-compare-serial.yml +60 -0
  4. package/.github/workflows/ci.yml +12 -17
  5. package/.release-it.json +18 -0
  6. package/.taprc +15 -6
  7. package/README.md +6 -4
  8. package/aedes.d.ts +0 -6
  9. package/aedes.js +270 -242
  10. package/benchmarks/README.md +33 -0
  11. package/benchmarks/pingpong.js +94 -25
  12. package/benchmarks/receiver.js +77 -0
  13. package/benchmarks/report.js +150 -0
  14. package/benchmarks/runBenchmarks.js +118 -0
  15. package/benchmarks/sender.js +86 -0
  16. package/benchmarks/server.js +19 -18
  17. package/checkVersion.js +20 -0
  18. package/docs/Aedes.md +66 -8
  19. package/docs/Client.md +3 -4
  20. package/docs/Examples.md +39 -22
  21. package/docs/MIGRATION.md +50 -0
  22. package/eslint.config.js +8 -0
  23. package/example.js +51 -40
  24. package/examples/clusters/index.js +28 -23
  25. package/examples/clusters/package.json +10 -6
  26. package/lib/client.js +405 -306
  27. package/lib/handlers/connect.js +42 -38
  28. package/lib/handlers/index.js +9 -11
  29. package/lib/handlers/ping.js +2 -3
  30. package/lib/handlers/puback.js +5 -5
  31. package/lib/handlers/publish.js +29 -14
  32. package/lib/handlers/pubrec.js +9 -17
  33. package/lib/handlers/pubrel.js +34 -25
  34. package/lib/handlers/subscribe.js +47 -43
  35. package/lib/handlers/unsubscribe.js +16 -19
  36. package/lib/qos-packet.js +14 -17
  37. package/lib/utils.js +5 -12
  38. package/lib/write.js +4 -5
  39. package/package.json +139 -136
  40. package/test/auth.js +468 -804
  41. package/test/basic.js +613 -575
  42. package/test/bridge.js +44 -40
  43. package/test/client-pub-sub.js +531 -504
  44. package/test/close_socket_by_other_party.js +137 -102
  45. package/test/connect.js +487 -484
  46. package/test/drain-timeout.js +593 -0
  47. package/test/drain-toxiproxy.js +620 -0
  48. package/test/events.js +173 -145
  49. package/test/helper.js +351 -73
  50. package/test/keep-alive.js +40 -67
  51. package/test/meta.js +257 -210
  52. package/test/not-blocking.js +93 -197
  53. package/test/qos1.js +464 -554
  54. package/test/qos2.js +308 -393
  55. package/test/regr-21.js +39 -21
  56. package/test/require.cjs +22 -0
  57. package/test/retain.js +349 -398
  58. package/test/topics.js +176 -183
  59. package/test/types/aedes.test-d.ts +4 -8
  60. package/test/will.js +310 -428
  61. package/types/instance.d.ts +40 -35
  62. package/types/packet.d.ts +10 -10
  63. package/.coveralls.yml +0 -1
  64. package/benchmarks/bombing.js +0 -34
  65. package/benchmarks/bombingQoS1.js +0 -36
  66. package/benchmarks/throughputCounter.js +0 -23
  67. package/benchmarks/throughputCounterQoS1.js +0 -33
  68. package/types/.eslintrc.json +0 -47
@@ -1,6 +1,6 @@
1
1
  import { Duplex } from 'node:stream'
2
2
  import { Socket } from 'node:net'
3
- import { IncomingMessage } from 'http'
3
+ import { IncomingMessage } from 'node:http'
4
4
  import { Client } from './client'
5
5
  import type {
6
6
  AedesPublishPacket,
@@ -13,13 +13,13 @@ import type {
13
13
  } from './packet'
14
14
  import { EventEmitter } from 'node:events'
15
15
 
16
- type LastHearthbeatTimestamp = Date;
16
+ type LastHearthbeatTimestamp = Date
17
17
 
18
18
  export interface Brokers {
19
19
  [brokerId: string]: LastHearthbeatTimestamp;
20
20
  }
21
21
 
22
- export type Connection = Duplex | Socket;
22
+ export type Connection = Duplex | Socket
23
23
 
24
24
  /* eslint no-unused-vars: 0 */
25
25
  export const enum AuthErrorCode {
@@ -30,43 +30,43 @@ export const enum AuthErrorCode {
30
30
  NOT_AUTHORIZED = 5,
31
31
  }
32
32
 
33
- export type AuthenticateError = Error & { returnCode: AuthErrorCode };
33
+ export type AuthenticateError = Error & { returnCode: AuthErrorCode }
34
34
 
35
35
  type PreConnectHandler = (
36
36
  client: Client,
37
37
  packet: ConnectPacket,
38
38
  callback: (error: Error | null, success: boolean) => void
39
- ) => void;
39
+ ) => void
40
40
 
41
41
  type AuthenticateHandler = (
42
42
  client: Client,
43
43
  username: Readonly<string | undefined>,
44
44
  password: Readonly<Buffer | undefined>,
45
45
  done: (error: AuthenticateError | null, success: boolean | null) => void
46
- ) => void;
46
+ ) => void
47
47
 
48
48
  type AuthorizePublishHandler = (
49
49
  client: Client | null,
50
50
  packet: PublishPacket,
51
51
  callback: (error?: Error | null) => void
52
- ) => void;
52
+ ) => void
53
53
 
54
54
  type AuthorizeSubscribeHandler = (
55
55
  client: Client,
56
56
  subscription: Subscription,
57
57
  callback: (error: Error | null, subscription?: Subscription | null) => void
58
- ) => void;
58
+ ) => void
59
59
 
60
60
  type AuthorizeForwardHandler = (
61
61
  client: Client,
62
62
  packet: AedesPublishPacket
63
- ) => AedesPublishPacket | null | void;
63
+ ) => AedesPublishPacket | null | void
64
64
 
65
65
  type PublishedHandler = (
66
66
  packet: AedesPublishPacket,
67
67
  client: Client,
68
68
  callback: (error?: Error | null) => void
69
- ) => void;
69
+ ) => void
70
70
 
71
71
  export interface AedesOptions {
72
72
  mq?: any;
@@ -75,6 +75,7 @@ export interface AedesOptions {
75
75
  concurrency?: number;
76
76
  heartbeatInterval?: number;
77
77
  connectTimeout?: number;
78
+ drainTimeout?: number; // default: 60000 (60 seconds)
78
79
  keepaliveLimit?: number;
79
80
  queueLimit?: number;
80
81
  maxClientsIdLength?: number;
@@ -86,70 +87,74 @@ export interface AedesOptions {
86
87
  published?: PublishedHandler;
87
88
  }
88
89
 
89
- export default class Aedes extends EventEmitter {
90
+ export class Aedes extends EventEmitter {
90
91
  id: Readonly<string>
91
92
  connectedClients: Readonly<number>
92
93
  closed: Readonly<boolean>
93
94
  brokers: Readonly<Brokers>
94
95
 
95
- constructor(option?: AedesOptions);
96
+ constructor (option?: AedesOptions)
96
97
  handle: (stream: Connection, request?: IncomingMessage) => Client
97
98
 
98
- on(event: 'closed', listener: () => void): this;
99
- on(
99
+ on (event: 'closed', listener: () => void): this
100
+ on (
100
101
  event: 'client' | 'clientReady' | 'clientDisconnect' | 'keepaliveTimeout',
101
102
  listener: (client: Client) => void
102
- ): this;
103
+ ): this
103
104
 
104
- on(
105
+ on (
105
106
  event: 'clientError' | 'connectionError',
106
107
  listener: (client: Client, error: Error) => void
107
- ): this;
108
+ ): this
108
109
 
109
- on(
110
+ on (
110
111
  event: 'connackSent',
111
112
  listener: (packet: ConnackPacket, client: Client) => void
112
- ): this;
113
+ ): this
113
114
 
114
- on(
115
+ on (
115
116
  event: 'ping',
116
117
  listener: (packet: PingreqPacket, client: Client) => void
117
- ): this;
118
+ ): this
118
119
 
119
- on(
120
+ on (
120
121
  event: 'publish',
121
122
  listener: (packet: AedesPublishPacket, client: Client | null) => void
122
- ): this;
123
+ ): this
123
124
 
124
- on(
125
+ on (
125
126
  event: 'ack',
126
127
  listener: (packet: PublishPacket | PubrelPacket, client: Client) => void
127
- ): this;
128
+ ): this
128
129
 
129
- on(
130
+ on (
130
131
  event: 'subscribe',
131
132
  listener: (subscriptions: Subscription[], client: Client) => void
132
- ): this;
133
+ ): this
133
134
 
134
- on(
135
+ on (
135
136
  event: 'unsubscribe',
136
137
  listener: (unsubscriptions: string[], client: Client) => void
137
- ): this;
138
+ ): this
138
139
 
139
- publish(packet: PublishPacket, callback: (error?: Error) => void): void;
140
- subscribe(
140
+ listen (): Promise<void>
141
+
142
+ static createBroker (option?: AedesOptions): Promise<Aedes>
143
+
144
+ publish (packet: PublishPacket, callback: (error?: Error) => void): void
145
+ subscribe (
141
146
  topic: string,
142
147
  deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void,
143
148
  callback: () => void
144
- ): void;
149
+ ): void
145
150
 
146
- unsubscribe(
151
+ unsubscribe (
147
152
  topic: string,
148
153
  deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void,
149
154
  callback: () => void
150
- ): void;
155
+ ): void
151
156
 
152
- close(callback?: () => void): void;
157
+ close (callback?: () => void): void
153
158
 
154
159
  preConnect: PreConnectHandler
155
160
  authenticate: AuthenticateHandler
package/types/packet.d.ts CHANGED
@@ -11,17 +11,17 @@ import {
11
11
  } from 'mqtt-packet'
12
12
  import { Client } from './client'
13
13
 
14
- export type SubscribePacket = ISubscribePacket & { cmd: 'subscribe' };
15
- export type UnsubscribePacket = IUnsubscribePacket & { cmd: 'unsubscribe' };
16
- export type Subscription = ISubscription & { clientId?: Client['id'] };
17
- export type Subscriptions = { subscriptions: Subscription[] };
14
+ export type SubscribePacket = ISubscribePacket & { cmd: 'subscribe' }
15
+ export type UnsubscribePacket = IUnsubscribePacket & { cmd: 'unsubscribe' }
16
+ export type Subscription = ISubscription & { clientId?: Client['id'] }
17
+ export type Subscriptions = { subscriptions: Subscription[] }
18
18
 
19
- export type PublishPacket = IPublishPacket & { cmd: 'publish' };
19
+ export type PublishPacket = IPublishPacket & { cmd: 'publish' }
20
20
 
21
- export type ConnectPacket = IConnectPacket & { cmd: 'connect' };
22
- export type ConnackPacket = IConnackPacket & { cmd: 'connack' };
21
+ export type ConnectPacket = IConnectPacket & { cmd: 'connect' }
22
+ export type ConnackPacket = IConnackPacket & { cmd: 'connack' }
23
23
 
24
- export type PubrelPacket = IPubrelPacket & { cmd: 'pubrel' };
25
- export type PingreqPacket = IPingreqPacket & { cmd: 'pingreq' };
24
+ export type PubrelPacket = IPubrelPacket & { cmd: 'pubrel' }
25
+ export type PingreqPacket = IPingreqPacket & { cmd: 'pingreq' }
26
26
 
27
- export type AedesPublishPacket = PublishPacket & AedesPacket;
27
+ export type AedesPublishPacket = PublishPacket & AedesPacket
package/.coveralls.yml DELETED
@@ -1 +0,0 @@
1
- repo_token: 0zzWBuyAWoQxHHR0JQ4jdZ12CPdvhiolr
@@ -1,34 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- const mqtt = require('mqtt')
4
- const client = mqtt.connect({ port: 1883, host: 'localhost', clean: true, keepalive: 0 })
5
- const interval = 5000
6
-
7
- let sent = 0
8
-
9
- function count () {
10
- console.log('sent/s', sent / interval * 1000)
11
- sent = 0
12
- }
13
-
14
- setInterval(count, interval)
15
-
16
- function immediatePublish () {
17
- setImmediate(publish)
18
- }
19
-
20
- function publish () {
21
- sent++
22
- client.publish('test', 'payload', immediatePublish)
23
- }
24
-
25
- client.on('connect', publish)
26
-
27
- client.on('offline', function () {
28
- console.log('offline')
29
- })
30
-
31
- client.on('error', function () {
32
- console.log('reconnect!')
33
- client.stream.end()
34
- })
@@ -1,36 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- const mqtt = require('mqtt')
4
- const client = mqtt.connect({ port: 1883, host: 'localhost', clean: true, keepalive: 0 })
5
- const interval = 5000
6
-
7
- let sent = 0
8
-
9
- function count () {
10
- console.log('sent/s', sent / interval * 1000)
11
- sent = 0
12
- }
13
-
14
- setInterval(count, interval)
15
-
16
- function publish () {
17
- sent++
18
- client.publish('test', 'payload', { qos: 1 }, publish)
19
- }
20
-
21
- client.setMaxListeners(100)
22
-
23
- client.on('connect', function () {
24
- for (let i = 0; i < 50; i++) {
25
- publish()
26
- }
27
- })
28
-
29
- client.on('offline', function () {
30
- console.log('offline')
31
- })
32
-
33
- client.on('error', function () {
34
- console.log('reconnect!')
35
- client.stream.end()
36
- })
@@ -1,23 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- const mqtt = require('mqtt')
4
-
5
- const client = mqtt.connect({ port: 1883, host: 'localhost', clean: true, encoding: 'binary', keepalive: 0 })
6
- const interval = 5000
7
-
8
- let counter = 0
9
-
10
- function count () {
11
- console.log('received/s', counter / interval * 1000)
12
- counter = 0
13
- }
14
-
15
- setInterval(count, interval)
16
-
17
- client.on('connect', function () {
18
- count()
19
- this.subscribe('test')
20
- this.on('message', function () {
21
- counter++
22
- })
23
- })
@@ -1,33 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- const mqtt = require('mqtt')
4
-
5
- const client = mqtt.connect({ port: 1883, host: 'localhost', clean: true, encoding: 'binary', keepalive: 0 })
6
- const interval = 5000
7
-
8
- let counter = 0
9
-
10
- function count () {
11
- console.log('received/s', counter / interval * 1000)
12
- counter = 0
13
- }
14
-
15
- setInterval(count, interval)
16
-
17
- client.on('connect', function () {
18
- this.subscribe('test', { qos: 1 })
19
- })
20
-
21
- client.handleMessage = function (packet, done) {
22
- counter++
23
- done()
24
- }
25
-
26
- client.on('offline', function () {
27
- console.log('offline')
28
- })
29
-
30
- client.on('error', function () {
31
- console.log('reconnect!')
32
- client.stream.end()
33
- })
@@ -1,47 +0,0 @@
1
- {
2
- "extends": [
3
- "eslint:recommended",
4
- "plugin:@typescript-eslint/recommended",
5
- "standard"
6
- ],
7
- "parser": "@typescript-eslint/parser",
8
- "plugins": ["@typescript-eslint"],
9
- "env": { "node": true },
10
- "parserOptions": {
11
- "ecmaVersion": 6,
12
- "sourceType": "module",
13
- "project": "./types/tsconfig.json",
14
- "createDefaultProgram": true
15
- },
16
- "rules": {
17
- "linebreak-style": ["warn", "unix"],
18
- "no-console": "off",
19
- "semi": ["error", "never"],
20
- "import/export": "off", // this errors on multiple exports (overload interfaces)
21
- "@typescript-eslint/indent": ["error", 2]
22
- },
23
- "overrides": [
24
- {
25
- "files": ["*.d.ts", "*.test-d.ts"],
26
- "rules": {
27
- "no-dupe-class-members": "off",
28
- "@typescript-eslint/no-explicit-any": "off",
29
- "@typescript-eslint/triple-slash-reference": "off"
30
- }
31
- },
32
- {
33
- "files": ["*.test-d.ts"],
34
- "rules": {
35
- "no-unused-vars": "off",
36
- "node/handle-callback-err": "off",
37
- "@typescript-eslint/no-empty-function": "off",
38
- "@typescript-eslint/explicit-function-return-type": "off",
39
- "@typescript-eslint/no-unused-vars": "off",
40
- "@typescript-eslint/no-non-null-assertion": "off"
41
- },
42
- "globals": {
43
- "NodeJS": "readonly"
44
- }
45
- }
46
- ]
47
- }