clutchit 0.0.3 → 0.0.6
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/README.md +530 -0
- package/dist/circuit/{circuit-breaker.d.ts → circuit.breaker.d.ts} +14 -10
- package/dist/circuit/{circuit-breaker.js → circuit.breaker.js} +7 -12
- package/dist/circuit/index.d.ts +7 -4
- package/dist/circuit/index.js +3 -2
- package/dist/concurrency/bulkhead.d.ts +10 -9
- package/dist/concurrency/bulkhead.js +4 -8
- package/dist/concurrency/index.d.ts +12 -5
- package/dist/concurrency/index.js +2 -0
- package/dist/concurrency/rate-limiter.d.ts +13 -9
- package/dist/concurrency/rate-limiter.js +4 -10
- package/dist/queue/base.queue.js +1 -1
- package/dist/queue/bounded.queue.d.ts +2 -2
- package/dist/queue/bounded.queue.js +2 -2
- package/dist/queue/faults.d.ts +22 -18
- package/dist/queue/faults.js +6 -15
- package/dist/queue/index.d.ts +12 -8
- package/dist/queue/index.js +7 -6
- package/dist/retry/index.d.ts +5 -3
- package/dist/retry/index.js +2 -2
- package/dist/schedule/index.d.ts +19 -13
- package/dist/schedule/index.js +11 -10
- package/dist/schedule/runner.d.ts +10 -9
- package/dist/schedule/runner.js +5 -9
- package/dist/schedule/schedule.d.ts +4 -0
- package/dist/schedule/schedule.js +12 -0
- package/dist/timeout/index.d.ts +1 -10
- package/dist/timeout/index.js +2 -2
- package/dist/timeout/timeout.d.ts +13 -9
- package/dist/timeout/timeout.js +4 -10
- package/dist/unthrow/fault.d.ts +9 -24
- package/dist/unthrow/fault.js +18 -13
- package/dist/unthrow/index.d.ts +17 -16
- package/dist/unthrow/index.js +12 -19
- package/package.json +4 -1
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { Semaphore as _Semaphore } from './semaphore.js';
|
|
2
|
+
import type { SemaphoreOptions as _SemaphoreOptions } from './semaphore.js';
|
|
2
3
|
import { RateLimiter as _RateLimiter } from './rate-limiter.js';
|
|
4
|
+
import type { RateLimiterOptions as _RateLimiterOptions } from './rate-limiter.js';
|
|
3
5
|
import { Bulkhead as _Bulkhead } from './bulkhead.js';
|
|
6
|
+
import type { BulkheadOptions as _BulkheadOptions } from './bulkhead.js';
|
|
4
7
|
import { Ref as _Ref } from './ref.js';
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export type { RateLimitFault } from './rate-limiter.js';
|
|
8
|
-
export type { BulkheadOptions } from './bulkhead.js';
|
|
9
|
-
export type { BulkheadRejectedFault } from './bulkhead.js';
|
|
8
|
+
export { RateLimitFault } from './rate-limiter.js';
|
|
9
|
+
export { BulkheadRejectedFault } from './bulkhead.js';
|
|
10
10
|
export declare namespace Concurrency {
|
|
11
11
|
const Semaphore: typeof _Semaphore;
|
|
12
|
+
type Semaphore = _Semaphore;
|
|
13
|
+
type SemaphoreOptions = _SemaphoreOptions;
|
|
12
14
|
const RateLimiter: typeof _RateLimiter;
|
|
15
|
+
type RateLimiter = _RateLimiter;
|
|
16
|
+
type RateLimiterOptions = _RateLimiterOptions;
|
|
13
17
|
const Bulkhead: typeof _Bulkhead;
|
|
18
|
+
type Bulkhead = _Bulkhead;
|
|
19
|
+
type BulkheadOptions = _BulkheadOptions;
|
|
14
20
|
const Ref: typeof _Ref;
|
|
21
|
+
type Ref<T> = _Ref<T>;
|
|
15
22
|
}
|
|
16
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,6 +2,8 @@ import { Semaphore as _Semaphore } from './semaphore.js';
|
|
|
2
2
|
import { RateLimiter as _RateLimiter } from './rate-limiter.js';
|
|
3
3
|
import { Bulkhead as _Bulkhead } from './bulkhead.js';
|
|
4
4
|
import { Ref as _Ref } from './ref.js';
|
|
5
|
+
export { RateLimitFault } from './rate-limiter.js';
|
|
6
|
+
export { BulkheadRejectedFault } from './bulkhead.js';
|
|
5
7
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
6
8
|
export var Concurrency;
|
|
7
9
|
(function (Concurrency) {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { ResultAsync } from '../unthrow/index.js';
|
|
2
|
-
|
|
3
|
-
code: "RATE_LIMITED";
|
|
4
|
-
_category: "infrastructure";
|
|
5
|
-
_transient: true;
|
|
6
|
-
message: string;
|
|
7
|
-
} & Omit<{
|
|
8
|
-
message: string;
|
|
2
|
+
declare const RateLimitFault_base: abstract new (fields: {
|
|
9
3
|
retryAfter: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
4
|
+
}) => Readonly<{
|
|
5
|
+
retryAfter: number;
|
|
6
|
+
}> & {
|
|
7
|
+
readonly code: "RATE_LIMITED";
|
|
8
|
+
readonly _category: "infrastructure";
|
|
9
|
+
readonly _transient: true;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
};
|
|
12
|
+
export declare class RateLimitFault extends RateLimitFault_base {
|
|
13
|
+
readonly message: string;
|
|
14
|
+
}
|
|
12
15
|
export interface RateLimiterOptions {
|
|
13
16
|
limit: number;
|
|
14
17
|
window: number;
|
|
@@ -22,4 +25,5 @@ export declare class RateLimiter {
|
|
|
22
25
|
get remaining(): number;
|
|
23
26
|
private cleanup;
|
|
24
27
|
}
|
|
28
|
+
export {};
|
|
25
29
|
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Fault, ResultAsync } from '../unthrow/index.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
transient: true,
|
|
6
|
-
create: (retryAfter) => ({
|
|
7
|
-
message: `Rate limit exceeded. Retry after ${retryAfter}ms`,
|
|
8
|
-
retryAfter,
|
|
9
|
-
}),
|
|
10
|
-
});
|
|
2
|
+
export class RateLimitFault extends Fault.Tagged('RATE_LIMITED', 'infrastructure', true)() {
|
|
3
|
+
message = `Rate limit exceeded. Retry after ${this.retryAfter}ms`;
|
|
4
|
+
}
|
|
11
5
|
export class RateLimiter {
|
|
12
6
|
_limit;
|
|
13
7
|
_window;
|
|
@@ -21,7 +15,7 @@ export class RateLimiter {
|
|
|
21
15
|
if (this._timestamps.length >= this._limit) {
|
|
22
16
|
const oldest = this._timestamps[0];
|
|
23
17
|
const retryAfter = Math.max(0, oldest + this._window - Date.now());
|
|
24
|
-
return ResultAsync.err(RateLimitFault(retryAfter));
|
|
18
|
+
return ResultAsync.err(new RateLimitFault({ retryAfter }));
|
|
25
19
|
}
|
|
26
20
|
this._timestamps.push(Date.now());
|
|
27
21
|
return fn();
|
package/dist/queue/base.queue.js
CHANGED
|
@@ -4,8 +4,8 @@ import { BaseQueue, type QueueOptions } from './base.queue.js';
|
|
|
4
4
|
export declare class BoundedQueue<T> extends BaseQueue<T> {
|
|
5
5
|
private readonly _putWaiters;
|
|
6
6
|
constructor(options: QueueOptions);
|
|
7
|
-
protected _tryTake(): Result<T,
|
|
8
|
-
offer(item: T): Result<void,
|
|
7
|
+
protected _tryTake(): Result<T, QueueEmptyFault>;
|
|
8
|
+
offer(item: T): Result<void, QueueFullFault>;
|
|
9
9
|
put(item: T, signal?: AbortSignal): ResultAsync<void, never>;
|
|
10
10
|
}
|
|
11
11
|
//# sourceMappingURL=bounded.queue.d.ts.map
|
|
@@ -23,7 +23,7 @@ export class BoundedQueue extends BaseQueue {
|
|
|
23
23
|
pw.resolve();
|
|
24
24
|
return Result.ok(pw.item);
|
|
25
25
|
}
|
|
26
|
-
return Result.err(QueueEmptyFault());
|
|
26
|
+
return Result.err(new QueueEmptyFault());
|
|
27
27
|
}
|
|
28
28
|
offer(item) {
|
|
29
29
|
// Give directly to a waiting consumer
|
|
@@ -33,7 +33,7 @@ export class BoundedQueue extends BaseQueue {
|
|
|
33
33
|
return Result.ok(undefined);
|
|
34
34
|
}
|
|
35
35
|
if (this._buffer.length >= this._capacity) {
|
|
36
|
-
return Result.err(QueueFullFault(this._capacity));
|
|
36
|
+
return Result.err(new QueueFullFault({ capacity: this._capacity }));
|
|
37
37
|
}
|
|
38
38
|
this._buffer.push(item);
|
|
39
39
|
return Result.ok(undefined);
|
package/dist/queue/faults.d.ts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
code: "QUEUE_FULL";
|
|
3
|
-
_category: "infrastructure";
|
|
4
|
-
_transient: false;
|
|
5
|
-
message: string;
|
|
6
|
-
} & Omit<{
|
|
7
|
-
message: string;
|
|
1
|
+
declare const QueueFullFault_base: abstract new (fields: {
|
|
8
2
|
capacity: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
code: "
|
|
13
|
-
_category: "infrastructure";
|
|
14
|
-
_transient: false;
|
|
15
|
-
message: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
}) => Readonly<{
|
|
4
|
+
capacity: number;
|
|
5
|
+
}> & {
|
|
6
|
+
readonly code: "QUEUE_FULL";
|
|
7
|
+
readonly _category: "infrastructure";
|
|
8
|
+
readonly _transient: false;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
};
|
|
11
|
+
export declare class QueueFullFault extends QueueFullFault_base {
|
|
12
|
+
readonly message: string;
|
|
13
|
+
}
|
|
14
|
+
declare const QueueEmptyFault_base: abstract new () => Readonly<Record<string, unknown>> & {
|
|
15
|
+
readonly code: "QUEUE_EMPTY";
|
|
16
|
+
readonly _category: "infrastructure";
|
|
17
|
+
readonly _transient: false;
|
|
18
|
+
readonly message: string;
|
|
19
|
+
};
|
|
20
|
+
export declare class QueueEmptyFault extends QueueEmptyFault_base {
|
|
21
|
+
readonly message = "Queue is empty";
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
20
24
|
//# sourceMappingURL=faults.d.ts.map
|
package/dist/queue/faults.js
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import { Fault } from '../unthrow/index.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}),
|
|
9
|
-
});
|
|
10
|
-
export const QueueEmptyFault = Fault.define({
|
|
11
|
-
code: 'QUEUE_EMPTY',
|
|
12
|
-
category: 'infrastructure',
|
|
13
|
-
create: () => ({
|
|
14
|
-
message: 'Queue is empty',
|
|
15
|
-
}),
|
|
16
|
-
});
|
|
2
|
+
export class QueueFullFault extends Fault.Tagged('QUEUE_FULL', 'infrastructure')() {
|
|
3
|
+
message = `Queue is full (capacity: ${this.capacity})`;
|
|
4
|
+
}
|
|
5
|
+
export class QueueEmptyFault extends Fault.Tagged('QUEUE_EMPTY', 'infrastructure')() {
|
|
6
|
+
message = 'Queue is empty';
|
|
7
|
+
}
|
|
17
8
|
//# sourceMappingURL=faults.js.map
|
package/dist/queue/index.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export
|
|
1
|
+
import type { QueueOptions } from './base.queue.js';
|
|
2
|
+
import { BoundedQueue } from './bounded.queue.js';
|
|
3
|
+
import { DroppingQueue } from './dropping.queue.js';
|
|
4
|
+
import { SlidingQueue } from './sliding.queue.js';
|
|
5
|
+
export { QueueFullFault, QueueEmptyFault } from './faults.js';
|
|
6
6
|
export declare namespace Queue {
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
7
|
+
type Options = QueueOptions;
|
|
8
|
+
const Bounded: typeof BoundedQueue;
|
|
9
|
+
type Bounded<T> = BoundedQueue<T>;
|
|
10
|
+
const Dropping: typeof DroppingQueue;
|
|
11
|
+
type Dropping<T> = DroppingQueue<T>;
|
|
12
|
+
const Sliding: typeof SlidingQueue;
|
|
13
|
+
type Sliding<T> = SlidingQueue<T>;
|
|
10
14
|
}
|
|
11
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/queue/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { BoundedQueue
|
|
2
|
-
import { DroppingQueue
|
|
3
|
-
import { SlidingQueue
|
|
1
|
+
import { BoundedQueue } from './bounded.queue.js';
|
|
2
|
+
import { DroppingQueue } from './dropping.queue.js';
|
|
3
|
+
import { SlidingQueue } from './sliding.queue.js';
|
|
4
|
+
export { QueueFullFault, QueueEmptyFault } from './faults.js';
|
|
4
5
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
5
6
|
export var Queue;
|
|
6
7
|
(function (Queue) {
|
|
7
|
-
Queue.Bounded =
|
|
8
|
-
Queue.Dropping =
|
|
9
|
-
Queue.Sliding =
|
|
8
|
+
Queue.Bounded = BoundedQueue;
|
|
9
|
+
Queue.Dropping = DroppingQueue;
|
|
10
|
+
Queue.Sliding = SlidingQueue;
|
|
10
11
|
})(Queue || (Queue = {}));
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
package/dist/retry/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { RetryPolicy
|
|
2
|
-
|
|
1
|
+
import { RetryPolicy } from './retry.js';
|
|
2
|
+
import type { RetryOptions } from './retry.js';
|
|
3
3
|
export declare namespace Retry {
|
|
4
|
-
|
|
4
|
+
type Options = RetryOptions;
|
|
5
|
+
const Policy: typeof RetryPolicy;
|
|
6
|
+
type Policy = RetryPolicy;
|
|
5
7
|
}
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/retry/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { RetryPolicy
|
|
1
|
+
import { RetryPolicy } from './retry.js';
|
|
2
2
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
3
3
|
export var Retry;
|
|
4
4
|
(function (Retry) {
|
|
5
|
-
Retry.Policy =
|
|
5
|
+
Retry.Policy = RetryPolicy;
|
|
6
6
|
})(Retry || (Retry = {}));
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/schedule/index.d.ts
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import { Schedule as
|
|
1
|
+
import { Schedule as _Schedule } from './schedule.js';
|
|
2
|
+
import type { ScheduleStep, ScheduleOperator } from './schedule.js';
|
|
2
3
|
import { recurs as _recurs, cappedDelay as _cappedDelay, jittered as _jittered, upTo as _upTo, andThen as _andThen, union as _union, intersect as _intersect, whileInput as _whileInput, whileOutput as _whileOutput, map as _map } from './operators.js';
|
|
3
4
|
import { repeat as _repeat } from './runner.js';
|
|
4
|
-
|
|
5
|
+
import type { RepeatOptions as _RepeatOptions } from './runner.js';
|
|
5
6
|
export { ScheduleInterruptedFault } from './runner.js';
|
|
6
|
-
export type
|
|
7
|
-
export type Schedule<In = unknown, Out = number> = ScheduleClass<In, Out>;
|
|
7
|
+
export type Schedule<In = unknown, Out = number> = _Schedule<In, Out>;
|
|
8
8
|
export declare namespace Schedule {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
9
|
+
type Step = ScheduleStep;
|
|
10
|
+
type Operator = ScheduleOperator;
|
|
11
|
+
const spaced: (ms: number) => _Schedule;
|
|
12
|
+
const exponential: (initialDelay: number, multiplier?: number) => _Schedule;
|
|
13
|
+
const linear: (initialDelay: number) => _Schedule;
|
|
14
|
+
const constant: (delay: number) => _Schedule;
|
|
15
|
+
const fixed: (interval: number) => _Schedule;
|
|
16
|
+
const windowed: (interval: number) => _Schedule;
|
|
17
|
+
const forever: _Schedule<unknown, number>;
|
|
18
|
+
const once: _Schedule<unknown, number>;
|
|
19
|
+
const fibonacci: (one: number) => _Schedule;
|
|
20
|
+
const cron: (expression: string, options?: {
|
|
21
|
+
timezone?: string;
|
|
22
|
+
}) => _Schedule;
|
|
18
23
|
const recurs: typeof _recurs;
|
|
19
24
|
const cappedDelay: typeof _cappedDelay;
|
|
20
25
|
const jittered: typeof _jittered;
|
|
@@ -26,5 +31,6 @@ export declare namespace Schedule {
|
|
|
26
31
|
const whileOutput: typeof _whileOutput;
|
|
27
32
|
const map: typeof _map;
|
|
28
33
|
const repeat: typeof _repeat;
|
|
34
|
+
type RepeatOptions = _RepeatOptions;
|
|
29
35
|
}
|
|
30
36
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/schedule/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { Schedule as
|
|
1
|
+
import { Schedule as _Schedule } from './schedule.js';
|
|
2
2
|
import { recurs as _recurs, cappedDelay as _cappedDelay, jittered as _jittered, upTo as _upTo, andThen as _andThen, union as _union, intersect as _intersect, whileInput as _whileInput, whileOutput as _whileOutput, map as _map, } from './operators.js';
|
|
3
3
|
import { repeat as _repeat } from './runner.js';
|
|
4
4
|
export { ScheduleInterruptedFault } from './runner.js';
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
6
6
|
export var Schedule;
|
|
7
7
|
(function (Schedule) {
|
|
8
|
-
Schedule.spaced =
|
|
9
|
-
Schedule.exponential =
|
|
10
|
-
Schedule.linear =
|
|
11
|
-
Schedule.constant =
|
|
12
|
-
Schedule.fixed =
|
|
13
|
-
Schedule.windowed =
|
|
14
|
-
Schedule.forever =
|
|
15
|
-
Schedule.once =
|
|
16
|
-
Schedule.fibonacci =
|
|
8
|
+
Schedule.spaced = _Schedule.spaced;
|
|
9
|
+
Schedule.exponential = _Schedule.exponential;
|
|
10
|
+
Schedule.linear = _Schedule.linear;
|
|
11
|
+
Schedule.constant = _Schedule.constant;
|
|
12
|
+
Schedule.fixed = _Schedule.fixed;
|
|
13
|
+
Schedule.windowed = _Schedule.windowed;
|
|
14
|
+
Schedule.forever = _Schedule.forever;
|
|
15
|
+
Schedule.once = _Schedule.once;
|
|
16
|
+
Schedule.fibonacci = _Schedule.fibonacci;
|
|
17
|
+
Schedule.cron = _Schedule.cron;
|
|
17
18
|
Schedule.recurs = _recurs;
|
|
18
19
|
Schedule.cappedDelay = _cappedDelay;
|
|
19
20
|
Schedule.jittered = _jittered;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { ResultAsync } from '../unthrow/index.js';
|
|
2
2
|
import type { Schedule } from './schedule.js';
|
|
3
|
-
|
|
4
|
-
code: "SCHEDULE_INTERRUPTED";
|
|
5
|
-
_category: "infrastructure";
|
|
6
|
-
_transient: false;
|
|
7
|
-
message: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
declare const ScheduleInterruptedFault_base: abstract new () => Readonly<Record<string, unknown>> & {
|
|
4
|
+
readonly code: "SCHEDULE_INTERRUPTED";
|
|
5
|
+
readonly _category: "infrastructure";
|
|
6
|
+
readonly _transient: false;
|
|
7
|
+
readonly message: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class ScheduleInterruptedFault extends ScheduleInterruptedFault_base {
|
|
10
|
+
readonly message = "Scheduled execution was interrupted";
|
|
11
|
+
}
|
|
12
12
|
export interface RepeatOptions {
|
|
13
13
|
/** External cancellation signal. Aborts the loop when signalled. */
|
|
14
14
|
signal?: AbortSignal;
|
|
@@ -27,4 +27,5 @@ export interface RepeatOptions {
|
|
|
27
27
|
* Returns the last schedule output on completion.
|
|
28
28
|
*/
|
|
29
29
|
export declare function repeat<Out, E>(schedule: Schedule<unknown, Out>, fn: (signal: AbortSignal) => ResultAsync<void, E>, options?: RepeatOptions): ResultAsync<Out, E | ScheduleInterruptedFault>;
|
|
30
|
+
export {};
|
|
30
31
|
//# sourceMappingURL=runner.d.ts.map
|
package/dist/schedule/runner.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Fault, ResultAsync } from '../unthrow/index.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
create: () => ({
|
|
6
|
-
message: 'Scheduled execution was interrupted',
|
|
7
|
-
}),
|
|
8
|
-
});
|
|
2
|
+
export class ScheduleInterruptedFault extends Fault.Tagged('SCHEDULE_INTERRUPTED', 'infrastructure')() {
|
|
3
|
+
message = 'Scheduled execution was interrupted';
|
|
4
|
+
}
|
|
9
5
|
const NEVER_ABORT = new AbortController().signal;
|
|
10
6
|
function sleep(ms, signal) {
|
|
11
7
|
return new Promise((resolve) => {
|
|
@@ -38,7 +34,7 @@ export function repeat(schedule, fn, options) {
|
|
|
38
34
|
for (let attempt = 0;; attempt++) {
|
|
39
35
|
// eslint-disable-next-line @typescript-eslint/only-throw-error -- intentional: fromPromise catches and maps E
|
|
40
36
|
if (signal?.aborted)
|
|
41
|
-
throw ScheduleInterruptedFault();
|
|
37
|
+
throw new ScheduleInterruptedFault();
|
|
42
38
|
const result = await fn(signal ?? NEVER_ABORT);
|
|
43
39
|
// eslint-disable-next-line @typescript-eslint/only-throw-error -- intentional: fromPromise catches and maps E
|
|
44
40
|
if (result.isErr())
|
|
@@ -50,7 +46,7 @@ export function repeat(schedule, fn, options) {
|
|
|
50
46
|
await sleep(step.delay, signal);
|
|
51
47
|
// eslint-disable-next-line @typescript-eslint/only-throw-error -- intentional: fromPromise catches and maps E
|
|
52
48
|
if (signal?.aborted)
|
|
53
|
-
throw ScheduleInterruptedFault();
|
|
49
|
+
throw new ScheduleInterruptedFault();
|
|
54
50
|
}
|
|
55
51
|
})(), (e) => e);
|
|
56
52
|
}
|
|
@@ -27,5 +27,9 @@ export declare class Schedule<In = unknown, Out = number> {
|
|
|
27
27
|
static once: Schedule;
|
|
28
28
|
/** Fibonacci delay sequence: one, one, 2*one, 3*one, 5*one, 8*one, ... */
|
|
29
29
|
static fibonacci: (one: number) => Schedule;
|
|
30
|
+
/** Cron expression schedule (aligned to cron windows) */
|
|
31
|
+
static cron: (expression: string, options?: {
|
|
32
|
+
timezone?: string;
|
|
33
|
+
}) => Schedule;
|
|
30
34
|
}
|
|
31
35
|
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Cron } from 'croner';
|
|
1
2
|
export class Schedule {
|
|
2
3
|
_next;
|
|
3
4
|
constructor(_next) {
|
|
@@ -90,5 +91,16 @@ export class Schedule {
|
|
|
90
91
|
return { delay, continue: true, output: attempt };
|
|
91
92
|
});
|
|
92
93
|
};
|
|
94
|
+
/** Cron expression schedule (aligned to cron windows) */
|
|
95
|
+
static cron = (expression, options) => {
|
|
96
|
+
const pattern = new Cron(expression, options?.timezone ? { timezone: options.timezone } : undefined);
|
|
97
|
+
return new Schedule((_input, attempt) => {
|
|
98
|
+
const next = pattern.nextRun();
|
|
99
|
+
if (!next)
|
|
100
|
+
return { delay: 0, continue: false, output: attempt };
|
|
101
|
+
const delay = Math.max(0, next.getTime() - Date.now());
|
|
102
|
+
return { delay, continue: true, output: attempt };
|
|
103
|
+
});
|
|
104
|
+
};
|
|
93
105
|
}
|
|
94
106
|
//# sourceMappingURL=schedule.js.map
|
package/dist/timeout/index.d.ts
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { withTimeout as _withTimeout, createTimeout as _createTimeout } from './timeout.js';
|
|
2
|
-
export
|
|
2
|
+
export { TimeoutFault } from './timeout.js';
|
|
3
3
|
export declare namespace Timeout {
|
|
4
4
|
const wrap: typeof _withTimeout;
|
|
5
5
|
const create: typeof _createTimeout;
|
|
6
|
-
const Fault: (duration: number) => Readonly<{
|
|
7
|
-
code: "TIMEOUT";
|
|
8
|
-
_category: "infrastructure";
|
|
9
|
-
_transient: true;
|
|
10
|
-
message: string;
|
|
11
|
-
} & Omit<{
|
|
12
|
-
message: string;
|
|
13
|
-
duration: number;
|
|
14
|
-
}, "message">>;
|
|
15
6
|
}
|
|
16
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/timeout/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { withTimeout as _withTimeout, createTimeout as _createTimeout, } from './timeout.js';
|
|
2
|
+
export { TimeoutFault } from './timeout.js';
|
|
2
3
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
3
4
|
export var Timeout;
|
|
4
5
|
(function (Timeout) {
|
|
5
6
|
Timeout.wrap = _withTimeout;
|
|
6
7
|
Timeout.create = _createTimeout;
|
|
7
|
-
Timeout.Fault = _TimeoutFault;
|
|
8
8
|
})(Timeout || (Timeout = {}));
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { ResultAsync } from '../unthrow/index.js';
|
|
2
|
-
|
|
3
|
-
code: "TIMEOUT";
|
|
4
|
-
_category: "infrastructure";
|
|
5
|
-
_transient: true;
|
|
6
|
-
message: string;
|
|
7
|
-
} & Omit<{
|
|
8
|
-
message: string;
|
|
2
|
+
declare const TimeoutFault_base: abstract new (fields: {
|
|
9
3
|
duration: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
4
|
+
}) => Readonly<{
|
|
5
|
+
duration: number;
|
|
6
|
+
}> & {
|
|
7
|
+
readonly code: "TIMEOUT";
|
|
8
|
+
readonly _category: "infrastructure";
|
|
9
|
+
readonly _transient: true;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
};
|
|
12
|
+
export declare class TimeoutFault extends TimeoutFault_base {
|
|
13
|
+
readonly message: string;
|
|
14
|
+
}
|
|
12
15
|
export declare function withTimeout<T, E>(fn: (signal: AbortSignal) => ResultAsync<T, E>, duration: number): ResultAsync<T, E | TimeoutFault>;
|
|
13
16
|
export declare function createTimeout(duration: number): <T, E>(fn: (signal: AbortSignal) => ResultAsync<T, E>) => ResultAsync<T, E | TimeoutFault>;
|
|
17
|
+
export {};
|
|
14
18
|
//# sourceMappingURL=timeout.d.ts.map
|
package/dist/timeout/timeout.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Fault, ResultAsync } from '../unthrow/index.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
transient: true,
|
|
6
|
-
create: (duration) => ({
|
|
7
|
-
message: `Operation timed out after ${duration}ms`,
|
|
8
|
-
duration,
|
|
9
|
-
}),
|
|
10
|
-
});
|
|
2
|
+
export class TimeoutFault extends Fault.Tagged('TIMEOUT', 'infrastructure', true)() {
|
|
3
|
+
message = `Operation timed out after ${this.duration}ms`;
|
|
4
|
+
}
|
|
11
5
|
export function withTimeout(fn, duration) {
|
|
12
6
|
const controller = new AbortController();
|
|
13
7
|
return ResultAsync.fromPromise(
|
|
@@ -15,7 +9,7 @@ export function withTimeout(fn, duration) {
|
|
|
15
9
|
new Promise((resolve, reject) => {
|
|
16
10
|
const timer = setTimeout(() => {
|
|
17
11
|
controller.abort();
|
|
18
|
-
reject(TimeoutFault(duration));
|
|
12
|
+
reject(new TimeoutFault({ duration }));
|
|
19
13
|
}, duration);
|
|
20
14
|
void fn(controller.signal).then((result) => {
|
|
21
15
|
clearTimeout(timer);
|
package/dist/unthrow/fault.d.ts
CHANGED
|
@@ -4,34 +4,19 @@ export interface Fault {
|
|
|
4
4
|
readonly _category: 'domain' | 'infrastructure';
|
|
5
5
|
readonly _transient: boolean;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
7
|
+
export declare function isDomainFault(error: Fault): error is Fault & {
|
|
8
8
|
readonly _category: 'domain';
|
|
9
|
-
readonly _transient: false;
|
|
10
9
|
};
|
|
11
|
-
export
|
|
10
|
+
export declare function isInfrastructureFault(error: Fault): error is Fault & {
|
|
12
11
|
readonly _category: 'infrastructure';
|
|
13
12
|
};
|
|
14
|
-
export
|
|
13
|
+
export declare function isTransientFault(error: Fault): error is Fault & {
|
|
15
14
|
readonly _transient: true;
|
|
16
15
|
};
|
|
17
|
-
export declare function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
export declare function defineFault<const O extends {
|
|
24
|
-
code: string;
|
|
25
|
-
category: 'domain' | 'infrastructure';
|
|
26
|
-
transient?: boolean;
|
|
27
|
-
create: (...args: any[]) => {
|
|
28
|
-
message: string;
|
|
29
|
-
};
|
|
30
|
-
}>(options: O): (...args: Parameters<O['create']>) => Readonly<{
|
|
31
|
-
code: O['code'];
|
|
32
|
-
_category: O['category'];
|
|
33
|
-
_transient: InferTransient<O>;
|
|
34
|
-
message: string;
|
|
35
|
-
} & Omit<ReturnType<O['create']>, 'message'>>;
|
|
36
|
-
export {};
|
|
16
|
+
export declare function Fault<const Code extends string, const Category extends 'domain' | 'infrastructure', const Transient extends boolean = false>(code: Code, category: Category, transient?: Transient): <A extends Record<string, unknown> = Record<string, unknown>>() => abstract new (...args: Record<string, unknown> extends A ? [] : [fields: A]) => Readonly<A> & {
|
|
17
|
+
readonly code: Code;
|
|
18
|
+
readonly _category: Category;
|
|
19
|
+
readonly _transient: Transient;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
};
|
|
37
22
|
//# sourceMappingURL=fault.d.ts.map
|
package/dist/unthrow/fault.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
export function isTransient(error) {
|
|
2
|
-
return error._transient && error._category === 'infrastructure';
|
|
3
|
-
}
|
|
4
1
|
export function isDomainFault(error) {
|
|
5
2
|
return error._category === 'domain';
|
|
6
3
|
}
|
|
7
4
|
export function isInfrastructureFault(error) {
|
|
8
5
|
return error._category === 'infrastructure';
|
|
9
6
|
}
|
|
10
|
-
export function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
export function isTransientFault(error) {
|
|
8
|
+
return error._transient && error._category === 'infrastructure';
|
|
9
|
+
}
|
|
10
|
+
export function Fault(code, category, transient) {
|
|
11
|
+
const _transient = (transient ?? false);
|
|
12
|
+
return () => {
|
|
13
|
+
class FaultImpl {
|
|
14
|
+
code = code;
|
|
15
|
+
_category = category;
|
|
16
|
+
_transient = _transient;
|
|
17
|
+
constructor(...args) {
|
|
18
|
+
const fields = args[0];
|
|
19
|
+
if (fields) {
|
|
20
|
+
Object.assign(this, fields);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return FaultImpl;
|
|
20
25
|
};
|
|
21
26
|
}
|
|
22
27
|
//# sourceMappingURL=fault.js.map
|