@depthbomb/common 2.1.0 → 2.2.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.
@@ -1,6 +1,9 @@
1
1
  import { Awaitable } from "./typing.mjs";
2
2
 
3
3
  //#region src/promise.d.ts
4
+ /**
5
+ * Configuration for promise concurrency helpers.
6
+ */
4
7
  interface IConcurrencyOptions {
5
8
  concurrency?: number;
6
9
  }
@@ -11,6 +14,9 @@ interface IConcurrencyOptions {
11
14
  * @returns A promise that resolves to an array of successful results
12
15
  */
13
16
  declare function allSettledSuccessful<T>(promises: Array<Awaitable<T>>): Promise<T[]>;
17
+ /**
18
+ * Detailed output from {@link allSettledDetailed}.
19
+ */
14
20
  interface SettledDetailed<T> {
15
21
  results: Array<PromiseSettledResult<T>>;
16
22
  fulfilled: T[];
package/dist/random.d.cts CHANGED
@@ -1,11 +1,36 @@
1
1
  //#region src/random.d.ts
2
+ /**
3
+ * A value paired with a non-negative selection weight.
4
+ */
2
5
  interface IWeightedItem<T> {
3
6
  value: T;
4
7
  weight: number;
5
8
  }
9
+ /**
10
+ * Returns a random floating-point number in the half-open range `[min, max)`.
11
+ *
12
+ * @param min Lower bound.
13
+ * @param max Upper bound.
14
+ */
6
15
  declare function randomFloat(min?: number, max?: number): number;
16
+ /**
17
+ * Returns a random integer in the inclusive range `[min, max]`.
18
+ *
19
+ * @param min Lower bound.
20
+ * @param max Upper bound.
21
+ */
7
22
  declare function randomInt(min: number, max: number): number;
23
+ /**
24
+ * Picks a random element from a non-empty array.
25
+ *
26
+ * @param values Candidate values.
27
+ */
8
28
  declare function pickRandom<T>(values: readonly T[]): T;
29
+ /**
30
+ * Picks a value from weighted candidates.
31
+ *
32
+ * @param items Weighted candidate items.
33
+ */
9
34
  declare function pickWeighted<T>(items: Array<IWeightedItem<T>>): T;
10
35
  //#endregion
11
36
  export { IWeightedItem, pickRandom, pickWeighted, randomFloat, randomInt };
package/dist/random.d.mts CHANGED
@@ -1,11 +1,36 @@
1
1
  //#region src/random.d.ts
2
+ /**
3
+ * A value paired with a non-negative selection weight.
4
+ */
2
5
  interface IWeightedItem<T> {
3
6
  value: T;
4
7
  weight: number;
5
8
  }
9
+ /**
10
+ * Returns a random floating-point number in the half-open range `[min, max)`.
11
+ *
12
+ * @param min Lower bound.
13
+ * @param max Upper bound.
14
+ */
6
15
  declare function randomFloat(min?: number, max?: number): number;
16
+ /**
17
+ * Returns a random integer in the inclusive range `[min, max]`.
18
+ *
19
+ * @param min Lower bound.
20
+ * @param max Upper bound.
21
+ */
7
22
  declare function randomInt(min: number, max: number): number;
23
+ /**
24
+ * Picks a random element from a non-empty array.
25
+ *
26
+ * @param values Candidate values.
27
+ */
8
28
  declare function pickRandom<T>(values: readonly T[]): T;
29
+ /**
30
+ * Picks a value from weighted candidates.
31
+ *
32
+ * @param items Weighted candidate items.
33
+ */
9
34
  declare function pickWeighted<T>(items: Array<IWeightedItem<T>>): T;
10
35
  //#endregion
11
36
  export { IWeightedItem, pickRandom, pickWeighted, randomFloat, randomInt };
package/dist/state.d.cts CHANGED
@@ -76,10 +76,20 @@ declare class Flag extends ResettableValue<boolean> {
76
76
  */
77
77
  toggle(): void;
78
78
  }
79
+ /**
80
+ * Creates a resettable lazy value accessor.
81
+ *
82
+ * @param factory Factory used to create the value.
83
+ */
79
84
  declare function resettableLazy<T>(factory: () => T): {
80
85
  get: () => T;
81
86
  reset: () => void;
82
87
  };
88
+ /**
89
+ * Creates a resettable async lazy accessor.
90
+ *
91
+ * @param factory Async factory used to create the value.
92
+ */
83
93
  declare function resettableLazyAsync<T>(factory: () => Promise<T>): {
84
94
  get: () => Promise<T>;
85
95
  reset: () => void;
package/dist/state.d.mts CHANGED
@@ -76,10 +76,20 @@ declare class Flag extends ResettableValue<boolean> {
76
76
  */
77
77
  toggle(): void;
78
78
  }
79
+ /**
80
+ * Creates a resettable lazy value accessor.
81
+ *
82
+ * @param factory Factory used to create the value.
83
+ */
79
84
  declare function resettableLazy<T>(factory: () => T): {
80
85
  get: () => T;
81
86
  reset: () => void;
82
87
  };
88
+ /**
89
+ * Creates a resettable async lazy accessor.
90
+ *
91
+ * @param factory Async factory used to create the value.
92
+ */
83
93
  declare function resettableLazyAsync<T>(factory: () => Promise<T>): {
84
94
  get: () => Promise<T>;
85
95
  reset: () => void;
package/dist/timing.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=function(e){return e[e.None=0]=`None`,e[e.Full=1]=`Full`,e[e.Equal=2]=`Equal`,e}({});function t(e){return new Promise(t=>setTimeout(t,e))}function n(e){return new Promise((t,n)=>setTimeout(n,e))}async function r(e,n=100,r=5e3){let i=Date.now();for(;!await e();){if(Date.now()-i>r)throw Error(`Timeout exceeded`);await t(n)}}async function i(e,t){let n;try{return await Promise.race([e,new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Operation timed out`)),t)})])}finally{n!==void 0&&clearTimeout(n)}}function a(){let e=Error(`Aborted`);return e.name=`AbortError`,e}function o(e){if(e?.aborted)throw a()}async function s(e,t){if(e<=0){o(t);return}await new Promise((n,r)=>{let i=setTimeout(()=>{t&&t.removeEventListener(`abort`,o),n()},e);function o(){clearTimeout(i),t?.removeEventListener(`abort`,o),r(a())}t&&t.addEventListener(`abort`,o,{once:!0})})}function c(e){if(!Number.isFinite(e)||e<0)throw Error(`ms must be a finite number >= 0`);let t=new AbortController,n=setTimeout(()=>t.abort(),e);return t.signal.addEventListener(`abort`,()=>clearTimeout(n),{once:!0}),t.signal}function l(...e){let t=e.filter(e=>e!==void 0),n=new AbortController,r=new Map,i=()=>{if(!n.signal.aborted){n.abort();for(let[e,t]of r)e.removeEventListener(`abort`,t);r.clear()}};for(let e of t){if(e.aborted){i();break}let t=()=>i();r.set(e,t),e.addEventListener(`abort`,t,{once:!0})}return n.signal}async function u(e,t){return o(t),await new Promise((n,r)=>{function i(){t.removeEventListener(`abort`,i),r(a())}t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function d(t,n){return n===e.None?t:n===e.Full?Math.floor(Math.random()*t):Math.floor(t/2+t/2*Math.random())}async function f(t,n={}){let r=n.attempts??3,i=n.baseMs??100,a=n.maxMs??1/0,c=n.jitter??e.None;if(!Number.isInteger(r)||r<1)throw Error(`attempts must be an integer >= 1`);if(i<0||!Number.isFinite(i))throw Error(`baseMs must be a finite number >= 0`);if(a<0||Number.isNaN(a))throw Error(`maxMs must be a number >= 0`);for(let e=1;e<=r;e++){o(n.signal);try{return await t(e)}catch(t){if(e>=r||n.shouldRetry&&!await n.shouldRetry(t,e))throw t;await s(d(Math.min(i*2**(e-1),a),c),n.signal)}}throw Error(`Unreachable`)}exports.RetryJitter=e,exports.abortAfter=c,exports.pollUntil=r,exports.raceSignals=l,exports.rejectionTimeout=n,exports.retry=f,exports.timeout=t,exports.withAbort=u,exports.withTimeout=i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=function(e){return e[e.None=0]=`None`,e[e.Full=1]=`Full`,e[e.Equal=2]=`Equal`,e}({});function t(e){return new Promise(t=>setTimeout(t,e))}function n(e){return new Promise((t,n)=>setTimeout(n,e))}async function r(e,n=100,r=5e3){let i=Date.now();for(;!await e();){if(Date.now()-i>r)throw Error(`Timeout exceeded`);await t(n)}}async function i(e,t){let n;try{return await Promise.race([e,new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Operation timed out`)),t)})])}finally{n!==void 0&&clearTimeout(n)}}function a(e){if(!Number.isFinite(e)||e<0)throw Error(`ms must be a finite number >= 0`);let t=new AbortController,n=setTimeout(()=>t.abort(),e);return t.signal.addEventListener(`abort`,()=>clearTimeout(n),{once:!0}),t.signal}function o(...e){let t=e.filter(e=>e!==void 0),n=new AbortController,r=new Map,i=()=>{if(!n.signal.aborted){n.abort();for(let[e,t]of r)e.removeEventListener(`abort`,t);r.clear()}};for(let e of t){if(e.aborted){i();break}let t=()=>i();r.set(e,t),e.addEventListener(`abort`,t,{once:!0})}return n.signal}async function s(e,t){return u(t),await new Promise((n,r)=>{function i(){t.removeEventListener(`abort`,i),r(l())}t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}async function c(t,n={}){let r=n.attempts??3,i=n.baseMs??100,a=n.maxMs??1/0,o=n.jitter??e.None;if(!Number.isInteger(r)||r<1)throw Error(`attempts must be an integer >= 1`);if(i<0||!Number.isFinite(i))throw Error(`baseMs must be a finite number >= 0`);if(a<0||Number.isNaN(a))throw Error(`maxMs must be a number >= 0`);for(let e=1;e<=r;e++){u(n.signal);try{return await t(e)}catch(t){if(e>=r||n.shouldRetry&&!await n.shouldRetry(t,e))throw t;await d(f(Math.min(i*2**(e-1),a),o),n.signal)}}throw Error(`Unreachable`)}function l(){let e=Error(`Aborted`);return e.name=`AbortError`,e}function u(e){if(e?.aborted)throw l()}async function d(e,t){if(e<=0){u(t);return}await new Promise((n,r)=>{let i=setTimeout(()=>{t&&t.removeEventListener(`abort`,a),n()},e);function a(){clearTimeout(i),t?.removeEventListener(`abort`,a),r(l())}t&&t.addEventListener(`abort`,a,{once:!0})})}function f(t,n){return n===e.None?t:n===e.Full?Math.floor(Math.random()*t):Math.floor(t/2+t/2*Math.random())}exports.RetryJitter=e,exports.abortAfter=a,exports.pollUntil=r,exports.raceSignals=o,exports.rejectionTimeout=n,exports.retry=c,exports.timeout=t,exports.withAbort=s,exports.withTimeout=i;
package/dist/timing.d.cts CHANGED
@@ -1,6 +1,9 @@
1
- import { Awaitable } from "./typing.cjs";
1
+ import { Awaitable, Maybe } from "./typing.cjs";
2
2
 
3
3
  //#region src/timing.d.ts
4
+ /**
5
+ * Options for {@link retry}.
6
+ */
4
7
  interface IRetryOptions {
5
8
  attempts?: number;
6
9
  baseMs?: number;
@@ -9,6 +12,9 @@ interface IRetryOptions {
9
12
  signal?: AbortSignal;
10
13
  shouldRetry?: (error: unknown, attempt: number) => Awaitable<boolean>;
11
14
  }
15
+ /**
16
+ * Jitter strategies for retry delays.
17
+ */
12
18
  declare const enum RetryJitter {
13
19
  None = 0,
14
20
  Full = 1,
@@ -52,7 +58,7 @@ declare function abortAfter(ms: number): AbortSignal;
52
58
  *
53
59
  * @param signals Input abort signals.
54
60
  */
55
- declare function raceSignals(...signals: Array<AbortSignal | undefined>): AbortSignal;
61
+ declare function raceSignals(...signals: Array<Maybe<AbortSignal>>): AbortSignal;
56
62
  /**
57
63
  * Wraps a promise and rejects when the signal aborts before completion.
58
64
  *
package/dist/timing.d.mts CHANGED
@@ -1,6 +1,9 @@
1
- import { Awaitable } from "./typing.mjs";
1
+ import { Awaitable, Maybe } from "./typing.mjs";
2
2
 
3
3
  //#region src/timing.d.ts
4
+ /**
5
+ * Options for {@link retry}.
6
+ */
4
7
  interface IRetryOptions {
5
8
  attempts?: number;
6
9
  baseMs?: number;
@@ -9,6 +12,9 @@ interface IRetryOptions {
9
12
  signal?: AbortSignal;
10
13
  shouldRetry?: (error: unknown, attempt: number) => Awaitable<boolean>;
11
14
  }
15
+ /**
16
+ * Jitter strategies for retry delays.
17
+ */
12
18
  declare const enum RetryJitter {
13
19
  None = 0,
14
20
  Full = 1,
@@ -52,7 +58,7 @@ declare function abortAfter(ms: number): AbortSignal;
52
58
  *
53
59
  * @param signals Input abort signals.
54
60
  */
55
- declare function raceSignals(...signals: Array<AbortSignal | undefined>): AbortSignal;
61
+ declare function raceSignals(...signals: Array<Maybe<AbortSignal>>): AbortSignal;
56
62
  /**
57
63
  * Wraps a promise and rejects when the signal aborts before completion.
58
64
  *
package/dist/timing.mjs CHANGED
@@ -1 +1 @@
1
- let e=function(e){return e[e.None=0]=`None`,e[e.Full=1]=`Full`,e[e.Equal=2]=`Equal`,e}({});function t(e){return new Promise(t=>setTimeout(t,e))}function n(e){return new Promise((t,n)=>setTimeout(n,e))}async function r(e,n=100,r=5e3){let i=Date.now();for(;!await e();){if(Date.now()-i>r)throw Error(`Timeout exceeded`);await t(n)}}async function i(e,t){let n;try{return await Promise.race([e,new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Operation timed out`)),t)})])}finally{n!==void 0&&clearTimeout(n)}}function a(){let e=Error(`Aborted`);return e.name=`AbortError`,e}function o(e){if(e?.aborted)throw a()}async function s(e,t){if(e<=0){o(t);return}await new Promise((n,r)=>{let i=setTimeout(()=>{t&&t.removeEventListener(`abort`,o),n()},e);function o(){clearTimeout(i),t?.removeEventListener(`abort`,o),r(a())}t&&t.addEventListener(`abort`,o,{once:!0})})}function c(e){if(!Number.isFinite(e)||e<0)throw Error(`ms must be a finite number >= 0`);let t=new AbortController,n=setTimeout(()=>t.abort(),e);return t.signal.addEventListener(`abort`,()=>clearTimeout(n),{once:!0}),t.signal}function l(...e){let t=e.filter(e=>e!==void 0),n=new AbortController,r=new Map,i=()=>{if(!n.signal.aborted){n.abort();for(let[e,t]of r)e.removeEventListener(`abort`,t);r.clear()}};for(let e of t){if(e.aborted){i();break}let t=()=>i();r.set(e,t),e.addEventListener(`abort`,t,{once:!0})}return n.signal}async function u(e,t){return o(t),await new Promise((n,r)=>{function i(){t.removeEventListener(`abort`,i),r(a())}t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function d(t,n){return n===e.None?t:n===e.Full?Math.floor(Math.random()*t):Math.floor(t/2+t/2*Math.random())}async function f(t,n={}){let r=n.attempts??3,i=n.baseMs??100,a=n.maxMs??1/0,c=n.jitter??e.None;if(!Number.isInteger(r)||r<1)throw Error(`attempts must be an integer >= 1`);if(i<0||!Number.isFinite(i))throw Error(`baseMs must be a finite number >= 0`);if(a<0||Number.isNaN(a))throw Error(`maxMs must be a number >= 0`);for(let e=1;e<=r;e++){o(n.signal);try{return await t(e)}catch(t){if(e>=r||n.shouldRetry&&!await n.shouldRetry(t,e))throw t;await s(d(Math.min(i*2**(e-1),a),c),n.signal)}}throw Error(`Unreachable`)}export{e as RetryJitter,c as abortAfter,r as pollUntil,l as raceSignals,n as rejectionTimeout,f as retry,t as timeout,u as withAbort,i as withTimeout};
1
+ let e=function(e){return e[e.None=0]=`None`,e[e.Full=1]=`Full`,e[e.Equal=2]=`Equal`,e}({});function t(e){return new Promise(t=>setTimeout(t,e))}function n(e){return new Promise((t,n)=>setTimeout(n,e))}async function r(e,n=100,r=5e3){let i=Date.now();for(;!await e();){if(Date.now()-i>r)throw Error(`Timeout exceeded`);await t(n)}}async function i(e,t){let n;try{return await Promise.race([e,new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Operation timed out`)),t)})])}finally{n!==void 0&&clearTimeout(n)}}function a(e){if(!Number.isFinite(e)||e<0)throw Error(`ms must be a finite number >= 0`);let t=new AbortController,n=setTimeout(()=>t.abort(),e);return t.signal.addEventListener(`abort`,()=>clearTimeout(n),{once:!0}),t.signal}function o(...e){let t=e.filter(e=>e!==void 0),n=new AbortController,r=new Map,i=()=>{if(!n.signal.aborted){n.abort();for(let[e,t]of r)e.removeEventListener(`abort`,t);r.clear()}};for(let e of t){if(e.aborted){i();break}let t=()=>i();r.set(e,t),e.addEventListener(`abort`,t,{once:!0})}return n.signal}async function s(e,t){return u(t),await new Promise((n,r)=>{function i(){t.removeEventListener(`abort`,i),r(l())}t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}async function c(t,n={}){let r=n.attempts??3,i=n.baseMs??100,a=n.maxMs??1/0,o=n.jitter??e.None;if(!Number.isInteger(r)||r<1)throw Error(`attempts must be an integer >= 1`);if(i<0||!Number.isFinite(i))throw Error(`baseMs must be a finite number >= 0`);if(a<0||Number.isNaN(a))throw Error(`maxMs must be a number >= 0`);for(let e=1;e<=r;e++){u(n.signal);try{return await t(e)}catch(t){if(e>=r||n.shouldRetry&&!await n.shouldRetry(t,e))throw t;await d(f(Math.min(i*2**(e-1),a),o),n.signal)}}throw Error(`Unreachable`)}function l(){let e=Error(`Aborted`);return e.name=`AbortError`,e}function u(e){if(e?.aborted)throw l()}async function d(e,t){if(e<=0){u(t);return}await new Promise((n,r)=>{let i=setTimeout(()=>{t&&t.removeEventListener(`abort`,a),n()},e);function a(){clearTimeout(i),t?.removeEventListener(`abort`,a),r(l())}t&&t.addEventListener(`abort`,a,{once:!0})})}function f(t,n){return n===e.None?t:n===e.Full?Math.floor(Math.random()*t):Math.floor(t/2+t/2*Math.random())}export{e as RetryJitter,a as abortAfter,r as pollUntil,o as raceSignals,n as rejectionTimeout,c as retry,t as timeout,s as withAbort,i as withTimeout};
package/dist/typing.d.cts CHANGED
@@ -1,9 +1,27 @@
1
1
  //#region src/typing.d.ts
2
+ /**
3
+ * A value or a promise-like value.
4
+ */
2
5
  type Awaitable<T> = PromiseLike<T> | T;
6
+ /**
7
+ * A value that may be `undefined`.
8
+ */
3
9
  type Maybe<T> = T | undefined;
10
+ /**
11
+ * A value that may be `null`.
12
+ */
4
13
  type Nullable<T> = T | null;
14
+ /**
15
+ * A single value or an array of values.
16
+ */
5
17
  type Arrayable<T> = T | Array<T>;
18
+ /**
19
+ * Flattens mapped/intersection display in editor tooltips.
20
+ */
6
21
  type Prettify<T> = { [K in keyof T]: T[K] } & {};
22
+ /**
23
+ * Discriminated result type for success/failure operations.
24
+ */
7
25
  type Result<T, E = unknown> = {
8
26
  ok: true;
9
27
  value: T;
@@ -11,19 +29,83 @@ type Result<T, E = unknown> = {
11
29
  ok: false;
12
30
  error: E;
13
31
  };
32
+ /**
33
+ * A generic function type.
34
+ */
35
+ type Fn<Return = void, Args extends unknown[] = unknown[]> = (...args: Args) => Return;
36
+ /**
37
+ * A generic function type that may return either a value or a promise-like value.
38
+ */
39
+ type AwaitableFn<Return = void, Args extends unknown[] = unknown[]> = (...args: Args) => Awaitable<Return>;
40
+ /**
41
+ * Class constructor type.
42
+ */
14
43
  type Class<T, Args extends unknown[] = any[]> = new (...args: Args) => T;
44
+ /**
45
+ * Recasts a value to a wider target type without runtime transformation.
46
+ *
47
+ * @param value Input value.
48
+ */
15
49
  declare const cast: <T, U extends T>(value: U) => U;
50
+ /**
51
+ * Asserts an unknown value as type `T` at compile time.
52
+ *
53
+ * @param value Value to assert.
54
+ */
16
55
  declare function assume<T>(value: unknown): asserts value is T;
56
+ /**
57
+ * Returns strongly typed `Object.entries` output.
58
+ *
59
+ * @param obj Object to enumerate.
60
+ */
17
61
  declare function typedEntries<T extends object>(obj: T): { [K in keyof T]: [K, T[K]] }[keyof T][];
62
+ /**
63
+ * Creates a successful {@link Result}.
64
+ *
65
+ * @param value Success value.
66
+ */
18
67
  declare function ok<T>(value: T): Result<T, never>;
68
+ /**
69
+ * Creates a failed {@link Result}.
70
+ *
71
+ * @param error Failure value.
72
+ */
19
73
  declare function err<E>(error: E): Result<never, E>;
74
+ /**
75
+ * Type guard for successful {@link Result} values.
76
+ *
77
+ * @param result Result to check.
78
+ */
20
79
  declare function isOk<T, E>(result: Result<T, E>): result is {
21
80
  ok: true;
22
81
  value: T;
23
82
  };
83
+ /**
84
+ * Maps only the success branch of a {@link Result}.
85
+ *
86
+ * @param result Result to map.
87
+ * @param mapper Success mapper.
88
+ */
24
89
  declare function mapOk<T, U, E>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E>;
90
+ /**
91
+ * Maps only the error branch of a {@link Result}.
92
+ *
93
+ * @param result Result to map.
94
+ * @param mapper Error mapper.
95
+ */
25
96
  declare function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F>;
97
+ /**
98
+ * Runs an async operation and converts thrown errors into a failed {@link Result}.
99
+ *
100
+ * @param operation Async operation to execute.
101
+ */
26
102
  declare function tryCatchAsync<T>(operation: () => Awaitable<T>): Promise<Result<T, unknown>>;
103
+ /**
104
+ * Runs an async operation and maps thrown errors into a custom error type.
105
+ *
106
+ * @param operation Async operation to execute.
107
+ * @param mapError Error mapper.
108
+ */
27
109
  declare function tryCatchAsync<T, E>(operation: () => Awaitable<T>, mapError: (error: unknown) => E): Promise<Result<T, E>>;
28
110
  //#endregion
29
- export { Arrayable, Awaitable, Class, Maybe, Nullable, Prettify, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries };
111
+ export { Arrayable, Awaitable, AwaitableFn, Class, Fn, Maybe, Nullable, Prettify, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries };
package/dist/typing.d.mts CHANGED
@@ -1,9 +1,27 @@
1
1
  //#region src/typing.d.ts
2
+ /**
3
+ * A value or a promise-like value.
4
+ */
2
5
  type Awaitable<T> = PromiseLike<T> | T;
6
+ /**
7
+ * A value that may be `undefined`.
8
+ */
3
9
  type Maybe<T> = T | undefined;
10
+ /**
11
+ * A value that may be `null`.
12
+ */
4
13
  type Nullable<T> = T | null;
14
+ /**
15
+ * A single value or an array of values.
16
+ */
5
17
  type Arrayable<T> = T | Array<T>;
18
+ /**
19
+ * Flattens mapped/intersection display in editor tooltips.
20
+ */
6
21
  type Prettify<T> = { [K in keyof T]: T[K] } & {};
22
+ /**
23
+ * Discriminated result type for success/failure operations.
24
+ */
7
25
  type Result<T, E = unknown> = {
8
26
  ok: true;
9
27
  value: T;
@@ -11,19 +29,83 @@ type Result<T, E = unknown> = {
11
29
  ok: false;
12
30
  error: E;
13
31
  };
32
+ /**
33
+ * A generic function type.
34
+ */
35
+ type Fn<Return = void, Args extends unknown[] = unknown[]> = (...args: Args) => Return;
36
+ /**
37
+ * A generic function type that may return either a value or a promise-like value.
38
+ */
39
+ type AwaitableFn<Return = void, Args extends unknown[] = unknown[]> = (...args: Args) => Awaitable<Return>;
40
+ /**
41
+ * Class constructor type.
42
+ */
14
43
  type Class<T, Args extends unknown[] = any[]> = new (...args: Args) => T;
44
+ /**
45
+ * Recasts a value to a wider target type without runtime transformation.
46
+ *
47
+ * @param value Input value.
48
+ */
15
49
  declare const cast: <T, U extends T>(value: U) => U;
50
+ /**
51
+ * Asserts an unknown value as type `T` at compile time.
52
+ *
53
+ * @param value Value to assert.
54
+ */
16
55
  declare function assume<T>(value: unknown): asserts value is T;
56
+ /**
57
+ * Returns strongly typed `Object.entries` output.
58
+ *
59
+ * @param obj Object to enumerate.
60
+ */
17
61
  declare function typedEntries<T extends object>(obj: T): { [K in keyof T]: [K, T[K]] }[keyof T][];
62
+ /**
63
+ * Creates a successful {@link Result}.
64
+ *
65
+ * @param value Success value.
66
+ */
18
67
  declare function ok<T>(value: T): Result<T, never>;
68
+ /**
69
+ * Creates a failed {@link Result}.
70
+ *
71
+ * @param error Failure value.
72
+ */
19
73
  declare function err<E>(error: E): Result<never, E>;
74
+ /**
75
+ * Type guard for successful {@link Result} values.
76
+ *
77
+ * @param result Result to check.
78
+ */
20
79
  declare function isOk<T, E>(result: Result<T, E>): result is {
21
80
  ok: true;
22
81
  value: T;
23
82
  };
83
+ /**
84
+ * Maps only the success branch of a {@link Result}.
85
+ *
86
+ * @param result Result to map.
87
+ * @param mapper Success mapper.
88
+ */
24
89
  declare function mapOk<T, U, E>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E>;
90
+ /**
91
+ * Maps only the error branch of a {@link Result}.
92
+ *
93
+ * @param result Result to map.
94
+ * @param mapper Error mapper.
95
+ */
25
96
  declare function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F>;
97
+ /**
98
+ * Runs an async operation and converts thrown errors into a failed {@link Result}.
99
+ *
100
+ * @param operation Async operation to execute.
101
+ */
26
102
  declare function tryCatchAsync<T>(operation: () => Awaitable<T>): Promise<Result<T, unknown>>;
103
+ /**
104
+ * Runs an async operation and maps thrown errors into a custom error type.
105
+ *
106
+ * @param operation Async operation to execute.
107
+ * @param mapError Error mapper.
108
+ */
27
109
  declare function tryCatchAsync<T, E>(operation: () => Awaitable<T>, mapError: (error: unknown) => E): Promise<Result<T, E>>;
28
110
  //#endregion
29
- export { Arrayable, Awaitable, Class, Maybe, Nullable, Prettify, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries };
111
+ export { Arrayable, Awaitable, AwaitableFn, Class, Fn, Maybe, Nullable, Prettify, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries };
package/dist/url.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,...t){let n=``;for(let r=0;r<e.length;r++)n+=e[r],r<t.length&&(n+=encodeURIComponent(String(t[r])));return n}function t(e,n,r){if(r!=null){if(Array.isArray(r)){for(let i of r)t(e,n,i);return}if(typeof r==`object`){try{e.append(n,JSON.stringify(r))}catch{e.append(n,String(r))}return}e.append(n,String(r))}}var n=class e{#e;constructor(t,n){t instanceof e||t instanceof URL?this.#e=new URL(t.toString()):n?this.#e=new URL(t,n.toString()):this.#e=new URL(t)}get protocol(){return this.#e.protocol}get host(){return this.#e.host}get hostname(){return this.#e.hostname}get port(){return this.#e.port}get origin(){return this.#e.origin}get username(){return this.#e.username}get password(){return this.#e.password}get hash(){return this.#e.hash}get search(){return this.#e.search}get searchParams(){return new URLSearchParams(this.#e.search)}get pathname(){return this.#e.pathname}get parts(){return this.#e.pathname.split(`/`).filter(Boolean).map(decodeURIComponent)}get name(){return this.parts.at(-1)??``}get suffix(){let e=this.name,t=e.lastIndexOf(`.`);return t>=0?e.slice(t):``}get stem(){let e=this.name,t=e.lastIndexOf(`.`);return t>=0?e.slice(0,t):e}get parent(){let e=this.parts.slice(0,-1);return this.withPath(e)}joinpath(...e){let t=[...this.parts,...e.map(e=>e.replace(/^\/+|\/+$/g,``))];return this.withPath(t)}div(...e){return this.joinpath(...e)}withPath(t){let n=new URL(this.#e.toString());return n.pathname=`/`+t.map(encodeURIComponent).join(`/`),new e(n)}withQuery(n){let r=new URL(this.#e.toString());for(let[e,i]of Object.entries(n))r.searchParams.delete(e),t(r.searchParams,e,i);return new e(r)}withQueryPatch(e){return this.withQuery(e)}appendQuery(n){let r=new URL(this.#e.toString());for(let[e,i]of Object.entries(n))t(r.searchParams,e,i);return new e(r)}withoutEmptyQuery(){let t=new URL(this.#e.toString()),n=new Set;for(let e of t.searchParams.keys())n.has(e)||(n.add(e),t.searchParams.getAll(e).every(e=>e===``)&&t.searchParams.delete(e));return new e(t)}withoutQuery(...t){let n=new URL(this.#e.toString());for(let e of t)n.searchParams.delete(e);return new e(n)}withHash(t){let n=new URL(this.#e.toString());return n.hash=t.startsWith(`#`)?t:`#${t}`,new e(n)}withoutHash(){let t=new URL(this.#e.toString());return t.hash=``,new e(t)}async fetch(e){return fetch(this.#e,e)}resolve(t){return new e(t,this)}equals(t){return this.toString()===new e(t).toString()}toURL(){return new URL(this.#e.toString())}toString(){return this.#e.toString()}valueOf(){return this.toString()}[Symbol.toPrimitive](){return this.toString()}static from(t,n){return new e(t,n)}static parse(t){return new e(t)}};exports.URLPath=n,exports.url=e;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,...t){let n=``;for(let r=0;r<e.length;r++)n+=e[r],r<t.length&&(n+=encodeURIComponent(String(t[r])));return n}var t=class e{#e;constructor(t,n){t instanceof e||t instanceof URL?this.#e=new URL(t.toString()):n?this.#e=new URL(t,n.toString()):this.#e=new URL(t)}get protocol(){return this.#e.protocol}get host(){return this.#e.host}get hostname(){return this.#e.hostname}get port(){return this.#e.port}get origin(){return this.#e.origin}get username(){return this.#e.username}get password(){return this.#e.password}get hash(){return this.#e.hash}get search(){return this.#e.search}get searchParams(){return new URLSearchParams(this.#e.search)}get pathname(){return this.#e.pathname}get parts(){return this.#e.pathname.split(`/`).filter(Boolean).map(decodeURIComponent)}get name(){return this.parts.at(-1)??``}get suffix(){let e=this.name,t=e.lastIndexOf(`.`);return t>=0?e.slice(t):``}get stem(){let e=this.name,t=e.lastIndexOf(`.`);return t>=0?e.slice(0,t):e}get parent(){let e=this.parts.slice(0,-1);return this.withPath(e)}joinpath(...e){let t=[...this.parts,...e.map(e=>e.replace(/^\/+|\/+$/g,``))];return this.withPath(t)}div(...e){return this.joinpath(...e)}withPath(t){let n=new URL(this.#e.toString());return n.pathname=`/`+t.map(encodeURIComponent).join(`/`),new e(n)}withQuery(t){let n=new URL(this.#e.toString());for(let[e,r]of Object.entries(t))n.searchParams.delete(e),this.appendQueryValue(n.searchParams,e,r);return new e(n)}withQueryPatch(e){return this.withQuery(e)}appendQuery(t){let n=new URL(this.#e.toString());for(let[e,r]of Object.entries(t))this.appendQueryValue(n.searchParams,e,r);return new e(n)}withoutEmptyQuery(){let t=new URL(this.#e.toString()),n=new Set;for(let e of t.searchParams.keys())n.has(e)||(n.add(e),t.searchParams.getAll(e).every(e=>e===``)&&t.searchParams.delete(e));return new e(t)}withoutQuery(...t){let n=new URL(this.#e.toString());for(let e of t)n.searchParams.delete(e);return new e(n)}withHash(t){let n=new URL(this.#e.toString());return n.hash=t.startsWith(`#`)?t:`#${t}`,new e(n)}withoutHash(){let t=new URL(this.#e.toString());return t.hash=``,new e(t)}async fetch(e){return fetch(this.#e,e)}resolve(t){return new e(t,this)}equals(t){return this.toString()===new e(t).toString()}toURL(){return new URL(this.#e.toString())}toString(){return this.#e.toString()}valueOf(){return this.toString()}[Symbol.toPrimitive](){return this.toString()}static from(t,n){return new e(t,n)}static parse(t){return new e(t)}appendQueryValue(e,t,n){if(n!=null){if(Array.isArray(n)){for(let r of n)this.appendQueryValue(e,t,r);return}if(typeof n==`object`){try{e.append(t,JSON.stringify(n))}catch{e.append(t,String(n))}return}e.append(t,String(n))}}};exports.URLPath=t,exports.url=e;
package/dist/url.d.cts CHANGED
@@ -1,6 +1,15 @@
1
1
  //#region src/url.d.ts
2
+ /**
3
+ * Values accepted by {@link URLPath} constructors and helpers.
4
+ */
2
5
  type URLLike = string | URL | URLPath;
6
+ /**
7
+ * A single query parameter value (including nested and array values).
8
+ */
3
9
  type QueryValue = string | number | undefined | null | boolean | Array<QueryValue> | Record<string, any>;
10
+ /**
11
+ * Query-object shape used by URL query mutation helpers.
12
+ */
4
13
  type QueryObject = Record<string, QueryValue | QueryValue[]>;
5
14
  /**
6
15
  * Tagged-template helper for encoded URL path segments.
@@ -9,44 +18,186 @@ type QueryObject = Record<string, QueryValue | QueryValue[]>;
9
18
  * const path = url`/users/${userId}/posts/${postId}`;
10
19
  */
11
20
  declare function url(strings: TemplateStringsArray, ...values: unknown[]): string;
21
+ /**
22
+ * Immutable URL utility wrapper with convenience path/query operations.
23
+ */
12
24
  declare class URLPath {
13
25
  #private;
26
+ /**
27
+ * Creates a `URLPath` from a URL-like input and optional base URL.
28
+ *
29
+ * @param input URL value to parse.
30
+ * @param base Optional base URL for relative inputs.
31
+ */
14
32
  constructor(input: URLLike, base?: URLLike);
33
+ /**
34
+ * URL protocol including trailing `:`.
35
+ */
15
36
  get protocol(): string;
37
+ /**
38
+ * Host including port when present.
39
+ */
16
40
  get host(): string;
41
+ /**
42
+ * Hostname without port.
43
+ */
17
44
  get hostname(): string;
45
+ /**
46
+ * Port component, or an empty string when absent.
47
+ */
18
48
  get port(): string;
49
+ /**
50
+ * URL origin (`protocol + // + host`).
51
+ */
19
52
  get origin(): string;
53
+ /**
54
+ * Username component.
55
+ */
20
56
  get username(): string;
57
+ /**
58
+ * Password component.
59
+ */
21
60
  get password(): string;
61
+ /**
62
+ * Hash fragment including leading `#` when present.
63
+ */
22
64
  get hash(): string;
65
+ /**
66
+ * Search component including leading `?` when present.
67
+ */
23
68
  get search(): string;
69
+ /**
70
+ * Returns a copy of query parameters.
71
+ */
24
72
  get searchParams(): URLSearchParams;
73
+ /**
74
+ * URL pathname component.
75
+ */
25
76
  get pathname(): string;
77
+ /**
78
+ * Decoded pathname segments without empty parts.
79
+ */
26
80
  get parts(): string[];
81
+ /**
82
+ * Final path segment (decoded).
83
+ */
27
84
  get name(): string;
85
+ /**
86
+ * File suffix from {@link name}, including the leading dot.
87
+ */
28
88
  get suffix(): string;
89
+ /**
90
+ * File name without suffix from {@link name}.
91
+ */
29
92
  get stem(): string;
93
+ /**
94
+ * Parent path with the last path segment removed.
95
+ */
30
96
  get parent(): URLPath;
97
+ /**
98
+ * Appends path segments and returns a new URL.
99
+ *
100
+ * @param segments Segments to append.
101
+ */
31
102
  joinpath(...segments: string[]): URLPath;
103
+ /**
104
+ * Alias of {@link joinpath}.
105
+ *
106
+ * @param segments Segments to append.
107
+ */
32
108
  div(...segments: string[]): URLPath;
109
+ /**
110
+ * Creates a copy with replaced pathname parts.
111
+ *
112
+ * @param parts Decoded path parts.
113
+ */
33
114
  private withPath;
115
+ /**
116
+ * Replaces query parameter values for the provided keys.
117
+ *
118
+ * @param params Query values to set.
119
+ */
34
120
  withQuery(params: QueryObject): URLPath;
121
+ /**
122
+ * Alias of {@link withQuery}.
123
+ *
124
+ * @param params Query values to set.
125
+ */
35
126
  withQueryPatch(params: QueryObject): URLPath;
127
+ /**
128
+ * Appends query parameter values without deleting existing values.
129
+ *
130
+ * @param params Query values to append.
131
+ */
36
132
  appendQuery(params: QueryObject): URLPath;
133
+ /**
134
+ * Removes query keys whose values are entirely empty strings.
135
+ */
37
136
  withoutEmptyQuery(): URLPath;
137
+ /**
138
+ * Removes selected query keys.
139
+ *
140
+ * @param keys Query keys to remove.
141
+ */
38
142
  withoutQuery(...keys: string[]): URLPath;
143
+ /**
144
+ * Sets the hash fragment and returns a new URL.
145
+ *
146
+ * @param hash Hash value with or without leading `#`.
147
+ */
39
148
  withHash(hash: string): URLPath;
149
+ /**
150
+ * Removes the hash fragment.
151
+ */
40
152
  withoutHash(): URLPath;
153
+ /**
154
+ * Calls global `fetch` with this URL as input.
155
+ *
156
+ * @param init Optional fetch options.
157
+ */
41
158
  fetch(init?: RequestInit): Promise<Response>;
159
+ /**
160
+ * Resolves a relative URL against this URL.
161
+ *
162
+ * @param relative Relative URL/path.
163
+ */
42
164
  resolve(relative: string): URLPath;
165
+ /**
166
+ * Compares URLs by normalized string value.
167
+ *
168
+ * @param other URL to compare.
169
+ */
43
170
  equals(other: URLLike): boolean;
171
+ /**
172
+ * Returns a new native `URL` instance.
173
+ */
44
174
  toURL(): URL;
175
+ /**
176
+ * Returns the URL as a string.
177
+ */
45
178
  toString(): string;
179
+ /**
180
+ * Primitive value representation.
181
+ */
46
182
  valueOf(): string;
183
+ /**
184
+ * Primitive coercion hook.
185
+ */
47
186
  [Symbol.toPrimitive](): string;
187
+ /**
188
+ * Creates a `URLPath` from URL-like input.
189
+ *
190
+ * @param input URL value to parse.
191
+ * @param base Optional base URL for relative inputs.
192
+ */
48
193
  static from(input: URLLike, base?: URLLike): URLPath;
194
+ /**
195
+ * Parses an absolute URL string.
196
+ *
197
+ * @param input URL string to parse.
198
+ */
49
199
  static parse(input: string): URLPath;
200
+ private appendQueryValue;
50
201
  }
51
202
  //#endregion
52
203
  export { QueryObject, QueryValue, URLLike, URLPath, url };