defer-close
Version:
A lightweight utility for adding JavaScript's Disposable and AsyncDisposable interfaces to any object
127 lines (93 loc) • 3.26 kB
Markdown
# defer-close
A lightweight utility for adding JavaScript's Disposable and AsyncDisposable interfaces to any object. This makes it easy to use automatic resource cleanup with `using` and `await using` statements.
[](https://www.npmjs.com/package/defer-close)
[](https://opensource.org/licenses/MIT)
## Installation
```bash
# Using npm
npm install defer-close
# Using yarn
yarn add defer-close
# Using pnpm
pnpm add defer-close
# Using bun
bun add defer-close
```
## Usage
```typescript
import deferClose from 'defer-close';
// Example with synchronous cleanup
function openResource() {
const resource = { data: 'important data' };
// Return a disposable version of the resource
return deferClose(resource, (res) => {
console.log('Resource closed:', res.data);
// Cleanup logic here
});
}
// Using the "using" statement (ES2022+)
{
using resource = openResource();
// Use the resource...
} // Resource automatically cleaned up here
// Example with asynchronous cleanup
function openAsyncResource() {
const resource = {
connection: 'db connection',
cache: new Map()
};
return deferClose(resource, async (res) => {
console.log('Closing connection:', res.connection);
await someAsyncCleanup();
res.cache.clear();
});
}
// Using with "await using" statement
async function example() {
{
await using dbResource = openAsyncResource();
// Use the resource...
} // Resource automatically cleaned up here, even if an exception occurs
}
```
## Real-World Example
Here's a practical example showing how to use `defer-close` with a POP3 email connection:
```typescript
import deferClose from 'defer-close';
import { Pop3Command } from 'your-pop3-library';
// Helper function for required environment variables
const DIE = (msg: string) => { throw new Error(msg); };
async function fetchEmails() {
// Create a disposable POP3 connection
await using pop3 = deferClose(new Pop3Command({
user: process.env.POP3_USER ?? DIE("missing POP3_USER"),
password: process.env.POP3_PASS ?? DIE("missing POP3_PASS"),
host: "pop.gmail.com",
port: 995,
tls: true,
}), async (pop3) => {
console.log('Closing connection...');
await pop3.QUIT();
});
// Use the POP3 connection to fetch emails
const messageList = await pop3.LIST();
console.log(`Found ${messageList.length} messages`);
// Process emails...
return messageList;
// Connection will be automatically closed when exiting this function
// The QUIT command will be called automatically
}
```
This example demonstrates how `defer-close` ensures proper resource cleanup even in complex scenarios like network connections.
## API
### deferClose<T>(obj: T, fn: (obj: T) => any): T & Disposable & AsyncDisposable
Adds Disposable and AsyncDisposable interfaces to an object.
- `obj`: The object to make disposable
- `fn`: A function that will be called when the resource is disposed. Can be synchronous or asynchronous.
Returns the original object enhanced with Disposable and AsyncDisposable interfaces.
## Testing
```bash
bun test
```
## License
MIT © snomiao