first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# hooks
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Provides the helper functions that invoke the queue's eight lifecycle
callbacks safely. The queue itself wires hook firing into its pipeline;
this module isolates the "safe invocation" logic — coercion of thrown
values to real `Error` instances, async-await of both sync and async
hooks, and re-routing of secondary failures through `onError`.
## Features
- `invokeHook` swallows hook errors after re-routing them via `onError`,
so a misbehaving listener cannot crash the queue's main loop.
- `toError` coerces any thrown value (string, object, primitive) into a
real `Error` so downstream consumers see a uniform shape.
- The helper avoids recursive re-routing when the failing hook IS the
`onError` hook itself.
## Usage: Basic
```ts
import { invokeHook } from "@suaveplan/streams-chunk-queue";
await invokeHook(hooks.onChunkReceived, [chunkId, metadata], hooks.onError, chunkId);
```
## Usage: Advanced
```ts
import { invokeHook, toError } from "@suaveplan/streams-chunk-queue";
const onError = (err: Error) => logger.error({ err: toError(err) });
await invokeHook(
async (id: bigint) => await reportToObservability(id),
[chunkId],
onError,
chunkId,
);
```
## API Reference
### `invokeHook(hook, args, onError?, chunkId?)` → `Promise<void>`
- `hook` — optional `LifecycleHook<Args>`. If `undefined`, the call is
a no-op.
- `args` — tuple of arguments to forward.
- `onError` — optional `(error, chunkId?) => void | Promise<void>`
re-route. Not invoked if it is the same reference as `hook`.
- `chunkId` — optional bigint forwarded to `onError`.
### `toError(value)` → `Error`
Coerces any value to an `Error`.
## Implementation Notes
The recursion guard `onError !== hook` is the difference between a
queue that survives a buggy `onError` callback and one that hangs in an
infinite loop. When the secondary `onError` invocation itself throws,
the helper swallows the failure — the primary path is preserved
because the queue independently surfaces the error via the event
emitter and (for streaming errors) the controller.