queue-jobs-worker 1.0.1 → 1.0.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.
- package/CHANGELOG.md +75 -69
- package/README.md +34 -120
- package/dist/core/worker.d.ts.map +1 -1
- package/dist/index.cjs +111 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +111 -47
- package/dist/index.js.map +1 -1
- package/dist/storage/in-memory.adapter.d.ts.map +1 -1
- package/dist/storage/redis.adapter.d.ts.map +1 -1
- package/package.json +20 -8
package/CHANGELOG.md
CHANGED
|
@@ -6,18 +6,45 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
6
6
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
8
|
---
|
|
9
|
-
## [1.0.
|
|
9
|
+
## [1.0.2] — 2026-09-05
|
|
10
10
|
|
|
11
11
|
### Core
|
|
12
12
|
|
|
13
13
|
### Fixed
|
|
14
14
|
|
|
15
|
-
- **`Worker
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
next
|
|
15
|
+
- **`Worker` — croner added as a required dependency; invalid expressions no longer fall back to a 1-minute interval** ([#5](https://github.com/rafidahmed870/queue-jobs-worker/issues/5))
|
|
16
|
+
|
|
17
|
+
`enqueueCronNext()` previously attempted a dynamic `import("croner")` inside
|
|
18
|
+
a try/catch. If the import failed — or if the resolved `Cron` class was not a
|
|
19
|
+
function — the code silently fell back to `Date.now() + 60_000`, scheduling
|
|
20
|
+
the next run 60 seconds later regardless of the configured cron expression.
|
|
21
|
+
The same silent fallback was also triggered for invalid cron expressions that
|
|
22
|
+
caused the `Cron` constructor to throw.
|
|
23
|
+
|
|
24
|
+
After the fix:
|
|
25
|
+
|
|
26
|
+
- `croner` is now declared as a proper `dependency` in `package.json`
|
|
27
|
+
(`^10.0.1`) and imported statically, so it is always available without any
|
|
28
|
+
dynamic-import dance.
|
|
29
|
+
- If the `Cron` constructor throws (invalid expression), a descriptive
|
|
30
|
+
`worker:error` event is emitted and re-enqueue is skipped. The worker
|
|
31
|
+
remains running.
|
|
32
|
+
- If `cronInstance.nextRun()` returns `null` (the schedule has no future
|
|
33
|
+
occurrences), a `worker:error` is emitted and re-enqueue is skipped. Again,
|
|
34
|
+
the worker keeps running.
|
|
35
|
+
- The 1-minute fallback path has been removed entirely — there is no silent
|
|
36
|
+
fallback under any failure condition.
|
|
37
|
+
|
|
38
|
+
- **`Worker` — rate-limit quota no longer consumed on empty-queue polls** ([#4](https://github.com/rafidahmed870/queue-jobs-worker/issues/4))
|
|
39
|
+
|
|
40
|
+
`claimNext()` previously called `checkAndIncrementRateLimit()` before
|
|
41
|
+
attempting to claim a job. This meant every poll cycle against an empty queue
|
|
42
|
+
burned a quota slot, potentially exhausting the configured window budget
|
|
43
|
+
before any real work was done. After the fix, the storage `claim()` call
|
|
44
|
+
happens first; the rate-limit counter is only incremented when a job is
|
|
45
|
+
actually claimed for processing. If the rate limit is reached at that point
|
|
46
|
+
the lock is immediately released via `releaseLock()` so the job remains
|
|
47
|
+
reclaimable on the next window.
|
|
21
48
|
|
|
22
49
|
---
|
|
23
50
|
|
|
@@ -38,85 +65,64 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
38
65
|
|
|
39
66
|
### Fixed
|
|
40
67
|
|
|
41
|
-
- **`
|
|
42
|
-
|
|
43
|
-
All four adapters were clearing `lockExpiresAt` to `null` / empty string
|
|
44
|
-
while keeping `status` as `"active"`. Because `recoverStalledJobs()` requires
|
|
45
|
-
a non-null, already-expired `lockExpiresAt` to match a stalled job, those
|
|
46
|
-
jobs were silently skipped and could never be reclaimed or retried.
|
|
47
|
-
|
|
48
|
-
- `InMemoryStorageAdapter.releaseLock()` — `lockExpiresAt` now set to `new Date().toISOString()` instead of `null`.
|
|
49
|
-
- `RedisStorageAdapter.releaseLock()` — `lockExpiresAt` hash field now set to the current ISO timestamp instead of `""`.
|
|
50
|
-
- `PostgreSQLStorageAdapter.releaseLock()` — `lock_expires_at` column now set to `NOW()` instead of `NULL`.
|
|
51
|
-
- `MySQLStorageAdapter.releaseLock()` — `lock_expires_at` column now set to `NOW(3)` instead of `NULL`.
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## [1.0.0] — 2026-08-29
|
|
56
|
-
|
|
57
|
-
### Added
|
|
58
|
-
|
|
59
|
-
**Core**
|
|
60
|
-
|
|
61
|
-
- `QueueClient` — primary entry point; configures storage, exposes queues, and coordinates lifecycle.
|
|
62
|
-
- `Queue` — independent job stream with per-queue configuration overrides.
|
|
63
|
-
- `Job` — rich wrapper around the raw job data record; passed to user processors.
|
|
64
|
-
- `Worker` — claims and executes jobs with configurable concurrency and graceful shutdown.
|
|
65
|
-
- `QueueEventEmitter` — strongly-typed lifecycle event bus shared across all components.
|
|
66
|
-
|
|
67
|
-
**Job processing**
|
|
68
|
-
|
|
69
|
-
- At-least-once delivery guarantee.
|
|
70
|
-
- Stable job identity preserved across all retries (no duplicate job IDs).
|
|
71
|
-
- Full attempt history stored per job.
|
|
72
|
-
- Per-job processor timeout enforcement.
|
|
73
|
-
- Priority-ordered job claiming (higher priority = claimed first).
|
|
74
|
-
- Delayed and scheduled job support via `schedule.delay` and `schedule.runAt`.
|
|
75
|
-
- Recurring job support via `schedule.cron` field (cron expression stored; recurrence integration point provided).
|
|
68
|
+
- **`recoverStalledJobs()` race condition — stale recovery overwrites a live job** ([#6](https://github.com/rafidahmed870/queue-jobs-worker/issues/6))
|
|
76
69
|
|
|
77
|
-
|
|
70
|
+
The previous implementation used a two-phase read-then-write pattern:
|
|
78
71
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- Dead Letter Queue (DLQ): jobs moved to `dead` status after exhausting all attempts.
|
|
82
|
-
- Stalled-job recovery: expired locks on `active` jobs are detected and re-queued automatically.
|
|
83
|
-
- Configurable lock duration (`lockDuration`) per queue.
|
|
72
|
+
1. A fetch pipeline read `lockExpiresAt` and `priority` for all active jobs.
|
|
73
|
+
2. A separate write pipeline recovered every job whose lock appeared expired.
|
|
84
74
|
|
|
85
|
-
|
|
75
|
+
Between those two phases a worker could complete the job, fail it, or renew
|
|
76
|
+
its lock. The write pipeline had no knowledge of that change and would
|
|
77
|
+
unconditionally overwrite the job back to `"waiting"`, causing duplicate
|
|
78
|
+
processing or data loss.
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
-
|
|
80
|
+
**`RedisStorageAdapter`** — the write pipeline has been replaced with a
|
|
81
|
+
per-job Lua script (`RECOVER_STALLED_LUA`) that implements a
|
|
82
|
+
**compare-and-swap (CAS)** guard. The script atomically re-reads
|
|
83
|
+
`lockExpiresAt`, `lockId`, and `status` from the hash and aborts if any of
|
|
84
|
+
the three values differ from what the caller observed in the read phase.
|
|
85
|
+
Because Redis executes Lua scripts as a single indivisible command, no
|
|
86
|
+
concurrent write can slip between the re-read and the state update. The
|
|
87
|
+
pre-filter (skip jobs whose lock has not yet expired) is preserved as an
|
|
88
|
+
optimisation to avoid unnecessary Lua round-trips.
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
**`InMemoryStorageAdapter`** — all operations run within a single event-loop
|
|
91
|
+
tick so the race is theoretical, but an equivalent CAS guard has been added
|
|
92
|
+
for consistency: `lockId` and `lockExpiresAt` are snapshotted at decision
|
|
93
|
+
time and re-validated immediately before the write. Any interleaving that
|
|
94
|
+
mutated those fields will cause the recovery to be skipped.
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
**Storage**
|
|
96
|
+
---
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
- `InMemoryStorageAdapter` — full-featured in-process adapter for development and testing.
|
|
98
|
+
## [1.0.1] — 2026-08-31
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
### Core
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
- `QueueClient.withAdapter()` static factory for supplying a custom storage adapter.
|
|
102
|
+
### Fixed
|
|
103
103
|
|
|
104
|
-
**
|
|
104
|
+
- **`Worker.stop()` — clarified `releaseLock()` behavior in shutdown comment** ([#1](https://github.com/rafidahmed870/queue-jobs-worker/issues/1))
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
The inline comment in `worker.ts` now correctly explains that `releaseLock()`
|
|
107
|
+
sets `lockExpiresAt` to an already-expired timestamp (not null/empty), so
|
|
108
|
+
`recoverStalledJobs()` on any worker will immediately reclaim the job on the
|
|
109
|
+
next stall-check cycle.
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
---
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
- Declaration files (`.d.ts` + `.d.ts.map`) generated via `tsc`.
|
|
113
|
+
### Events
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
### Added
|
|
115
116
|
|
|
116
|
-
-
|
|
117
|
-
-
|
|
117
|
+
- `QueueEventEmitter` — strongly-typed lifecycle event bus shared across all components.
|
|
118
|
+
- Emits events for the full job lifecycle: enqueued, started, completed, failed, retrying, dead, stalled.
|
|
119
|
+
- All event payloads fully typed via `events.types.ts`.
|
|
118
120
|
|
|
119
121
|
---
|
|
120
122
|
|
|
123
|
+
<!-- Links -->
|
|
124
|
+
|
|
125
|
+
[1.0.2]: https://github.com/rafidahmed870/queue-jobs-worker/compare/v1.0.0...v1.0.2
|
|
126
|
+
[1.0.0]: https://github.com/rafidahmed870/queue-jobs-worker/releases/tag/v1.0.0
|
|
121
127
|
[1.0.1]: https://github.com/rafidahmed870/queue-jobs-worker/compare/v1.0.0...v1.0.1
|
|
122
128
|
[1.0.0]: https://github.com/rafidahmed870/queue-jobs-worker/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ A production-ready background job queue for Node.js — persistent, reliable, an
|
|
|
12
12
|
|
|
13
13
|
`queue-jobs-worker` lets you push work into a persistent queue and process it in the background — outside the main request lifecycle. You define the processor; the library handles everything else: queueing, persistence, retries, scheduling, concurrency, and failure recovery.
|
|
14
14
|
|
|
15
|
+
For a full breakdown of every feature, see [FEATURES.md](./FEATURES.md).
|
|
16
|
+
|
|
15
17
|
**Supports:**
|
|
16
18
|
- In-memory (dev / testing)
|
|
17
19
|
- Redis (node-redis v4+)
|
|
@@ -374,29 +376,7 @@ queue.process("send-push", async (job) => {
|
|
|
374
376
|
});
|
|
375
377
|
```
|
|
376
378
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
```js
|
|
380
|
-
job.id // unique stable ID
|
|
381
|
-
job.type // job type string
|
|
382
|
-
job.data // your payload (never logged)
|
|
383
|
-
job.attemptsMade // attempts already executed
|
|
384
|
-
job.maxAttempts // maximum allowed
|
|
385
|
-
job.attemptsRemaining
|
|
386
|
-
job.attemptHistory // array of past attempt records
|
|
387
|
-
job.status // current status
|
|
388
|
-
job.priority
|
|
389
|
-
job.runAt
|
|
390
|
-
job.createdAt
|
|
391
|
-
job.updatedAt
|
|
392
|
-
|
|
393
|
-
// helpers
|
|
394
|
-
job.isActive()
|
|
395
|
-
job.isCompleted()
|
|
396
|
-
job.isWaiting()
|
|
397
|
-
job.isDelayed()
|
|
398
|
-
job.isDead()
|
|
399
|
-
```
|
|
379
|
+
For the full list of `job` fields and helper methods, see [FEATURES.md → Job Identity & Metadata](./FEATURES.md#job-identity--metadata).
|
|
400
380
|
|
|
401
381
|
---
|
|
402
382
|
|
|
@@ -429,35 +409,17 @@ const w2 = queue.createWorker({ concurrency: 5 });
|
|
|
429
409
|
All lifecycle events are emitted on the client. Subscribe before creating queues/workers:
|
|
430
410
|
|
|
431
411
|
```js
|
|
432
|
-
// Job events
|
|
433
|
-
client.on("job:enqueued", (job) => console.log("Enqueued:", job.id));
|
|
434
|
-
client.on("job:started", (job) => console.log("Started:", job.id));
|
|
435
412
|
client.on("job:completed", (job) => console.log("Done:", job.id));
|
|
436
413
|
client.on("job:failed", (job, err) => console.error("Failed:", job.id, err.message));
|
|
437
|
-
client.on("job:retrying", (job, err, nextRunAt) => {
|
|
438
|
-
console.log(`Retrying ${job.id} at ${nextRunAt}`);
|
|
439
|
-
});
|
|
440
414
|
client.on("job:dead", (job, err) => console.error("DLQ:", job.id, err.message));
|
|
441
|
-
client.on("
|
|
442
|
-
client.on("job:recovered", (jobId) => console.log("Recovered:", jobId));
|
|
415
|
+
client.on("worker:error", (workerId, err) => console.error("Worker error:", err));
|
|
443
416
|
|
|
444
|
-
//
|
|
445
|
-
client.
|
|
446
|
-
client.on("worker:stopped", (workerId) => console.log("Worker stopped:", workerId));
|
|
447
|
-
client.on("worker:status", (workerId, status) => console.log(workerId, "→", status));
|
|
448
|
-
client.on("worker:error", (workerId, err) => console.error("Worker error:", err));
|
|
449
|
-
|
|
450
|
-
// Queue / system errors
|
|
451
|
-
client.on("queue:error", (queueName, err) => console.error("Queue error:", queueName, err));
|
|
452
|
-
client.on("error", (err) => console.error("Error:", err));
|
|
453
|
-
|
|
454
|
-
// Remove a listener
|
|
455
|
-
client.off("job:completed", myListener);
|
|
456
|
-
|
|
457
|
-
// One-time listener
|
|
458
|
-
client.once("job:dead", (job, err) => alertTeam(job, err));
|
|
417
|
+
client.off("job:completed", myListener); // remove a listener
|
|
418
|
+
client.once("job:dead", (job, err) => alertTeam(job, err)); // one-time listener
|
|
459
419
|
```
|
|
460
420
|
|
|
421
|
+
For the full event reference (all job, worker, and system events), see [FEATURES.md → Event System](./FEATURES.md#event-system).
|
|
422
|
+
|
|
461
423
|
---
|
|
462
424
|
|
|
463
425
|
## Querying Jobs
|
|
@@ -507,44 +469,24 @@ await queue.enqueue("task", payload, {
|
|
|
507
469
|
});
|
|
508
470
|
```
|
|
509
471
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
| Strategy | Formula | Example (base = 1 s) |
|
|
513
|
-
|---|---|---|
|
|
514
|
-
| `fixed` | `baseDelay` | 1 s, 1 s, 1 s |
|
|
515
|
-
| `linear` | `baseDelay × attempt` | 1 s, 2 s, 3 s |
|
|
516
|
-
| `exponential` | `baseDelay × 2^(attempt-1)` (max 10 min) | 1 s, 2 s, 4 s, 8 s |
|
|
517
|
-
|
|
518
|
-
Each failed attempt is recorded in `job.attemptHistory`:
|
|
519
|
-
|
|
520
|
-
```js
|
|
521
|
-
job.attemptHistory.forEach((attempt) => {
|
|
522
|
-
console.log(`Attempt ${attempt.attempt}: ${attempt.error}`);
|
|
523
|
-
});
|
|
524
|
-
```
|
|
472
|
+
Three strategies are available: `fixed`, `linear`, and `exponential`. Each failed attempt is recorded in `job.attemptHistory`. See [FEATURES.md → Retry & Backoff](./FEATURES.md#retry--backoff) for strategy formulas and details.
|
|
525
473
|
|
|
526
474
|
---
|
|
527
475
|
|
|
528
476
|
## Scheduling
|
|
529
477
|
|
|
530
478
|
```js
|
|
531
|
-
//
|
|
532
|
-
await queue.enqueue("reminder", payload, {
|
|
533
|
-
schedule: { delay: 30_000 },
|
|
534
|
-
});
|
|
479
|
+
// Relative delay
|
|
480
|
+
await queue.enqueue("reminder", payload, { schedule: { delay: 30_000 } });
|
|
535
481
|
|
|
536
|
-
//
|
|
537
|
-
await queue.enqueue("report", payload, {
|
|
538
|
-
schedule: { runAt: "2026-09-01T09:00:00Z" },
|
|
539
|
-
});
|
|
482
|
+
// Absolute timestamp
|
|
483
|
+
await queue.enqueue("report", payload, { schedule: { runAt: "2026-09-01T09:00:00Z" } });
|
|
540
484
|
|
|
541
|
-
//
|
|
542
|
-
await queue.enqueue("cleanup", payload, {
|
|
543
|
-
schedule: { cron: "0 3 * * *" },
|
|
544
|
-
});
|
|
485
|
+
// Cron expression (stored for recurring jobs)
|
|
486
|
+
await queue.enqueue("cleanup", payload, { schedule: { cron: "0 3 * * *" } });
|
|
545
487
|
```
|
|
546
488
|
|
|
547
|
-
Delayed jobs are not eligible until their `runAt` time.
|
|
489
|
+
Delayed jobs are not eligible until their `runAt` time. See [FEATURES.md → Scheduling](./FEATURES.md#scheduling) for details on how each adapter handles promotion.
|
|
548
490
|
|
|
549
491
|
---
|
|
550
492
|
|
|
@@ -556,34 +498,22 @@ Higher values are processed first. Default is `0`.
|
|
|
556
498
|
await queue.enqueue("urgent-task", payload, { priority: 100 });
|
|
557
499
|
await queue.enqueue("normal-task", payload, { priority: 0 });
|
|
558
500
|
await queue.enqueue("low-task", payload, { priority: -10 });
|
|
559
|
-
|
|
560
501
|
// Processing order: urgent → normal → low
|
|
561
502
|
```
|
|
562
503
|
|
|
504
|
+
See [FEATURES.md → Priority](./FEATURES.md#priority).
|
|
505
|
+
|
|
563
506
|
---
|
|
564
507
|
|
|
565
508
|
## Rate Limiting
|
|
566
509
|
|
|
567
|
-
Limit how many jobs are processed per time window:
|
|
568
|
-
|
|
569
510
|
```js
|
|
570
|
-
// Queue-level rate limit
|
|
571
511
|
const queue = client.createQueue("webhooks", {
|
|
572
|
-
rateLimit: {
|
|
573
|
-
max: 50, // max 50 jobs
|
|
574
|
-
duration: 60_000, // per 60 seconds
|
|
575
|
-
},
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
// Or as a client default
|
|
579
|
-
const client = new QueueClient({
|
|
580
|
-
defaults: {
|
|
581
|
-
rateLimit: { max: 100, duration: 60_000 },
|
|
582
|
-
},
|
|
512
|
+
rateLimit: { max: 50, duration: 60_000 }, // 50 jobs per minute
|
|
583
513
|
});
|
|
584
514
|
```
|
|
585
515
|
|
|
586
|
-
When the limit is reached, workers skip claiming until the window resets
|
|
516
|
+
When the limit is reached, workers skip claiming until the window resets — jobs are never discarded. See [FEATURES.md → Rate Limiting](./FEATURES.md#rate-limiting).
|
|
587
517
|
|
|
588
518
|
---
|
|
589
519
|
|
|
@@ -593,26 +523,14 @@ When a job exhausts all retry attempts it is moved to the DLQ (status: `"dead"`)
|
|
|
593
523
|
|
|
594
524
|
```js
|
|
595
525
|
client.on("job:dead", async (job, error) => {
|
|
596
|
-
await alertOncall({
|
|
597
|
-
jobId: job.id,
|
|
598
|
-
type: job.type,
|
|
599
|
-
error: error.message,
|
|
600
|
-
attempts: job.attemptsMade,
|
|
601
|
-
});
|
|
526
|
+
await alertOncall({ jobId: job.id, type: job.type, error: error.message });
|
|
602
527
|
});
|
|
603
528
|
|
|
604
|
-
// Query dead jobs
|
|
605
529
|
const deadJobs = await queue.getJobs("dead");
|
|
606
|
-
|
|
607
|
-
// Inspect a dead job's full attempt history
|
|
608
|
-
const job = await queue.getJob(jobId);
|
|
609
|
-
if (job) {
|
|
610
|
-
job.attemptHistory.forEach((a) => {
|
|
611
|
-
console.log(`Attempt ${a.attempt} failed: ${a.error}`);
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
530
|
```
|
|
615
531
|
|
|
532
|
+
Full attempt history is preserved on the job. See [FEATURES.md → Dead Letter Queue](./FEATURES.md#dead-letter-queue).
|
|
533
|
+
|
|
616
534
|
---
|
|
617
535
|
|
|
618
536
|
## Graceful Shutdown
|
|
@@ -620,21 +538,17 @@ if (job) {
|
|
|
620
538
|
Always call `client.close()` before your process exits:
|
|
621
539
|
|
|
622
540
|
```js
|
|
623
|
-
async
|
|
624
|
-
await client.close(); // stops workers, releases locks, closes
|
|
541
|
+
process.on("SIGTERM", async () => {
|
|
542
|
+
await client.close(); // stops workers, releases locks, closes connections
|
|
625
543
|
process.exit(0);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
process.
|
|
544
|
+
});
|
|
545
|
+
process.on("SIGINT", async () => {
|
|
546
|
+
await client.close();
|
|
547
|
+
process.exit(0);
|
|
548
|
+
});
|
|
630
549
|
```
|
|
631
550
|
|
|
632
|
-
|
|
633
|
-
1. Stops polling for new jobs
|
|
634
|
-
2. Waits up to `shutdownTimeout` (default 30 s) for active jobs to finish
|
|
635
|
-
3. Releases DB/Redis connections
|
|
636
|
-
|
|
637
|
-
Interrupted jobs remain recoverable — the stalled-job recovery mechanism will reclaim them on the next startup.
|
|
551
|
+
Interrupted jobs remain recoverable via the stalled-job recovery mechanism. See [FEATURES.md → Graceful Shutdown](./FEATURES.md#graceful-shutdown).
|
|
638
552
|
|
|
639
553
|
---
|
|
640
554
|
|
|
@@ -820,8 +734,8 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
|
820
734
|
|
|
821
735
|
MIT — [LICENSE](./LICENSE)
|
|
822
736
|
|
|
823
|
-
|
|
737
|
+
## Donation
|
|
824
738
|
|
|
825
|
-
|
|
739
|
+
If you find this project useful, you can support me with a coffee.
|
|
826
740
|
|
|
827
|
-
BTC
|
|
741
|
+
**BTC:** `12dxgVQ3sRFhc4g7M6oydsN2tTMMthJJqS`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/core/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/core/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAyBjD,qBAAa,MAAM;IACjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAE1D,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,WAAW,CAAK;IAExB;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAElD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,YAAY,CAA+B;IAEnD,4DAA4D;IAC5D,OAAO,CAAC,YAAY,CAA6B;gBAG/C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,EAC3C,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,gBAAgB;IAc5B,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,8BAA8B;IAC9B,KAAK,IAAI,IAAI;IAab;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD3B,OAAO,CAAC,YAAY;YAQN,IAAI;YAsBJ,SAAS;YAyCT,UAAU;YAwDV,eAAe;YA4Df,aAAa;IA0C3B,OAAO,CAAC,kBAAkB;YAQZ,kBAAkB;CAkBjC"}
|