Repository: moscajs/aedes
Pull request #812 (2023-02-28 16:10:58)

fix: typescript types issues
Also renamed `Aedes` alias function `Server` to `createBroker`

coveralls: ## Pull Request Test Coverage Report for [Build 4295152793](https://coveralls.io/builds/57380326)

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **99.739%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/57380326/badge)](https://coveralls.io/builds/57380326) |
| :-- | --: |
| Change from base [Build 3911640084](https://coveralls.io/builds/55927322): |  0.0% |
| Covered Lines: | 816 |
| Relevant Lines: | 816 |

---
##### 💛  - [Coveralls](https://coveralls.io)

coveralls: ## Pull Request Test Coverage Report for [Build 4295152793](https://coveralls.io/builds/57380326)

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **99.739%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/57380326/badge)](https://coveralls.io/builds/57380326) |
| :-- | --: |
| Change from base [Build 3911640084](https://coveralls.io/builds/55927322): |  0.0% |
| Covered Lines: | 816 |
| Relevant Lines: | 816 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/aedes.d.ts b/aedes.d.ts
index d671cdc..1574faf 100644
--- a/aedes.d.ts
+++ b/aedes.d.ts
@@ -1,3 +1,8 @@
-/// <reference path="./types/instance.d.ts" />
-/// <reference path="./types/client.d.ts" />
-/// <reference path="./types/packet.d.ts" />
+import Aedes, { AedesOptions } from './types/instance'
+
+export declare function createBroker (options?: AedesOptions): Aedes
+
+export * from './types/instance'
+export * from './types/packet'
+export * from './types/client'
+export default Aedes
diff --git a/aedes.js b/aedes.js
index 213e772..c02d289 100644
--- a/aedes.js
+++ b/aedes.js
@@ -13,7 +13,7 @@ const mqemitter = require('mqemitter')
 const Client = require('./lib/client')
 const { $SYS_PREFIX, bulk } = require('./lib/utils')
 
-module.exports = Aedes.Server = Aedes
+module.exports = Aedes.createBroker = Aedes
 
 const defaultOptions = {
   concurrency: 100,
diff --git a/docs/Examples.md b/docs/Examples.md
index f391c2e..808888a 100644
--- a/docs/Examples.md
+++ b/docs/Examples.md
@@ -13,6 +13,22 @@ server.listen(port, function () {
 })
 ```
 
+## Typescript
+
+```ts
+import Aedes from 'aedes'
+import { createServer } from 'net'
+
+const port = 1883
+
+const aedes = new Aedes()
+const server = createServer(aedes.handle)
+
+server.listen(port, function () {
+  console.log('server started and listening on port ', port)
+})
+```
+
 ## Simple plain MQTT server using server-factory
 
 ```js
diff --git a/types/client.d.ts b/types/client.d.ts
index fa2ae0b..2906213 100644
--- a/types/client.d.ts
+++ b/types/client.d.ts
@@ -1,32 +1,44 @@
-declare module 'client' {
-  import { IncomingMessage } from 'node:http'
-  import { PublishPacket, SubscribePacket, Subscription, Subscriptions, UnsubscribePacket } from 'aedes:packet'
-  import { Connection } from 'aedes:server'
-  import { EventEmitter } from 'node:events'
+import { IncomingMessage } from 'node:http'
+import {
+  PublishPacket,
+  SubscribePacket,
+  Subscription,
+  Subscriptions,
+  UnsubscribePacket
+} from './packet'
+import { Connection } from './instance'
+import { EventEmitter } from 'node:events'
 
-  export interface Client extends EventEmitter {
-    id: Readonly<string>
-    clean: Readonly<boolean>
-    version: Readonly<number>
-    conn: Connection
-    req?: IncomingMessage
-    connecting: Readonly<boolean>
-    connected: Readonly<boolean>
-    closed: Readonly<boolean>
+export interface Client extends EventEmitter {
+  id: Readonly<string>;
+  clean: Readonly<boolean>;
+  version: Readonly<number>;
+  conn: Connection;
+  req?: IncomingMessage;
+  connecting: Readonly<boolean>;
+  connected: Readonly<boolean>;
+  closed: Readonly<boolean>;
 
-    on (event: 'connected', listener: () => void): this
-    on (event: 'error', listener: (error: Error) => void): this
+  on(event: 'connected', listener: () => void): this;
+  on(event: 'error', listener: (error: Error) => void): this;
 
-    publish (message: PublishPacket, callback?: (error?: Error) => void): void
-    subscribe (
-      subscriptions: Subscriptions | Subscription | Subscription[] | SubscribePacket,
-      callback?: (error?: Error) => void
-    ): void
-    unsubscribe (topicObjects: Subscriptions | Subscription | Subscription[] | UnsubscribePacket, callback?: (error?: Error) => void): void
-    close (callback?: () => void): void
-    emptyOutgoingQueue (callback?: () => void): void
-  }
-}
-declare module 'aedes:client' {
-  export * from 'client'
+  publish(message: PublishPacket, callback?: (error?: Error) => void): void;
+  subscribe(
+    subscriptions:
+    | Subscriptions
+    | Subscription
+    | Subscription[]
+    | SubscribePacket,
+    callback?: (error?: Error) => void
+  ): void;
+  unsubscribe(
+    topicObjects:
+    | Subscriptions
+    | Subscription
+    | Subscription[]
+    | UnsubscribePacket,
+    callback?: (error?: Error) => void
+  ): void;
+  close(callback?: () => void): void;
+  emptyOutgoingQueue(callback?: () => void): void;
 }
diff --git a/types/instance.d.ts b/types/instance.d.ts
index a18165a..f912a95 100644
--- a/types/instance.d.ts
+++ b/types/instance.d.ts
@@ -1,101 +1,159 @@
-declare module 'aedes' {
-  import { Duplex } from 'node:stream'
-  import { Socket } from 'node:net'
-  import { IncomingMessage } from 'http'
-  import { Client } from 'aedes:client'
-  import type { AedesPublishPacket, ConnectPacket, ConnackPacket, Subscription, PingreqPacket, PublishPacket, PubrelPacket } from 'aedes:packet'
-  import { EventEmitter } from 'node:events'
-
-  type LastHearthbeatTimestamp = Date;
-
-  export interface Brokers {
-    [brokerId: string]: LastHearthbeatTimestamp;
-  }
-
-  export type Connection = Duplex | Socket
-
-  /* eslint no-unused-vars: 0 */
-  export const enum AuthErrorCode {
-    UNNACCEPTABLE_PROTOCOL = 1,
-    IDENTIFIER_REJECTED = 2,
-    SERVER_UNAVAILABLE = 3,
-    BAD_USERNAME_OR_PASSWORD = 4,
-    NOT_AUTHORIZED = 5
-  }
-
-  export type AuthenticateError = Error & { returnCode: AuthErrorCode }
-
-  type PreConnectHandler = (client: Client, packet: ConnectPacket, callback: (error: Error | null, success: boolean) => void) => void
-
-  type AuthenticateHandler = (
-    client: Client,
-    username: Readonly<string | undefined>,
-    password: Readonly<Buffer | undefined>,
-    done: (error: AuthenticateError | null, success: boolean | null) => void
-  ) => void
-
-  type AuthorizePublishHandler = (client: Client | null, packet: PublishPacket, callback: (error?: Error | null) => void) => void
-
-  type AuthorizeSubscribeHandler = (client: Client, subscription: Subscription, callback: (error: Error | null, subscription?: Subscription | null) => void) => void
-
-  type AuthorizeForwardHandler = (client: Client, packet: AedesPublishPacket) => AedesPublishPacket | null | void
-
-  type PublishedHandler = (packet: AedesPublishPacket, client: Client, callback: (error?: Error | null) => void) => void
-
-  export interface AedesOptions {
-    mq?: any
-    id?: string
-    persistence?: any
-    concurrency?: number
-    heartbeatInterval?: number
-    connectTimeout?: number
-    queueLimit?: number
-    maxClientsIdLength?: number
-    preConnect?: PreConnectHandler
-    authenticate?: AuthenticateHandler
-    authorizePublish?: AuthorizePublishHandler
-    authorizeSubscribe?: AuthorizeSubscribeHandler
-    authorizeForward?: AuthorizeForwardHandler
-    published?: PublishedHandler
-  }
-
-  export default class Aedes extends EventEmitter {
-    id: Readonly<string>
-    connectedClients: Readonly<number>
-    closed: Readonly<boolean>
-    brokers: Readonly<Brokers>
-
-    constructor(option?: AedesOptions)
-    handle: (stream: Connection, request: IncomingMessage) => Client
-
-    on (event: 'closed', listener: () => void): this
-    on (event: 'client' | 'clientReady' | 'clientDisconnect' | 'keepaliveTimeout', listener: (client: Client) => void): this
-    on (event: 'clientError' | 'connectionError', listener: (client: Client, error: Error) => void): this
-    on (event: 'connackSent', listener: (packet: ConnackPacket, client: Client) => void): this
-    on (event: 'ping', listener: (packet: PingreqPacket, client: Client) => void): this
-    on (event: 'publish', listener: (packet: AedesPublishPacket, client: Client | null) => void): this
-    on (event: 'ack', listener: (packet: PublishPacket | PubrelPacket, client: Client) => void): this
-    on (event: 'subscribe', listener: (subscriptions: Subscription[], client: Client) => void): this
-    on (event: 'unsubscribe', listener: (unsubscriptions: string[], client: Client) => void): this
-
-    publish (packet: PublishPacket, callback: (error?: Error) => void): void
-    subscribe (topic: string, deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void, callback: () => void): void
-    unsubscribe (topic: string, deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void, callback: () => void): void
-    close (callback?: () => void): void
-
-    preConnect: PreConnectHandler
-    authenticate: AuthenticateHandler
-    authorizePublish: AuthorizePublishHandler
-    authorizeSubscribe: AuthorizeSubscribeHandler
-    authorizeForward: AuthorizeForwardHandler
-    published: PublishedHandler
-  }
-
-  export { Aedes }
-  // export function createServer(options?: AedesOptions): Aedes
+import { Duplex } from 'node:stream'
+import { Socket } from 'node:net'
+import { IncomingMessage } from 'http'
+import { Client } from './client'
+import type {
+  AedesPublishPacket,
+  ConnectPacket,
+  ConnackPacket,
+  Subscription,
+  PingreqPacket,
+  PublishPacket,
+  PubrelPacket
+} from './packet'
+import { EventEmitter } from 'node:events'
+
+type LastHearthbeatTimestamp = Date;
+
+export interface Brokers {
+  [brokerId: string]: LastHearthbeatTimestamp;
 }
 
-declare module 'aedes:server' {
-  export * from 'aedes'
-  export { default } from 'aedes'
+export type Connection = Duplex | Socket;
+
+/* eslint no-unused-vars: 0 */
+export const enum AuthErrorCode {
+  UNNACCEPTABLE_PROTOCOL = 1,
+  IDENTIFIER_REJECTED = 2,
+  SERVER_UNAVAILABLE = 3,
+  BAD_USERNAME_OR_PASSWORD = 4,
+  NOT_AUTHORIZED = 5,
+}
+
+export type AuthenticateError = Error & { returnCode: AuthErrorCode };
+
+type PreConnectHandler = (
+  client: Client,
+  packet: ConnectPacket,
+  callback: (error: Error | null, success: boolean) => void
+) => void;
+
+type AuthenticateHandler = (
+  client: Client,
+  username: Readonly<string | undefined>,
+  password: Readonly<Buffer | undefined>,
+  done: (error: AuthenticateError | null, success: boolean | null) => void
+) => void;
+
+type AuthorizePublishHandler = (
+  client: Client | null,
+  packet: PublishPacket,
+  callback: (error?: Error | null) => void
+) => void;
+
+type AuthorizeSubscribeHandler = (
+  client: Client,
+  subscription: Subscription,
+  callback: (error: Error | null, subscription?: Subscription | null) => void
+) => void;
+
+type AuthorizeForwardHandler = (
+  client: Client,
+  packet: AedesPublishPacket
+) => AedesPublishPacket | null | void;
+
+type PublishedHandler = (
+  packet: AedesPublishPacket,
+  client: Client,
+  callback: (error?: Error | null) => void
+) => void;
+
+export interface AedesOptions {
+  mq?: any;
+  id?: string;
+  persistence?: any;
+  concurrency?: number;
+  heartbeatInterval?: number;
+  connectTimeout?: number;
+  queueLimit?: number;
+  maxClientsIdLength?: number;
+  preConnect?: PreConnectHandler;
+  authenticate?: AuthenticateHandler;
+  authorizePublish?: AuthorizePublishHandler;
+  authorizeSubscribe?: AuthorizeSubscribeHandler;
+  authorizeForward?: AuthorizeForwardHandler;
+  published?: PublishedHandler;
+}
+
+export default class Aedes extends EventEmitter {
+  id: Readonly<string>
+  connectedClients: Readonly<number>
+  closed: Readonly<boolean>
+  brokers: Readonly<Brokers>
+
+  constructor(option?: AedesOptions);
+  handle: (stream: Connection, request?: IncomingMessage) => Client
+
+  on(event: 'closed', listener: () => void): this;
+  on(
+    event: 'client' | 'clientReady' | 'clientDisconnect' | 'keepaliveTimeout',
+    listener: (client: Client) => void
+  ): this;
+
+  on(
+    event: 'clientError' | 'connectionError',
+    listener: (client: Client, error: Error) => void
+  ): this;
+
+  on(
+    event: 'connackSent',
+    listener: (packet: ConnackPacket, client: Client) => void
+  ): this;
+
+  on(
+    event: 'ping',
+    listener: (packet: PingreqPacket, client: Client) => void
+  ): this;
+
+  on(
+    event: 'publish',
+    listener: (packet: AedesPublishPacket, client: Client | null) => void
+  ): this;
+
+  on(
+    event: 'ack',
+    listener: (packet: PublishPacket | PubrelPacket, client: Client) => void
+  ): this;
+
+  on(
+    event: 'subscribe',
+    listener: (subscriptions: Subscription[], client: Client) => void
+  ): this;
+
+  on(
+    event: 'unsubscribe',
+    listener: (unsubscriptions: string[], client: Client) => void
+  ): this;
+
+  publish(packet: PublishPacket, callback: (error?: Error) => void): void;
+  subscribe(
+    topic: string,
+    deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void,
+    callback: () => void
+  ): void;
+
+  unsubscribe(
+    topic: string,
+    deliverfunc: (packet: AedesPublishPacket, callback: () => void) => void,
+    callback: () => void
+  ): void;
+
+  close(callback?: () => void): void;
+
+  preConnect: PreConnectHandler
+  authenticate: AuthenticateHandler
+  authorizePublish: AuthorizePublishHandler
+  authorizeSubscribe: AuthorizeSubscribeHandler
+  authorizeForward: AuthorizeForwardHandler
+  published: PublishedHandler
 }
diff --git a/types/packet.d.ts b/types/packet.d.ts
index e9a6f3a..5ffdc15 100644
--- a/types/packet.d.ts
+++ b/types/packet.d.ts
@@ -1,23 +1,27 @@
-declare module 'packet' {
-  import { AedesPacket } from 'aedes-packet'
-  import { IConnackPacket, IConnectPacket, IPingreqPacket, IPublishPacket, IPubrelPacket, ISubscribePacket, ISubscription, IUnsubscribePacket } from 'mqtt-packet'
-  import { Client } from 'aedes:client'
+import { AedesPacket } from 'aedes-packet'
+import {
+  IConnackPacket,
+  IConnectPacket,
+  IPingreqPacket,
+  IPublishPacket,
+  IPubrelPacket,
+  ISubscribePacket,
+  ISubscription,
+  IUnsubscribePacket
+} from 'mqtt-packet'
+import { Client } from './client'
 
-  export type SubscribePacket = ISubscribePacket & { cmd: 'subscribe' }
-  export type UnsubscribePacket = IUnsubscribePacket & { cmd: 'unsubscribe' }
-  export type Subscription = ISubscription & { clientId?: Client['id'] }
-  export type Subscriptions = { subscriptions: Subscription[] }
+export type SubscribePacket = ISubscribePacket & { cmd: 'subscribe' };
+export type UnsubscribePacket = IUnsubscribePacket & { cmd: 'unsubscribe' };
+export type Subscription = ISubscription & { clientId?: Client['id'] };
+export type Subscriptions = { subscriptions: Subscription[] };
 
-  export type PublishPacket = IPublishPacket & { cmd: 'publish' }
+export type PublishPacket = IPublishPacket & { cmd: 'publish' };
 
-  export type ConnectPacket = IConnectPacket & { cmd: 'connect' }
-  export type ConnackPacket = IConnackPacket & { cmd: 'connack' }
+export type ConnectPacket = IConnectPacket & { cmd: 'connect' };
+export type ConnackPacket = IConnackPacket & { cmd: 'connack' };
 
-  export type PubrelPacket = IPubrelPacket & { cmd: 'pubrel' }
-  export type PingreqPacket = IPingreqPacket & { cmd: 'pingreq' }
+export type PubrelPacket = IPubrelPacket & { cmd: 'pubrel' };
+export type PingreqPacket = IPingreqPacket & { cmd: 'pingreq' };
 
-  export type AedesPublishPacket = PublishPacket & AedesPacket
-}
-declare module 'aedes:packet' {
-  export * from 'packet'
-}
+export type AedesPublishPacket = PublishPacket & AedesPacket;
diff --git a/types/tsconfig.json b/types/tsconfig.json
index 271cd26..1381611 100644
--- a/types/tsconfig.json
+++ b/types/tsconfig.json
@@ -5,11 +5,11 @@
     "noEmit": true,
     "strict": true,
     "removeComments": true,
-    "typeRoots" : ["../types", "../node_modules/@types/"]
+    "typeRoots" : ["./", "../node_modules/@types/"]
   },
   "include": [
-    "./test/types/*.test-d.ts",
-    "./types/*.d.ts",
-    "aedes.d.ts"
+    "../test/types/*.test-d.ts",
+    "./*.d.ts",
+    "../aedes.d.ts"
   ]
 }


Test patch:
diff --git a/test/basic.js b/test/basic.js
index 1638847..6ca103f 100644
--- a/test/basic.js
+++ b/test/basic.js
@@ -6,10 +6,10 @@ const { setup, connect, subscribe, subscribeMultiple, noError } = require('./hel
 const aedes = require('../')
 const proxyquire = require('proxyquire')
 
-test('test aedes.Server', function (t) {
+test('test aedes.createBroker', function (t) {
   t.plan(1)
 
-  const broker = new aedes.Server()
+  const broker = aedes.createBroker()
   t.teardown(broker.close.bind(broker))
 
   connect(setup(broker), {}, function () {
diff --git a/test/types/aedes.test-d.ts b/test/types/aedes.test-d.ts
index c3be3ff..abac7ca 100644
--- a/test/types/aedes.test-d.ts
+++ b/test/types/aedes.test-d.ts
@@ -1,16 +1,18 @@
-/// <reference path="../../aedes.d.ts" />
-
-import type { AedesPublishPacket, ConnackPacket, ConnectPacket, PingreqPacket, PublishPacket, PubrelPacket, SubscribePacket, Subscription, UnsubscribePacket } from 'aedes:packet'
-import type { AuthenticateError, Brokers, Connection } from 'aedes:server'
-import Server, { Aedes } from 'aedes:server'
 
 import { IncomingMessage } from 'node:http'
-import type { Client } from 'aedes:client'
 import { Socket } from 'node:net'
+import type {
+  Brokers,
+  AuthenticateError,
+  Client,
+  Connection
+} from '../../aedes'
+import Aedes, { createBroker } from '../../aedes'
+import type { AedesPublishPacket, ConnackPacket, ConnectPacket, PingreqPacket, PublishPacket, PubrelPacket, Subscription, SubscribePacket, UnsubscribePacket } from '../../types/packet'
 import { expectType } from 'tsd'
 
 // Aedes server
-let broker = new Server()
+let broker = createBroker()
 expectType<Aedes>(broker)
 
 broker = new Aedes({
@@ -29,8 +31,17 @@ broker = new Aedes({
       callback(new Error('connection error'), false)
     }
   },
-  authenticate: (client: Client, username: Readonly<string | undefined>, password: Readonly<Buffer | undefined>, callback) => {
-    if (username === 'test' && password === Buffer.from('test') && client.version === 4) {
+  authenticate: (
+    client: Client,
+    username: Readonly<string | undefined>,
+    password: Readonly<Buffer | undefined>,
+    callback
+  ) => {
+    if (
+      username === 'test' &&
+      password === Buffer.from('test') &&
+      client.version === 4
+    ) {
       callback(null, true)
     } else {
       const error = new Error() as AuthenticateError
@@ -39,7 +50,11 @@ broker = new Aedes({
       callback(error, false)
     }
   },
-  authorizePublish: (client: Client | null, packet: PublishPacket, callback) => {
+  authorizePublish: (
+    client: Client | null,
+    packet: PublishPacket,
+    callback
+  ) => {
     if (packet.topic === 'aaaa') {
       return callback(new Error('wrong topic'))
     }
@@ -66,7 +81,10 @@ broker = new Aedes({
     if (packet.topic === 'aaaa' && client.id === 'I should not see this') {
       return null
       // also works with return undefined
-    } else if (packet.topic === 'aaaa' && client.id === 'I should not see this either') {
+    } else if (
+      packet.topic === 'aaaa' &&
+      client.id === 'I should not see this either'
+    ) {
       return
     }
 
@@ -91,75 +109,107 @@ expectType<Aedes>(broker.on('client', (client: Client) => {}))
 expectType<Aedes>(broker.on('clientReady', (client: Client) => {}))
 expectType<Aedes>(broker.on('clientDisconnect', (client: Client) => {}))
 expectType<Aedes>(broker.on('keepaliveTimeout', (client: Client) => {}))
-expectType<Aedes>(broker.on('clientError', (client: Client, error: Error) => {}))
-expectType<Aedes>(broker.on('connectionError', (client: Client, error: Error) => {}))
-expectType<Aedes>(broker.on('connackSent', (packet: ConnackPacket, client: Client) => {}))
-expectType<Aedes>(broker.on('ping', (packet: PingreqPacket, client: Client) => {}))
-expectType<Aedes>(broker.on('publish', (packet: AedesPublishPacket, client: Client | null) => {}))
-expectType<Aedes>(broker.on('ack', (packet: PublishPacket | PubrelPacket, client: Client) => {}))
-expectType<Aedes>(broker.on('subscribe', (subscriptions: Subscription[], client: Client) => {}))
-expectType<Aedes>(broker.on('unsubscribe', (unsubscriptions: string[], client: Client) => {}))
-
-expectType<void>(broker.publish(
-  {} as PublishPacket,
-  (error?: Error) => {
+expectType<Aedes>(
+  broker.on('clientError', (client: Client, error: Error) => {})
+)
+expectType<Aedes>(
+  broker.on('connectionError', (client: Client, error: Error) => {})
+)
+expectType<Aedes>(
+  broker.on('connackSent', (packet: ConnackPacket, client: Client) => {})
+)
+expectType<Aedes>(
+  broker.on('ping', (packet: PingreqPacket, client: Client) => {})
+)
+expectType<Aedes>(
+  broker.on(
+    'publish',
+    (packet: AedesPublishPacket, client: Client | null) => {}
+  )
+)
+expectType<Aedes>(
+  broker.on('ack', (packet: PublishPacket | PubrelPacket, client: Client) => {})
+)
+expectType<Aedes>(
+  broker.on('subscribe', (subscriptions: Subscription[], client: Client) => {})
+)
+expectType<Aedes>(
+  broker.on('unsubscribe', (unsubscriptions: string[], client: Client) => {})
+)
+
+expectType<void>(
+  broker.publish({} as PublishPacket, (error?: Error) => {
     if (error) {
       console.error(error)
     }
-  }
-))
-
-expectType<void>(broker.subscribe(
-  'topic',
-  (packet: AedesPublishPacket, callback: () => void) => {},
-  () => {}
-))
-
-expectType<void>(broker.unsubscribe(
-  'topic',
-  (packet: AedesPublishPacket, callback: () => void) => {},
-  () => {}
-))
+  })
+)
+
+expectType<void>(
+  broker.subscribe(
+    'topic',
+    (packet: AedesPublishPacket, callback: () => void) => {},
+    () => {}
+  )
+)
+
+expectType<void>(
+  broker.unsubscribe(
+    'topic',
+    (packet: AedesPublishPacket, callback: () => void) => {},
+    () => {}
+  )
+)
 
 expectType<void>(broker.close())
 expectType<void>(broker.close(() => {}))
 
 // Aedes client
 const client = broker.handle({} as Connection, {} as IncomingMessage)
+const client2 = broker.handle({} as Connection)
 
 expectType<Client>(client)
+expectType<Client>(client2)
 
 expectType<Connection>(client.conn)
 expectType<IncomingMessage>(client.req!)
 
 expectType<Client>(client.on('connected', () => {}))
-expectType<Client>(client.on('error', (error: Error) => {
-  if (error) {
-    console.error(error)
-  }
-}))
+expectType<Client>(
+  client.on('error', (error: Error) => {
+    if (error) {
+      console.error(error)
+    }
+  })
+)
 
-expectType<void>(client.publish({} as PublishPacket, (error?: Error) => {
-  if (error) {
-    console.error(error)
-  }
-}))
+expectType<void>(
+  client.publish({} as PublishPacket, (error?: Error) => {
+    if (error) {
+      console.error(error)
+    }
+  })
+)
 expectType<void>(client.publish({} as PublishPacket))
 
-expectType<void>(client.subscribe({} as Subscription, (error?: Error) => {
-  if (error) {
-    console.error(error)
-  }
-}))
+expectType<void>(
+  client.subscribe({} as Subscription, (error?: Error) => {
+    if (error) {
+      console.error(error)
+    }
+  })
+)
 expectType<void>(client.subscribe({} as Subscription))
 expectType<void>(client.subscribe([] as Subscription[]))
 expectType<void>(client.subscribe({} as SubscribePacket))
 
-expectType<void>(client.unsubscribe({} as Subscription, (error?: Error) => {
-  if (error) {
-    console.error(error)
-  }
-}))
+expectType<void>(
+  client.unsubscribe({} as Subscription, (error?: Error) => {
+    if (error) {
+      console.error(error)
+    }
+  })
+)
 expectType<void>(client.unsubscribe({} as Subscription))
 expectType<void>(client.unsubscribe([] as Subscription[]))
 expectType<void>(client.unsubscribe({} as UnsubscribePacket))