@woltz/rich-domain 1.3.0 → 1.3.2

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 (76) hide show
  1. package/dist/aggregate-changes.js +1 -1
  2. package/dist/aggregate-changes.js.map +1 -1
  3. package/dist/base-entity.d.ts.map +1 -1
  4. package/dist/base-entity.js +17 -5
  5. package/dist/base-entity.js.map +1 -1
  6. package/dist/change-tracker.d.ts +1 -1
  7. package/dist/change-tracker.d.ts.map +1 -1
  8. package/dist/change-tracker.js +20 -8
  9. package/dist/change-tracker.js.map +1 -1
  10. package/dist/criteria.js +6 -5
  11. package/dist/criteria.js.map +1 -1
  12. package/dist/domain-event-bus.js +4 -4
  13. package/dist/domain-event-bus.js.map +1 -1
  14. package/dist/domain-event.js +3 -0
  15. package/dist/domain-event.js.map +1 -1
  16. package/dist/entity-changes.js +1 -0
  17. package/dist/entity-changes.js.map +1 -1
  18. package/dist/entity-schema-registry.d.ts +4 -0
  19. package/dist/entity-schema-registry.d.ts.map +1 -1
  20. package/dist/entity-schema-registry.js +8 -6
  21. package/dist/entity-schema-registry.js.map +1 -1
  22. package/dist/exceptions.js +26 -1
  23. package/dist/exceptions.js.map +1 -1
  24. package/dist/id.js +2 -0
  25. package/dist/id.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/paginated-result.d.ts.map +1 -1
  30. package/dist/paginated-result.js +9 -0
  31. package/dist/paginated-result.js.map +1 -1
  32. package/dist/repository/unit-of-work.js +3 -7
  33. package/dist/repository/unit-of-work.js.map +1 -1
  34. package/dist/types/domain.d.ts +0 -1
  35. package/dist/types/domain.d.ts.map +1 -1
  36. package/dist/validation-error.d.ts +15 -1
  37. package/dist/validation-error.d.ts.map +1 -1
  38. package/dist/validation-error.js +46 -3
  39. package/dist/validation-error.js.map +1 -1
  40. package/dist/value-object.d.ts.map +1 -1
  41. package/dist/value-object.js +29 -1
  42. package/dist/value-object.js.map +1 -1
  43. package/package.json +9 -11
  44. package/eslint.config.js +0 -57
  45. package/jest.config.js +0 -21
  46. package/src/aggregate-changes.ts +0 -444
  47. package/src/base-entity.ts +0 -404
  48. package/src/change-tracker.ts +0 -1133
  49. package/src/constants.ts +0 -81
  50. package/src/criteria.ts +0 -521
  51. package/src/crypto.ts +0 -31
  52. package/src/domain-event-bus.ts +0 -152
  53. package/src/domain-event.ts +0 -49
  54. package/src/entity-changes.ts +0 -146
  55. package/src/entity-schema-registry.ts +0 -502
  56. package/src/entity.ts +0 -5
  57. package/src/exceptions.ts +0 -435
  58. package/src/id.ts +0 -98
  59. package/src/index.ts +0 -52
  60. package/src/mapper.ts +0 -6
  61. package/src/paginated-result.ts +0 -238
  62. package/src/repository/base-repository.ts +0 -33
  63. package/src/repository/index.ts +0 -3
  64. package/src/repository/unit-of-work.ts +0 -76
  65. package/src/types/change-tracker.ts +0 -264
  66. package/src/types/criteria.ts +0 -159
  67. package/src/types/domain-event.ts +0 -38
  68. package/src/types/domain.ts +0 -34
  69. package/src/types/index.ts +0 -7
  70. package/src/types/standard-schema.ts +0 -19
  71. package/src/types/unit-of-work.ts +0 -46
  72. package/src/types/utils.ts +0 -20
  73. package/src/utils/criteria-operator-validation.ts +0 -209
  74. package/src/utils/helpers.ts +0 -34
  75. package/src/validation-error.ts +0 -91
  76. package/src/value-object.ts +0 -244
@@ -1,159 +0,0 @@
1
- import { Primitive } from "./utils";
2
-
3
- export const FILTER_OPERATORS = [
4
- "equals",
5
- "notEquals",
6
- "greaterThan",
7
- "greaterThanOrEqual",
8
- "lessThan",
9
- "lessThanOrEqual",
10
- "contains",
11
- "startsWith",
12
- "endsWith",
13
- "in",
14
- "notIn",
15
- "between",
16
- "isNull",
17
- "isNotNull",
18
- ] as const;
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
-
75
- export type FilterValueFor<T> =
76
- | T
77
- | (T extends number | Date ? [T, T] : never)
78
- | T[]
79
- | null;
80
-
81
- export type PathValue<
82
- T,
83
- P extends string
84
- > = P extends `${infer K}.${infer Rest}`
85
- ? K extends keyof T
86
- ? T[K] extends Array<infer U>
87
- ? PathValue<U, Rest>
88
- : PathValue<T[K], Rest>
89
- : never
90
- : P extends keyof T
91
- ? T[P]
92
- : never;
93
-
94
- export interface Filter<TField = string, TValue = unknown> {
95
- field: TField;
96
- operator: unknown extends TValue ? FilterOperator : OperatorsForType<TValue>;
97
- value: TValue;
98
- options?: CriteriaOptions;
99
- }
100
-
101
- export type TypedFilter<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
- };
108
- }[FieldPath<T>];
109
-
110
- export type CriteriaAdapter<Input, Output> = {
111
- [K in FieldPath<Input>]?: FieldPath<Output>;
112
- };
113
-
114
- export type OrderDirection = "asc" | "desc";
115
-
116
- export interface Order {
117
- field: string;
118
- direction: OrderDirection;
119
- }
120
-
121
- export type TypedOrder<T> = {
122
- field: FieldPath<T>;
123
- direction: OrderDirection;
124
- };
125
-
126
- export interface Pagination {
127
- page: number;
128
- limit: number;
129
- offset: number;
130
- }
131
-
132
- export type Search = string;
133
-
134
- export interface PaginationMeta {
135
- page: number;
136
- limit: number;
137
- total: number;
138
- totalPages: number;
139
- hasNext: boolean;
140
- hasPrevious: boolean;
141
- }
142
-
143
- export interface CriteriaOptions {
144
- quantifier?: "some" | "every" | "none";
145
- }
146
-
147
- type ExcludeBuiltInKeys<T> = Exclude<keyof T, keyof any[] | number | symbol>;
148
-
149
- export type FieldPath<T> = T extends Primitive
150
- ? never
151
- : {
152
- [K in ExcludeBuiltInKeys<T> & string]: NonNullable<T[K]> extends Primitive
153
- ? K
154
- : NonNullable<T[K]> extends Array<infer U>
155
- ? U extends Primitive
156
- ? K
157
- : K | `${K}.${FieldPath<U>}`
158
- : `${K}.${FieldPath<NonNullable<T[K]>>}`;
159
- }[ExcludeBuiltInKeys<T> & string];
@@ -1,38 +0,0 @@
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
- }
@@ -1,34 +0,0 @@
1
- import { Id } from "../id";
2
- import { StandardSchema } from "./standard-schema";
3
-
4
- export interface BaseProps {
5
- id: Id;
6
- }
7
-
8
- interface DomainValidation<T> {
9
- schema: StandardSchema<T>;
10
- config?: ValidationConfig;
11
- }
12
-
13
- export type EntityValidation<T> = DomainValidation<T>;
14
- export type VOValidation<T> = DomainValidation<T>;
15
-
16
- export interface VOHooks<T, E> {
17
- onBeforeCreate?: (props: T) => void;
18
- onBeforeUpdate?: (entity: E, snapshot: T) => boolean;
19
- onCreate?: (entity: E) => void;
20
- rules?: (entity: E) => void;
21
- }
22
-
23
- export interface EntityHooks<T extends BaseProps, E> {
24
- onBeforeCreate?: (props: T) => void;
25
- onBeforeUpdate?: (entity: E, snapshot: T) => boolean;
26
- onCreate?: (entity: E) => void;
27
- rules?: (entity: E) => void;
28
- }
29
-
30
- export interface ValidationConfig {
31
- onCreate?: boolean;
32
- onUpdate?: boolean;
33
- throwOnError?: boolean;
34
- }
@@ -1,7 +0,0 @@
1
- export * from "./criteria";
2
- export * from "./domain";
3
- export * from "./standard-schema";
4
- export * from "./utils";
5
- export * from "./unit-of-work";
6
- export * from "./domain-event";
7
- export * from "./change-tracker";
@@ -1,19 +0,0 @@
1
- export interface StandardSchemaIssue {
2
- message: string;
3
- path?: ReadonlyArray<unknown>;
4
- }
5
-
6
- export interface StandardSchemaResult<T> {
7
- value?: T;
8
- issues?: ReadonlyArray<StandardSchemaIssue>;
9
- }
10
-
11
- export interface StandardSchemaProps<T> {
12
- validate: (
13
- value: unknown
14
- ) => StandardSchemaResult<T> | Promise<StandardSchemaResult<T>>;
15
- }
16
-
17
- export interface StandardSchema<T = unknown> {
18
- "~standard": StandardSchemaProps<T>;
19
- }
@@ -1,46 +0,0 @@
1
- import { Aggregate } from "../entity";
2
- import { Repository } from "../repository/base-repository";
3
-
4
- /**
5
- * Transaction context for Unit of Work
6
- */
7
- export interface TransactionContext {
8
- /**
9
- * Commit all changes
10
- */
11
- commit(): Promise<void>;
12
-
13
- /**
14
- * Rollback all changes
15
- */
16
- rollback(): Promise<void>;
17
-
18
- /**
19
- * Check if transaction is active
20
- */
21
- isActive(): boolean;
22
- }
23
-
24
- /**
25
- * Unit of Work interface
26
- * Manages transactions across multiple repositories
27
- */
28
- export interface IUnitOfWork {
29
- /**
30
- * Start a new transaction
31
- */
32
- begin(): Promise<TransactionContext>;
33
-
34
- /**
35
- * Execute work within a transaction
36
- * Auto-commits on success, rolls back on error
37
- */
38
- transaction<T>(work: (ctx: TransactionContext) => Promise<T>): Promise<T>;
39
-
40
- /**
41
- * Get repository within transaction context
42
- */
43
- getRepository<TDomain extends Aggregate<any>>(
44
- repository: new (...args: any[]) => Repository<TDomain>
45
- ): Repository<TDomain>;
46
- }
@@ -1,20 +0,0 @@
1
- import { Id } from "../id";
2
-
3
- export type DeepJsonResult<T> = {
4
- [K in keyof T]: T[K] extends Id
5
- ? string
6
- : T[K] extends { toJSON(): infer U }
7
- ? U
8
- : T[K] extends Array<infer U>
9
- ? U extends { toJSON(): infer V }
10
- ? V[]
11
- : U extends Id
12
- ? string[]
13
- : U[]
14
- : T[K];
15
- };
16
-
17
- export type Primitive = string | number | boolean | Date | null | undefined;
18
- export type UnwrapArray<T> = T extends Array<infer U> ? U : never;
19
- export type IsArray<T> = T extends Array<any> ? true : false;
20
- export type NonUndefined<T> = T extends undefined ? never : T;
@@ -1,209 +0,0 @@
1
- import {
2
- ArrayOperators,
3
- BooleanOperators,
4
- DateOperators,
5
- FILTER_OPERATORS,
6
- FilterOperator,
7
- NumberOperators,
8
- StringOperators,
9
- } from "../types";
10
-
11
- const FORCE_STRING_OPERATORS = new Set(["contains", "startsWith", "endsWith"]);
12
-
13
- export function sanitizeFieldValue(
14
- value: unknown,
15
- operator: FilterOperator
16
- ): unknown {
17
- if (value === null || value === undefined) {
18
- return value;
19
- }
20
-
21
- if (Array.isArray(value)) {
22
- return value.map((item) => sanitizeFieldValue(item, operator));
23
- }
24
-
25
- if (value instanceof Date) {
26
- return value;
27
- }
28
-
29
- const stringValue = String(value).trim();
30
-
31
- if (stringValue === "") {
32
- return "";
33
- }
34
-
35
- if (operator && FORCE_STRING_OPERATORS.has(operator)) {
36
- return stringValue;
37
- }
38
-
39
- if (stringValue === "true" || stringValue === "false") {
40
- return stringValue === "true";
41
- }
42
-
43
- const numberValue = Number(stringValue);
44
- if (!Number.isNaN(numberValue)) {
45
- return numberValue;
46
- }
47
-
48
- const dateObj = new Date(stringValue);
49
- if (!Number.isNaN(dateObj.getTime())) {
50
- return dateObj;
51
- }
52
-
53
- return stringValue;
54
- }
55
-
56
- export function isValidOperatorForType(
57
- value: unknown,
58
- operator: FilterOperator
59
- ): boolean {
60
- const sanitizedValue = sanitizeFieldValue(value, operator);
61
-
62
- if (
63
- operator === "between" &&
64
- Array.isArray(sanitizedValue) &&
65
- sanitizedValue.length === 2
66
- ) {
67
- const elementType = typeof sanitizedValue[0];
68
- if (elementType === "number" || sanitizedValue[0] instanceof Date) {
69
- return true;
70
- }
71
- return false;
72
- }
73
-
74
- const valueType = typeof sanitizedValue;
75
-
76
- if (valueType === "string") {
77
- const validOps: StringOperators[] = [
78
- "equals",
79
- "notEquals",
80
- "contains",
81
- "startsWith",
82
- "endsWith",
83
- "in",
84
- "notIn",
85
- "isNull",
86
- "isNotNull",
87
- ];
88
- return validOps.includes(operator as StringOperators);
89
- }
90
-
91
- if (valueType === "number") {
92
- const validOps: NumberOperators[] = [
93
- "equals",
94
- "notEquals",
95
- "greaterThan",
96
- "greaterThanOrEqual",
97
- "lessThan",
98
- "lessThanOrEqual",
99
- "in",
100
- "notIn",
101
- "between",
102
- "isNull",
103
- "isNotNull",
104
- ];
105
- return validOps.includes(operator as NumberOperators);
106
- }
107
-
108
- if (valueType === "boolean") {
109
- const validOps: BooleanOperators[] = [
110
- "equals",
111
- "notEquals",
112
- "isNull",
113
- "isNotNull",
114
- ];
115
- return validOps.includes(operator as BooleanOperators);
116
- }
117
-
118
- if (sanitizedValue instanceof Date) {
119
- const validOps: DateOperators[] = [
120
- "equals",
121
- "notEquals",
122
- "greaterThan",
123
- "greaterThanOrEqual",
124
- "lessThan",
125
- "lessThanOrEqual",
126
- "in",
127
- "notIn",
128
- "between",
129
- "isNull",
130
- "isNotNull",
131
- ];
132
- return validOps.includes(operator as DateOperators);
133
- }
134
-
135
- if (Array.isArray(sanitizedValue)) {
136
- const validOps: ArrayOperators[] = ["in", "notIn", "isNull", "isNotNull"];
137
- return validOps.includes(operator as ArrayOperators);
138
- }
139
-
140
- return true;
141
- }
142
-
143
- export function getValidOperatorsForType(value: unknown): FilterOperator[] {
144
- if (value === null || value === undefined) {
145
- return ["isNull", "isNotNull", "equals", "notEquals"];
146
- }
147
-
148
- const valueType = typeof value;
149
-
150
- if (valueType === "string" && Number.isNaN(Number(value))) {
151
- return [
152
- "equals",
153
- "notEquals",
154
- "contains",
155
- "startsWith",
156
- "endsWith",
157
- "in",
158
- "notIn",
159
- "isNull",
160
- "isNotNull",
161
- ];
162
- }
163
-
164
- if (valueType === "number") {
165
- return [
166
- "equals",
167
- "notEquals",
168
- "greaterThan",
169
- "greaterThanOrEqual",
170
- "lessThan",
171
- "lessThanOrEqual",
172
- "in",
173
- "notIn",
174
- "between",
175
- "isNull",
176
- "isNotNull",
177
- ];
178
- }
179
-
180
- if (valueType === "boolean") {
181
- return ["equals", "notEquals", "isNull", "isNotNull"];
182
- }
183
-
184
- if (value instanceof Date) {
185
- return [
186
- "equals",
187
- "notEquals",
188
- "greaterThan",
189
- "greaterThanOrEqual",
190
- "lessThan",
191
- "lessThanOrEqual",
192
- "in",
193
- "notIn",
194
- "between",
195
- "isNull",
196
- "isNotNull",
197
- ];
198
- }
199
-
200
- if (Array.isArray(value)) {
201
- return ["in", "notIn", "isNull", "isNotNull"];
202
- }
203
-
204
- return [...FILTER_OPERATORS];
205
- }
206
-
207
- export function isOperator(value: string): value is FilterOperator {
208
- return FILTER_OPERATORS.includes(value as FilterOperator);
209
- }
@@ -1,34 +0,0 @@
1
- export function parseQueryValue(value: string): any {
2
- if (!isNaN(Number(value))) return Number(value); // number
3
- if (value === "true" || value === "false") return value === "true"; // boolean
4
- if (!isNaN(Date.parse(value))) return new Date(value); // Date
5
- return value; // string
6
- }
7
-
8
- export function levenshteinDistance(a: string, b: string): number {
9
- const matrix: number[][] = [];
10
-
11
- for (let i = 0; i <= b.length; i++) {
12
- matrix[i] = [i];
13
- }
14
-
15
- for (let j = 0; j <= a.length; j++) {
16
- matrix[0][j] = j;
17
- }
18
-
19
- for (let i = 1; i <= b.length; i++) {
20
- for (let j = 1; j <= a.length; j++) {
21
- if (b.charAt(i - 1) === a.charAt(j - 1)) {
22
- matrix[i][j] = matrix[i - 1][j - 1];
23
- } else {
24
- matrix[i][j] = Math.min(
25
- matrix[i - 1][j - 1] + 1, // substitution
26
- matrix[i][j - 1] + 1, // insertion
27
- matrix[i - 1][j] + 1 // deletion
28
- );
29
- }
30
- }
31
- }
32
-
33
- return matrix[b.length][a.length];
34
- }
@@ -1,91 +0,0 @@
1
- export interface ValidationIssue {
2
- path: string[];
3
- message: string;
4
- }
5
-
6
- export class ValidationError extends Error {
7
- public readonly issues: ValidationIssue[];
8
- public readonly __isValidationError = true;
9
-
10
- constructor(issues: ValidationIssue[], message?: string) {
11
- const errorMessage =
12
- message || `Validation failed: ${issues.map(i => i.message).join(', ')}`;
13
- super(errorMessage);
14
- this.name = 'ValidationError';
15
- this.issues = issues;
16
-
17
- if (Error.captureStackTrace) {
18
- Error.captureStackTrace(this, ValidationError);
19
- }
20
- }
21
-
22
- /**
23
- * Check if an error is a ValidationError (works across module boundaries)
24
- */
25
- static isValidationError(error: unknown): error is ValidationError {
26
- if (error instanceof ValidationError) {
27
- return true;
28
- }
29
- return (
30
- error instanceof Error &&
31
- error.name === 'ValidationError' &&
32
- 'issues' in error &&
33
- Array.isArray((error as any).issues)
34
- );
35
- }
36
-
37
- /**
38
- * Get all error messages as a simple array
39
- */
40
- getMessages(): string[] {
41
- return this.issues.map(i => i.message);
42
- }
43
-
44
- /**
45
- * Get errors for a specific field path
46
- */
47
- getErrorsForPath(path: string): ValidationIssue[] {
48
- return this.issues.filter(i => i.path.join('.') === path);
49
- }
50
-
51
- /**
52
- * Check if a specific path has errors
53
- */
54
- hasErrorsForPath(path: string): boolean {
55
- return this.getErrorsForPath(path).length > 0;
56
- }
57
-
58
- /**
59
- * Convert to a plain object for serialization
60
- */
61
- toJSON(): { name: string; message: string; issues: ValidationIssue[] } {
62
- return {
63
- name: this.name,
64
- message: this.message,
65
- issues: this.issues,
66
- };
67
- }
68
- }
69
-
70
- /**
71
- * Helper to create a single validation issue
72
- */
73
- export function createValidationIssue(
74
- path: string | string[],
75
- message: string
76
- ): ValidationIssue {
77
- return {
78
- path: Array.isArray(path) ? path : path.split('.'),
79
- message,
80
- };
81
- }
82
-
83
- /**
84
- * Helper to throw a validation error with a single issue
85
- */
86
- export function throwValidationError(
87
- path: string | string[],
88
- message: string
89
- ): never {
90
- throw new ValidationError([createValidationIssue(path, message)]);
91
- }