@kikiutils/shared 18.0.1 → 18.1.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 (156) hide show
  1. package/dist/buffer.d.ts +19 -21
  2. package/dist/buffer.d.ts.map +1 -1
  3. package/dist/buffer.js +18 -19
  4. package/dist/buffer.js.map +1 -1
  5. package/dist/classes/enhanced-date.d.ts +425 -0
  6. package/dist/classes/enhanced-date.d.ts.map +1 -0
  7. package/dist/classes/enhanced-date.js +591 -0
  8. package/dist/classes/enhanced-date.js.map +1 -0
  9. package/dist/classes/path.d.ts +211 -48
  10. package/dist/classes/path.d.ts.map +1 -1
  11. package/dist/classes/path.js +181 -52
  12. package/dist/classes/path.js.map +1 -1
  13. package/dist/classes/precision-number.d.ts +44 -39
  14. package/dist/classes/precision-number.d.ts.map +1 -1
  15. package/dist/classes/precision-number.js +51 -45
  16. package/dist/classes/precision-number.js.map +1 -1
  17. package/dist/classes/ssh-client.d.ts +3 -4
  18. package/dist/classes/ssh-client.d.ts.map +1 -1
  19. package/dist/classes/ssh-client.js +2 -2
  20. package/dist/classes/ssh-client.js.map +1 -1
  21. package/dist/clipboard.d.ts +25 -26
  22. package/dist/clipboard.d.ts.map +1 -1
  23. package/dist/clipboard.js +23 -23
  24. package/dist/clipboard.js.map +1 -1
  25. package/dist/consola.d.ts +12 -15
  26. package/dist/consola.d.ts.map +1 -1
  27. package/dist/consola.js +10 -12
  28. package/dist/consola.js.map +1 -1
  29. package/dist/crypto-hash.d.ts +65 -56
  30. package/dist/crypto-hash.d.ts.map +1 -1
  31. package/dist/crypto-hash.js +55 -45
  32. package/dist/crypto-hash.js.map +1 -1
  33. package/dist/datetime.d.ts +41 -53
  34. package/dist/datetime.d.ts.map +1 -1
  35. package/dist/datetime.js +53 -66
  36. package/dist/datetime.js.map +1 -1
  37. package/dist/element-plus.d.ts +13 -14
  38. package/dist/element-plus.d.ts.map +1 -1
  39. package/dist/element-plus.js +11 -11
  40. package/dist/element-plus.js.map +1 -1
  41. package/dist/enum.d.ts +39 -36
  42. package/dist/enum.d.ts.map +1 -1
  43. package/dist/enum.js +36 -32
  44. package/dist/enum.js.map +1 -1
  45. package/dist/env.d.ts +22 -15
  46. package/dist/env.d.ts.map +1 -1
  47. package/dist/env.js +20 -12
  48. package/dist/env.js.map +1 -1
  49. package/dist/event-awaiter.d.ts +47 -52
  50. package/dist/event-awaiter.d.ts.map +1 -1
  51. package/dist/event-awaiter.js +46 -50
  52. package/dist/event-awaiter.js.map +1 -1
  53. package/dist/general.d.ts +22 -17
  54. package/dist/general.d.ts.map +1 -1
  55. package/dist/general.js.map +1 -1
  56. package/dist/hash.d.ts +24 -21
  57. package/dist/hash.d.ts.map +1 -1
  58. package/dist/hash.js +20 -16
  59. package/dist/hash.js.map +1 -1
  60. package/dist/math.d.ts +20 -19
  61. package/dist/math.d.ts.map +1 -1
  62. package/dist/math.js +14 -12
  63. package/dist/math.js.map +1 -1
  64. package/dist/number.d.ts +10 -9
  65. package/dist/number.d.ts.map +1 -1
  66. package/dist/number.js +9 -7
  67. package/dist/number.js.map +1 -1
  68. package/dist/object.d.ts +22 -10
  69. package/dist/object.d.ts.map +1 -1
  70. package/dist/object.js +21 -8
  71. package/dist/object.js.map +1 -1
  72. package/dist/pino.d.ts +12 -15
  73. package/dist/pino.d.ts.map +1 -1
  74. package/dist/pino.js +10 -15
  75. package/dist/pino.js.map +1 -1
  76. package/dist/random.d.ts +17 -15
  77. package/dist/random.d.ts.map +1 -1
  78. package/dist/random.js +16 -13
  79. package/dist/random.js.map +1 -1
  80. package/dist/redis/script-runner.d.ts +57 -0
  81. package/dist/redis/script-runner.d.ts.map +1 -0
  82. package/dist/redis/script-runner.js +46 -0
  83. package/dist/redis/script-runner.js.map +1 -0
  84. package/dist/storages/lru/keyed-store.d.ts +18 -14
  85. package/dist/storages/lru/keyed-store.d.ts.map +1 -1
  86. package/dist/storages/lru/keyed-store.js +17 -12
  87. package/dist/storages/lru/keyed-store.js.map +1 -1
  88. package/dist/storages/redis/keyed-store.d.ts +11 -21
  89. package/dist/storages/redis/keyed-store.d.ts.map +1 -1
  90. package/dist/storages/redis/keyed-store.js +10 -19
  91. package/dist/storages/redis/keyed-store.js.map +1 -1
  92. package/dist/storages/redis/msgpack.d.ts +33 -13
  93. package/dist/storages/redis/msgpack.d.ts.map +1 -1
  94. package/dist/storages/redis/msgpack.js +32 -11
  95. package/dist/storages/redis/msgpack.js.map +1 -1
  96. package/dist/storages/redis/types.d.ts +34 -17
  97. package/dist/storages/redis/types.d.ts.map +1 -1
  98. package/dist/string.d.ts +12 -11
  99. package/dist/string.d.ts.map +1 -1
  100. package/dist/string.js +20 -15
  101. package/dist/string.js.map +1 -1
  102. package/dist/time.d.ts +26 -21
  103. package/dist/time.d.ts.map +1 -1
  104. package/dist/time.js +24 -18
  105. package/dist/time.js.map +1 -1
  106. package/dist/types/filtered-key-path.d.ts +4 -15
  107. package/dist/types/filtered-key-path.d.ts.map +1 -1
  108. package/dist/types/index.d.ts +10 -10
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types/vue.d.ts +7 -7
  111. package/dist/types/vue.d.ts.map +1 -1
  112. package/dist/url.d.ts +15 -14
  113. package/dist/url.d.ts.map +1 -1
  114. package/dist/url.js +12 -10
  115. package/dist/url.js.map +1 -1
  116. package/dist/vue.d.ts +19 -21
  117. package/dist/vue.d.ts.map +1 -1
  118. package/dist/vue.js +15 -16
  119. package/dist/vue.js.map +1 -1
  120. package/dist/web.d.ts +14 -11
  121. package/dist/web.d.ts.map +1 -1
  122. package/dist/web.js +12 -8
  123. package/dist/web.js.map +1 -1
  124. package/package.json +20 -20
  125. package/src/buffer.ts +18 -19
  126. package/src/classes/enhanced-date.ts +665 -0
  127. package/src/classes/path.ts +232 -91
  128. package/src/classes/precision-number.ts +61 -53
  129. package/src/classes/ssh-client.ts +8 -5
  130. package/src/clipboard.ts +23 -23
  131. package/src/consola.ts +10 -12
  132. package/src/crypto-hash.ts +55 -45
  133. package/src/datetime.ts +65 -85
  134. package/src/element-plus.ts +11 -11
  135. package/src/enum.ts +36 -32
  136. package/src/env.ts +20 -12
  137. package/src/event-awaiter.ts +49 -50
  138. package/src/general.ts +20 -14
  139. package/src/hash.ts +20 -16
  140. package/src/math.ts +18 -16
  141. package/src/number.ts +9 -7
  142. package/src/object.ts +21 -8
  143. package/src/pino.ts +11 -15
  144. package/src/random.ts +16 -13
  145. package/src/redis/script-runner.ts +107 -0
  146. package/src/storages/lru/keyed-store.ts +17 -12
  147. package/src/storages/redis/keyed-store.ts +10 -19
  148. package/src/storages/redis/msgpack.ts +32 -11
  149. package/src/storages/redis/types.ts +32 -14
  150. package/src/string.ts +10 -8
  151. package/src/time.ts +24 -18
  152. package/src/types/filtered-key-path.ts +9 -14
  153. package/src/types/vue.ts +6 -5
  154. package/src/url.ts +12 -10
  155. package/src/vue.ts +15 -16
  156. package/src/web.ts +12 -8
package/src/datetime.ts CHANGED
@@ -1,77 +1,66 @@
1
- import {
2
- format as dateFnsFormat,
3
- endOfDay,
4
- endOfMonth,
5
- endOfWeek,
6
- startOfDay,
7
- startOfMonth,
8
- startOfWeek,
9
- subDays,
10
- subMonths,
11
- subWeeks,
12
- } from 'date-fns';
13
- import type {
14
- DateArg,
15
- Day,
16
- FormatOptions,
17
- } from 'date-fns';
1
+ import * as dateFns from 'date-fns';
2
+
3
+ import { EnhancedDate } from './classes/enhanced-date';
18
4
 
19
5
  export type DateRangeType = 'lastMonth' | 'lastWeek' | 'thisMonth' | 'thisWeek' | 'today' | 'yesterday';
20
6
 
21
7
  /**
22
- * Formats a given date, timestamp, or date string into a specified format.
8
+ * Formats a date using a date-fns pattern without changing the input.
23
9
  *
24
- * This function is a wrapper around `date-fns/format`.
10
+ * @remarks
11
+ * Formatting uses the system time zone unless configured through date-fns options.
12
+ * Invalid dates and unsupported patterns propagate date-fns exceptions.
25
13
  *
26
- * @param {DateArg<Date>} date - The input date to format. Can be a Date object, a timestamp, or a string
27
- * @param {string} [format] - The target format string
28
- * @param {FormatOptions} [options] - Optional formatting options passed to `date-fns/format`
14
+ * @param date - The date, timestamp in milliseconds, or date string to format.
15
+ * @param format - The date-fns pattern. Defaults to `yyyy-MM-dd HH:mm:ss`.
16
+ * @param options - Formatting options passed to date-fns.
29
17
  *
30
- * @returns {string} The formatted date string
18
+ * @returns The formatted date string.
31
19
  *
32
20
  * @example
33
- * ```typescript
34
- * import { formatDate } from '@kikiutils/shared/datetime';
35
21
  *
36
- * // Format a Date object
37
- * console.log(formatDate(new Date(), 'yyyy-MM-dd')); // 2024-07-10
38
- *
39
- * // Format a timestamp
40
- * console.log(formatDate(1657814400000, 'yyyy-MM-dd')); // 2022-07-15
22
+ * ```ts
23
+ * import { formatDate } from '@kikiutils/shared/datetime';
41
24
  *
42
- * // Format a date string
43
- * console.log(formatDate('2024-07-10T00:00:00Z', 'yyyy-MM-dd')); // 2024-07-10
25
+ * const date = new Date(2026, 0, 15, 12);
26
+ * console.log(formatDate(date, 'yyyy-MM-dd')); // => '2026-01-15'
44
27
  * ```
45
28
  */
46
- export function formatDate(date: DateArg<Date> & {}, format: string = 'yyyy-MM-dd HH:mm:ss', options?: FormatOptions) {
47
- return dateFnsFormat(date, format, options);
29
+ export function formatDate(
30
+ date: dateFns.DateArg<Date>,
31
+ format: string = 'yyyy-MM-dd HH:mm:ss',
32
+ options?: dateFns.FormatOptions,
33
+ ) {
34
+ return dateFns.format(date, format, options);
48
35
  }
49
36
 
37
+ /* eslint-disable jsdoc/check-param-names -- Inline TypeScript options are documented in remarks. */
38
+
50
39
  /**
51
- * Get the date range (start and end) based on a given date and range type.
40
+ * Returns new start and end dates for a calendar range in the system time zone.
41
+ *
42
+ * @remarks
43
+ * The reference date is unchanged. Boundaries are inclusive by default, ending at `23:59:59.999`.
44
+ * When `options.setEndDateToNextDayStart` is `true`, the end is the exclusive start of the next calendar day.
45
+ * `options.weekStartsOn` defaults to `1` (Monday); `0` means Sunday and `6` means Saturday.
46
+ * Calendar ranges follow local daylight saving transitions rather than fixed 24-hour durations.
52
47
  *
53
- * Supports common range types like 'lastMonth', 'lastWeek', 'thisMonth', 'thisWeek', 'today', and 'yesterday'.
48
+ * @param date - The reference date for the range.
49
+ * @param type - The current or previous day, week, or month to select.
50
+ * @param options - Settings for the end boundary and first day of the week.
54
51
  *
55
- * @param {Date} date - The reference date
56
- * @param {DateRangeType} type - The range type to compute
57
- * @param {object} [options] - Optional settings
58
- * @param {boolean} [options.setEndDateToNextDayStart] - If true, set `endDate` to 00:00:00.000 of the next day
59
- * @param {Day} [options.weekStartsOn] - The start day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)
52
+ * @returns An object containing new `EnhancedDate` boundaries; the reference date is unchanged.
60
53
  *
61
- * @returns {{ startDate: Date, endDate: Date }} An object with `startDate` and `endDate`
54
+ * @throws Error if the range type is unsupported at runtime.
62
55
  *
63
56
  * @example
64
- * ```typescript
65
- * import { getDateRangeFromDate } from '@kikiutils/shared/datetime';
66
57
  *
67
- * // Get the date range for last month
68
- * const date = new Date('2023-07-01');
69
- * console.log(getDateRangeFromDate(date, 'lastMonth'));
70
- * // { startDate: 2023-06-01T00:00:00.000Z, endDate: 2023-06-30T23:59:59.999Z }
58
+ * ```ts
59
+ * import { getDateRangeFromDate } from '@kikiutils/shared/datetime';
71
60
  *
72
- * // Get this week's range with Sunday as the first day
73
- * console.log(getDateRangeFromDate(date, 'thisWeek', { weekStartsOn: 0 }));
74
- * // { startDate: 2023-06-25T00:00:00.000Z, endDate: 2023-07-01T23:59:59.999Z }
61
+ * const range = getDateRangeFromDate(new Date(2026, 6, 15, 12), 'lastMonth');
62
+ * console.log(range.startDate.format('yyyy-MM-dd')); // => '2026-06-01'
63
+ * console.log(range.endDate.format('yyyy-MM-dd')); // => '2026-06-30'
75
64
  * ```
76
65
  */
77
66
  export function getDateRangeFromDate(
@@ -79,45 +68,46 @@ export function getDateRangeFromDate(
79
68
  type: DateRangeType,
80
69
  options?: {
81
70
  setEndDateToNextDayStart?: boolean;
82
- weekStartsOn?: Day;
71
+ weekStartsOn?: dateFns.Day;
83
72
  },
84
73
  ) {
85
- let endDate: Date;
86
- let startDate: Date;
74
+ const referenceDate = new EnhancedDate(date);
75
+ let endDate: EnhancedDate;
76
+ let startDate: EnhancedDate;
87
77
  switch (type) {
88
78
  case 'lastMonth':
89
79
  {
90
- const lastMonth = subMonths(date, 1);
91
- endDate = endOfMonth(lastMonth);
92
- startDate = startOfMonth(lastMonth);
80
+ const lastMonth = referenceDate.toSubMonths(1);
81
+ endDate = lastMonth.toEndOfMonth();
82
+ startDate = lastMonth.toStartOfMonth();
93
83
  }
94
84
 
95
85
  break;
96
86
  case 'lastWeek':
97
87
  {
98
- const lastWeek = subWeeks(date, 1);
99
- endDate = endOfWeek(lastWeek, { weekStartsOn: options?.weekStartsOn ?? 1 });
100
- startDate = startOfWeek(lastWeek, { weekStartsOn: options?.weekStartsOn ?? 1 });
88
+ const lastWeek = referenceDate.toSubWeeks(1);
89
+ endDate = lastWeek.toEndOfWeek({ weekStartsOn: options?.weekStartsOn ?? 1 });
90
+ startDate = lastWeek.toStartOfWeek({ weekStartsOn: options?.weekStartsOn ?? 1 });
101
91
  }
102
92
 
103
93
  break;
104
94
  case 'thisMonth':
105
- endDate = endOfMonth(date);
106
- startDate = startOfMonth(date);
95
+ endDate = referenceDate.toEndOfMonth();
96
+ startDate = referenceDate.toStartOfMonth();
107
97
  break;
108
98
  case 'thisWeek':
109
- endDate = endOfWeek(date, { weekStartsOn: options?.weekStartsOn ?? 1 });
110
- startDate = startOfWeek(date, { weekStartsOn: options?.weekStartsOn ?? 1 });
99
+ endDate = referenceDate.toEndOfWeek({ weekStartsOn: options?.weekStartsOn ?? 1 });
100
+ startDate = referenceDate.toStartOfWeek({ weekStartsOn: options?.weekStartsOn ?? 1 });
111
101
  break;
112
102
  case 'today':
113
- endDate = endOfDay(date);
114
- startDate = startOfDay(date);
103
+ endDate = referenceDate.toEndOfDay();
104
+ startDate = referenceDate.toStartOfDay();
115
105
  break;
116
106
  case 'yesterday':
117
107
  {
118
- const yesterday = subDays(date, 1);
119
- endDate = endOfDay(yesterday);
120
- startDate = startOfDay(yesterday);
108
+ const yesterday = referenceDate.toSubDays(1);
109
+ endDate = yesterday.toEndOfDay();
110
+ startDate = yesterday.toStartOfDay();
121
111
  }
122
112
 
123
113
  break;
@@ -131,25 +121,15 @@ export function getDateRangeFromDate(
131
121
  };
132
122
  }
133
123
 
124
+ /* eslint-enable jsdoc/check-param-names */
125
+
134
126
  /**
135
- * Returns a `Date` object set to midnight (00:00:00) of today, with an optional day offset.
136
- *
137
- * @param {number} [offsetDays] - Number of days to offset from today. Can be negative
127
+ * Returns a new date at local midnight with an optional calendar-day offset from today.
138
128
  *
139
- * @returns {Date} A `Date` object at 00:00:00 of the offset day
129
+ * @param offsetDays - The calendar days to add; negative values select earlier days.
140
130
  *
141
- * @example
142
- * ```typescript
143
- * import { getMidnightDateFromToday } from '@kikiutils/shared/datetime';
144
- *
145
- * console.log(getMidnightDateFromToday()); // today at 00:00:00
146
- * console.log(getMidnightDateFromToday(3)); // 3 days from today at 00:00:00
147
- * console.log(getMidnightDateFromToday(-1)); // yesterday at 00:00:00
148
- * ```
131
+ * @returns A new `EnhancedDate` at local midnight on the selected day.
149
132
  */
150
133
  export function getMidnightDateFromToday(offsetDays: number = 0) {
151
- const date = new Date();
152
- date.setDate(date.getDate() + offsetDays);
153
- date.setHours(0, 0, 0, 0);
154
- return date;
134
+ return new EnhancedDate().addDays(offsetDays).startOfDay();
155
135
  }
@@ -4,22 +4,22 @@ import type { FormItemRule } from 'element-plus';
4
4
  export type DoNotRemoveOrUseThisType = RuleType;
5
5
 
6
6
  /**
7
- * Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.
7
+ * Creates a new Element Plus form validation rule with overridable defaults.
8
8
  *
9
- * This utility provides default values for `required`, `trigger`, and `type`,
10
- * while allowing overrides via the `options` parameter. It simplifies common
11
- * form validation rule creation and ensures consistency across forms.
9
+ * @remarks
10
+ * Defaults to `required: true`, `trigger: 'blur'`, and `type: 'string'`.
11
+ * Non-nullish options override those defaults; `null` and `undefined` use the defaults.
12
+ * The `message` argument takes precedence over `options.message`.
13
+ * The options object is unchanged.
12
14
  *
13
- * @param {FormItemRule['message']} message - The validation message to display when the rule fails
14
- * @param {FormItemRule} [options] - Optional overrides for the rule fields
15
- * @param {boolean} [options.required] - Whether the field is required (default: `true`)
16
- * @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`)
17
- * @param {RuleType} [options.type] - The expected type of the field (default: `'string'`)
15
+ * @param message - The validation message displayed on failure.
16
+ * @param options - Additional rule fields and non-nullish overrides for the defaults; `message` takes precedence.
18
17
  *
19
- * @returns A `FormItemRule` object that can be used in Element Plus form validation
18
+ * @returns A new `FormItemRule` object.
20
19
  *
21
20
  * @example
22
- * ```typescript
21
+ *
22
+ * ```ts
23
23
  * import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';
24
24
  *
25
25
  * const rule = createElFormItemRuleWithDefaults('This field is required');
package/src/enum.ts CHANGED
@@ -1,24 +1,25 @@
1
1
  /**
2
2
  * Extracts only the numeric values from an enumeration-like object.
3
3
  *
4
- * @template T - The type of the enum object
4
+ * @typeParam T - The type of the enum object.
5
5
  *
6
- * @param {T} enumObject - The enumeration-like object to extract numeric values from,
6
+ * @param enumObject - The enumeration-like object to extract numeric values from,
7
7
  * the object can contain numeric values, string values, or both.
8
8
  *
9
- * @returns {Extract<T[keyof T], number>[]} An array of numeric values extracted from the enum object
9
+ * @returns An array of numeric values extracted from the enum object.
10
10
  *
11
11
  * @example
12
- * ```typescript
12
+ *
13
+ * ```ts
13
14
  * import { getEnumNumberValues } from '@kikiutils/shared/enum';
14
15
  *
15
16
  * enum RecordType {
16
- * Receive = 0,
17
- * Send = 1,
18
- * Unknown = 'unknown'
17
+ * Receive = 0,
18
+ * Send = 1,
19
+ * Unknown = 'unknown',
19
20
  * }
20
21
  *
21
- * console.log(getEnumNumberValues(RecordType)); // [0, 1]
22
+ * console.log(getEnumNumberValues(RecordType)); // => [0, 1]
22
23
  * ```
23
24
  */
24
25
  export function getEnumNumberValues<T extends Record<string, any>>(enumObject: T): Extract<T[keyof T], number>[] {
@@ -28,24 +29,25 @@ export function getEnumNumberValues<T extends Record<string, any>>(enumObject: T
28
29
  /**
29
30
  * Extracts only the string values from an enumeration-like object.
30
31
  *
31
- * @template T - The type of the enum object
32
+ * @typeParam T - The type of the enum object.
32
33
  *
33
- * @param {T} enumObject - The enumeration-like object to extract string values from,
34
+ * @param enumObject - The enumeration-like object to extract string values from,
34
35
  * the object can contain numeric values, string values, or both.
35
36
  *
36
- * @returns {Extract<T[keyof T], string>[]} An array of string values extracted from the enum object
37
+ * @returns An array of string values extracted from the enum object.
37
38
  *
38
39
  * @example
39
- * ```typescript
40
+ *
41
+ * ```ts
40
42
  * import { getEnumStringValues } from '@kikiutils/shared/enum';
41
43
  *
42
44
  * enum RecordType {
43
- * Receive = 0,
44
- * Send = 1,
45
- * Unknown = 'unknown'
45
+ * Receive = 0,
46
+ * Send = 1,
47
+ * Unknown = 'unknown',
46
48
  * }
47
49
  *
48
- * console.log(getEnumStringValues(RecordType)); // ['unknown']
50
+ * console.log(getEnumStringValues(RecordType)); // => ['unknown']
49
51
  * ```
50
52
  */
51
53
  export function getEnumStringValues<T extends Record<string, any>>(enumObject: T): Extract<T[keyof T], string>[] {
@@ -55,47 +57,49 @@ export function getEnumStringValues<T extends Record<string, any>>(enumObject: T
55
57
  /**
56
58
  * Extracts all values from an enumeration-like object.
57
59
  *
60
+ * @remarks
58
61
  * This function handles TypeScript enums correctly by accounting for the reverse mapping
59
62
  * that occurs with numeric enums. It works with pure numeric enums, pure string enums,
60
63
  * and mixed enums.
61
64
  *
62
- * @template T - The type of the enum object
65
+ * @typeParam T - The type of the enum object.
63
66
  *
64
- * @param {T} enumObject - The enumeration-like object to extract values from,
67
+ * @param enumObject - The enumeration-like object to extract values from,
65
68
  * the object can contain numeric values, string values, or both.
66
69
  *
67
- * @returns {(T[keyof T])[]} An array containing all the values from the enum object
70
+ * @returns An array containing all the values from the enum object.
68
71
  *
69
72
  * @example
70
- * ```typescript
73
+ *
74
+ * ```ts
71
75
  * import { getEnumValues } from '@kikiutils/shared/enum';
72
76
  *
73
77
  * // Numeric enum
74
78
  * enum Status {
75
- * Active = 0,
76
- * Inactive = 1,
77
- * Pending = 2
79
+ * Active = 0,
80
+ * Inactive = 1,
81
+ * Pending = 2,
78
82
  * }
79
83
  *
80
- * console.log(getEnumValues(Status)); // [0, 1, 2]
84
+ * console.log(getEnumValues(Status)); // => [0, 1, 2]
81
85
  *
82
86
  * // String enum
83
87
  * enum Color {
84
- * Red = 'RED',
85
- * Green = 'GREEN',
86
- * Blue = 'BLUE'
88
+ * Red = 'RED',
89
+ * Green = 'GREEN',
90
+ * Blue = 'BLUE',
87
91
  * }
88
92
  *
89
- * console.log(getEnumValues(Color)); // ['RED', 'GREEN', 'BLUE']
93
+ * console.log(getEnumValues(Color)); // => ['RED', 'GREEN', 'BLUE']
90
94
  *
91
95
  * // Mixed enum
92
96
  * enum RecordType {
93
- * Receive = 0,
94
- * Send = 1,
95
- * Unknown = 'unknown'
97
+ * Receive = 0,
98
+ * Send = 1,
99
+ * Unknown = 'unknown',
96
100
  * }
97
101
  *
98
- * console.log(getEnumValues(RecordType)); // [0, 1, 'unknown']
102
+ * console.log(getEnumValues(RecordType)); // => [0, 1, 'unknown']
99
103
  * ```
100
104
  */
101
105
  export function getEnumValues<T extends Record<string, any>>(enumObject: T): (T[keyof T])[] {
package/src/env.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * Custom error class for handling missing environment variables.
3
3
  *
4
+ * @remarks
4
5
  * Extends the built-in `Error` class and includes the missing key.
5
- *
6
- * @extends {Error}
7
6
  */
8
7
  export class EnvironmentNotFoundError extends Error {
9
8
  readonly key: string;
10
9
 
11
10
  /**
12
- * Creates a new EnvironmentNotFoundError.
11
+ * Creates an error identifying a missing environment variable.
13
12
  *
14
- * @param {string} key - The missing environment variable key
13
+ * @param key - The missing environment variable key.
15
14
  */
16
15
  constructor(key: string) {
17
16
  super(`Missing environment variable: ${key}`);
@@ -24,24 +23,33 @@ export class EnvironmentNotFoundError extends Error {
24
23
  /**
25
24
  * Retrieves the value of an environment variable, or throws an error if it is not defined.
26
25
  *
27
- * Only checks for `process.env[key] === undefined`. An empty string (e.g. '') or any falsy string
26
+ * @remarks
27
+ * Only checks for `process.env[key] === undefined`. An empty string (for example `''`) or any falsy string
28
28
  * value like `'0'` or `'false'` is considered a valid (defined) value.
29
29
  *
30
- * @param {string} key - The environment variable key to retrieve
30
+ * @param key - The environment variable key to retrieve.
31
31
  *
32
- * @returns {string} The value of the environment variable
32
+ * @returns The value of the environment variable.
33
33
  *
34
- * @throws {EnvironmentNotFoundError} If the environment variable is not defined
34
+ * @throws EnvironmentNotFoundError if the environment variable is not defined.
35
35
  *
36
36
  * @example
37
- * ```typescript
38
- * import { checkAndGetEnvValue } from '@kikiutils/shared/env';
37
+ *
38
+ * ```ts
39
+ * import {
40
+ * checkAndGetEnvValue,
41
+ * EnvironmentNotFoundError,
42
+ * } from '@kikiutils/shared/env';
39
43
  *
40
44
  * process.env.API_KEY = '';
41
- * checkAndGetEnvValue('API_KEY'); // ✅ Returns '' (still considered "defined")
45
+ * checkAndGetEnvValue('API_KEY'); // => ''
42
46
  *
43
47
  * delete process.env.API_KEY;
44
- * checkAndGetEnvValue('API_KEY'); // ❌ Throws EnvironmentNotFoundError
48
+ * try {
49
+ * checkAndGetEnvValue('API_KEY');
50
+ * } catch (error) {
51
+ * console.log(error instanceof EnvironmentNotFoundError); // => true
52
+ * }
45
53
  * ```
46
54
  */
47
55
  export function checkAndGetEnvValue(key: string) {
@@ -1,25 +1,25 @@
1
1
  /**
2
- * EventAwaiter provides a mechanism to wait for events (by key) asynchronously.
2
+ * An asynchronous keyed event rendezvous for one or more waiting consumers.
3
3
  *
4
- * This class allows multiple consumers to `wait` for a specific key
5
- * and be resolved when `trigger` is called for that key, or automatically
6
- * resolved with `undefined` if a timeout occurs or an AbortSignal is triggered.
4
+ * @remarks
5
+ * Triggers resolve the currently registered waiters; values are not retained for future waits.
6
+ * Timeouts and subsequent abort events resolve affected waiters with `undefined`.
7
+ * Use `triggerAll` to resolve pending waits during cleanup. Timers and abort listeners are not proactively
8
+ * removed by triggers, so they may remain until their timeout or abort event occurs.
7
9
  *
8
- * Typical use cases include long-polling, request coordination,
9
- * or implementing event-driven primitives in applications or services.
10
- *
11
- * @template T - The type of value that will be resolved when the event is triggered
10
+ * @typeParam T - The value delivered to waiting consumers.
12
11
  */
13
12
  export class EventAwaiter<T> {
13
+ // Private instance properties
14
14
  #promiseResolvers = new Map<string, ((value: PromiseLike<T | undefined> | T | undefined) => void)[]>();
15
15
 
16
+ // Public instance methods
17
+
16
18
  /**
17
- * Triggers all pending promises waiting for the given key.
18
- * Each promise will be resolved with the provided value.
19
+ * Resolves all currently pending waits for a key with the supplied value.
19
20
  *
20
- * @param {string} key - Identifier for the awaited event
21
- * @param {T | undefined} value - The value to resolve the awaiting promises with.
22
- * May be `undefined` to indicate no result or a timeout-like behavior.
21
+ * @param key - The event identifier; a key without pending waits has no effect.
22
+ * @param value - The delivered value; `undefined` indicates no result.
23
23
  */
24
24
  trigger(key: string, value: T | undefined) {
25
25
  const resolvers = this.#promiseResolvers.get(key);
@@ -30,13 +30,9 @@ export class EventAwaiter<T> {
30
30
  }
31
31
 
32
32
  /**
33
- * Triggers and resolves all pending promises across all keys.
34
- *
35
- * This is typically used during shutdown or cleanup to ensure that
36
- * no consumer is left waiting indefinitely.
33
+ * Resolves all currently pending waits and clears their registrations.
37
34
  *
38
- * @param {T | undefined} [value] - Optional value to resolve all waiters with.
39
- * Defaults to `undefined`, which usually indicates cancellation or shutdown.
35
+ * @param value - The delivered value; omission resolves all pending waits with `undefined`.
40
36
  */
41
37
  triggerAll(value: T | undefined = undefined) {
42
38
  for (const [_, resolvers] of this.#promiseResolvers.entries()) resolvers.forEach((resolve) => resolve(value));
@@ -44,27 +40,23 @@ export class EventAwaiter<T> {
44
40
  }
45
41
 
46
42
  /**
47
- * Waits for an event associated with the given key.
43
+ * Waits for a trigger associated with a key.
48
44
  *
49
- * The returned promise will resolve when:
50
- * - `trigger(key)` is called, in which case it resolves with the provided value.
51
- * - The optional timeout is reached, in which case it resolves with `undefined`.
52
- * - The optional `AbortSignal` is aborted, in which case it resolves with `undefined`.
45
+ * @remarks
46
+ * By default, multiple waiters share a key and all receive the next trigger value.
47
+ * `strict` mode rejects duplicate waits; `override` mode resolves existing waits with `undefined` before
48
+ * registering the new wait. Timeout and abort remove only the affected waiter's registration.
49
+ * An already aborted signal is not checked; only an abort event emitted after registration ends the wait.
50
+ * Without a timeout or subsequent abort, the wait remains pending until a trigger arrives.
53
51
  *
54
- * Behavior when multiple waiters exist for the same key:
55
- * - Default (no mode): multiple waiters are allowed, all will be resolved when triggered.
56
- * - `strict` mode: throws an error if a waiter already exists for the given key.
57
- * - `override` mode: cancels all existing waiters (resolving them with `undefined`)
58
- * and only keeps the latest one.
52
+ * @param key - The event identifier to wait for.
53
+ * @param timeoutMs - The optional timeout in milliseconds, using native `setTimeout` timing rules.
54
+ * @param mode - The policy for existing waiters; omission allows multiple waiters.
55
+ * @param signal - A signal whose subsequent abort event ends this wait.
59
56
  *
60
- * @param {string} key - Identifier for the awaited event
61
- * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
62
- * If reached, the promise resolves with `undefined`.
63
- * @param {'override' | 'strict'} [mode] - Optional behavior mode for handling multiple waiters
64
- * @param {AbortSignal} [signal] - Optional AbortSignal. If aborted, the promise resolves with `undefined`
57
+ * @returns A promise resolving to the triggered value, or `undefined` after timeout, abort, or replacement.
65
58
  *
66
- * @returns {Promise<T | undefined>} A promise that resolves with the triggered value,
67
- * or `undefined` if timeout or abort occurs
59
+ * @throws Error through promise rejection if `strict` mode encounters an existing waiter.
68
60
  */
69
61
  wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict', signal?: AbortSignal) {
70
62
  return new Promise<T | undefined>((resolve) => {
@@ -116,28 +108,35 @@ export class EventAwaiter<T> {
116
108
  }
117
109
 
118
110
  /**
119
- * Waits for an event in strict mode.
120
- * Only one waiter is allowed per key. If another waiter already exists,
121
- * this method will throw an error.
111
+ * Waits for a key while rejecting duplicate registrations.
112
+ *
113
+ * @param key - The event identifier to wait for.
114
+ * @param timeoutMs - The optional timeout in milliseconds.
115
+ * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.
116
+ *
117
+ * @returns A promise resolving to the triggered value, or `undefined` on timeout or subsequent abort.
122
118
  *
123
- * @param {string} key - Identifier for the awaited event
124
- * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
125
- * If reached, the promise resolves with `undefined`.
126
- * @param {AbortSignal} [signal] - Optional AbortSignal. If aborted, the promise resolves with `undefined`
119
+ * @throws Error through promise rejection if the key already has a pending waiter.
120
+ *
121
+ * @see {@link EventAwaiter.wait}
127
122
  */
128
123
  waitExclusive(key: string, timeoutMs?: number, signal?: AbortSignal) {
129
124
  return this.wait(key, timeoutMs, 'strict', signal);
130
125
  }
131
126
 
132
127
  /**
133
- * Waits for an event in override mode.
134
- * If another waiter already exists for the given key, it will be canceled
135
- * (resolved with `undefined`) and replaced by the new waiter.
128
+ * Replaces existing waiters for a key and waits for its next trigger.
129
+ *
130
+ * @remarks
131
+ * Existing waiters resolve with `undefined` before the new waiter is registered.
132
+ *
133
+ * @param key - The event identifier to wait for.
134
+ * @param timeoutMs - The optional timeout in milliseconds.
135
+ * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.
136
+ *
137
+ * @returns A promise resolving to the triggered value, or `undefined` on timeout, subsequent abort, or replacement.
136
138
  *
137
- * @param {string} key - Identifier for the awaited event
138
- * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
139
- * If reached, the promise resolves with `undefined`.
140
- * @param {AbortSignal} [signal] - Optional AbortSignal. If aborted, the promise resolves with `undefined`
139
+ * @see {@link EventAwaiter.wait}
141
140
  */
142
141
  waitLatest(key: string, timeoutMs?: number, signal?: AbortSignal) {
143
142
  return this.wait(key, timeoutMs, 'override', signal);
package/src/general.ts CHANGED
@@ -1,28 +1,34 @@
1
1
  /* eslint-disable jsdoc/check-param-names */
2
2
 
3
3
  /**
4
- * Extracts the first value from an array or returns the value itself if it's not an array.
4
+ * Returns the first array element or the input value, with a nullish fallback.
5
5
  *
6
- * - If `value` is an array, returns the first element.
7
- * - If `value` is not an array, returns `value` directly.
8
- * - If the result is `null` or `undefined`, and `defaultValue` is provided, returns `defaultValue` instead.
6
+ * @remarks
7
+ * An empty array, `null`, or `undefined` selects the fallback; omission of a fallback yields `undefined`.
8
+ * The input and selected values are not copied or changed.
9
9
  *
10
- * @template T - The type of the input value(s)
11
- * @template D - The type of the default value (if provided)
10
+ * @typeParam T - The input value or array element type.
11
+ * @typeParam D - The fallback type when the fallback overload is used.
12
12
  *
13
- * @param {T | T[]} value - A single value or an array of values
14
- * @param {D} [defaultValue] - A fallback value if the result is `null` or `undefined`
13
+ * @param value - A single value or an array of values.
14
+ * @param defaultValue - The fallback returned when the selected value is nullish.
15
15
  *
16
- * @returns {T | D | undefined} The first value or the fallback
16
+ * @returns The selected non-nullish value, or the fallback without copying either value.
17
17
  *
18
18
  * @example
19
- * ```typescript
19
+ *
20
+ * ```ts
20
21
  * import { extractFirstValue } from '@kikiutils/shared/general';
21
22
  *
22
- * console.log(extractFirstValue([1, 2, 3])); // 1
23
- * console.log(extractFirstValue('hello')); // hello
24
- * console.log(extractFirstValue([], 'default')); // default
25
- * console.log(extractFirstValue(undefined, 'fallback')); // fallback
23
+ * console.log(extractFirstValue([
24
+ * 1,
25
+ * 2,
26
+ * 3,
27
+ * ])); // => 1
28
+ *
29
+ * console.log(extractFirstValue('hello')); // => 'hello'
30
+ * console.log(extractFirstValue([], 'default')); // => 'default'
31
+ * console.log(extractFirstValue(undefined, 'fallback')); // => 'fallback'
26
32
  * ```
27
33
  */
28
34
  export function extractFirstValue<T>(value: T | T[]): T | undefined;