feat: tiny event dispatcher

This commit is contained in:
Michal Szczepanski 2023-06-14 05:35:19 +02:00
parent 0af06e63d9
commit bbddec8ead
6 changed files with 176 additions and 6 deletions

2
.gitignore vendored

@ -1,3 +1,5 @@
node_modules node_modules
dist dist
.parcel-cache .parcel-cache
*.iml

4
.npmignore Normal file

@ -0,0 +1,4 @@
node_modules
.parcel-cache
*.iml

3
bin/cloc Executable file

@ -0,0 +1,3 @@
#!/bin/bash
git shortlog -sne
cloc src/

97
package-lock.json generated

@ -1,14 +1,20 @@
{ {
"name": "typescript-parcel-base", "name": "@pinmenote/tiny-dispatcher",
"version": "0.0.1", "version": "0.0.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "typescript-parcel-base", "name": "@pinmenote/tiny-dispatcher",
"version": "0.0.1", "version": "0.0.1",
"license": "MIT",
"dependencies": {
"nanoid": "^4.0.2"
},
"devDependencies": { "devDependencies": {
"@parcel/packager-ts": "^2.8.3",
"@parcel/transformer-typescript-tsc": "^2.8.3", "@parcel/transformer-typescript-tsc": "^2.8.3",
"@parcel/transformer-typescript-types": "^2.8.3",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2", "@typescript-eslint/parser": "^5.48.2",
@ -1018,6 +1024,23 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
} }
}, },
"node_modules/@parcel/packager-ts": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/packager-ts/-/packager-ts-2.8.3.tgz",
"integrity": "sha512-8JooYHjKntHnQywLT7LAnfoGiAQ1fUu0N2DtuM0PxpgQqYJ4KE9TZS+SZq7hpe24cZkD0A4A+1kBlYAyvuanrg==",
"dev": true,
"dependencies": {
"@parcel/plugin": "2.8.3"
},
"engines": {
"node": ">= 12.0.0",
"parcel": "^2.8.3"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/plugin": { "node_modules/@parcel/plugin": {
"version": "2.8.3", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz", "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz",
@ -1447,6 +1470,31 @@
"typescript": ">=3.0.0" "typescript": ">=3.0.0"
} }
}, },
"node_modules/@parcel/transformer-typescript-types": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.8.3.tgz",
"integrity": "sha512-zjsJsgecjw4X1nt5R7A61uWwzwCce0usKKPqnE5tQpYtF4FfK5X69r0l5JLovlyaT2uwoe+hvhu2AELA0kKRQA==",
"dev": true,
"dependencies": {
"@parcel/diagnostic": "2.8.3",
"@parcel/plugin": "2.8.3",
"@parcel/source-map": "^2.1.1",
"@parcel/ts-utils": "2.8.3",
"@parcel/utils": "2.8.3",
"nullthrows": "^1.1.1"
},
"engines": {
"node": ">= 12.0.0",
"parcel": "^2.8.3"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"peerDependencies": {
"typescript": ">=3.0.0"
}
},
"node_modules/@parcel/ts-utils": { "node_modules/@parcel/ts-utils": {
"version": "2.8.3", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/ts-utils/-/ts-utils-2.8.3.tgz", "resolved": "https://registry.npmjs.org/@parcel/ts-utils/-/ts-utils-2.8.3.tgz",
@ -3387,6 +3435,23 @@
"@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0" "@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0"
} }
}, },
"node_modules/nanoid": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^14 || ^16 || >=18"
}
},
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -5050,6 +5115,15 @@
"posthtml": "^0.16.4" "posthtml": "^0.16.4"
} }
}, },
"@parcel/packager-ts": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/packager-ts/-/packager-ts-2.8.3.tgz",
"integrity": "sha512-8JooYHjKntHnQywLT7LAnfoGiAQ1fUu0N2DtuM0PxpgQqYJ4KE9TZS+SZq7hpe24cZkD0A4A+1kBlYAyvuanrg==",
"dev": true,
"requires": {
"@parcel/plugin": "2.8.3"
}
},
"@parcel/plugin": { "@parcel/plugin": {
"version": "2.8.3", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz", "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz",
@ -5312,6 +5386,20 @@
"@parcel/ts-utils": "2.8.3" "@parcel/ts-utils": "2.8.3"
} }
}, },
"@parcel/transformer-typescript-types": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.8.3.tgz",
"integrity": "sha512-zjsJsgecjw4X1nt5R7A61uWwzwCce0usKKPqnE5tQpYtF4FfK5X69r0l5JLovlyaT2uwoe+hvhu2AELA0kKRQA==",
"dev": true,
"requires": {
"@parcel/diagnostic": "2.8.3",
"@parcel/plugin": "2.8.3",
"@parcel/source-map": "^2.1.1",
"@parcel/ts-utils": "2.8.3",
"@parcel/utils": "2.8.3",
"nullthrows": "^1.1.1"
}
},
"@parcel/ts-utils": { "@parcel/ts-utils": {
"version": "2.8.3", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/@parcel/ts-utils/-/ts-utils-2.8.3.tgz", "resolved": "https://registry.npmjs.org/@parcel/ts-utils/-/ts-utils-2.8.3.tgz",
@ -6624,6 +6712,11 @@
"node-gyp-build-optional-packages": "5.0.3" "node-gyp-build-optional-packages": "5.0.3"
} }
}, },
"nanoid": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
},
"natural-compare": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",

@ -1,9 +1,19 @@
{ {
"name": "typescript-parcel-base", "name": "@pinmenote/tiny-dispatcher",
"version": "0.0.1", "version": "0.0.1",
"author": "Michal Szczepanski",
"license": "MIT",
"description": "tiny event dispatcher",
"bugs": {
"url": "https://github.com/pinmenote/tiny-dispatcher/issues"
},
"homepage": "https://github.com/pinmenote/tiny-dispatcher#readme",
"source": "src/tiny.dispatcher.ts",
"module": "dist/module.js",
"types": "dist/types.d.ts",
"scripts": { "scripts": {
"dev": "parcel src/index.html", "build": "parcel build",
"prod": "parcel build src/index.html", "dev": "NODE_ENV=development parcel build",
"lint": "eslint --ext .ts src/", "lint": "eslint --ext .ts src/",
"lint:fix": "eslint --ext .ts,.tsx src/ --fix" "lint:fix": "eslint --ext .ts,.tsx src/ --fix"
}, },
@ -11,7 +21,9 @@
"lint" "lint"
], ],
"devDependencies": { "devDependencies": {
"@parcel/packager-ts": "^2.8.3",
"@parcel/transformer-typescript-tsc": "^2.8.3", "@parcel/transformer-typescript-tsc": "^2.8.3",
"@parcel/transformer-typescript-types": "^2.8.3",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2", "@typescript-eslint/parser": "^5.48.2",
@ -21,5 +33,8 @@
"parcel": "^2.8.3", "parcel": "^2.8.3",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"typescript": "^4.9.4" "typescript": "^4.9.4"
},
"dependencies": {
"nanoid": "^4.0.2"
} }
} }

53
src/tiny.dispatcher.ts Normal file

@ -0,0 +1,53 @@
import { customAlphabet } from 'nanoid';
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
const alphabet: (size: number) => string = customAlphabet('abcdefghijklmnopqrstuwxyz0123456789');
const uid = (size = 10): string => {
return alphabet(size);
};
export class TinyDispatcher {
private static listeners: { [key: string]: { [key: string]: any } } = {};
private static once: { [key: string]: string } = {};
static addListener<T>(event: string, handler: (event: string, key: string, value: T) => void, once = false): string {
if (!this.listeners[event]) {
this.listeners[event] = {};
}
const key = uid();
if (once) this.once[key] = event;
this.listeners[event][key] = handler;
return key;
}
static dispatch<T>(event: string, value?: T): void {
if (this.listeners[event]) {
for (const key in this.listeners[event]) {
this.listeners[event][key](event, key, value); // eslint-disable-line @typescript-eslint/no-unsafe-call
if (this.once[key]) {
this.removeListener(event, key);
delete this.once[key];
}
}
}
}
static removeListener(event: string, key: string): boolean {
if (!this.listeners[event]) return false;
if (this.listeners[event][key]) {
delete this.listeners[event][key];
return true;
}
return false;
}
static removeAllListener(event: string): boolean {
if (!this.listeners[event]) return false;
delete this.listeners[event];
return true;
}
static cleanup() {
this.listeners = {};
}
}