@woltz/rich-domain 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +40 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.versionrc.json +21 -0
- package/.vscode/settings.json +3 -0
- package/CHANGELOG.md +81 -0
- package/LICENSE +21 -0
- package/README.md +712 -0
- package/commitlint.config.js +23 -0
- package/dist/base-entity.d.ts +67 -0
- package/dist/base-entity.d.ts.map +1 -0
- package/dist/base-entity.js +309 -0
- package/dist/base-entity.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/criteria.d.ts +60 -0
- package/dist/criteria.d.ts.map +1 -0
- package/dist/criteria.js +214 -0
- package/dist/criteria.js.map +1 -0
- package/dist/deep-proxy.d.ts +34 -0
- package/dist/deep-proxy.d.ts.map +1 -0
- package/dist/deep-proxy.js +297 -0
- package/dist/deep-proxy.js.map +1 -0
- package/dist/domain-event-bus.d.ts +57 -0
- package/dist/domain-event-bus.d.ts.map +1 -0
- package/dist/domain-event-bus.js +112 -0
- package/dist/domain-event-bus.js.map +1 -0
- package/dist/domain-event.d.ts +55 -0
- package/dist/domain-event.d.ts.map +1 -0
- package/dist/domain-event.js +42 -0
- package/dist/domain-event.js.map +1 -0
- package/dist/entity.d.ts +13 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/entity.js +15 -0
- package/dist/entity.js.map +1 -0
- package/dist/filtering.d.ts +107 -0
- package/dist/filtering.d.ts.map +1 -0
- package/dist/filtering.js +202 -0
- package/dist/filtering.js.map +1 -0
- package/dist/id.d.ts +51 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +84 -0
- package/dist/id.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/ordering.d.ts +93 -0
- package/dist/ordering.d.ts.map +1 -0
- package/dist/ordering.js +154 -0
- package/dist/ordering.js.map +1 -0
- package/dist/paginated-result.d.ts +62 -0
- package/dist/paginated-result.d.ts.map +1 -0
- package/dist/paginated-result.js +201 -0
- package/dist/paginated-result.js.map +1 -0
- package/dist/pagination.d.ts +218 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +281 -0
- package/dist/pagination.js.map +1 -0
- package/dist/repository/base-repository.d.ts +77 -0
- package/dist/repository/base-repository.d.ts.map +1 -0
- package/dist/repository/base-repository.js +80 -0
- package/dist/repository/base-repository.js.map +1 -0
- package/dist/repository/in-memory-repository.d.ts +46 -0
- package/dist/repository/in-memory-repository.d.ts.map +1 -0
- package/dist/repository/in-memory-repository.js +85 -0
- package/dist/repository/in-memory-repository.js.map +1 -0
- package/dist/repository/index.d.ts +42 -0
- package/dist/repository/index.d.ts.map +1 -0
- package/dist/repository/index.js +47 -0
- package/dist/repository/index.js.map +1 -0
- package/dist/repository/mapper.d.ts +56 -0
- package/dist/repository/mapper.d.ts.map +1 -0
- package/dist/repository/mapper.js +15 -0
- package/dist/repository/mapper.js.map +1 -0
- package/dist/repository/types.d.ts +87 -0
- package/dist/repository/types.d.ts.map +1 -0
- package/dist/repository/types.js +6 -0
- package/dist/repository/types.js.map +1 -0
- package/dist/repository/unit-of-work.d.ts +70 -0
- package/dist/repository/unit-of-work.d.ts.map +1 -0
- package/dist/repository/unit-of-work.js +122 -0
- package/dist/repository/unit-of-work.js.map +1 -0
- package/dist/repository.d.ts +2 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +21 -0
- package/dist/repository.js.map +1 -0
- package/dist/specification.d.ts +102 -0
- package/dist/specification.d.ts.map +1 -0
- package/dist/specification.js +187 -0
- package/dist/specification.js.map +1 -0
- package/dist/types/criteria.d.ts +35 -0
- package/dist/types/criteria.d.ts.map +1 -0
- package/dist/types/criteria.js +17 -0
- package/dist/types/criteria.js.map +1 -0
- package/dist/types/domain.d.ts +30 -0
- package/dist/types/domain.d.ts.map +1 -0
- package/dist/types/domain.js +2 -0
- package/dist/types/domain.js.map +1 -0
- package/dist/types/history-tracker.d.ts +36 -0
- package/dist/types/history-tracker.d.ts.map +1 -0
- package/dist/types/history-tracker.js +2 -0
- package/dist/types/history-tracker.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/repository.d.ts +43 -0
- package/dist/types/repository.d.ts.map +1 -0
- package/dist/types/repository.js +2 -0
- package/dist/types/repository.js.map +1 -0
- package/dist/types/standard-schema.d.ts +15 -0
- package/dist/types/standard-schema.d.ts.map +1 -0
- package/dist/types/standard-schema.js +2 -0
- package/dist/types/standard-schema.js.map +1 -0
- package/dist/types/unit-of-work.d.ts +39 -0
- package/dist/types/unit-of-work.d.ts.map +1 -0
- package/dist/types/unit-of-work.js +2 -0
- package/dist/types/unit-of-work.js.map +1 -0
- package/dist/types/utils.d.ts +14 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/utils.js +2 -0
- package/dist/types/utils.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist/validation-error.d.ts +42 -0
- package/dist/validation-error.d.ts.map +1 -0
- package/dist/validation-error.js +73 -0
- package/dist/validation-error.js.map +1 -0
- package/dist/value-object.d.ts +47 -0
- package/dist/value-object.d.ts.map +1 -0
- package/dist/value-object.js +136 -0
- package/dist/value-object.js.map +1 -0
- package/eslint.config.js +51 -0
- package/jest.config.js +21 -0
- package/package.json +58 -0
- package/src/base-entity.ts +401 -0
- package/src/constants.ts +7 -0
- package/src/criteria.ts +291 -0
- package/src/deep-proxy.ts +339 -0
- package/src/domain-event-bus.ts +166 -0
- package/src/domain-event.ts +90 -0
- package/src/entity.ts +16 -0
- package/src/id.ts +94 -0
- package/src/index.ts +33 -0
- package/src/paginated-result.ts +274 -0
- package/src/repository/base-repository.ts +152 -0
- package/src/repository/in-memory-repository.ts +104 -0
- package/src/repository/index.ts +55 -0
- package/src/repository/mapper.ts +74 -0
- package/src/repository/unit-of-work.ts +148 -0
- package/src/types/criteria.ts +79 -0
- package/src/types/domain.ts +37 -0
- package/src/types/history-tracker.ts +45 -0
- package/src/types/index.ts +7 -0
- package/src/types/repository.ts +51 -0
- package/src/types/standard-schema.ts +19 -0
- package/src/types/unit-of-work.ts +46 -0
- package/src/types/utils.ts +29 -0
- package/src/validation-error.ts +97 -0
- package/src/value-object.ts +187 -0
- package/tests/criteria.test.ts +432 -0
- package/tests/domain-events.test.ts +445 -0
- package/tests/entity-equality.test.ts +487 -0
- package/tests/entity-validation.test.ts +339 -0
- package/tests/entity.test.ts +33 -0
- package/tests/history-tracker.spec.ts +667 -0
- package/tests/id.test.ts +341 -0
- package/tests/repository.test.ts +641 -0
- package/tests/to-json.test.ts +91 -0
- package/tests/utils.ts +151 -0
- package/tests/value-object-validation.test.ts +228 -0
- package/tests/value-objects.test.ts +52 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-repository.js","sourceRoot":"","sources":["../../src/repository/base-repository.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8DAA8D;AAC9D,+EAA+E;AAS/E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAgB,cAAc;IAKlC,YAA+B,MAAsC;QAAtC,WAAM,GAAN,MAAM,CAAgC;IAAG,CAAC;IAsDzE,+EAA+E;IAC/E,kDAAkD;IAClD,+EAA+E;IAE/E,KAAK,CAAC,QAAQ,CAAC,EAAM;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAA2B;QACpC,OAAO,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA4B;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA2B;QACvC,oBAAoB;QACpB,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAEhD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAkB;QAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAEzD,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAkB;QAC7B,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAM;QACrB,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAM;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAA4B;QACtC,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Id } from "../id";
|
|
2
|
+
import type { Aggregate } from "../entity";
|
|
3
|
+
import type { Criteria } from "../criteria";
|
|
4
|
+
import { PaginatedResult } from "../paginated-result";
|
|
5
|
+
import type { IRepository } from "../types";
|
|
6
|
+
/**
|
|
7
|
+
* In-memory repository implementation
|
|
8
|
+
* Perfect for unit tests and prototyping
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const userRepo = new InMemoryRepository<User>();
|
|
13
|
+
*
|
|
14
|
+
* await userRepo.save(user);
|
|
15
|
+
* const found = await userRepo.findById(user.id);
|
|
16
|
+
* const active = await userRepo.find(
|
|
17
|
+
* Criteria.create<User>().whereEquals('status', 'active')
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare class InMemoryRepository<TDomain extends Aggregate<any>> implements IRepository<TDomain> {
|
|
22
|
+
protected items: Map<string, TDomain>;
|
|
23
|
+
findById(id: Id): Promise<TDomain | null>;
|
|
24
|
+
find(criteria: Criteria<TDomain>): Promise<PaginatedResult<TDomain>>;
|
|
25
|
+
findAll(criteria?: Criteria<TDomain>): Promise<TDomain[]>;
|
|
26
|
+
findOne(criteria: Criteria<TDomain>): Promise<TDomain | null>;
|
|
27
|
+
save(aggregate: TDomain): Promise<void>;
|
|
28
|
+
saveMany(aggregates: TDomain[]): Promise<void>;
|
|
29
|
+
delete(aggregate: TDomain): Promise<void>;
|
|
30
|
+
deleteById(id: Id): Promise<void>;
|
|
31
|
+
exists(id: Id): Promise<boolean>;
|
|
32
|
+
count(criteria?: Criteria<TDomain>): Promise<number>;
|
|
33
|
+
/**
|
|
34
|
+
* Clear all items (useful for test cleanup)
|
|
35
|
+
*/
|
|
36
|
+
clear(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Get all items as array (useful for debugging)
|
|
39
|
+
*/
|
|
40
|
+
getAll(): TDomain[];
|
|
41
|
+
/**
|
|
42
|
+
* Get items count
|
|
43
|
+
*/
|
|
44
|
+
size(): number;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=in-memory-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-repository.d.ts","sourceRoot":"","sources":["../../src/repository/in-memory-repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,kBAAkB,CAAC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,CAC5D,YAAW,WAAW,CAAC,OAAO,CAAC;IAE/B,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;IAE5C,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIzC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAKpE,OAAO,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IASzD,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAK7D,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ1D;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,MAAM,IAAI,OAAO,EAAE;IAInB;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// In-Memory Repository - Perfect for testing
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { PaginatedResult } from "../paginated-result";
|
|
5
|
+
/**
|
|
6
|
+
* In-memory repository implementation
|
|
7
|
+
* Perfect for unit tests and prototyping
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const userRepo = new InMemoryRepository<User>();
|
|
12
|
+
*
|
|
13
|
+
* await userRepo.save(user);
|
|
14
|
+
* const found = await userRepo.findById(user.id);
|
|
15
|
+
* const active = await userRepo.find(
|
|
16
|
+
* Criteria.create<User>().whereEquals('status', 'active')
|
|
17
|
+
* );
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class InMemoryRepository {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.items = new Map();
|
|
23
|
+
}
|
|
24
|
+
async findById(id) {
|
|
25
|
+
return this.items.get(id.value) || null;
|
|
26
|
+
}
|
|
27
|
+
async find(criteria) {
|
|
28
|
+
const allItems = Array.from(this.items.values());
|
|
29
|
+
return PaginatedResult.fromArray(allItems, criteria);
|
|
30
|
+
}
|
|
31
|
+
async findAll(criteria) {
|
|
32
|
+
if (criteria) {
|
|
33
|
+
const result = await this.find(criteria);
|
|
34
|
+
return result.data;
|
|
35
|
+
}
|
|
36
|
+
return Array.from(this.items.values());
|
|
37
|
+
}
|
|
38
|
+
async findOne(criteria) {
|
|
39
|
+
const result = await this.find(criteria.clone().limit(1));
|
|
40
|
+
return result.data.length > 0 ? result.data[0] : null;
|
|
41
|
+
}
|
|
42
|
+
async save(aggregate) {
|
|
43
|
+
this.items.set(aggregate.id.value, aggregate);
|
|
44
|
+
}
|
|
45
|
+
async saveMany(aggregates) {
|
|
46
|
+
for (const aggregate of aggregates) {
|
|
47
|
+
await this.save(aggregate);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async delete(aggregate) {
|
|
51
|
+
this.items.delete(aggregate.id.value);
|
|
52
|
+
}
|
|
53
|
+
async deleteById(id) {
|
|
54
|
+
this.items.delete(id.value);
|
|
55
|
+
}
|
|
56
|
+
async exists(id) {
|
|
57
|
+
return this.items.has(id.value);
|
|
58
|
+
}
|
|
59
|
+
async count(criteria) {
|
|
60
|
+
if (criteria) {
|
|
61
|
+
const result = await this.find(criteria);
|
|
62
|
+
return result.meta.total;
|
|
63
|
+
}
|
|
64
|
+
return this.items.size;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Clear all items (useful for test cleanup)
|
|
68
|
+
*/
|
|
69
|
+
clear() {
|
|
70
|
+
this.items.clear();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get all items as array (useful for debugging)
|
|
74
|
+
*/
|
|
75
|
+
getAll() {
|
|
76
|
+
return Array.from(this.items.values());
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get items count
|
|
80
|
+
*/
|
|
81
|
+
size() {
|
|
82
|
+
return this.items.size;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=in-memory-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-repository.js","sourceRoot":"","sources":["../../src/repository/in-memory-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export { BaseMapper } from "./mapper";
|
|
2
|
+
export type { IMapper } from "./mapper";
|
|
3
|
+
export { BaseRepository } from "./base-repository";
|
|
4
|
+
export { InMemoryRepository } from "./in-memory-repository";
|
|
5
|
+
export { UnitOfWork, BaseTransactionContext, InMemoryUnitOfWork, } from "./unit-of-work";
|
|
6
|
+
/**
|
|
7
|
+
* QUICK START:
|
|
8
|
+
*
|
|
9
|
+
* 1. For Testing:
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { InMemoryRepository } from 'rich-domain';
|
|
12
|
+
*
|
|
13
|
+
* const userRepo = new InMemoryRepository<User>();
|
|
14
|
+
* await userRepo.save(user);
|
|
15
|
+
* const found = await userRepo.findById(user.id);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* 2. For Production (Prisma, TypeORM, etc):
|
|
19
|
+
* - Extend BaseRepository
|
|
20
|
+
* - Implement abstract methods
|
|
21
|
+
* - Create a Mapper
|
|
22
|
+
* - See examples/ folder for reference
|
|
23
|
+
*
|
|
24
|
+
* 3. With Criteria:
|
|
25
|
+
* ```ts
|
|
26
|
+
* const result = await userRepo.find(
|
|
27
|
+
* Criteria.create<User>()
|
|
28
|
+
* .whereEquals('status', 'active')
|
|
29
|
+
* .orderByDesc('createdAt')
|
|
30
|
+
* .paginate(1, 10)
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* 4. With Unit of Work:
|
|
35
|
+
* ```ts
|
|
36
|
+
* await uow.transaction(async (ctx) => {
|
|
37
|
+
* const userRepo = uow.getRepository(UserRepository);
|
|
38
|
+
* await userRepo.save(user);
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Repository Module - Clean exports
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Mapper
|
|
5
|
+
export { BaseMapper } from "./mapper";
|
|
6
|
+
// Base implementations
|
|
7
|
+
export { BaseRepository } from "./base-repository";
|
|
8
|
+
export { InMemoryRepository } from "./in-memory-repository";
|
|
9
|
+
// Unit of Work
|
|
10
|
+
export { UnitOfWork, BaseTransactionContext, InMemoryUnitOfWork, } from "./unit-of-work";
|
|
11
|
+
/**
|
|
12
|
+
* QUICK START:
|
|
13
|
+
*
|
|
14
|
+
* 1. For Testing:
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { InMemoryRepository } from 'rich-domain';
|
|
17
|
+
*
|
|
18
|
+
* const userRepo = new InMemoryRepository<User>();
|
|
19
|
+
* await userRepo.save(user);
|
|
20
|
+
* const found = await userRepo.findById(user.id);
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* 2. For Production (Prisma, TypeORM, etc):
|
|
24
|
+
* - Extend BaseRepository
|
|
25
|
+
* - Implement abstract methods
|
|
26
|
+
* - Create a Mapper
|
|
27
|
+
* - See examples/ folder for reference
|
|
28
|
+
*
|
|
29
|
+
* 3. With Criteria:
|
|
30
|
+
* ```ts
|
|
31
|
+
* const result = await userRepo.find(
|
|
32
|
+
* Criteria.create<User>()
|
|
33
|
+
* .whereEquals('status', 'active')
|
|
34
|
+
* .orderByDesc('createdAt')
|
|
35
|
+
* .paginate(1, 10)
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* 4. With Unit of Work:
|
|
40
|
+
* ```ts
|
|
41
|
+
* await uow.transaction(async (ctx) => {
|
|
42
|
+
* const userRepo = uow.getRepository(UserRepository);
|
|
43
|
+
* await userRepo.save(user);
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,oCAAoC;AACpC,+EAA+E;AAE/E,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,eAAe;AACf,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Aggregate } from "../entity";
|
|
2
|
+
/**
|
|
3
|
+
* Mapper interface for converting between Domain and Persistence models
|
|
4
|
+
*
|
|
5
|
+
* @template TDomain - Domain aggregate/entity
|
|
6
|
+
* @template TPersistence - Database model (Prisma, TypeORM, etc.)
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* class UserMapper implements IMapper<User, PrismaUser> {
|
|
11
|
+
* toDomain(persistence: PrismaUser): User {
|
|
12
|
+
* return new User({
|
|
13
|
+
* id: Id.from(persistence.id),
|
|
14
|
+
* name: persistence.name,
|
|
15
|
+
* email: persistence.email,
|
|
16
|
+
* });
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* toPersistence(domain: User): PrismaUser {
|
|
20
|
+
* return {
|
|
21
|
+
* id: domain.id.value,
|
|
22
|
+
* name: domain.props.name,
|
|
23
|
+
* email: domain.props.email,
|
|
24
|
+
* };
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface IMapper<TDomain extends Aggregate<any>, TPersistence = any> {
|
|
30
|
+
/**
|
|
31
|
+
* Convert from persistence model to domain aggregate
|
|
32
|
+
*/
|
|
33
|
+
toDomain(persistence: TPersistence): TDomain;
|
|
34
|
+
/**
|
|
35
|
+
* Convert from domain aggregate to persistence model
|
|
36
|
+
*/
|
|
37
|
+
toPersistence(domain: TDomain): TPersistence;
|
|
38
|
+
/**
|
|
39
|
+
* Convert array of persistence models to domain aggregates
|
|
40
|
+
*/
|
|
41
|
+
toDomainList?(persistence: TPersistence[]): TDomain[];
|
|
42
|
+
/**
|
|
43
|
+
* Convert array of domain aggregates to persistence models
|
|
44
|
+
*/
|
|
45
|
+
toPersistenceList?(domain: TDomain[]): TPersistence[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Base mapper with default array implementations
|
|
49
|
+
*/
|
|
50
|
+
export declare abstract class BaseMapper<TDomain extends Aggregate<any>, TPersistence = any> implements IMapper<TDomain, TPersistence> {
|
|
51
|
+
abstract toDomain(persistence: TPersistence): TDomain;
|
|
52
|
+
abstract toPersistence(domain: TDomain): TPersistence;
|
|
53
|
+
toDomainList(persistence: TPersistence[]): TDomain[];
|
|
54
|
+
toPersistenceList(domain: TDomain[]): TPersistence[];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../src/repository/mapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,OAAO,CAAC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,EAAE,YAAY,GAAG,GAAG;IACzE;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC;IAE7C;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,CAAC;IAE7C;;OAEG;IACH,YAAY,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC;IAEtD;;OAEG;IACH,iBAAiB,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;CACvD;AAED;;GAEG;AACH,8BAAsB,UAAU,CAC9B,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,EAC9B,YAAY,GAAG,GAAG,CAClB,YAAW,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC;IAEzC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,OAAO;IACrD,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY;IAErD,YAAY,CAAC,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE;IAIpD,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE;CAGrD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Mapper - Domain ↔ Persistence
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Base mapper with default array implementations
|
|
6
|
+
*/
|
|
7
|
+
export class BaseMapper {
|
|
8
|
+
toDomainList(persistence) {
|
|
9
|
+
return persistence.map((p) => this.toDomain(p));
|
|
10
|
+
}
|
|
11
|
+
toPersistenceList(domain) {
|
|
12
|
+
return domain.map((d) => this.toPersistence(d));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../src/repository/mapper.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gCAAgC;AAChC,+EAA+E;AAqD/E;;GAEG;AACH,MAAM,OAAgB,UAAU;IAQ9B,YAAY,CAAC,WAA2B;QACtC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,iBAAiB,CAAC,MAAiB;QACjC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Id } from "../id";
|
|
2
|
+
import type { Aggregate } from "../entity";
|
|
3
|
+
import type { Criteria } from "../criteria";
|
|
4
|
+
import type { PaginatedResult } from "../paginated-result";
|
|
5
|
+
/**
|
|
6
|
+
* Base repository interface
|
|
7
|
+
* Keep it minimal - only what you actually need
|
|
8
|
+
*/
|
|
9
|
+
export interface IRepository<TDomain extends Aggregate<any>> {
|
|
10
|
+
/**
|
|
11
|
+
* Find by ID
|
|
12
|
+
*/
|
|
13
|
+
findById(id: Id): Promise<TDomain | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Find using criteria (filtering, ordering, pagination)
|
|
16
|
+
*/
|
|
17
|
+
find(criteria: Criteria<TDomain>): Promise<PaginatedResult<TDomain>>;
|
|
18
|
+
/**
|
|
19
|
+
* Find all (with optional criteria)
|
|
20
|
+
*/
|
|
21
|
+
findAll(criteria?: Criteria<TDomain>): Promise<TDomain[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Find one (first matching criteria)
|
|
24
|
+
*/
|
|
25
|
+
findOne(criteria: Criteria<TDomain>): Promise<TDomain | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Save (insert or update based on aggregate.isNew)
|
|
28
|
+
*/
|
|
29
|
+
save(aggregate: TDomain): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Save multiple aggregates
|
|
32
|
+
*/
|
|
33
|
+
saveMany(aggregates: TDomain[]): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Delete aggregate
|
|
36
|
+
*/
|
|
37
|
+
delete(aggregate: TDomain): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Delete by ID
|
|
40
|
+
*/
|
|
41
|
+
deleteById(id: Id): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Check if exists
|
|
44
|
+
*/
|
|
45
|
+
exists(id: Id): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Count matching criteria
|
|
48
|
+
*/
|
|
49
|
+
count(criteria?: Criteria<TDomain>): Promise<number>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Transaction context for Unit of Work
|
|
53
|
+
*/
|
|
54
|
+
export interface TransactionContext {
|
|
55
|
+
/**
|
|
56
|
+
* Commit all changes
|
|
57
|
+
*/
|
|
58
|
+
commit(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Rollback all changes
|
|
61
|
+
*/
|
|
62
|
+
rollback(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Check if transaction is active
|
|
65
|
+
*/
|
|
66
|
+
isActive(): boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Unit of Work interface
|
|
70
|
+
* Manages transactions across multiple repositories
|
|
71
|
+
*/
|
|
72
|
+
export interface IUnitOfWork {
|
|
73
|
+
/**
|
|
74
|
+
* Start a new transaction
|
|
75
|
+
*/
|
|
76
|
+
begin(): Promise<TransactionContext>;
|
|
77
|
+
/**
|
|
78
|
+
* Execute work within a transaction
|
|
79
|
+
* Auto-commits on success, rolls back on error
|
|
80
|
+
*/
|
|
81
|
+
transaction<T>(work: (ctx: TransactionContext) => Promise<T>): Promise<T>;
|
|
82
|
+
/**
|
|
83
|
+
* Get repository within transaction context
|
|
84
|
+
*/
|
|
85
|
+
getRepository<TDomain extends Aggregate<any>>(repository: new (...args: any[]) => IRepository<TDomain>): IRepository<TDomain>;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/repository/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC;IACzD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAErE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAE1D;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE9D;;OAEG;IACH,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjC;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAErC;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,aAAa,CAAC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,EAC1C,UAAU,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW,CAAC,OAAO,CAAC,GACvD,WAAW,CAAC,OAAO,CAAC,CAAC;CACzB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Repository Types - Simple and Type-Safe
|
|
4
|
+
// ============================================================================
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/repository/types.ts"],"names":[],"mappings":";AAAA,+EAA+E;AAC/E,0CAA0C;AAC1C,+EAA+E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { IUnitOfWork, TransactionContext } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Abstract Unit of Work
|
|
4
|
+
* Provides transaction management across multiple repositories
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* // Using transaction helper (recommended)
|
|
9
|
+
* await uow.transaction(async (ctx) => {
|
|
10
|
+
* const userRepo = uow.getRepository(UserRepository);
|
|
11
|
+
* const orderRepo = uow.getRepository(OrderRepository);
|
|
12
|
+
*
|
|
13
|
+
* await userRepo.save(user);
|
|
14
|
+
* await orderRepo.save(order);
|
|
15
|
+
*
|
|
16
|
+
* // Auto-commits on success, rolls back on error
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Manual control
|
|
20
|
+
* const ctx = await uow.begin();
|
|
21
|
+
* try {
|
|
22
|
+
* await userRepo.save(user);
|
|
23
|
+
* await orderRepo.save(order);
|
|
24
|
+
* await ctx.commit();
|
|
25
|
+
* } catch (error) {
|
|
26
|
+
* await ctx.rollback();
|
|
27
|
+
* throw error;
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare abstract class UnitOfWork implements IUnitOfWork {
|
|
32
|
+
protected currentContext: TransactionContext | null;
|
|
33
|
+
protected repositoryCache: Map<string, any>;
|
|
34
|
+
abstract begin(): Promise<TransactionContext>;
|
|
35
|
+
/**
|
|
36
|
+
* Execute work within a transaction
|
|
37
|
+
* Auto-commits on success, rolls back on error
|
|
38
|
+
*/
|
|
39
|
+
transaction<T>(work: (ctx: TransactionContext) => Promise<T>): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Get repository instance (cached per transaction)
|
|
42
|
+
*/
|
|
43
|
+
getRepository<TRepo>(RepositoryClass: new (...args: any[]) => TRepo): TRepo;
|
|
44
|
+
/**
|
|
45
|
+
* Create repository instance - implement in subclass
|
|
46
|
+
*/
|
|
47
|
+
protected abstract createRepository<TRepo>(RepositoryClass: new (...args: any[]) => TRepo): TRepo;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Base Transaction Context
|
|
51
|
+
*/
|
|
52
|
+
export declare abstract class BaseTransactionContext implements TransactionContext {
|
|
53
|
+
protected _isActive: boolean;
|
|
54
|
+
abstract commit(): Promise<void>;
|
|
55
|
+
abstract rollback(): Promise<void>;
|
|
56
|
+
isActive(): boolean;
|
|
57
|
+
protected markInactive(): void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* In-Memory Unit of Work (for testing)
|
|
61
|
+
*/
|
|
62
|
+
export declare class InMemoryUnitOfWork extends UnitOfWork {
|
|
63
|
+
private committed;
|
|
64
|
+
private rolledBack;
|
|
65
|
+
begin(): Promise<TransactionContext>;
|
|
66
|
+
protected createRepository<TRepo>(RepositoryClass: new (...args: any[]) => TRepo): TRepo;
|
|
67
|
+
isCommitted(): boolean;
|
|
68
|
+
isRolledBack(): boolean;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=unit-of-work.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unit-of-work.d.ts","sourceRoot":"","sources":["../../src/repository/unit-of-work.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,8BAAsB,UAAW,YAAW,WAAW;IACrD,SAAS,CAAC,cAAc,EAAE,kBAAkB,GAAG,IAAI,CAAQ;IAC3D,SAAS,CAAC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAa;IAExD,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAE7C;;;OAGG;IACG,WAAW,CAAC,CAAC,EACjB,IAAI,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC;IAkBb;;OAEG;IACH,aAAa,CAAC,KAAK,EACjB,eAAe,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,GAC7C,KAAK;IAYR;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EACvC,eAAe,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,GAC7C,KAAK;CACT;AAED;;GAEG;AACH,8BAAsB,sBAAuB,YAAW,kBAAkB;IACxE,SAAS,CAAC,SAAS,UAAQ;IAE3B,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAElC,QAAQ,IAAI,OAAO;IAInB,SAAS,CAAC,YAAY,IAAI,IAAI;CAG/B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAErB,KAAK,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAO1C,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAC9B,eAAe,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,GAC7C,KAAK;IAMR,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,OAAO;CAGxB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Unit of Work - Simple transaction management
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Abstract Unit of Work
|
|
6
|
+
* Provides transaction management across multiple repositories
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // Using transaction helper (recommended)
|
|
11
|
+
* await uow.transaction(async (ctx) => {
|
|
12
|
+
* const userRepo = uow.getRepository(UserRepository);
|
|
13
|
+
* const orderRepo = uow.getRepository(OrderRepository);
|
|
14
|
+
*
|
|
15
|
+
* await userRepo.save(user);
|
|
16
|
+
* await orderRepo.save(order);
|
|
17
|
+
*
|
|
18
|
+
* // Auto-commits on success, rolls back on error
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Manual control
|
|
22
|
+
* const ctx = await uow.begin();
|
|
23
|
+
* try {
|
|
24
|
+
* await userRepo.save(user);
|
|
25
|
+
* await orderRepo.save(order);
|
|
26
|
+
* await ctx.commit();
|
|
27
|
+
* } catch (error) {
|
|
28
|
+
* await ctx.rollback();
|
|
29
|
+
* throw error;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class UnitOfWork {
|
|
34
|
+
constructor() {
|
|
35
|
+
this.currentContext = null;
|
|
36
|
+
this.repositoryCache = new Map();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Execute work within a transaction
|
|
40
|
+
* Auto-commits on success, rolls back on error
|
|
41
|
+
*/
|
|
42
|
+
async transaction(work) {
|
|
43
|
+
const ctx = await this.begin();
|
|
44
|
+
try {
|
|
45
|
+
const result = await work(ctx);
|
|
46
|
+
await ctx.commit();
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (ctx.isActive()) {
|
|
51
|
+
await ctx.rollback();
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
this.currentContext = null;
|
|
57
|
+
this.repositoryCache.clear();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get repository instance (cached per transaction)
|
|
62
|
+
*/
|
|
63
|
+
getRepository(RepositoryClass) {
|
|
64
|
+
const key = RepositoryClass.name;
|
|
65
|
+
if (this.repositoryCache.has(key)) {
|
|
66
|
+
return this.repositoryCache.get(key);
|
|
67
|
+
}
|
|
68
|
+
const repo = this.createRepository(RepositoryClass);
|
|
69
|
+
this.repositoryCache.set(key, repo);
|
|
70
|
+
return repo;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Base Transaction Context
|
|
75
|
+
*/
|
|
76
|
+
export class BaseTransactionContext {
|
|
77
|
+
constructor() {
|
|
78
|
+
this._isActive = true;
|
|
79
|
+
}
|
|
80
|
+
isActive() {
|
|
81
|
+
return this._isActive;
|
|
82
|
+
}
|
|
83
|
+
markInactive() {
|
|
84
|
+
this._isActive = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* In-Memory Unit of Work (for testing)
|
|
89
|
+
*/
|
|
90
|
+
export class InMemoryUnitOfWork extends UnitOfWork {
|
|
91
|
+
constructor() {
|
|
92
|
+
super(...arguments);
|
|
93
|
+
this.committed = false;
|
|
94
|
+
this.rolledBack = false;
|
|
95
|
+
}
|
|
96
|
+
async begin() {
|
|
97
|
+
this.currentContext = new InMemoryTransactionContext();
|
|
98
|
+
this.committed = false;
|
|
99
|
+
this.rolledBack = false;
|
|
100
|
+
return this.currentContext;
|
|
101
|
+
}
|
|
102
|
+
createRepository(RepositoryClass) {
|
|
103
|
+
// For in-memory, just create a new instance
|
|
104
|
+
// In real implementation, pass transaction client
|
|
105
|
+
return new RepositoryClass();
|
|
106
|
+
}
|
|
107
|
+
isCommitted() {
|
|
108
|
+
return this.committed;
|
|
109
|
+
}
|
|
110
|
+
isRolledBack() {
|
|
111
|
+
return this.rolledBack;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
class InMemoryTransactionContext extends BaseTransactionContext {
|
|
115
|
+
async commit() {
|
|
116
|
+
this.markInactive();
|
|
117
|
+
}
|
|
118
|
+
async rollback() {
|
|
119
|
+
this.markInactive();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=unit-of-work.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unit-of-work.js","sourceRoot":"","sources":["../../src/repository/unit-of-work.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+CAA+C;AAC/C,+EAA+E;AAI/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAgB,UAAU;IAAhC;QACY,mBAAc,GAA8B,IAAI,CAAC;QACjD,oBAAe,GAAqB,IAAI,GAAG,EAAE,CAAC;IAmD1D,CAAC;IA/CC;;;OAGG;IACH,KAAK,CAAC,WAAW,CACf,IAA6C;QAE7C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACnB,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC;YACvB,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CACX,eAA8C;QAE9C,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC;QAEjC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;CAQF;AAED;;GAEG;AACH,MAAM,OAAgB,sBAAsB;IAA5C;QACY,cAAS,GAAG,IAAI,CAAC;IAY7B,CAAC;IAPC,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAES,YAAY;QACpB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAAlD;;QACU,cAAS,GAAG,KAAK,CAAC;QAClB,eAAU,GAAG,KAAK,CAAC;IAwB7B,CAAC;IAtBC,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,cAAc,GAAG,IAAI,0BAA0B,EAAE,CAAC;QACvD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAES,gBAAgB,CACxB,eAA8C;QAE9C,4CAA4C;QAC5C,kDAAkD;QAClD,OAAO,IAAI,eAAe,EAAE,CAAC;IAC/B,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,0BAA2B,SAAQ,sBAAsB;IAC7D,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAIA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Repository - Main export (backward compatibility)
|
|
4
|
+
// ============================================================================
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./repository/index"), exports);
|
|
21
|
+
//# sourceMappingURL=repository.js.map
|