@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.
Files changed (128) hide show
  1. package/README.md +104 -19
  2. package/dist/array/getMostRecentIds.d.ts +21 -0
  3. package/dist/array/getMostRecentIds.d.ts.map +1 -0
  4. package/dist/array/getMostRecentIds.js +30 -0
  5. package/dist/array/index.d.ts +3 -0
  6. package/dist/array/index.d.ts.map +1 -1
  7. package/dist/array/index.js +3 -0
  8. package/dist/array/nextInCycle.d.ts +15 -0
  9. package/dist/array/nextInCycle.d.ts.map +1 -0
  10. package/dist/array/nextInCycle.js +19 -0
  11. package/dist/array/rankByNameMatch.d.ts +19 -0
  12. package/dist/array/rankByNameMatch.d.ts.map +1 -0
  13. package/dist/array/rankByNameMatch.js +45 -0
  14. package/dist/async/debounce.d.ts +20 -0
  15. package/dist/async/debounce.d.ts.map +1 -0
  16. package/dist/async/debounce.js +44 -0
  17. package/dist/async/index.d.ts +7 -0
  18. package/dist/async/index.d.ts.map +1 -0
  19. package/dist/async/index.js +6 -0
  20. package/dist/async/memoize.d.ts +19 -0
  21. package/dist/async/memoize.d.ts.map +1 -0
  22. package/dist/async/memoize.js +25 -0
  23. package/dist/async/retry.d.ts +25 -0
  24. package/dist/async/retry.d.ts.map +1 -0
  25. package/dist/async/retry.js +33 -0
  26. package/dist/async/sleep.d.ts +9 -0
  27. package/dist/async/sleep.d.ts.map +1 -0
  28. package/dist/async/sleep.js +10 -0
  29. package/dist/async/throttle.d.ts +20 -0
  30. package/dist/async/throttle.d.ts.map +1 -0
  31. package/dist/async/throttle.js +43 -0
  32. package/dist/async/withTimeout.d.ts +19 -0
  33. package/dist/async/withTimeout.d.ts.map +1 -0
  34. package/dist/async/withTimeout.js +34 -0
  35. package/dist/classes/array.d.ts +88 -0
  36. package/dist/classes/array.d.ts.map +1 -1
  37. package/dist/classes/array.js +74 -0
  38. package/dist/classes/index.d.ts +2 -0
  39. package/dist/classes/index.d.ts.map +1 -0
  40. package/dist/classes/index.js +1 -0
  41. package/dist/date/formatRelativeTime.d.ts +13 -0
  42. package/dist/date/formatRelativeTime.d.ts.map +1 -0
  43. package/dist/date/formatRelativeTime.js +30 -0
  44. package/dist/date/getPeriodStartMs.d.ts +16 -0
  45. package/dist/date/getPeriodStartMs.d.ts.map +1 -0
  46. package/dist/date/getPeriodStartMs.js +24 -0
  47. package/dist/date/index.d.ts +5 -0
  48. package/dist/date/index.d.ts.map +1 -0
  49. package/dist/date/index.js +4 -0
  50. package/dist/date/isSameDay.d.ts +11 -0
  51. package/dist/date/isSameDay.d.ts.map +1 -0
  52. package/dist/date/isSameDay.js +14 -0
  53. package/dist/date/startOfDay.d.ts +10 -0
  54. package/dist/date/startOfDay.d.ts.map +1 -0
  55. package/dist/date/startOfDay.js +13 -0
  56. package/dist/files/index.d.ts +2 -0
  57. package/dist/files/index.d.ts.map +1 -0
  58. package/dist/files/index.js +1 -0
  59. package/dist/index.d.ts +10 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +15 -1
  62. package/dist/number/clamp.d.ts +13 -0
  63. package/dist/number/clamp.d.ts.map +1 -0
  64. package/dist/number/clamp.js +14 -0
  65. package/dist/number/formatBytes.d.ts +12 -0
  66. package/dist/number/formatBytes.d.ts.map +1 -0
  67. package/dist/number/formatBytes.js +19 -0
  68. package/dist/number/formatCsvNumber.d.ts +14 -0
  69. package/dist/number/formatCsvNumber.d.ts.map +1 -0
  70. package/dist/number/formatCsvNumber.js +15 -0
  71. package/dist/number/formatDuration.d.ts +12 -0
  72. package/dist/number/formatDuration.d.ts.map +1 -0
  73. package/dist/number/formatDuration.js +29 -0
  74. package/dist/number/index.d.ts +6 -0
  75. package/dist/number/index.d.ts.map +1 -0
  76. package/dist/number/index.js +5 -0
  77. package/dist/number/round.d.ts +12 -0
  78. package/dist/number/round.d.ts.map +1 -0
  79. package/dist/number/round.js +14 -0
  80. package/dist/object/deepClone.d.ts +12 -0
  81. package/dist/object/deepClone.d.ts.map +1 -0
  82. package/dist/object/deepClone.js +16 -0
  83. package/dist/object/deepEqual.d.ts +12 -0
  84. package/dist/object/deepEqual.d.ts.map +1 -0
  85. package/dist/object/deepEqual.js +31 -0
  86. package/dist/object/groupBy.d.ts +12 -0
  87. package/dist/object/groupBy.d.ts.map +1 -0
  88. package/dist/object/groupBy.js +18 -0
  89. package/dist/object/index.d.ts +8 -0
  90. package/dist/object/index.d.ts.map +1 -0
  91. package/dist/object/index.js +7 -0
  92. package/dist/object/mapValues.d.ts +11 -0
  93. package/dist/object/mapValues.d.ts.map +1 -0
  94. package/dist/object/mapValues.js +16 -0
  95. package/dist/object/omit.d.ts +11 -0
  96. package/dist/object/omit.d.ts.map +1 -0
  97. package/dist/object/omit.js +16 -0
  98. package/dist/object/pick.d.ts +11 -0
  99. package/dist/object/pick.d.ts.map +1 -0
  100. package/dist/object/pick.js +18 -0
  101. package/dist/object/uniqueBy.d.ts +13 -0
  102. package/dist/object/uniqueBy.d.ts.map +1 -0
  103. package/dist/object/uniqueBy.js +23 -0
  104. package/dist/string/capitalize.d.ts +11 -0
  105. package/dist/string/capitalize.d.ts.map +1 -0
  106. package/dist/string/capitalize.js +14 -0
  107. package/dist/string/escapeCsvField.d.ts +14 -0
  108. package/dist/string/escapeCsvField.d.ts.map +1 -0
  109. package/dist/string/escapeCsvField.js +17 -0
  110. package/dist/string/escapeHtml.d.ts +12 -0
  111. package/dist/string/escapeHtml.d.ts.map +1 -0
  112. package/dist/string/escapeHtml.js +17 -0
  113. package/dist/string/index.d.ts +8 -0
  114. package/dist/string/index.d.ts.map +1 -0
  115. package/dist/string/index.js +7 -0
  116. package/dist/string/normalizeForSearch.d.ts +12 -0
  117. package/dist/string/normalizeForSearch.d.ts.map +1 -0
  118. package/dist/string/normalizeForSearch.js +25 -0
  119. package/dist/string/pluralize.d.ts +17 -0
  120. package/dist/string/pluralize.d.ts.map +1 -0
  121. package/dist/string/pluralize.js +26 -0
  122. package/dist/string/slugify.d.ts +12 -0
  123. package/dist/string/slugify.d.ts.map +1 -0
  124. package/dist/string/slugify.js +18 -0
  125. package/dist/string/truncate.d.ts +13 -0
  126. package/dist/string/truncate.d.ts.map +1 -0
  127. package/dist/string/truncate.js +17 -0
  128. 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
+ }
@@ -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;CAIzE"}
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"}
@@ -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,2 @@
1
+ export * from "./array.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,5 @@
1
+ export * from "./formatRelativeTime.js";
2
+ export * from "./getPeriodStartMs.js";
3
+ export * from "./isSameDay.js";
4
+ export * from "./startOfDay.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -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,4 @@
1
+ export * from "./formatRelativeTime.js";
2
+ export * from "./getPeriodStartMs.js";
3
+ export * from "./isSameDay.js";
4
+ export * from "./startOfDay.js";
@@ -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,2 @@
1
+ export * from "./downloadText.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -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
- export {};
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,6 @@
1
+ export * from "./clamp.js";
2
+ export * from "./formatBytes.js";
3
+ export * from "./formatCsvNumber.js";
4
+ export * from "./formatDuration.js";
5
+ export * from "./round.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -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"}