adaptive-concurrency 0.5.0 → 0.6.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/dist/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.d.ts +8 -8
- package/dist/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.d.ts.map +1 -1
- package/dist/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.js +7 -5
- package/dist/limiter/factories/makeBlockingLimiter.js +1 -1
- package/dist/limiter/factories/makeLifoBlockingLimiter.js +1 -1
- package/dist/limiter/factories/makePartitionedBlockingLimiter.js +1 -1
- package/dist/limiter/factories/makePartitionedLifoBlockingLimiter.js +1 -1
- package/dist/utils/LinkedWaiterQueue.d.ts +6 -4
- package/dist/utils/LinkedWaiterQueue.d.ts.map +1 -1
- package/dist/utils/LinkedWaiterQueue.js +83 -35
- package/package.json +6 -7
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { LimitAllotment } from "../../LimitAllotment.js";
|
|
2
2
|
import type { AcquireResult, AllotmentUnavailableStrategy } from "../../Limiter.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { EnqueueOptions } from "../../utils/LinkedWaiterQueue.js";
|
|
4
4
|
export type Waiter<ContextT> = {
|
|
5
5
|
context: ContextT;
|
|
6
6
|
retry: (context: ContextT) => AcquireResult;
|
|
7
7
|
resolve: (allotment: LimitAllotment | undefined) => void;
|
|
8
8
|
};
|
|
9
9
|
export declare const MAX_TIMEOUT: number;
|
|
10
|
-
export type BlockingBacklogRejectionOptions<ContextT, Handle> = {
|
|
10
|
+
export type BlockingBacklogRejectionOptions<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> = {
|
|
11
11
|
backlogSize: number;
|
|
12
12
|
backlogTimeout: number | ((context: ContextT) => number);
|
|
13
|
-
queue: WaiterQueue<ContextT, Handle>;
|
|
14
|
-
|
|
13
|
+
queue: WaiterQueue<ContextT, Handle, EnqueueOptionsT>;
|
|
14
|
+
enqueueOptions: EnqueueOptionsT | ((context: ContextT) => EnqueueOptionsT);
|
|
15
15
|
};
|
|
16
|
-
export type WaiterQueue<ContextT, Handle> = {
|
|
17
|
-
enqueue: (waiter: Waiter<ContextT>, options:
|
|
16
|
+
export type WaiterQueue<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> = {
|
|
17
|
+
enqueue: (waiter: Waiter<ContextT>, options: EnqueueOptionsT) => {
|
|
18
18
|
value: Waiter<ContextT>;
|
|
19
19
|
handle: Handle;
|
|
20
20
|
};
|
|
@@ -25,14 +25,14 @@ export type WaiterQueue<ContextT, Handle> = {
|
|
|
25
25
|
removeByHandle: (handle: Handle) => boolean;
|
|
26
26
|
size: () => number;
|
|
27
27
|
};
|
|
28
|
-
export declare class BlockingBacklogRejection<ContextT, Handle> implements AllotmentUnavailableStrategy<ContextT> {
|
|
28
|
+
export declare class BlockingBacklogRejection<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> implements AllotmentUnavailableStrategy<ContextT> {
|
|
29
29
|
private readonly backlogSize;
|
|
30
30
|
private readonly getBacklogTimeout;
|
|
31
31
|
private readonly getEnqueueOptions;
|
|
32
32
|
private readonly queue;
|
|
33
33
|
private drainInProgress;
|
|
34
34
|
private releaseDuringDrain;
|
|
35
|
-
constructor(options: BlockingBacklogRejectionOptions<ContextT, Handle>);
|
|
35
|
+
constructor(options: BlockingBacklogRejectionOptions<ContextT, Handle, EnqueueOptionsT>);
|
|
36
36
|
onAllotmentUnavailable(context: ContextT, retry: (context: ContextT) => AcquireResult, signal?: AbortSignal): Promise<LimitAllotment | undefined>;
|
|
37
37
|
onAllotmentReleased(): Promise<void>;
|
|
38
38
|
onLimitChanged(oldLimit: number, newLimit: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockingBacklogRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"BlockingBacklogRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,MAAM,MAAM,MAAM,CAAC,QAAQ,IAAI;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC5C,OAAO,EAAE,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,eAAO,MAAM,WAAW,QAAiB,CAAC;AAE1C,MAAM,MAAM,+BAA+B,CACzC,QAAQ,EACR,MAAM,EACN,eAAe,GAAG,cAAc,IAC9B;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzD,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACtD,cAAc,EAAE,eAAe,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,eAAe,CAAC,CAAC;CAC5E,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,GAAG,cAAc,IAAI;IAC5E,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,OAAO,EAAE,eAAe,KACrB;QAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,wBAAwB,CACnC,QAAQ,EACR,MAAM,EACN,eAAe,GAAG,cAAc,CAChC,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyC;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiD;IACvE,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAS;gBAGjC,OAAO,EAAE,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC;IAiC7E,sBAAsB,CACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,EAC3C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAYhC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6C1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQxD,OAAO,CAAC,aAAa;IAoCrB,OAAO,CAAC,yBAAyB;CAUlC"}
|
|
@@ -14,7 +14,7 @@ export class BlockingBacklogRejection {
|
|
|
14
14
|
this.backlogSize = backlogSize;
|
|
15
15
|
this.queue = options.queue;
|
|
16
16
|
const backlogTimeout = options.backlogTimeout;
|
|
17
|
-
const
|
|
17
|
+
const enqueueOptions = options.enqueueOptions;
|
|
18
18
|
this.getBacklogTimeout = (() => {
|
|
19
19
|
if (typeof backlogTimeout === "number") {
|
|
20
20
|
this.assertTimeoutWithinBounds(backlogTimeout);
|
|
@@ -26,10 +26,12 @@ export class BlockingBacklogRejection {
|
|
|
26
26
|
return contextTimeout;
|
|
27
27
|
};
|
|
28
28
|
})();
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
if (typeof enqueueOptions === "function") {
|
|
30
|
+
this.getEnqueueOptions = enqueueOptions;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.getEnqueueOptions = () => enqueueOptions;
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
36
|
onAllotmentUnavailable(context, retry, signal) {
|
|
35
37
|
if (signal?.aborted) {
|
|
@@ -7,7 +7,7 @@ export function makeBlockingLimiter(options = {}) {
|
|
|
7
7
|
allotmentUnavailableStrategy: new BlockingBacklogRejection({
|
|
8
8
|
backlogSize: options.backlogSize ?? Number.POSITIVE_INFINITY,
|
|
9
9
|
backlogTimeout: options.backlogTimeout ?? MAX_TIMEOUT,
|
|
10
|
-
|
|
10
|
+
enqueueOptions: { direction: "back" },
|
|
11
11
|
queue: new LinkedWaiterQueue(),
|
|
12
12
|
}),
|
|
13
13
|
});
|
|
@@ -7,7 +7,7 @@ export function makeLifoBlockingLimiter(options = {}) {
|
|
|
7
7
|
allotmentUnavailableStrategy: new BlockingBacklogRejection({
|
|
8
8
|
backlogSize: options.backlogSize ?? 100,
|
|
9
9
|
backlogTimeout: options.backlogTimeout ?? 1_000,
|
|
10
|
-
|
|
10
|
+
enqueueOptions: { direction: "front" },
|
|
11
11
|
queue: new LinkedWaiterQueue(),
|
|
12
12
|
}),
|
|
13
13
|
});
|
|
@@ -32,7 +32,7 @@ export function makePartitionedBlockingLimiter(options) {
|
|
|
32
32
|
blockingStrategy: new BlockingBacklogRejection({
|
|
33
33
|
backlogSize: options.backlogSize ?? Number.POSITIVE_INFINITY,
|
|
34
34
|
backlogTimeout: options.backlogTimeout ?? MAX_TIMEOUT,
|
|
35
|
-
|
|
35
|
+
enqueueOptions: { direction: "back" },
|
|
36
36
|
queue: new LinkedWaiterQueue(),
|
|
37
37
|
}),
|
|
38
38
|
}),
|
|
@@ -32,7 +32,7 @@ export function makePartitionedLifoBlockingLimiter(options) {
|
|
|
32
32
|
blockingStrategy: new BlockingBacklogRejection({
|
|
33
33
|
backlogSize: options.backlogSize ?? 100,
|
|
34
34
|
backlogTimeout: options.backlogTimeout ?? 1_000,
|
|
35
|
-
|
|
35
|
+
enqueueOptions: { direction: "front" },
|
|
36
36
|
queue: new LinkedWaiterQueue(),
|
|
37
37
|
}),
|
|
38
38
|
}),
|
|
@@ -3,11 +3,12 @@ declare class ItemHandle {
|
|
|
3
3
|
export type EnqueueDirection = "front" | "back";
|
|
4
4
|
export type EnqueueOptions = {
|
|
5
5
|
direction: EnqueueDirection;
|
|
6
|
+
priority?: number | undefined;
|
|
6
7
|
};
|
|
7
8
|
export declare class LinkedWaiterQueue<T extends object> {
|
|
8
|
-
private
|
|
9
|
-
private tail;
|
|
9
|
+
private readonly buckets;
|
|
10
10
|
private readonly nodes;
|
|
11
|
+
private maxPriority;
|
|
11
12
|
private length;
|
|
12
13
|
enqueue(value: T, options: EnqueueOptions): {
|
|
13
14
|
value: T;
|
|
@@ -19,8 +20,9 @@ export declare class LinkedWaiterQueue<T extends object> {
|
|
|
19
20
|
} | undefined;
|
|
20
21
|
removeByHandle(handle: ItemHandle): boolean;
|
|
21
22
|
size(): number;
|
|
22
|
-
private
|
|
23
|
-
private
|
|
23
|
+
private getOrCreateBucket;
|
|
24
|
+
private insertInBucket;
|
|
25
|
+
private unlinkFromBucket;
|
|
24
26
|
}
|
|
25
27
|
export {};
|
|
26
28
|
//# sourceMappingURL=LinkedWaiterQueue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LinkedWaiterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/LinkedWaiterQueue.ts"],"names":[],"mappings":"AAAA,cAAM,UAAU;CAAG;AAEnB,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAChD,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"LinkedWaiterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/LinkedWaiterQueue.ts"],"names":[],"mappings":"AAAA,cAAM,UAAU;CAAG;AAEnB,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAChD,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AAkBF,qBAAa,iBAAiB,CAAC,CAAC,SAAS,MAAM;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAC9D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CACL,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,cAAc,GACtB;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE;IA0BnC,QAAQ,IAAI;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,GAAG,SAAS;IAcxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAa3C,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,gBAAgB;CA+BzB"}
|
|
@@ -1,35 +1,44 @@
|
|
|
1
1
|
class ItemHandle {
|
|
2
2
|
}
|
|
3
3
|
export class LinkedWaiterQueue {
|
|
4
|
-
|
|
5
|
-
tail;
|
|
4
|
+
buckets = new Map();
|
|
6
5
|
nodes = new Map();
|
|
6
|
+
maxPriority;
|
|
7
7
|
length = 0;
|
|
8
8
|
enqueue(value, options) {
|
|
9
9
|
const handle = new ItemHandle();
|
|
10
|
+
const priority = options.priority ?? 0;
|
|
11
|
+
if (!Number.isFinite(priority)) {
|
|
12
|
+
throw new RangeError("priority must be a finite number");
|
|
13
|
+
}
|
|
14
|
+
const bucket = this.getOrCreateBucket(priority);
|
|
10
15
|
const node = {
|
|
11
16
|
handle,
|
|
12
17
|
value: value,
|
|
18
|
+
priority,
|
|
13
19
|
prev: undefined,
|
|
14
20
|
next: undefined,
|
|
21
|
+
bucket,
|
|
15
22
|
};
|
|
16
23
|
this.nodes.set(handle, node);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
else {
|
|
21
|
-
this.pushBack(node);
|
|
24
|
+
this.insertInBucket(node, options.direction);
|
|
25
|
+
if (this.maxPriority === undefined || priority > this.maxPriority) {
|
|
26
|
+
this.maxPriority = priority;
|
|
22
27
|
}
|
|
23
28
|
this.length += 1;
|
|
24
29
|
return { value, handle };
|
|
25
30
|
}
|
|
26
31
|
peekHead() {
|
|
27
|
-
if (
|
|
32
|
+
if (this.maxPriority === undefined) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const bucket = this.buckets.get(this.maxPriority);
|
|
36
|
+
if (!bucket || !bucket.head) {
|
|
28
37
|
return undefined;
|
|
29
38
|
}
|
|
30
39
|
return {
|
|
31
|
-
value:
|
|
32
|
-
handle:
|
|
40
|
+
value: bucket.head.value,
|
|
41
|
+
handle: bucket.head.handle,
|
|
33
42
|
};
|
|
34
43
|
}
|
|
35
44
|
removeByHandle(handle) {
|
|
@@ -37,44 +46,83 @@ export class LinkedWaiterQueue {
|
|
|
37
46
|
if (!node)
|
|
38
47
|
return false;
|
|
39
48
|
this.nodes.delete(handle);
|
|
49
|
+
this.unlinkFromBucket(node);
|
|
50
|
+
node.prev = undefined;
|
|
51
|
+
node.next = undefined;
|
|
52
|
+
this.length -= 1;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
size() {
|
|
56
|
+
return this.length;
|
|
57
|
+
}
|
|
58
|
+
getOrCreateBucket(priority) {
|
|
59
|
+
const existing = this.buckets.get(priority);
|
|
60
|
+
if (existing) {
|
|
61
|
+
return existing;
|
|
62
|
+
}
|
|
63
|
+
const created = {
|
|
64
|
+
priority,
|
|
65
|
+
head: undefined,
|
|
66
|
+
tail: undefined,
|
|
67
|
+
size: 0,
|
|
68
|
+
};
|
|
69
|
+
this.buckets.set(priority, created);
|
|
70
|
+
return created;
|
|
71
|
+
}
|
|
72
|
+
insertInBucket(node, direction) {
|
|
73
|
+
const bucket = node.bucket;
|
|
74
|
+
if (direction === "front") {
|
|
75
|
+
if (!bucket.head) {
|
|
76
|
+
bucket.head = node;
|
|
77
|
+
bucket.tail = node;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
node.next = bucket.head;
|
|
81
|
+
bucket.head.prev = node;
|
|
82
|
+
bucket.head = node;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!bucket.tail) {
|
|
87
|
+
bucket.head = node;
|
|
88
|
+
bucket.tail = node;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
node.prev = bucket.tail;
|
|
92
|
+
bucket.tail.next = node;
|
|
93
|
+
bucket.tail = node;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
bucket.size += 1;
|
|
97
|
+
}
|
|
98
|
+
unlinkFromBucket(node) {
|
|
99
|
+
const bucket = node.bucket;
|
|
40
100
|
if (node.prev) {
|
|
41
101
|
node.prev.next = node.next;
|
|
42
102
|
}
|
|
43
103
|
else {
|
|
44
|
-
|
|
104
|
+
bucket.head = node.next;
|
|
45
105
|
}
|
|
46
106
|
if (node.next) {
|
|
47
107
|
node.next.prev = node.prev;
|
|
48
108
|
}
|
|
49
109
|
else {
|
|
50
|
-
|
|
110
|
+
bucket.tail = node.prev;
|
|
51
111
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.length -= 1;
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
size() {
|
|
58
|
-
return this.length;
|
|
59
|
-
}
|
|
60
|
-
pushFront(node) {
|
|
61
|
-
if (!this.head) {
|
|
62
|
-
this.head = node;
|
|
63
|
-
this.tail = node;
|
|
112
|
+
bucket.size -= 1;
|
|
113
|
+
if (bucket.size > 0) {
|
|
64
114
|
return;
|
|
65
115
|
}
|
|
66
|
-
|
|
67
|
-
this.
|
|
68
|
-
this.head = node;
|
|
69
|
-
}
|
|
70
|
-
pushBack(node) {
|
|
71
|
-
if (!this.tail) {
|
|
72
|
-
this.head = node;
|
|
73
|
-
this.tail = node;
|
|
116
|
+
this.buckets.delete(bucket.priority);
|
|
117
|
+
if (this.maxPriority !== bucket.priority) {
|
|
74
118
|
return;
|
|
75
119
|
}
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
|
|
120
|
+
let newMax;
|
|
121
|
+
for (const priority of this.buckets.keys()) {
|
|
122
|
+
if (newMax === undefined || priority > newMax) {
|
|
123
|
+
newMax = priority;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
this.maxPriority = newMax;
|
|
79
127
|
}
|
|
80
128
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dynamic rate limiting"
|
|
10
10
|
],
|
|
11
11
|
"author": "Ethan Resnick <ethan.resnick@gmail.com>",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.6.0",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
@@ -20,15 +20,14 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
|
-
"scripts": {
|
|
24
|
-
"build": "tsc",
|
|
25
|
-
"test": "node --import tsx --test \"src/**/*.test.ts\"",
|
|
26
|
-
"prepublishOnly": "pnpm build"
|
|
27
|
-
},
|
|
28
23
|
"devDependencies": {
|
|
29
24
|
"tsx": "^4.19.0",
|
|
30
25
|
"type-fest": "^5.5.0",
|
|
31
26
|
"type-party": "^0.7.3",
|
|
32
27
|
"typescript": "^6.0.2"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"test": "node --import tsx --test \"src/**/*.test.ts\""
|
|
33
32
|
}
|
|
34
|
-
}
|
|
33
|
+
}
|