@forthtilliath/ts-kit 0.2.0 → 0.4.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/README.md +104 -19
- package/dist/array/getMostRecentIds.d.ts +21 -0
- package/dist/array/getMostRecentIds.d.ts.map +1 -0
- package/dist/array/getMostRecentIds.js +30 -0
- package/dist/array/index.d.ts +3 -0
- package/dist/array/index.d.ts.map +1 -1
- package/dist/array/index.js +3 -0
- package/dist/array/nextInCycle.d.ts +15 -0
- package/dist/array/nextInCycle.d.ts.map +1 -0
- package/dist/array/nextInCycle.js +19 -0
- package/dist/array/rankByNameMatch.d.ts +19 -0
- package/dist/array/rankByNameMatch.d.ts.map +1 -0
- package/dist/array/rankByNameMatch.js +45 -0
- package/dist/async/debounce.d.ts +20 -0
- package/dist/async/debounce.d.ts.map +1 -0
- package/dist/async/debounce.js +44 -0
- package/dist/async/index.d.ts +7 -0
- package/dist/async/index.d.ts.map +1 -0
- package/dist/async/index.js +6 -0
- package/dist/async/memoize.d.ts +19 -0
- package/dist/async/memoize.d.ts.map +1 -0
- package/dist/async/memoize.js +25 -0
- package/dist/async/retry.d.ts +25 -0
- package/dist/async/retry.d.ts.map +1 -0
- package/dist/async/retry.js +33 -0
- package/dist/async/sleep.d.ts +9 -0
- package/dist/async/sleep.d.ts.map +1 -0
- package/dist/async/sleep.js +10 -0
- package/dist/async/throttle.d.ts +20 -0
- package/dist/async/throttle.d.ts.map +1 -0
- package/dist/async/throttle.js +43 -0
- package/dist/async/withTimeout.d.ts +19 -0
- package/dist/async/withTimeout.d.ts.map +1 -0
- package/dist/async/withTimeout.js +34 -0
- package/dist/classes/array.d.ts +88 -0
- package/dist/classes/array.d.ts.map +1 -1
- package/dist/classes/array.js +74 -0
- package/dist/classes/index.d.ts +2 -0
- package/dist/classes/index.d.ts.map +1 -0
- package/dist/classes/index.js +1 -0
- package/dist/date/formatRelativeTime.d.ts +13 -0
- package/dist/date/formatRelativeTime.d.ts.map +1 -0
- package/dist/date/formatRelativeTime.js +30 -0
- package/dist/date/getPeriodStartMs.d.ts +16 -0
- package/dist/date/getPeriodStartMs.d.ts.map +1 -0
- package/dist/date/getPeriodStartMs.js +24 -0
- package/dist/date/index.d.ts +5 -0
- package/dist/date/index.d.ts.map +1 -0
- package/dist/date/index.js +4 -0
- package/dist/date/isSameDay.d.ts +11 -0
- package/dist/date/isSameDay.d.ts.map +1 -0
- package/dist/date/isSameDay.js +14 -0
- package/dist/date/startOfDay.d.ts +10 -0
- package/dist/date/startOfDay.d.ts.map +1 -0
- package/dist/date/startOfDay.js +13 -0
- package/dist/files/index.d.ts +2 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/number/clamp.d.ts +13 -0
- package/dist/number/clamp.d.ts.map +1 -0
- package/dist/number/clamp.js +14 -0
- package/dist/number/formatBytes.d.ts +12 -0
- package/dist/number/formatBytes.d.ts.map +1 -0
- package/dist/number/formatBytes.js +19 -0
- package/dist/number/formatCsvNumber.d.ts +14 -0
- package/dist/number/formatCsvNumber.d.ts.map +1 -0
- package/dist/number/formatCsvNumber.js +15 -0
- package/dist/number/formatDuration.d.ts +12 -0
- package/dist/number/formatDuration.d.ts.map +1 -0
- package/dist/number/formatDuration.js +29 -0
- package/dist/number/index.d.ts +6 -0
- package/dist/number/index.d.ts.map +1 -0
- package/dist/number/index.js +5 -0
- package/dist/number/round.d.ts +12 -0
- package/dist/number/round.d.ts.map +1 -0
- package/dist/number/round.js +14 -0
- package/dist/object/deepClone.d.ts +12 -0
- package/dist/object/deepClone.d.ts.map +1 -0
- package/dist/object/deepClone.js +16 -0
- package/dist/object/deepEqual.d.ts +12 -0
- package/dist/object/deepEqual.d.ts.map +1 -0
- package/dist/object/deepEqual.js +31 -0
- package/dist/object/groupBy.d.ts +12 -0
- package/dist/object/groupBy.d.ts.map +1 -0
- package/dist/object/groupBy.js +18 -0
- package/dist/object/index.d.ts +8 -0
- package/dist/object/index.d.ts.map +1 -0
- package/dist/object/index.js +7 -0
- package/dist/object/mapValues.d.ts +11 -0
- package/dist/object/mapValues.d.ts.map +1 -0
- package/dist/object/mapValues.js +16 -0
- package/dist/object/omit.d.ts +11 -0
- package/dist/object/omit.d.ts.map +1 -0
- package/dist/object/omit.js +16 -0
- package/dist/object/pick.d.ts +11 -0
- package/dist/object/pick.d.ts.map +1 -0
- package/dist/object/pick.js +18 -0
- package/dist/object/uniqueBy.d.ts +13 -0
- package/dist/object/uniqueBy.d.ts.map +1 -0
- package/dist/object/uniqueBy.js +23 -0
- package/dist/string/capitalize.d.ts +11 -0
- package/dist/string/capitalize.d.ts.map +1 -0
- package/dist/string/capitalize.js +14 -0
- package/dist/string/escapeCsvField.d.ts +14 -0
- package/dist/string/escapeCsvField.d.ts.map +1 -0
- package/dist/string/escapeCsvField.js +17 -0
- package/dist/string/escapeHtml.d.ts +12 -0
- package/dist/string/escapeHtml.d.ts.map +1 -0
- package/dist/string/escapeHtml.js +17 -0
- package/dist/string/index.d.ts +8 -0
- package/dist/string/index.d.ts.map +1 -0
- package/dist/string/index.js +7 -0
- package/dist/string/normalizeForSearch.d.ts +12 -0
- package/dist/string/normalizeForSearch.d.ts.map +1 -0
- package/dist/string/normalizeForSearch.js +25 -0
- package/dist/string/pluralize.d.ts +17 -0
- package/dist/string/pluralize.d.ts.map +1 -0
- package/dist/string/pluralize.js +26 -0
- package/dist/string/slugify.d.ts +12 -0
- package/dist/string/slugify.d.ts.map +1 -0
- package/dist/string/slugify.js +18 -0
- package/dist/string/truncate.d.ts +13 -0
- package/dist/string/truncate.d.ts.map +1 -0
- package/dist/string/truncate.js +17 -0
- package/package.json +3 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by {@link withTimeout} when the wrapped promise does not settle in
|
|
3
|
+
* time.
|
|
4
|
+
*/
|
|
5
|
+
export declare class TimeoutError extends Error {
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Rejects with a {@link TimeoutError} if `promise` has not settled within
|
|
10
|
+
* `ms` milliseconds.
|
|
11
|
+
*
|
|
12
|
+
* @param promise - The promise to race against the timeout.
|
|
13
|
+
* @param ms - The timeout in milliseconds.
|
|
14
|
+
* @param message - Optional error message (defaults to a generic one).
|
|
15
|
+
* @example
|
|
16
|
+
* await withTimeout(fetch("/api"), 5000);
|
|
17
|
+
*/
|
|
18
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
19
|
+
//# sourceMappingURL=withTimeout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withTimeout.d.ts","sourceRoot":"","sources":["../../src/async/withTimeout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,SAAwB;CAI5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by {@link withTimeout} when the wrapped promise does not settle in
|
|
3
|
+
* time.
|
|
4
|
+
*/
|
|
5
|
+
export class TimeoutError extends Error {
|
|
6
|
+
constructor(message = "Operation timed out") {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "TimeoutError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Rejects with a {@link TimeoutError} if `promise` has not settled within
|
|
13
|
+
* `ms` milliseconds.
|
|
14
|
+
*
|
|
15
|
+
* @param promise - The promise to race against the timeout.
|
|
16
|
+
* @param ms - The timeout in milliseconds.
|
|
17
|
+
* @param message - Optional error message (defaults to a generic one).
|
|
18
|
+
* @example
|
|
19
|
+
* await withTimeout(fetch("/api"), 5000);
|
|
20
|
+
*/
|
|
21
|
+
export function withTimeout(promise, ms, message) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const timer = setTimeout(() => {
|
|
24
|
+
reject(new TimeoutError(message));
|
|
25
|
+
}, ms);
|
|
26
|
+
promise.then((value) => {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
resolve(value);
|
|
29
|
+
}, (error) => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
package/dist/classes/array.d.ts
CHANGED
|
@@ -49,5 +49,93 @@ export declare class FArray<T> extends Array<T> {
|
|
|
49
49
|
* }
|
|
50
50
|
*/
|
|
51
51
|
includes<S>(searchElement: S | T, fromIndex?: number): searchElement is S & T;
|
|
52
|
+
/**
|
|
53
|
+
* Same as `Array.indexOf`, but accepts a search value outside of `T`
|
|
54
|
+
* instead of rejecting it at compile-time (the native typings only accept
|
|
55
|
+
* `T`, exactly like `Array.includes` before the override above).
|
|
56
|
+
*
|
|
57
|
+
* @param searchElement The value to search for — no longer restricted to `T`.
|
|
58
|
+
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
|
59
|
+
* @returns The index of the first match, or -1 if not found.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Normal operation of Array.indexOf
|
|
63
|
+
* const buz = "buz";
|
|
64
|
+
* type FBB = "foo" | "bar" | "baz";
|
|
65
|
+
* const arr: FBB[] = ["foo", "bar", "baz"];
|
|
66
|
+
* arr.indexOf(buz);
|
|
67
|
+
* // -----------^
|
|
68
|
+
* // The argument of type 'buz' is not assignable to the parameter of type 'FBB'.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // FArray.indexOf
|
|
72
|
+
* const buz = "buz";
|
|
73
|
+
* type FBB = "foo" | "bar" | "baz";
|
|
74
|
+
* const arr = new FArray<FBB>("foo", "bar", "baz");
|
|
75
|
+
* arr.indexOf(buz); // compiles fine, returns -1
|
|
76
|
+
*/
|
|
77
|
+
indexOf(searchElement: unknown, fromIndex?: number): number;
|
|
78
|
+
/**
|
|
79
|
+
* Same as `Array.lastIndexOf`, but accepts a search value outside of `T`
|
|
80
|
+
* instead of rejecting it at compile-time. See {@link FArray.indexOf}.
|
|
81
|
+
*
|
|
82
|
+
* @param searchElement The value to search for — no longer restricted to `T`.
|
|
83
|
+
* @param fromIndex The position in this array at which to start searching backwards. Defaults to the last index, like the native method.
|
|
84
|
+
* @returns The index of the last match, or -1 if not found.
|
|
85
|
+
*/
|
|
86
|
+
lastIndexOf(searchElement: unknown, fromIndex?: number): number;
|
|
87
|
+
/**
|
|
88
|
+
* Same as `Array.filter`, but recognizes the `Boolean` global constructor
|
|
89
|
+
* as a type guard — the native typings don't, so `arr.filter(Boolean)`
|
|
90
|
+
* keeps `null`/`undefined` in the result's element type even though
|
|
91
|
+
* they're removed at runtime.
|
|
92
|
+
*
|
|
93
|
+
* Note: like the native runtime behavior, this also drops other falsy
|
|
94
|
+
* values (`0`, `""`, `NaN`, `false`) — but the type only reflects the
|
|
95
|
+
* removal of `null`/`undefined`, since narrowing those further would
|
|
96
|
+
* require them to be literal members of `T`.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* // Normal operation of Array.filter
|
|
100
|
+
* const arr: (number | null | undefined)[] = [1, null, 2, undefined];
|
|
101
|
+
* const result = arr.filter(Boolean); // still (number | null | undefined)[]
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* // FArray.filter
|
|
105
|
+
* const arr = new FArray<number | null | undefined>(1, null, 2, undefined);
|
|
106
|
+
* const result = arr.filter(Boolean); // FArray<number>
|
|
107
|
+
*/
|
|
108
|
+
filter(predicate: BooleanConstructor): FArray<NonNullable<T>>;
|
|
109
|
+
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: unknown): FArray<S>;
|
|
110
|
+
filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: unknown): FArray<T>;
|
|
111
|
+
/**
|
|
112
|
+
* Same as `Array.from`, but returns an `FArray` — the native typings
|
|
113
|
+
* return a plain `T[]`/`U[]` even though `Array.from` (and `Array.of`
|
|
114
|
+
* below) already construct an instance of the calling class at runtime.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* const fromPlain = FArray.from([1, 2, 3]); // FArray<number>, not number[]
|
|
118
|
+
*/
|
|
119
|
+
static from<T>(iterable: Iterable<T> | ArrayLike<T>): FArray<T>;
|
|
120
|
+
static from<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: unknown): FArray<U>;
|
|
121
|
+
/**
|
|
122
|
+
* Same as `Array.of`, but returns an `FArray`. See {@link FArray.from}.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* const fa = FArray.of(1, 2, 3); // FArray<number>, not number[]
|
|
126
|
+
*/
|
|
127
|
+
static of<T>(...items: T[]): FArray<T>;
|
|
128
|
+
/**
|
|
129
|
+
* Converts this `FArray` back into a plain `Array` instance — the
|
|
130
|
+
* reverse of {@link FArray.from}/{@link FArray.of}. `FArray` is already
|
|
131
|
+
* assignable to `T[]` anywhere a plain array is expected (it extends
|
|
132
|
+
* `Array`), so this is mostly useful when the runtime type matters too
|
|
133
|
+
* (e.g. a library that special-cases `Array` and rejects subclasses).
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* const fa = new FArray(1, 2, 3);
|
|
137
|
+
* const plain = fa.toArray(); // Array(3) [1, 2, 3], not instanceof FArray
|
|
138
|
+
*/
|
|
139
|
+
toArray(): T[];
|
|
52
140
|
}
|
|
53
141
|
//# sourceMappingURL=array.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/classes/array.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,CAAC,CAAC;IACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACH,QAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,SAAI,GAAG,aAAa,IAAI,CAAC,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/classes/array.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,CAAC,CAAC;IACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACH,QAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,SAAI,GAAG,aAAa,IAAI,CAAC,GAAG,CAAC;IAKxE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,OAAO,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,SAAI,GAAG,MAAM;IAKtD;;;;;;;OAOG;IACH,WAAW,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAS/D;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,SAAS,EAAE,kBAAkB,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,CAAC,SAAS,CAAC,EAChB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,EAC9D,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,CAAC,CAAC,CAAC;IACZ,MAAM,CACJ,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,EAC3D,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,CAAC,CAAC,CAAC;IAQZ;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EACd,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EACpC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC,EAC7B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,CAAC,CAAC,CAAC;IAWZ;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IAItC;;;;;;;;;;OAUG;IACH,OAAO,IAAI,CAAC,EAAE;CAGf"}
|
package/dist/classes/array.js
CHANGED
|
@@ -52,4 +52,78 @@ export class FArray extends Array {
|
|
|
52
52
|
// @ts-expect-error searchElement is unknown
|
|
53
53
|
return super.includes(searchElement, fromIndex);
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Same as `Array.indexOf`, but accepts a search value outside of `T`
|
|
57
|
+
* instead of rejecting it at compile-time (the native typings only accept
|
|
58
|
+
* `T`, exactly like `Array.includes` before the override above).
|
|
59
|
+
*
|
|
60
|
+
* @param searchElement The value to search for — no longer restricted to `T`.
|
|
61
|
+
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
|
62
|
+
* @returns The index of the first match, or -1 if not found.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Normal operation of Array.indexOf
|
|
66
|
+
* const buz = "buz";
|
|
67
|
+
* type FBB = "foo" | "bar" | "baz";
|
|
68
|
+
* const arr: FBB[] = ["foo", "bar", "baz"];
|
|
69
|
+
* arr.indexOf(buz);
|
|
70
|
+
* // -----------^
|
|
71
|
+
* // The argument of type 'buz' is not assignable to the parameter of type 'FBB'.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // FArray.indexOf
|
|
75
|
+
* const buz = "buz";
|
|
76
|
+
* type FBB = "foo" | "bar" | "baz";
|
|
77
|
+
* const arr = new FArray<FBB>("foo", "bar", "baz");
|
|
78
|
+
* arr.indexOf(buz); // compiles fine, returns -1
|
|
79
|
+
*/
|
|
80
|
+
indexOf(searchElement, fromIndex = 0) {
|
|
81
|
+
// @ts-expect-error searchElement is unknown
|
|
82
|
+
return super.indexOf(searchElement, fromIndex);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Same as `Array.lastIndexOf`, but accepts a search value outside of `T`
|
|
86
|
+
* instead of rejecting it at compile-time. See {@link FArray.indexOf}.
|
|
87
|
+
*
|
|
88
|
+
* @param searchElement The value to search for — no longer restricted to `T`.
|
|
89
|
+
* @param fromIndex The position in this array at which to start searching backwards. Defaults to the last index, like the native method.
|
|
90
|
+
* @returns The index of the last match, or -1 if not found.
|
|
91
|
+
*/
|
|
92
|
+
lastIndexOf(searchElement, fromIndex) {
|
|
93
|
+
if (fromIndex === undefined) {
|
|
94
|
+
// @ts-expect-error searchElement is unknown
|
|
95
|
+
return super.lastIndexOf(searchElement);
|
|
96
|
+
}
|
|
97
|
+
// @ts-expect-error searchElement is unknown
|
|
98
|
+
return super.lastIndexOf(searchElement, fromIndex);
|
|
99
|
+
}
|
|
100
|
+
filter(predicate, thisArg) {
|
|
101
|
+
return super.filter(predicate, thisArg);
|
|
102
|
+
}
|
|
103
|
+
static from(iterable, mapfn, thisArg) {
|
|
104
|
+
return (mapfn ? super.from(iterable, mapfn, thisArg) : super.from(iterable));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Same as `Array.of`, but returns an `FArray`. See {@link FArray.from}.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* const fa = FArray.of(1, 2, 3); // FArray<number>, not number[]
|
|
111
|
+
*/
|
|
112
|
+
static of(...items) {
|
|
113
|
+
return super.of(...items);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Converts this `FArray` back into a plain `Array` instance — the
|
|
117
|
+
* reverse of {@link FArray.from}/{@link FArray.of}. `FArray` is already
|
|
118
|
+
* assignable to `T[]` anywhere a plain array is expected (it extends
|
|
119
|
+
* `Array`), so this is mostly useful when the runtime type matters too
|
|
120
|
+
* (e.g. a library that special-cases `Array` and rejects subclasses).
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* const fa = new FArray(1, 2, 3);
|
|
124
|
+
* const plain = fa.toArray(); // Array(3) [1, 2, 3], not instanceof FArray
|
|
125
|
+
*/
|
|
126
|
+
toArray() {
|
|
127
|
+
return [...this];
|
|
128
|
+
}
|
|
55
129
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/classes/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./array.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats the difference between two dates as a human-readable relative
|
|
3
|
+
* string ("3 hours ago", "in 2 days"), backed by `Intl.RelativeTimeFormat`.
|
|
4
|
+
*
|
|
5
|
+
* @param date - The date to describe.
|
|
6
|
+
* @param baseDate - The reference date to compare against (defaults to now).
|
|
7
|
+
* @param locale - The locale to format with (defaults to `"en"`).
|
|
8
|
+
* @returns The formatted relative time.
|
|
9
|
+
* @example
|
|
10
|
+
* formatRelativeTime(new Date(Date.now() - 3_600_000)); // => "1 hour ago"
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatRelativeTime(date: Date, baseDate?: Date, locale?: string): string;
|
|
13
|
+
//# sourceMappingURL=formatRelativeTime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatRelativeTime.d.ts","sourceRoot":"","sources":["../../src/date/formatRelativeTime.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,QAAQ,GAAE,IAAiB,EAC3B,MAAM,SAAO,GACZ,MAAM,CAWR"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const UNITS = [
|
|
2
|
+
{ unit: "year", ms: 365 * 24 * 60 * 60 * 1000 },
|
|
3
|
+
{ unit: "month", ms: 30 * 24 * 60 * 60 * 1000 },
|
|
4
|
+
{ unit: "week", ms: 7 * 24 * 60 * 60 * 1000 },
|
|
5
|
+
{ unit: "day", ms: 24 * 60 * 60 * 1000 },
|
|
6
|
+
{ unit: "hour", ms: 60 * 60 * 1000 },
|
|
7
|
+
{ unit: "minute", ms: 60 * 1000 },
|
|
8
|
+
{ unit: "second", ms: 1000 },
|
|
9
|
+
];
|
|
10
|
+
/**
|
|
11
|
+
* Formats the difference between two dates as a human-readable relative
|
|
12
|
+
* string ("3 hours ago", "in 2 days"), backed by `Intl.RelativeTimeFormat`.
|
|
13
|
+
*
|
|
14
|
+
* @param date - The date to describe.
|
|
15
|
+
* @param baseDate - The reference date to compare against (defaults to now).
|
|
16
|
+
* @param locale - The locale to format with (defaults to `"en"`).
|
|
17
|
+
* @returns The formatted relative time.
|
|
18
|
+
* @example
|
|
19
|
+
* formatRelativeTime(new Date(Date.now() - 3_600_000)); // => "1 hour ago"
|
|
20
|
+
*/
|
|
21
|
+
export function formatRelativeTime(date, baseDate = new Date(), locale = "en") {
|
|
22
|
+
const diffMs = date.getTime() - baseDate.getTime();
|
|
23
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
24
|
+
for (const { unit, ms } of UNITS) {
|
|
25
|
+
if (Math.abs(diffMs) >= ms || unit === "second") {
|
|
26
|
+
return rtf.format(Math.round(diffMs / ms), unit);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return rtf.format(0, "second");
|
|
30
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type PeriodFilter = "all" | "today" | "7d" | "30d";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the timestamp (ms) from which a record is included for a given
|
|
4
|
+
* period filter, or `null` for `"all"` (no date filter). `"today"` starts at
|
|
5
|
+
* the current calendar day, not a rolling 24h window.
|
|
6
|
+
*
|
|
7
|
+
* @param period - The period filter.
|
|
8
|
+
* @param now - The reference date. Defaults to `new Date()`.
|
|
9
|
+
* @returns The period's start timestamp in ms, or `null` for `"all"`.
|
|
10
|
+
* @example
|
|
11
|
+
* getPeriodStartMs("today"); // => start of today, local time, in ms
|
|
12
|
+
* getPeriodStartMs("7d"); // => now minus 7 days, in ms
|
|
13
|
+
* getPeriodStartMs("all"); // => null
|
|
14
|
+
*/
|
|
15
|
+
export declare function getPeriodStartMs(period: PeriodFilter, now?: Date): number | null;
|
|
16
|
+
//# sourceMappingURL=getPeriodStartMs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getPeriodStartMs.d.ts","sourceRoot":"","sources":["../../src/date/getPeriodStartMs.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,GAAG,OAAa,GACf,MAAM,GAAG,IAAI,CASf"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the timestamp (ms) from which a record is included for a given
|
|
3
|
+
* period filter, or `null` for `"all"` (no date filter). `"today"` starts at
|
|
4
|
+
* the current calendar day, not a rolling 24h window.
|
|
5
|
+
*
|
|
6
|
+
* @param period - The period filter.
|
|
7
|
+
* @param now - The reference date. Defaults to `new Date()`.
|
|
8
|
+
* @returns The period's start timestamp in ms, or `null` for `"all"`.
|
|
9
|
+
* @example
|
|
10
|
+
* getPeriodStartMs("today"); // => start of today, local time, in ms
|
|
11
|
+
* getPeriodStartMs("7d"); // => now minus 7 days, in ms
|
|
12
|
+
* getPeriodStartMs("all"); // => null
|
|
13
|
+
*/
|
|
14
|
+
export function getPeriodStartMs(period, now = new Date()) {
|
|
15
|
+
if (period === "all")
|
|
16
|
+
return null;
|
|
17
|
+
if (period === "today") {
|
|
18
|
+
const startOfDay = new Date(now);
|
|
19
|
+
startOfDay.setHours(0, 0, 0, 0);
|
|
20
|
+
return startOfDay.getTime();
|
|
21
|
+
}
|
|
22
|
+
const days = period === "7d" ? 7 : 30;
|
|
23
|
+
return now.getTime() - days * 24 * 60 * 60 * 1000;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether two dates fall on the same local calendar day.
|
|
3
|
+
*
|
|
4
|
+
* @param a - The first date.
|
|
5
|
+
* @param b - The second date.
|
|
6
|
+
* @returns `true` if both dates share the same year, month and day.
|
|
7
|
+
* @example
|
|
8
|
+
* isSameDay(new Date("2026-03-14T08:00"), new Date("2026-03-14T22:00")); // => true
|
|
9
|
+
*/
|
|
10
|
+
export declare function isSameDay(a: Date, b: Date): boolean;
|
|
11
|
+
//# sourceMappingURL=isSameDay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isSameDay.d.ts","sourceRoot":"","sources":["../../src/date/isSameDay.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAMnD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether two dates fall on the same local calendar day.
|
|
3
|
+
*
|
|
4
|
+
* @param a - The first date.
|
|
5
|
+
* @param b - The second date.
|
|
6
|
+
* @returns `true` if both dates share the same year, month and day.
|
|
7
|
+
* @example
|
|
8
|
+
* isSameDay(new Date("2026-03-14T08:00"), new Date("2026-03-14T22:00")); // => true
|
|
9
|
+
*/
|
|
10
|
+
export function isSameDay(a, b) {
|
|
11
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
12
|
+
a.getMonth() === b.getMonth() &&
|
|
13
|
+
a.getDate() === b.getDate());
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a new `Date` set to midnight (00:00:00.000) of the same local day.
|
|
3
|
+
*
|
|
4
|
+
* @param date - The reference date (defaults to now).
|
|
5
|
+
* @returns A new `Date` at the start of that day.
|
|
6
|
+
* @example
|
|
7
|
+
* startOfDay(new Date("2026-03-14T18:30:00")); // => 2026-03-14T00:00:00.000
|
|
8
|
+
*/
|
|
9
|
+
export declare function startOfDay(date?: Date): Date;
|
|
10
|
+
//# sourceMappingURL=startOfDay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startOfDay.d.ts","sourceRoot":"","sources":["../../src/date/startOfDay.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,IAAiB,GAAG,IAAI,CAIxD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a new `Date` set to midnight (00:00:00.000) of the same local day.
|
|
3
|
+
*
|
|
4
|
+
* @param date - The reference date (defaults to now).
|
|
5
|
+
* @returns A new `Date` at the start of that day.
|
|
6
|
+
* @example
|
|
7
|
+
* startOfDay(new Date("2026-03-14T18:30:00")); // => 2026-03-14T00:00:00.000
|
|
8
|
+
*/
|
|
9
|
+
export function startOfDay(date = new Date()) {
|
|
10
|
+
const result = new Date(date);
|
|
11
|
+
result.setHours(0, 0, 0, 0);
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./downloadText.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from "./array/index.js";
|
|
2
|
+
export * from "./async/index.js";
|
|
3
|
+
export * from "./classes/index.js";
|
|
4
|
+
export * from "./date/index.js";
|
|
5
|
+
export * from "./files/index.js";
|
|
6
|
+
export * from "./id/index.js";
|
|
7
|
+
export * from "./maths/index.js";
|
|
8
|
+
export * from "./number/index.js";
|
|
9
|
+
export * from "./object/index.js";
|
|
10
|
+
export * from "./string/index.js";
|
|
2
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
// Barrel: re-exports every category so consumers can do a single
|
|
2
|
+
// import { chunk, pick, sleep, clamp } from "@forthtilliath/ts-kit";
|
|
3
|
+
// instead of one import line per module. Subpath imports
|
|
4
|
+
// (`@forthtilliath/ts-kit/array/chunk`) still work if you want to keep
|
|
5
|
+
// bundles minimal, but this is the default, low-friction entry point.
|
|
6
|
+
export * from "./array/index.js";
|
|
7
|
+
export * from "./async/index.js";
|
|
8
|
+
export * from "./classes/index.js";
|
|
9
|
+
export * from "./date/index.js";
|
|
10
|
+
export * from "./files/index.js";
|
|
11
|
+
export * from "./id/index.js";
|
|
12
|
+
export * from "./maths/index.js";
|
|
13
|
+
export * from "./number/index.js";
|
|
14
|
+
export * from "./object/index.js";
|
|
15
|
+
export * from "./string/index.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamps a number between a minimum and maximum value.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The value to clamp.
|
|
5
|
+
* @param min - The lower bound.
|
|
6
|
+
* @param max - The upper bound.
|
|
7
|
+
* @returns `value`, or the nearest bound if it falls outside `[min, max]`.
|
|
8
|
+
* @example
|
|
9
|
+
* clamp(15, 0, 10); // => 10
|
|
10
|
+
* clamp(-5, 0, 10); // => 0
|
|
11
|
+
*/
|
|
12
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
13
|
+
//# sourceMappingURL=clamp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clamp.d.ts","sourceRoot":"","sources":["../../src/number/clamp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamps a number between a minimum and maximum value.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The value to clamp.
|
|
5
|
+
* @param min - The lower bound.
|
|
6
|
+
* @param max - The upper bound.
|
|
7
|
+
* @returns `value`, or the nearest bound if it falls outside `[min, max]`.
|
|
8
|
+
* @example
|
|
9
|
+
* clamp(15, 0, 10); // => 10
|
|
10
|
+
* clamp(-5, 0, 10); // => 0
|
|
11
|
+
*/
|
|
12
|
+
export function clamp(value, min, max) {
|
|
13
|
+
return Math.min(Math.max(value, min), max);
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a byte count as a human-readable string (`"1.5 MB"`).
|
|
3
|
+
*
|
|
4
|
+
* @param bytes - The number of bytes.
|
|
5
|
+
* @param decimals - The number of decimal places to keep (default: 2).
|
|
6
|
+
* @returns The formatted string.
|
|
7
|
+
* @example
|
|
8
|
+
* formatBytes(1536); // => "1.5 KB"
|
|
9
|
+
* formatBytes(0); // => "0 B"
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatBytes(bytes: number, decimals?: number): string;
|
|
12
|
+
//# sourceMappingURL=formatBytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatBytes.d.ts","sourceRoot":"","sources":["../../src/number/formatBytes.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAW/D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const UNITS = ["B", "KB", "MB", "GB", "TB", "PB"];
|
|
2
|
+
/**
|
|
3
|
+
* Formats a byte count as a human-readable string (`"1.5 MB"`).
|
|
4
|
+
*
|
|
5
|
+
* @param bytes - The number of bytes.
|
|
6
|
+
* @param decimals - The number of decimal places to keep (default: 2).
|
|
7
|
+
* @returns The formatted string.
|
|
8
|
+
* @example
|
|
9
|
+
* formatBytes(1536); // => "1.5 KB"
|
|
10
|
+
* formatBytes(0); // => "0 B"
|
|
11
|
+
*/
|
|
12
|
+
export function formatBytes(bytes, decimals = 2) {
|
|
13
|
+
if (bytes === 0)
|
|
14
|
+
return "0 B";
|
|
15
|
+
const exponent = Math.min(Math.floor(Math.log(Math.abs(bytes)) / Math.log(1024)), UNITS.length - 1);
|
|
16
|
+
const value = bytes / 1024 ** exponent;
|
|
17
|
+
const formatted = value.toFixed(Math.max(decimals, 0)).replace(/\.?0+$/, "");
|
|
18
|
+
return `${formatted} ${UNITS[exponent]}`;
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a number as a raw value (no unit suffix) for use in a spreadsheet
|
|
3
|
+
* (sum, average...), with a comma decimal separator as expected by
|
|
4
|
+
* French-locale spreadsheets instead of JS's dot.
|
|
5
|
+
*
|
|
6
|
+
* @param value - The number to format.
|
|
7
|
+
* @param decimals - Number of decimal places. Defaults to `1`.
|
|
8
|
+
* @returns The formatted number, comma as decimal separator.
|
|
9
|
+
* @example
|
|
10
|
+
* formatCsvNumber(1.5); // => "1,5"
|
|
11
|
+
* formatCsvNumber(12.345, 2); // => "12,35"
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatCsvNumber(value: number, decimals?: number): string;
|
|
14
|
+
//# sourceMappingURL=formatCsvNumber.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatCsvNumber.d.ts","sourceRoot":"","sources":["../../src/number/formatCsvNumber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a number as a raw value (no unit suffix) for use in a spreadsheet
|
|
3
|
+
* (sum, average...), with a comma decimal separator as expected by
|
|
4
|
+
* French-locale spreadsheets instead of JS's dot.
|
|
5
|
+
*
|
|
6
|
+
* @param value - The number to format.
|
|
7
|
+
* @param decimals - Number of decimal places. Defaults to `1`.
|
|
8
|
+
* @returns The formatted number, comma as decimal separator.
|
|
9
|
+
* @example
|
|
10
|
+
* formatCsvNumber(1.5); // => "1,5"
|
|
11
|
+
* formatCsvNumber(12.345, 2); // => "12,35"
|
|
12
|
+
*/
|
|
13
|
+
export function formatCsvNumber(value, decimals = 1) {
|
|
14
|
+
return value.toFixed(decimals).replace(".", ",");
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a duration in milliseconds as a human-readable string
|
|
3
|
+
* (`"1d 1h 1m 1s"`, `"500ms"`).
|
|
4
|
+
*
|
|
5
|
+
* @param ms - The duration in milliseconds.
|
|
6
|
+
* @returns The formatted string.
|
|
7
|
+
* @example
|
|
8
|
+
* formatDuration(90_061_000); // => "1d 1h 1m 1s"
|
|
9
|
+
* formatDuration(500); // => "500ms"
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatDuration(ms: number): string;
|
|
12
|
+
//# sourceMappingURL=formatDuration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDuration.d.ts","sourceRoot":"","sources":["../../src/number/formatDuration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAgBjD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a duration in milliseconds as a human-readable string
|
|
3
|
+
* (`"1d 1h 1m 1s"`, `"500ms"`).
|
|
4
|
+
*
|
|
5
|
+
* @param ms - The duration in milliseconds.
|
|
6
|
+
* @returns The formatted string.
|
|
7
|
+
* @example
|
|
8
|
+
* formatDuration(90_061_000); // => "1d 1h 1m 1s"
|
|
9
|
+
* formatDuration(500); // => "500ms"
|
|
10
|
+
*/
|
|
11
|
+
export function formatDuration(ms) {
|
|
12
|
+
if (ms < 1000)
|
|
13
|
+
return `${Math.round(ms)}ms`;
|
|
14
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
15
|
+
const days = Math.floor(totalSeconds / 86400);
|
|
16
|
+
const hours = Math.floor((totalSeconds % 86400) / 3600);
|
|
17
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
18
|
+
const seconds = totalSeconds % 60;
|
|
19
|
+
const parts = [];
|
|
20
|
+
if (days > 0)
|
|
21
|
+
parts.push(`${days}d`);
|
|
22
|
+
if (hours > 0)
|
|
23
|
+
parts.push(`${hours}h`);
|
|
24
|
+
if (minutes > 0)
|
|
25
|
+
parts.push(`${minutes}m`);
|
|
26
|
+
if (seconds > 0 || parts.length === 0)
|
|
27
|
+
parts.push(`${seconds}s`);
|
|
28
|
+
return parts.join(" ");
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/number/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
|