@zudojs/queue 0.1.0 → 1.1.0
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/LICENSE +21 -0
- package/README.md +40 -8
- package/dist/deadLetter/deadLetter.core.js +1 -1
- package/dist/inMemoryQueue/inMemoryQueue.core.d.ts +95 -4
- package/dist/inMemoryQueue/inMemoryQueue.core.js +398 -73
- package/dist/inMemoryQueue/inMemoryQueue.processing.d.ts +53 -8
- package/dist/inMemoryQueue/inMemoryQueue.processing.js +83 -36
- package/dist/inMemoryQueue/inMemoryQueue.scheduling.d.ts +17 -1
- package/dist/inMemoryQueue/inMemoryQueue.scheduling.js +43 -11
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/job/job.core.js +20 -12
- package/dist/job/job.type.d.ts +3 -2
- package/dist/jobOptions/jobOptions.type.d.ts +12 -3
- package/dist/jobTypes/index.d.ts +1 -1
- package/dist/jobTypes/jobTypes.type.d.ts +9 -0
- package/dist/middleware/middleware.core.d.ts +10 -1
- package/dist/middleware/middleware.core.js +40 -17
- package/dist/processor/index.d.ts +1 -1
- package/dist/processor/index.js +1 -1
- package/dist/processor/processor.core.js +2 -0
- package/dist/processor/processor.type.d.ts +18 -1
- package/dist/processor/processor.type.js +15 -0
- package/dist/queue/index.d.ts +1 -1
- package/dist/queue/queue.core.js +2 -2
- package/dist/queue/queue.type.d.ts +108 -2
- package/dist/queueEmitter/queueEmitter.core.d.ts +22 -2
- package/dist/queueEmitter/queueEmitter.core.js +47 -7
- package/dist/queueManager/queueManager.core.js +24 -5
- package/dist/queueRegistry/queueRegistry.core.js +15 -0
- package/dist/queueRegistry/queueRegistry.type.d.ts +2 -0
- package/dist/retryPolicy/retryPolicy.core.d.ts +42 -3
- package/dist/retryPolicy/retryPolicy.core.js +82 -13
- package/dist/serializer/serializer.core.d.ts +2 -1
- package/dist/worker/worker.core.d.ts +4 -0
- package/dist/worker/worker.core.js +139 -37
- package/dist/worker/worker.type.d.ts +17 -3
- package/package.json +25 -14
- package/dist/.tsbuildinfo +0 -1
- package/dist/deadLetter/deadLetter.core.d.ts.map +0 -1
- package/dist/deadLetter/deadLetter.core.js.map +0 -1
- package/dist/deadLetter/deadLetter.type.d.ts.map +0 -1
- package/dist/deadLetter/deadLetter.type.js.map +0 -1
- package/dist/deadLetter/index.d.ts.map +0 -1
- package/dist/deadLetter/index.js.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.core.d.ts.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.core.js.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.factory.d.ts.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.factory.js.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.processing.d.ts.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.processing.js.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.scheduling.d.ts.map +0 -1
- package/dist/inMemoryQueue/inMemoryQueue.scheduling.js.map +0 -1
- package/dist/inMemoryQueue/index.d.ts.map +0 -1
- package/dist/inMemoryQueue/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/job/index.d.ts.map +0 -1
- package/dist/job/index.js.map +0 -1
- package/dist/job/job.core.d.ts.map +0 -1
- package/dist/job/job.core.js.map +0 -1
- package/dist/job/job.type.d.ts.map +0 -1
- package/dist/job/job.type.js.map +0 -1
- package/dist/jobContext/index.d.ts.map +0 -1
- package/dist/jobContext/index.js.map +0 -1
- package/dist/jobContext/jobContext.core.d.ts.map +0 -1
- package/dist/jobContext/jobContext.core.js.map +0 -1
- package/dist/jobContext/jobContext.type.d.ts.map +0 -1
- package/dist/jobContext/jobContext.type.js.map +0 -1
- package/dist/jobOptions/index.d.ts.map +0 -1
- package/dist/jobOptions/index.js.map +0 -1
- package/dist/jobOptions/jobOptions.core.d.ts.map +0 -1
- package/dist/jobOptions/jobOptions.core.js.map +0 -1
- package/dist/jobOptions/jobOptions.type.d.ts.map +0 -1
- package/dist/jobOptions/jobOptions.type.js.map +0 -1
- package/dist/jobResult/index.d.ts.map +0 -1
- package/dist/jobResult/index.js.map +0 -1
- package/dist/jobResult/jobResult.core.d.ts.map +0 -1
- package/dist/jobResult/jobResult.core.js.map +0 -1
- package/dist/jobResult/jobResult.type.d.ts.map +0 -1
- package/dist/jobResult/jobResult.type.js.map +0 -1
- package/dist/jobTypes/index.d.ts.map +0 -1
- package/dist/jobTypes/index.js.map +0 -1
- package/dist/jobTypes/jobTypes.type.d.ts.map +0 -1
- package/dist/jobTypes/jobTypes.type.js.map +0 -1
- package/dist/middleware/index.d.ts.map +0 -1
- package/dist/middleware/index.js.map +0 -1
- package/dist/middleware/middleware.core.d.ts.map +0 -1
- package/dist/middleware/middleware.core.js.map +0 -1
- package/dist/middleware/middleware.type.d.ts.map +0 -1
- package/dist/middleware/middleware.type.js.map +0 -1
- package/dist/processor/index.d.ts.map +0 -1
- package/dist/processor/index.js.map +0 -1
- package/dist/processor/processor.core.d.ts.map +0 -1
- package/dist/processor/processor.core.js.map +0 -1
- package/dist/processor/processor.type.d.ts.map +0 -1
- package/dist/processor/processor.type.js.map +0 -1
- package/dist/queue/index.d.ts.map +0 -1
- package/dist/queue/index.js.map +0 -1
- package/dist/queue/queue.core.d.ts.map +0 -1
- package/dist/queue/queue.core.js.map +0 -1
- package/dist/queue/queue.type.d.ts.map +0 -1
- package/dist/queue/queue.type.js.map +0 -1
- package/dist/queueEmitter/index.d.ts.map +0 -1
- package/dist/queueEmitter/index.js.map +0 -1
- package/dist/queueEmitter/queueEmitter.core.d.ts.map +0 -1
- package/dist/queueEmitter/queueEmitter.core.js.map +0 -1
- package/dist/queueEmitter/queueEmitter.type.d.ts.map +0 -1
- package/dist/queueEmitter/queueEmitter.type.js.map +0 -1
- package/dist/queueEvents/index.d.ts +0 -8
- package/dist/queueEvents/index.d.ts.map +0 -1
- package/dist/queueEvents/index.js +0 -7
- package/dist/queueEvents/index.js.map +0 -1
- package/dist/queueEvents/queueEvents.core.d.ts +0 -6
- package/dist/queueEvents/queueEvents.core.d.ts.map +0 -1
- package/dist/queueEvents/queueEvents.core.js +0 -12
- package/dist/queueEvents/queueEvents.core.js.map +0 -1
- package/dist/queueEvents/queueEvents.type.d.ts +0 -97
- package/dist/queueEvents/queueEvents.type.d.ts.map +0 -1
- package/dist/queueEvents/queueEvents.type.js +0 -2
- package/dist/queueEvents/queueEvents.type.js.map +0 -1
- package/dist/queueManager/index.d.ts.map +0 -1
- package/dist/queueManager/index.js.map +0 -1
- package/dist/queueManager/queueManager.core.d.ts.map +0 -1
- package/dist/queueManager/queueManager.core.js.map +0 -1
- package/dist/queueManager/queueManager.type.d.ts.map +0 -1
- package/dist/queueManager/queueManager.type.js.map +0 -1
- package/dist/queueRegistry/index.d.ts.map +0 -1
- package/dist/queueRegistry/index.js.map +0 -1
- package/dist/queueRegistry/queueRegistry.core.d.ts.map +0 -1
- package/dist/queueRegistry/queueRegistry.core.js.map +0 -1
- package/dist/queueRegistry/queueRegistry.type.d.ts.map +0 -1
- package/dist/queueRegistry/queueRegistry.type.js.map +0 -1
- package/dist/retryPolicy/index.d.ts.map +0 -1
- package/dist/retryPolicy/index.js.map +0 -1
- package/dist/retryPolicy/retryPolicy.core.d.ts.map +0 -1
- package/dist/retryPolicy/retryPolicy.core.js.map +0 -1
- package/dist/serializer/index.d.ts.map +0 -1
- package/dist/serializer/index.js.map +0 -1
- package/dist/serializer/serializer.core.d.ts.map +0 -1
- package/dist/serializer/serializer.core.js.map +0 -1
- package/dist/serializer/serializer.type.d.ts.map +0 -1
- package/dist/serializer/serializer.type.js.map +0 -1
- package/dist/worker/index.d.ts.map +0 -1
- package/dist/worker/index.js.map +0 -1
- package/dist/worker/worker.core.d.ts.map +0 -1
- package/dist/worker/worker.core.js.map +0 -1
- package/dist/worker/worker.type.d.ts.map +0 -1
- package/dist/worker/worker.type.js.map +0 -1
|
@@ -1,48 +1,138 @@
|
|
|
1
|
-
import { WorkerState } from "../jobTypes/jobTypes.type.js";
|
|
1
|
+
import { JobState as JobStateEnum, WorkerState, } from "../jobTypes/jobTypes.type.js";
|
|
2
2
|
import { WorkerLifecycleError } from "@zudojs/errors";
|
|
3
|
+
/** How long `stop()` waits for in-flight jobs before forcing a stop. */
|
|
4
|
+
const DEFAULT_DRAIN_TIMEOUT_MS = 30_000;
|
|
3
5
|
/**
|
|
4
6
|
* Creates a new Worker.
|
|
7
|
+
*
|
|
8
|
+
* The worker claims each job before running it, so a job is never picked
|
|
9
|
+
* up twice — by this worker on its next poll, or by another worker on the
|
|
10
|
+
* same queue.
|
|
5
11
|
*/
|
|
6
12
|
export function createWorker(id, queue, options) {
|
|
7
13
|
let state = WorkerState.CREATED;
|
|
8
|
-
|
|
9
|
-
const concurrency = options?.concurrency ?? 1;
|
|
14
|
+
const stats = { processed: 0, succeeded: 0, failed: 0 };
|
|
15
|
+
const concurrency = Math.max(1, options?.concurrency ?? 1);
|
|
10
16
|
const pollInterval = options?.pollInterval ?? 100;
|
|
17
|
+
const drainTimeout = options?.drainTimeout ?? DEFAULT_DRAIN_TIMEOUT_MS;
|
|
11
18
|
let pollTimer = null;
|
|
12
19
|
let activeJobs = 0;
|
|
20
|
+
let polling = false;
|
|
13
21
|
let abortController = null;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const onError = options?.onError ??
|
|
23
|
+
((error) => {
|
|
24
|
+
queueMicrotask(() => {
|
|
25
|
+
console.error(`[@zudojs/queue] Worker "${id}" poll failed.`, error);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Arms the next poll. At most one timer is ever armed: a delayed poll
|
|
30
|
+
* already pending is left alone, while an immediate poll (capacity just
|
|
31
|
+
* freed up, or a job was just dispatched) supersedes it.
|
|
32
|
+
*/
|
|
33
|
+
const scheduleNextPoll = (delay) => {
|
|
34
|
+
if (state !== WorkerState.RUNNING) {
|
|
25
35
|
return;
|
|
26
36
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
if (pollTimer !== null) {
|
|
38
|
+
if (delay > 0)
|
|
39
|
+
return;
|
|
40
|
+
clearTimeout(pollTimer);
|
|
31
41
|
}
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
pollTimer = setTimeout(runPoll, delay);
|
|
43
|
+
pollTimer.unref?.();
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Wraps `poll` so a rejection can never escape as an unhandled promise
|
|
47
|
+
* rejection — which, under a runtime configured to treat those as
|
|
48
|
+
* fatal, would take down the whole application.
|
|
49
|
+
*/
|
|
50
|
+
const runPoll = () => {
|
|
51
|
+
pollTimer = null;
|
|
52
|
+
void poll().catch((error) => {
|
|
53
|
+
onError(error);
|
|
54
|
+
scheduleNextPoll(pollInterval);
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Runs one claimed job to completion and frees its concurrency slot.
|
|
59
|
+
*
|
|
60
|
+
* Deliberately not awaited by `poll`: awaiting it there serialised the
|
|
61
|
+
* worker, so `concurrency` was reported by `getStats()` and honoured by
|
|
62
|
+
* nothing.
|
|
63
|
+
*/
|
|
64
|
+
const runClaimedJob = async (job) => {
|
|
34
65
|
try {
|
|
35
|
-
|
|
36
|
-
|
|
66
|
+
// Dispatch through the queue rather than invoking the processor
|
|
67
|
+
// directly. The queue owns job state, retry, dead-lettering and
|
|
68
|
+
// middleware; calling the processor here left every job the worker
|
|
69
|
+
// ran stuck in `active` forever.
|
|
70
|
+
await queue.runJob(job, {
|
|
71
|
+
...(options?.middleware ? { middleware: options.middleware } : {}),
|
|
72
|
+
...(abortController ? { signal: abortController.signal } : {}),
|
|
73
|
+
...(options?.timeoutMs !== undefined
|
|
74
|
+
? { timeoutMs: options.timeoutMs }
|
|
75
|
+
: {}),
|
|
37
76
|
});
|
|
38
|
-
|
|
77
|
+
const settled = await queue.getJob(job.id);
|
|
78
|
+
if (settled?.state === JobStateEnum.COMPLETED) {
|
|
79
|
+
stats.succeeded++;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
stats.failed++;
|
|
83
|
+
}
|
|
39
84
|
}
|
|
40
|
-
catch {
|
|
85
|
+
catch (error) {
|
|
41
86
|
stats.failed++;
|
|
87
|
+
onError(error);
|
|
42
88
|
}
|
|
43
89
|
finally {
|
|
44
90
|
activeJobs--;
|
|
45
|
-
|
|
91
|
+
// A slot just opened: poll again immediately, yielding to the event
|
|
92
|
+
// loop first so a saturated queue cannot starve timers.
|
|
93
|
+
scheduleNextPoll(0);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const poll = async () => {
|
|
97
|
+
if (polling ||
|
|
98
|
+
state !== WorkerState.RUNNING ||
|
|
99
|
+
abortController?.signal.aborted) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
polling = true;
|
|
103
|
+
try {
|
|
104
|
+
if (activeJobs >= concurrency) {
|
|
105
|
+
scheduleNextPoll(pollInterval);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const job = await queue.claimNextJob();
|
|
109
|
+
if (!job) {
|
|
110
|
+
scheduleNextPoll(pollInterval);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const proc = queue.getProcessor(job.name);
|
|
114
|
+
if (!proc) {
|
|
115
|
+
// Claimed but unrunnable: release it rather than stranding it in
|
|
116
|
+
// `active` where nothing would ever pick it up again.
|
|
117
|
+
await queue.releaseJob(job.id);
|
|
118
|
+
scheduleNextPoll(pollInterval);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
activeJobs++;
|
|
122
|
+
stats.processed++;
|
|
123
|
+
void runClaimedJob(job);
|
|
124
|
+
// Capacity may remain: look for more work now, not after this job
|
|
125
|
+
// settles.
|
|
126
|
+
scheduleNextPoll(0);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
polling = false;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const clearPollTimer = () => {
|
|
133
|
+
if (pollTimer) {
|
|
134
|
+
clearTimeout(pollTimer);
|
|
135
|
+
pollTimer = null;
|
|
46
136
|
}
|
|
47
137
|
};
|
|
48
138
|
return {
|
|
@@ -60,34 +150,46 @@ export function createWorker(id, queue, options) {
|
|
|
60
150
|
abortController = new AbortController();
|
|
61
151
|
try {
|
|
62
152
|
state = WorkerState.RUNNING;
|
|
63
|
-
|
|
153
|
+
scheduleNextPoll(0);
|
|
64
154
|
}
|
|
65
155
|
catch (error) {
|
|
66
156
|
state = WorkerState.FAILED;
|
|
67
157
|
throw error;
|
|
68
158
|
}
|
|
69
159
|
},
|
|
160
|
+
/**
|
|
161
|
+
* Stops accepting new jobs and waits for in-flight ones to finish.
|
|
162
|
+
*
|
|
163
|
+
* The wait is bounded: past `drainTimeout` the worker force-stops
|
|
164
|
+
* rather than hanging shutdown on a job that never settles.
|
|
165
|
+
*/
|
|
70
166
|
async stop() {
|
|
71
|
-
if (state !== WorkerState.RUNNING) {
|
|
167
|
+
if (state !== WorkerState.RUNNING && state !== WorkerState.STARTING) {
|
|
168
|
+
// Still clear any timer armed before the state moved on.
|
|
169
|
+
clearPollTimer();
|
|
72
170
|
return;
|
|
73
171
|
}
|
|
74
172
|
state = WorkerState.DRAINING;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
173
|
+
clearPollTimer();
|
|
174
|
+
// Graceful means graceful: in-flight jobs get `drainTimeout` to
|
|
175
|
+
// finish on their own. Aborting them up front — as this once did —
|
|
176
|
+
// made `stop()` indistinguishable from `forceStop()` for any
|
|
177
|
+
// processor that honours its signal, and turned every routine
|
|
178
|
+
// shutdown into a batch of failed jobs.
|
|
179
|
+
const deadline = Date.now() + Math.max(0, drainTimeout);
|
|
180
|
+
while (activeJobs > 0 && Date.now() < deadline) {
|
|
181
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
78
182
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
183
|
+
if (activeJobs > 0) {
|
|
184
|
+
onError(new WorkerLifecycleError(`Worker "${id}" still had ${activeJobs} job(s) in flight after ${drainTimeout}ms; forcing stop.`, { workerId: id }));
|
|
185
|
+
abortController?.abort();
|
|
82
186
|
}
|
|
187
|
+
clearPollTimer();
|
|
83
188
|
state = WorkerState.STOPPED;
|
|
84
189
|
},
|
|
85
190
|
async forceStop() {
|
|
86
191
|
abortController?.abort();
|
|
87
|
-
|
|
88
|
-
clearTimeout(pollTimer);
|
|
89
|
-
pollTimer = null;
|
|
90
|
-
}
|
|
192
|
+
clearPollTimer();
|
|
91
193
|
state = WorkerState.STOPPED;
|
|
92
194
|
},
|
|
93
195
|
isRunning() {
|
|
@@ -9,12 +9,26 @@ export interface WorkerOptions {
|
|
|
9
9
|
readonly concurrency?: number;
|
|
10
10
|
/** Poll interval in milliseconds. */
|
|
11
11
|
readonly pollInterval?: number;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Default job timeout in milliseconds, applied to jobs that do not
|
|
14
|
+
* carry their own. Stall detection is a queue-level concern; configure
|
|
15
|
+
* it with `QueueOptions.stalledAfter` and `maxStalledCount`.
|
|
16
|
+
*/
|
|
15
17
|
readonly timeoutMs?: number;
|
|
16
18
|
/** Middleware for job processing. */
|
|
17
19
|
readonly middleware?: QueueMiddleware[];
|
|
20
|
+
/**
|
|
21
|
+
* How long `stop()` waits for in-flight jobs before forcing a stop, in
|
|
22
|
+
* milliseconds. Defaults to 30000. Without a bound, one stuck job
|
|
23
|
+
* hangs shutdown forever.
|
|
24
|
+
*/
|
|
25
|
+
readonly drainTimeout?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Invoked for errors raised outside a job — a failing poll, a job that
|
|
28
|
+
* threw, or a drain that timed out. Defaults to reporting on the
|
|
29
|
+
* console. Poll errors are never left as unhandled rejections.
|
|
30
|
+
*/
|
|
31
|
+
readonly onError?: (error: unknown) => void;
|
|
18
32
|
}
|
|
19
33
|
/**
|
|
20
34
|
* Worker lifecycle states.
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/queue",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Background job and asynchronous task infrastructure with in-memory and adapter-based queue implementations.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Oluwayemi Oyinlola",
|
|
8
|
+
"url": "https://github.com/oyinlola-tech"
|
|
9
|
+
},
|
|
6
10
|
"type": "module",
|
|
7
11
|
"main": "./dist/index.js",
|
|
8
12
|
"module": "./dist/index.js",
|
|
@@ -15,19 +19,15 @@
|
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
21
|
"files": [
|
|
18
|
-
"dist"
|
|
22
|
+
"dist",
|
|
23
|
+
"!dist/**/*.map",
|
|
24
|
+
"!dist/**/*.tsbuildinfo",
|
|
25
|
+
"!dist/.tsbuildinfo"
|
|
19
26
|
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
23
|
-
"clean": "rm -rf dist",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:watch": "vitest"
|
|
26
|
-
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@zudojs/errors": "0.1
|
|
29
|
-
"@zudojs/constants": "0.1
|
|
30
|
-
"@zudojs/serialization": "0.1
|
|
28
|
+
"@zudojs/errors": "1.0.1",
|
|
29
|
+
"@zudojs/constants": "1.0.1",
|
|
30
|
+
"@zudojs/serialization": "1.0.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "7.0.2",
|
|
@@ -47,8 +47,19 @@
|
|
|
47
47
|
"worker"
|
|
48
48
|
],
|
|
49
49
|
"homepage": "https://github.com/oyinlola-tech/zudo#readme",
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/oyinlola-tech/zudo/issues"
|
|
52
|
+
},
|
|
50
53
|
"repository": {
|
|
51
54
|
"type": "git",
|
|
52
|
-
"url": "https://github.com/oyinlola-tech/zudo"
|
|
55
|
+
"url": "https://github.com/oyinlola-tech/zudo",
|
|
56
|
+
"directory": "packages/queue"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -p tsconfig.json",
|
|
60
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
61
|
+
"clean": "rm -rf dist",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest"
|
|
53
64
|
}
|
|
54
|
-
}
|
|
65
|
+
}
|