chore: project setup and tooling cleanup (#26)

* add project setup

* add tools to eslint

* remove contributing.md

* update claude md

* chore: simplify CI to single Node.js version (22)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* use node 20

* adjust formatting

* fix linting

* format

* fix layout

* fix: align CI node version to .nvmrc (22), remove redundant gotcha

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: arkon <arkon.85@hotmail.com>
This commit is contained in:
Noah Waldner
2026-02-27 13:16:23 +01:00
committed by GitHub
co-authored by Claude Sonnet 4.6 arkon
parent 2b2829ebde
commit 480584de63
61 changed files with 4306 additions and 4013 deletions
+37 -45
View File
@@ -115,11 +115,7 @@ export class CleanupManager implements Disposable {
* @param options - Optional configuration
* @returns Timer ID for manual clearing if needed
*/
setTimeout(
callback: () => void,
delay: number,
options?: TimerOptions
): string {
setTimeout(callback: () => void, delay: number, options?: TimerOptions): string {
const id = uuidv4();
const timeoutId = setTimeout(() => {
// Remove registration when timer fires naturally
@@ -148,11 +144,7 @@ export class CleanupManager implements Disposable {
* @param options - Optional configuration
* @returns Interval ID for manual clearing if needed
*/
setInterval(
callback: () => void,
delay: number,
options?: TimerOptions
): string {
setInterval(callback: () => void, delay: number, options?: TimerOptions): string {
const id = uuidv4();
const intervalId = setInterval(() => {
// Don't execute if stopped
@@ -179,11 +171,7 @@ export class CleanupManager implements Disposable {
* @param description - Human-readable description
* @returns Registration ID for manual removal if needed
*/
registerCleanup(
type: CleanupResourceType,
cleanup: () => void,
description: string
): string {
registerCleanup(type: CleanupResourceType, cleanup: () => void, description: string): string {
const id = uuidv4();
this.register({
id,
@@ -202,10 +190,7 @@ export class CleanupManager implements Disposable {
* @param description - Human-readable description
* @returns Registration ID
*/
registerWatcher(
watcher: { close: () => void },
description: string
): string {
registerWatcher(watcher: { close: () => void }, description: string): string {
return this.registerCleanup('watcher', () => watcher.close(), description);
}
@@ -218,19 +203,23 @@ export class CleanupManager implements Disposable {
* @param description - Human-readable description
* @returns Registration ID
*/
registerListener<T extends { removeListener?: (event: string, listener: () => void) => void; off?: (event: string, listener: () => void) => void }>(
emitter: T,
event: string,
listener: () => void,
description: string
): string {
return this.registerCleanup('listener', () => {
if (emitter.removeListener) {
emitter.removeListener(event, listener);
} else if (emitter.off) {
emitter.off(event, listener);
}
}, description);
registerListener<
T extends {
removeListener?: (event: string, listener: () => void) => void;
off?: (event: string, listener: () => void) => void;
},
>(emitter: T, event: string, listener: () => void, description: string): string {
return this.registerCleanup(
'listener',
() => {
if (emitter.removeListener) {
emitter.removeListener(event, listener);
} else if (emitter.off) {
emitter.off(event, listener);
}
},
description
);
}
/**
@@ -240,17 +229,18 @@ export class CleanupManager implements Disposable {
* @param description - Human-readable description
* @returns Registration ID
*/
registerStream(
stream: { destroy?: () => void; close?: () => void },
description: string
): string {
return this.registerCleanup('stream', () => {
if (stream.destroy) {
stream.destroy();
} else if (stream.close) {
stream.close();
}
}, description);
registerStream(stream: { destroy?: () => void; close?: () => void }, description: string): string {
return this.registerCleanup(
'stream',
() => {
if (stream.destroy) {
stream.destroy();
} else if (stream.close) {
stream.close();
}
},
description
);
}
/**
@@ -297,8 +287,10 @@ export class CleanupManager implements Disposable {
this.registrations.clear();
if (errors.length > 0) {
console.error(`[CleanupManager] ${errors.length} errors during disposal:`,
errors.map(e => e.description).join(', '));
console.error(
`[CleanupManager] ${errors.length} errors during disposal:`,
errors.map((e) => e.description).join(', ')
);
}
}