@woltz/rich-domain 1.0.0 → 1.2.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/CHANGELOG.md +37 -86
- package/LICENSE +20 -20
- package/dist/base-entity.d.ts +1 -1
- package/dist/base-entity.d.ts.map +1 -1
- package/dist/base-entity.js +15 -19
- package/dist/base-entity.js.map +1 -1
- package/dist/constants.js +1 -4
- package/dist/constants.js.map +1 -1
- package/dist/criteria.d.ts +24 -14
- package/dist/criteria.d.ts.map +1 -1
- package/dist/criteria.js +154 -67
- package/dist/criteria.js.map +1 -1
- package/dist/deep-proxy.d.ts.map +1 -1
- package/dist/deep-proxy.js +19 -9
- package/dist/deep-proxy.js.map +1 -1
- package/dist/domain-event-bus.d.ts +5 -6
- package/dist/domain-event-bus.d.ts.map +1 -1
- package/dist/domain-event-bus.js +4 -17
- package/dist/domain-event-bus.js.map +1 -1
- package/dist/domain-event.d.ts +1 -31
- package/dist/domain-event.d.ts.map +1 -1
- package/dist/domain-event.js +4 -7
- package/dist/domain-event.js.map +1 -1
- package/dist/entity.d.ts +2 -2
- package/dist/entity.js +3 -8
- package/dist/entity.js.map +1 -1
- package/dist/exceptions.d.ts +251 -0
- package/dist/exceptions.d.ts.map +1 -0
- package/dist/exceptions.js +321 -0
- package/dist/exceptions.js.map +1 -0
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +14 -7
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -40
- package/dist/index.js.map +1 -1
- package/dist/mapper.js +1 -5
- package/dist/mapper.js.map +1 -1
- package/dist/paginated-result.d.ts.map +1 -1
- package/dist/paginated-result.js +17 -9
- package/dist/paginated-result.js.map +1 -1
- package/dist/repository/base-repository.js +4 -11
- package/dist/repository/base-repository.js.map +1 -1
- package/dist/repository/index.d.ts +1 -2
- package/dist/repository/index.d.ts.map +1 -1
- package/dist/repository/index.js +3 -26
- package/dist/repository/index.js.map +1 -1
- package/dist/repository/unit-of-work.d.ts +0 -11
- package/dist/repository/unit-of-work.d.ts.map +1 -1
- package/dist/repository/unit-of-work.js +2 -43
- package/dist/repository/unit-of-work.js.map +1 -1
- package/dist/types/criteria.d.ts +31 -7
- package/dist/types/criteria.d.ts.map +1 -1
- package/dist/types/criteria.js +1 -4
- package/dist/types/criteria.js.map +1 -1
- package/dist/types/domain-event.d.ts +32 -0
- package/dist/types/domain-event.d.ts.map +1 -0
- package/dist/types/domain-event.js +2 -0
- package/dist/types/domain-event.js.map +1 -0
- package/dist/types/domain.d.ts +2 -2
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/types/domain.js +1 -2
- package/dist/types/history-tracker.d.ts +1 -1
- package/dist/types/history-tracker.d.ts.map +1 -1
- package/dist/types/history-tracker.js +1 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -22
- package/dist/types/index.js.map +1 -1
- package/dist/types/standard-schema.js +1 -2
- package/dist/types/unit-of-work.js +1 -2
- package/dist/types/utils.js +1 -2
- package/dist/utils/criteria-operator-validation.d.ts +5 -0
- package/dist/utils/criteria-operator-validation.d.ts.map +1 -0
- package/dist/utils/criteria-operator-validation.js +143 -0
- package/dist/utils/criteria-operator-validation.js.map +1 -0
- package/dist/utils/helpers.d.ts +2 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +10 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/validation-error.js +3 -9
- package/dist/validation-error.js.map +1 -1
- package/dist/value-object.d.ts +1 -1
- package/dist/value-object.d.ts.map +1 -1
- package/dist/value-object.js +7 -14
- package/dist/value-object.js.map +1 -1
- package/eslint.config.js +9 -3
- package/jest.config.js +1 -1
- package/package.json +14 -20
- package/src/base-entity.ts +3 -3
- package/src/criteria.ts +268 -87
- package/src/deep-proxy.ts +50 -38
- package/src/domain-event-bus.ts +152 -166
- package/src/domain-event.ts +53 -90
- package/src/entity.ts +16 -16
- package/src/exceptions.ts +435 -0
- package/src/id.ts +107 -94
- package/src/index.ts +32 -8
- package/src/paginated-result.ts +15 -3
- package/src/repository/index.ts +1 -6
- package/src/repository/unit-of-work.ts +1 -44
- package/src/types/criteria.ts +95 -17
- package/src/types/domain-event.ts +38 -0
- package/src/types/domain.ts +2 -3
- package/src/types/history-tracker.ts +1 -1
- package/src/types/index.ts +1 -0
- package/src/utils/criteria-operator-validation.ts +171 -0
- package/src/utils/helpers.ts +6 -0
- package/src/validation-error.ts +97 -97
- package/src/value-object.ts +3 -6
- package/tests/criteria.test.ts +324 -1
- package/tests/domain-events.test.ts +431 -445
- package/tests/entity-validation.test.ts +1 -1
- package/tests/entity.test.ts +33 -33
- package/tests/repository.test.ts +4 -2
- package/tests/utils.ts +254 -151
- package/tests/value-object-validation.test.ts +0 -9
- package/tsconfig.json +2 -24
- package/.github/workflows/ci.yml +0 -40
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -1
- package/.vscode/settings.json +0 -3
- package/commitlint.config.js +0 -23
- package/dist/repository/in-memory-repository.d.ts +0 -50
- package/dist/repository/in-memory-repository.d.ts.map +0 -1
- package/dist/repository/in-memory-repository.js +0 -97
- package/dist/repository/in-memory-repository.js.map +0 -1
- package/src/repository/in-memory-repository.ts +0 -116
package/src/id.ts
CHANGED
|
@@ -1,94 +1,107 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Id Class - Smart Identity Management
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
function randomUUID(): string {
|
|
6
|
+
// If we are in the browser, use the browser's crypto API
|
|
7
|
+
// @ts-expect-error - window.crypto is not defined in the browser
|
|
8
|
+
if (typeof window !== "undefined" && window.crypto) {
|
|
9
|
+
// @ts-expect-error - window.crypto is not defined in the browser
|
|
10
|
+
return window.crypto.randomUUID();
|
|
11
|
+
}
|
|
12
|
+
// If we are in the server, use the crypto library
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
14
|
+
const crypto = require("crypto");
|
|
15
|
+
|
|
16
|
+
return crypto.randomUUID();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class Id {
|
|
20
|
+
private readonly _value: string;
|
|
21
|
+
private readonly _isNew: boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a new Id
|
|
25
|
+
* @param value - Optional existing ID value. If not provided, generates a new UUID.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // New entity (generates UUID)
|
|
29
|
+
* const newId = new Id();
|
|
30
|
+
* newuser.isNew() // true
|
|
31
|
+
*
|
|
32
|
+
* // Existing entity (uses provided ID)
|
|
33
|
+
* const existingId = new Id("550e8400-e29b-41d4-a716-446655440000");
|
|
34
|
+
* existinguser.isNew() // false
|
|
35
|
+
*/
|
|
36
|
+
constructor(value?: string) {
|
|
37
|
+
if (value !== undefined) {
|
|
38
|
+
// ID was provided - this is an existing entity
|
|
39
|
+
this._value = value;
|
|
40
|
+
this._isNew = false;
|
|
41
|
+
} else {
|
|
42
|
+
// No ID provided - generate new one, this is a new entity
|
|
43
|
+
this._value = this.generateUUID();
|
|
44
|
+
this._isNew = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the string value of the ID
|
|
50
|
+
*/
|
|
51
|
+
get value(): string {
|
|
52
|
+
return this._value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if this ID represents a new entity
|
|
57
|
+
*/
|
|
58
|
+
public isNew(): boolean {
|
|
59
|
+
return this._isNew;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Convert to string (for JSON serialization and comparisons)
|
|
64
|
+
*/
|
|
65
|
+
toString(): string {
|
|
66
|
+
return this._value;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Convert to JSON (returns the string value)
|
|
71
|
+
*/
|
|
72
|
+
toJSON(): string {
|
|
73
|
+
return this._value;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check equality with another Id or string
|
|
78
|
+
*/
|
|
79
|
+
equals(other: Id | string): boolean {
|
|
80
|
+
if (other instanceof Id) {
|
|
81
|
+
return this._value === other._value;
|
|
82
|
+
}
|
|
83
|
+
return this._value === other;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Generate a UUID v4
|
|
88
|
+
*/
|
|
89
|
+
private generateUUID(): string {
|
|
90
|
+
// Simple UUID v4 implementation
|
|
91
|
+
return randomUUID();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Create a new Id (convenience static method)
|
|
96
|
+
*/
|
|
97
|
+
static create(): Id {
|
|
98
|
+
return new Id();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Create an Id from an existing value
|
|
103
|
+
*/
|
|
104
|
+
static from(value: string): Id {
|
|
105
|
+
return new Id(value);
|
|
106
|
+
}
|
|
107
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
// Core Classes
|
|
6
6
|
export { Id } from "./id";
|
|
7
|
-
export { BaseEntity } from "./base-entity";
|
|
8
7
|
export { Entity, Aggregate } from "./entity";
|
|
9
8
|
export { ValueObject } from "./value-object";
|
|
10
9
|
export { Mapper } from "./mapper";
|
|
@@ -13,8 +12,8 @@ export * from "./validation-error";
|
|
|
13
12
|
|
|
14
13
|
// Domain Events
|
|
15
14
|
export * from "./domain-event";
|
|
16
|
-
|
|
17
15
|
export * from "./domain-event-bus";
|
|
16
|
+
export * from "./exceptions";
|
|
18
17
|
|
|
19
18
|
// Criteria
|
|
20
19
|
export * from "./criteria";
|
|
@@ -24,9 +23,34 @@ export * from "./paginated-result";
|
|
|
24
23
|
export * from "./repository";
|
|
25
24
|
|
|
26
25
|
// Types
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
export {
|
|
27
|
+
DomainEventHandler,
|
|
28
|
+
EntityHooks,
|
|
29
|
+
Filter,
|
|
30
|
+
EntityValidation,
|
|
31
|
+
IDomainEvent,
|
|
32
|
+
VOValidation,
|
|
33
|
+
VOHooks,
|
|
34
|
+
ValidationConfig,
|
|
35
|
+
Primitive,
|
|
36
|
+
TransactionContext,
|
|
37
|
+
PaginationMeta,
|
|
38
|
+
Pagination,
|
|
39
|
+
OrderDirection,
|
|
40
|
+
Order,
|
|
41
|
+
IUnitOfWork,
|
|
42
|
+
IDomainEventHandler,
|
|
43
|
+
EntityId,
|
|
44
|
+
FieldPath,
|
|
45
|
+
FilterOperator,
|
|
46
|
+
Search,
|
|
47
|
+
FilterValueFor,
|
|
48
|
+
PathValue,
|
|
49
|
+
OperatorsForType,
|
|
50
|
+
DateOperators,
|
|
51
|
+
NumberOperators,
|
|
52
|
+
StringOperators,
|
|
53
|
+
BooleanOperators,
|
|
54
|
+
ArrayOperators,
|
|
55
|
+
CriteriaOptions,
|
|
56
|
+
} from "./types";
|
package/src/paginated-result.ts
CHANGED
|
@@ -64,14 +64,26 @@ export class PaginatedResult<T> {
|
|
|
64
64
|
*/
|
|
65
65
|
static fromArray<T>(items: T[], criteria: Criteria<T>): PaginatedResult<T> {
|
|
66
66
|
let result = [...items];
|
|
67
|
+
let total = result.length;
|
|
68
|
+
|
|
69
|
+
const search = criteria.getSearch();
|
|
70
|
+
if (search) {
|
|
71
|
+
result = result.filter((item) => {
|
|
72
|
+
return search.fields.some((field) => {
|
|
73
|
+
return String(getNestedValue(item, field))
|
|
74
|
+
.toLowerCase()
|
|
75
|
+
.includes(search.value.trim().toLowerCase());
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
total = result.length;
|
|
79
|
+
}
|
|
67
80
|
|
|
68
81
|
// Apply filters
|
|
69
82
|
for (const filter of criteria.getFilters()) {
|
|
70
83
|
result = result.filter((item) => applyFilter(item, filter));
|
|
84
|
+
total = result.length;
|
|
71
85
|
}
|
|
72
86
|
|
|
73
|
-
const total = result.length;
|
|
74
|
-
|
|
75
87
|
// Apply ordering
|
|
76
88
|
for (const order of criteria.getOrders().reverse()) {
|
|
77
89
|
result.sort((a, b) => {
|
|
@@ -88,7 +100,7 @@ export class PaginatedResult<T> {
|
|
|
88
100
|
|
|
89
101
|
// Apply pagination
|
|
90
102
|
const pagination = criteria.getPagination();
|
|
91
|
-
if (pagination) {
|
|
103
|
+
if (pagination && !criteria.hasSearch()) {
|
|
92
104
|
result = result.slice(
|
|
93
105
|
pagination.offset,
|
|
94
106
|
pagination.offset + pagination.limit
|
package/src/repository/index.ts
CHANGED
|
@@ -7,11 +7,6 @@ export { Mapper } from "../mapper";
|
|
|
7
7
|
|
|
8
8
|
// Base implementations
|
|
9
9
|
export * from "./base-repository";
|
|
10
|
-
export { InMemoryRepository } from "./in-memory-repository";
|
|
11
10
|
|
|
12
11
|
// Unit of Work
|
|
13
|
-
export {
|
|
14
|
-
UnitOfWork,
|
|
15
|
-
BaseTransactionContext,
|
|
16
|
-
InMemoryUnitOfWork,
|
|
17
|
-
} from "./unit-of-work";
|
|
12
|
+
export { UnitOfWork, BaseTransactionContext } from "./unit-of-work";
|
|
@@ -66,9 +66,7 @@ export abstract class UnitOfWork implements IUnitOfWork {
|
|
|
66
66
|
/**
|
|
67
67
|
* Get repository instance (cached per transaction)
|
|
68
68
|
*/
|
|
69
|
-
getRepository<TRepo>(
|
|
70
|
-
RepositoryClass: new (...args: any[]) => TRepo
|
|
71
|
-
): TRepo {
|
|
69
|
+
getRepository<TRepo>(RepositoryClass: new (...args: any[]) => TRepo): TRepo {
|
|
72
70
|
const key = RepositoryClass.name;
|
|
73
71
|
|
|
74
72
|
if (this.repositoryCache.has(key)) {
|
|
@@ -105,44 +103,3 @@ export abstract class BaseTransactionContext implements TransactionContext {
|
|
|
105
103
|
this._isActive = false;
|
|
106
104
|
}
|
|
107
105
|
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* In-Memory Unit of Work (for testing)
|
|
111
|
-
*/
|
|
112
|
-
export class InMemoryUnitOfWork extends UnitOfWork {
|
|
113
|
-
private committed = false;
|
|
114
|
-
private rolledBack = false;
|
|
115
|
-
|
|
116
|
-
async begin(): Promise<TransactionContext> {
|
|
117
|
-
this.currentContext = new InMemoryTransactionContext();
|
|
118
|
-
this.committed = false;
|
|
119
|
-
this.rolledBack = false;
|
|
120
|
-
return this.currentContext;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
protected createRepository<TRepo>(
|
|
124
|
-
RepositoryClass: new (...args: any[]) => TRepo
|
|
125
|
-
): TRepo {
|
|
126
|
-
// For in-memory, just create a new instance
|
|
127
|
-
// In real implementation, pass transaction client
|
|
128
|
-
return new RepositoryClass();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
isCommitted(): boolean {
|
|
132
|
-
return this.committed;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
isRolledBack(): boolean {
|
|
136
|
-
return this.rolledBack;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
class InMemoryTransactionContext extends BaseTransactionContext {
|
|
141
|
-
async commit(): Promise<void> {
|
|
142
|
-
this.markInactive();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async rollback(): Promise<void> {
|
|
146
|
-
this.markInactive();
|
|
147
|
-
}
|
|
148
|
-
}
|
package/src/types/criteria.ts
CHANGED
|
@@ -17,12 +17,65 @@ export const FILTER_OPERATORS = [
|
|
|
17
17
|
"isNotNull",
|
|
18
18
|
] as const;
|
|
19
19
|
|
|
20
|
+
export type FilterOperator = (typeof FILTER_OPERATORS)[number];
|
|
21
|
+
|
|
22
|
+
export type StringOperators =
|
|
23
|
+
| "equals"
|
|
24
|
+
| "notEquals"
|
|
25
|
+
| "contains"
|
|
26
|
+
| "startsWith"
|
|
27
|
+
| "endsWith"
|
|
28
|
+
| "in"
|
|
29
|
+
| "notIn"
|
|
30
|
+
| "isNull"
|
|
31
|
+
| "isNotNull";
|
|
32
|
+
|
|
33
|
+
export type NumberOperators =
|
|
34
|
+
| "equals"
|
|
35
|
+
| "notEquals"
|
|
36
|
+
| "greaterThan"
|
|
37
|
+
| "greaterThanOrEqual"
|
|
38
|
+
| "lessThan"
|
|
39
|
+
| "lessThanOrEqual"
|
|
40
|
+
| "in"
|
|
41
|
+
| "notIn"
|
|
42
|
+
| "between"
|
|
43
|
+
| "isNull"
|
|
44
|
+
| "isNotNull";
|
|
45
|
+
|
|
46
|
+
export type DateOperators =
|
|
47
|
+
| "equals"
|
|
48
|
+
| "notEquals"
|
|
49
|
+
| "greaterThan"
|
|
50
|
+
| "greaterThanOrEqual"
|
|
51
|
+
| "lessThan"
|
|
52
|
+
| "lessThanOrEqual"
|
|
53
|
+
| "in"
|
|
54
|
+
| "notIn"
|
|
55
|
+
| "between"
|
|
56
|
+
| "isNull"
|
|
57
|
+
| "isNotNull";
|
|
58
|
+
|
|
59
|
+
export type BooleanOperators = "equals" | "notEquals" | "isNull" | "isNotNull";
|
|
60
|
+
|
|
61
|
+
export type ArrayOperators = "in" | "notIn" | "isNull" | "isNotNull";
|
|
62
|
+
|
|
63
|
+
export type OperatorsForType<T> = T extends string
|
|
64
|
+
? StringOperators
|
|
65
|
+
: T extends number
|
|
66
|
+
? NumberOperators
|
|
67
|
+
: T extends Date
|
|
68
|
+
? DateOperators
|
|
69
|
+
: T extends boolean
|
|
70
|
+
? BooleanOperators
|
|
71
|
+
: T extends Array<any>
|
|
72
|
+
? ArrayOperators
|
|
73
|
+
: FilterOperator;
|
|
74
|
+
|
|
20
75
|
export type FilterValueFor<T> =
|
|
21
|
-
| T
|
|
22
|
-
| (T extends number | Date
|
|
23
|
-
|
|
24
|
-
: never)
|
|
25
|
-
| T[] // in, notIn
|
|
76
|
+
| T
|
|
77
|
+
| (T extends number | Date ? [T, T] : never)
|
|
78
|
+
| T[]
|
|
26
79
|
| null;
|
|
27
80
|
|
|
28
81
|
export type PathValue<
|
|
@@ -30,24 +83,34 @@ export type PathValue<
|
|
|
30
83
|
P extends string
|
|
31
84
|
> = P extends `${infer K}.${infer Rest}`
|
|
32
85
|
? K extends keyof T
|
|
33
|
-
?
|
|
86
|
+
? T[K] extends Array<infer U>
|
|
87
|
+
? PathValue<U, Rest>
|
|
88
|
+
: PathValue<T[K], Rest>
|
|
34
89
|
: never
|
|
35
90
|
: P extends keyof T
|
|
36
91
|
? T[P]
|
|
37
92
|
: never;
|
|
38
93
|
|
|
39
|
-
export type FilterOperator = (typeof FILTER_OPERATORS)[number];
|
|
40
|
-
|
|
41
94
|
export interface Filter<TField = string, TValue = unknown> {
|
|
42
95
|
field: TField;
|
|
43
|
-
operator: FilterOperator
|
|
96
|
+
operator: unknown extends TValue ? FilterOperator : OperatorsForType<TValue>;
|
|
44
97
|
value: TValue;
|
|
98
|
+
options?: CriteriaOptions;
|
|
45
99
|
}
|
|
46
100
|
|
|
47
101
|
export type TypedFilter<T> = {
|
|
48
|
-
[K in FieldPath<T>]:
|
|
102
|
+
[K in FieldPath<T>]: {
|
|
103
|
+
field: K;
|
|
104
|
+
operator: OperatorsForType<NonNullable<PathValue<T, K>>>;
|
|
105
|
+
value: FilterValueFor<NonNullable<PathValue<T, K>>>;
|
|
106
|
+
options?: CriteriaOptions;
|
|
107
|
+
};
|
|
49
108
|
}[FieldPath<T>];
|
|
50
109
|
|
|
110
|
+
export type CriteriaAdapter<Input, Output> = {
|
|
111
|
+
[K in FieldPath<Input>]?: FieldPath<Output>;
|
|
112
|
+
};
|
|
113
|
+
|
|
51
114
|
export type OrderDirection = "asc" | "desc";
|
|
52
115
|
|
|
53
116
|
export interface Order {
|
|
@@ -61,6 +124,11 @@ export interface Pagination {
|
|
|
61
124
|
offset: number;
|
|
62
125
|
}
|
|
63
126
|
|
|
127
|
+
export interface Search<T> {
|
|
128
|
+
fields: FieldPath<T>[];
|
|
129
|
+
value: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
64
132
|
export interface PaginationMeta {
|
|
65
133
|
page: number;
|
|
66
134
|
limit: number;
|
|
@@ -70,10 +138,20 @@ export interface PaginationMeta {
|
|
|
70
138
|
hasPrevious: boolean;
|
|
71
139
|
}
|
|
72
140
|
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
141
|
+
export interface CriteriaOptions {
|
|
142
|
+
quantifier?: "some" | "every" | "none";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
type ExcludeBuiltInKeys<T> = Exclude<keyof T, keyof any[] | number | symbol>;
|
|
146
|
+
|
|
147
|
+
export type FieldPath<T> = T extends Primitive
|
|
148
|
+
? never
|
|
149
|
+
: {
|
|
150
|
+
[K in ExcludeBuiltInKeys<T> & string]: NonNullable<T[K]> extends Primitive
|
|
151
|
+
? K
|
|
152
|
+
: NonNullable<T[K]> extends Array<infer U>
|
|
153
|
+
? U extends Primitive
|
|
154
|
+
? K
|
|
155
|
+
: K | `${K}.${FieldPath<U>}`
|
|
156
|
+
: K | `${K}.${FieldPath<NonNullable<T[K]>>}`;
|
|
157
|
+
}[ExcludeBuiltInKeys<T> & string];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for all domain events
|
|
3
|
+
*/
|
|
4
|
+
export interface IDomainEvent {
|
|
5
|
+
/**
|
|
6
|
+
* Unique identifier for this event occurrence
|
|
7
|
+
*/
|
|
8
|
+
readonly eventId: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* When the event occurred
|
|
12
|
+
*/
|
|
13
|
+
readonly occurredOn: Date;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Name/type of the event (e.g., "UserCreated", "OrderPlaced")
|
|
17
|
+
*/
|
|
18
|
+
readonly eventName: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* ID of the aggregate that raised this event
|
|
22
|
+
*/
|
|
23
|
+
readonly aggregateId: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Event handler function type
|
|
28
|
+
*/
|
|
29
|
+
export type DomainEventHandler<T extends IDomainEvent = IDomainEvent> = (
|
|
30
|
+
event: T
|
|
31
|
+
) => void | Promise<void>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Event handler class type
|
|
35
|
+
*/
|
|
36
|
+
export interface IDomainEventHandler<T extends IDomainEvent = IDomainEvent> {
|
|
37
|
+
handle(event: T): void | Promise<void>;
|
|
38
|
+
}
|
package/src/types/domain.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValidationConfig } from "..";
|
|
2
2
|
import { Id } from "../id";
|
|
3
|
+
import { StandardSchema } from "./standard-schema";
|
|
3
4
|
|
|
4
5
|
export type EntityId = string | number;
|
|
5
6
|
|
|
@@ -15,12 +16,10 @@ interface DomainValidation<T> {
|
|
|
15
16
|
export type EntityValidation<T> = DomainValidation<T>;
|
|
16
17
|
export type VOValidation<T> = DomainValidation<T>;
|
|
17
18
|
|
|
18
|
-
|
|
19
19
|
export interface VOHooks<T, E> {
|
|
20
20
|
onBeforeUpdate?: (entity: E, snapshot: T) => boolean;
|
|
21
21
|
onCreate?: (entity: E) => void;
|
|
22
22
|
rules?: (entity: E) => void;
|
|
23
|
-
defaultValues?: Partial<T>;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
// Specialized hooks for entities (with BaseProps)
|
package/src/types/index.ts
CHANGED