drimion 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +955 -0
- package/dist/cli/index.js +1045 -0
- package/dist/cli/templates/aggregate.ts.hbs +22 -0
- package/dist/cli/templates/entity.ts.hbs +16 -0
- package/dist/cli/templates/repository.ts.hbs +24 -0
- package/dist/cli/templates/use-case.ts.hbs +20 -0
- package/dist/cli/templates/value-object.ts.hbs +16 -0
- package/dist/kernel/core/aggregate.ts +234 -0
- package/dist/kernel/core/entity.ts +348 -0
- package/dist/kernel/core/id.ts +207 -0
- package/dist/kernel/core/index.ts +5 -0
- package/dist/kernel/core/repository.ts +81 -0
- package/dist/kernel/core/value-object.ts +309 -0
- package/dist/kernel/events/browser-event-manager.ts +241 -0
- package/dist/kernel/events/domain-event.ts +76 -0
- package/dist/kernel/events/event-bus.ts +158 -0
- package/dist/kernel/events/event-context.ts +95 -0
- package/dist/kernel/events/event-manager.ts +20 -0
- package/dist/kernel/events/event-utils.ts +19 -0
- package/dist/kernel/events/index.ts +7 -0
- package/dist/kernel/events/server-event-manager.ts +169 -0
- package/dist/kernel/helpers/auto-mapper.ts +222 -0
- package/dist/kernel/helpers/domain-classes.ts +162 -0
- package/dist/kernel/helpers/domain-error.ts +52 -0
- package/dist/kernel/helpers/getters-setters.ts +385 -0
- package/dist/kernel/helpers/index.ts +7 -0
- package/dist/kernel/index.ts +73 -0
- package/dist/kernel/libs/crypto.ts +33 -0
- package/dist/kernel/libs/index.ts +5 -0
- package/dist/kernel/libs/iterator.ts +298 -0
- package/dist/kernel/libs/result.ts +252 -0
- package/dist/kernel/libs/utils.ts +260 -0
- package/dist/kernel/libs/validator.ts +353 -0
- package/dist/kernel/types/adapter.types.ts +26 -0
- package/dist/kernel/types/command.types.ts +37 -0
- package/dist/kernel/types/entity.types.ts +60 -0
- package/dist/kernel/types/event.types.ts +129 -0
- package/dist/kernel/types/index.ts +26 -0
- package/dist/kernel/types/iterator.types.ts +39 -0
- package/dist/kernel/types/result.types.ts +122 -0
- package/dist/kernel/types/uid.types.ts +18 -0
- package/dist/kernel/types/utils.types.ts +120 -0
- package/dist/kernel/types/value-object.types.ts +20 -0
- package/dist/kernel/utils/date.utils.ts +111 -0
- package/dist/kernel/utils/index.ts +32 -0
- package/dist/kernel/utils/number.utils.ts +341 -0
- package/dist/kernel/utils/object.utils.ts +61 -0
- package/dist/kernel/utils/string.utils.ts +128 -0
- package/dist/kernel/utils/type.utils.ts +33 -0
- package/package.json +59 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { UID } from "./uid.types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* Represents the static side (constructor + factory contract) of an `Aggregate` subclass.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `EntityConstructor` but scoped to `Aggregate` subclasses, enabling the same
|
|
8
|
+
* polymorphic `this`-typed factory pattern used by `Entity.create()` and `Entity.init()`.
|
|
9
|
+
*
|
|
10
|
+
* @template Props The shape of the aggregate's user-defined domain properties.
|
|
11
|
+
* @template T The concrete `Aggregate` subclass type.
|
|
12
|
+
*/
|
|
13
|
+
export type AggregateConstructor<Props extends object, T> = {
|
|
14
|
+
isValidProps(props: Props): boolean;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
prototype: T;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @description
|
|
21
|
+
* Represents the static side (constructor + factory contract) of an `Entity` subclass.
|
|
22
|
+
*
|
|
23
|
+
* Used by `Entity.create()` and `Entity.init()` to enable the polymorphic
|
|
24
|
+
* `this`-typed factory pattern — calling `User.create(props)` infers `T = User`
|
|
25
|
+
* automatically without requiring subclasses to override the factory.
|
|
26
|
+
*
|
|
27
|
+
* @template Props The shape of the entity's user-defined domain properties.
|
|
28
|
+
* @template T The concrete `Entity` subclass type.
|
|
29
|
+
*/
|
|
30
|
+
export type EntityConstructor<Props extends object, T> = {
|
|
31
|
+
isValidProps(props: Props): boolean;
|
|
32
|
+
readonly name: string;
|
|
33
|
+
prototype: T;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @description
|
|
38
|
+
* Merges user-defined `Props` with the implicit Entity lifecycle fields.
|
|
39
|
+
*/
|
|
40
|
+
export type EntityProps<T extends object> = T & {
|
|
41
|
+
id?: string | number | UID<string>;
|
|
42
|
+
createdAt?: Date;
|
|
43
|
+
updatedAt?: Date;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @description
|
|
48
|
+
* Represents the base constraint for an entity's user-defined properties.
|
|
49
|
+
* Must be a plain object (no primitives, arrays, or class instances).
|
|
50
|
+
*/
|
|
51
|
+
export type IEntityProps = object;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @description
|
|
55
|
+
* Configuration options for getter and setter behavior on an entity instance.
|
|
56
|
+
*/
|
|
57
|
+
export interface IEntitySettings {
|
|
58
|
+
disableGetters?: boolean;
|
|
59
|
+
disableSetters?: boolean;
|
|
60
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Represents a domain event — an immutable record of something that happened
|
|
4
|
+
* within an aggregate boundary.
|
|
5
|
+
*
|
|
6
|
+
* Domain events are plain data. They carry no behaviour, no handlers, and no
|
|
7
|
+
* knowledge of how they will be consumed. The `type` field is the only
|
|
8
|
+
* required identifier; every other field provides tracing context.
|
|
9
|
+
*
|
|
10
|
+
* Naming convention: past-tense, `aggregate:fact` format.
|
|
11
|
+
* @example `'order:placed'`, `'user:registered'`, `'pokemon:caught'`
|
|
12
|
+
*
|
|
13
|
+
* @template TPayload The shape of the event-specific data.
|
|
14
|
+
*/
|
|
15
|
+
export interface DomainEvent<TPayload = unknown> {
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* The event type identifier. Use past-tense, colon-separated format:
|
|
19
|
+
* `'<aggregate>:<fact>'` — e.g. `'order:placed'`, `'user:email-changed'`.
|
|
20
|
+
*/
|
|
21
|
+
readonly type: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @description
|
|
25
|
+
* The string value of the aggregate's `id` at the time the event was emitted.
|
|
26
|
+
*/
|
|
27
|
+
readonly aggregateId?: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description
|
|
31
|
+
* The class name of the aggregate that emitted this event.
|
|
32
|
+
* Useful for logging, filtering, and debugging across aggregate boundaries.
|
|
33
|
+
*
|
|
34
|
+
* @example `'Order'`, `'User'`, `'Pokemon'`
|
|
35
|
+
*/
|
|
36
|
+
readonly aggregateName?: string;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @description
|
|
40
|
+
* The timestamp at which this event was created inside the aggregate.
|
|
41
|
+
* Reflects domain time, not infrastructure time.
|
|
42
|
+
*/
|
|
43
|
+
readonly occurredAt?: Date;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @description
|
|
47
|
+
* Event-specific data. Keep this flat and serializable — avoid class
|
|
48
|
+
* instances, functions, or circular references so the event can be safely
|
|
49
|
+
* transmitted across process boundaries.
|
|
50
|
+
*/
|
|
51
|
+
readonly payload?: TPayload;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @description
|
|
56
|
+
* Represents a generic browser / server event payload wrapper.
|
|
57
|
+
* Used internally by `BrowserEventManager` and `ServerEventManager`.
|
|
58
|
+
*
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export type DomainEventPayload = { detail?: unknown[] };
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @description
|
|
65
|
+
* Stores a registered event name and its associated callback.
|
|
66
|
+
* Used internally by the built-in event managers.
|
|
67
|
+
*
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
export interface EventEntry {
|
|
71
|
+
eventName: string;
|
|
72
|
+
callback: (event: DomainEventPayload) => void | Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @description
|
|
77
|
+
* Subscriber callback type — receives a fully-typed `DomainEvent` and may
|
|
78
|
+
* return a `Promise` for async side effects.
|
|
79
|
+
*/
|
|
80
|
+
export type EventSubscriber<TPayload = unknown> = (
|
|
81
|
+
event: DomainEvent<TPayload>,
|
|
82
|
+
) => void | Promise<void>;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @description
|
|
86
|
+
* Contract for an application-level event bus.
|
|
87
|
+
*
|
|
88
|
+
* Implement this interface to integrate any pub-sub mechanism — an in-process
|
|
89
|
+
* `EventEmitter`, a Redis Streams adapter, BullMQ, NATS, or any other
|
|
90
|
+
* transport — with the domain event system produced by `Aggregate.pullEvents()`.
|
|
91
|
+
*
|
|
92
|
+
* The library ships with a `EventBus` implementation that works
|
|
93
|
+
* out-of-the-box in both Node.js and browser environments. Swap it for your
|
|
94
|
+
* own at the application layer without touching any domain code.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* class RedisEventBus implements IEventBus {
|
|
99
|
+
* async publish(event: DomainEvent): Promise<void> {
|
|
100
|
+
* await redis.xadd(event.type, '*', 'data', JSON.stringify(event));
|
|
101
|
+
* }
|
|
102
|
+
* async publishAll(events: ReadonlyArray<DomainEvent>): Promise<void> {
|
|
103
|
+
* for (const event of events) await this.publish(event);
|
|
104
|
+
* }
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export interface IEventBus {
|
|
109
|
+
/**
|
|
110
|
+
* @description Publishes a single domain event.
|
|
111
|
+
*/
|
|
112
|
+
publish(event: DomainEvent): Promise<void>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @description
|
|
116
|
+
* Publishes all domain events in the provided array.
|
|
117
|
+
* Implementations should preserve order.
|
|
118
|
+
*/
|
|
119
|
+
publishAll(events: ReadonlyArray<DomainEvent>): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @description
|
|
124
|
+
* Internal registry entry stored per event type.
|
|
125
|
+
*/
|
|
126
|
+
export interface SubscriberEntry {
|
|
127
|
+
type: string;
|
|
128
|
+
subscriber: EventSubscriber;
|
|
129
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
Adapter,
|
|
3
|
+
IAdapter,
|
|
4
|
+
} from "./adapter.types";
|
|
5
|
+
|
|
6
|
+
export type { ICommand, IQuery, IUseCase } from "./command.types";
|
|
7
|
+
export type { IEntityProps, IEntitySettings } from "./entity.types";
|
|
8
|
+
export type { IIterator, IIteratorConfig } from "./iterator.types";
|
|
9
|
+
export type {
|
|
10
|
+
IResult,
|
|
11
|
+
IResultExecuteFn,
|
|
12
|
+
IResultHook,
|
|
13
|
+
IResultObject,
|
|
14
|
+
IResultOption,
|
|
15
|
+
} from "./result.types";
|
|
16
|
+
|
|
17
|
+
export type { UID } from "./uid.types";
|
|
18
|
+
export type {
|
|
19
|
+
AnyObject,
|
|
20
|
+
BuiltIns,
|
|
21
|
+
CalcOpt,
|
|
22
|
+
Primitive,
|
|
23
|
+
ReadonlyDeep,
|
|
24
|
+
} from "./utils.types";
|
|
25
|
+
|
|
26
|
+
export type { IValueObjectSettings } from "./value-object.types";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Defines the operations supported by an iterator for managing sequential traversal of items.
|
|
4
|
+
*
|
|
5
|
+
* @template T The type of items in the iterator.
|
|
6
|
+
*/
|
|
7
|
+
export interface IIterator<T> {
|
|
8
|
+
addToEnd(data: T): IIterator<T>;
|
|
9
|
+
add(data: T): IIterator<T>;
|
|
10
|
+
addToStart(data: T): IIterator<T>;
|
|
11
|
+
clear(): IIterator<T>;
|
|
12
|
+
clone(): IIterator<T>;
|
|
13
|
+
first(): T;
|
|
14
|
+
hasNext(): boolean;
|
|
15
|
+
hasPrev(): boolean;
|
|
16
|
+
isEmpty(): boolean;
|
|
17
|
+
last(): T;
|
|
18
|
+
next(): T;
|
|
19
|
+
prev(): T;
|
|
20
|
+
removeFirst(): IIterator<T>;
|
|
21
|
+
removeItem(item: T): void;
|
|
22
|
+
removeLast(): IIterator<T>;
|
|
23
|
+
toArray(): Array<T>;
|
|
24
|
+
toFirst(): IIterator<T>;
|
|
25
|
+
toLast(): IIterator<T>;
|
|
26
|
+
total(): number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description
|
|
31
|
+
* Configuration options for creating an iterator.
|
|
32
|
+
*
|
|
33
|
+
* @template T The type of items in the iterator.
|
|
34
|
+
*/
|
|
35
|
+
export interface IIteratorConfig<T> {
|
|
36
|
+
initialData?: Array<T>;
|
|
37
|
+
restartOnFinish?: boolean;
|
|
38
|
+
returnCurrentOnReversion?: boolean;
|
|
39
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { ICommand } from "./command.types";
|
|
2
|
+
import type { AnyObject } from "./utils.types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* Represents the result of an operation, encapsulating its state, value, error, and metadata.
|
|
7
|
+
*
|
|
8
|
+
* @template T The type of the result's value.
|
|
9
|
+
* @template D The type of the result's error (default: string).
|
|
10
|
+
* @template M The type of the result's metadata (default: empty object).
|
|
11
|
+
*/
|
|
12
|
+
export interface IResult<T, D = string, M = AnyObject> {
|
|
13
|
+
/**
|
|
14
|
+
* @description
|
|
15
|
+
* Retrieves the error of the result. Returns null if the result represents success.
|
|
16
|
+
*
|
|
17
|
+
* @returns The result's error or null.
|
|
18
|
+
*/
|
|
19
|
+
error(): D;
|
|
20
|
+
/**
|
|
21
|
+
* @description
|
|
22
|
+
* Executes a command based on the result's state (success or failure).
|
|
23
|
+
*
|
|
24
|
+
* @template X The input type for the command.
|
|
25
|
+
* @template Y The output type of the command.
|
|
26
|
+
* @param command The command to execute.
|
|
27
|
+
* @returns An object containing hooks for further execution.
|
|
28
|
+
*/
|
|
29
|
+
execute: <X, Y>(command: ICommand<X, Y>) => IResultExecuteFn<X, Y>;
|
|
30
|
+
/**
|
|
31
|
+
* @description
|
|
32
|
+
* Checks if the result represents a failure.
|
|
33
|
+
*
|
|
34
|
+
* @returns True if the result is a failure, false otherwise.
|
|
35
|
+
*/
|
|
36
|
+
isError(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* @description
|
|
39
|
+
* Checks if the result contains a null value.
|
|
40
|
+
*
|
|
41
|
+
* @returns True if the value is null, false otherwise.
|
|
42
|
+
*/
|
|
43
|
+
isNull(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* @description
|
|
46
|
+
* Checks if the result represents success.
|
|
47
|
+
*
|
|
48
|
+
* @returns True if the result is a success, false otherwise.
|
|
49
|
+
*/
|
|
50
|
+
isSuccess(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* @description
|
|
53
|
+
* Retrieves the metadata associated with the result.
|
|
54
|
+
*
|
|
55
|
+
* @returns The result's metadata.
|
|
56
|
+
*/
|
|
57
|
+
metaData(): M;
|
|
58
|
+
/**
|
|
59
|
+
* @description
|
|
60
|
+
* Converts the result into an object representing its current state.
|
|
61
|
+
*
|
|
62
|
+
* @returns An object containing the result's value, error, and metadata.
|
|
63
|
+
*/
|
|
64
|
+
toObject(): IResultObject<T, D, M>;
|
|
65
|
+
/**
|
|
66
|
+
* @description
|
|
67
|
+
* Retrieves the value of the result. Returns null if the result represents a failure.
|
|
68
|
+
*
|
|
69
|
+
* @returns The result's value or null.
|
|
70
|
+
*/
|
|
71
|
+
value(): T;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @description
|
|
76
|
+
* Represents the possible states of a result: success (`success`) or failure (`error`).
|
|
77
|
+
*/
|
|
78
|
+
export type IResultOption = "error" | "success";
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @description
|
|
82
|
+
* Hook for handling specific result states during execution.
|
|
83
|
+
*
|
|
84
|
+
* @template Y The type of the hook's output.
|
|
85
|
+
*/
|
|
86
|
+
export interface IResultHook<Y> {
|
|
87
|
+
/**
|
|
88
|
+
* @description
|
|
89
|
+
* Executes a function based on the result state.
|
|
90
|
+
*
|
|
91
|
+
* @param option The result state to handle (`success` or `error`).
|
|
92
|
+
* @returns The result of the function execution, if applicable.
|
|
93
|
+
*/
|
|
94
|
+
on(option: IResultOption): Promise<IResult<Y, string>> | undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @description
|
|
99
|
+
* Extends `IResultHook` with support for data input.
|
|
100
|
+
*
|
|
101
|
+
* @template X The input type for the hook.
|
|
102
|
+
* @template Y The output type for the hook.
|
|
103
|
+
*/
|
|
104
|
+
export interface IResultExecuteFn<X, Y> extends IResultHook<Y> {
|
|
105
|
+
withData(data: X): IResultHook<Y>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @description
|
|
110
|
+
* Represents the state of a result, including its value, error, and metadata.
|
|
111
|
+
*
|
|
112
|
+
* @template T The type of the result's value.
|
|
113
|
+
* @template D The type of the result's error.
|
|
114
|
+
* @template M The type of the result's metadata.
|
|
115
|
+
*/
|
|
116
|
+
export interface IResultObject<T, D, M> {
|
|
117
|
+
data: T | null;
|
|
118
|
+
error: D | null;
|
|
119
|
+
isError: boolean;
|
|
120
|
+
isSuccess: boolean;
|
|
121
|
+
metaData: M;
|
|
122
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Represents a unique identifier (UID) with methods for manipulation and comparison.
|
|
4
|
+
*
|
|
5
|
+
* @template T The type of the UID's value (default: string).
|
|
6
|
+
*/
|
|
7
|
+
export interface UID<T = string> {
|
|
8
|
+
clone(): UID<T>;
|
|
9
|
+
cloneAsNew(): UID<string>;
|
|
10
|
+
createdAt(): Date;
|
|
11
|
+
deepEqual(id: UID<string>): boolean;
|
|
12
|
+
equal(id: UID<string>): boolean;
|
|
13
|
+
isEqual(id: UID<string>): boolean;
|
|
14
|
+
isNew(): boolean;
|
|
15
|
+
isShort(): boolean;
|
|
16
|
+
value(): string;
|
|
17
|
+
toShort(): UID<string>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Represents an unknown object.
|
|
4
|
+
*/
|
|
5
|
+
export type AnyObject = Record<string, unknown>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* Built-in types that are excluded from recursive transformations.
|
|
10
|
+
*/
|
|
11
|
+
export type BuiltIns = Primitive | Date | RegExp;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @description
|
|
15
|
+
* Options for calculations, such as specifying precision.
|
|
16
|
+
*/
|
|
17
|
+
export type CalcOpt = { fractionDigits: number };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @description
|
|
21
|
+
* Utility type to determine if a function type has multiple call signatures.
|
|
22
|
+
*
|
|
23
|
+
* Used to differentiate simple functions from overloaded functions.
|
|
24
|
+
*
|
|
25
|
+
* @template T The function type to analyze.
|
|
26
|
+
*/
|
|
27
|
+
type HasMultipleCallSignatures<
|
|
28
|
+
T extends (...arguments_: unknown[]) => unknown,
|
|
29
|
+
> = T extends {
|
|
30
|
+
(...arguments_: infer A): unknown;
|
|
31
|
+
(...arguments_: infer B): unknown;
|
|
32
|
+
}
|
|
33
|
+
? B extends A
|
|
34
|
+
? A extends B
|
|
35
|
+
? false // Single call signature.
|
|
36
|
+
: true // Multiple call signatures.
|
|
37
|
+
: true
|
|
38
|
+
: false;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @description
|
|
42
|
+
* Primitive types that are not recursively transformed.
|
|
43
|
+
*/
|
|
44
|
+
export type Primitive =
|
|
45
|
+
| null
|
|
46
|
+
| undefined
|
|
47
|
+
| string
|
|
48
|
+
| number
|
|
49
|
+
| boolean
|
|
50
|
+
| symbol
|
|
51
|
+
| bigint;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @description
|
|
55
|
+
* A utility type to recursively make all properties of a type `T` deeply readonly.
|
|
56
|
+
*
|
|
57
|
+
* Handles built-in types, objects, arrays, tuples, sets, and maps.
|
|
58
|
+
* Special cases include skipping class constructors and functions.
|
|
59
|
+
*
|
|
60
|
+
* @template T The type to be made deeply readonly.
|
|
61
|
+
*/
|
|
62
|
+
export type ReadonlyDeep<T> = T extends BuiltIns
|
|
63
|
+
? T // Built-in types remain unchanged.
|
|
64
|
+
: T extends new (
|
|
65
|
+
...arguments_: unknown[]
|
|
66
|
+
) => unknown
|
|
67
|
+
? T // Skip class constructors to preserve mutability.
|
|
68
|
+
: T extends (...arguments_: unknown[]) => unknown
|
|
69
|
+
? AnyObject extends ReadonlyObjectDeep<T>
|
|
70
|
+
? T // Skip plain functions with no call signatures.
|
|
71
|
+
: HasMultipleCallSignatures<T> extends true
|
|
72
|
+
? T // Preserve functions with multiple call signatures.
|
|
73
|
+
: ((...arguments_: Parameters<T>) => ReturnType<T>) &
|
|
74
|
+
ReadonlyObjectDeep<T>
|
|
75
|
+
: T extends Readonly<ReadonlyMap<infer KeyType, infer ValueType>>
|
|
76
|
+
? ReadonlyMapDeep<KeyType, ValueType> // Recursively make map keys and values readonly.
|
|
77
|
+
: T extends Readonly<ReadonlySet<infer ItemType>>
|
|
78
|
+
? ReadonlySetDeep<ItemType> // Recursively make set items readonly.
|
|
79
|
+
: T extends readonly [] | readonly [...never[]]
|
|
80
|
+
? readonly [] // Handle empty or unspecific tuples as empty arrays.
|
|
81
|
+
: T extends readonly [infer U, ...infer V]
|
|
82
|
+
? readonly [ReadonlyDeep<U>, ...ReadonlyDeep<V>] // Handle tuples with specific types.
|
|
83
|
+
: T extends readonly [...infer U, infer V]
|
|
84
|
+
? readonly [...ReadonlyDeep<U>, ReadonlyDeep<V>] // Handle generic tuples.
|
|
85
|
+
: T extends ReadonlyArray<infer ItemType>
|
|
86
|
+
? ReadonlyArray<ReadonlyDeep<ItemType>> // Recursively make array items readonly.
|
|
87
|
+
: T extends object
|
|
88
|
+
? ReadonlyObjectDeep<T> // Recursively make object properties readonly.
|
|
89
|
+
: unknown; // For unknown types, no transformation is applied.
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @description
|
|
93
|
+
* Makes all key-value pairs of a `ReadonlyMap` deeply readonly.
|
|
94
|
+
*
|
|
95
|
+
* @template KeyType Type of the keys in the map.
|
|
96
|
+
* @template ValueType Type of the values in the map.
|
|
97
|
+
*/
|
|
98
|
+
type ReadonlyMapDeep<KeyType, ValueType> = {} & Readonly<
|
|
99
|
+
ReadonlyMap<ReadonlyDeep<KeyType>, ReadonlyDeep<ValueType>>
|
|
100
|
+
>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @description
|
|
104
|
+
* Makes all properties of an object type deeply readonly.
|
|
105
|
+
*
|
|
106
|
+
* @template ObjectType The type of the object to be made deeply readonly.
|
|
107
|
+
*/
|
|
108
|
+
type ReadonlyObjectDeep<ObjectType extends object> = {
|
|
109
|
+
readonly [KeyType in keyof ObjectType]: ReadonlyDeep<ObjectType[KeyType]>;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @description
|
|
114
|
+
* Makes all elements of a `ReadonlySet` deeply readonly.
|
|
115
|
+
*
|
|
116
|
+
* @template ItemType Type of the items in the set.
|
|
117
|
+
*/
|
|
118
|
+
type ReadonlySetDeep<ItemType> = {} & Readonly<
|
|
119
|
+
ReadonlySet<ReadonlyDeep<ItemType>>
|
|
120
|
+
>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Represents the static side (constructor + factory contract) of a `ValueObject` subclass.
|
|
4
|
+
*
|
|
5
|
+
* @template Props The shape of the value object's properties.
|
|
6
|
+
* @template T The concrete `ValueObject` subclass type.
|
|
7
|
+
*/
|
|
8
|
+
export type ValueObjectConstructor<Props, T> = {
|
|
9
|
+
isValidProps(props: Props): boolean;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
prototype: T;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @description
|
|
16
|
+
* Configuration for value object settings.
|
|
17
|
+
*/
|
|
18
|
+
export interface IValueObjectSettings {
|
|
19
|
+
disableGetters?: boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** Supported time units for operations like incrementing or decrementing time. */
|
|
2
|
+
export type Unit = "minute" | "hour" | "day" | "week" | "month" | "year";
|
|
3
|
+
|
|
4
|
+
/** Milliseconds in common time units. */
|
|
5
|
+
export const ONE_MINUTE = 60000;
|
|
6
|
+
export const ONE_HOUR = ONE_MINUTE * 60;
|
|
7
|
+
export const ONE_DAY = ONE_HOUR * 24;
|
|
8
|
+
export const ONE_WEEK = ONE_DAY * 7;
|
|
9
|
+
export const ONE_MONTH = ONE_DAY * 30;
|
|
10
|
+
export const ONE_YEAR = ONE_DAY * 365;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @description Decreases a given date by a specified amount of time based on the unit provided.
|
|
14
|
+
*
|
|
15
|
+
* @param date The starting date from which the time will be decremented.
|
|
16
|
+
* @param value The number of units to decrement. If not a valid number, the original timestamp is returned.
|
|
17
|
+
* @param unit The unit of time to decrement. Possible values are:
|
|
18
|
+
* - `'day'`: Decrement by days.
|
|
19
|
+
* - `'hour'`: Decrement by hours.
|
|
20
|
+
* - `'minute'`: Decrement by minutes.
|
|
21
|
+
* - `'month'`: Decrement by months.
|
|
22
|
+
* - `'week'`: Decrement by weeks.
|
|
23
|
+
* - `'year'`: Decrement by years.
|
|
24
|
+
*
|
|
25
|
+
* @returns The decremented timestamp as a number. If the input date is invalid, the current timestamp is returned.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const now = new Date();
|
|
30
|
+
* const decrementedTime = DecrementTime(now, 2, 'day'); // Subtracts 2 days from the current date.
|
|
31
|
+
* console.log(new Date(decrementedTime)); // Logs the decremented date.
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const DecrementTime = (
|
|
35
|
+
date: Date,
|
|
36
|
+
value: number,
|
|
37
|
+
unit: Unit,
|
|
38
|
+
): number => {
|
|
39
|
+
if (!(date instanceof Date)) return Date.now();
|
|
40
|
+
|
|
41
|
+
const time = date.getTime();
|
|
42
|
+
if (typeof value !== "number") return time;
|
|
43
|
+
|
|
44
|
+
switch (unit) {
|
|
45
|
+
case "day":
|
|
46
|
+
return time - ONE_DAY * value;
|
|
47
|
+
case "hour":
|
|
48
|
+
return time - ONE_HOUR * value;
|
|
49
|
+
case "minute":
|
|
50
|
+
return time - ONE_MINUTE * value;
|
|
51
|
+
case "month":
|
|
52
|
+
return time - ONE_MONTH * value;
|
|
53
|
+
case "week":
|
|
54
|
+
return time - ONE_WEEK * value;
|
|
55
|
+
case "year":
|
|
56
|
+
return time - ONE_YEAR * value;
|
|
57
|
+
default:
|
|
58
|
+
return time;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @description
|
|
64
|
+
* Increments a given date by a specified amount of time based on the unit provided.
|
|
65
|
+
*
|
|
66
|
+
* @param date The starting date to increment.
|
|
67
|
+
* @param value The number of units to increment. If not a valid number, the original timestamp is returned.
|
|
68
|
+
* @param unit The unit of time to increment. Possible values are:
|
|
69
|
+
* - `'day'`: Increment by days.
|
|
70
|
+
* - `'hour'`: Increment by hours.
|
|
71
|
+
* - `'minute'`: Increment by minutes.
|
|
72
|
+
* - `'month'`: Increment by months.
|
|
73
|
+
* - `'week'`: Increment by weeks.
|
|
74
|
+
* - `'year'`: Increment by years.
|
|
75
|
+
*
|
|
76
|
+
* @returns The incremented timestamp as a number. If the input date is invalid, the current timestamp is returned.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const now = new Date();
|
|
81
|
+
* const incrementedTime = IncrementTime(now, 3, 'day'); // Adds 3 days to the current date.
|
|
82
|
+
* console.log(new Date(incrementedTime)); // Logs the incremented date.
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const IncrementTime = (
|
|
86
|
+
date: Date,
|
|
87
|
+
value: number,
|
|
88
|
+
unit: Unit,
|
|
89
|
+
): number => {
|
|
90
|
+
if (!(date instanceof Date)) return Date.now();
|
|
91
|
+
|
|
92
|
+
const time = date.getTime();
|
|
93
|
+
if (typeof value !== "number") return time;
|
|
94
|
+
|
|
95
|
+
switch (unit) {
|
|
96
|
+
case "day":
|
|
97
|
+
return ONE_DAY * value + time;
|
|
98
|
+
case "hour":
|
|
99
|
+
return ONE_HOUR * value + time;
|
|
100
|
+
case "minute":
|
|
101
|
+
return ONE_MINUTE * value + time;
|
|
102
|
+
case "month":
|
|
103
|
+
return ONE_MONTH * value + time;
|
|
104
|
+
case "week":
|
|
105
|
+
return ONE_WEEK * value + time;
|
|
106
|
+
case "year":
|
|
107
|
+
return ONE_YEAR * value + time;
|
|
108
|
+
default:
|
|
109
|
+
return time;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export {
|
|
2
|
+
DecrementTime,
|
|
3
|
+
IncrementTime,
|
|
4
|
+
ONE_DAY,
|
|
5
|
+
ONE_HOUR,
|
|
6
|
+
ONE_MINUTE,
|
|
7
|
+
ONE_MONTH,
|
|
8
|
+
ONE_WEEK,
|
|
9
|
+
ONE_YEAR,
|
|
10
|
+
} from "./date.utils";
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
Divide,
|
|
14
|
+
EnsureNumber,
|
|
15
|
+
Float,
|
|
16
|
+
IsNaN,
|
|
17
|
+
Multiply,
|
|
18
|
+
Subtract,
|
|
19
|
+
Sum,
|
|
20
|
+
ToDecimal,
|
|
21
|
+
ToLong,
|
|
22
|
+
ToPrecision,
|
|
23
|
+
} from "./number.utils";
|
|
24
|
+
|
|
25
|
+
export { DeepFreeze, StableStringify } from "./object.utils";
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
RemoveChars,
|
|
29
|
+
RemoveSpaces,
|
|
30
|
+
ReplaceChars,
|
|
31
|
+
Stringify,
|
|
32
|
+
} from "./string.utils";
|