From abd7cc619e7b53819bbc3f2e8bbb9854e50e185f Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 01:41:50 +0000 Subject: [PATCH 01/11] Remove type assertion: --- source/event-emitter.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index e455a08..da22964 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -2,13 +2,21 @@ export type EventMap = Record; type Listener = (detail: T) => void; +/** + * Internally permits listeners for individual event payloads to be stored + * in a collection typed with the union of all event payloads. + */ +type StoredListener = { + bivarianceHack(detail: Readonly): void; +}['bivarianceHack']; + /** * A listener entry. - * @template T - The event type. + * @template T - The event payload type. */ interface ListenerEntry { - listener: Listener; - wrappedListener: Listener; + listener: StoredListener; + wrappedListener: StoredListener; debounceTime?: number; once?: boolean; } @@ -50,7 +58,7 @@ export class EventEmitter { }; // Add the listener entry to the listeners map. - this.listeners.get(type)?.add(listenerEntry as ListenerEntry); + this.#listeners.get(type)?.add(listenerEntry); // Return an "off" callback that can be called to stop listening for events. return () => this.off(type, listener); @@ -87,7 +95,7 @@ export class EventEmitter { }; // Add the listener entry to the listeners map. - this.listeners.get(type)?.add(listenerEntry as ListenerEntry); + this.#listeners.get(type)?.add(listenerEntry); // Return an "off" callback that can be called to stop listening for events. return () => this.off(type, listener); From 2b6f4e2f8ea149ac20ce474d51ed4301e0609b58 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 01:42:55 +0000 Subject: [PATCH 02/11] Freeze object when emitting --- source/event-emitter.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index da22964..d369166 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -1,6 +1,6 @@ export type EventMap = Record; -type Listener = (detail: T) => void; +type Listener = (detail: Readonly) => void; /** * Internally permits listeners for individual event payloads to be stored @@ -72,7 +72,7 @@ export class EventEmitter { * @returns An off callback that can be called to stop listening for events. */ once(type: K, listener: Listener, debounceMilliseconds?: number): OffCallback { - const wrappedListener: Listener = (detail: T[K]) => { + const wrappedListener: Listener = (detail: Readonly) => { this.off(type, listener); listener(detail); }; @@ -131,9 +131,12 @@ export class EventEmitter { const listeners = this.listeners.get(type); if (!listeners) return false; + // Freeze the payload to make it readonly. + const readonlyPayload = Object.freeze(payload); + // Emit the event to all listeners. listeners.forEach((entry) => { - entry.wrappedListener(payload); + entry.wrappedListener(readonlyPayload); }); // Return true if there are listeners for the event, false otherwise. @@ -154,13 +157,13 @@ export class EventEmitter { * @param timeoutMs - The timeout in milliseconds. * @returns The event payload. */ - async waitFor(type: K, predicate: (payload: T[K]) => boolean, timeoutMs?: number): Promise { + async waitFor(type: K, predicate: (payload: Readonly) => boolean, timeoutMs?: number): Promise> { // Create a promise to wait for the event to be emitted. return new Promise((resolve, reject) => { let timeoutId: ReturnType | undefined; // Create a listener function. - const listener = (payload: T[K]): void => { + const listener = (payload: Readonly): void => { if (predicate(payload)) { // Clean up this.off(type, listener); @@ -195,7 +198,7 @@ export class EventEmitter { // Create a timeout variable. let timeout: ReturnType; - return (detail: T[K]) => { + return (detail: Readonly) => { // If a debounce timer is already pending, clear it before scheduling the next one. if (timeout !== undefined) { clearTimeout(timeout); From c7f8637ea09edf6a995b098ade9dc05d86b53164 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 01:43:06 +0000 Subject: [PATCH 03/11] Add off callback docs --- source/event-emitter.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index d369166..a5381d8 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -21,6 +21,9 @@ interface ListenerEntry { once?: boolean; } +/** + * Callback returned by {@link on} and {@link once} for removing a listener. + */ export type OffCallback = () => void; /** From 3664464903c773242ed6712ee0d2caf5bb1e699e Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 01:43:49 +0000 Subject: [PATCH 04/11] Use hash private --- source/event-emitter.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index a5381d8..857f9c4 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -35,7 +35,7 @@ export class EventEmitter { * The listeners map. * @private */ - private listeners: Map>> = new Map(); + #listeners: Map>> = new Map(); /** * Add a listener for an event. @@ -49,8 +49,8 @@ export class EventEmitter { const wrappedListener = debounceMilliseconds && debounceMilliseconds > 0 ? this.debounce(listener, debounceMilliseconds) : listener; // If the listeners map does not have the event type, create a new set. - if (!this.listeners.has(type)) { - this.listeners.set(type, new Set()); + if (!this.#listeners.has(type)) { + this.#listeners.set(type, new Set()); } // Create a listener entry. @@ -85,8 +85,8 @@ export class EventEmitter { debounceMilliseconds && debounceMilliseconds > 0 ? this.debounce(wrappedListener, debounceMilliseconds) : wrappedListener; // If the listeners map does not have the event type, create a new set. - if (!this.listeners.has(type)) { - this.listeners.set(type, new Set()); + if (!this.#listeners.has(type)) { + this.#listeners.set(type, new Set()); } // Create a listener entry. @@ -111,7 +111,7 @@ export class EventEmitter { */ off(type: K, listener: Listener): void { // Get the listeners for the event type. - const listeners = this.listeners.get(type); + const listeners = this.#listeners.get(type); if (!listeners) return; // Find the listener entry. @@ -131,7 +131,7 @@ export class EventEmitter { */ emit(type: K, payload: T[K]): boolean { // Get the listeners for the event type. - const listeners = this.listeners.get(type); + const listeners = this.#listeners.get(type); if (!listeners) return false; // Freeze the payload to make it readonly. @@ -150,7 +150,7 @@ export class EventEmitter { * Remove all listeners. */ removeAllListeners(): void { - this.listeners.clear(); + this.#listeners.clear(); } /** From a9486712518b770695b8a5a6cb207d69064dbc67 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 01:44:20 +0000 Subject: [PATCH 05/11] Use variable for debounce addtion --- source/event-emitter.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 857f9c4..5ea4070 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -57,9 +57,13 @@ export class EventEmitter { const listenerEntry: ListenerEntry = { listener, wrappedListener, - ...(debounceMilliseconds !== undefined ? { debounceTime: debounceMilliseconds } : {}), }; + // Set the debounce time if specified. + if (debounceMilliseconds && debounceMilliseconds > 0) { + listenerEntry.debounceTime = debounceMilliseconds; + } + // Add the listener entry to the listeners map. this.#listeners.get(type)?.add(listenerEntry); @@ -94,9 +98,13 @@ export class EventEmitter { listener, wrappedListener: debouncedListener, once: true, - ...(debounceMilliseconds !== undefined ? { debounceTime: debounceMilliseconds } : {}), }; + // Set the debounce time if specified. + if (debounceMilliseconds && debounceMilliseconds > 0) { + listenerEntry.debounceTime = debounceMilliseconds; + } + // Add the listener entry to the listeners map. this.#listeners.get(type)?.add(listenerEntry); From 8b47dd2d8b7869554855bbe359433a8b2d5e59d4 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:11:40 +0000 Subject: [PATCH 06/11] Add general off handling --- source/event-emitter.ts | 8 +++++++- test/event-emitter.test.ts | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 5ea4070..8544fca 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -117,11 +117,17 @@ export class EventEmitter { * @param type - The event type. * @param listener - The listener function. */ - off(type: K, listener: Listener): void { + off(type: K, listener?: Listener): void { // Get the listeners for the event type. const listeners = this.#listeners.get(type); if (!listeners) return; + // If no listener is provided, remove all listeners for the event type. + if (!listener) { + this.#listeners.delete(type); + return; + } + // Find the listener entry. const listenerEntry = Array.from(listeners).find((entry) => entry.listener === listener || entry.wrappedListener === listener); diff --git a/test/event-emitter.test.ts b/test/event-emitter.test.ts index b0b0e81..11d6a3e 100644 --- a/test/event-emitter.test.ts +++ b/test/event-emitter.test.ts @@ -124,6 +124,21 @@ const testEventEmitterOffRemovesListenerByReference = (): void => { expect(listener).not.toHaveBeenCalled(); }; +/** + * Tests that off() removes all listeners for an event type when no listener is provided. + */ +const testEventEmitterOffRemovesAllListenersForEventType = (): void => { + const emitter = new EventEmitter(); + const listener = vi.fn(); + + emitter.on('message', listener); + emitter.off('message'); + + expect(listener).not.toHaveBeenCalled(); + expect(emitter.emit('message', 'hello')).toBe(false); + expect(emitter.emit('count', 42)).toBe(false); +}; + /** * Tests that off() does nothing when given an unknown listener reference. */ @@ -484,6 +499,7 @@ const runTests = async (): Promise => { test('EventEmitter: returns true when emitting with listeners', testEventEmitterEmitReturnsTrueWithListeners); test('EventEmitter: stops calling a listener after its off callback is invoked', testEventEmitterOffCallbackRemovesListener); test('EventEmitter: removes a listener when off is called with the same reference', testEventEmitterOffRemovesListenerByReference); + test('EventEmitter: removes all listeners for an event type when off is called with no listener', testEventEmitterOffRemovesAllListenersForEventType); test('EventEmitter: ignores off when the listener reference is unknown', testEventEmitterOffIgnoresUnknownListener); test('EventEmitter: ignores off for an event type with no listeners', testEventEmitterOffIgnoresUnregisteredEventType); test('EventEmitter: calls a once listener only one time', testEventEmitterOnceListenerFiresOnce); From ede4c542524404fb82a08ce10b2c1a4775091b4d Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:11:55 +0000 Subject: [PATCH 07/11] Improve waitFor docs --- source/event-emitter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 8544fca..3ed7a75 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -168,9 +168,9 @@ export class EventEmitter { } /** - * Wait for an event to be emitted. + * Wait for an event to be emitted that matches the provided predicate function's criteria. * @param type - The event type. - * @param predicate - The predicate function. + * @param predicate - Predicate function to filter for whether the event payload matches the criteria. * @param timeoutMs - The timeout in milliseconds. * @returns The event payload. */ From c919728fb3992e042e95465591cc5ab8fe225964 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:12:09 +0000 Subject: [PATCH 08/11] Handle errors in Predicate function --- source/event-emitter.ts | 9 ++++++++- test/event-emitter.test.ts | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 3ed7a75..73bf2b7 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -181,7 +181,12 @@ export class EventEmitter { // Create a listener function. const listener = (payload: Readonly): void => { - if (predicate(payload)) { + try { + // If the event payload does not match the predicate condition, return. + if (!predicate(payload)) { + return; + } + // Clean up this.off(type, listener); if (timeoutId !== undefined) { @@ -189,6 +194,8 @@ export class EventEmitter { } resolve(payload); + } catch (error) { + reject(error); } }; diff --git a/test/event-emitter.test.ts b/test/event-emitter.test.ts index 11d6a3e..dbbd461 100644 --- a/test/event-emitter.test.ts +++ b/test/event-emitter.test.ts @@ -491,6 +491,23 @@ const testEventEmitterDebouncedOnceListener = async (): Promise => { } }; +/** + * Tests that the `waitFor` method rejects if the predicate function throws + */ +const testEventEmitterWaitForRejectsOnPredicateError = async (): Promise => { + const emitter = new EventEmitter(); + const listener = vi.fn(); + + const waitPromise = emitter.waitFor('message', () => { + throw new Error('predicate error'); + }); + + emitter.emit('message', 'hello'); + + await expect(waitPromise).rejects.toThrow('predicate error'); + expect(listener).not.toHaveBeenCalled(); +}; + const runTests = async (): Promise => { test('EventEmitter: calls listeners when an event is emitted', testEventEmitterCallsListeners); test('EventEmitter: calls multiple listeners for the same event', testEventEmitterCallsMultipleListeners); @@ -516,6 +533,7 @@ const runTests = async (): Promise => { test('EventEmitter: resets the debounce timer on repeated emits', testEventEmitterDebouncedTimerResetsOnRepeatedEmits); test('EventEmitter: does not debounce when debounceMilliseconds is zero', testEventEmitterZeroDebounceDoesNotDebounce); test('EventEmitter: debounces once listeners and invokes them only once', testEventEmitterDebouncedOnceListener); + test('EventEmitter: rejects waitFor when the predicate function throws', testEventEmitterWaitForRejectsOnPredicateError); }; await runTests(); From dc57495a86d76fde74fbf3e7c291df462b3201ea Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:17:58 +0000 Subject: [PATCH 09/11] Formatting --- source/event-emitter.ts | 1 + test/event-emitter.test.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 73bf2b7..64cdcb0 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -125,6 +125,7 @@ export class EventEmitter { // If no listener is provided, remove all listeners for the event type. if (!listener) { this.#listeners.delete(type); + return; } diff --git a/test/event-emitter.test.ts b/test/event-emitter.test.ts index dbbd461..7b1eb71 100644 --- a/test/event-emitter.test.ts +++ b/test/event-emitter.test.ts @@ -516,7 +516,10 @@ const runTests = async (): Promise => { test('EventEmitter: returns true when emitting with listeners', testEventEmitterEmitReturnsTrueWithListeners); test('EventEmitter: stops calling a listener after its off callback is invoked', testEventEmitterOffCallbackRemovesListener); test('EventEmitter: removes a listener when off is called with the same reference', testEventEmitterOffRemovesListenerByReference); - test('EventEmitter: removes all listeners for an event type when off is called with no listener', testEventEmitterOffRemovesAllListenersForEventType); + test( + 'EventEmitter: removes all listeners for an event type when off is called with no listener', + testEventEmitterOffRemovesAllListenersForEventType, + ); test('EventEmitter: ignores off when the listener reference is unknown', testEventEmitterOffIgnoresUnknownListener); test('EventEmitter: ignores off for an event type with no listeners', testEventEmitterOffIgnoresUnregisteredEventType); test('EventEmitter: calls a once listener only one time', testEventEmitterOnceListenerFiresOnce); From da6afe410775f3d7c3fbd164868fd7270f31d8e2 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:25:42 +0000 Subject: [PATCH 10/11] Audit Fix --- package-lock.json | 76 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2d1a9ee..74bb9dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1105,9 +1105,9 @@ "license": "MIT" }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -1186,9 +1186,9 @@ "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -3435,9 +3435,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", - "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", "dev": true, "license": "MIT", "dependencies": { @@ -3503,16 +3503,16 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/brotli-size": { @@ -5292,9 +5292,9 @@ "peer": true }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "peer": true, @@ -5379,9 +5379,9 @@ "peer": true }, "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "peer": true, @@ -5468,9 +5468,9 @@ "peer": true }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "peer": true, @@ -5542,9 +5542,9 @@ "license": "MIT" }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -7129,9 +7129,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { @@ -7524,9 +7524,9 @@ } }, "node_modules/linkify-it": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", - "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", "dev": true, "funding": [ { @@ -7810,9 +7810,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", "dev": true, "funding": [ { @@ -8288,9 +8288,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -8308,7 +8308,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, From e981bf80958eb67fd9b9b92f0a12218811a786b4 Mon Sep 17 00:00:00 2001 From: Harvmaster Date: Fri, 7 Aug 2026 02:29:58 +0000 Subject: [PATCH 11/11] Added bivariance to allowed words --- .cspell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 8290ebb..3aa6a11 100644 --- a/.cspell.json +++ b/.cspell.json @@ -1,6 +1,6 @@ { "version": "0.1", "import": ["@generalprotocols/cspell-dictionary/cspell.json"], - "words": ["nonfungible", "lockscript"], + "words": ["nonfungible", "lockscript", "bivariance"], "ignorePaths": ["source/template/xo-template.schema.json"] }