### Install Disposiq Source: https://context7.com/tioniq/disposiq/llms.txt Install the Disposiq library using npm or jsr. ```sh npm install @tioniq/disposiq # or npx jsr add @tioniq/disposiq ``` -------------------------------- ### Install Disposiq Package Source: https://github.com/tioniq/disposiq/blob/main/README.md Install the Disposiq library using npm to manage resources effectively. ```sh npm install @tioniq/disposiq ``` -------------------------------- ### Extending Disposiq with Custom Methods Source: https://github.com/tioniq/disposiq/blob/main/README.md Extend the Disposiq class to add custom functionality. This example adds a 'togetherWith' method to dispose of multiple disposables simultaneously. ```typescript import { Disposiq, DisposableAction, IDisposable } from '@tioniq/disposiq' declare module '@tioniq/disposiq' { interface Disposiq { togetherWith(other: IDisposable): Disposiq } } Disposiq.prototype.togetherWith = function (this: Disposiq, other: IDisposable): Disposiq { return new DisposableAction(() => { this.dispose() other.dispose() }) } ``` -------------------------------- ### FileHandle Class with Disposal Logic Source: https://context7.com/tioniq/disposiq/llms.txt Example of a custom class extending `Disposable` that includes disposal logic and uses `throwIfDisposed` to prevent operations on closed resources. ```typescript import { Disposable, ObjectDisposedException } from '@tioniq/disposiq' class FileHandle extends Disposable { private path: string constructor(path: string) { super() this.path = path this.addDisposable(() => console.log(`closed ${this.path}`)) } read(): string { this.throwIfDisposed(`FileHandle(${this.path}) is already closed`) return `contents of ${this.path}` } } const fh = new FileHandle('/tmp/data.txt') console.log(fh.read()) // Output: contents of /tmp/data.txt fh.dispose() // Output: closed /tmp/data.txt try { fh.read() } catch (e) { console.log(e instanceof ObjectDisposedException) // true console.log(e.message) // FileHandle(/tmp/data.txt) is already closed } ``` -------------------------------- ### using() Source: https://context7.com/tioniq/disposiq/llms.txt Provides explicit resource management for environments or code paths that cannot use the native `using` keyword. Accepts synchronous or asynchronous actions and guarantees resource disposal. ```APIDOC ## using(resource: T, action: (resource: T) => void | Promise): void | Promise ### Description Manages the lifecycle of a resource, ensuring it is disposed after the provided action is executed. Supports both synchronous and asynchronous actions. ### Parameters #### Path Parameters - **resource** (T) - Required - The resource to manage, which must be disposable. - **action** ((resource: T) => void | Promise) - Required - The synchronous or asynchronous function to execute with the resource. ### Request Example ```typescript import { Disposable, using } from '@tioniq/disposiq' class DatabaseConnection extends Disposable { constructor(private readonly url: string) { super() console.log(`connected to ${url}`) this.addDisposable(() => console.log(`disconnected from ${url}`)) } async query(sql: string): Promise { this.throwIfDisposed('Connection closed') console.log(`query: ${sql}`) return ['row1', 'row2'] } } // Synchronous scope using(new DatabaseConnection('db://local'), (conn) => { // conn is available synchronously }) // Output: connected to db://local // Output: disconnected from db://local // Async scope — disposal waits for the promise await using(new DatabaseConnection('db://remote'), async (conn) => { const rows = await conn.query('SELECT * FROM users') console.log(rows) }) // Output: connected to db://remote // Output: query: SELECT * FROM users // Output: [ 'row1', 'row2' ] // Output: disconnected from db://remote ``` ``` -------------------------------- ### Using the 'using' Function for Resource Management Source: https://github.com/tioniq/disposiq/blob/main/README.md Use the 'using' function as an alternative to the 'using' keyword for managing disposable resources. Ensure the resource is properly cleaned up after execution. ```typescript import { Disposable, using } from '@tioniq/disposiq' using(new Client(), async (client) => { await client.makeRequest() // Output: Request made }) // Output: Resource cleaned up class Client extends Disposable { constructor() { super() this.addDisposable(() => { console.log('Resource cleaned up') }) } async makeRequest() { console.log('Request made') } } ``` -------------------------------- ### createDisposable / createDisposiq / createDisposableCompat Source: https://context7.com/tioniq/disposiq/llms.txt Universal factory functions to normalize various types of values into `IDisposable` or `Disposiq` instances. Supports functions, objects with `dispose`, `AbortController`, `Symbol.dispose`/`Symbol.asyncDispose`, `unref()`-able objects, and cancellation tokens. ```APIDOC ## createDisposable(value: CanBeDisposable): IDisposable ### Description Normalizes a `CanBeDisposable` value into an `IDisposable` instance. ### Parameters #### Path Parameters - **value** (CanBeDisposable) - Required - The value to convert into a disposable. ### Request Example ```typescript import { createDisposable } from '@tioniq/disposiq' // From a plain function const a = createDisposable(() => console.log('a disposed')) a.dispose() // Output: a disposed // From an AbortController const controller = new AbortController() const b = createDisposable(controller) b.dispose() console.log(controller.signal.aborted) // true ``` ``` ```APIDOC ## createDisposiq(value: CanBeDisposable): Disposiq ### Description Normalizes a `CanBeDisposable` value into a `Disposiq` instance, which includes extension methods like `disposeIn`. ### Parameters #### Path Parameters - **value** (CanBeDisposable) - Required - The value to convert into a disposable. ### Request Example ```typescript import { createDisposiq } from '@tioniq/disposiq' const c = createDisposiq(() => console.log('c disposed')) c.disposeIn(100) // dispose after 100ms ``` ``` ```APIDOC ## createDisposableCompat(value: CanBeDisposable): IDisposable ### Description Normalizes a `CanBeDisposable` value into an `IDisposable` instance, ensuring `Symbol.dispose` support. ### Parameters #### Path Parameters - **value** (CanBeDisposable) - Required - The value to convert into a disposable. ### Request Example ```typescript import { createDisposableCompat } from '@tioniq/disposiq' const d = createDisposableCompat(() => console.log('d disposed')) using _ = d // works with the 'using' keyword ``` ``` -------------------------------- ### Using Explicit Resource Management with 'using' Source: https://github.com/tioniq/disposiq/blob/main/README.md Leverage the 'using' keyword for automatic disposal of resources when they go out of scope. This works with DisposableAction and DisposableStore. ```typescript import { DisposableStore, DisposableAction } from '@tioniq/disposiq' // When using the new 'using' keyword, the disposable will be disposed of automatically when it goes out of scope { using disposable = new DisposableAction(() => { console.log('Resource cleaned up') }) } // Output: Resource cleaned up // It also works with other disposable objects from the library. For example, DisposableStore: { using store = new DisposableStore() store.add(new DisposableAction(() => { console.log('Resource cleaned up') })) } // Output: Resource cleaned up ``` -------------------------------- ### Disposiq Extension Methods Source: https://context7.com/tioniq/disposiq/llms.txt These methods extend Disposiq objects for easier composition and transformation of disposables. ```APIDOC ## disposeWith ### Description Registers this disposable into a container. ### Method `disposeWith(container)` ### Parameters - **container** (DisposableStore) - The container to register the disposable with. ### Example ```typescript import { DisposableAction, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() const d1 = new DisposableAction(() => console.log('d1 disposed')) d1.disposeWith(store) // equivalent to store.add(d1) ``` ## disposeIn ### Description Auto-disposes the object after a specified number of milliseconds. ### Method `disposeIn(milliseconds)` ### Parameters - **milliseconds** (number) - The delay in milliseconds before disposal. ### Example ```typescript import { DisposableAction } from '@tioniq/disposiq' const d2 = new DisposableAction(() => console.log('d2 auto-disposed after 500ms')) d2.disposeIn(500) ``` ## toFunction ### Description Converts a disposable object into a plain `() => void` callable function. ### Method `toFunction()` ### Returns - `() => void` - A function that, when called, disposes the object. ### Example ```typescript import { DisposableAction } from '@tioniq/disposiq' const d3 = new DisposableAction(() => console.log('d3 disposed')) const fn = d3.toFunction() fn() // Output: d3 disposed ``` ## toPlainObject ### Description Strips Disposiq methods and returns a minimal object with only a `dispose()` method. ### Method `toPlainObject()` ### Returns - `{ dispose: () => void }` - An object with a `dispose` method. ### Example ```typescript import { DisposableAction } from '@tioniq/disposiq' const d4 = new DisposableAction(() => console.log('d4 disposed')) const plain = d4.toPlainObject() // plain.dispose is a function; no Disposiq methods ``` ## embedTo ### Description Attaches the `dispose()` method onto an arbitrary object, returning the modified object. ### Method `embedTo(targetObject)` ### Parameters - **targetObject** (object) - The object to embed the dispose functionality into. ### Returns - `object` - The modified target object with an added `dispose` method. ### Example ```typescript import { DisposableAction } from '@tioniq/disposiq' const d5 = new DisposableAction(() => console.log('d5 via embed')) const myObj = { name: 'resource' } const embedded = d5.embedTo(myObj) // embedded.name === 'resource', embedded.dispose() works embedded.dispose() // Output: d5 via embed ``` ## toSafe ### Description Wraps the disposable in an error-swallowing shell, optionally providing an error handler. ### Method `toSafe(errorHandler?)` ### Parameters - **errorHandler** (function, optional) - A function to handle errors during disposal. ### Returns - `Disposable` - A new disposable that swallows errors. ### Example ```typescript import { DisposableAction } from '@tioniq/disposiq' const d6 = new DisposableAction(() => { throw new Error('boom') }) const safe = d6.toSafe((err) => console.error('caught:', err)) safe.dispose() // Output: caught: Error: boom ``` ``` -------------------------------- ### Scoped Resource Management with `using()` Source: https://context7.com/tioniq/disposiq/llms.txt Provides explicit resource management for environments that cannot use the `using` keyword. Accepts sync or async actions and guarantees disposal of the resource. ```typescript import { Disposable, using } from '@tioniq/disposiq' class DatabaseConnection extends Disposable { constructor(private readonly url: string) { super() console.log(`connected to ${url}`) this.addDisposable(() => console.log(`disconnected from ${url}`)) } async query(sql: string): Promise { this.throwIfDisposed('Connection closed') console.log(`query: ${sql}`) return ['row1', 'row2'] } } // Synchronous scope using(new DatabaseConnection('db://local'), (conn) => { // conn is available synchronously }) // Output: connected to db://local // Output: disconnected from db://local // Async scope — disposal waits for the promise await using(new DatabaseConnection('db://remote'), async (conn) => { const rows = await conn.query('SELECT * FROM users') console.log(rows) }) // Output: connected to db://remote // Output: query: SELECT * FROM users // Output: [ 'row1', 'row2' ] // Output: disconnected from db://remote ``` -------------------------------- ### Register Disposable with Store using disposeWith Source: https://context7.com/tioniq/disposiq/llms.txt Use `disposeWith` to add a disposable to a `DisposableStore`. This is equivalent to `store.add(disposable)`. ```typescript import { DisposableAction, DisposableStore, createDisposiq, } from '@tioniq/disposiq' const store = new DisposableStore() // disposeWith — register this disposable into a container const d1 = new DisposableAction(() => console.log('d1 disposed')) d1.disposeWith(store) // equivalent to store.add(d1) ``` -------------------------------- ### Async DisposableStore for Asynchronous Resources Source: https://context7.com/tioniq/disposiq/llms.txt Manage asynchronous resources with AsyncDisposableStore. Its dispose() method returns a Promise. Supports 'await using' for automatic disposal. ```typescript import { AsyncDisposableAction, AsyncDisposableStore } from '@tioniq/disposiq' const store = new AsyncDisposableStore() store.add(new AsyncDisposableAction(async () => { await new Promise(r => setTimeout(r, 10)) console.log('db connection closed') })) store.add(async () => { console.log('cache flushed') }) await store.dispose() // Output: db connection closed // Output: cache flushed // await using { await using asyncStore = new AsyncDisposableStore() asyncStore.add(async () => console.log('auto async cleanup')) } // Output: auto async cleanup ``` -------------------------------- ### Classes Source: https://github.com/tioniq/disposiq/blob/main/README.md Defines various classes for managing disposables, including base classes, action containers, stores, and exception types. ```APIDOC ## Class: Disposiq ### Description Base class for all library disposables. ### Aliases - `BaseDisposable` ``` ```APIDOC ## Class: AsyncDisposiq ### Description Base class for all library asynchronous disposables. ### Aliases - `BaseAsyncDisposable` ``` ```APIDOC ## Class: DisposableAction ### Description A container for a function to be called on dispose. ### Aliases - ``` ```APIDOC ## Class: AsyncDisposableAction ### Description A container for an asynchronous function to be called on dispose. ### Aliases - ``` ```APIDOC ## Class: DisposableStore ### Description A container for disposables. ### Aliases `CompositeDisposable` ``` ```APIDOC ## Class: AsyncDisposableStore ### Description A container for async disposables. ### Aliases `CompositeAsyncDisposable` ``` ```APIDOC ## Class: DisposableMapStore ### Description A container for disposables stored by a key. ### Aliases `DisposableDictionary` ``` ```APIDOC ## Class: DisposableContainer ### Description A container for a disposable object. ### Aliases `SerialDisposable` ``` ```APIDOC ## Class: BoolDisposable ### Description An object that aware of its disposed state. ### Aliases `BooleanDisposable` ``` ```APIDOC ## Class: SafeActionDisposable ### Description A container for a function that is safely called on dispose. ### Aliases `ActionSafeDisposable` ``` ```APIDOC ## Class: SafeAsyncActionDisposable ### Description A container for an asynchronous function that is safely called on dispose. ### Aliases `AsyncActionSafeDisposable` ``` ```APIDOC ## Class: AbortDisposable ### Description A wrapper for AbortController to make it disposable. ### Aliases - ``` ```APIDOC ## Class: ObjectDisposedException ### Description An exception thrown when an object is already disposed. ### Aliases - ``` -------------------------------- ### Universal Disposable Factory Functions Source: https://context7.com/tioniq/disposiq/llms.txt Normalizes various resource types (functions, objects with dispose, AbortControllers, Symbol.dispose/asyncDispose, unref()-able objects, cancellation tokens) into IDisposable or Disposiq. `createDisposableCompat` ensures Symbol.dispose support for 'using' keyword compatibility. ```typescript import { createDisposable, createDisposiq, createDisposableCompat } from '@tioniq/disposiq' // From a plain function const a = createDisposable(() => console.log('a disposed')) a.dispose() // Output: a disposed // From an AbortController const controller = new AbortController() const b = createDisposable(controller) b.dispose() console.log(controller.signal.aborted) // true // createDisposiq returns a full Disposiq instance (with extension methods) const c = createDisposiq(() => console.log('c disposed')) c.disposeIn(100) // dispose after 100ms // createDisposableCompat guarantees Symbol.dispose support const d = createDisposableCompat(() => console.log('d disposed')) using _ = d // works with the 'using' keyword ``` -------------------------------- ### Functions Source: https://github.com/tioniq/disposiq/blob/main/README.md Provides utility functions for managing disposables, including disposal, creation, and checking disposable types. ```APIDOC ## disposeAll ### Description Dispose of all disposables in the array safely, allowing array modification during disposal. ### Function Signature disposeAll(disposables: Array): void ### Aliases disposeAllSafe ``` ```APIDOC ## disposeAllUnsafe ### Description Dispose of all disposables in the array unsafely, array modification during disposal is dangerous. ### Function Signature disposeAllUnsafe(disposables: Array): void ### Aliases - ``` ```APIDOC ## disposeAllSafely ### Description Dispose of all disposables in the array safely, with error callback, array modification during disposal is dangerous. ### Function Signature disposeAllSafely(disposables: Array, errorCallback?: (error: any) => void): void ### Aliases - ``` ```APIDOC ## createDisposable ### Description Create a disposable object from a given parameter. ### Function Signature createDisposable(value: any): any ### Aliases toDisposable ``` ```APIDOC ## createDisposableCompat ### Description Create a disposable object from a given parameter compatible with the 'using' keyword. ### Function Signature createDisposableCompat(value: any): any ### Aliases toDisposableCompat ``` ```APIDOC ## disposableFromEvent ### Description Create a disposable object from an event listener. ### Function Signature disposableFromEvent(target: EventTarget, eventName: string, listener: Function, options?: AddEventListenerOptions): any ### Aliases on ``` ```APIDOC ## disposableFromEventOnce ### Description Create a disposable object from an event listener that disposes after the first call. ### Function Signature disposableFromEventOnce(target: EventTarget, eventName: string, listener: Function, options?: AddEventListenerOptions): any ### Aliases once ``` ```APIDOC ## isDisposable ### Description Check if the object is a disposable object. ### Function Signature isDisposable(value: any): boolean ### Aliases - ``` ```APIDOC ## isDisposableLike ### Description Check if the object is a disposable-like. ### Function Signature isDisposableLike(value: any): boolean ### Aliases - ``` ```APIDOC ## isDisposableCompat ### Description Check if the object is a disposable object that is compatible with the 'using' keyword. ### Function Signature isDisposableCompat(value: any): boolean ### Aliases - ``` ```APIDOC ## isAsyncDisposableCompat ### Description Check if the object is an asynchronous disposable object that is compatible with the 'using' keyword. ### Function Signature isAsyncDisposableCompat(value: any): boolean ### Aliases - ``` ```APIDOC ## isSystemDisposable ### Description Check if the object is compatible with the system 'using' keyword. ### Function Signature isSystemDisposable(value: any): boolean ### Aliases - ``` ```APIDOC ## isSystemAsyncDisposable ### Description Check if the object is compatible with the system 'await using' keyword. ### Function Signature isSystemAsyncDisposable(value: any): boolean ### Aliases - ``` ```APIDOC ## addEventListener ### Description Add an event listener to the target object and return a disposable object. Useful for DOM events. ### Function Signature addEventListener(target: EventTarget, eventName: string, listener: Function, options?: AddEventListenerOptions): any ### Aliases - ``` -------------------------------- ### DisposableStore Source: https://context7.com/tioniq/disposiq/llms.txt Aggregates multiple `DisposableLike` items (objects with `dispose()` or plain functions) and disposes them all when the store itself is disposed. Newly added items are disposed immediately if the store is already disposed. ```APIDOC ## DisposableStore ### Description `DisposableStore` collects any number of `DisposableLike` items (objects with `dispose()` or plain functions) and disposes them all when the store itself is disposed. If the store is already disposed, any newly added item is disposed immediately. ### Usage ```typescript import { DisposableAction, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() store.add(new DisposableAction(() => console.log('resource A cleaned up'))) store.add(() => console.log('resource B cleaned up')) // plain function accepted store.add( () => console.log('resource C'), () => console.log('resource D'), // multiple at once ) // Temporarily flush contained resources without destroying the store store.disposeCurrent() // Output: resource A cleaned up // Output: resource B cleaned up // Output: resource C // Output: resource D store.add(() => console.log('resource E')) // store still alive — adds normally store.dispose() // Output: resource E // After dispose, new additions are disposed immediately store.add(() => console.log('resource F')) // Output: resource F immediately // Static factory helper const fromStore = DisposableStore.from(['ws1', 'ws2'], (id) => new DisposableAction(() => { console.log(`closing ${id}`) })) fromStore.dispose() // Output: closing ws1 // Output: closing ws2 ``` ``` -------------------------------- ### Safe Disposal with Error Handling in DisposableStore Source: https://context7.com/tioniq/disposiq/llms.txt Use disposeSafely to ensure all disposables are called, even if one throws an error. Errors are passed to an optional callback. addOneSafe handles errors for a single disposable without propagating them. ```typescript import { DisposableAction, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() store.add(new DisposableAction(() => { throw new Error('cleanup failed') })) store.add(new DisposableAction(() => console.log('second cleanup runs anyway'))) store.disposeSafely((err) => console.error('caught:', err)) // Output: caught: Error: cleanup failed // Output: second cleanup runs anyway // addOneSafe wraps a single item so errors during its disposal never propagate const safeStore = new DisposableStore() safeStore.addOneSafe( new DisposableAction(() => { throw new Error('silent failure') }), (err) => console.error('handled:', err) ) safeStore.dispose() // Output: handled: Error: silent failure ``` -------------------------------- ### DisposableStore: Aggregate and batch-dispose resources Source: https://context7.com/tioniq/disposiq/llms.txt Use `DisposableStore` to collect multiple `DisposableLike` items or functions. All collected items are disposed when the store is disposed. Newly added items to a disposed store are disposed immediately. ```typescript import { DisposableAction, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() store.add(new DisposableAction(() => console.log('resource A cleaned up'))) store.add(() => console.log('resource B cleaned up')) // plain function accepted store.add( () => console.log('resource C'), () => console.log('resource D'), // multiple at once ) // Temporarily flush contained resources without destroying the store store.disposeCurrent() // Output: resource A cleaned up // Output: resource B cleaned up // Output: resource C // Output: resource D store.add(() => console.log('resource E')) // store still alive — adds normally store.dispose() // Output: resource E // After dispose, new additions are disposed immediately store.add(() => console.log('resource F')) // Output: resource F immediately // Static factory helper const fromStore = DisposableStore.from(['ws1', 'ws2'], (id) => new DisposableAction(() => { console.log(`closing ${id}`) })) fromStore.dispose() // Output: closing ws1 // Output: closing ws2 ``` -------------------------------- ### Batch Disposal Utility Functions Source: https://context7.com/tioniq/disposiq/llms.txt Low-level functions for disposing arrays of disposables directly, without a store. ```APIDOC ## disposeAll ### Description Disposes all items in an array. This function is array-modification-safe as it creates a copy before iterating. ### Method `disposeAll(items)` ### Parameters - **items** (Array void)>) - An array of disposables or functions to dispose. ### Example ```typescript import { disposeAll } from '@tioniq/disposiq' disposeAll([() => console.log('item 1'), { dispose: () => console.log('item 2') }]) // Output: item 1 // Output: item 2 ``` ## disposeAllUnsafe ### Description Disposes all items in an array. This function is faster but requires that the array is not modified during iteration. ### Method `disposeAllUnsafe(items)` ### Parameters - **items** (Array void)>) - An array of disposables or functions to dispose. ### Example ```typescript import { disposeAllUnsafe } from '@tioniq/disposiq' disposeAllUnsafe([() => console.log('fast item')]) // Output: fast item ``` ## disposeAllSafely ### Description Disposes all items in an array, catching and handling errors for each item individually. The array must not be modified during iteration. ### Method `disposeAllSafely(items, errorHandler)` ### Parameters - **items** (Array void)>) - An array of disposables or functions to dispose. - **errorHandler** (function) - A function to handle errors that occur during the disposal of individual items. ### Example ```typescript import { disposeAllSafely } from '@tioniq/disposiq' const items = [ () => console.log('item 1'), { dispose: () => console.log('item 2') }, () => { throw new Error('item 3 failed') }, () => console.log('item 4') ] disposeAllSafely(items, (err) => console.error('error during disposal:', err)) // Output: // item 1 // item 2 // error during disposal: Error: item 3 failed // item 4 ``` ``` -------------------------------- ### disposableFromEvent / disposableFromEventOnce Source: https://context7.com/tioniq/disposiq/llms.txt Manages event listener lifecycles for Node.js-style EventEmitters. `disposableFromEvent` attaches a persistent listener, while `disposableFromEventOnce` attaches a listener that is removed after the first call or upon disposal. ```APIDOC ## disposableFromEvent(emitter: EventEmitter, eventName: string, listener: (...args: any[]) => void): IDisposable ### Description Attaches a listener to a Node.js-style `EventEmitter` and returns a disposable that removes the listener when disposed. ### Parameters #### Path Parameters - **emitter** (EventEmitter) - Required - The event emitter instance. - **eventName** (string) - Required - The name of the event to listen for. - **listener** (function) - Required - The callback function to execute when the event is emitted. ### Request Example ```typescript import { disposableFromEvent, DisposableStore } from '@tioniq/disposiq' import { EventEmitter } from 'events' const emitter = new EventEmitter() const store = new DisposableStore() store.add( disposableFromEvent(emitter, 'data', (chunk) => { console.log('received:', chunk) }) ) emitter.emit('data', 'hello') // Output: received: hello store.dispose() emitter.emit('data', 'ignored') // no output — listener removed ``` ``` ```APIDOC ## disposableFromEventOnce(emitter: EventEmitter, eventName: string, listener: (...args: any[]) => void): IDisposable ### Description Attaches a one-time listener to a Node.js-style `EventEmitter`. The listener is automatically removed after the first call or when the returned disposable is disposed. ### Parameters #### Path Parameters - **emitter** (EventEmitter) - Required - The event emitter instance. - **eventName** (string) - Required - The name of the event to listen for. - **listener** (function) - Required - The callback function to execute when the event is emitted. ### Request Example ```typescript import { disposableFromEventOnce, DisposableStore } from '@tioniq/disposiq' import { EventEmitter } from 'events' const emitter = new EventEmitter() const store = new DisposableStore() store.add( disposableFromEventOnce(emitter, 'close', (code) => { console.log('closed with code:', code) }) ) emitter.emit('close', 0) // Output: closed with code: 0 store.dispose() emitter.emit('close', 1) // no output — listener removed ``` ``` -------------------------------- ### Convert Disposable to Plain Object using toPlainObject Source: https://context7.com/tioniq/disposiq/llms.txt Use `toPlainObject` to create a minimal object with only a `dispose()` method, stripping away Disposiq-specific methods. ```typescript // toPlainObject — strip Disposiq methods, return minimal { dispose() } object const d4 = new DisposableAction(() => console.log('d4 disposed')) const plain = d4.toPlainObject() // plain.dispose is a function; no Disposiq methods ``` -------------------------------- ### Manage Disposables with DisposableStore Source: https://github.com/tioniq/disposiq/blob/main/README.md DisposableStore aggregates multiple disposables, allowing them to be disposed of collectively. It accepts functions or DisposableAction instances. ```typescript import { DisposableStore, DisposableAction } from '@tioniq/disposiq' const store = new DisposableStore() const disposable1 = new DisposableAction(() => { console.log('Resource cleaned up 1') }) // DisposableStore accepts functions as disposables const disposable2 = () => { console.log('Resource cleaned up 2') } store.add(disposable1) store.add(disposable2) store.dispose() // Output: Resource cleaned up 1, Resource cleaned up 2 const disposable3 = () => { console.log('Resource cleaned up 3') } // After disposing of the store, all disposables added to the store will be disposed of immediately store.add(disposable3) // Output: Resource cleaned up 3 ``` -------------------------------- ### Key-Indexed Disposable Map with DisposableMapStore Source: https://context7.com/tioniq/disposiq/llms.txt Use DisposableMapStore to maintain a Map of key-disposable pairs. Setting a key disposes the previous value. Deleting or disposing the store disposes all contained values. ```typescript import { DisposableAction, DisposableMapStore } from '@tioniq/disposiq' const map = new DisposableMapStore() map.set('user:1', new DisposableAction(() => console.log('user:1 connection closed'))) map.set('user:2', new DisposableAction(() => console.log('user:2 connection closed'))) // Replace an existing entry — old one is disposed automatically map.set('user:1', new DisposableAction(() => console.log('user:1 reconnection closed'))) // Output: user:1 connection closed // Delete and dispose a single entry map.delete('user:2') // Output: user:2 connection closed // extract() removes without disposing — useful for transferring ownership const d = map.extract('user:1') // returns the disposable, does NOT call dispose() // Dispose all remaining entries map.dispose() ``` -------------------------------- ### Type Guard Utilities Source: https://context7.com/tioniq/disposiq/llms.txt Runtime type guards for narrowing unknown values to disposable interfaces. ```APIDOC ## isDisposable ### Description Checks if an object is a direct implementation of the `IDisposable` interface (has a `dispose()` method). ### Method `isDisposable(obj)` ### Parameters - **obj** (any) - The value to check. ### Returns - `boolean` - True if the object is disposable, false otherwise. ### Example ```typescript import { isDisposable } from '@tioniq/disposiq' const obj = { dispose: () => {} } console.log(isDisposable(obj)) // true ``` ## isDisposableLike ### Description Checks if an object is disposable or can be treated as disposable (e.g., functions). ### Method `isDisposableLike(obj)` ### Parameters - **obj** (any) - The value to check. ### Returns - `boolean` - True if the object is disposable-like, false otherwise. ### Example ```typescript import { isDisposableLike } from '@tioniq/disposiq' const obj = { dispose: () => {} } const fn = () => {} console.log(isDisposableLike(obj)) // true console.log(isDisposableLike(fn)) // true ``` ## isDisposableCompat ### Description Checks if an object implements the compatible disposable interface (has both `dispose()` and `Symbol.dispose`). ### Method `isDisposableCompat(obj)` ### Parameters - **obj** (any) - The value to check. ### Returns - `boolean` - True if the object has the compatible disposable interface, false otherwise. ### Example ```typescript import { isDisposableCompat, DisposableAction } from '@tioniq/disposiq' const obj = { dispose: () => {} } // Does not have Symbol.dispose console.log(isDisposableCompat(obj)) // false const d = new DisposableAction(() => {}) // Has both dispose() and Symbol.dispose console.log(isDisposableCompat(d)) // true ``` ## isSystemDisposable ### Description Checks if an object implements the system disposable interface (has `Symbol.dispose`). ### Method `isSystemDisposable(obj)` ### Parameters - **obj** (any) - The value to check. ### Returns - `boolean` - True if the object has the system disposable interface, false otherwise. ### Example ```typescript import { isSystemDisposable, DisposableAction } from '@tioniq/disposiq' const d = new DisposableAction(() => {}) console.log(isSystemDisposable(d)) // true ``` ## isAsyncDisposableCompat ### Description Checks if an object implements the compatible async disposable interface (has both `disposeAsync()` and `Symbol.asyncDispose`). ### Method `isAsyncDisposableCompat(obj)` ### Parameters - **obj** (any) - The value to check. ### Returns - `boolean` - True if the object has the compatible async disposable interface, false otherwise. ### Example ```typescript // Assuming an AsyncDisposableAction class exists and implements this interface // import { isAsyncDisposableCompat, AsyncDisposableAction } from '@tioniq/disposiq' // const ad = new AsyncDisposableAction(async () => {}) // console.log(isAsyncDisposableCompat(ad)) // true ``` ``` -------------------------------- ### Single-Slot Swappable Disposable with DisposableContainer Source: https://context7.com/tioniq/disposiq/llms.txt Manage a single disposable at a time using DisposableContainer. Calling set() disposes the previous disposable. replace() swaps without disposing the old one, returning it. ```typescript import { DisposableAction, DisposableContainer } from '@tioniq/disposiq' const container = new DisposableContainer() container.set(new DisposableAction(() => console.log('first disposed'))) container.set(new DisposableAction(() => console.log('second disposed'))) // Output: first disposed ← automatically disposed when replaced // replace() swaps without disposing the old one — returns it instead const old = container.replace(new DisposableAction(() => console.log('third disposed'))) console.log(old) // DisposableAction { _disposed: false, ... } // disposeCurrent() clears the slot without marking the container disposed container.disposeCurrent() // Output: third disposed console.log(container.disposed) // false — container still active container.dispose() // no-op — slot is empty ``` -------------------------------- ### Fast Batch Dispose using disposeAllUnsafe Source: https://context7.com/tioniq/disposiq/llms.txt Use `disposeAllUnsafe` for faster batch disposal of array items. The array must not be modified during iteration. ```typescript // disposeAllUnsafe — faster, but array MUST NOT be modified during iteration disposeAllUnsafe([() => console.log('fast item')]) // Output: fast item ``` -------------------------------- ### Auto-dispose Disposable after Delay using disposeIn Source: https://context7.com/tioniq/disposiq/llms.txt Use `disposeIn` to schedule a disposable to be automatically disposed after a specified number of milliseconds. ```typescript // disposeIn — auto-dispose after N milliseconds const d2 = new DisposableAction(() => console.log('d2 auto-disposed after 500ms')) d2.disposeIn(500) ``` -------------------------------- ### DisposableAction Source: https://context7.com/tioniq/disposiq/llms.txt Wraps a zero-argument function to ensure it is called at most once, providing a `disposed` property and implementing `Symbol.dispose` for `using` keyword compatibility. ```APIDOC ## DisposableAction ### Description Wraps any zero-argument function and guarantees it is called **at most once**, no matter how many times `dispose()` is invoked. It exposes a `disposed` boolean property and implements `Symbol.dispose` for use with the `using` keyword. ### Usage ```typescript import { DisposableAction } from '@tioniq/disposiq' // Basic one-shot cleanup const cleanup = new DisposableAction(() => { console.log('connection closed') }) console.log(cleanup.disposed) // false cleanup.dispose() // Output: connection closed cleanup.dispose() // no-op — action is NOT called again console.log(cleanup.disposed) // true // Works with the 'using' keyword (TypeScript 5.2+) { using scoped = new DisposableAction(() => console.log('scope exited')) // ... do work ... } // Output: scope exited ``` ``` -------------------------------- ### Dispose Container Store Source: https://context7.com/tioniq/disposiq/llms.txt Call `store.dispose()` to dispose all disposables that were registered within the store. ```typescript store.dispose() // Output: d1 disposed ``` -------------------------------- ### addEventListener Source: https://context7.com/tioniq/disposiq/llms.txt Wraps the browser DOM `EventTarget.addEventListener` API, returning a `Disposiq` instance that automatically calls `removeEventListener` upon disposal. Compatible with any `EventTarget`-compatible object. ```APIDOC ## addEventListener(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): Disposiq ### Description Attaches an event listener to a DOM `EventTarget` and returns a `Disposiq` object that handles cleanup via `removeEventListener`. ### Parameters #### Path Parameters - **target** (EventTarget) - Required - The event target to attach the listener to. - **type** (string) - Required - The event type to listen for. - **listener** (EventListenerOrEventListenerObject) - Required - The callback function or object implementing the listener. - **options** (boolean | AddEventListenerOptions) - Optional - Options for the event listener. ### Request Example ```typescript import { addEventListener, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() // Attach a click listener; removed automatically when store is disposed store.add( addEventListener(document.getElementById('btn')!, 'click', (e: MouseEvent) => { console.log('clicked at', e.clientX, e.clientY) }) ) // With options store.add( addEventListener(window, 'scroll', () => console.log('scrolled'), { passive: true }) ) // Teardown — all DOM listeners removed store.dispose() ``` ``` -------------------------------- ### Dispose Current Disposables in Store Source: https://github.com/tioniq/disposiq/blob/main/README.md Use disposeCurrent to clean up only the disposables currently in the store without disposing of the store itself. This allows for adding new disposables later. ```typescript import { DisposableStore, DisposableAction } from '@tioniq/disposiq' const store = new DisposableStore() const disposable1 = new DisposableAction(() => { console.log('Resource cleaned up 1') }) const disposable2 = new DisposableAction(() => { console.log('Resource cleaned up 2') }) // You can add multiple disposables at once store.add(disposable1, disposable2) // Dispose of the current disposables in the store without disposing of the store itself store.disposeCurrent() // Output: Resource cleaned up 1, Resource cleaned up 2 // The store is still active, but all contained disposables are disposed of and removed from the store // You can now add new disposables to the store store.add(() => { console.log('Resource cleaned up 3') }) // No output // Dispose the store completely store.dispose() // Output: Resource cleaned up 3 ``` -------------------------------- ### Add Timers to DisposableStore Source: https://context7.com/tioniq/disposiq/llms.txt Register setTimeout and setInterval callbacks with DisposableStore. Both timers are automatically cleared when the store is disposed. ```typescript import { DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() // Register a timeout — clearTimeout is called on dispose store.addTimeout(() => console.log('delayed work'), 5000) // Register an interval — clearInterval is called on dispose store.addInterval(() => console.log('tick'), 1000) // Tear everything down; timers are cancelled before they fire store.dispose() ``` -------------------------------- ### Extend Disposable for Resource Management Source: https://context7.com/tioniq/disposiq/llms.txt Extend the base Disposable class to manage child resources. Use addDisposable() to attach child disposables which are automatically cleaned up when the parent is disposed. Supports 'using' keyword for automatic disposal. ```typescript import { Disposable, DisposableAction, disposableFromEvent } from '@tioniq/disposiq' import { EventEmitter } from 'events' class DataService extends Disposable { private readonly emitter = new EventEmitter() constructor() { super() // All registered disposables are cleaned up when this service is disposed this.addDisposable(new DisposableAction(() => console.log('DataService teardown'))) this.addDisposable(disposableFromEvent(this.emitter, 'data', (d) => console.log('data:', d))) } emit(data: unknown) { this.throwIfDisposed('DataService is disposed') this.emitter.emit('data', data) } } const svc = new DataService() sic.emit('hello') // Output: data: hello sic.dispose() // Output: DataService teardown // (event listener removed) // using keyword support built in { using s = new DataService() s.emit('world') // Output: data: world } // Output: DataService teardown ``` -------------------------------- ### DOM Event Listener with Disposable Cleanup Source: https://context7.com/tioniq/disposiq/llms.txt Wraps `EventTarget.addEventListener` to return a `Disposiq` that calls `removeEventListener` on dispose. Works with any `EventTarget`-compatible object. ```typescript import { addEventListener, DisposableStore } from '@tioniq/disposiq' const store = new DisposableStore() // Attach a click listener; removed automatically when store is disposed store.add( addEventListener(document.getElementById('btn')!, 'click', (e: MouseEvent) => { console.log('clicked at', e.clientX, e.clientY) }) ) // With options store.add( addEventListener(window, 'scroll', () => console.log('scrolled'), { passive: true }) ) // Teardown — all DOM listeners removed store.dispose() ``` -------------------------------- ### Create Disposable from CancellationToken Source: https://context7.com/tioniq/disposiq/llms.txt Bridges objects implementing CancellationTokenLike into the dispose pattern. Use `disposableFromCancellationToken` for this conversion. ```typescript import { disposableFromCancellationToken } from '@tioniq/disposiq' // Any object with a cancel() method qualifies const tokenSource = { cancelled: false, cancel() { this.cancelled = true }, get isCancelled() { return this.cancelled }, } const d = disposableFromCancellationToken(tokenSource) console.log(d.disposed) // false d.dispose() // calls tokenSource.cancel() console.log(d.disposed) // true console.log(tokenSource.cancelled) // true ``` -------------------------------- ### Wrap Disposable in Error-Swallowing Shell using toSafe Source: https://context7.com/tioniq/disposiq/llms.txt Use `toSafe` to wrap a disposable in a shell that catches and handles any errors thrown during disposal, preventing application crashes. ```typescript // toSafe — wrap in error-swallowing shell const d6 = new DisposableAction(() => { throw new Error('boom') }) const safe = d6.toSafe((err) => console.error('caught:', err)) safe.dispose() // Output: caught: Error: boom ``` -------------------------------- ### Use emptyDisposable as a No-op Singleton Source: https://context7.com/tioniq/disposiq/llms.txt Utilize `emptyDisposable` as a safe placeholder or default value. It implements both `DisposableCompat` and `AsyncDisposableCompat` and performs no operation when disposed. ```typescript import { emptyDisposable } from '@tioniq/disposiq' // Safe to call any number of times emptyDisposable.dispose() await emptyDisposable.dispose() // Useful as a default function createOptionalCleanup(enabled: boolean) { if (!enabled) return emptyDisposable return new DisposableAction(() => console.log('cleanup')) } const d = createOptionalCleanup(false) d.dispose() // no-op, no error ``` -------------------------------- ### Manage Event Listener Lifecycles Source: https://context7.com/tioniq/disposiq/llms.txt `disposableFromEvent` (or `on`) attaches a listener to a Node.js-style EventEmitter, returning a disposable that removes it. `disposableFromEventOnce` (or `once`) is for one-time listeners. ```typescript import { disposableFromEvent, disposableFromEventOnce, DisposableStore } from '@tioniq/disposiq' import { EventEmitter } from 'events' const emitter = new EventEmitter() const store = new DisposableStore() // Persistent listener — removed when store is disposed store.add( disposableFromEvent(emitter, 'data', (chunk) => { console.log('received:', chunk) }) ) // One-shot listener — auto-unregisters after first call, or on dispose store.add( disposableFromEventOnce(emitter, 'close', (code) => { console.log('closed with code:', code) }) ) emitter.emit('data', 'hello') // Output: received: hello emitter.emit('data', 'world') // Output: received: world store.dispose() emitter.emit('data', 'ignored') // no output — listener removed ```