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.
@@ -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 type { SemaphoreOptions } from './semaphore.js';
6
- export type { RateLimiterOptions } from './rate-limiter.js';
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
- export declare const RateLimitFault: (retryAfter: number) => Readonly<{
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
- }, "message">>;
11
- export type RateLimitFault = ReturnType<typeof RateLimitFault>;
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 const RateLimitFault = Fault.define({
3
- code: 'RATE_LIMITED',
4
- category: 'infrastructure',
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();
@@ -11,7 +11,7 @@ export class BaseQueue {
11
11
  if (this._buffer.length > 0) {
12
12
  return Result.ok(this._buffer.shift());
13
13
  }
14
- return Result.err(QueueEmptyFault());
14
+ return Result.err(new QueueEmptyFault());
15
15
  }
16
16
  take(signal) {
17
17
  const taken = this._tryTake();
@@ -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, ReturnType<typeof QueueEmptyFault>>;
8
- offer(item: T): Result<void, ReturnType<typeof QueueFullFault>>;
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);
@@ -1,20 +1,24 @@
1
- export declare const QueueFullFault: (capacity: number) => Readonly<{
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
- }, "message">>;
10
- export type QueueFullFault = ReturnType<typeof QueueFullFault>;
11
- export declare const QueueEmptyFault: () => Readonly<{
12
- code: "QUEUE_EMPTY";
13
- _category: "infrastructure";
14
- _transient: false;
15
- message: string;
16
- } & Omit<{
17
- message: string;
18
- }, "message">>;
19
- export type QueueEmptyFault = ReturnType<typeof QueueEmptyFault>;
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
@@ -1,17 +1,8 @@
1
1
  import { Fault } from '../unthrow/index.js';
2
- export const QueueFullFault = Fault.define({
3
- code: 'QUEUE_FULL',
4
- category: 'infrastructure',
5
- create: (capacity) => ({
6
- message: `Queue is full (capacity: ${capacity})`,
7
- capacity,
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
@@ -1,11 +1,15 @@
1
- import { BoundedQueue as _BoundedQueue } from './bounded.queue.js';
2
- import { DroppingQueue as _DroppingQueue } from './dropping.queue.js';
3
- import { SlidingQueue as _SlidingQueue } from './sliding.queue.js';
4
- export type { QueueOptions } from './base.queue.js';
5
- export type { QueueFullFault, QueueEmptyFault } from './faults.js';
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
- const Bounded: typeof _BoundedQueue;
8
- const Dropping: typeof _DroppingQueue;
9
- const Sliding: typeof _SlidingQueue;
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
@@ -1,11 +1,12 @@
1
- import { BoundedQueue as _BoundedQueue } from './bounded.queue.js';
2
- import { DroppingQueue as _DroppingQueue } from './dropping.queue.js';
3
- import { SlidingQueue as _SlidingQueue } from './sliding.queue.js';
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 = _BoundedQueue;
8
- Queue.Dropping = _DroppingQueue;
9
- Queue.Sliding = _SlidingQueue;
8
+ Queue.Bounded = BoundedQueue;
9
+ Queue.Dropping = DroppingQueue;
10
+ Queue.Sliding = SlidingQueue;
10
11
  })(Queue || (Queue = {}));
11
12
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,8 @@
1
- import { RetryPolicy as _RetryPolicy } from './retry.js';
2
- export type { RetryOptions } from './retry.js';
1
+ import { RetryPolicy } from './retry.js';
2
+ import type { RetryOptions } from './retry.js';
3
3
  export declare namespace Retry {
4
- const Policy: typeof _RetryPolicy;
4
+ type Options = RetryOptions;
5
+ const Policy: typeof RetryPolicy;
6
+ type Policy = RetryPolicy;
5
7
  }
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,7 @@
1
- import { RetryPolicy as _RetryPolicy } from './retry.js';
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 = _RetryPolicy;
5
+ Retry.Policy = RetryPolicy;
6
6
  })(Retry || (Retry = {}));
7
7
  //# sourceMappingURL=index.js.map
@@ -1,20 +1,25 @@
1
- import { Schedule as ScheduleClass } from './schedule.js';
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
- export type { ScheduleStep, ScheduleOperator } from './schedule.js';
5
+ import type { RepeatOptions as _RepeatOptions } from './runner.js';
5
6
  export { ScheduleInterruptedFault } from './runner.js';
6
- export type { RepeatOptions } from './runner.js';
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
- const spaced: (ms: number) => ScheduleClass;
10
- const exponential: (initialDelay: number, multiplier?: number) => ScheduleClass;
11
- const linear: (initialDelay: number) => ScheduleClass;
12
- const constant: (delay: number) => ScheduleClass;
13
- const fixed: (interval: number) => ScheduleClass;
14
- const windowed: (interval: number) => ScheduleClass;
15
- const forever: ScheduleClass<unknown, number>;
16
- const once: ScheduleClass<unknown, number>;
17
- const fibonacci: (one: number) => ScheduleClass;
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
@@ -1,19 +1,20 @@
1
- import { Schedule as ScheduleClass } from './schedule.js';
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 = ScheduleClass.spaced;
9
- Schedule.exponential = ScheduleClass.exponential;
10
- Schedule.linear = ScheduleClass.linear;
11
- Schedule.constant = ScheduleClass.constant;
12
- Schedule.fixed = ScheduleClass.fixed;
13
- Schedule.windowed = ScheduleClass.windowed;
14
- Schedule.forever = ScheduleClass.forever;
15
- Schedule.once = ScheduleClass.once;
16
- Schedule.fibonacci = ScheduleClass.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
- export declare const ScheduleInterruptedFault: () => Readonly<{
4
- code: "SCHEDULE_INTERRUPTED";
5
- _category: "infrastructure";
6
- _transient: false;
7
- message: string;
8
- } & Omit<{
9
- message: string;
10
- }, "message">>;
11
- export type ScheduleInterruptedFault = ReturnType<typeof ScheduleInterruptedFault>;
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
@@ -1,11 +1,7 @@
1
1
  import { Fault, ResultAsync } from '../unthrow/index.js';
2
- export const ScheduleInterruptedFault = Fault.define({
3
- code: 'SCHEDULE_INTERRUPTED',
4
- category: 'infrastructure',
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
@@ -1,16 +1,7 @@
1
1
  import { withTimeout as _withTimeout, createTimeout as _createTimeout } from './timeout.js';
2
- export type { TimeoutFault } from './timeout.js';
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
@@ -1,9 +1,9 @@
1
- import { TimeoutFault as _TimeoutFault, withTimeout as _withTimeout, createTimeout as _createTimeout, } from './timeout.js';
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
- export declare const TimeoutFault: (duration: number) => Readonly<{
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
- }, "message">>;
11
- export type TimeoutFault = ReturnType<typeof TimeoutFault>;
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
@@ -1,13 +1,7 @@
1
1
  import { Fault, ResultAsync } from '../unthrow/index.js';
2
- export const TimeoutFault = Fault.define({
3
- code: 'TIMEOUT',
4
- category: 'infrastructure',
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);
@@ -4,34 +4,19 @@ export interface Fault {
4
4
  readonly _category: 'domain' | 'infrastructure';
5
5
  readonly _transient: boolean;
6
6
  }
7
- export type DomainFault = Fault & {
7
+ export declare function isDomainFault(error: Fault): error is Fault & {
8
8
  readonly _category: 'domain';
9
- readonly _transient: false;
10
9
  };
11
- export type InfrastructureFault = Fault & {
10
+ export declare function isInfrastructureFault(error: Fault): error is Fault & {
12
11
  readonly _category: 'infrastructure';
13
12
  };
14
- export type TransientFault = InfrastructureFault & {
13
+ export declare function isTransientFault(error: Fault): error is Fault & {
15
14
  readonly _transient: true;
16
15
  };
17
- export declare function isTransient(error: Fault): error is TransientFault;
18
- export declare function isDomainFault(error: Fault): error is DomainFault;
19
- export declare function isInfrastructureFault(error: Fault): error is InfrastructureFault;
20
- type InferTransient<O> = O extends {
21
- transient: infer T extends boolean;
22
- } ? T : false;
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
@@ -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 defineFault(options) {
11
- const transient = (options.transient ?? false);
12
- return (...args) => {
13
- const extra = options.create(...args);
14
- return Object.freeze({
15
- code: options.code,
16
- _category: options.category,
17
- _transient: transient,
18
- ...extra,
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