From 46838aa3bfcf7f200a37aa1227fb499ea3d4843f Mon Sep 17 00:00:00 2001 From: Ishan Ravindu Date: Tue, 4 Apr 2023 14:38:01 +0530 Subject: [PATCH] Rewrite with typescript --- .gitignore | 2 +- example/example-stopwatch.ts | 13 ++++ index.js | 1 - lib/stopwatch.js | 60 ------------------ package-lock.json | 38 ++++++++++++ package.json | 12 ++-- src/index.ts | 1 + src/lib/stopwatch.ts | 70 +++++++++++++++++++++ test/manager.test.js | 31 ---------- test/stopwatch.test.js | 114 ----------------------------------- tsconfig.json | 29 +++++++++ 11 files changed, 158 insertions(+), 213 deletions(-) create mode 100644 example/example-stopwatch.ts delete mode 100644 index.js delete mode 100644 lib/stopwatch.js create mode 100644 package-lock.json create mode 100644 src/index.ts create mode 100644 src/lib/stopwatch.ts delete mode 100644 test/manager.test.js delete mode 100644 test/stopwatch.test.js create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 1d37fc0..ddd9158 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ node_modules .tmp_*~ *# .#* - +dist/ \ No newline at end of file diff --git a/example/example-stopwatch.ts b/example/example-stopwatch.ts new file mode 100644 index 0000000..a367230 --- /dev/null +++ b/example/example-stopwatch.ts @@ -0,0 +1,13 @@ +import { Stopwatch} from "../src/index"; + +const stopwatch = new Stopwatch(1, { seconds: 10 }); + +stopwatch.on('tick', (seconds) => { + console.log(`${seconds} seconds remaining`); +}); + +stopwatch.on('end', () => { + console.log('Stopwatch ended'); +}); + +stopwatch.start(); \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index b47652d..0000000 --- a/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/stopwatch'); diff --git a/lib/stopwatch.js b/lib/stopwatch.js deleted file mode 100644 index dd84d11..0000000 --- a/lib/stopwatch.js +++ /dev/null @@ -1,60 +0,0 @@ -var EventEmitter = require('events').EventEmitter; -var stopwatches = {}; - -function Stopwatch(id, options) { - EventEmitter.call(this); - - this.id = id; - this.seconds = options.seconds || 10; - this.interval = (options.interval || options.interval == 0) ? options.interval : 1000; - this.timer = null; -} - -Stopwatch.prototype.__proto__ = EventEmitter.prototype; - -Stopwatch.prototype.stop = function() { - clearInterval(this.timer); - this.timer = null; -}; - -Stopwatch.prototype.start = function() { - if (this.started()) { return false; } - - var self = this; - - self.timer = setInterval(function () { - self.emit('tick', self.seconds); - - if (--self.seconds < 0) { - self.stop(); - self.emit('end'); - } - }, self.interval); - - return true; -}; - -Stopwatch.prototype.started = function() { - return !!this.timer; -}; - -Stopwatch.prototype.restart = function() { - this.stop(); - this.removeAllListeners('tick'); - this.removeAllListeners('end'); - this.start(); -}; - -module.exports = { - Stopwatch : Stopwatch, - get: function(id, options) { - if (!stopwatches[id]) { - stopwatches[id] = new Stopwatch(id, options); - stopwatches[id].on('end', function() { - stopwatches[id] = null; - delete stopwatches[id]; - }); - } - return stopwatches[id]; - } -}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aaa82fb --- /dev/null +++ b/package-lock.json @@ -0,0 +1,38 @@ +{ + "name": "stopwatch", + "version": "0.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "stopwatch", + "version": "0.2.0", + "devDependencies": { + "@types/node": "^18.15.11", + "typescript": "^5.0.3" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + } + } +} diff --git a/package.json b/package.json index 179769b..da87e7b 100644 --- a/package.json +++ b/package.json @@ -8,16 +8,16 @@ "type": "git", "url": "git://github.com/emerleite/node-stopwatch.git" }, - "main": "index.js", + "main": "dist/index.js", + "typings": "dist/index.d.ts", "scripts": { - "test": "node_modules/mocha/bin/mocha -R spec" + "build": "tsc -d -p ." }, "engines": { "node": ">=0.8.0" }, - "dependencies": {}, - "devDependencies": { - "mocha" : "2.0.1", - "should" : "4.3.0" + "devDependencies": { + "@types/node": "^18.15.11", + "typescript": "^5.0.3" } } diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..bdbf49f --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export { Stopwatch,StopwatchManager} from "./lib/stopwatch"; \ No newline at end of file diff --git a/src/lib/stopwatch.ts b/src/lib/stopwatch.ts new file mode 100644 index 0000000..27f5f1f --- /dev/null +++ b/src/lib/stopwatch.ts @@ -0,0 +1,70 @@ +import { EventEmitter } from 'events'; + +interface StopwatchOptions { + seconds?: number; + interval?: number; +} + +class Stopwatch extends EventEmitter { + private seconds: number; + private interval: number; + private timer: NodeJS.Timeout | null = null; + + constructor(private id: number, options: StopwatchOptions = {}) { + super(); + this.seconds = options.seconds ?? 10; + this.interval = (options.interval || options.interval === 0) ? options.interval : 1000; + } + + public stop(): void { + if (this.timer) { + clearInterval(this.timer); + this.timer = null; + } + } + + public start(): boolean { + if (this.started()) { + return false; + } + + this.timer = setInterval(() => { + this.emit('tick', this.seconds); + + if (--this.seconds < 0) { + this.stop(); + this.emit('end'); + } + }, this.interval); + + return true; + } + + public started(): boolean { + return !!this.timer; + } + + public restart(): void { + this.stop(); + this.removeAllListeners('tick'); + this.removeAllListeners('end'); + this.start(); + } +} + +class StopwatchManager { + private static stopwatches: Record = {}; + + public static get(id: number, options: StopwatchOptions = {}): Stopwatch { + if (!StopwatchManager.stopwatches[id]) { + StopwatchManager.stopwatches[id] = new Stopwatch(id, options); + StopwatchManager.stopwatches[id].on('end', () => { + delete StopwatchManager.stopwatches[id]; + }); + } + + return StopwatchManager.stopwatches[id]; + } +} + +export { Stopwatch, StopwatchManager}; diff --git a/test/manager.test.js b/test/manager.test.js deleted file mode 100644 index 804cfaf..0000000 --- a/test/manager.test.js +++ /dev/null @@ -1,31 +0,0 @@ -var should = require('should'); -var StopwatchManager = require('../lib/stopwatch'); - -describe('StopwatchManager', function() { - var stopwatch = StopwatchManager.get(1, {seconds: 1, interval: 0}); - - describe('getting an instance', function() { - var subject = StopwatchManager.get(1); - - it('should have the same seconds', function() { - subject.seconds.should.equal(stopwatch.seconds); - }); - - it('should have the same interval', function() { - subject.interval.should.equal(stopwatch.interval); - }); - }); - - describe('when the time ends', function() { - it('should create a new instance', function(done) { - stopwatch.start(); - stopwatch.on('end', function() { - var subject = StopwatchManager.get(1, { seconds: 10, interval: 2000 }); - subject.seconds.should.equal(10); - subject.interval.should.equal(2000); - done(); - }); - }); - - }); -}); diff --git a/test/stopwatch.test.js b/test/stopwatch.test.js deleted file mode 100644 index 046447e..0000000 --- a/test/stopwatch.test.js +++ /dev/null @@ -1,114 +0,0 @@ -var should = require('should'); -var Stopwatch = require('../lib/stopwatch').Stopwatch; - -describe('Stopwatch', function() { - var stopwatch = null; - - beforeEach(function() { - stopwatch = new Stopwatch(1, { interval:0 }); - }); - - describe('events', function() { - describe('tick and end', function() { - beforeEach(function() { - stopwatch.start(); - }); - - it('should emit tick N times based on', function(done) { - var left = 10; - stopwatch.on('tick', function(secondsLeft) { - secondsLeft.should.equal(left--); - if (left < 0) { done(); } - }); - }); - - it('should emit an end event', function(done) { - stopwatch.on('end', done); - }); - }); - }); - - describe('#start', function() { - it('should return true when first time', function() { - stopwatch.start().should.be.true; - }); - - it('should return false when sencod time', function() { - stopwatch.start(); - stopwatch.start().should.be.false; - }); - }); - - describe('#stop', function() { - it('should not be started', function() { - stopwatch.start(); - stopwatch.stop(); - stopwatch.started().should.be.false - }); - - it('should allow a new start', function() { - stopwatch.stop(); - stopwatch.start().should.be.true; - }); - }); - - describe('#restart', function() { - describe('when already started', function() { - beforeEach(function() { - stopwatch.start(); - }); - - it('should be started', function() { - stopwatch.restart(); - stopwatch.started().should.be.true; - }); - - describe('when has listeners', function() { - beforeEach(function() { - stopwatch.on('tick', function() {}); - stopwatch.on('end', function() {}); - stopwatch.restart(); - }); - - it('should remove all tick listeners', function() { - stopwatch.listeners('tick').length.should.equal(0); - }); - - it('should remove all end listeners', function() { - stopwatch.listeners('end').length.should.equal(0); - }); - }); - }); - - describe('when stopped', function() { - beforeEach(function() { - stopwatch.start(); - stopwatch.stop(); - }); - - it('should be started', function() { - stopwatch.restart(); - stopwatch.started().should.be.true; - }); - }); - }); - - describe('#started', function() { - it('should not be started without calling #start', function() { - stopwatch.started().should.be.false; - }); - - it('should be started after calling #start', function() { - stopwatch.start(); - stopwatch.started().should.be.true; - }); - - it('should not be started when end', function(done) { - stopwatch.start(); - stopwatch.on('end', function() { - stopwatch.started().should.be.false; - done(); - }); - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ef8edf --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2017", + "esModuleInterop": true, + "noImplicitAny": true, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true, + "strict": true, + "lib": [ + "es2017", + "esnext.asynciterable", + "dom" + ], + "outDir": "dist", + "baseUrl": ".", + "paths": { + "*": [ + "node_modules/*", + "src/types/*" + ] + } + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file