Initial Commit

This commit is contained in:
2026-01-15 21:52:12 +01:00
committed by erik
parent 3ed42cdeb6
commit 5a70f775f1
6702 changed files with 1389544 additions and 0 deletions

79
node_modules/strict-event-emitter/README.md generated vendored Normal file
View File

@@ -0,0 +1,79 @@
# Strict Event Emitter
A type-safe implementation of `EventEmitter` for browser and Node.js.
## Motivation
Despite event emitters potentially accepting any runtime value, defining a strict event contract is crucial when developing complex event-driven architectures. Unfortunately, the native type definitions for Node's `EventEmitter` annotate event names as `string`, which forbids any stricter type validation.
```js
// index.js
const emitter = new EventEmitter()
// Let's say our application expects a "ping"
// event with the number payload.
emitter.on('ping', (n: number) => {})
// We can, however, emit a different event by mistake.
emitter.emit('pong', 1)
// Or even the correct event with the wrong data.
emitter.emit('ping', 'wait, not a number')
```
The purpose of this library is to provide an `EventEmitter` instance that can accept a generic describing the expected events contract.
```ts
import { Emitter } from 'strict-event-emitter'
// Define a strict events contract where keys
// represent event names and values represent
// the list of arguments expected in ".emit()".
type Events = {
ping: [number]
}
const emitter = new Emitter<Events>()
emitter.addListener('ping', (n) => {
// "n" argument type is inferred as "number'.
})
emitter.emit('ping', 10) // OK
emitter.emit('unknown', 10) // TypeError (invalid event name)
emitter.emit('ping', 'wait, not a number') // TypeError (invalid data)
```
This library is also a custom `EventEmitter` implementation, which makes it compatible with other environments, like browsers or React Native.
## Getting started
### Install
```bash
npm install strict-event-emitter
```
### Use
```ts
import { Emitter } from 'strict-event-emitter'
// 1. Define an interface that describes your events.
// Set event names as the keys, and their expected payloads as values.
interface Events {
connect: [id: string]
disconnect: [id: string]
}
// 2. Create a strict emitter and pass the previously defined "Events"
// as its first generic argument.
const emitter = new Emitter<Events>()
// 3. Use the "emitter" the same way you'd use the regular "EventEmitter" instance.
emitter.addListener('connect', (id) => {})
emitter.emit('connect', 'abc-123')
```
## License
MIT

81
node_modules/strict-event-emitter/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,81 @@
declare type EventMap = {
[eventName: string]: Array<unknown>;
};
declare type InternalEventNames = 'newListener' | 'removeListener';
declare type InternalListener<Events extends EventMap> = Listener<[
eventName: keyof Events,
listener: Listener<Array<unknown>>
]>;
declare type Listener<Data extends Array<unknown>> = (...data: Data) => void;
/**
* Node.js-compatible implementation of `EventEmitter`.
*
* @example
* const emitter = new Emitter<{ hello: [string] }>()
* emitter.on('hello', (name) => console.log(name))
* emitter.emit('hello', 'John')
*/
declare class Emitter<Events extends EventMap> {
private events;
private maxListeners;
private hasWarnedAboutPotentialMemoryLeak;
static defaultMaxListeners: number;
static listenerCount<Events extends EventMap>(emitter: Emitter<EventMap>, eventName: keyof Events): number;
constructor();
private _emitInternalEvent;
private _getListeners;
private _removeListener;
private _wrapOnceListener;
setMaxListeners(maxListeners: number): this;
/**
* Returns the current max listener value for the `Emitter` which is
* either set by `emitter.setMaxListeners(n)` or defaults to
* `Emitter.defaultMaxListeners`.
*/
getMaxListeners(): number;
/**
* Returns an array listing the events for which the emitter has registered listeners.
* The values in the array will be strings or Symbols.
*/
eventNames(): Array<keyof Events>;
/**
* Synchronously calls each of the listeners registered for the event named `eventName`,
* in the order they were registered, passing the supplied arguments to each.
* Returns `true` if the event has listeners, `false` otherwise.
*
* @example
* const emitter = new Emitter<{ hello: [string] }>()
* emitter.emit('hello', 'John')
*/
emit<EventName extends keyof Events>(eventName: EventName, ...data: Events[EventName]): boolean;
addListener(eventName: InternalEventNames, listener: InternalListener<Events>): this;
addListener<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
on(eventName: InternalEventNames, listener: InternalListener<Events>): this;
on<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
once(eventName: InternalEventNames, listener: InternalListener<Events>): this;
once<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
prependListener(eventName: InternalEventNames, listener: InternalListener<Events>): this;
prependListener<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
prependOnceListener(eventName: InternalEventNames, listener: InternalListener<Events>): this;
prependOnceListener<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
removeListener(eventName: InternalEventNames, listener: InternalListener<Events>): this;
removeListener<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
off(eventName: InternalEventNames, listener: InternalListener<Events>): this;
off<EventName extends keyof Events>(eventName: EventName, listener: Listener<Events[EventName]>): this;
removeAllListeners(eventName?: InternalEventNames): this;
removeAllListeners<EventName extends keyof Events>(eventName?: EventName): this;
listeners(eventName: InternalEventNames): Array<Listener<any>>;
listeners<EventName extends keyof Events>(eventName: EventName): Array<Listener<Events[EventName]>>;
listenerCount(eventName: InternalEventNames): number;
listenerCount<EventName extends keyof Events>(eventName: EventName): number;
rawListeners<EventName extends keyof Events>(eventName: EventName): Array<Listener<Events[EventName]>>;
}
declare class MemoryLeakError extends Error {
readonly emitter: Emitter<any>;
readonly type: string | number | symbol;
readonly count: number;
constructor(emitter: Emitter<any>, type: string | number | symbol, count: number);
}
export { Emitter, EventMap, InternalEventNames, InternalListener, Listener, MemoryLeakError };

198
node_modules/strict-event-emitter/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,198 @@
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
Emitter: () => Emitter,
MemoryLeakError: () => MemoryLeakError
});
module.exports = __toCommonJS(src_exports);
// src/MemoryLeakError.ts
var MemoryLeakError = class extends Error {
constructor(emitter, type, count) {
super(
`Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit`
);
this.emitter = emitter;
this.type = type;
this.count = count;
this.name = "MaxListenersExceededWarning";
}
};
// src/Emitter.ts
var _Emitter = class {
static listenerCount(emitter, eventName) {
return emitter.listenerCount(eventName);
}
constructor() {
this.events = /* @__PURE__ */ new Map();
this.maxListeners = _Emitter.defaultMaxListeners;
this.hasWarnedAboutPotentialMemoryLeak = false;
}
_emitInternalEvent(internalEventName, eventName, listener) {
this.emit(
internalEventName,
...[eventName, listener]
);
}
_getListeners(eventName) {
return Array.prototype.concat.apply([], this.events.get(eventName)) || [];
}
_removeListener(listeners, listener) {
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
return [];
}
_wrapOnceListener(eventName, listener) {
const onceListener = (...data) => {
this.removeListener(eventName, onceListener);
return listener.apply(this, data);
};
Object.defineProperty(onceListener, "name", { value: listener.name });
return onceListener;
}
setMaxListeners(maxListeners) {
this.maxListeners = maxListeners;
return this;
}
/**
* Returns the current max listener value for the `Emitter` which is
* either set by `emitter.setMaxListeners(n)` or defaults to
* `Emitter.defaultMaxListeners`.
*/
getMaxListeners() {
return this.maxListeners;
}
/**
* Returns an array listing the events for which the emitter has registered listeners.
* The values in the array will be strings or Symbols.
*/
eventNames() {
return Array.from(this.events.keys());
}
/**
* Synchronously calls each of the listeners registered for the event named `eventName`,
* in the order they were registered, passing the supplied arguments to each.
* Returns `true` if the event has listeners, `false` otherwise.
*
* @example
* const emitter = new Emitter<{ hello: [string] }>()
* emitter.emit('hello', 'John')
*/
emit(eventName, ...data) {
const listeners = this._getListeners(eventName);
listeners.forEach((listener) => {
listener.apply(this, data);
});
return listeners.length > 0;
}
addListener(eventName, listener) {
this._emitInternalEvent("newListener", eventName, listener);
const nextListeners = this._getListeners(eventName).concat(listener);
this.events.set(eventName, nextListeners);
if (this.maxListeners > 0 && this.listenerCount(eventName) > this.maxListeners && !this.hasWarnedAboutPotentialMemoryLeak) {
this.hasWarnedAboutPotentialMemoryLeak = true;
const memoryLeakWarning = new MemoryLeakError(
this,
eventName,
this.listenerCount(eventName)
);
console.warn(memoryLeakWarning);
}
return this;
}
on(eventName, listener) {
return this.addListener(eventName, listener);
}
once(eventName, listener) {
return this.addListener(
eventName,
this._wrapOnceListener(eventName, listener)
);
}
prependListener(eventName, listener) {
const listeners = this._getListeners(eventName);
if (listeners.length > 0) {
const nextListeners = [listener].concat(listeners);
this.events.set(eventName, nextListeners);
} else {
this.events.set(eventName, listeners.concat(listener));
}
return this;
}
prependOnceListener(eventName, listener) {
return this.prependListener(
eventName,
this._wrapOnceListener(eventName, listener)
);
}
removeListener(eventName, listener) {
const listeners = this._getListeners(eventName);
if (listeners.length > 0) {
this._removeListener(listeners, listener);
this.events.set(eventName, listeners);
this._emitInternalEvent("removeListener", eventName, listener);
}
return this;
}
/**
* Alias for `emitter.removeListener()`.
*
* @example
* emitter.off('hello', listener)
*/
off(eventName, listener) {
return this.removeListener(eventName, listener);
}
removeAllListeners(eventName) {
if (eventName) {
this.events.delete(eventName);
} else {
this.events.clear();
}
return this;
}
/**
* Returns a copy of the array of listeners for the event named `eventName`.
*/
listeners(eventName) {
return Array.from(this._getListeners(eventName));
}
/**
* Returns the number of listeners listening to the event named `eventName`.
*/
listenerCount(eventName) {
return this._getListeners(eventName).length;
}
rawListeners(eventName) {
return this.listeners(eventName);
}
};
var Emitter = _Emitter;
Emitter.defaultMaxListeners = 10;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Emitter,
MemoryLeakError
});
//# sourceMappingURL=index.js.map

1
node_modules/strict-event-emitter/lib/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

171
node_modules/strict-event-emitter/lib/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,171 @@
// src/MemoryLeakError.ts
var MemoryLeakError = class extends Error {
constructor(emitter, type, count) {
super(
`Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit`
);
this.emitter = emitter;
this.type = type;
this.count = count;
this.name = "MaxListenersExceededWarning";
}
};
// src/Emitter.ts
var _Emitter = class {
static listenerCount(emitter, eventName) {
return emitter.listenerCount(eventName);
}
constructor() {
this.events = /* @__PURE__ */ new Map();
this.maxListeners = _Emitter.defaultMaxListeners;
this.hasWarnedAboutPotentialMemoryLeak = false;
}
_emitInternalEvent(internalEventName, eventName, listener) {
this.emit(
internalEventName,
...[eventName, listener]
);
}
_getListeners(eventName) {
return Array.prototype.concat.apply([], this.events.get(eventName)) || [];
}
_removeListener(listeners, listener) {
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
return [];
}
_wrapOnceListener(eventName, listener) {
const onceListener = (...data) => {
this.removeListener(eventName, onceListener);
return listener.apply(this, data);
};
Object.defineProperty(onceListener, "name", { value: listener.name });
return onceListener;
}
setMaxListeners(maxListeners) {
this.maxListeners = maxListeners;
return this;
}
/**
* Returns the current max listener value for the `Emitter` which is
* either set by `emitter.setMaxListeners(n)` or defaults to
* `Emitter.defaultMaxListeners`.
*/
getMaxListeners() {
return this.maxListeners;
}
/**
* Returns an array listing the events for which the emitter has registered listeners.
* The values in the array will be strings or Symbols.
*/
eventNames() {
return Array.from(this.events.keys());
}
/**
* Synchronously calls each of the listeners registered for the event named `eventName`,
* in the order they were registered, passing the supplied arguments to each.
* Returns `true` if the event has listeners, `false` otherwise.
*
* @example
* const emitter = new Emitter<{ hello: [string] }>()
* emitter.emit('hello', 'John')
*/
emit(eventName, ...data) {
const listeners = this._getListeners(eventName);
listeners.forEach((listener) => {
listener.apply(this, data);
});
return listeners.length > 0;
}
addListener(eventName, listener) {
this._emitInternalEvent("newListener", eventName, listener);
const nextListeners = this._getListeners(eventName).concat(listener);
this.events.set(eventName, nextListeners);
if (this.maxListeners > 0 && this.listenerCount(eventName) > this.maxListeners && !this.hasWarnedAboutPotentialMemoryLeak) {
this.hasWarnedAboutPotentialMemoryLeak = true;
const memoryLeakWarning = new MemoryLeakError(
this,
eventName,
this.listenerCount(eventName)
);
console.warn(memoryLeakWarning);
}
return this;
}
on(eventName, listener) {
return this.addListener(eventName, listener);
}
once(eventName, listener) {
return this.addListener(
eventName,
this._wrapOnceListener(eventName, listener)
);
}
prependListener(eventName, listener) {
const listeners = this._getListeners(eventName);
if (listeners.length > 0) {
const nextListeners = [listener].concat(listeners);
this.events.set(eventName, nextListeners);
} else {
this.events.set(eventName, listeners.concat(listener));
}
return this;
}
prependOnceListener(eventName, listener) {
return this.prependListener(
eventName,
this._wrapOnceListener(eventName, listener)
);
}
removeListener(eventName, listener) {
const listeners = this._getListeners(eventName);
if (listeners.length > 0) {
this._removeListener(listeners, listener);
this.events.set(eventName, listeners);
this._emitInternalEvent("removeListener", eventName, listener);
}
return this;
}
/**
* Alias for `emitter.removeListener()`.
*
* @example
* emitter.off('hello', listener)
*/
off(eventName, listener) {
return this.removeListener(eventName, listener);
}
removeAllListeners(eventName) {
if (eventName) {
this.events.delete(eventName);
} else {
this.events.clear();
}
return this;
}
/**
* Returns a copy of the array of listeners for the event named `eventName`.
*/
listeners(eventName) {
return Array.from(this._getListeners(eventName));
}
/**
* Returns the number of listeners listening to the event named `eventName`.
*/
listenerCount(eventName) {
return this._getListeners(eventName).length;
}
rawListeners(eventName) {
return this.listeners(eventName);
}
};
var Emitter = _Emitter;
Emitter.defaultMaxListeners = 10;
export {
Emitter,
MemoryLeakError
};
//# sourceMappingURL=index.mjs.map

1
node_modules/strict-event-emitter/lib/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

41
node_modules/strict-event-emitter/package.json generated vendored Normal file
View File

@@ -0,0 +1,41 @@
{
"name": "strict-event-emitter",
"version": "0.5.1",
"description": "Type-safe implementation of EventEmitter for browser and Node.js",
"main": "lib/index.js",
"module": "lib/index.mjs",
"typings": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"require": "./lib/index.js",
"default": "./lib/index.mjs"
}
},
"repository": "git@github.com:open-draft/strict-event-emitter.git",
"author": "Artem Zakharchenko <kettanaito@gmail.com>",
"license": "MIT",
"files": [
"lib"
],
"devDependencies": {
"@ossjs/release": "^0.8.0",
"@types/events": "^3.0.0",
"@types/jest": "^29.2.4",
"jest": "^29.3.1",
"jest-extended": "^3.2.0",
"rimraf": "^3.0.2",
"ts-jest": "^29.0.3",
"ts-node": "^9.1.1",
"tsup": "^6.2.3",
"typescript": "4.8"
},
"scripts": {
"dev": "tsc -w",
"test": "jest",
"test:ts": "tsc -p test/typings.tsconfig.json",
"clean": "rimraf ./lib",
"build": "pnpm clean && tsup",
"release": "release publish"
}
}