@naturalcycles/js-lib 14.163.0 → 14.164.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.
@@ -23,16 +23,14 @@ class LocalDate {
23
23
  */
24
24
  static of(d) {
25
25
  const t = this.parseOrNull(d);
26
- if (t === null) {
27
- throw new Error(`Cannot parse "${d}" into LocalDate`);
28
- }
26
+ (0, assert_1._assert)(t !== null, `Cannot parse "${d}" into LocalDate`, {
27
+ input: d,
28
+ });
29
29
  return t;
30
30
  }
31
31
  static parseCompact(d) {
32
32
  const [year, month, day] = [d.slice(0, 4), d.slice(4, 2), d.slice(6, 2)].map(Number);
33
- if (!day || !month || !year) {
34
- throw new Error(`Cannot parse "${d}" into LocalDate`);
35
- }
33
+ (0, assert_1._assert)(day && month && year, `Cannot parse "${d}" into LocalDate`);
36
34
  return new LocalDate(year, month, day);
37
35
  }
38
36
  static fromDate(d) {
@@ -33,9 +33,9 @@ class LocalTime {
33
33
  */
34
34
  static of(d) {
35
35
  const t = this.parseOrNull(d);
36
- if (t === null) {
37
- throw new TypeError(`Cannot parse "${d}" into LocalTime`);
38
- }
36
+ (0, assert_1._assert)(t !== null, `Cannot parse "${d}" into LocalTime`, {
37
+ input: d,
38
+ });
39
39
  return t;
40
40
  }
41
41
  /**
@@ -82,9 +82,9 @@ class LocalTime {
82
82
  if (d instanceof Date)
83
83
  return d;
84
84
  const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
85
- if (isNaN(date.getDate())) {
86
- throw new TypeError(`Cannot parse "${d}" to Date`);
87
- }
85
+ (0, assert_1._assert)(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
86
+ input: d,
87
+ });
88
88
  return date;
89
89
  }
90
90
  static parseToUnixTimestamp(d) {
@@ -93,9 +93,9 @@ class LocalTime {
93
93
  if (d instanceof LocalTime)
94
94
  return d.unix();
95
95
  const date = d instanceof Date ? d : new Date(d);
96
- if (isNaN(date.getDate())) {
97
- throw new TypeError(`Cannot parse "${d}" to UnixTimestamp`);
98
- }
96
+ (0, assert_1._assert)(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
97
+ input: d,
98
+ });
99
99
  return date.valueOf() / 1000;
100
100
  }
101
101
  static isValid(d) {
@@ -171,8 +171,7 @@ class LocalTime {
171
171
  if (v === undefined) {
172
172
  return dow;
173
173
  }
174
- if (!VALID_DAYS_OF_WEEK.has(v))
175
- throw new Error(`Invalid dayOfWeek: ${v}`);
174
+ (0, assert_1._assert)(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`);
176
175
  return this.add(v - dow, 'day');
177
176
  }
178
177
  hour(v) {
package/dist/index.d.ts CHANGED
@@ -81,6 +81,7 @@ export * from './http/fetcher.model';
81
81
  export * from './string/hash.util';
82
82
  export * from './env/buildInfo';
83
83
  export * from './form.util';
84
+ export * from './semver';
84
85
  export * from './zod/zod.util';
85
86
  export * from './zod/zod.shared.schemas';
86
87
  import { z, ZodSchema, ZodError, ZodIssue } from 'zod';
package/dist/index.js CHANGED
@@ -85,6 +85,7 @@ tslib_1.__exportStar(require("./http/fetcher.model"), exports);
85
85
  tslib_1.__exportStar(require("./string/hash.util"), exports);
86
86
  tslib_1.__exportStar(require("./env/buildInfo"), exports);
87
87
  tslib_1.__exportStar(require("./form.util"), exports);
88
+ tslib_1.__exportStar(require("./semver"), exports);
88
89
  tslib_1.__exportStar(require("./zod/zod.util"), exports);
89
90
  tslib_1.__exportStar(require("./zod/zod.shared.schemas"), exports);
90
91
  const zod_1 = require("zod");
@@ -0,0 +1,44 @@
1
+ export type SemverInput = string | Semver;
2
+ export type SemverTokens = [major: number, minor: number, patch: number];
3
+ /**
4
+ * Simple Semver implementation.
5
+ *
6
+ * Suitable for Browser usage, unlike npm `semver` which is Node-targeted and simply too big for the Browser.
7
+ *
8
+ * Parsing algorithm is simple:
9
+ * 1. Split by `.`
10
+ * 2. parseInt each of 3 tokens, set to 0 if falsy
11
+ *
12
+ * toString returns `major.minor.patch`
13
+ * Missing tokens are replaced with 0.
14
+ *
15
+ * _semver('1').toString() === '1.0.0'
16
+ *
17
+ * @experimental
18
+ */
19
+ export declare class Semver {
20
+ tokens: SemverTokens;
21
+ private constructor();
22
+ get major(): number;
23
+ get minor(): number;
24
+ get patch(): number;
25
+ static of(input: SemverInput): Semver;
26
+ static parseOrNull(input: SemverInput | undefined | null): Semver | null;
27
+ isAfter: (other: SemverInput) => boolean;
28
+ isSameOrAfter: (other: SemverInput) => boolean;
29
+ isBefore: (other: SemverInput) => boolean;
30
+ isSameOrBefore: (other: SemverInput) => boolean;
31
+ isSame: (other: SemverInput) => boolean;
32
+ /**
33
+ * Returns 1 if this > other
34
+ * returns 0 if they are equal
35
+ * returns -1 if this < other
36
+ */
37
+ cmp(other: SemverInput): -1 | 0 | 1;
38
+ toJSON: () => string;
39
+ toString(): string;
40
+ }
41
+ /**
42
+ * Shortcut for Semver.of(input)
43
+ */
44
+ export declare function _semver(input: SemverInput): Semver;
package/dist/semver.js ADDED
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._semver = exports.Semver = void 0;
4
+ const range_1 = require("./array/range");
5
+ const assert_1 = require("./error/assert");
6
+ /**
7
+ * Simple Semver implementation.
8
+ *
9
+ * Suitable for Browser usage, unlike npm `semver` which is Node-targeted and simply too big for the Browser.
10
+ *
11
+ * Parsing algorithm is simple:
12
+ * 1. Split by `.`
13
+ * 2. parseInt each of 3 tokens, set to 0 if falsy
14
+ *
15
+ * toString returns `major.minor.patch`
16
+ * Missing tokens are replaced with 0.
17
+ *
18
+ * _semver('1').toString() === '1.0.0'
19
+ *
20
+ * @experimental
21
+ */
22
+ class Semver {
23
+ constructor(tokens) {
24
+ this.tokens = tokens;
25
+ this.isAfter = (other) => this.cmp(other) > 0;
26
+ this.isSameOrAfter = (other) => this.cmp(other) >= 0;
27
+ this.isBefore = (other) => this.cmp(other) < 0;
28
+ this.isSameOrBefore = (other) => this.cmp(other) <= 0;
29
+ this.isSame = (other) => this.cmp(other) === 0;
30
+ this.toJSON = () => this.toString();
31
+ }
32
+ get major() {
33
+ return this.tokens[0];
34
+ }
35
+ get minor() {
36
+ return this.tokens[1];
37
+ }
38
+ get patch() {
39
+ return this.tokens[2];
40
+ }
41
+ static of(input) {
42
+ const s = this.parseOrNull(input);
43
+ (0, assert_1._assert)(s !== null, `Cannot parse "${input}" into Semver`, {
44
+ userFriendly: true,
45
+ input,
46
+ });
47
+ return s;
48
+ }
49
+ static parseOrNull(input) {
50
+ if (!input)
51
+ return null;
52
+ if (input instanceof Semver)
53
+ return input;
54
+ const t = input.split('.');
55
+ return new Semver((0, range_1._range)(3).map(i => parseInt(t[i]) || 0));
56
+ }
57
+ /**
58
+ * Returns 1 if this > other
59
+ * returns 0 if they are equal
60
+ * returns -1 if this < other
61
+ */
62
+ cmp(other) {
63
+ const { tokens } = Semver.of(other);
64
+ for (let i = 0; i < 3; i++) {
65
+ if (this.tokens[i] < tokens[i])
66
+ return -1;
67
+ if (this.tokens[i] > tokens[i])
68
+ return 1;
69
+ }
70
+ return 0;
71
+ }
72
+ toString() {
73
+ return this.tokens.join('.');
74
+ }
75
+ }
76
+ exports.Semver = Semver;
77
+ /**
78
+ * Shortcut for Semver.of(input)
79
+ */
80
+ function _semver(input) {
81
+ return Semver.of(input);
82
+ }
83
+ exports._semver = _semver;
@@ -20,16 +20,14 @@ export class LocalDate {
20
20
  */
21
21
  static of(d) {
22
22
  const t = this.parseOrNull(d);
23
- if (t === null) {
24
- throw new Error(`Cannot parse "${d}" into LocalDate`);
25
- }
23
+ _assert(t !== null, `Cannot parse "${d}" into LocalDate`, {
24
+ input: d,
25
+ });
26
26
  return t;
27
27
  }
28
28
  static parseCompact(d) {
29
29
  const [year, month, day] = [d.slice(0, 4), d.slice(4, 2), d.slice(6, 2)].map(Number);
30
- if (!day || !month || !year) {
31
- throw new Error(`Cannot parse "${d}" into LocalDate`);
32
- }
30
+ _assert(day && month && year, `Cannot parse "${d}" into LocalDate`);
33
31
  return new LocalDate(year, month, day);
34
32
  }
35
33
  static fromDate(d) {
@@ -30,9 +30,9 @@ export class LocalTime {
30
30
  */
31
31
  static of(d) {
32
32
  const t = this.parseOrNull(d);
33
- if (t === null) {
34
- throw new TypeError(`Cannot parse "${d}" into LocalTime`);
35
- }
33
+ _assert(t !== null, `Cannot parse "${d}" into LocalTime`, {
34
+ input: d,
35
+ });
36
36
  return t;
37
37
  }
38
38
  /**
@@ -79,9 +79,9 @@ export class LocalTime {
79
79
  if (d instanceof Date)
80
80
  return d;
81
81
  const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d);
82
- if (isNaN(date.getDate())) {
83
- throw new TypeError(`Cannot parse "${d}" to Date`);
84
- }
82
+ _assert(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
83
+ input: d,
84
+ });
85
85
  return date;
86
86
  }
87
87
  static parseToUnixTimestamp(d) {
@@ -90,9 +90,9 @@ export class LocalTime {
90
90
  if (d instanceof LocalTime)
91
91
  return d.unix();
92
92
  const date = d instanceof Date ? d : new Date(d);
93
- if (isNaN(date.getDate())) {
94
- throw new TypeError(`Cannot parse "${d}" to UnixTimestamp`);
95
- }
93
+ _assert(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
94
+ input: d,
95
+ });
96
96
  return date.valueOf() / 1000;
97
97
  }
98
98
  static isValid(d) {
@@ -168,8 +168,7 @@ export class LocalTime {
168
168
  if (v === undefined) {
169
169
  return dow;
170
170
  }
171
- if (!VALID_DAYS_OF_WEEK.has(v))
172
- throw new Error(`Invalid dayOfWeek: ${v}`);
171
+ _assert(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`);
173
172
  return this.add(v - dow, 'day');
174
173
  }
175
174
  hour(v) {
package/dist-esm/index.js CHANGED
@@ -81,6 +81,7 @@ export * from './http/fetcher.model';
81
81
  export * from './string/hash.util';
82
82
  export * from './env/buildInfo';
83
83
  export * from './form.util';
84
+ export * from './semver';
84
85
  export * from './zod/zod.util';
85
86
  export * from './zod/zod.shared.schemas';
86
87
  import { z, ZodSchema, ZodError } from 'zod';
@@ -0,0 +1,78 @@
1
+ import { _range } from './array/range';
2
+ import { _assert } from './error/assert';
3
+ /**
4
+ * Simple Semver implementation.
5
+ *
6
+ * Suitable for Browser usage, unlike npm `semver` which is Node-targeted and simply too big for the Browser.
7
+ *
8
+ * Parsing algorithm is simple:
9
+ * 1. Split by `.`
10
+ * 2. parseInt each of 3 tokens, set to 0 if falsy
11
+ *
12
+ * toString returns `major.minor.patch`
13
+ * Missing tokens are replaced with 0.
14
+ *
15
+ * _semver('1').toString() === '1.0.0'
16
+ *
17
+ * @experimental
18
+ */
19
+ export class Semver {
20
+ constructor(tokens) {
21
+ this.tokens = tokens;
22
+ this.isAfter = (other) => this.cmp(other) > 0;
23
+ this.isSameOrAfter = (other) => this.cmp(other) >= 0;
24
+ this.isBefore = (other) => this.cmp(other) < 0;
25
+ this.isSameOrBefore = (other) => this.cmp(other) <= 0;
26
+ this.isSame = (other) => this.cmp(other) === 0;
27
+ this.toJSON = () => this.toString();
28
+ }
29
+ get major() {
30
+ return this.tokens[0];
31
+ }
32
+ get minor() {
33
+ return this.tokens[1];
34
+ }
35
+ get patch() {
36
+ return this.tokens[2];
37
+ }
38
+ static of(input) {
39
+ const s = this.parseOrNull(input);
40
+ _assert(s !== null, `Cannot parse "${input}" into Semver`, {
41
+ userFriendly: true,
42
+ input,
43
+ });
44
+ return s;
45
+ }
46
+ static parseOrNull(input) {
47
+ if (!input)
48
+ return null;
49
+ if (input instanceof Semver)
50
+ return input;
51
+ const t = input.split('.');
52
+ return new Semver(_range(3).map(i => parseInt(t[i]) || 0));
53
+ }
54
+ /**
55
+ * Returns 1 if this > other
56
+ * returns 0 if they are equal
57
+ * returns -1 if this < other
58
+ */
59
+ cmp(other) {
60
+ const { tokens } = Semver.of(other);
61
+ for (let i = 0; i < 3; i++) {
62
+ if (this.tokens[i] < tokens[i])
63
+ return -1;
64
+ if (this.tokens[i] > tokens[i])
65
+ return 1;
66
+ }
67
+ return 0;
68
+ }
69
+ toString() {
70
+ return this.tokens.join('.');
71
+ }
72
+ }
73
+ /**
74
+ * Shortcut for Semver.of(input)
75
+ */
76
+ export function _semver(input) {
77
+ return Semver.of(input);
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.163.0",
3
+ "version": "14.164.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -38,9 +38,9 @@ export class LocalDate {
38
38
  static of(d: LocalDateInput): LocalDate {
39
39
  const t = this.parseOrNull(d)
40
40
 
41
- if (t === null) {
42
- throw new Error(`Cannot parse "${d}" into LocalDate`)
43
- }
41
+ _assert(t !== null, `Cannot parse "${d}" into LocalDate`, {
42
+ input: d,
43
+ })
44
44
 
45
45
  return t
46
46
  }
@@ -48,9 +48,7 @@ export class LocalDate {
48
48
  static parseCompact(d: string): LocalDate {
49
49
  const [year, month, day] = [d.slice(0, 4), d.slice(4, 2), d.slice(6, 2)].map(Number)
50
50
 
51
- if (!day || !month || !year) {
52
- throw new Error(`Cannot parse "${d}" into LocalDate`)
53
- }
51
+ _assert(day && month && year, `Cannot parse "${d}" into LocalDate`)
54
52
 
55
53
  return new LocalDate(year, month, day)
56
54
  }
@@ -53,9 +53,9 @@ export class LocalTime {
53
53
  static of(d: LocalTimeInput): LocalTime {
54
54
  const t = this.parseOrNull(d)
55
55
 
56
- if (t === null) {
57
- throw new TypeError(`Cannot parse "${d}" into LocalTime`)
58
- }
56
+ _assert(t !== null, `Cannot parse "${d}" into LocalTime`, {
57
+ input: d,
58
+ })
59
59
 
60
60
  return t
61
61
  }
@@ -106,9 +106,9 @@ export class LocalTime {
106
106
 
107
107
  const date = typeof d === 'number' ? new Date(d * 1000) : new Date(d)
108
108
 
109
- if (isNaN(date.getDate())) {
110
- throw new TypeError(`Cannot parse "${d}" to Date`)
111
- }
109
+ _assert(!isNaN(date.getDate()), `Cannot parse "${d}" to Date`, {
110
+ input: d,
111
+ })
112
112
 
113
113
  return date
114
114
  }
@@ -119,9 +119,9 @@ export class LocalTime {
119
119
 
120
120
  const date = d instanceof Date ? d : new Date(d)
121
121
 
122
- if (isNaN(date.getDate())) {
123
- throw new TypeError(`Cannot parse "${d}" to UnixTimestamp`)
124
- }
122
+ _assert(!isNaN(date.getDate()), `Cannot parse "${d}" to UnixTimestamp`, {
123
+ input: d,
124
+ })
125
125
 
126
126
  return date.valueOf() / 1000
127
127
  }
@@ -220,7 +220,7 @@ export class LocalTime {
220
220
  return dow
221
221
  }
222
222
 
223
- if (!VALID_DAYS_OF_WEEK.has(v)) throw new Error(`Invalid dayOfWeek: ${v}`)
223
+ _assert(VALID_DAYS_OF_WEEK.has(v), `Invalid dayOfWeek: ${v}`)
224
224
 
225
225
  return this.add(v - dow, 'day')
226
226
  }
package/src/index.ts CHANGED
@@ -81,6 +81,7 @@ export * from './http/fetcher.model'
81
81
  export * from './string/hash.util'
82
82
  export * from './env/buildInfo'
83
83
  export * from './form.util'
84
+ export * from './semver'
84
85
  export * from './zod/zod.util'
85
86
  export * from './zod/zod.shared.schemas'
86
87
  import { z, ZodSchema, ZodError, ZodIssue } from 'zod'
package/src/semver.ts ADDED
@@ -0,0 +1,87 @@
1
+ import { _range } from './array/range'
2
+ import { _assert } from './error/assert'
3
+
4
+ export type SemverInput = string | Semver
5
+ export type SemverTokens = [major: number, minor: number, patch: number]
6
+
7
+ /**
8
+ * Simple Semver implementation.
9
+ *
10
+ * Suitable for Browser usage, unlike npm `semver` which is Node-targeted and simply too big for the Browser.
11
+ *
12
+ * Parsing algorithm is simple:
13
+ * 1. Split by `.`
14
+ * 2. parseInt each of 3 tokens, set to 0 if falsy
15
+ *
16
+ * toString returns `major.minor.patch`
17
+ * Missing tokens are replaced with 0.
18
+ *
19
+ * _semver('1').toString() === '1.0.0'
20
+ *
21
+ * @experimental
22
+ */
23
+ export class Semver {
24
+ private constructor(public tokens: SemverTokens) {}
25
+
26
+ get major(): number {
27
+ return this.tokens[0]
28
+ }
29
+ get minor(): number {
30
+ return this.tokens[1]
31
+ }
32
+ get patch(): number {
33
+ return this.tokens[2]
34
+ }
35
+
36
+ static of(input: SemverInput): Semver {
37
+ const s = this.parseOrNull(input)
38
+
39
+ _assert(s !== null, `Cannot parse "${input}" into Semver`, {
40
+ userFriendly: true,
41
+ input,
42
+ })
43
+
44
+ return s
45
+ }
46
+
47
+ static parseOrNull(input: SemverInput | undefined | null): Semver | null {
48
+ if (!input) return null
49
+ if (input instanceof Semver) return input
50
+
51
+ const t = input.split('.')
52
+ return new Semver(_range(3).map(i => parseInt(t[i]!) || 0) as SemverTokens)
53
+ }
54
+
55
+ isAfter = (other: SemverInput): boolean => this.cmp(other) > 0
56
+ isSameOrAfter = (other: SemverInput): boolean => this.cmp(other) >= 0
57
+ isBefore = (other: SemverInput): boolean => this.cmp(other) < 0
58
+ isSameOrBefore = (other: SemverInput): boolean => this.cmp(other) <= 0
59
+ isSame = (other: SemverInput): boolean => this.cmp(other) === 0
60
+
61
+ /**
62
+ * Returns 1 if this > other
63
+ * returns 0 if they are equal
64
+ * returns -1 if this < other
65
+ */
66
+ cmp(other: SemverInput): -1 | 0 | 1 {
67
+ const { tokens } = Semver.of(other)
68
+ for (let i = 0; i < 3; i++) {
69
+ if (this.tokens[i]! < tokens[i]!) return -1
70
+ if (this.tokens[i]! > tokens[i]!) return 1
71
+ }
72
+ return 0
73
+ }
74
+
75
+ toJSON = (): string => this.toString()
76
+
77
+ toString(): string {
78
+ return this.tokens.join('.')
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Shortcut for Semver.of(input)
84
+ */
85
+ export function _semver(input: SemverInput): Semver {
86
+ return Semver.of(input)
87
+ }