@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.
Files changed (257) hide show
  1. package/dist/age-years.vo.d.ts +11 -0
  2. package/dist/age-years.vo.js +9 -0
  3. package/dist/age.vo.d.ts +11 -16
  4. package/dist/age.vo.js +20 -31
  5. package/dist/api-key.vo.d.ts +3 -1
  6. package/dist/api-key.vo.js +10 -5
  7. package/dist/basename.vo.d.ts +9 -9
  8. package/dist/basename.vo.js +22 -22
  9. package/dist/clock.vo.d.ts +10 -4
  10. package/dist/clock.vo.js +12 -14
  11. package/dist/date-calculator.service.d.ts +2 -1
  12. package/dist/date-formatter.service.d.ts +3 -4
  13. package/dist/date-range.vo.d.ts +7 -1
  14. package/dist/date-range.vo.js +5 -2
  15. package/dist/day-iso-id.vo.d.ts +5 -2
  16. package/dist/day-iso-id.vo.js +11 -7
  17. package/dist/day.vo.d.ts +4 -3
  18. package/dist/day.vo.js +18 -16
  19. package/dist/directory-path-absolute.vo.d.ts +10 -6
  20. package/dist/directory-path-absolute.vo.js +19 -17
  21. package/dist/directory-path-relative.vo.d.ts +10 -7
  22. package/dist/directory-path-relative.vo.js +18 -17
  23. package/dist/division-factor.vo.d.ts +7 -0
  24. package/dist/division-factor.vo.js +9 -0
  25. package/dist/duration-ms.vo.d.ts +6 -0
  26. package/dist/duration-ms.vo.js +3 -0
  27. package/dist/duration.service.d.ts +2 -14
  28. package/dist/duration.service.js +16 -35
  29. package/dist/email-mask.service.d.ts +1 -6
  30. package/dist/email-mask.service.js +6 -8
  31. package/dist/etags.vo.d.ts +4 -3
  32. package/dist/etags.vo.js +3 -3
  33. package/dist/extension.vo.d.ts +6 -4
  34. package/dist/extension.vo.js +15 -10
  35. package/dist/feature-flag-value.vo.d.ts +10 -0
  36. package/dist/feature-flag-value.vo.js +8 -0
  37. package/dist/feature-flag.vo.d.ts +1 -7
  38. package/dist/feature-flag.vo.js +1 -7
  39. package/dist/file-path-absolute-schema.vo.d.ts +10 -7
  40. package/dist/file-path-absolute-schema.vo.js +17 -17
  41. package/dist/file-path-relative-schema.vo.d.ts +10 -7
  42. package/dist/file-path-relative-schema.vo.js +14 -12
  43. package/dist/file-path.vo.d.ts +4 -4
  44. package/dist/file-path.vo.js +8 -8
  45. package/dist/filename-from-string.vo.d.ts +4 -2
  46. package/dist/filename-from-string.vo.js +10 -8
  47. package/dist/filename-suffix.vo.d.ts +7 -3
  48. package/dist/filename-suffix.vo.js +13 -7
  49. package/dist/filename.vo.d.ts +2 -0
  50. package/dist/filename.vo.js +8 -2
  51. package/dist/height-milimiters.vo.d.ts +6 -0
  52. package/dist/height-milimiters.vo.js +10 -0
  53. package/dist/height.vo.d.ts +3 -20
  54. package/dist/height.vo.js +11 -62
  55. package/dist/hour-format.service.js +1 -1
  56. package/dist/hour-schema.vo.d.ts +7 -0
  57. package/dist/hour-schema.vo.js +8 -0
  58. package/dist/hour.vo.d.ts +4 -3
  59. package/dist/hour.vo.js +8 -8
  60. package/dist/iban-mask.service.d.ts +1 -3
  61. package/dist/iban-mask.service.js +2 -2
  62. package/dist/iban-schema.vo.d.ts +7 -0
  63. package/dist/iban-schema.vo.js +10 -0
  64. package/dist/iban.vo.d.ts +4 -10
  65. package/dist/iban.vo.js +6 -13
  66. package/dist/image.vo.d.ts +6 -4
  67. package/dist/image.vo.js +13 -12
  68. package/dist/index.d.ts +24 -2
  69. package/dist/index.js +24 -2
  70. package/dist/language.vo.d.ts +2 -1
  71. package/dist/language.vo.js +6 -4
  72. package/dist/linear-regression.service.d.ts +27 -0
  73. package/dist/{simple-linear-regression.service.js → linear-regression.service.js} +17 -15
  74. package/dist/mean.service.d.ts +3 -1
  75. package/dist/mean.service.js +3 -4
  76. package/dist/mime-types.vo.d.ts +1 -2
  77. package/dist/mime-value.vo.d.ts +9 -0
  78. package/dist/mime-value.vo.js +9 -0
  79. package/dist/mime.vo.d.ts +11 -17
  80. package/dist/mime.vo.js +10 -27
  81. package/dist/min-max-scaler.service.d.ts +7 -5
  82. package/dist/min-max-scaler.service.js +12 -10
  83. package/dist/minute-schema.vo.d.ts +7 -0
  84. package/dist/minute-schema.vo.js +8 -0
  85. package/dist/minute.vo.d.ts +4 -3
  86. package/dist/minute.vo.js +8 -8
  87. package/dist/money-amount.vo.d.ts +7 -0
  88. package/dist/money-amount.vo.js +7 -0
  89. package/dist/money.vo.d.ts +9 -18
  90. package/dist/money.vo.js +14 -27
  91. package/dist/month-iso-id.vo.d.ts +4 -2
  92. package/dist/month-iso-id.vo.js +13 -7
  93. package/dist/month.vo.d.ts +4 -3
  94. package/dist/month.vo.js +21 -21
  95. package/dist/multiplication-factor.vo.d.ts +7 -0
  96. package/dist/multiplication-factor.vo.js +9 -0
  97. package/dist/object-key.vo.d.ts +9 -6
  98. package/dist/object-key.vo.js +20 -19
  99. package/dist/outlier-detector.service.d.ts +3 -1
  100. package/dist/outlier-detector.service.js +2 -2
  101. package/dist/package-version-schema.vo.d.ts +11 -0
  102. package/dist/package-version-schema.vo.js +15 -0
  103. package/dist/package-version.vo.d.ts +11 -20
  104. package/dist/package-version.vo.js +11 -20
  105. package/dist/pagination-page.vo.d.ts +6 -0
  106. package/dist/pagination-page.vo.js +7 -0
  107. package/dist/pagination-skip.vo.d.ts +7 -0
  108. package/dist/pagination-skip.vo.js +9 -0
  109. package/dist/pagination-take.vo.d.ts +7 -0
  110. package/dist/pagination-take.vo.js +9 -0
  111. package/dist/pagination.service.d.ts +3 -8
  112. package/dist/pagination.service.js +5 -12
  113. package/dist/percentage.service.d.ts +3 -1
  114. package/dist/percentage.service.js +2 -2
  115. package/dist/population-standard-deviation.service.d.ts +3 -1
  116. package/dist/population-standard-deviation.service.js +5 -4
  117. package/dist/quarter-iso-id.vo.d.ts +3 -2
  118. package/dist/quarter-iso-id.vo.js +7 -9
  119. package/dist/quarter.vo.d.ts +2 -1
  120. package/dist/quarter.vo.js +10 -7
  121. package/dist/random.service.d.ts +3 -4
  122. package/dist/random.service.js +5 -11
  123. package/dist/rate-limiter.service.d.ts +2 -2
  124. package/dist/rate-limiter.service.js +8 -8
  125. package/dist/reordering-item-position-value.vo.d.ts +6 -0
  126. package/dist/reordering-item-position-value.vo.js +6 -0
  127. package/dist/reordering.service.d.ts +7 -23
  128. package/dist/reordering.service.js +15 -24
  129. package/dist/revision-value.vo.d.ts +7 -0
  130. package/dist/revision-value.vo.js +6 -0
  131. package/dist/revision.vo.d.ts +6 -13
  132. package/dist/revision.vo.js +10 -22
  133. package/dist/rounding.adapter.d.ts +7 -2
  134. package/dist/rounding.adapter.js +13 -5
  135. package/dist/size-bytes.vo.d.ts +6 -0
  136. package/dist/size-bytes.vo.js +7 -0
  137. package/dist/size.vo.d.ts +15 -15
  138. package/dist/size.vo.js +41 -51
  139. package/dist/stopwatch.service.d.ts +3 -1
  140. package/dist/stopwatch.service.js +2 -2
  141. package/dist/sum.service.js +8 -8
  142. package/dist/thousands-separator.service.js +4 -1
  143. package/dist/time.service.d.ts +8 -0
  144. package/dist/time.service.js +13 -0
  145. package/dist/timestamp.vo.d.ts +1 -1
  146. package/dist/timestamp.vo.js +4 -5
  147. package/dist/timezone.vo.d.ts +4 -1
  148. package/dist/timezone.vo.js +12 -6
  149. package/dist/tsconfig.tsbuildinfo +1 -1
  150. package/dist/week-iso-id.vo.d.ts +4 -2
  151. package/dist/week-iso-id.vo.js +15 -9
  152. package/dist/week.vo.d.ts +4 -3
  153. package/dist/week.vo.js +21 -22
  154. package/dist/weekday.vo.d.ts +1 -1
  155. package/dist/weekday.vo.js +6 -8
  156. package/dist/weight-grams.vo.d.ts +7 -0
  157. package/dist/weight-grams.vo.js +7 -0
  158. package/dist/weight.vo.d.ts +12 -35
  159. package/dist/weight.vo.js +23 -72
  160. package/dist/year-iso-id.vo.d.ts +3 -2
  161. package/dist/year-iso-id.vo.js +6 -4
  162. package/dist/year.vo.d.ts +5 -6
  163. package/dist/year.vo.js +21 -26
  164. package/dist/z-score.service.d.ts +3 -1
  165. package/dist/z-score.service.js +2 -2
  166. package/package.json +4 -4
  167. package/readme.md +21 -2
  168. package/src/age-years.vo.ts +14 -0
  169. package/src/age.vo.ts +22 -35
  170. package/src/api-key.vo.ts +11 -5
  171. package/src/basename.vo.ts +24 -22
  172. package/src/clock.vo.ts +16 -17
  173. package/src/date-calculator.service.ts +2 -1
  174. package/src/date-formatter.service.ts +4 -5
  175. package/src/date-range.vo.ts +6 -2
  176. package/src/day-iso-id.vo.ts +12 -8
  177. package/src/day.vo.ts +27 -24
  178. package/src/directory-path-absolute.vo.ts +23 -18
  179. package/src/directory-path-relative.vo.ts +21 -18
  180. package/src/division-factor.vo.ts +13 -0
  181. package/src/duration-ms.vo.ts +7 -0
  182. package/src/duration.service.ts +16 -40
  183. package/src/email-mask.service.ts +7 -15
  184. package/src/etags.vo.ts +4 -5
  185. package/src/extension.vo.ts +17 -10
  186. package/src/feature-flag-value.vo.ts +12 -0
  187. package/src/feature-flag.vo.ts +1 -9
  188. package/src/file-path-absolute-schema.vo.ts +18 -17
  189. package/src/file-path-relative-schema.vo.ts +15 -12
  190. package/src/file-path.vo.ts +8 -8
  191. package/src/filename-from-string.vo.ts +12 -9
  192. package/src/filename-suffix.vo.ts +14 -7
  193. package/src/filename.vo.ts +11 -2
  194. package/src/height-milimiters.vo.ts +12 -0
  195. package/src/height.vo.ts +12 -83
  196. package/src/hour-format.service.ts +2 -1
  197. package/src/hour-schema.vo.ts +12 -0
  198. package/src/hour.vo.ts +12 -12
  199. package/src/iban-mask.service.ts +3 -5
  200. package/src/iban-schema.vo.ts +15 -0
  201. package/src/iban.vo.ts +9 -22
  202. package/src/image.vo.ts +14 -12
  203. package/src/index.ts +24 -2
  204. package/src/language.vo.ts +7 -4
  205. package/src/linear-regression.service.ts +71 -0
  206. package/src/mean.service.ts +3 -5
  207. package/src/mime-types.vo.ts +1 -3
  208. package/src/mime-value.vo.ts +12 -0
  209. package/src/mime.vo.ts +12 -33
  210. package/src/min-max-scaler.service.ts +13 -11
  211. package/src/minute-schema.vo.ts +12 -0
  212. package/src/minute.vo.ts +12 -12
  213. package/src/money-amount.vo.ts +11 -0
  214. package/src/money.vo.ts +20 -38
  215. package/src/month-iso-id.vo.ts +14 -7
  216. package/src/month.vo.ts +25 -24
  217. package/src/multiplication-factor.vo.ts +13 -0
  218. package/src/object-key.vo.ts +25 -21
  219. package/src/outlier-detector.service.ts +2 -2
  220. package/src/package-version-schema.vo.ts +21 -0
  221. package/src/package-version.vo.ts +17 -33
  222. package/src/pagination-page.vo.ts +11 -0
  223. package/src/pagination-skip.vo.ts +13 -0
  224. package/src/pagination-take.vo.ts +13 -0
  225. package/src/pagination.service.ts +5 -22
  226. package/src/percentage.service.ts +2 -2
  227. package/src/population-standard-deviation.service.ts +5 -4
  228. package/src/quarter-iso-id.vo.ts +7 -10
  229. package/src/quarter.vo.ts +14 -9
  230. package/src/random.service.ts +6 -9
  231. package/src/rate-limiter.service.ts +9 -8
  232. package/src/reordering-item-position-value.vo.ts +10 -0
  233. package/src/reordering.service.ts +19 -28
  234. package/src/revision-value.vo.ts +10 -0
  235. package/src/revision.vo.ts +10 -25
  236. package/src/rounding.adapter.ts +16 -3
  237. package/src/size-bytes.vo.ts +11 -0
  238. package/src/size.vo.ts +43 -54
  239. package/src/stopwatch.service.ts +3 -3
  240. package/src/sum.service.ts +8 -8
  241. package/src/thousands-separator.service.ts +4 -1
  242. package/src/time.service.ts +15 -0
  243. package/src/timestamp.vo.ts +4 -5
  244. package/src/timezone.vo.ts +12 -6
  245. package/src/week-iso-id.vo.ts +16 -12
  246. package/src/week.vo.ts +26 -28
  247. package/src/weekday.vo.ts +6 -9
  248. package/src/weight-grams.vo.ts +11 -0
  249. package/src/weight.vo.ts +28 -85
  250. package/src/year-iso-id.vo.ts +7 -4
  251. package/src/year.vo.ts +27 -33
  252. package/src/z-score.service.ts +2 -2
  253. package/dist/simple-linear-regression.service.d.ts +0 -25
  254. package/dist/streak-calculator.service.d.ts +0 -13
  255. package/dist/streak-calculator.service.js +0 -22
  256. package/src/simple-linear-regression.service.ts +0 -69
  257. package/src/streak-calculator.service.ts +0 -32
package/dist/week.vo.d.ts CHANGED
@@ -2,11 +2,12 @@ import { DateRange } from "./date-range.vo";
2
2
  import { type TimestampType } from "./timestamp.vo";
3
3
  import { type WeekIsoIdType } from "./week-iso-id.vo";
4
4
  export declare class Week extends DateRange {
5
+ static fromTimestamp(timestamp: TimestampType): Week;
6
+ static fromNow(now: TimestampType): Week;
7
+ static fromIsoId(isoId: WeekIsoIdType): Week;
5
8
  toIsoId(): WeekIsoIdType;
6
9
  previous(): Week;
7
10
  next(): Week;
8
11
  shift(count: number): Week;
9
- static fromTimestamp(timestamp: TimestampType): Week;
10
- static fromNow(now: TimestampType): Week;
11
- static fromIsoId(isoId: WeekIsoIdType): Week;
12
+ toString(): string;
12
13
  }
package/dist/week.vo.js CHANGED
@@ -3,23 +3,6 @@ import { DateRange } from "./date-range.vo";
3
3
  import { Timestamp } from "./timestamp.vo";
4
4
  import { WeekIsoId } from "./week-iso-id.vo";
5
5
  export class Week extends DateRange {
6
- toIsoId() {
7
- const year = getISOWeekYear(this.getStart());
8
- const week = getISOWeek(this.getStart()).toString().padStart(2, "0");
9
- return WeekIsoId.parse(`${year}-W${week}`);
10
- }
11
- previous() {
12
- const shifted = addWeeks(new Date(this.getStart()), -1).getTime();
13
- return Week.fromTimestamp(Timestamp.parse(shifted));
14
- }
15
- next() {
16
- const shifted = addWeeks(new Date(this.getStart()), 1).getTime();
17
- return Week.fromTimestamp(Timestamp.parse(shifted));
18
- }
19
- shift(count) {
20
- const shifted = addWeeks(new Date(this.getStart()), count).getTime();
21
- return Week.fromTimestamp(Timestamp.parse(shifted));
22
- }
23
6
  static fromTimestamp(timestamp) {
24
7
  const start = Timestamp.parse(startOfISOWeek(timestamp).getTime());
25
8
  const end = Timestamp.parse(endOfISOWeek(timestamp).getTime());
@@ -29,11 +12,27 @@ export class Week extends DateRange {
29
12
  return Week.fromTimestamp(now);
30
13
  }
31
14
  static fromIsoId(isoId) {
32
- const [yearPart, weekPart] = WeekIsoId.parse(isoId).split("-W");
33
- const year = Number(yearPart);
34
- const week = Number(weekPart);
15
+ const [year, week] = WeekIsoId.parse(isoId).split("-W").map(Number);
35
16
  // ISO-8601 rule: Jan 4 is always in week 01 of the ISO week-year.
36
- const reference = setISOWeek(new Date(Date.UTC(year, 0, 4)), week);
37
- return Week.fromTimestamp(Timestamp.parse(reference.getTime()));
17
+ const reference = setISOWeek(Date.UTC(year, 0, 4), week).getTime();
18
+ return Week.fromTimestamp(Timestamp.parse(reference));
19
+ }
20
+ toIsoId() {
21
+ const year = getISOWeekYear(this.getStart());
22
+ const week = getISOWeek(this.getStart());
23
+ return WeekIsoId.parse(`${year}-W${String(week).padStart(2, "0")}`);
24
+ }
25
+ previous() {
26
+ return this.shift(-1);
27
+ }
28
+ next() {
29
+ return this.shift(1);
30
+ }
31
+ shift(count) {
32
+ const shifted = addWeeks(this.getStart(), count).getTime();
33
+ return Week.fromTimestamp(Timestamp.parse(shifted));
34
+ }
35
+ toString() {
36
+ return this.toIsoId();
38
37
  }
39
38
  }
@@ -21,7 +21,7 @@ export declare class Weekday {
21
21
  constructor(candidate: number, formatter?: WeekdayFormatter);
22
22
  static fromUtcTimestamp(timestamp: TimestampType, formatter?: WeekdayFormatter): Weekday;
23
23
  get(): number;
24
- format(formatter?: WeekdayFormatter): string;
24
+ format(): string;
25
25
  toString(): string;
26
26
  equals(another: Weekday): boolean;
27
27
  /** ISO-8601 weekday number: Monday=1 ... Sunday=7 */
@@ -47,12 +47,11 @@ export class Weekday {
47
47
  get() {
48
48
  return this.value;
49
49
  }
50
- format(formatter) {
51
- const chosen = formatter ?? this.formatter;
52
- return chosen(this.value);
50
+ format() {
51
+ return this.formatter(this.value);
53
52
  }
54
53
  toString() {
55
- return this.format(WeekdayFormatters.FULL);
54
+ return this.format();
56
55
  }
57
56
  equals(another) {
58
57
  return this.value === another.value;
@@ -83,11 +82,10 @@ export class Weekday {
83
82
  return this.value === 0;
84
83
  }
85
84
  static list(formatter) {
86
- const chosen = formatter ?? undefined;
87
- return Array.from({ length: 7 }, (_, index) => new Weekday(index, chosen));
85
+ return Array.from({ length: 7 }, (_, index) => new Weekday(index, formatter));
88
86
  }
89
87
  static listMondayFirst(formatter) {
90
- const days = Weekday.list(formatter);
91
- return [...days.slice(1), days[0]];
88
+ const [Sunday, ...rest] = Weekday.list(formatter);
89
+ return [...rest, Sunday];
92
90
  }
93
91
  }
@@ -0,0 +1,7 @@
1
+ import { z } from "zod/v4";
2
+ export declare const WeightGramsError: {
3
+ readonly Type: "weight.grams.type";
4
+ readonly Invalid: "weight.grams.invalid";
5
+ };
6
+ export declare const WeightGrams: z.core.$ZodBranded<z.ZodNumber, "WeightGrams">;
7
+ export type WeightGramsType = z.infer<typeof WeightGrams>;
@@ -0,0 +1,7 @@
1
+ import { z } from "zod/v4";
2
+ export const WeightGramsError = { Type: "weight.grams.type", Invalid: "weight.grams.invalid" };
3
+ export const WeightGrams = z
4
+ .number(WeightGramsError.Type)
5
+ .int(WeightGramsError.Type)
6
+ .gte(0, WeightGramsError.Invalid)
7
+ .brand("WeightGrams");
@@ -1,50 +1,27 @@
1
+ import type { DivisionFactorType } from "./division-factor.vo";
2
+ import type { MultiplicationFactorType } from "./multiplication-factor.vo";
1
3
  import type { RoundingPort } from "./rounding.port";
2
- export declare enum WeightUnit {
3
- kg = "kg",
4
- lb = "lb"
5
- }
6
- export declare const WeightNonFiniteError: {
7
- readonly error: "weight.non_finite";
8
- };
9
- export declare const WeightNegativeError: {
10
- readonly error: "weight.negative";
11
- };
12
- export declare const WeightNonPositiveError: {
13
- readonly error: "weight.non_positive";
14
- };
15
- export declare const WeightGramsNonNegativeError: {
16
- readonly error: "weight.grams_non_negative";
17
- };
18
4
  export declare class Weight {
19
5
  private readonly grams;
6
+ private readonly rounding;
20
7
  private static readonly GRAMS_PER_KILOGRAM;
21
- private static readonly POUNDS_PER_KILOGRAM;
22
- private static readonly KILOGRAMS_PER_POUND;
23
8
  private constructor();
24
- static fromKilograms(kilograms: number): Weight;
25
- static fromPounds(pounds: number): Weight;
26
- static fromGrams(grams: number): Weight;
9
+ static fromKilograms(kilograms: number, rounding?: RoundingPort): Weight;
10
+ static fromGrams(grams: number, rounding?: RoundingPort): Weight;
27
11
  static zero(): Weight;
28
- toGrams(): number;
29
- toKilograms(rounding?: RoundingPort): number;
30
- toPounds(rounding?: RoundingPort): number;
31
- format(unit: WeightUnit, rounding?: RoundingPort): string;
12
+ get(): number;
13
+ toKilograms(): number;
14
+ format(): string;
32
15
  add(other: Weight): Weight;
33
16
  subtract(other: Weight): Weight;
34
- multiply(factor: number): Weight;
35
- divideByScalar(divisor: number): Weight;
17
+ multiply(factor: MultiplicationFactorType): Weight;
18
+ divide(divisor: DivisionFactorType): Weight;
36
19
  equals(other: Weight): boolean;
37
- compare(other: Weight): -1 | 0 | 1;
38
20
  greaterThan(other: Weight): boolean;
39
21
  greaterThanOrEqual(other: Weight): boolean;
40
22
  lessThan(other: Weight): boolean;
41
23
  lessThanOrEqual(other: Weight): boolean;
42
24
  isZero(): boolean;
43
- isPositive(): boolean;
44
- toJSON(): {
45
- g: number;
46
- };
47
- static fromJSON(input: {
48
- g: number;
49
- }): Weight;
25
+ toString(): string;
26
+ toJSON(): number;
50
27
  }
package/dist/weight.vo.js CHANGED
@@ -1,69 +1,32 @@
1
- import { z } from "zod/v4";
2
- import { RoundToDecimal } from "./rounding.adapter";
3
- export var WeightUnit;
4
- (function (WeightUnit) {
5
- WeightUnit["kg"] = "kg";
6
- WeightUnit["lb"] = "lb";
7
- })(WeightUnit || (WeightUnit = {}));
8
- export const WeightNonFiniteError = { error: "weight.non_finite" };
9
- export const WeightNegativeError = { error: "weight.negative" };
10
- export const WeightNonPositiveError = { error: "weight.non_positive" };
11
- export const WeightGramsNonNegativeError = { error: "weight.grams_non_negative" };
12
- const WeightQuantityNumber = z
13
- .number(WeightNonFiniteError)
14
- .refine(Number.isFinite, WeightNonFiniteError)
15
- .min(0, WeightNegativeError);
16
- const DivisionScalarNumber = z
17
- .number(WeightNonFiniteError)
18
- .refine(Number.isFinite, WeightNonFiniteError)
19
- .gt(0, WeightNonPositiveError);
20
- const CanonicalGramsInteger = z
21
- .number(WeightGramsNonNegativeError)
22
- .int(WeightGramsNonNegativeError)
23
- .min(0, WeightGramsNonNegativeError);
1
+ import { RoundToNearest } from "./rounding.adapter";
2
+ import { WeightGrams } from "./weight-grams.vo";
24
3
  export class Weight {
25
4
  grams;
5
+ rounding;
26
6
  static GRAMS_PER_KILOGRAM = 1_000;
27
- static POUNDS_PER_KILOGRAM = 2.2046226218487757;
28
- static KILOGRAMS_PER_POUND = 1 / Weight.POUNDS_PER_KILOGRAM;
29
- constructor(grams) {
7
+ constructor(grams, rounding = new RoundToNearest()) {
30
8
  this.grams = grams;
9
+ this.rounding = rounding;
31
10
  }
32
- static fromKilograms(kilograms) {
33
- const kilogramsParsed = WeightQuantityNumber.parse(kilograms);
34
- const gramsRounded = Math.round(kilogramsParsed * Weight.GRAMS_PER_KILOGRAM);
35
- const grams = CanonicalGramsInteger.parse(gramsRounded);
36
- return new Weight(grams);
11
+ static fromKilograms(kilograms, rounding = new RoundToNearest()) {
12
+ const grams = rounding.round(kilograms * Weight.GRAMS_PER_KILOGRAM);
13
+ return new Weight(WeightGrams.parse(grams), rounding);
37
14
  }
38
- static fromPounds(pounds) {
39
- const poundsParsed = WeightQuantityNumber.parse(pounds);
40
- const gramsRounded = Math.round(poundsParsed * Weight.KILOGRAMS_PER_POUND * Weight.GRAMS_PER_KILOGRAM);
41
- const grams = CanonicalGramsInteger.parse(gramsRounded);
42
- return new Weight(grams);
43
- }
44
- static fromGrams(grams) {
45
- const gramsParsed = WeightQuantityNumber.parse(grams);
46
- const gramsRounded = Math.round(gramsParsed);
47
- const integerGrams = CanonicalGramsInteger.parse(gramsRounded);
48
- return new Weight(integerGrams);
15
+ static fromGrams(grams, rounding = new RoundToNearest()) {
16
+ return new Weight(WeightGrams.parse(grams), rounding);
49
17
  }
50
18
  static zero() {
51
19
  return new Weight(0);
52
20
  }
53
- toGrams() {
21
+ get() {
54
22
  return this.grams;
55
23
  }
56
- toKilograms(rounding) {
24
+ toKilograms() {
57
25
  const kilograms = this.grams / Weight.GRAMS_PER_KILOGRAM;
58
- return rounding ? rounding.round(kilograms) : kilograms;
59
- }
60
- toPounds(rounding) {
61
- const pounds = (this.grams / Weight.GRAMS_PER_KILOGRAM) * Weight.POUNDS_PER_KILOGRAM;
62
- return rounding ? rounding.round(pounds) : pounds;
26
+ return this.rounding.round(kilograms);
63
27
  }
64
- format(unit, rounding = new RoundToDecimal(2)) {
65
- const value = unit === WeightUnit.kg ? this.toKilograms(rounding) : this.toPounds(rounding);
66
- return `${value.toString()} ${unit}`;
28
+ format() {
29
+ return `${this.grams} g`;
67
30
  }
68
31
  add(other) {
69
32
  return new Weight(this.grams + other.grams);
@@ -73,25 +36,16 @@ export class Weight {
73
36
  return new Weight(result < 0 ? 0 : result);
74
37
  }
75
38
  multiply(factor) {
76
- const factorParsed = WeightQuantityNumber.parse(factor);
77
- const gramsRounded = Math.round(this.grams * factorParsed);
78
- const grams = CanonicalGramsInteger.parse(gramsRounded);
79
- return new Weight(grams);
39
+ const grams = this.rounding.round(this.grams * factor);
40
+ return new Weight(WeightGrams.parse(grams));
80
41
  }
81
- divideByScalar(divisor) {
82
- const divisorParsed = DivisionScalarNumber.parse(divisor);
83
- const gramsRounded = Math.round(this.grams / divisorParsed);
84
- const grams = CanonicalGramsInteger.parse(gramsRounded);
85
- return new Weight(grams);
42
+ divide(divisor) {
43
+ const grams = this.rounding.round(this.grams / divisor);
44
+ return new Weight(WeightGrams.parse(grams));
86
45
  }
87
46
  equals(other) {
88
47
  return this.grams === other.grams;
89
48
  }
90
- compare(other) {
91
- if (this.grams === other.grams)
92
- return 0;
93
- return this.grams < other.grams ? -1 : 1;
94
- }
95
49
  greaterThan(other) {
96
50
  return this.grams > other.grams;
97
51
  }
@@ -107,13 +61,10 @@ export class Weight {
107
61
  isZero() {
108
62
  return this.grams === 0;
109
63
  }
110
- isPositive() {
111
- return this.grams > 0;
64
+ toString() {
65
+ return this.format();
112
66
  }
113
67
  toJSON() {
114
- return { g: this.grams };
115
- }
116
- static fromJSON(input) {
117
- return Weight.fromGrams(input.g);
68
+ return this.grams;
118
69
  }
119
70
  }
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  export declare const YearIsoIdError: {
3
- readonly error: "year-iso-id.invalid";
3
+ readonly Type: "year.iso.id.type";
4
+ readonly BadChars: "year.iso.id.bad.chars";
4
5
  };
5
- export declare const YearIsoId: z.ZodString;
6
+ export declare const YearIsoId: z.core.$ZodBranded<z.ZodString, "YearIsoId">;
6
7
  export type YearIsoIdType = z.infer<typeof YearIsoId>;
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod/v4";
2
- export const YearIsoIdError = { error: "year-iso-id.invalid" };
2
+ export const YearIsoIdError = { Type: "year.iso.id.type", BadChars: "year.iso.id.bad.chars" };
3
+ // Four digits
4
+ const YEAR_ISO_ID_CHARS_WHITELIST = /^[0-9]{4}$/;
3
5
  export const YearIsoId = z
4
- .string(YearIsoIdError)
5
- .regex(/^\d{4}$/, YearIsoIdError)
6
- .refine((value) => Number.isInteger(Number(value)), YearIsoIdError);
6
+ .string(YearIsoIdError.Type)
7
+ .regex(YEAR_ISO_ID_CHARS_WHITELIST, YearIsoIdError.BadChars)
8
+ .brand("YearIsoId");
package/dist/year.vo.d.ts CHANGED
@@ -1,16 +1,15 @@
1
1
  import { DateRange } from "./date-range.vo";
2
2
  import { type TimestampType } from "./timestamp.vo";
3
3
  import { type YearIsoIdType } from "./year-iso-id.vo";
4
- export declare const YearInvalidIntegerError: "year.invalid_integer";
5
- export declare const YearOutOfRangeError: "year.out_of_range";
6
4
  export declare class Year extends DateRange {
5
+ static fromTimestamp(timestamp: TimestampType): Year;
6
+ static fromNow(now: TimestampType): Year;
7
+ static fromNumber(candidate: number): Year;
8
+ static fromIsoId(isoId: YearIsoIdType): Year;
7
9
  toIsoId(): YearIsoIdType;
8
10
  isLeapYear(): boolean;
9
11
  previous(): Year;
10
12
  next(): Year;
11
13
  shift(count: number): Year;
12
- static fromTimestamp(timestamp: TimestampType): Year;
13
- static fromNow(now: TimestampType): Year;
14
- static fromNumber(value: number): Year;
15
- static fromIsoId(isoId: YearIsoIdType): Year;
14
+ toString(): string;
16
15
  }
package/dist/year.vo.js CHANGED
@@ -2,45 +2,40 @@ import { addYears, endOfYear, getYear, startOfYear } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { Timestamp } from "./timestamp.vo";
4
4
  import { YearIsoId } from "./year-iso-id.vo";
5
- export const YearInvalidIntegerError = "year.invalid_integer";
6
- export const YearOutOfRangeError = "year.out_of_range";
7
5
  export class Year extends DateRange {
6
+ static fromTimestamp(timestamp) {
7
+ const start = Timestamp.parse(startOfYear(timestamp).getTime());
8
+ const end = Timestamp.parse(endOfYear(timestamp).getTime());
9
+ return new Year(start, end);
10
+ }
11
+ static fromNow(now) {
12
+ return Year.fromTimestamp(now);
13
+ }
14
+ static fromNumber(candidate) {
15
+ return Year.fromIsoId(YearIsoId.parse(String(candidate)));
16
+ }
17
+ static fromIsoId(isoId) {
18
+ const reference = Date.UTC(Number(isoId));
19
+ return Year.fromTimestamp(Timestamp.parse(reference));
20
+ }
8
21
  toIsoId() {
9
- return String(getYear(this.getStart()));
22
+ return YearIsoId.parse(String(getYear(this.getStart())));
10
23
  }
11
24
  isLeapYear() {
12
25
  const year = getYear(this.getStart());
13
26
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
14
27
  }
15
28
  previous() {
16
- const shifted = addYears(new Date(this.getStart()), -1).getTime();
17
- return Year.fromTimestamp(Timestamp.parse(shifted));
29
+ return this.shift(-1);
18
30
  }
19
31
  next() {
20
- const shifted = addYears(new Date(this.getStart()), 1).getTime();
21
- return Year.fromTimestamp(Timestamp.parse(shifted));
32
+ return this.shift(1);
22
33
  }
23
34
  shift(count) {
24
- const shifted = addYears(new Date(this.getStart()), count).getTime();
35
+ const shifted = addYears(this.getStart(), count).getTime();
25
36
  return Year.fromTimestamp(Timestamp.parse(shifted));
26
37
  }
27
- static fromTimestamp(timestamp) {
28
- const start = Timestamp.parse(startOfYear(timestamp).getTime());
29
- const end = Timestamp.parse(endOfYear(timestamp).getTime());
30
- return new Year(start, end);
31
- }
32
- static fromNow(now) {
33
- return Year.fromTimestamp(now);
34
- }
35
- static fromNumber(value) {
36
- if (!Number.isInteger(value))
37
- throw new Error(YearInvalidIntegerError);
38
- if (value < 0 || value > 9999)
39
- throw new Error(YearOutOfRangeError);
40
- const reference = Timestamp.parse(Date.UTC(value, 0, 1, 0, 0, 0, 0));
41
- return Year.fromTimestamp(reference);
42
- }
43
- static fromIsoId(isoId) {
44
- return Year.fromNumber(Number(YearIsoId.parse(isoId)));
38
+ toString() {
39
+ return this.toIsoId();
45
40
  }
46
41
  }
@@ -1,5 +1,7 @@
1
1
  import type { RoundingPort } from "./rounding.port";
2
- export declare const ZScoreMinValuesError: "zscore.min.values";
2
+ export declare const ZScoreError: {
3
+ readonly NotEnoughValues: "z.score.not.enough.values";
4
+ };
3
5
  export declare class ZScore {
4
6
  private readonly rounding;
5
7
  private readonly mean;
@@ -1,7 +1,7 @@
1
1
  import { Mean } from "./mean.service";
2
2
  import { PopulationStandardDeviation } from "./population-standard-deviation.service";
3
3
  import { RoundToDecimal } from "./rounding.adapter";
4
- export const ZScoreMinValuesError = "zscore.min.values";
4
+ export const ZScoreError = { NotEnoughValues: "z.score.not.enough.values" };
5
5
  export class ZScore {
6
6
  rounding;
7
7
  mean;
@@ -9,7 +9,7 @@ export class ZScore {
9
9
  constructor(values, rounding = new RoundToDecimal(2)) {
10
10
  this.rounding = rounding;
11
11
  if (values.length < 2)
12
- throw new Error(ZScoreMinValuesError);
12
+ throw new Error(ZScoreError.NotEnoughValues);
13
13
  this.mean = Mean.calculate(values);
14
14
  this.standardDeviation = PopulationStandardDeviation.calculate(values);
15
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/tools",
3
- "version": "0.17.2",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Bartosz Gordon",
@@ -21,13 +21,13 @@
21
21
  "preinstall": "bunx only-allow bun"
22
22
  },
23
23
  "devDependencies": {
24
- "@biomejs/biome": "2.2.5",
24
+ "@biomejs/biome": "2.2.6",
25
25
  "@commitlint/cli": "20.1.0",
26
26
  "@commitlint/config-conventional": "20.0.0",
27
- "@types/bun": "1.2.23",
27
+ "@types/bun": "1.3.0",
28
28
  "@types/mime-types": "3.0.1",
29
29
  "cspell": "9.2.1",
30
- "knip": "5.64.2",
30
+ "knip": "5.65.0",
31
31
  "lefthook": "1.13.6",
32
32
  "only-allow": "1.2.1",
33
33
  "shellcheck": "4.1.0",
package/readme.md CHANGED
@@ -24,6 +24,7 @@ Run the tests
24
24
 
25
25
  ```
26
26
  src/
27
+ ├── age-years.vo.ts
27
28
  ├── age.vo.ts
28
29
  ├── api-key.vo.ts
29
30
  ├── basename.vo.ts
@@ -36,11 +37,14 @@ src/
36
37
  ├── day.vo.ts
37
38
  ├── directory-path-absolute.vo.ts
38
39
  ├── directory-path-relative.vo.ts
40
+ ├── division-factor.vo.ts
39
41
  ├── dll.service.ts
42
+ ├── duration-ms.vo.ts
40
43
  ├── duration.service.ts
41
44
  ├── email-mask.service.ts
42
45
  ├── etags.vo.ts
43
46
  ├── extension.vo.ts
47
+ ├── feature-flag-value.vo.ts
44
48
  ├── feature-flag.vo.ts
45
49
  ├── file-path-absolute-schema.vo.ts
46
50
  ├── file-path-relative-schema.vo.ts
@@ -48,26 +52,38 @@ src/
48
52
  ├── filename-from-string.vo.ts
49
53
  ├── filename-suffix.vo.ts
50
54
  ├── filename.vo.ts
55
+ ├── height-milimiters.vo.ts
51
56
  ├── height.vo.ts
52
57
  ├── hour-format.service.ts
58
+ ├── hour-schema.vo.ts
53
59
  ├── hour.vo.ts
54
60
  ├── iban-mask.service.ts
61
+ ├── iban-schema.vo.ts
55
62
  ├── iban.vo.ts
56
63
  ├── image.vo.ts
57
64
  ├── language.vo.ts
65
+ ├── linear-regression.service.ts
58
66
  ├── mean.service.ts
59
67
  ├── mime-types.vo.ts
68
+ ├── mime-value.vo.ts
60
69
  ├── mime.vo.ts
61
70
  ├── min-max-scaler.service.ts
71
+ ├── minute-schema.vo.ts
62
72
  ├── minute.vo.ts
73
+ ├── money-amount.vo.ts
63
74
  ├── money.vo.ts
64
75
  ├── month-iso-id.vo.ts
65
76
  ├── month.vo.ts
77
+ ├── multiplication-factor.vo.ts
66
78
  ├── noop.service.ts
67
79
  ├── notification-template.vo.ts
68
80
  ├── object-key.vo.ts
69
81
  ├── outlier-detector.service.ts
82
+ ├── package-version-schema.vo.ts
70
83
  ├── package-version.vo.ts
84
+ ├── pagination-page.vo.ts
85
+ ├── pagination-skip.vo.ts
86
+ ├── pagination-take.vo.ts
71
87
  ├── pagination.service.ts
72
88
  ├── percentage.service.ts
73
89
  ├── population-standard-deviation.service.ts
@@ -76,17 +92,19 @@ src/
76
92
  ├── random.service.ts
77
93
  ├── rate-limiter.service.ts
78
94
  ├── relative-date.vo.ts
95
+ ├── reordering-item-position-value.vo.ts
79
96
  ├── reordering.service.ts
97
+ ├── revision-value.vo.ts
80
98
  ├── revision.vo.ts
81
99
  ├── rounding.adapter.ts
82
100
  ├── rounding.port.ts
83
- ├── simple-linear-regression.service.ts
101
+ ├── size-bytes.vo.ts
84
102
  ├── size.vo.ts
85
103
  ├── stopwatch.service.ts
86
- ├── streak-calculator.service.ts
87
104
  ├── sum.service.ts
88
105
  ├── thousands-separator.service.ts
89
106
  ├── time-zone-offset-value.vo.ts
107
+ ├── time.service.ts
90
108
  ├── timestamp.vo.ts
91
109
  ├── timezone.vo.ts
92
110
  ├── ts-utils.ts
@@ -94,6 +112,7 @@ src/
94
112
  ├── week-iso-id.vo.ts
95
113
  ├── week.vo.ts
96
114
  ├── weekday.vo.ts
115
+ ├── weight-grams.vo.ts
97
116
  ├── weight.vo.ts
98
117
  ├── year-iso-id.vo.ts
99
118
  ├── year.vo.ts
@@ -0,0 +1,14 @@
1
+ import { z } from "zod/v4";
2
+
3
+ export const AgeYearsError = { Type: "age.years.type", Invalid: "age.years.invalid" } as const;
4
+
5
+ export const AgeYearsConstraints = { min: 1, max: 130 };
6
+
7
+ export const AgeYears = z
8
+ .number(AgeYearsError.Type)
9
+ .int(AgeYearsError.Type)
10
+ .min(1, AgeYearsError.Invalid)
11
+ .max(130, AgeYearsError.Invalid)
12
+ .brand("AgeYears");
13
+
14
+ export type AgeYearsType = z.infer<typeof AgeYears>;