diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f119c0..996ea4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- reworked HObjects(no backward compatible changes) +- renamed ValueObjects: + - DateTime -> HDateTime + - UIntValue -> UInt + - UBigInt -> UBigInt64 + - StringValue -> HString + - RegexStringValue -> HRegexString + + ## [0.16.0] - 2024-09-23 ### Added diff --git a/src/Domain/ValueObject/AccountId.ts b/src/Domain/ValueObject/AccountId.ts index 6c21574..63669b3 100644 --- a/src/Domain/ValueObject/AccountId.ts +++ b/src/Domain/ValueObject/AccountId.ts @@ -1,6 +1,6 @@ import { HObjectTypeMeta } from "../../Util"; -import { StringValue } from "./StringValue"; +import { HString } from "./HString"; -export class AccountId extends StringValue { +export class AccountId extends HString { public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Account', 'ValueObject', 'AccountId', AccountId); } \ No newline at end of file diff --git a/src/Domain/ValueObject/Email.ts b/src/Domain/ValueObject/Email.ts index 956848b..cc5b645 100644 --- a/src/Domain/ValueObject/Email.ts +++ b/src/Domain/ValueObject/Email.ts @@ -1,11 +1,11 @@ import { HObjectTypeMeta } from "../../Util"; import { EmailHash } from './EmailHash'; -import { RegexStringValue } from './RegexStringValue'; +import { HRegexString } from './HRegexString'; const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i; -export class Email extends RegexStringValue { +export class Email extends HRegexString { public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'Email', Email); public static getRegex(): RegExp { diff --git a/src/Domain/ValueObject/EmailHash.ts b/src/Domain/ValueObject/EmailHash.ts index 597871d..5ff98d9 100644 --- a/src/Domain/ValueObject/EmailHash.ts +++ b/src/Domain/ValueObject/EmailHash.ts @@ -1,9 +1,9 @@ -import { StringValue } from './StringValue'; +import { HString } from './HString'; import { hash } from 'node:crypto'; import { Email } from './Email'; import { HObjectTypeMeta } from "../../Util"; -export class EmailHash extends StringValue { +export class EmailHash extends HString { public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'EmailHash', EmailHash); public static createFromEmail(email: Email): EmailHash { diff --git a/src/Domain/ValueObject/DateTime.ts b/src/Domain/ValueObject/HDateTime.ts similarity index 77% rename from src/Domain/ValueObject/DateTime.ts rename to src/Domain/ValueObject/HDateTime.ts index 62e48d2..33c4adf 100644 --- a/src/Domain/ValueObject/DateTime.ts +++ b/src/Domain/ValueObject/HDateTime.ts @@ -1,7 +1,7 @@ import { AbstractValueObject, type AnyValueObject, type ValueObjectType } from './AbstractValueObject'; import { OK, R } from '../../Util/Result'; import { DateTimeFormatter, Duration, Instant, LocalDateTime, Period, ZoneId, ZoneOffset, convert } from '@js-joda/core'; -import { HObjectTypeMeta, InvalidStringPlainParseIssue, InvalidTypePlainParseIssue, PlainParseHelper, TooSmallPlainParseIssue, type PlainParseError } from "../../Util"; +import { HObjectTypeMeta, InvalidStringPlainParseIssue, InvalidTypePlainParseIssue, PlainParseHelper, TooSmallPlainParseIssue, type PlainParseError } from "../../Util"; export const DEFAULT_DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); @@ -28,29 +28,29 @@ function createJsJodaFromTimestamp(v: number): LocalDateTime { /** * DateTime in UTC zone value object */ -export class DateTime extends AbstractValueObject { - public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'DateTime', DateTime); +export class HDateTime extends AbstractValueObject { + public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'HDateTime', HDateTime); public constructor(private readonly value: LocalDateTime) { super(); } - public static now(): DateTime { + public static now(): HDateTime { return new this(LocalDateTime.now(ZoneOffset.UTC).withNano(0)); } - public static nowWithNano(): DateTime { + public static nowWithNano(): HDateTime { return new this(LocalDateTime.now(ZoneOffset.UTC)); } public static parse(this: ValueObjectType, plain: unknown): R { switch (typeof plain) { - case 'number': return DateTime.fromTimestamp(plain) as any; + case 'number': return HDateTime.fromTimestamp(plain) as any; case 'string': try { return OK(new this(createJsJodaFromString(plain))); } catch (e) { - return PlainParseHelper.HObjectParseErr(DateTime, [ + return PlainParseHelper.HObjectParseErr(HDateTime, [ new InvalidStringPlainParseIssue('datetime', {}, 'Given plain string is not valid datetime') ]) as any; } @@ -60,7 +60,7 @@ export class DateTime extends AbstractValueObject { return OK(new this(createJsJodaFromDate(plain))); } - return PlainParseHelper.HObjectParseErr(DateTime, [ + return PlainParseHelper.HObjectParseErr(HDateTime, [ new InvalidTypePlainParseIssue(["number", "string", "Date"], typeof plain) ]) as any; } @@ -70,7 +70,7 @@ export class DateTime extends AbstractValueObject { * @param v * @returns */ - public static cs(v: Date | number | string): DateTime { + public static cs(v: Date | number | string): HDateTime { if (typeof v === 'number') { return new this(createJsJodaFromTimestamp(v)); } @@ -87,14 +87,14 @@ export class DateTime extends AbstractValueObject { * @param timestamp * @returns */ - public static fromTimestamp(timestamp: number): R { + public static fromTimestamp(timestamp: number): R { timestamp = Math.trunc(timestamp); if (timestamp < 0) { - return PlainParseHelper.HObjectParseErr(DateTime, [ + return PlainParseHelper.HObjectParseErr(HDateTime, [ TooSmallPlainParseIssue.numberGTE(0, timestamp) ]); } - return OK(new DateTime(createJsJodaFromTimestamp(timestamp))); + return OK(new HDateTime(createJsJodaFromTimestamp(timestamp))); } /** @@ -116,8 +116,8 @@ export class DateTime extends AbstractValueObject { * @param amount * @returns */ - public plus(amount: Period | Duration): DateTime { - return new DateTime(this.value.plus(amount)); + public plus(amount: Period | Duration): HDateTime { + return new HDateTime(this.value.plus(amount)); } /** @@ -125,19 +125,19 @@ export class DateTime extends AbstractValueObject { * @param amount * @returns */ - public minus(amount: Period | Duration): DateTime { - return new DateTime(this.value.minus(amount)); + public minus(amount: Period | Duration): HDateTime { + return new HDateTime(this.value.minus(amount)); } - public equals(o: DateTime): boolean { + public equals(o: HDateTime): boolean { return this.value.equals(o.value); } - public isAfter(o: DateTime): boolean { + public isAfter(o: HDateTime): boolean { return this.value.isAfter(o.value); } - public isBefore(o: DateTime): boolean { + public isBefore(o: HDateTime): boolean { return this.value.isBefore(o.value); } diff --git a/src/Domain/ValueObject/RegexStringValue.ts b/src/Domain/ValueObject/HRegexString.ts similarity index 84% rename from src/Domain/ValueObject/RegexStringValue.ts rename to src/Domain/ValueObject/HRegexString.ts index 3f8f8f2..cc89efb 100644 --- a/src/Domain/ValueObject/RegexStringValue.ts +++ b/src/Domain/ValueObject/HRegexString.ts @@ -1,7 +1,7 @@ import { LogicError, OK, StringPlainParseHelper, PlainParseHelper, PlainParseIssue, type PlainParseError, type R } from '../../Util'; import { AbstractValueObject, type AnyValueObject, type ValueObjectType } from "./AbstractValueObject"; -export abstract class RegexStringValue> extends AbstractValueObject { +export abstract class HRegexString> extends AbstractValueObject { public constructor(public readonly v: string) { super(); } @@ -24,7 +24,7 @@ export abstract class RegexStringValue> extends * @param v * @returns */ - public static cs>(this: ValueObjectType, v: string): T { + public static cs>(this: ValueObjectType, v: string): T { return new (this as any)(v); } diff --git a/src/Domain/ValueObject/StringValue.ts b/src/Domain/ValueObject/HString.ts similarity index 81% rename from src/Domain/ValueObject/StringValue.ts rename to src/Domain/ValueObject/HString.ts index 3f7524f..e058df6 100644 --- a/src/Domain/ValueObject/StringValue.ts +++ b/src/Domain/ValueObject/HString.ts @@ -1,8 +1,8 @@ import { HObjectTypeMeta, OK, PlainParseError, PlainParseHelper, StringPlainParseHelper, PlainParseIssue, type R } from "../../Util"; import { AbstractValueObject, type AnyValueObject, type ValueObjectType } from "./AbstractValueObject"; -export class StringValue = any> extends AbstractValueObject { - public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'String', StringValue); +export class HString = any> extends AbstractValueObject { + public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'HString', HString); public constructor(public readonly v: string) { @@ -23,7 +23,7 @@ export class StringValue = any> extends AbstractValue * @param v * @returns */ - public static cs(this: ValueObjectType, v: string): T { + public static cs(this: ValueObjectType, v: string): T { return new (this as any)(v); } diff --git a/src/Domain/ValueObject/RefId.ts b/src/Domain/ValueObject/RefId.ts index 7f9c38e..fff5403 100644 --- a/src/Domain/ValueObject/RefId.ts +++ b/src/Domain/ValueObject/RefId.ts @@ -1,4 +1,4 @@ -import { StringValue } from "./StringValue"; +import { HString } from "./HString"; import { customAlphabet } from 'nanoid'; import { HObjectTypeMeta } from "../../Util"; @@ -7,7 +7,7 @@ const RefIdGenerator = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcde /** * Represents unique random string id. Generates nanoid - 21 characters */ -export class RefId extends StringValue { +export class RefId extends HString { public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'RefId', RefId); public static gen(): RefId { diff --git a/src/Domain/ValueObject/UBigIntValue.ts b/src/Domain/ValueObject/UBigInt64.ts similarity index 80% rename from src/Domain/ValueObject/UBigIntValue.ts rename to src/Domain/ValueObject/UBigInt64.ts index 517b7a6..9c6688d 100644 --- a/src/Domain/ValueObject/UBigIntValue.ts +++ b/src/Domain/ValueObject/UBigInt64.ts @@ -1,8 +1,8 @@ import { HObjectTypeMeta, OK, PlainParseHelper, PlainParseIssue, type PlainParseError, type R } from '../../Util'; import { AbstractValueObject, type AnyValueObject, type ValueObjectType } from './AbstractValueObject'; -export class UBigIntValue = any> extends AbstractValueObject { - public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'UBigInt', UBigIntValue); +export class UBigInt64 = any> extends AbstractValueObject { + public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'Core', 'ValueObject', 'UBigInt64', UBigInt64); public constructor(public readonly v: bigint) { super(); @@ -22,7 +22,7 @@ export class UBigIntValue = any> extends AbstractVal * @param v * @returns */ - public static cs(this: ValueObjectType, v: string | number | bigint): T { + public static cs(this: ValueObjectType, v: string | number | bigint): T { return new (this as any)(BigInt(v)); } diff --git a/src/Domain/ValueObject/UIntValue.ts b/src/Domain/ValueObject/UInt.ts similarity index 82% rename from src/Domain/ValueObject/UIntValue.ts rename to src/Domain/ValueObject/UInt.ts index 3ed9b34..d35e0da 100644 --- a/src/Domain/ValueObject/UIntValue.ts +++ b/src/Domain/ValueObject/UInt.ts @@ -1,8 +1,8 @@ import { HObjectTypeMeta, IntegerPlainParseHelper, OK, PlainParseHelper, type PlainParseError, type R } from '../../Util'; import { AbstractValueObject, type AnyValueObject, type ValueObjectType } from './AbstractValueObject'; -export class UIntValue = any> extends AbstractValueObject { - public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'User', 'ValueObject', 'UInt', UIntValue); +export class UInt = any> extends AbstractValueObject { + public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'User', 'ValueObject', 'UInt', UInt); public constructor(public readonly v: number) { super(); @@ -18,7 +18,7 @@ export class UIntValue = any> extends AbstractValueObje * @param v * @returns */ - public static cs(this: ValueObjectType, v: string | number): T { + public static cs(this: ValueObjectType, v: string | number): T { if (typeof v === 'string') { v = Number.parseInt(v); } diff --git a/src/Domain/ValueObject/UserId.ts b/src/Domain/ValueObject/UserId.ts index 154f4f9..25c9a98 100644 --- a/src/Domain/ValueObject/UserId.ts +++ b/src/Domain/ValueObject/UserId.ts @@ -1,6 +1,6 @@ import { HObjectTypeMeta } from "../../Util"; -import { StringValue } from "./StringValue"; +import { HString } from "./HString"; -export class UserId extends StringValue { +export class UserId extends HString { public static readonly HOBJ_META = HObjectTypeMeta.domain('Core', 'User', 'ValueObject', 'UserId', UserId); } diff --git a/src/Domain/ValueObject/index.ts b/src/Domain/ValueObject/index.ts index e689d4d..cd93ba1 100644 --- a/src/Domain/ValueObject/index.ts +++ b/src/Domain/ValueObject/index.ts @@ -10,11 +10,11 @@ export * from './Email'; export * from './EmailHash'; // TIME -export * from './DateTime'; +export * from './HDateTime'; // PRIMITIVE -export * from './StringValue'; -export * from './UBigIntValue'; -export * from './UIntValue'; -export * from './RegexStringValue'; +export * from './HString'; +export * from './UBigInt64'; +export * from './UInt'; +export * from './HRegexString'; export * from './RefId'; diff --git a/src/Util/CurrentTime.ts b/src/Util/CurrentTime.ts index 4401dc9..99f466e 100644 --- a/src/Util/CurrentTime.ts +++ b/src/Util/CurrentTime.ts @@ -1,15 +1,15 @@ -import { DateTime } from '../Domain'; +import { HDateTime } from '../Domain'; export class CurrentTime { public static i: CurrentTime; - private constNow!: DateTime|null; + private constNow!: HDateTime | null; - public get now(): DateTime { - return this.constNow ?? DateTime.now(); + public get now(): HDateTime { + return this.constNow ?? HDateTime.now(); } - public set now(now: DateTime | null) { + public set now(now: HDateTime | null) { this.constNow = now; } } diff --git a/test/helper/TestDto.ts b/test/helper/TestDto.ts index 5d8d444..a087842 100644 --- a/test/helper/TestDto.ts +++ b/test/helper/TestDto.ts @@ -1,5 +1,5 @@ import { - UIntValue, Dto, + UInt, Dto, type JsonObjectType, type R, type PlainParseError, PlainParseHelper, @@ -16,7 +16,7 @@ import { } from "@"; import type { v } from "@/Util/Plain/types"; -export class TestValueObject extends UIntValue { } +export class TestValueObject extends UInt { } export class OtherTestDto extends Dto { public primitiveField!: v.int.between<10, 100>; diff --git a/test/unit/Domain/ValueObject/DateTime.test.ts b/test/unit/Domain/ValueObject/HDateTime.test.ts similarity index 52% rename from test/unit/Domain/ValueObject/DateTime.test.ts rename to test/unit/Domain/ValueObject/HDateTime.test.ts index 34c9847..fab8020 100644 --- a/test/unit/Domain/ValueObject/DateTime.test.ts +++ b/test/unit/Domain/ValueObject/HDateTime.test.ts @@ -2,7 +2,7 @@ * @group unit */ -import { DateTime, InvalidHObjectPlainParseIssue, PlainParseError, TooSmallPlainParseIssue } from '@'; +import { HDateTime, InvalidHObjectPlainParseIssue, PlainParseError, TooSmallPlainParseIssue } from '@'; import { Duration, Period } from '@js-joda/core'; describe('DateTime', () => { @@ -10,19 +10,19 @@ describe('DateTime', () => { test('when input is Date', () => { const raw = new Date("2024-01-01 10:30:30"); - const result = DateTime.parse(raw); + const result = HDateTime.parse(raw); expect(result.v.formatDateTime()).toBe(raw.toISOString().replace(/\..+/, "")); }); test.each([ - {name: "dateTimeIso", raw: "2024-01-01 10:30:30.300Z", expected: "2024-01-01T10:30:30"}, - {name: "dateTimeSpace", raw: "2024-01-01 10:30:30", expected: "2024-01-01T10:30:30"}, - {name: "dateTimeTSeparator", raw: "2024-01-01T10:30:30", expected: "2024-01-01T10:30:30"}, - {name: "onlyDate", raw: "2024-01-01", expected: "2024-01-01T00:00:00"} + { name: "dateTimeIso", raw: "2024-01-01 10:30:30.300Z", expected: "2024-01-01T10:30:30" }, + { name: "dateTimeSpace", raw: "2024-01-01 10:30:30", expected: "2024-01-01T10:30:30" }, + { name: "dateTimeTSeparator", raw: "2024-01-01T10:30:30", expected: "2024-01-01T10:30:30" }, + { name: "onlyDate", raw: "2024-01-01", expected: "2024-01-01T00:00:00" } ])('when input is string($name)', (data) => { - const result = DateTime.parse(data.raw); + const result = HDateTime.parse(data.raw); expect(result.isSuccess()).toBe(true); expect(result.v.formatDateTime()).toBe(data.expected); @@ -33,19 +33,19 @@ describe('DateTime', () => { test('when input is Date', () => { const raw = new Date("2024-01-01 10:30:30"); - const result = DateTime.cs(raw); + const result = HDateTime.cs(raw); expect(result.formatDateTime()).toBe(raw.toISOString().replace(/\..+/, "")); }); test.each([ - {name: "dateTimeIso", raw: "2024-01-01 10:30:30.300Z", expected: "2024-01-01T10:30:30"}, - {name: "dateTimeSpace", raw: "2024-01-01 10:30:30", expected: "2024-01-01T10:30:30"}, - {name: "dateTimeTSeparator", raw: "2024-01-01T10:30:30", expected: "2024-01-01T10:30:30"}, - {name: "onlyDate", raw: "2024-01-01", expected: "2024-01-01T00:00:00"} + { name: "dateTimeIso", raw: "2024-01-01 10:30:30.300Z", expected: "2024-01-01T10:30:30" }, + { name: "dateTimeSpace", raw: "2024-01-01 10:30:30", expected: "2024-01-01T10:30:30" }, + { name: "dateTimeTSeparator", raw: "2024-01-01T10:30:30", expected: "2024-01-01T10:30:30" }, + { name: "onlyDate", raw: "2024-01-01", expected: "2024-01-01T00:00:00" } ])('when input is string($name)', (data) => { - const result = DateTime.parse(data.raw); + const result = HDateTime.parse(data.raw); expect(result.isSuccess()).toBe(true); expect(result.v.formatDateTime()).toBe(data.expected); @@ -53,32 +53,32 @@ describe('DateTime', () => { }); test('fromTimestamp', () => { - const result = DateTime.fromTimestamp(1652651144); + const result = HDateTime.fromTimestamp(1652651144); expect(result.v.t).toBe(1652651144); }); test('fromTimestamp when invalid raw value', () => { - const result = DateTime.fromTimestamp(-10); + const result = HDateTime.fromTimestamp(-10); expect(result.isError()).toBe(true); expect(result.e.type).toEqual(PlainParseError); - expect(result.e.data).toEqual(new InvalidHObjectPlainParseIssue(DateTime.HOBJ_META, [ + expect(result.e.data).toEqual(new InvalidHObjectPlainParseIssue(HDateTime.HOBJ_META, [ TooSmallPlainParseIssue.numberGTE(0, -10) ])); }); test('plus()', () => { - const current = DateTime.cs('2023-01-01T10:50:00').plus(Period.ofDays(2)).plus(Duration.ofHours(2)); + const current = HDateTime.cs('2023-01-01T10:50:00').plus(Period.ofDays(2)).plus(Duration.ofHours(2)); expect(current.toString()).toBe('2023-01-03T12:50:00'); }); test('minus()', () => { - const current = DateTime.cs('2023-10-01T10:50:00').minus(Period.ofDays(2)).minus(Duration.ofHours(2)); + const current = HDateTime.cs('2023-10-01T10:50:00').minus(Period.ofDays(2)).minus(Duration.ofHours(2)); expect(current.toString()).toBe('2023-09-29T08:50:00'); }); test('formatRfc1123', () => { - const date = DateTime.cs('2023-10-01 08:50:00'); + const date = HDateTime.cs('2023-10-01 08:50:00'); const current = date.formatRfc1123(); diff --git a/test/unit/Domain/ValueObject/UBigIntValue.test.ts b/test/unit/Domain/ValueObject/UBigInt64.test.ts similarity index 74% rename from test/unit/Domain/ValueObject/UBigIntValue.test.ts rename to test/unit/Domain/ValueObject/UBigInt64.test.ts index d31aff2..62be5ec 100644 --- a/test/unit/Domain/ValueObject/UBigIntValue.test.ts +++ b/test/unit/Domain/ValueObject/UBigInt64.test.ts @@ -2,9 +2,9 @@ * @group unit/core */ -import { PlainParseError, UBigIntValue } from '../../../../src'; +import { PlainParseError, UBigInt64 } from '../../../../src'; -class CustomUBigInt extends UBigIntValue { +class CustomUBigInt extends UBigInt64 { public customMethod() { return 'test'; } @@ -12,19 +12,19 @@ class CustomUBigInt extends UBigIntValue { describe('UBigIntValue', () => { test('create from string', () => { - const result = UBigIntValue.parse('10'); + const result = UBigInt64.parse('10'); expect(result.v.v).toBe(10n); }); test('create when invalid string raw value', () => { - const result = UBigIntValue.parse('-10'); + const result = UBigInt64.parse('-10'); expect(result.isError()).toBe(true); expect(result.e.type).toEqual(PlainParseError); }); test('create from bigint', () => { - const result = UBigIntValue.parse(10n); + const result = UBigInt64.parse(10n); expect(result.v.v).toBe(10n); }); diff --git a/test/unit/Domain/ValueObject/UIntValue.test.ts b/test/unit/Domain/ValueObject/UInt.test.ts similarity index 69% rename from test/unit/Domain/ValueObject/UIntValue.test.ts rename to test/unit/Domain/ValueObject/UInt.test.ts index a6c3536..a83dcfd 100644 --- a/test/unit/Domain/ValueObject/UIntValue.test.ts +++ b/test/unit/Domain/ValueObject/UInt.test.ts @@ -3,16 +3,16 @@ */ import { PlainParseError } from "@"; -import { UIntValue } from '@/Domain/ValueObject/UIntValue'; +import { UInt } from '@/Domain/ValueObject/UInt'; describe('UIntValue', () => { test('create', () => { - const result = UIntValue.parse(10); + const result = UInt.parse(10); expect(result.v.v).toBe(10); }); test('create when invalid raw value', () => { - const result = UIntValue.parse(-10); + const result = UInt.parse(-10); expect(result.isError()).toBe(true); expect(result.e.type).toEqual(PlainParseError);