@bgord/tools 0.17.2 → 1.0.1
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.
- package/dist/age-years.vo.d.ts +11 -0
- package/dist/age-years.vo.js +9 -0
- package/dist/age.vo.d.ts +11 -16
- package/dist/age.vo.js +20 -31
- package/dist/api-key.vo.d.ts +3 -1
- package/dist/api-key.vo.js +10 -5
- package/dist/basename.vo.d.ts +9 -9
- package/dist/basename.vo.js +22 -22
- package/dist/clock.vo.d.ts +10 -4
- package/dist/clock.vo.js +12 -14
- package/dist/date-calculator.service.d.ts +2 -1
- package/dist/date-formatter.service.d.ts +3 -4
- package/dist/date-range.vo.d.ts +7 -1
- package/dist/date-range.vo.js +5 -2
- package/dist/day-iso-id.vo.d.ts +5 -2
- package/dist/day-iso-id.vo.js +11 -7
- package/dist/day.vo.d.ts +4 -3
- package/dist/day.vo.js +18 -16
- package/dist/directory-path-absolute.vo.d.ts +10 -6
- package/dist/directory-path-absolute.vo.js +19 -17
- package/dist/directory-path-relative.vo.d.ts +10 -7
- package/dist/directory-path-relative.vo.js +18 -17
- package/dist/division-factor.vo.d.ts +7 -0
- package/dist/division-factor.vo.js +9 -0
- package/dist/duration-ms.vo.d.ts +6 -0
- package/dist/duration-ms.vo.js +3 -0
- package/dist/duration.service.d.ts +2 -14
- package/dist/duration.service.js +16 -35
- package/dist/email-mask.service.d.ts +1 -6
- package/dist/email-mask.service.js +6 -8
- package/dist/etags.vo.d.ts +4 -3
- package/dist/etags.vo.js +3 -3
- package/dist/extension.vo.d.ts +6 -4
- package/dist/extension.vo.js +15 -10
- package/dist/feature-flag-value.vo.d.ts +10 -0
- package/dist/feature-flag-value.vo.js +8 -0
- package/dist/feature-flag.vo.d.ts +1 -7
- package/dist/feature-flag.vo.js +1 -7
- package/dist/file-path-absolute-schema.vo.d.ts +10 -7
- package/dist/file-path-absolute-schema.vo.js +17 -17
- package/dist/file-path-relative-schema.vo.d.ts +10 -7
- package/dist/file-path-relative-schema.vo.js +14 -12
- package/dist/file-path.vo.d.ts +4 -4
- package/dist/file-path.vo.js +8 -8
- package/dist/filename-from-string.vo.d.ts +4 -2
- package/dist/filename-from-string.vo.js +10 -8
- package/dist/filename-suffix.vo.d.ts +7 -3
- package/dist/filename-suffix.vo.js +13 -7
- package/dist/filename.vo.d.ts +2 -0
- package/dist/filename.vo.js +8 -2
- package/dist/height-milimiters.vo.d.ts +6 -0
- package/dist/height-milimiters.vo.js +10 -0
- package/dist/height.vo.d.ts +3 -20
- package/dist/height.vo.js +11 -62
- package/dist/hour-format.service.js +1 -1
- package/dist/hour-schema.vo.d.ts +7 -0
- package/dist/hour-schema.vo.js +8 -0
- package/dist/hour.vo.d.ts +4 -3
- package/dist/hour.vo.js +8 -8
- package/dist/iban-mask.service.d.ts +1 -3
- package/dist/iban-mask.service.js +2 -2
- package/dist/iban-schema.vo.d.ts +7 -0
- package/dist/iban-schema.vo.js +10 -0
- package/dist/iban.vo.d.ts +4 -10
- package/dist/iban.vo.js +6 -13
- package/dist/image.vo.d.ts +6 -4
- package/dist/image.vo.js +13 -12
- package/dist/index.d.ts +24 -2
- package/dist/index.js +24 -2
- package/dist/language.vo.d.ts +2 -1
- package/dist/language.vo.js +6 -4
- package/dist/linear-regression.service.d.ts +27 -0
- package/dist/{simple-linear-regression.service.js → linear-regression.service.js} +17 -15
- package/dist/mean.service.d.ts +3 -1
- package/dist/mean.service.js +3 -4
- package/dist/mime-types.vo.d.ts +1 -2
- package/dist/mime-value.vo.d.ts +9 -0
- package/dist/mime-value.vo.js +9 -0
- package/dist/mime.vo.d.ts +11 -17
- package/dist/mime.vo.js +10 -27
- package/dist/min-max-scaler.service.d.ts +7 -5
- package/dist/min-max-scaler.service.js +12 -10
- package/dist/minute-schema.vo.d.ts +7 -0
- package/dist/minute-schema.vo.js +8 -0
- package/dist/minute.vo.d.ts +4 -3
- package/dist/minute.vo.js +8 -8
- package/dist/money-amount.vo.d.ts +7 -0
- package/dist/money-amount.vo.js +7 -0
- package/dist/money.vo.d.ts +9 -18
- package/dist/money.vo.js +14 -27
- package/dist/month-iso-id.vo.d.ts +4 -2
- package/dist/month-iso-id.vo.js +13 -7
- package/dist/month.vo.d.ts +4 -3
- package/dist/month.vo.js +21 -21
- package/dist/multiplication-factor.vo.d.ts +7 -0
- package/dist/multiplication-factor.vo.js +9 -0
- package/dist/object-key.vo.d.ts +9 -6
- package/dist/object-key.vo.js +20 -19
- package/dist/outlier-detector.service.d.ts +3 -1
- package/dist/outlier-detector.service.js +2 -2
- package/dist/package-version-schema.vo.d.ts +11 -0
- package/dist/package-version-schema.vo.js +15 -0
- package/dist/package-version.vo.d.ts +11 -20
- package/dist/package-version.vo.js +11 -20
- package/dist/pagination-page.vo.d.ts +6 -0
- package/dist/pagination-page.vo.js +7 -0
- package/dist/pagination-skip.vo.d.ts +7 -0
- package/dist/pagination-skip.vo.js +9 -0
- package/dist/pagination-take.vo.d.ts +7 -0
- package/dist/pagination-take.vo.js +9 -0
- package/dist/pagination.service.d.ts +3 -8
- package/dist/pagination.service.js +5 -12
- package/dist/percentage.service.d.ts +3 -1
- package/dist/percentage.service.js +2 -2
- package/dist/population-standard-deviation.service.d.ts +3 -1
- package/dist/population-standard-deviation.service.js +5 -4
- package/dist/quarter-iso-id.vo.d.ts +3 -2
- package/dist/quarter-iso-id.vo.js +7 -9
- package/dist/quarter.vo.d.ts +2 -1
- package/dist/quarter.vo.js +10 -7
- package/dist/random.service.d.ts +3 -4
- package/dist/random.service.js +5 -11
- package/dist/rate-limiter.service.d.ts +2 -2
- package/dist/rate-limiter.service.js +8 -8
- package/dist/reordering-item-position-value.vo.d.ts +6 -0
- package/dist/reordering-item-position-value.vo.js +6 -0
- package/dist/reordering.service.d.ts +7 -23
- package/dist/reordering.service.js +15 -24
- package/dist/revision-value.vo.d.ts +7 -0
- package/dist/revision-value.vo.js +6 -0
- package/dist/revision.vo.d.ts +6 -13
- package/dist/revision.vo.js +10 -22
- package/dist/rounding.adapter.d.ts +7 -2
- package/dist/rounding.adapter.js +13 -5
- package/dist/size-bytes.vo.d.ts +6 -0
- package/dist/size-bytes.vo.js +7 -0
- package/dist/size.vo.d.ts +15 -15
- package/dist/size.vo.js +41 -51
- package/dist/stopwatch.service.d.ts +3 -1
- package/dist/stopwatch.service.js +2 -2
- package/dist/sum.service.js +8 -8
- package/dist/thousands-separator.service.js +4 -1
- package/dist/time.service.d.ts +8 -0
- package/dist/time.service.js +13 -0
- package/dist/timestamp.vo.d.ts +1 -1
- package/dist/timestamp.vo.js +4 -5
- package/dist/timezone.vo.d.ts +4 -1
- package/dist/timezone.vo.js +12 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/week-iso-id.vo.d.ts +4 -2
- package/dist/week-iso-id.vo.js +15 -9
- package/dist/week.vo.d.ts +4 -3
- package/dist/week.vo.js +21 -22
- package/dist/weekday.vo.d.ts +1 -1
- package/dist/weekday.vo.js +6 -8
- package/dist/weight-grams.vo.d.ts +7 -0
- package/dist/weight-grams.vo.js +7 -0
- package/dist/weight.vo.d.ts +12 -35
- package/dist/weight.vo.js +23 -72
- package/dist/year-iso-id.vo.d.ts +3 -2
- package/dist/year-iso-id.vo.js +6 -4
- package/dist/year.vo.d.ts +5 -6
- package/dist/year.vo.js +21 -26
- package/dist/z-score.service.d.ts +3 -1
- package/dist/z-score.service.js +2 -2
- package/package.json +4 -4
- package/readme.md +21 -2
- package/src/age-years.vo.ts +14 -0
- package/src/age.vo.ts +22 -35
- package/src/api-key.vo.ts +11 -5
- package/src/basename.vo.ts +24 -22
- package/src/clock.vo.ts +16 -17
- package/src/date-calculator.service.ts +2 -1
- package/src/date-formatter.service.ts +4 -5
- package/src/date-range.vo.ts +6 -2
- package/src/day-iso-id.vo.ts +12 -8
- package/src/day.vo.ts +27 -24
- package/src/directory-path-absolute.vo.ts +23 -18
- package/src/directory-path-relative.vo.ts +21 -18
- package/src/division-factor.vo.ts +13 -0
- package/src/duration-ms.vo.ts +7 -0
- package/src/duration.service.ts +16 -40
- package/src/email-mask.service.ts +7 -15
- package/src/etags.vo.ts +4 -5
- package/src/extension.vo.ts +17 -10
- package/src/feature-flag-value.vo.ts +12 -0
- package/src/feature-flag.vo.ts +1 -9
- package/src/file-path-absolute-schema.vo.ts +18 -17
- package/src/file-path-relative-schema.vo.ts +15 -12
- package/src/file-path.vo.ts +8 -8
- package/src/filename-from-string.vo.ts +12 -9
- package/src/filename-suffix.vo.ts +14 -7
- package/src/filename.vo.ts +11 -2
- package/src/height-milimiters.vo.ts +12 -0
- package/src/height.vo.ts +12 -83
- package/src/hour-format.service.ts +2 -1
- package/src/hour-schema.vo.ts +12 -0
- package/src/hour.vo.ts +12 -12
- package/src/iban-mask.service.ts +3 -5
- package/src/iban-schema.vo.ts +15 -0
- package/src/iban.vo.ts +9 -22
- package/src/image.vo.ts +14 -12
- package/src/index.ts +24 -2
- package/src/language.vo.ts +7 -4
- package/src/linear-regression.service.ts +71 -0
- package/src/mean.service.ts +3 -5
- package/src/mime-types.vo.ts +1 -3
- package/src/mime-value.vo.ts +12 -0
- package/src/mime.vo.ts +12 -33
- package/src/min-max-scaler.service.ts +13 -11
- package/src/minute-schema.vo.ts +12 -0
- package/src/minute.vo.ts +12 -12
- package/src/money-amount.vo.ts +11 -0
- package/src/money.vo.ts +20 -38
- package/src/month-iso-id.vo.ts +14 -7
- package/src/month.vo.ts +25 -24
- package/src/multiplication-factor.vo.ts +13 -0
- package/src/object-key.vo.ts +25 -21
- package/src/outlier-detector.service.ts +2 -2
- package/src/package-version-schema.vo.ts +21 -0
- package/src/package-version.vo.ts +17 -33
- package/src/pagination-page.vo.ts +11 -0
- package/src/pagination-skip.vo.ts +13 -0
- package/src/pagination-take.vo.ts +13 -0
- package/src/pagination.service.ts +5 -22
- package/src/percentage.service.ts +2 -2
- package/src/population-standard-deviation.service.ts +5 -4
- package/src/quarter-iso-id.vo.ts +7 -10
- package/src/quarter.vo.ts +14 -9
- package/src/random.service.ts +6 -9
- package/src/rate-limiter.service.ts +9 -8
- package/src/reordering-item-position-value.vo.ts +10 -0
- package/src/reordering.service.ts +19 -28
- package/src/revision-value.vo.ts +10 -0
- package/src/revision.vo.ts +10 -25
- package/src/rounding.adapter.ts +16 -3
- package/src/size-bytes.vo.ts +11 -0
- package/src/size.vo.ts +43 -54
- package/src/stopwatch.service.ts +3 -3
- package/src/sum.service.ts +8 -8
- package/src/thousands-separator.service.ts +4 -1
- package/src/time.service.ts +15 -0
- package/src/timestamp.vo.ts +4 -5
- package/src/timezone.vo.ts +12 -6
- package/src/week-iso-id.vo.ts +16 -12
- package/src/week.vo.ts +26 -28
- package/src/weekday.vo.ts +6 -9
- package/src/weight-grams.vo.ts +11 -0
- package/src/weight.vo.ts +28 -85
- package/src/year-iso-id.vo.ts +7 -4
- package/src/year.vo.ts +27 -33
- package/src/z-score.service.ts +2 -2
- package/dist/simple-linear-regression.service.d.ts +0 -25
- package/dist/streak-calculator.service.d.ts +0 -13
- package/dist/streak-calculator.service.js +0 -22
- package/src/simple-linear-regression.service.ts +0 -69
- package/src/streak-calculator.service.ts +0 -32
package/src/image.vo.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
|
|
3
|
-
export const ImageWidthError = {
|
|
4
|
-
export const ImageHeightError = {
|
|
3
|
+
export const ImageWidthError = { Type: "image.width.type", Length: "image.width.length" } as const;
|
|
4
|
+
export const ImageHeightError = { Type: "image.height.type", Length: "image.height.length" } as const;
|
|
5
|
+
|
|
6
|
+
const IMAGE_DIMENSIONS_CONSTRAINTS = { min: 1, max: 10_000 };
|
|
5
7
|
|
|
6
8
|
export const ImageWidth = z
|
|
7
|
-
.number(ImageWidthError)
|
|
8
|
-
.int(ImageWidthError)
|
|
9
|
-
.
|
|
10
|
-
.max(
|
|
11
|
-
.brand("
|
|
9
|
+
.number(ImageWidthError.Type)
|
|
10
|
+
.int(ImageWidthError.Type)
|
|
11
|
+
.min(IMAGE_DIMENSIONS_CONSTRAINTS.min, ImageWidthError.Length)
|
|
12
|
+
.max(IMAGE_DIMENSIONS_CONSTRAINTS.max, ImageWidthError.Length)
|
|
13
|
+
.brand("ImageWidth");
|
|
12
14
|
|
|
13
15
|
export type ImageWidthType = z.infer<typeof ImageWidth>;
|
|
14
16
|
|
|
15
17
|
export const ImageHeight = z
|
|
16
|
-
.number(ImageHeightError)
|
|
17
|
-
.int(ImageHeightError)
|
|
18
|
-
.
|
|
19
|
-
.max(
|
|
20
|
-
.brand("
|
|
18
|
+
.number(ImageHeightError.Type)
|
|
19
|
+
.int(ImageHeightError.Type)
|
|
20
|
+
.min(IMAGE_DIMENSIONS_CONSTRAINTS.min, ImageHeightError.Length)
|
|
21
|
+
.max(IMAGE_DIMENSIONS_CONSTRAINTS.max, ImageHeightError.Length)
|
|
22
|
+
.brand("ImageHeight");
|
|
21
23
|
|
|
22
24
|
export type ImageHeightType = z.infer<typeof ImageHeight>;
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from "./age.vo";
|
|
2
|
+
export * from "./age-years.vo";
|
|
2
3
|
export * from "./api-key.vo";
|
|
3
4
|
export * from "./basename.vo";
|
|
4
5
|
export * from "./clock.vo";
|
|
6
|
+
export * from "./clock-format.service";
|
|
5
7
|
export * from "./date-calculator.service";
|
|
6
8
|
export * from "./date-formatter.service";
|
|
7
9
|
export * from "./date-range.vo";
|
|
@@ -9,12 +11,15 @@ export * from "./day.vo";
|
|
|
9
11
|
export * from "./day-iso-id.vo";
|
|
10
12
|
export * from "./directory-path-absolute.vo";
|
|
11
13
|
export * from "./directory-path-relative.vo";
|
|
14
|
+
export * from "./division-factor.vo";
|
|
12
15
|
export * from "./dll.service";
|
|
13
16
|
export * from "./duration.service";
|
|
17
|
+
export * from "./duration-ms.vo";
|
|
14
18
|
export * from "./email-mask.service";
|
|
15
19
|
export * from "./etags.vo";
|
|
16
20
|
export * from "./extension.vo";
|
|
17
21
|
export * from "./feature-flag.vo";
|
|
22
|
+
export * from "./feature-flag-value.vo";
|
|
18
23
|
export * from "./file-path.vo";
|
|
19
24
|
export * from "./file-path-absolute-schema.vo";
|
|
20
25
|
export * from "./file-path-relative-schema.vo";
|
|
@@ -22,25 +27,39 @@ export * from "./filename.vo";
|
|
|
22
27
|
export * from "./filename-from-string.vo";
|
|
23
28
|
export * from "./filename-suffix.vo";
|
|
24
29
|
export * from "./height.vo";
|
|
30
|
+
export * from "./height-milimiters.vo";
|
|
25
31
|
export * from "./hour.vo";
|
|
32
|
+
export * from "./hour-format.service";
|
|
33
|
+
export * from "./hour-schema.vo";
|
|
26
34
|
export * from "./iban.vo";
|
|
27
35
|
export * from "./iban-mask.service";
|
|
36
|
+
export * from "./iban-schema.vo";
|
|
28
37
|
export * from "./image.vo";
|
|
38
|
+
export * from "./index";
|
|
29
39
|
export * from "./language.vo";
|
|
40
|
+
export * from "./linear-regression.service";
|
|
30
41
|
export * from "./mean.service";
|
|
31
42
|
export * from "./mime.vo";
|
|
32
43
|
export * from "./mime-types.vo";
|
|
44
|
+
export * from "./mime-value.vo";
|
|
33
45
|
export * from "./min-max-scaler.service";
|
|
34
46
|
export * from "./minute.vo";
|
|
47
|
+
export * from "./minute-schema.vo";
|
|
35
48
|
export * from "./money.vo";
|
|
49
|
+
export * from "./money-amount.vo";
|
|
36
50
|
export * from "./month.vo";
|
|
37
51
|
export * from "./month-iso-id.vo";
|
|
52
|
+
export * from "./multiplication-factor.vo";
|
|
38
53
|
export * from "./noop.service";
|
|
39
54
|
export * from "./notification-template.vo";
|
|
40
55
|
export * from "./object-key.vo";
|
|
41
56
|
export * from "./outlier-detector.service";
|
|
42
57
|
export * from "./package-version.vo";
|
|
58
|
+
export * from "./package-version-schema.vo";
|
|
43
59
|
export * from "./pagination.service";
|
|
60
|
+
export * from "./pagination-page.vo";
|
|
61
|
+
export * from "./pagination-skip.vo";
|
|
62
|
+
export * from "./pagination-take.vo";
|
|
44
63
|
export * from "./percentage.service";
|
|
45
64
|
export * from "./population-standard-deviation.service";
|
|
46
65
|
export * from "./quarter.vo";
|
|
@@ -49,15 +68,17 @@ export * from "./random.service";
|
|
|
49
68
|
export * from "./rate-limiter.service";
|
|
50
69
|
export * from "./relative-date.vo";
|
|
51
70
|
export * from "./reordering.service";
|
|
71
|
+
export * from "./reordering-item-position-value.vo";
|
|
52
72
|
export * from "./revision.vo";
|
|
73
|
+
export * from "./revision-value.vo";
|
|
53
74
|
export * from "./rounding.adapter";
|
|
54
75
|
export * from "./rounding.port";
|
|
55
|
-
export * from "./simple-linear-regression.service";
|
|
56
76
|
export * from "./size.vo";
|
|
77
|
+
export * from "./size-bytes.vo";
|
|
57
78
|
export * from "./stopwatch.service";
|
|
58
|
-
export * from "./streak-calculator.service";
|
|
59
79
|
export * from "./sum.service";
|
|
60
80
|
export * from "./thousands-separator.service";
|
|
81
|
+
export * from "./time.service";
|
|
61
82
|
export * from "./time-zone-offset-value.vo";
|
|
62
83
|
export * from "./timestamp.vo";
|
|
63
84
|
export * from "./timezone.vo";
|
|
@@ -67,6 +88,7 @@ export * from "./week.vo";
|
|
|
67
88
|
export * from "./week-iso-id.vo";
|
|
68
89
|
export * from "./weekday.vo";
|
|
69
90
|
export * from "./weight.vo";
|
|
91
|
+
export * from "./weight-grams.vo";
|
|
70
92
|
export * from "./year.vo";
|
|
71
93
|
export * from "./year-iso-id.vo";
|
|
72
94
|
export * from "./z-score.service";
|
package/src/language.vo.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
|
|
3
|
-
export const LanguageError = {
|
|
3
|
+
export const LanguageError = { Type: "language.type", BadChars: "language.bad.chars" } as const;
|
|
4
|
+
|
|
5
|
+
// Two lowercase letters
|
|
6
|
+
const LANGUAGE_CHARS_WHITELIST = /^[a-z]{2}$/;
|
|
4
7
|
|
|
5
8
|
export const Language = z
|
|
6
|
-
.string(LanguageError)
|
|
7
|
-
.
|
|
8
|
-
.regex(
|
|
9
|
+
.string(LanguageError.Type)
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.regex(LANGUAGE_CHARS_WHITELIST, LanguageError.BadChars);
|
|
9
12
|
|
|
10
13
|
export type LanguageType = z.infer<typeof Language>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { RoundToNearest } from "./rounding.adapter";
|
|
2
|
+
import type { RoundingPort } from "./rounding.port";
|
|
3
|
+
|
|
4
|
+
export type LinearRegressionPairType = { x: number; y: number };
|
|
5
|
+
export type LinearRegressionParamsType = { a: number; b: number };
|
|
6
|
+
export type LinearRegressionPredictionType = number;
|
|
7
|
+
|
|
8
|
+
export const LinearRegressionError = {
|
|
9
|
+
MinPairs: "linear.regression.min.pairs",
|
|
10
|
+
SumXTooBig: "linear.regression.sum.x.too.big",
|
|
11
|
+
SumYTooBig: "linear.regression.sum.y.too.big",
|
|
12
|
+
SumXSquaredTooBig: "linear.regression.sum.x.squared.too.big",
|
|
13
|
+
SumXTimesYTooBig: "linear.regression.sum.x.times.y.too.big",
|
|
14
|
+
ModelCreation: "linear.regression.model.creation",
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
export class LinearRegression {
|
|
18
|
+
private static readonly DEFAULT_ROUNDING: RoundingPort = new RoundToNearest();
|
|
19
|
+
|
|
20
|
+
private readonly params: LinearRegressionParamsType;
|
|
21
|
+
private readonly rounding: RoundingPort;
|
|
22
|
+
|
|
23
|
+
constructor(params: LinearRegressionParamsType, rounding?: RoundingPort) {
|
|
24
|
+
this.params = params;
|
|
25
|
+
this.rounding = rounding ?? LinearRegression.DEFAULT_ROUNDING;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static fromPairs(pairs: LinearRegressionPairType[], rounding?: RoundingPort): LinearRegression {
|
|
29
|
+
const count = pairs.length;
|
|
30
|
+
|
|
31
|
+
if (count < 2) throw new Error(LinearRegressionError.MinPairs);
|
|
32
|
+
|
|
33
|
+
let sumX = 0;
|
|
34
|
+
let sumY = 0;
|
|
35
|
+
let sumXX = 0;
|
|
36
|
+
let sumXY = 0;
|
|
37
|
+
|
|
38
|
+
for (let index = 0; index < count; index++) {
|
|
39
|
+
const pair = pairs[index];
|
|
40
|
+
sumX += pair.x;
|
|
41
|
+
sumY += pair.y;
|
|
42
|
+
sumXX += pair.x * pair.x;
|
|
43
|
+
sumXY += pair.x * pair.y;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (Math.abs(sumX) >= Number.MAX_SAFE_INTEGER) throw new Error(LinearRegressionError.SumXTooBig);
|
|
47
|
+
if (Math.abs(sumY) >= Number.MAX_SAFE_INTEGER) throw new Error(LinearRegressionError.SumYTooBig);
|
|
48
|
+
if (Math.abs(sumXY) >= Number.MAX_SAFE_INTEGER) throw new Error(LinearRegressionError.SumXTimesYTooBig);
|
|
49
|
+
if (Math.abs(sumXX) >= Number.MAX_SAFE_INTEGER) throw new Error(LinearRegressionError.SumXSquaredTooBig);
|
|
50
|
+
|
|
51
|
+
const bDenominator = sumXX - sumX ** 2 / count;
|
|
52
|
+
|
|
53
|
+
if (bDenominator === 0) throw new Error(LinearRegressionError.ModelCreation);
|
|
54
|
+
|
|
55
|
+
const b = (sumXY - (sumX * sumY) / count) / bDenominator;
|
|
56
|
+
const a = (sumY - b * sumX) / count;
|
|
57
|
+
|
|
58
|
+
return new LinearRegression({ a, b }, rounding);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
predict(x: LinearRegressionPairType["x"], rounding?: RoundingPort): LinearRegressionPredictionType {
|
|
62
|
+
const chosen = rounding ?? this.rounding;
|
|
63
|
+
const prediction = this.params.b * x + this.params.a;
|
|
64
|
+
|
|
65
|
+
return chosen.round(prediction);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
inspect(): LinearRegression["params"] {
|
|
69
|
+
return this.params;
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/mean.service.ts
CHANGED
|
@@ -2,19 +2,17 @@ import { RoundToDecimal } from "./rounding.adapter";
|
|
|
2
2
|
import type { RoundingPort } from "./rounding.port";
|
|
3
3
|
import { Sum } from "./sum.service";
|
|
4
4
|
|
|
5
|
-
export const
|
|
5
|
+
export const MeanError = { NotEnoughValues: "mean.not.enough.values" } as const;
|
|
6
6
|
|
|
7
7
|
export class Mean {
|
|
8
8
|
private static readonly DEFAULT_ROUNDING: RoundingPort = new RoundToDecimal(2);
|
|
9
9
|
|
|
10
10
|
static calculate(values: number[], rounding?: RoundingPort): number {
|
|
11
|
-
if (values.length === 0) throw new Error(
|
|
11
|
+
if (values.length === 0) throw new Error(MeanError.NotEnoughValues);
|
|
12
12
|
|
|
13
13
|
const sum = Sum.of(values);
|
|
14
14
|
const mean = sum / values.length;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return chosen.round(mean);
|
|
16
|
+
return (rounding ?? Mean.DEFAULT_ROUNDING).round(mean);
|
|
19
17
|
}
|
|
20
18
|
}
|
package/src/mime-types.vo.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const MimeValueError = { Type: "mime.value.type", Invalid: "mime.value.invalid" };
|
|
4
|
+
|
|
5
|
+
// One to twenty four lowercase letters, asterisk or hyphen, forward slash, one to twenty four lowercase letters, asterisk or hyphen
|
|
6
|
+
const MIME_VALUE_CHARS_WHITELIST = /^[a-z*-]{1,24}\/[a-z*-]{1,24}$/;
|
|
7
|
+
|
|
8
|
+
export const MimeValue = z
|
|
9
|
+
.string(MimeValueError.Type)
|
|
10
|
+
.regex(MIME_VALUE_CHARS_WHITELIST, MimeValueError.Invalid)
|
|
11
|
+
.transform((value) => ({ type: value.split("/")[0], subtype: value.split("/")[1] }))
|
|
12
|
+
.brand("MimeValue");
|
package/src/mime.vo.ts
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import * as mime from "mime-types";
|
|
2
2
|
import { Extension, type ExtensionType } from "./extension.vo";
|
|
3
|
+
import { MimeValue } from "./mime-value.vo";
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
type MimeTypeType = string;
|
|
6
|
-
type MimeSubtypeType = string;
|
|
7
|
-
|
|
8
|
-
export const InvalidMimeErrorMessage = "invalid.mime" as const;
|
|
9
|
-
export const NotAcceptedMimeErrorMessage = "mime.not.accepted" as const;
|
|
5
|
+
export const MimeError = { NotAccepted: "mime.not.accepted" } as const;
|
|
10
6
|
|
|
11
7
|
export class Mime {
|
|
12
|
-
readonly
|
|
13
|
-
readonly
|
|
14
|
-
readonly subtype: MimeSubtypeType;
|
|
15
|
-
|
|
16
|
-
constructor(value: MimeRawType) {
|
|
17
|
-
const [type, subtype] = value.split("/");
|
|
8
|
+
readonly type: string;
|
|
9
|
+
readonly subtype: string;
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
constructor(candidate: string) {
|
|
12
|
+
const { type, subtype } = MimeValue.parse(candidate);
|
|
21
13
|
|
|
22
|
-
this.raw = value;
|
|
23
14
|
this.type = type;
|
|
24
15
|
this.subtype = subtype;
|
|
25
16
|
}
|
|
@@ -29,32 +20,20 @@ export class Mime {
|
|
|
29
20
|
}
|
|
30
21
|
|
|
31
22
|
isSatisfiedBy(another: Mime): boolean {
|
|
32
|
-
if (this.
|
|
33
|
-
|
|
34
|
-
const typeMatches = this.type === another.type || this.type === "*";
|
|
35
|
-
|
|
36
|
-
if (!typeMatches) return false;
|
|
23
|
+
if (!(this.type === another.type || this.type === "*")) return false;
|
|
37
24
|
return this.subtype === another.subtype || this.subtype === "*";
|
|
38
25
|
}
|
|
39
26
|
|
|
40
27
|
toExtension(): ExtensionType {
|
|
41
|
-
return Extension.parse(mime.extension(this.
|
|
28
|
+
return Extension.parse(mime.extension(this.toString()));
|
|
42
29
|
}
|
|
43
|
-
}
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
super(InvalidMimeErrorMessage);
|
|
48
|
-
Object.setPrototypeOf(this, InvalidMimeError.prototype);
|
|
31
|
+
toString(): string {
|
|
32
|
+
return `${this.type}/${this.subtype}`;
|
|
49
33
|
}
|
|
50
|
-
}
|
|
51
34
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
constructor(mimeValue: MimeRawType) {
|
|
55
|
-
super(NotAcceptedMimeErrorMessage);
|
|
56
|
-
Object.setPrototypeOf(this, NotAcceptedMimeError.prototype);
|
|
57
|
-
this.mime = mimeValue;
|
|
35
|
+
toJSON(): { type: string; subtype: string } {
|
|
36
|
+
return { type: this.type, subtype: this.subtype };
|
|
58
37
|
}
|
|
59
38
|
}
|
|
60
39
|
|
|
@@ -10,12 +10,6 @@ type MinMaxScalerConfigType = {
|
|
|
10
10
|
rounding?: RoundingPort;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export const MinMaxInvalidMinMaxError = "minmax.invalid.minmax" as const;
|
|
14
|
-
export const MinMaxInvalidBoundError = "minmax.invalid.bound" as const;
|
|
15
|
-
export const MinMaxValueOutOfRangeError = "minmax.value.out.of.range" as const;
|
|
16
|
-
export const MinMaxScaledOutOfBoundsError = "minmax.scaled.out.of.bounds" as const;
|
|
17
|
-
export const MinMaxEmptyArrayError = "minmax.empty.array" as const;
|
|
18
|
-
|
|
19
13
|
type ScaleResult = {
|
|
20
14
|
original: MinMaxScalerValueType;
|
|
21
15
|
scaled: MinMaxScalerValueType;
|
|
@@ -30,6 +24,14 @@ type DescaleResult = {
|
|
|
30
24
|
isUpperBound: boolean;
|
|
31
25
|
};
|
|
32
26
|
|
|
27
|
+
export const MinMaxScalerError = {
|
|
28
|
+
InvalidMinMax: "min.max.scaler.invalid.min.max",
|
|
29
|
+
InvalidBound: "min.max.scaler.invalid.bound",
|
|
30
|
+
ValueOutOfRange: "min.max.scaler.value.out.of.range",
|
|
31
|
+
ScaledOutOfBounds: "min.max.scaler.scaled.out.of.bounds",
|
|
32
|
+
EmptyArray: "min.max.scaler.empty.array",
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
33
35
|
export class MinMaxScaler {
|
|
34
36
|
private static readonly DEFAULT_ROUNDING: RoundingPort = new RoundToDecimal(2);
|
|
35
37
|
|
|
@@ -43,8 +45,8 @@ export class MinMaxScaler {
|
|
|
43
45
|
const lower = config.bound?.lower ?? 0;
|
|
44
46
|
const upper = config.bound?.upper ?? 1;
|
|
45
47
|
|
|
46
|
-
if (config.max - config.min < 0) throw new Error(
|
|
47
|
-
if (upper - lower <= 0) throw new Error(
|
|
48
|
+
if (config.max - config.min < 0) throw new Error(MinMaxScalerError.InvalidMinMax);
|
|
49
|
+
if (upper - lower <= 0) throw new Error(MinMaxScalerError.InvalidBound);
|
|
48
50
|
|
|
49
51
|
this.rounding = config.rounding ?? MinMaxScaler.DEFAULT_ROUNDING;
|
|
50
52
|
this.min = config.min;
|
|
@@ -56,7 +58,7 @@ export class MinMaxScaler {
|
|
|
56
58
|
scale(value: MinMaxScalerValueType): ScaleResult {
|
|
57
59
|
const { min, max, lower, upper } = this;
|
|
58
60
|
|
|
59
|
-
if (value < min || value > max) throw new Error(
|
|
61
|
+
if (value < min || value > max) throw new Error(MinMaxScalerError.ValueOutOfRange);
|
|
60
62
|
|
|
61
63
|
if (min === max) {
|
|
62
64
|
return { original: value, scaled: (lower + upper) / 2, isMin: value === min, isMax: value === max };
|
|
@@ -75,7 +77,7 @@ export class MinMaxScaler {
|
|
|
75
77
|
descale(scaled: MinMaxScalerValueType): DescaleResult {
|
|
76
78
|
const { min, max, lower, upper } = this;
|
|
77
79
|
|
|
78
|
-
if (scaled < lower || scaled > upper) throw new Error(
|
|
80
|
+
if (scaled < lower || scaled > upper) throw new Error(MinMaxScalerError.ScaledOutOfBounds);
|
|
79
81
|
|
|
80
82
|
const result = ((scaled - lower) / (upper - lower)) * (max - min) + min;
|
|
81
83
|
|
|
@@ -88,7 +90,7 @@ export class MinMaxScaler {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
static getMinMax(values: MinMaxScalerValueType[]): { min: number; max: number } {
|
|
91
|
-
if (values.length === 0) throw new Error(
|
|
93
|
+
if (values.length === 0) throw new Error(MinMaxScalerError.EmptyArray);
|
|
92
94
|
return { min: Math.min(...values), max: Math.max(...values) };
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const MinuteSchemaError = { Type: "minute.schema.error", Invalid: "minute.schema.invalid" };
|
|
4
|
+
|
|
5
|
+
export const MinuteSchema = z
|
|
6
|
+
.number(MinuteSchemaError.Type)
|
|
7
|
+
.int(MinuteSchemaError.Type)
|
|
8
|
+
.gte(0, MinuteSchemaError.Invalid)
|
|
9
|
+
.lte(59, MinuteSchemaError.Invalid)
|
|
10
|
+
.brand("MinuteSchema");
|
|
11
|
+
|
|
12
|
+
export type MinuteSchemaType = z.infer<typeof MinuteSchema>;
|
package/src/minute.vo.ts
CHANGED
|
@@ -1,32 +1,24 @@
|
|
|
1
|
+
import { MinuteSchema, type MinuteSchemaType } from "./minute-schema.vo";
|
|
1
2
|
import type { TimestampType } from "./timestamp.vo";
|
|
2
3
|
|
|
3
|
-
export const MinuteValueError = "invalid.minute" as const;
|
|
4
|
-
|
|
5
4
|
export class Minute {
|
|
6
|
-
private readonly value:
|
|
5
|
+
private readonly value: MinuteSchemaType;
|
|
7
6
|
|
|
8
7
|
static readonly ZERO = new Minute(0);
|
|
9
8
|
static readonly MAX = new Minute(59);
|
|
10
9
|
|
|
11
10
|
constructor(candidate: number) {
|
|
12
|
-
|
|
13
|
-
throw new Error(MinuteValueError);
|
|
14
|
-
}
|
|
15
|
-
this.value = candidate;
|
|
11
|
+
this.value = MinuteSchema.parse(candidate);
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
static fromEpochMs(timestamp: TimestampType): Minute {
|
|
19
15
|
return new Minute(new Date(timestamp).getUTCMinutes());
|
|
20
16
|
}
|
|
21
17
|
|
|
22
|
-
get():
|
|
18
|
+
get(): MinuteSchemaType {
|
|
23
19
|
return this.value;
|
|
24
20
|
}
|
|
25
21
|
|
|
26
|
-
toString(): string {
|
|
27
|
-
return this.value.toString().padStart(2, "0");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
22
|
equals(another: Minute): boolean {
|
|
31
23
|
return this.value === another.value;
|
|
32
24
|
}
|
|
@@ -42,4 +34,12 @@ export class Minute {
|
|
|
42
34
|
static list(): readonly Minute[] {
|
|
43
35
|
return Array.from({ length: 60 }, (_, index) => new Minute(index));
|
|
44
36
|
}
|
|
37
|
+
|
|
38
|
+
toString(): string {
|
|
39
|
+
return this.value.toString().padStart(2, "0");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
toJSON(): number {
|
|
43
|
+
return this.value;
|
|
44
|
+
}
|
|
45
45
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const MoneyAmountError = { Type: "money.amount.type", Invalid: "money.amount.invalid" };
|
|
4
|
+
|
|
5
|
+
export const MoneyAmount = z
|
|
6
|
+
.number(MoneyAmountError.Type)
|
|
7
|
+
.int(MoneyAmountError.Type)
|
|
8
|
+
.min(0, MoneyAmountError.Invalid)
|
|
9
|
+
.brand("MoneyAmount");
|
|
10
|
+
|
|
11
|
+
export type MoneyAmountType = z.infer<typeof MoneyAmount>;
|
package/src/money.vo.ts
CHANGED
|
@@ -1,35 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { DivisionFactorType } from "./division-factor.vo";
|
|
2
|
+
import { MoneyAmount, type MoneyAmountType } from "./money-amount.vo";
|
|
3
|
+
import type { MultiplicationFactorType } from "./multiplication-factor.vo";
|
|
4
|
+
import { RoundDown, RoundToNearest } from "./rounding.adapter";
|
|
3
5
|
import type { RoundingPort } from "./rounding.port";
|
|
4
6
|
|
|
5
|
-
export const
|
|
6
|
-
export const MoneyMultiplicationFactorInvalidError = {
|
|
7
|
-
error: "money.multiplication-factor.invalid",
|
|
8
|
-
} as const;
|
|
9
|
-
export const MoneyDivisionFactorInvalidError = { error: "money.division-factor.invalid" } as const;
|
|
10
|
-
export const MoneySubtractLessThanZeroError = "money.subtract.less.than.zero" as const;
|
|
11
|
-
|
|
12
|
-
export const MoneyAmount = z
|
|
13
|
-
.number(MoneyAmountInvalidError)
|
|
14
|
-
.int(MoneyAmountInvalidError)
|
|
15
|
-
.min(0, MoneyAmountInvalidError)
|
|
16
|
-
.brand("MoneyAmount");
|
|
17
|
-
|
|
18
|
-
export type MoneyAmountType = z.infer<typeof MoneyAmount>;
|
|
19
|
-
|
|
20
|
-
export const MoneyMultiplicationFactor = z
|
|
21
|
-
.number(MoneyMultiplicationFactorInvalidError)
|
|
22
|
-
.min(0, MoneyMultiplicationFactorInvalidError)
|
|
23
|
-
.brand("MoneyMultiplicationFactor");
|
|
24
|
-
|
|
25
|
-
export type MoneyMultiplicationFactorType = z.infer<typeof MoneyMultiplicationFactor>;
|
|
26
|
-
|
|
27
|
-
export const MoneyDivisionFactor = z
|
|
28
|
-
.number(MoneyDivisionFactorInvalidError)
|
|
29
|
-
.gt(0, MoneyDivisionFactorInvalidError)
|
|
30
|
-
.brand("MoneyDivisionFactor");
|
|
31
|
-
|
|
32
|
-
export type MoneyDivisionFactorType = z.infer<typeof MoneyDivisionFactor>;
|
|
7
|
+
export const MoneyError = { SubtractResultLessThanZero: "money.subtract.result.less.than.zero" } as const;
|
|
33
8
|
|
|
34
9
|
export class Money {
|
|
35
10
|
private static readonly ZERO = 0;
|
|
@@ -48,25 +23,25 @@ export class Money {
|
|
|
48
23
|
}
|
|
49
24
|
|
|
50
25
|
add(money: Money): Money {
|
|
51
|
-
const result = this.
|
|
26
|
+
const result = this.amount + money.getAmount();
|
|
52
27
|
|
|
53
28
|
return new Money(MoneyAmount.parse(result), this.rounding);
|
|
54
29
|
}
|
|
55
30
|
|
|
56
|
-
multiply(factor:
|
|
31
|
+
multiply(factor: MultiplicationFactorType): Money {
|
|
57
32
|
const result = this.rounding.round(this.amount * factor);
|
|
58
33
|
|
|
59
34
|
return new Money(MoneyAmount.parse(result), this.rounding);
|
|
60
35
|
}
|
|
61
36
|
|
|
62
37
|
subtract(money: Money): Money {
|
|
63
|
-
const result = this.
|
|
38
|
+
const result = this.amount - money.getAmount();
|
|
64
39
|
|
|
65
|
-
if (result < Money.ZERO) throw new Error(
|
|
40
|
+
if (result < Money.ZERO) throw new Error(MoneyError.SubtractResultLessThanZero);
|
|
66
41
|
return new Money(MoneyAmount.parse(result), this.rounding);
|
|
67
42
|
}
|
|
68
43
|
|
|
69
|
-
divide(factor:
|
|
44
|
+
divide(factor: DivisionFactorType): Money {
|
|
70
45
|
const result = this.rounding.round(this.amount / factor);
|
|
71
46
|
|
|
72
47
|
return new Money(MoneyAmount.parse(result), this.rounding);
|
|
@@ -89,10 +64,17 @@ export class Money {
|
|
|
89
64
|
}
|
|
90
65
|
|
|
91
66
|
format(): string {
|
|
92
|
-
const whole =
|
|
67
|
+
const whole = new RoundDown().round(this.amount / 100);
|
|
93
68
|
const fraction = this.amount % 100;
|
|
94
|
-
const fractionFormatted = fraction.toString().padStart(2, "0");
|
|
95
69
|
|
|
96
|
-
return `${whole}.${
|
|
70
|
+
return `${whole}.${fraction.toString().padStart(2, "0")}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
toString(): string {
|
|
74
|
+
return this.format();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
toJSON(): number {
|
|
78
|
+
return this.amount;
|
|
97
79
|
}
|
|
98
80
|
}
|
package/src/month-iso-id.vo.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
|
|
3
|
-
export const MonthIsoIdError = {
|
|
3
|
+
export const MonthIsoIdError = {
|
|
4
|
+
Type: "month.iso.id.type",
|
|
5
|
+
BadChars: "month.iso.id.bad.chars",
|
|
6
|
+
Invalid: "month.iso.id.invalid",
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
// Four digits, hyphen, two digits
|
|
10
|
+
const MONTH_ISO_ID_CHARS_WHITELIST = /^\d{4}-\d{2}$/;
|
|
4
11
|
|
|
5
12
|
export const MonthIsoId = z
|
|
6
|
-
.string(MonthIsoIdError)
|
|
7
|
-
.regex(
|
|
13
|
+
.string(MonthIsoIdError.Type)
|
|
14
|
+
.regex(MONTH_ISO_ID_CHARS_WHITELIST, MonthIsoIdError.BadChars)
|
|
8
15
|
.refine((value) => {
|
|
9
|
-
const
|
|
10
|
-
const month = Number(value.slice(5, 7));
|
|
16
|
+
const month = value.split("-").map(Number)[1];
|
|
11
17
|
|
|
12
|
-
return
|
|
13
|
-
}, MonthIsoIdError)
|
|
18
|
+
return month >= 1 && month <= 12;
|
|
19
|
+
}, MonthIsoIdError.Invalid)
|
|
20
|
+
.brand("MonthIsoId");
|
|
14
21
|
|
|
15
22
|
export type MonthIsoIdType = z.infer<typeof MonthIsoId>;
|