Skip to content

Commit

Permalink
feat(UdpServer)!: UdpServer export was changed to a class instance (#40)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Changed from an object to a class instance that may
break consuming code in some edge cases.
  • Loading branch information
plasticrake authored Nov 9, 2023
1 parent 69920e0 commit ecc96d0
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 33 deletions.
20 changes: 20 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"source-map-support": "^0.5.21",
"ts-essentials": "^9.4.1",
"ts-node": "^10.9.1",
"typed-emitter": "^2.1.0",
"typescript": "~5.2.2"
},
"engines": {
Expand Down
58 changes: 28 additions & 30 deletions src/udp-server.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@
import EventEmitter from 'events';
import dgram from 'dgram';
import dgram from 'node:dgram';
import EventEmitter from 'node:events';

import debug from 'debug';
import type TypedEmitter from 'typed-emitter';

const log = debug('tplink-simulator:udp-server');
const logErr = debug('tplink-simulator:udp-server:error');

interface UdpServerType extends EventEmitter {
start: () => Promise<UdpServerType>;
stop: () => void;
socketBound: boolean;
socket?: dgram.Socket;
}

const Emitter = new EventEmitter();
Emitter.setMaxListeners(25);
type UdpServerEvents = {
message: (msg: Buffer, rinfo: dgram.RemoteInfo) => void;
};

const UdpServer: UdpServerType = Object.assign(Emitter, {
socketBound: false,
class UdpServer extends (EventEmitter as new () => TypedEmitter<UdpServerEvents>) {
socketBound = false;

socket: undefined,
socket: dgram.Socket | undefined = undefined;

start: function start({ port = 9999 } = {}): Promise<UdpServerType> {
const self = UdpServer;
constructor() {
super();
this.setMaxListeners(25);
}

start({ port = 9999 } = {}): Promise<UdpServer> {
return new Promise((resolve, reject) => {
try {
const socket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
self.socket = socket;
this.socket = socket;

socket.on('listening', () => {
const address = socket.address();
self.socketBound = true;
this.socketBound = true;
log('UDP server listening', address);
resolve(UdpServer);
resolve(this);
});

socket.on('message', (msg, rinfo) => {
self.emit('message', msg, rinfo);
this.emit('message', msg, rinfo);
});

socket.on('error', (exception) => {
logErr(exception);
socket.close();
self.socketBound = false;
this.socketBound = false;
reject(exception);
});

Expand All @@ -51,15 +50,14 @@ const UdpServer: UdpServerType = Object.assign(Emitter, {
reject(err);
}
});
},
}

stop: function stop() {
const self = UdpServer;
if (self.socketBound) {
if (self.socket != null) self.socket.close();
self.socketBound = false;
stop() {
if (this.socketBound) {
if (this.socket != null) this.socket.close();
this.socketBound = false;
}
},
});
}
}

export default UdpServer as UdpServerType;
export default new UdpServer();
13 changes: 10 additions & 3 deletions test/udp-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ const { UdpServer } = require('../src');

describe('UdpServer', function () {
this.retries(2);
describe('self', function () {
it('is a singleton', function () {
// eslint-disable-next-line global-require
expect(UdpServer).to.equal(require('../src').UdpServer);
});
});
describe('.start()', function () {
it('defaults', async function () {
await UdpServer.start();
Expand All @@ -28,12 +34,13 @@ describe('UdpServer', function () {
expect(UdpServer.socketBound).to.be.false;
});
it('does nothing if not started', function () {
expect(UdpServer.stop).to.not.throw();
expect(() => UdpServer.stop()).to.not.throw();
});
it('does nothing when stopped twice', async function () {
await UdpServer.start();
expect(UdpServer.stop).to.not.throw();
expect(UdpServer.stop).to.not.throw();

expect(() => UdpServer.stop()).to.not.throw();
expect(() => UdpServer.stop()).to.not.throw();
});
});
});

0 comments on commit ecc96d0

Please sign in to comment.