@naturalcycles/js-lib 15.8.0 → 15.9.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.
@@ -4,8 +4,8 @@ import { _objectEntries, SKIP } from '../types.js';
4
4
  * Returns clone of `obj` with only `props` preserved.
5
5
  * Opposite of Omit.
6
6
  */
7
- export function _pick(obj, props, mutate = false) {
8
- if (mutate) {
7
+ export function _pick(obj, props, opt = {}) {
8
+ if (opt.mutate) {
9
9
  // Start as original object (mutable), DELETE properties that are not whitelisted
10
10
  for (const k of Object.keys(obj)) {
11
11
  if (!props.includes(k))
@@ -25,8 +25,8 @@ export function _pick(obj, props, mutate = false) {
25
25
  * Sets all properties of an object except passed ones to `undefined`.
26
26
  * This is a more performant alternative to `_pick` that does picking/deleting.
27
27
  */
28
- export function _pickWithUndefined(obj, props, mutate = false) {
29
- const r = mutate ? obj : { ...obj };
28
+ export function _pickWithUndefined(obj, props, opt = {}) {
29
+ const r = opt.mutate ? obj : { ...obj };
30
30
  for (const k of Object.keys(r)) {
31
31
  if (!props.includes(k)) {
32
32
  r[k] = undefined;
@@ -38,8 +38,8 @@ export function _pickWithUndefined(obj, props, mutate = false) {
38
38
  * Returns clone of `obj` with `props` omitted.
39
39
  * Opposite of Pick.
40
40
  */
41
- export function _omit(obj, props, mutate = false) {
42
- if (mutate) {
41
+ export function _omit(obj, props, opt = {}) {
42
+ if (opt.mutate) {
43
43
  for (const k of props) {
44
44
  delete obj[k];
45
45
  }
@@ -56,8 +56,8 @@ export function _omit(obj, props, mutate = false) {
56
56
  * Sets all passed properties of an object to `undefined`.
57
57
  * This is a more performant alternative to `_omit` that does picking/deleting.
58
58
  */
59
- export function _omitWithUndefined(obj, props, mutate = false) {
60
- const r = mutate ? obj : { ...obj };
59
+ export function _omitWithUndefined(obj, props, opt = {}) {
60
+ const r = opt.mutate ? obj : { ...obj };
61
61
  for (const k of props) {
62
62
  r[k] = undefined;
63
63
  }
@@ -71,8 +71,8 @@ export function _omitWithUndefined(obj, props, mutate = false) {
71
71
  * 'account.updated',
72
72
  * ])
73
73
  */
74
- export function _mask(obj, props, mutate = false) {
75
- const r = mutate ? obj : _deepCopy(obj);
74
+ export function _mask(obj, props, opt = {}) {
75
+ const r = opt.mutate ? obj : _deepCopy(obj);
76
76
  for (const k of props) {
77
77
  _unset(r, k);
78
78
  }
@@ -81,31 +81,31 @@ export function _mask(obj, props, mutate = false) {
81
81
  /**
82
82
  * Removes "falsy" values from the object.
83
83
  */
84
- export function _filterFalsyValues(obj, mutate = false) {
85
- return _filterObject(obj, (_k, v) => !!v, mutate);
84
+ export function _filterFalsyValues(obj, opt = {}) {
85
+ return _filterObject(obj, (_k, v) => !!v, opt);
86
86
  }
87
87
  /**
88
88
  * Removes values from the object that are `null` or `undefined`.
89
89
  */
90
- export function _filterNullishValues(obj, mutate = false) {
91
- return _filterObject(obj, (_k, v) => v !== undefined && v !== null, mutate);
90
+ export function _filterNullishValues(obj, opt = {}) {
91
+ return _filterObject(obj, (_k, v) => v !== undefined && v !== null, opt);
92
92
  }
93
93
  /**
94
94
  * Removes values from the object that are `undefined`.
95
95
  * Only `undefined` values are removed. `null` values are kept!
96
96
  */
97
- export function _filterUndefinedValues(obj, mutate = false) {
98
- return _filterObject(obj, (_k, v) => v !== undefined, mutate);
97
+ export function _filterUndefinedValues(obj, opt = {}) {
98
+ return _filterObject(obj, (_k, v) => v !== undefined, opt);
99
99
  }
100
- export function _filterEmptyArrays(obj, mutate = false) {
101
- return _filterObject(obj, (_k, v) => !Array.isArray(v) || v.length > 0, mutate);
100
+ export function _filterEmptyArrays(obj, opt = {}) {
101
+ return _filterObject(obj, (_k, v) => !Array.isArray(v) || v.length > 0, opt);
102
102
  }
103
103
  /**
104
104
  * Returns clone of `obj` without properties that does not pass `predicate`.
105
105
  * Allows filtering by both key and value.
106
106
  */
107
- export function _filterObject(obj, predicate, mutate = false) {
108
- if (mutate) {
107
+ export function _filterObject(obj, predicate, opt = {}) {
108
+ if (opt.mutate) {
109
109
  for (const [k, v] of _objectEntries(obj)) {
110
110
  if (!predicate(k, v, obj)) {
111
111
  delete obj[k];
@@ -132,8 +132,8 @@ export function _filterObject(obj, predicate, mutate = false) {
132
132
  *
133
133
  * To skip some key-value pairs - use _mapObject instead.
134
134
  */
135
- export function _mapValues(obj, mapper, mutate = false) {
136
- const map = mutate ? obj : {};
135
+ export function _mapValues(obj, mapper, opt = {}) {
136
+ const map = opt.mutate ? obj : {};
137
137
  for (const [k, v] of Object.entries(obj)) {
138
138
  map[k] = mapper(k, v, obj);
139
139
  }
@@ -183,8 +183,8 @@ export function _mapObject(obj, mapper) {
183
183
  export function _findKeyByValue(obj, v) {
184
184
  return Object.entries(obj).find(([_, value]) => value === v)?.[0];
185
185
  }
186
- export function _objectNullValuesToUndefined(obj, mutate = false) {
187
- return _mapValues(obj, (_k, v) => (v === null ? undefined : v), mutate);
186
+ export function _objectNullValuesToUndefined(obj, opt = {}) {
187
+ return _mapValues(obj, (_k, v) => (v === null ? undefined : v), opt);
188
188
  }
189
189
  /**
190
190
  * Deep copy object (by json parse/stringify, since it has unbeatable performance+simplicity combo).
@@ -202,8 +202,8 @@ export function _undefinedIfEmpty(obj) {
202
202
  /**
203
203
  * Filters the object by removing all key-value pairs where Value is Empty (according to _isEmpty() specification).
204
204
  */
205
- export function _filterEmptyValues(obj, mutate = false) {
206
- return _filterObject(obj, (_k, v) => !_isEmpty(v), mutate);
205
+ export function _filterEmptyValues(obj, opt = {}) {
206
+ return _filterObject(obj, (_k, v) => !_isEmpty(v), opt);
207
207
  }
208
208
  /**
209
209
  * Recursively merges own and inherited enumerable properties of source
package/dist/types.d.ts CHANGED
@@ -117,10 +117,12 @@ export declare const MISS: unique symbol;
117
117
  /**
118
118
  * Function which is called for every item in `input`. Expected to return a `Promise` or value.
119
119
  */
120
- export type AsyncMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT | PromiseLike<OUT>;
121
- export type Mapper<IN = any, OUT = any> = (input: IN, index: number) => OUT;
122
- export declare const _passthroughMapper: Mapper;
123
- export declare const _passUndefinedMapper: Mapper<any, void>;
120
+ export type AsyncMapper<IN = any, OUT = any> = (input: IN) => OUT | PromiseLike<OUT>;
121
+ export type AsyncIndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT | PromiseLike<OUT>;
122
+ export type Mapper<IN = any, OUT = any> = (input: IN) => OUT;
123
+ export type IndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT;
124
+ export declare const _passthroughMapper: IndexedMapper;
125
+ export declare const _passUndefinedMapper: IndexedMapper<any, void>;
124
126
  /**
125
127
  * Function that does nothings and returns `undefined`.
126
128
  */
@@ -326,7 +328,7 @@ export declare const _objectAssign: <T extends AnyObject>(target: T, part: Parti
326
328
  */
327
329
  export type ErrorDataTuple<T = unknown, ERR = Error> = [err: null, data: T] | [err: ERR, data: null];
328
330
  export type SortDirection = 'asc' | 'desc';
329
- export type Inclusiveness = '()' | '[]' | '[)' | '(]';
331
+ export type Inclusiveness = '[]' | '[)';
330
332
  /**
331
333
  * @experimental
332
334
  */
package/dist/types.js CHANGED
@@ -24,7 +24,7 @@ export const _passNothingPredicate = () => false;
24
24
  * Like _stringMapValues, but values are sorted.
25
25
  */
26
26
  export function _stringMapValuesSorted(map, mapper, dir = 'asc') {
27
- return _sortBy(_stringMapValues(map), mapper, false, dir);
27
+ return _sortBy(_stringMapValues(map), mapper, { dir });
28
28
  }
29
29
  /**
30
30
  * Needed due to https://github.com/microsoft/TypeScript/issues/13778
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.8.0",
4
+ "version": "15.9.0",
5
5
  "dependencies": {
6
6
  "tslib": "^2",
7
7
  "zod": "^3"
@@ -61,9 +61,9 @@ export function _pushUniq<T>(a: T[], ...items: T[]): T[] {
61
61
  * Mutates the array (same as normal `push`).
62
62
  */
63
63
  export function _pushUniqBy<T>(a: T[], mapper: Mapper<T, any>, ...items: T[]): T[] {
64
- const mappedSet = new Set(a.map((item, i) => mapper(item, i)))
65
- items.forEach((item, i) => {
66
- const mapped = mapper(item, i)
64
+ const mappedSet = new Set(a.map(mapper))
65
+ items.forEach(item => {
66
+ const mapped = mapper(item)
67
67
  if (!mappedSet.has(mapped)) {
68
68
  a.push(item)
69
69
  mappedSet.add(mapped)
@@ -91,8 +91,9 @@ export function _pushUniqBy<T>(a: T[], mapper: Mapper<T, any>, ...items: T[]): T
91
91
  */
92
92
  export function _uniqBy<T>(arr: readonly T[], mapper: Mapper<T, any>): T[] {
93
93
  const map = new Map<any, T>()
94
- for (const [i, item] of arr.entries()) {
95
- const key = item === undefined || item === null ? item : mapper(item, i)
94
+ for (let i = 0; i < arr.length; i++) {
95
+ const item = arr[i]!
96
+ const key = item === undefined || item === null ? item : mapper(item)
96
97
  if (!map.has(key)) map.set(key, item)
97
98
  }
98
99
  return [...map.values()]
@@ -119,9 +120,16 @@ export function _uniqBy<T>(arr: readonly T[], mapper: Mapper<T, any>): T[] {
119
120
  * Returning `undefined` from the Mapper will EXCLUDE the item.
120
121
  */
121
122
  export function _by<T>(items: readonly T[], mapper: Mapper<T, any>): StringMap<T> {
122
- return Object.fromEntries(
123
- items.map((item, i) => [mapper(item, i), item]).filter(([k]) => k !== undefined) as [any, T][],
124
- )
123
+ const map: StringMap<T> = {}
124
+ for (let i = 0; i < items.length; i++) {
125
+ const v = items[i]!
126
+ const k = mapper(v)
127
+ if (k !== undefined) {
128
+ map[k] = v
129
+ }
130
+ }
131
+
132
+ return map
125
133
  }
126
134
 
127
135
  /**
@@ -131,12 +139,15 @@ export function _mapBy<ITEM, KEY>(
131
139
  items: readonly ITEM[],
132
140
  mapper: Mapper<ITEM, KEY>,
133
141
  ): Map<KEY, ITEM> {
134
- return new Map(
135
- items.map((item, i) => [mapper(item, i), item]).filter(([k]) => k !== undefined) as [
136
- KEY,
137
- ITEM,
138
- ][],
139
- )
142
+ const map = new Map<KEY, ITEM>()
143
+ for (let i = 0; i < items.length; i++) {
144
+ const item = items[i]!
145
+ const key = mapper(item)
146
+ if (key !== undefined) {
147
+ map.set(key, item)
148
+ }
149
+ }
150
+ return map
140
151
  }
141
152
 
142
153
  /**
@@ -152,14 +163,31 @@ export function _mapBy<ITEM, KEY>(
152
163
  */
153
164
  export function _groupBy<T>(items: readonly T[], mapper: Mapper<T, any>): StringMap<T[]> {
154
165
  const map: StringMap<T[]> = {}
155
- for (const [i, item] of items.entries()) {
156
- const key = mapper(item, i)
157
- if (key === undefined) continue
158
- ;(map[key] ||= []).push(item)
166
+
167
+ for (let i = 0; i < items.length; i++) {
168
+ const item = items[i]!
169
+ const key = mapper(item)
170
+ if (key !== undefined) {
171
+ ;(map[key] ||= []).push(item)
172
+ }
159
173
  }
160
174
  return map
161
175
  }
162
176
 
177
+ export interface MutateOptions {
178
+ /**
179
+ * Defaults to false.
180
+ */
181
+ mutate?: boolean
182
+ }
183
+
184
+ export interface SortByOptions extends MutateOptions {
185
+ /**
186
+ * Defaults to 'asc'.
187
+ */
188
+ dir?: SortDirection
189
+ }
190
+
163
191
  /**
164
192
  * _sortBy([{age: 20}, {age: 10}], 'age')
165
193
  * // => [{age: 10}, {age: 20}]
@@ -167,34 +195,34 @@ export function _groupBy<T>(items: readonly T[], mapper: Mapper<T, any>): String
167
195
  * Same:
168
196
  * _sortBy([{age: 20}, {age: 10}], o => o.age)
169
197
  */
170
- export function _sortBy<T>(
198
+ export function _sortBy<T, COMPARE_TYPE extends string | number>(
171
199
  items: T[],
172
- mapper: Mapper<T, any>,
173
- mutate = false,
174
- dir: SortDirection = 'asc',
200
+ mapper: Mapper<T, COMPARE_TYPE>,
201
+ opt: SortByOptions = {},
175
202
  ): T[] {
176
- const mod = dir === 'desc' ? -1 : 1
177
- return (mutate ? items : [...items]).sort((_a, _b) => {
178
- const [a, b] = [_a, _b].map(mapper)
179
- if (typeof a === 'number' && typeof b === 'number') return (a - b) * mod
180
- return String(a).localeCompare(String(b)) * mod
203
+ const mod = opt.dir === 'desc' ? -1 : 1
204
+
205
+ return (opt.mutate ? items : [...items]).sort((_a, _b) => {
206
+ // This implementation may call mapper more than once per item,
207
+ // but the benchmarks show no significant difference in performance.
208
+ const a = mapper(_a)
209
+ const b = mapper(_b)
210
+ // if (typeof a === 'number' && typeof b === 'number') return (a - b) * mod
211
+ // return String(a).localeCompare(String(b)) * mod
212
+ if (a > b) return mod
213
+ if (a < b) return -mod
214
+ return 0
181
215
  })
182
216
  }
183
217
 
184
- /**
185
- * Alias for _sortBy with descending order.
186
- */
187
- export function _sortDescBy<T>(items: T[], mapper: Mapper<T, any>, mutate = false): T[] {
188
- return _sortBy(items, mapper, mutate, 'desc')
189
- }
190
-
191
218
  /**
192
219
  * Similar to `Array.find`, but the `predicate` may return `END` to stop the iteration early.
193
220
  *
194
221
  * Use `Array.find` if you don't need to stop the iteration early.
195
222
  */
196
223
  export function _find<T>(items: readonly T[], predicate: AbortablePredicate<T>): T | undefined {
197
- for (const [i, item] of items.entries()) {
224
+ for (let i = 0; i < items.length; i++) {
225
+ const item = items[i]!
198
226
  const result = predicate(item, i)
199
227
  if (result === END) return
200
228
  if (result) return item
@@ -290,9 +318,8 @@ export function _count<T>(
290
318
  export function _countBy<T>(items: Iterable<T>, mapper: Mapper<T, any>): StringMap<number> {
291
319
  const map: StringMap<number> = {}
292
320
 
293
- let i = 0
294
321
  for (const item of items) {
295
- const key = mapper(item, i++)
322
+ const key = mapper(item)
296
323
  map[key] = (map[key] || 0) + 1
297
324
  }
298
325
 
@@ -360,10 +387,9 @@ export function _sumBy<T, N extends number>(
360
387
  mapper: Mapper<T, N | undefined>,
361
388
  ): N {
362
389
  let sum = 0 as N
363
- let i = 0
364
390
 
365
391
  for (const n of items) {
366
- const v = mapper(n, i++)
392
+ const v = mapper(n)
367
393
  if (typeof v === 'number') {
368
394
  // count only numbers, nothing else
369
395
  sum = (sum + v) as N
@@ -407,8 +433,8 @@ export function _mapToObject<T, V>(
407
433
  * Fisher–Yates algorithm.
408
434
  * Based on: https://stackoverflow.com/a/12646864/4919972
409
435
  */
410
- export function _shuffle<T>(array: T[], mutate = false): T[] {
411
- const a = mutate ? array : [...array]
436
+ export function _shuffle<T>(array: T[], opt: MutateOptions = {}): T[] {
437
+ const a = opt.mutate ? array : [...array]
412
438
 
413
439
  for (let i = a.length - 1; i > 0; i--) {
414
440
  const j = Math.floor(Math.random() * (i + 1))
@@ -505,8 +531,9 @@ export function _maxByOrUndefined<T>(
505
531
  let maxItem: T | undefined
506
532
  let max: number | string | undefined
507
533
 
508
- for (const [i, item] of array.entries()) {
509
- const v = mapper(item, i)
534
+ for (let i = 0; i < array.length; i++) {
535
+ const item = array[i]!
536
+ const v = mapper(item)
510
537
  if (v !== undefined && (max === undefined || v > max)) {
511
538
  maxItem = item
512
539
  max = v
@@ -524,8 +551,9 @@ export function _minByOrUndefined<T>(
524
551
  let minItem: T | undefined
525
552
  let min: number | string | undefined
526
553
 
527
- for (const [i, item] of array.entries()) {
528
- const v = mapper(item, i)
554
+ for (let i = 0; i < array.length; i++) {
555
+ const item = array[i]!
556
+ const v = mapper(item)
529
557
  if (v !== undefined && (min === undefined || v < min)) {
530
558
  minItem = item
531
559
  min = v
@@ -36,7 +36,7 @@ export function _range(fromIncl: Integer, toExcl?: Integer, step = 1): number[]
36
36
  * Fill is Primitive, because it's safe to shallow-copy.
37
37
  * If it was an object - it'll paste the same object reference, which can create bugs.
38
38
  */
39
- export function _rangeFilled<T extends Primitive>(length: Integer, fill: T): T[] {
39
+ export function _arrayFilled<T extends Primitive>(length: Integer, fill: T): T[] {
40
40
  // biome-ignore lint/style/useConsistentBuiltinInstantiation: ok
41
41
  return Array(length).fill(fill)
42
42
  }
@@ -1,4 +1,4 @@
1
- import type { Inclusiveness, IsoDate } from '../types.js'
1
+ import type { IsoDate } from '../types.js'
2
2
  import type { LocalDate, LocalDateInput, LocalDateUnit } from './localDate.js'
3
3
  import { localDate } from './localDate.js'
4
4
 
@@ -60,16 +60,13 @@ export class DateInterval {
60
60
  /**
61
61
  * Ranges of DateInterval (start, end) are INCLUSIVE.
62
62
  */
63
- includes(d: LocalDateInput, incl: Inclusiveness = '[]'): boolean {
64
- d = localDate(d)
65
- // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
66
- return d.isAfter(this.start, incl[0] === '[') && d.isBefore(this.end, incl[1] === ']')
63
+ includes(d: LocalDateInput): boolean {
64
+ return localDate(d).isBetween(this.start, this.end, '[]')
67
65
  }
68
66
 
69
- intersects(int: DateIntervalConfig, inclusive = true): boolean {
67
+ intersects(int: DateIntervalConfig): boolean {
70
68
  const $int = DateInterval.parse(int)
71
- const incl = inclusive ? '[]' : '()'
72
- return this.includes($int.start, incl) || this.includes($int.end, incl)
69
+ return this.includes($int.start) || this.includes($int.end)
73
70
  }
74
71
 
75
72
  /**
@@ -81,15 +78,15 @@ export class DateInterval {
81
78
  return this.start.compare(d.start) || this.end.compare(d.end)
82
79
  }
83
80
 
84
- getDays(incl: Inclusiveness = '[]'): LocalDate[] {
85
- return localDate.range(this.start, this.end, incl, 1, 'day')
81
+ getDays(): LocalDate[] {
82
+ return localDate.range(this.start, this.end, '[]', 1, 'day')
86
83
  }
87
84
 
88
85
  /**
89
86
  * Returns an array of LocalDates that are included in the interval.
90
87
  */
91
- range(incl: Inclusiveness = '[]', step = 1, stepUnit: LocalDateUnit = 'day'): LocalDate[] {
92
- return localDate.range(this.start, this.end, incl, step, stepUnit)
88
+ range(step = 1, stepUnit: LocalDateUnit = 'day'): LocalDate[] {
89
+ return localDate.range(this.start, this.end, '[]', step, stepUnit)
93
90
  }
94
91
 
95
92
  toString(): DateIntervalString {
@@ -117,10 +117,9 @@ export class LocalDate {
117
117
  return this.compare(d) >= 0
118
118
  }
119
119
 
120
- isBetween(min: LocalDateInput, max: LocalDateInput, incl: Inclusiveness = '[)'): boolean {
120
+ isBetween(min: LocalDateInput, max: LocalDateInput, incl: Inclusiveness): boolean {
121
121
  let r = this.compare(min)
122
- // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
123
- if (r < 0 || (r === 0 && incl[0] === '(')) return false
122
+ if (r < 0) return false
124
123
  r = this.compare(max)
125
124
  if (r > 0 || (r === 0 && incl[1] === ')')) return false
126
125
  return true
@@ -779,7 +778,7 @@ class LocalDateFactory {
779
778
  range(
780
779
  min: LocalDateInput,
781
780
  max: LocalDateInput,
782
- incl: Inclusiveness = '[)',
781
+ incl: Inclusiveness,
783
782
  step = 1,
784
783
  stepUnit: LocalDateUnit = 'day',
785
784
  ): LocalDate[] {
@@ -793,7 +792,7 @@ class LocalDateFactory {
793
792
  rangeIterable(
794
793
  min: LocalDateInput,
795
794
  max: LocalDateInput,
796
- incl: Inclusiveness = '[)',
795
+ incl: Inclusiveness,
797
796
  step = 1,
798
797
  stepUnit: LocalDateUnit = 'day',
799
798
  ): Iterable2<LocalDate> {
@@ -806,8 +805,8 @@ class LocalDateFactory {
806
805
  const $max = this.fromInput(max).startOf(stepUnit)
807
806
 
808
807
  let value = $min
809
- // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
810
- if (value.isAfter($min, incl[0] === '[')) {
808
+
809
+ if (value.isSameOrAfter($min)) {
811
810
  // ok
812
811
  } else {
813
812
  value.plus(1, stepUnit, true)
@@ -517,10 +517,9 @@ export class LocalTime {
517
517
  return this.compare(d) >= 0
518
518
  }
519
519
 
520
- isBetween(min: LocalTimeInput, max: LocalTimeInput, incl: Inclusiveness = '[)'): boolean {
520
+ isBetween(min: LocalTimeInput, max: LocalTimeInput, incl: Inclusiveness): boolean {
521
521
  let r = this.compare(min)
522
- // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
523
- if (r < 0 || (r === 0 && incl[0] === '(')) return false
522
+ if (r < 0) return false
524
523
  r = this.compare(max)
525
524
  if (r > 0 || (r === 0 && incl[1] === ')')) return false
526
525
  return true
@@ -1,4 +1,4 @@
1
- import type { Inclusiveness, UnixTimestamp } from '../types.js'
1
+ import type { UnixTimestamp } from '../types.js'
2
2
  import type { LocalTime, LocalTimeInput } from './localTime.js'
3
3
  import { localTime } from './localTime.js'
4
4
 
@@ -74,11 +74,10 @@ export class TimeInterval {
74
74
  return this.cmp(d) >= 0
75
75
  }
76
76
 
77
- includes(d: LocalTimeInput, incl: Inclusiveness = '[)'): boolean {
77
+ includes(d: LocalTimeInput): boolean {
78
78
  d = localTime.fromInput(d).unix
79
- // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
80
- if (d < this.$start || (d === this.$start && incl[0] === '(')) return false
81
- if (d > this.$end || (d === this.$end && incl[1] === ')')) return false
79
+ if (d < this.$start) return false
80
+ if (d > this.$end) return false
82
81
  return true
83
82
  }
84
83
 
@@ -803,7 +803,7 @@ export class Fetcher {
803
803
  }
804
804
 
805
805
  // Because all header values are stringified, so `a: undefined` becomes `undefined` as a string
806
- _filterNullishValues(req.init.headers, true)
806
+ _filterNullishValues(req.init.headers, { mutate: true })
807
807
 
808
808
  // setup url
809
809
  const baseUrl = opt.baseUrl || this.cfg.baseUrl
@@ -32,5 +32,5 @@ export function mergeJsonSchemaObjects<T1 extends AnyObject, T2 extends AnyObjec
32
32
 
33
33
  // `additionalProperties` remains the same
34
34
 
35
- return _filterNullishValues(s1, true) as any
35
+ return _filterNullishValues(s1, { mutate: true }) as any
36
36
  }
@@ -29,7 +29,6 @@ export function _averageOrNull(values: number[] | undefined | null): number | nu
29
29
  export function _averageWeighted(values: number[], weights: number[]): number {
30
30
  let numerator = 0
31
31
  let denominator = 0
32
- // eslint-disable-next-line unicorn/no-for-loop
33
32
  for (let i = 0; i < values.length; i++) {
34
33
  numerator += values[i]! * weights[i]!
35
34
  denominator += weights[i]!
@@ -42,18 +42,11 @@ export function _isBetween<T extends number | string>(
42
42
  x: T,
43
43
  min: T,
44
44
  max: T,
45
- incl: Inclusiveness = '[)',
45
+ incl: Inclusiveness,
46
46
  ): boolean {
47
- if (incl === '[)') {
48
- return x >= min && x < max
49
- }
50
- if (incl === '[]') {
51
- return x >= min && x <= max
52
- }
53
- if (incl === '(]') {
54
- return x > min && x <= max
55
- }
56
- return x > min && x < max
47
+ if (x < min || x > max) return false
48
+ if (x === max && incl === '[)') return false
49
+ return true
57
50
  }
58
51
 
59
52
  export function _clamp(x: number, minIncl: number, maxIncl: number): number {