@naturalcycles/js-lib 14.239.0 → 14.240.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,6 +4,7 @@ import { DateObject, ISODayOfWeek, LocalTime } from './localTime';
4
4
  export type LocalDateUnit = LocalDateUnitStrict | 'week';
5
5
  export type LocalDateUnitStrict = 'year' | 'month' | 'day';
6
6
  export type LocalDateInput = LocalDate | Date | IsoDateString;
7
+ export type LocalDateInputNullable = LocalDateInput | null | undefined;
7
8
  export type LocalDateFormatter = (ld: LocalDate) => string;
8
9
  /**
9
10
  * LocalDate represents a date without time.
@@ -166,7 +167,7 @@ declare class LocalDateFactory {
166
167
  * Tries to construct LocalDate from LocalDateInput, returns null otherwise.
167
168
  * Does not throw (returns null instead).
168
169
  */
169
- parseOrNull(d: LocalDateInput | undefined | null): LocalDate | null;
170
+ parseOrNull(d: LocalDateInputNullable): LocalDate | null;
170
171
  /**
171
172
  * Parses "compact iso8601 format", e.g `19840621` into LocalDate.
172
173
  * Throws if it fails to do so.
@@ -204,21 +205,21 @@ declare class LocalDateFactory {
204
205
  /**
205
206
  * Returns the earliest (min) LocalDate from the array, or undefined if the array is empty.
206
207
  */
207
- minOrUndefined(items: LocalDateInput[]): LocalDate | undefined;
208
+ minOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined;
208
209
  /**
209
210
  * Returns the earliest LocalDate from the array.
210
211
  * Throws if the array is empty.
211
212
  */
212
- min(items: LocalDateInput[]): LocalDate;
213
+ min(items: LocalDateInputNullable[]): LocalDate;
213
214
  /**
214
215
  * Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
215
216
  */
216
- maxOrUndefined(items: LocalDateInput[]): LocalDate | undefined;
217
+ maxOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined;
217
218
  /**
218
219
  * Returns the latest LocalDate from the array.
219
220
  * Throws if the array is empty.
220
221
  */
221
- max(items: LocalDateInput[]): LocalDate;
222
+ max(items: LocalDateInputNullable[]): LocalDate;
222
223
  /**
223
224
  * Returns the range (array) of LocalDates between min and max.
224
225
  * By default, min is included, max is excluded.
@@ -234,11 +235,11 @@ declare class LocalDateFactory {
234
235
  *
235
236
  * Similar to `localDate.orToday`, but that will instead return Today on falsy input.
236
237
  */
237
- orUndefined(d: LocalDateInput | null | undefined): LocalDate | undefined;
238
+ orUndefined(d: LocalDateInputNullable): LocalDate | undefined;
238
239
  /**
239
240
  * Creates a LocalDate from the input, unless it's falsy - then returns localDate.today.
240
241
  */
241
- orToday(d: LocalDateInput | null | undefined): LocalDate;
242
+ orToday(d: LocalDateInputNullable): LocalDate;
242
243
  }
243
244
  interface LocalDateFn extends LocalDateFactory {
244
245
  (d: LocalDateInput): LocalDate;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.todayString = exports.localDate = exports.LocalDate = void 0;
4
4
  const assert_1 = require("../error/assert");
5
+ const is_util_1 = require("../is.util");
5
6
  const iterable2_1 = require("../iter/iterable2");
6
7
  const localTime_1 = require("./localTime");
7
8
  const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
@@ -537,8 +538,11 @@ class LocalDateFactory {
537
538
  * Throws if the array is empty.
538
539
  */
539
540
  min(items) {
540
- (0, assert_1._assert)(items.length, 'localDate.min called on empty array');
541
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
541
+ const items2 = items.filter(is_util_1._isTruthy);
542
+ (0, assert_1._assert)(items2.length, 'localDate.min called on empty array');
543
+ return items2
544
+ .map(i => this.of(i))
545
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
542
546
  }
543
547
  /**
544
548
  * Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
@@ -551,8 +555,9 @@ class LocalDateFactory {
551
555
  * Throws if the array is empty.
552
556
  */
553
557
  max(items) {
554
- (0, assert_1._assert)(items.length, 'localDate.max called on empty array');
555
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
558
+ const items2 = items.filter(is_util_1._isTruthy);
559
+ (0, assert_1._assert)(items2.length, 'localDate.max called on empty array');
560
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
556
561
  }
557
562
  /**
558
563
  * Returns the range (array) of LocalDates between min and max.
@@ -12,6 +12,7 @@ export declare enum ISODayOfWeek {
12
12
  SUNDAY = 7
13
13
  }
14
14
  export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber;
15
+ export type LocalTimeInputNullable = LocalTimeInput | null | undefined;
15
16
  export type LocalTimeFormatter = (ld: LocalTime) => string;
16
17
  export type DateTimeObject = DateObject & TimeObject;
17
18
  export interface DateObject {
@@ -226,10 +227,10 @@ declare class LocalTimeFactory {
226
227
  /**
227
228
  * Returns null if invalid
228
229
  */
229
- parseOrNull(d: LocalTimeInput | undefined | null): LocalTime | null;
230
+ parseOrNull(d: LocalTimeInputNullable): LocalTime | null;
230
231
  parseToDate(d: LocalTimeInput): Date;
231
232
  parseToUnixTimestamp(d: LocalTimeInput): UnixTimestampNumber;
232
- isValid(d: LocalTimeInput | undefined | null): boolean;
233
+ isValid(d: LocalTimeInputNullable): boolean;
233
234
  /**
234
235
  * Returns the IANA timezone e.g `Europe/Stockholm`.
235
236
  * https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
@@ -249,20 +250,20 @@ declare class LocalTimeFactory {
249
250
  *
250
251
  * `localTime` function will instead return LocalTime of `now` for falsy input.
251
252
  */
252
- orUndefined(d: LocalTimeInput | null | undefined): LocalTime | undefined;
253
+ orUndefined(d: LocalTimeInputNullable): LocalTime | undefined;
253
254
  /**
254
255
  * Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
255
256
  */
256
- orNow(d: LocalTimeInput | null | undefined): LocalTime;
257
+ orNow(d: LocalTimeInputNullable): LocalTime;
257
258
  fromComponents(c: {
258
259
  year: number;
259
260
  month: number;
260
261
  } & Partial<DateTimeObject>): LocalTime;
261
262
  sort(items: LocalTime[], dir?: SortDirection, mutate?: boolean): LocalTime[];
262
- minOrUndefined(items: LocalTimeInput[]): LocalTime | undefined;
263
- min(items: LocalTimeInput[]): LocalTime;
264
- maxOrUndefined(items: LocalTimeInput[]): LocalTime | undefined;
265
- max(items: LocalTimeInput[]): LocalTime;
263
+ minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined;
264
+ min(items: LocalTimeInputNullable[]): LocalTime;
265
+ maxOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined;
266
+ max(items: LocalTimeInputNullable[]): LocalTime;
266
267
  }
267
268
  interface LocalTimeFn extends LocalTimeFactory {
268
269
  (d: LocalTimeInput): LocalTime;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.nowUnix = exports.localTime = exports.LocalTime = exports.ISODayOfWeek = void 0;
4
4
  const assert_1 = require("../error/assert");
5
+ const is_util_1 = require("../is.util");
5
6
  const time_util_1 = require("../time/time.util");
6
7
  const localDate_1 = require("./localDate");
7
8
  const wallTime_1 = require("./wallTime");
@@ -705,8 +706,9 @@ class LocalTimeFactory {
705
706
  return items.length ? this.min(items) : undefined;
706
707
  }
707
708
  min(items) {
708
- (0, assert_1._assert)(items.length, 'localTime.min called on empty array');
709
- return items
709
+ const items2 = items.filter(is_util_1._isTruthy);
710
+ (0, assert_1._assert)(items2.length, 'localTime.min called on empty array');
711
+ return items2
710
712
  .map(i => this.of(i))
711
713
  .reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
712
714
  }
@@ -714,8 +716,9 @@ class LocalTimeFactory {
714
716
  return items.length ? this.max(items) : undefined;
715
717
  }
716
718
  max(items) {
717
- (0, assert_1._assert)(items.length, 'localTime.max called on empty array');
718
- return items
719
+ const items2 = items.filter(is_util_1._isTruthy);
720
+ (0, assert_1._assert)(items2.length, 'localTime.max called on empty array');
721
+ return items2
719
722
  .map(i => this.of(i))
720
723
  .reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
721
724
  }
package/dist/semver.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import { SortDirection } from './types';
1
2
  export type SemverInput = string | Semver;
3
+ export type SemverInputNullable = SemverInput | null | undefined;
2
4
  export type SemverTokens = [major: number, minor: number, patch: number];
3
5
  /**
4
6
  * Simple Semver implementation.
@@ -38,25 +40,29 @@ export declare class Semver {
38
40
  }
39
41
  declare class SemverFactory {
40
42
  of(input: SemverInput): Semver;
41
- parseOrNull(input: SemverInput | undefined | null): Semver | null;
43
+ parseOrNull(input: SemverInputNullable): Semver | null;
42
44
  /**
43
45
  * Returns the highest (max) Semver from the array, or undefined if the array is empty.
44
46
  */
45
- maxOrUndefined(items: SemverInput[]): Semver | undefined;
47
+ maxOrUndefined(items: SemverInputNullable[]): Semver | undefined;
46
48
  /**
47
49
  * Returns the highest Semver from the array.
48
50
  * Throws if the array is empty.
49
51
  */
50
- max(items: SemverInput[]): Semver;
52
+ max(items: SemverInputNullable[]): Semver;
51
53
  /**
52
54
  * Returns the lowest (min) Semver from the array, or undefined if the array is empty.
53
55
  */
54
- minOrUndefined(items: SemverInput[]): Semver | undefined;
56
+ minOrUndefined(items: SemverInputNullable[]): Semver | undefined;
55
57
  /**
56
58
  * Returns the lowest Semver from the array.
57
59
  * Throws if the array is empty.
58
60
  */
59
- min(items: SemverInput[]): Semver;
61
+ min(items: SemverInputNullable[]): Semver;
62
+ /**
63
+ * Sorts an array of Semvers in `dir` order (ascending by default).
64
+ */
65
+ sort(items: Semver[], dir?: SortDirection, mutate?: boolean): Semver[];
60
66
  }
61
67
  interface SemverFn extends SemverFactory {
62
68
  (input: SemverInput): Semver;
package/dist/semver.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._quickSemverCompare = exports.semver2 = exports.Semver = void 0;
4
4
  const range_1 = require("./array/range");
5
5
  const assert_1 = require("./error/assert");
6
+ const is_util_1 = require("./is.util");
6
7
  /**
7
8
  * Simple Semver implementation.
8
9
  *
@@ -86,8 +87,9 @@ class SemverFactory {
86
87
  * Throws if the array is empty.
87
88
  */
88
89
  max(items) {
89
- (0, assert_1._assert)(items.length, 'semver.max called on empty array');
90
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
90
+ const items2 = items.filter(is_util_1._isTruthy);
91
+ (0, assert_1._assert)(items2.length, 'semver.max called on empty array');
92
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
91
93
  }
92
94
  /**
93
95
  * Returns the lowest (min) Semver from the array, or undefined if the array is empty.
@@ -100,8 +102,18 @@ class SemverFactory {
100
102
  * Throws if the array is empty.
101
103
  */
102
104
  min(items) {
103
- (0, assert_1._assert)(items.length, 'semver.min called on empty array');
104
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
105
+ const items2 = items.filter(is_util_1._isTruthy);
106
+ (0, assert_1._assert)(items2.length, 'semver.min called on empty array');
107
+ return items2
108
+ .map(i => this.of(i))
109
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
110
+ }
111
+ /**
112
+ * Sorts an array of Semvers in `dir` order (ascending by default).
113
+ */
114
+ sort(items, dir = 'asc', mutate = false) {
115
+ const mod = dir === 'desc' ? -1 : 1;
116
+ return (mutate ? items : [...items]).sort((a, b) => a.cmp(b) * mod);
105
117
  }
106
118
  }
107
119
  const semverFactory = new SemverFactory();
@@ -1,4 +1,5 @@
1
1
  import { _assert } from '../error/assert';
2
+ import { _isTruthy } from '../is.util';
2
3
  import { Iterable2 } from '../iter/iterable2';
3
4
  import { localTime } from './localTime';
4
5
  const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
@@ -533,8 +534,11 @@ class LocalDateFactory {
533
534
  * Throws if the array is empty.
534
535
  */
535
536
  min(items) {
536
- _assert(items.length, 'localDate.min called on empty array');
537
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
537
+ const items2 = items.filter(_isTruthy);
538
+ _assert(items2.length, 'localDate.min called on empty array');
539
+ return items2
540
+ .map(i => this.of(i))
541
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
538
542
  }
539
543
  /**
540
544
  * Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
@@ -547,8 +551,9 @@ class LocalDateFactory {
547
551
  * Throws if the array is empty.
548
552
  */
549
553
  max(items) {
550
- _assert(items.length, 'localDate.max called on empty array');
551
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
554
+ const items2 = items.filter(_isTruthy);
555
+ _assert(items2.length, 'localDate.max called on empty array');
556
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
552
557
  }
553
558
  /**
554
559
  * Returns the range (array) of LocalDates between min and max.
@@ -1,4 +1,5 @@
1
1
  import { _assert } from '../error/assert';
2
+ import { _isTruthy } from '../is.util';
2
3
  import { _ms } from '../time/time.util';
3
4
  import { localDate } from './localDate';
4
5
  import { WallTime } from './wallTime';
@@ -701,8 +702,9 @@ class LocalTimeFactory {
701
702
  return items.length ? this.min(items) : undefined;
702
703
  }
703
704
  min(items) {
704
- _assert(items.length, 'localTime.min called on empty array');
705
- return items
705
+ const items2 = items.filter(_isTruthy);
706
+ _assert(items2.length, 'localTime.min called on empty array');
707
+ return items2
706
708
  .map(i => this.of(i))
707
709
  .reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item));
708
710
  }
@@ -710,8 +712,9 @@ class LocalTimeFactory {
710
712
  return items.length ? this.max(items) : undefined;
711
713
  }
712
714
  max(items) {
713
- _assert(items.length, 'localTime.max called on empty array');
714
- return items
715
+ const items2 = items.filter(_isTruthy);
716
+ _assert(items2.length, 'localTime.max called on empty array');
717
+ return items2
715
718
  .map(i => this.of(i))
716
719
  .reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item));
717
720
  }
@@ -1,5 +1,6 @@
1
1
  import { _range } from './array/range';
2
2
  import { _assert } from './error/assert';
3
+ import { _isTruthy } from './is.util';
3
4
  /**
4
5
  * Simple Semver implementation.
5
6
  *
@@ -82,8 +83,9 @@ class SemverFactory {
82
83
  * Throws if the array is empty.
83
84
  */
84
85
  max(items) {
85
- _assert(items.length, 'semver.max called on empty array');
86
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
86
+ const items2 = items.filter(_isTruthy);
87
+ _assert(items2.length, 'semver.max called on empty array');
88
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item));
87
89
  }
88
90
  /**
89
91
  * Returns the lowest (min) Semver from the array, or undefined if the array is empty.
@@ -96,8 +98,18 @@ class SemverFactory {
96
98
  * Throws if the array is empty.
97
99
  */
98
100
  min(items) {
99
- _assert(items.length, 'semver.min called on empty array');
100
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
101
+ const items2 = items.filter(_isTruthy);
102
+ _assert(items2.length, 'semver.min called on empty array');
103
+ return items2
104
+ .map(i => this.of(i))
105
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item));
106
+ }
107
+ /**
108
+ * Sorts an array of Semvers in `dir` order (ascending by default).
109
+ */
110
+ sort(items, dir = 'asc', mutate = false) {
111
+ const mod = dir === 'desc' ? -1 : 1;
112
+ return (mutate ? items : [...items]).sort((a, b) => a.cmp(b) * mod);
101
113
  }
102
114
  }
103
115
  const semverFactory = new SemverFactory();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.239.0",
3
+ "version": "14.240.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -1,4 +1,5 @@
1
1
  import { _assert } from '../error/assert'
2
+ import { _isTruthy } from '../is.util'
2
3
  import { Iterable2 } from '../iter/iterable2'
3
4
  import type {
4
5
  Inclusiveness,
@@ -18,6 +19,7 @@ const MDAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
18
19
  const DATE_REGEX = /^(\d\d\d\d)-(\d\d)-(\d\d)$/
19
20
 
20
21
  export type LocalDateInput = LocalDate | Date | IsoDateString
22
+ export type LocalDateInputNullable = LocalDateInput | null | undefined
21
23
  export type LocalDateFormatter = (ld: LocalDate) => string
22
24
 
23
25
  /**
@@ -517,7 +519,7 @@ class LocalDateFactory {
517
519
  * Tries to construct LocalDate from LocalDateInput, returns null otherwise.
518
520
  * Does not throw (returns null instead).
519
521
  */
520
- parseOrNull(d: LocalDateInput | undefined | null): LocalDate | null {
522
+ parseOrNull(d: LocalDateInputNullable): LocalDate | null {
521
523
  if (!d) return null
522
524
  if (d instanceof LocalDate) return d
523
525
  if (d instanceof Date) {
@@ -619,7 +621,7 @@ class LocalDateFactory {
619
621
  /**
620
622
  * Returns the earliest (min) LocalDate from the array, or undefined if the array is empty.
621
623
  */
622
- minOrUndefined(items: LocalDateInput[]): LocalDate | undefined {
624
+ minOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined {
623
625
  return items.length ? this.min(items) : undefined
624
626
  }
625
627
 
@@ -627,16 +629,19 @@ class LocalDateFactory {
627
629
  * Returns the earliest LocalDate from the array.
628
630
  * Throws if the array is empty.
629
631
  */
630
- min(items: LocalDateInput[]): LocalDate {
631
- _assert(items.length, 'localDate.min called on empty array')
632
+ min(items: LocalDateInputNullable[]): LocalDate {
633
+ const items2 = items.filter(_isTruthy)
634
+ _assert(items2.length, 'localDate.min called on empty array')
632
635
 
633
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
636
+ return items2
637
+ .map(i => this.of(i))
638
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
634
639
  }
635
640
 
636
641
  /**
637
642
  * Returns the latest (max) LocalDate from the array, or undefined if the array is empty.
638
643
  */
639
- maxOrUndefined(items: LocalDateInput[]): LocalDate | undefined {
644
+ maxOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined {
640
645
  return items.length ? this.max(items) : undefined
641
646
  }
642
647
 
@@ -644,10 +649,11 @@ class LocalDateFactory {
644
649
  * Returns the latest LocalDate from the array.
645
650
  * Throws if the array is empty.
646
651
  */
647
- max(items: LocalDateInput[]): LocalDate {
648
- _assert(items.length, 'localDate.max called on empty array')
652
+ max(items: LocalDateInputNullable[]): LocalDate {
653
+ const items2 = items.filter(_isTruthy)
654
+ _assert(items2.length, 'localDate.max called on empty array')
649
655
 
650
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
656
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
651
657
  }
652
658
 
653
659
  /**
@@ -711,14 +717,14 @@ class LocalDateFactory {
711
717
  *
712
718
  * Similar to `localDate.orToday`, but that will instead return Today on falsy input.
713
719
  */
714
- orUndefined(d: LocalDateInput | null | undefined): LocalDate | undefined {
720
+ orUndefined(d: LocalDateInputNullable): LocalDate | undefined {
715
721
  return d ? this.of(d) : undefined
716
722
  }
717
723
 
718
724
  /**
719
725
  * Creates a LocalDate from the input, unless it's falsy - then returns localDate.today.
720
726
  */
721
- orToday(d: LocalDateInput | null | undefined): LocalDate {
727
+ orToday(d: LocalDateInputNullable): LocalDate {
722
728
  return d ? this.of(d) : this.today()
723
729
  }
724
730
  }
@@ -1,4 +1,5 @@
1
1
  import { _assert } from '../error/assert'
2
+ import { _isTruthy } from '../is.util'
2
3
  import { _ms } from '../time/time.util'
3
4
  import type {
4
5
  Inclusiveness,
@@ -27,6 +28,7 @@ export enum ISODayOfWeek {
27
28
  }
28
29
 
29
30
  export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber
31
+ export type LocalTimeInputNullable = LocalTimeInput | null | undefined
30
32
  export type LocalTimeFormatter = (ld: LocalTime) => string
31
33
 
32
34
  export type DateTimeObject = DateObject & TimeObject
@@ -711,7 +713,7 @@ class LocalTimeFactory {
711
713
  /**
712
714
  * Returns null if invalid
713
715
  */
714
- parseOrNull(d: LocalTimeInput | undefined | null): LocalTime | null {
716
+ parseOrNull(d: LocalTimeInputNullable): LocalTime | null {
715
717
  if (!d) return null
716
718
  if (d instanceof LocalTime) return d
717
719
 
@@ -768,7 +770,7 @@ class LocalTimeFactory {
768
770
  return date.valueOf() / 1000
769
771
  }
770
772
 
771
- isValid(d: LocalTimeInput | undefined | null): boolean {
773
+ isValid(d: LocalTimeInputNullable): boolean {
772
774
  return this.parseOrNull(d) !== null
773
775
  }
774
776
 
@@ -800,14 +802,14 @@ class LocalTimeFactory {
800
802
  *
801
803
  * `localTime` function will instead return LocalTime of `now` for falsy input.
802
804
  */
803
- orUndefined(d: LocalTimeInput | null | undefined): LocalTime | undefined {
805
+ orUndefined(d: LocalTimeInputNullable): LocalTime | undefined {
804
806
  return d ? this.of(d) : undefined
805
807
  }
806
808
 
807
809
  /**
808
810
  * Creates a LocalTime from the input, unless it's falsy - then returns LocalTime.now
809
811
  */
810
- orNow(d: LocalTimeInput | null | undefined): LocalTime {
812
+ orNow(d: LocalTimeInputNullable): LocalTime {
811
813
  return d ? this.of(d) : this.now()
812
814
  }
813
815
 
@@ -827,26 +829,28 @@ class LocalTimeFactory {
827
829
  })
828
830
  }
829
831
 
830
- minOrUndefined(items: LocalTimeInput[]): LocalTime | undefined {
832
+ minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined {
831
833
  return items.length ? this.min(items) : undefined
832
834
  }
833
835
 
834
- min(items: LocalTimeInput[]): LocalTime {
835
- _assert(items.length, 'localTime.min called on empty array')
836
+ min(items: LocalTimeInputNullable[]): LocalTime {
837
+ const items2 = items.filter(_isTruthy)
838
+ _assert(items2.length, 'localTime.min called on empty array')
836
839
 
837
- return items
840
+ return items2
838
841
  .map(i => this.of(i))
839
842
  .reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item))
840
843
  }
841
844
 
842
- maxOrUndefined(items: LocalTimeInput[]): LocalTime | undefined {
845
+ maxOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined {
843
846
  return items.length ? this.max(items) : undefined
844
847
  }
845
848
 
846
- max(items: LocalTimeInput[]): LocalTime {
847
- _assert(items.length, 'localTime.max called on empty array')
849
+ max(items: LocalTimeInputNullable[]): LocalTime {
850
+ const items2 = items.filter(_isTruthy)
851
+ _assert(items2.length, 'localTime.max called on empty array')
848
852
 
849
- return items
853
+ return items2
850
854
  .map(i => this.of(i))
851
855
  .reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item))
852
856
  }
package/src/semver.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { _range } from './array/range'
2
2
  import { _assert } from './error/assert'
3
+ import { _isTruthy } from './is.util'
4
+ import { SortDirection } from './types'
3
5
 
4
6
  export type SemverInput = string | Semver
7
+ export type SemverInputNullable = SemverInput | null | undefined
5
8
  export type SemverTokens = [major: number, minor: number, patch: number]
6
9
 
7
10
  /**
@@ -72,7 +75,7 @@ class SemverFactory {
72
75
  return s
73
76
  }
74
77
 
75
- parseOrNull(input: SemverInput | undefined | null): Semver | null {
78
+ parseOrNull(input: SemverInputNullable): Semver | null {
76
79
  if (!input) return null
77
80
  if (input instanceof Semver) return input
78
81
 
@@ -83,7 +86,7 @@ class SemverFactory {
83
86
  /**
84
87
  * Returns the highest (max) Semver from the array, or undefined if the array is empty.
85
88
  */
86
- maxOrUndefined(items: SemverInput[]): Semver | undefined {
89
+ maxOrUndefined(items: SemverInputNullable[]): Semver | undefined {
87
90
  return items.length ? this.max(items) : undefined
88
91
  }
89
92
 
@@ -91,15 +94,16 @@ class SemverFactory {
91
94
  * Returns the highest Semver from the array.
92
95
  * Throws if the array is empty.
93
96
  */
94
- max(items: SemverInput[]): Semver {
95
- _assert(items.length, 'semver.max called on empty array')
96
- return items.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
97
+ max(items: SemverInputNullable[]): Semver {
98
+ const items2 = items.filter(_isTruthy)
99
+ _assert(items2.length, 'semver.max called on empty array')
100
+ return items2.map(i => this.of(i)).reduce((max, item) => (max.isSameOrAfter(item) ? max : item))
97
101
  }
98
102
 
99
103
  /**
100
104
  * Returns the lowest (min) Semver from the array, or undefined if the array is empty.
101
105
  */
102
- minOrUndefined(items: SemverInput[]): Semver | undefined {
106
+ minOrUndefined(items: SemverInputNullable[]): Semver | undefined {
103
107
  return items.length ? this.min(items) : undefined
104
108
  }
105
109
 
@@ -107,9 +111,20 @@ class SemverFactory {
107
111
  * Returns the lowest Semver from the array.
108
112
  * Throws if the array is empty.
109
113
  */
110
- min(items: SemverInput[]): Semver {
111
- _assert(items.length, 'semver.min called on empty array')
112
- return items.map(i => this.of(i)).reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
114
+ min(items: SemverInputNullable[]): Semver {
115
+ const items2 = items.filter(_isTruthy)
116
+ _assert(items2.length, 'semver.min called on empty array')
117
+ return items2
118
+ .map(i => this.of(i))
119
+ .reduce((min, item) => (min.isSameOrBefore(item) ? min : item))
120
+ }
121
+
122
+ /**
123
+ * Sorts an array of Semvers in `dir` order (ascending by default).
124
+ */
125
+ sort(items: Semver[], dir: SortDirection = 'asc', mutate = false): Semver[] {
126
+ const mod = dir === 'desc' ? -1 : 1
127
+ return (mutate ? items : [...items]).sort((a, b) => a.cmp(b) * mod)
113
128
  }
114
129
  }
115
130