bunqueue-client 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +102 -66
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,36 +1,74 @@
1
- # bunqueue-client — TypeScript SDK (Node / Bun / Deno)
1
+ # bunqueue-client
2
2
 
3
- Cross-runtime TypeScript client for [bunqueue](https://github.com/egeominotti/bunqueue),
4
- the high-performance job queue server. Talks the native TCP protocol
5
- (msgpack, pipelined, port 6789) — feature parity with the built-in Bun client,
6
- but runs on **any** modern JS/TS runtime.
3
+ Official TypeScript client for [bunqueue](https://github.com/egeominotti/bunqueue), the high performance job queue server. The client implements the native TCP protocol (msgpack, pipelined) and provides full feature parity with the built in Bun client, while running on every modern JavaScript runtime.
7
4
 
8
- The bunqueue **server** runs on Bun (binary or Docker). This SDK lets any
9
- Node, Bun, or Deno service produce and consume jobs on it: *one queue, any
10
- language, any runtime*.
5
+ The bunqueue server runs on Bun, distributed as a binary or a Docker image. This client allows any Node.js, Bun, Deno, or Cloudflare Workers service to produce and consume jobs against it: one queue, any language, any runtime.
11
6
 
12
- ## Runtime support
7
+ ## Compatibility
13
8
 
14
9
  | Runtime | Status | Notes |
15
10
  |---|---|---|
16
- | Node.js ≥ 20 | ✅ tested (58/58 e2e + 8/8 integration) | ESM; TS files run directly on Node ≥ 22 via `--experimental-strip-types` |
17
- | Bun | ✅ tested (58/58 e2e + 8/8 integration) | works out of the box |
18
- | Deno ≥ 2 | ✅ tested (58/58 e2e + 8/8 integration) | `node:` builtins + npm `msgpackr` |
19
- | tsx / ts-node / vitest / jest | ✅ | they run on Node underneath |
20
- | Cloudflare Workers | ✅ tested (11/11 e2e inside workerd) | needs `nodejs_compat` flag; no long-lived worker loops (request-scoped runtime) — consume via Cron Triggers / Durable Object alarms with batch pulls (covered by the suite); TLS requires a publicly trusted cert |
21
- | Browser | ❌ | no raw TCP sockets — use the server's HTTP API instead |
11
+ | Node.js 20 or later | Supported, 58/58 e2e and 8/8 integration tests | ESM. TypeScript files run directly on Node 22 or later via `--experimental-strip-types` |
12
+ | Bun | Supported, 58/58 e2e and 8/8 integration tests | No additional configuration required |
13
+ | Deno 2 or later | Supported, 58/58 e2e and 8/8 integration tests | Uses `node:` builtins and the npm `msgpackr` package |
14
+ | tsx, ts-node, vitest, jest | Supported | These environments execute on Node.js |
15
+ | Cloudflare Workers | Supported, 11/11 e2e tests inside workerd | Requires the `nodejs_compat` compatibility flag. The runtime is request scoped, so long lived worker loops are not available: consume in batches from Cron Triggers or Durable Object alarms, a pattern covered by the test suite. TLS connections require a publicly trusted certificate |
16
+ | Browser | Not supported | Raw TCP sockets are unavailable. Use the server HTTP API instead |
22
17
 
23
- The rule that makes this possible: the SDK uses **only `node:*` builtins**
24
- (`net`, `tls`, `events`, `crypto`, `os`) — no `Bun.*` globals, no
25
- `bun:`/`deno:` imports. Single runtime dependency: `msgpackr`.
18
+ Portability is guaranteed by design: the client relies exclusively on `node:*` builtins (`net`, `tls`, `events`, `crypto`, `os`), uses no `Bun.*` globals and no runtime specific imports, and carries a single runtime dependency, `msgpackr`.
26
19
 
27
- ## Install
20
+ ## Installation
28
21
 
29
22
  ```bash
30
- npm install bunqueue-client # or: bun add / pnpm add / deno add npm:bunqueue-client
23
+ npm install bunqueue-client
24
+ # or: bun add bunqueue-client / pnpm add bunqueue-client / deno add npm:bunqueue-client
31
25
  ```
32
26
 
33
- ## Producer
27
+ ## Quick start
28
+
29
+ Sixty seconds from zero to a working queue. Step 1, start the server (requires [Bun](https://bun.sh), or use the Docker image):
30
+
31
+ ```bash
32
+ bunx bunqueue start
33
+ ```
34
+
35
+ Step 2, create `app.ts`: add a job and process it, in the same file for the sake of the demo:
36
+
37
+ ```typescript
38
+ import { Queue, Worker } from 'bunqueue-client';
39
+
40
+ const worker = new Worker('hello', async (job) => {
41
+ console.log('processing', job.data);
42
+ return { greeted: job.data.name };
43
+ });
44
+ worker.on('completed', (job, result) => {
45
+ console.log('completed', job.id, result);
46
+ worker.close();
47
+ });
48
+
49
+ const queue = new Queue('hello');
50
+ await queue.add('greet', { name: 'world' });
51
+ queue.close();
52
+ ```
53
+
54
+ Step 3, run it with the runtime you already use:
55
+
56
+ ```bash
57
+ node --experimental-strip-types app.ts # Node 22 or later
58
+ bun app.ts # Bun
59
+ deno run -A app.ts # Deno 2 or later
60
+ ```
61
+
62
+ Expected output:
63
+
64
+ ```
65
+ processing { name: 'world' }
66
+ completed 019f40a5-... { greeted: 'world' }
67
+ ```
68
+
69
+ That is the whole model: the server owns state, retries, and scheduling, your code only adds and processes. In production the producer and the worker are separate services, often in different languages: the [Python client](https://github.com/egeominotti/bunqueue/tree/main/sdk/python) speaks the same protocol against the same queue. Defaults are `host: 'localhost'`, `port: 6789`, so constructors need no options on a local setup.
70
+
71
+ ## Producing jobs
34
72
 
35
73
  ```typescript
36
74
  import { Queue } from 'bunqueue-client';
@@ -47,7 +85,7 @@ const counts = await queue.getJobCounts();
47
85
  queue.close();
48
86
  ```
49
87
 
50
- ## Worker
88
+ ## Processing jobs
51
89
 
52
90
  ```typescript
53
91
  import { Worker, UnrecoverableError } from 'bunqueue-client';
@@ -56,7 +94,7 @@ const worker = new Worker(
56
94
  'emails',
57
95
  async (job) => {
58
96
  await job.updateProgress(50);
59
- if (job.data.invalid) throw new UnrecoverableError('bad payload'); // no retries → DLQ
97
+ if (job.data.invalid) throw new UnrecoverableError('bad payload'); // no retries, straight to the DLQ
60
98
  return { sent: true };
61
99
  },
62
100
  { host: 'localhost', port: 6789, concurrency: 10 }
@@ -65,11 +103,10 @@ const worker = new Worker(
65
103
  worker.on('completed', (job, result) => console.log(job.id, result));
66
104
  worker.on('failed', (job, err) => console.error(job.id, err.message));
67
105
 
68
- // later: await worker.close(); // graceful — waits for in-flight jobs
106
+ // later: await worker.close(); // graceful shutdown, waits for in flight jobs
69
107
  ```
70
108
 
71
- Retry, backoff, DLQ, stall detection, priorities and rate limiting all run
72
- **server-side** — the worker only pulls, heartbeats and acks.
109
+ Retry, backoff, dead letter queue, stall detection, priorities, and rate limiting all execute server side. The worker only pulls, heartbeats, and acknowledges, which keeps the client thin and the behavior consistent across languages.
73
110
 
74
111
  ## Flows
75
112
 
@@ -78,14 +115,14 @@ import { FlowProducer } from 'bunqueue-client';
78
115
 
79
116
  const flow = new FlowProducer({ host: 'localhost', port: 6789 });
80
117
 
81
- // sequential chain: step1 → step2 → step3
118
+ // sequential chain: step1, then step2, then step3
82
119
  await flow.addChain([
83
120
  { name: 'step1', queueName: 'pipeline' },
84
121
  { name: 'step2', queueName: 'pipeline' },
85
122
  { name: 'step3', queueName: 'pipeline' },
86
123
  ]);
87
124
 
88
- // fan-in: parallel jobs converge into a final job that reads their results
125
+ // fan in: parallel jobs converge into a final job that reads their results
89
126
  const { finalId } = await flow.addBulkThen(
90
127
  [
91
128
  { name: 'part1', queueName: 'pipeline' },
@@ -95,7 +132,7 @@ const { finalId } = await flow.addBulkThen(
95
132
  );
96
133
  // inside the 'merge' processor: await job.getChildrenValues()
97
134
 
98
- // parent/child tree (children run BEFORE the parent)
135
+ // parent and child tree: children always run before the parent
99
136
  const node = await flow.add({
100
137
  name: 'assemble', queueName: 'orders',
101
138
  children: [
@@ -105,7 +142,7 @@ const node = await flow.add({
105
142
  });
106
143
  ```
107
144
 
108
- ## Schedulers (cron)
145
+ ## Scheduling
109
146
 
110
147
  ```typescript
111
148
  await queue.addCron('daily-report', '0 9 * * *', { type: 'report' });
@@ -113,53 +150,52 @@ await queue.every('health-ping', 30_000, { type: 'ping' });
113
150
  await queue.removeJobScheduler('daily-report');
114
151
  ```
115
152
 
116
- ## TLS + Auth
153
+ ## Security
117
154
 
118
155
  ```typescript
119
156
  const queue = new Queue('emails', {
120
157
  host: 'queue.example.com',
121
158
  port: 6789,
122
159
  token: process.env.BUNQUEUE_TOKEN,
123
- tls: { caFile: './ca.pem' }, // or `true` for system CAs
160
+ tls: { caFile: './ca.pem' }, // or `true` for system certificate authorities
124
161
  });
125
162
  ```
126
163
 
127
- ## Feature surface
128
-
129
- - **Queue** — add/addBulk with full `JobOptions` (priority, delay, attempts,
130
- backoff, ttl, timeout, jobId, deduplication, dependsOn, tags, groupId, lifo,
131
- removeOnComplete/Fail, durable, repeat, debounce, …)
132
- - **Query** — getJob, getJobByCustomId, getJobs + per-state helpers, state,
133
- result, progress, waitForJob, counts (+ per priority), children values, logs
134
- - **Control** — pause/resume/drain/obliterate/clean, remove, discard, promote,
135
- retryJob/retryJobs, move to wait/delayed, change priority/delay, update
136
- data, extend lock
137
- - **DLQ** — getDlq, retryDlq, purgeDlq, DLQ config
138
- - **Admin** — rate limit, global concurrency, stall config, webhooks,
139
- stats/metrics/listQueues/getWorkers
140
- - **Worker events** — `ready`, `active`, `completed`, `failed`, `progress`,
141
- `drained`, `error`, `closed`; automatic lock heartbeats (jobs longer than
142
- the lock TTL survive)
143
-
144
- Not applicable outside Bun (by design): embedded mode, sandboxed workers,
145
- `QueueEvents` (in-process subscription — use webhooks or the HTTP SSE/WS
146
- endpoints instead).
147
-
148
- ## Development
164
+ Authentication uses server side tokens (`AUTH_TOKENS`). Transport security uses native TLS, with support for system certificate authorities, a custom CA bundle, or disabled verification for development environments.
165
+
166
+ ## API surface
167
+
168
+ | Area | Capabilities |
169
+ |---|---|
170
+ | Queue | `add`, `addBulk`, full `JobOptions`: priority, delay, attempts, backoff, ttl, timeout, jobId, deduplication, dependsOn, tags, groupId, lifo, removeOnComplete, removeOnFail, durable, repeat, debounce |
171
+ | Query | `getJob`, `getJobByCustomId`, `getJobs` with per state helpers, state, result, progress, `waitForJob`, counts, counts per priority, children values, job logs |
172
+ | Control | pause, resume, drain, obliterate, clean, remove, discard, promote, `retryJob`, `retryJobs`, move to wait or delayed, change priority or delay, update data, extend lock |
173
+ | Dead letter queue | `getDlq`, `retryDlq`, `purgeDlq`, DLQ configuration |
174
+ | Administration | rate limiting, global concurrency, stall configuration, webhooks, stats, metrics, `listQueues`, `getWorkers` |
175
+ | Worker events | `ready`, `active`, `completed`, `failed`, `progress`, `drained`, `error`, `closed`, with automatic lock heartbeats so that jobs longer than the lock TTL survive |
176
+
177
+ The following features require the in process Bun runtime and are intentionally out of scope for this client: embedded mode, sandboxed workers, and `QueueEvents`. Use webhooks or the HTTP SSE and WebSocket endpoints for event streaming.
178
+
179
+ Note on numeric payloads: JavaScript numbers are IEEE 754 doubles, exact up to 2^53. Pass larger 64 bit identifiers, for example snowflake IDs, as strings to avoid silent precision loss. Never place `BigInt` values in job data.
180
+
181
+ ## Quality assurance
182
+
183
+ Every release is validated against a real bunqueue server, spawned fresh for each run, across every supported runtime:
149
184
 
150
185
  ```bash
151
186
  bun install
152
- bun run build # tsc → dist/
153
- bun run check # biome check
154
-
155
- # Test suites (each spawns a real bunqueue server from the repo root)
156
- bun tests/integration.ts # smoke
157
- bun tests/e2e.ts # full surface + edge cases + realistic load
158
- node --experimental-strip-types tests/e2e.ts # same file on Node ≥22
159
- deno run -A tests/e2e.ts # same file on Deno ≥2
160
- bun run test:workers # full suite INSIDE workerd (Cloudflare Workers)
187
+ bun run build # tsc, emits dist/
188
+ bun run check # Biome lint and format verification
189
+
190
+ bun tests/integration.ts # smoke suite
191
+ bun tests/e2e.ts # full surface, edge cases, realistic load
192
+ node --experimental-strip-types tests/e2e.ts # identical suite on Node 22 or later
193
+ deno run -A tests/e2e.ts # identical suite on Deno 2 or later
194
+ bun run test:workers # full suite inside workerd, the Cloudflare Workers runtime
161
195
  ```
162
196
 
163
- Style rules: Biome, max 250 lines per file, relative imports with explicit
164
- `.js` extension (NodeNext resolution — required for Node ESM). See `CLAUDE.md`
165
- for the full development guide and wire-protocol gotchas.
197
+ The e2e suite includes payload limits, unicode integrity, pipelining under concurrency, server crash and restart with automatic reconnection, and a realistic multi queue production scenario with zero loss accounting. Engineering standards: Biome, a maximum of 250 lines per file, and relative imports with explicit `.js` extensions for NodeNext resolution. See `CLAUDE.md` for the full development guide and wire protocol notes.
198
+
199
+ ## License
200
+
201
+ MIT. See the [LICENSE](./LICENSE) file. Documentation: [bunqueue.dev/guide/sdks](https://bunqueue.dev/guide/sdks/). Issues and feature requests: [GitHub issues](https://github.com/egeominotti/bunqueue/issues).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunqueue-client",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Cross-runtime TypeScript client for the bunqueue job queue server — Node.js, Bun, Deno and Cloudflare Workers",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "lint": "biome lint src tests",
30
30
  "format": "biome format --write src tests",
31
31
  "check": "biome check src tests",
32
- "test:workers": "cd tests/workers && node run.mjs"
32
+ "test:workers": "bun pm pack --destination tests/workers && cd tests/workers && mv bunqueue-client-*.tgz bunqueue-client.tgz && bun install && node run.mjs"
33
33
  },
34
34
  "keywords": [
35
35
  "queue",