@woltz/rich-domain-drizzle 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.
Files changed (93) hide show
  1. package/dist/cjs/batch-executor.d.ts +30 -0
  2. package/dist/cjs/batch-executor.d.ts.map +1 -0
  3. package/dist/cjs/batch-executor.js +201 -0
  4. package/dist/cjs/batch-executor.js.map +1 -0
  5. package/dist/cjs/errors.d.ts +31 -0
  6. package/dist/cjs/errors.d.ts.map +1 -0
  7. package/dist/cjs/errors.js +84 -0
  8. package/dist/cjs/errors.js.map +1 -0
  9. package/dist/cjs/index.d.ts +8 -0
  10. package/dist/cjs/index.d.ts.map +1 -0
  11. package/dist/cjs/index.js +34 -0
  12. package/dist/cjs/index.js.map +1 -0
  13. package/dist/cjs/mappers/to-domain.d.ts +11 -0
  14. package/dist/cjs/mappers/to-domain.d.ts.map +1 -0
  15. package/dist/cjs/mappers/to-domain.js +15 -0
  16. package/dist/cjs/mappers/to-domain.js.map +1 -0
  17. package/dist/cjs/mappers/to-persistence.d.ts +47 -0
  18. package/dist/cjs/mappers/to-persistence.d.ts.map +1 -0
  19. package/dist/cjs/mappers/to-persistence.js +69 -0
  20. package/dist/cjs/mappers/to-persistence.js.map +1 -0
  21. package/dist/cjs/query-builder.d.ts +24 -0
  22. package/dist/cjs/query-builder.d.ts.map +1 -0
  23. package/dist/cjs/query-builder.js +146 -0
  24. package/dist/cjs/query-builder.js.map +1 -0
  25. package/dist/cjs/repository.d.ts +46 -0
  26. package/dist/cjs/repository.d.ts.map +1 -0
  27. package/dist/cjs/repository.js +192 -0
  28. package/dist/cjs/repository.js.map +1 -0
  29. package/dist/cjs/unit-of-work.d.ts +49 -0
  30. package/dist/cjs/unit-of-work.d.ts.map +1 -0
  31. package/dist/cjs/unit-of-work.js +94 -0
  32. package/dist/cjs/unit-of-work.js.map +1 -0
  33. package/dist/esm/batch-executor.d.ts +30 -0
  34. package/dist/esm/batch-executor.d.ts.map +1 -0
  35. package/dist/esm/batch-executor.js +196 -0
  36. package/dist/esm/batch-executor.js.map +1 -0
  37. package/dist/esm/errors.d.ts +31 -0
  38. package/dist/esm/errors.d.ts.map +1 -0
  39. package/dist/esm/errors.js +75 -0
  40. package/dist/esm/errors.js.map +1 -0
  41. package/dist/esm/index.d.ts +8 -0
  42. package/dist/esm/index.d.ts.map +1 -0
  43. package/dist/esm/index.js +14 -0
  44. package/dist/esm/index.js.map +1 -0
  45. package/dist/esm/mappers/to-domain.d.ts +11 -0
  46. package/dist/esm/mappers/to-domain.d.ts.map +1 -0
  47. package/dist/esm/mappers/to-domain.js +11 -0
  48. package/dist/esm/mappers/to-domain.js.map +1 -0
  49. package/dist/esm/mappers/to-persistence.d.ts +47 -0
  50. package/dist/esm/mappers/to-persistence.d.ts.map +1 -0
  51. package/dist/esm/mappers/to-persistence.js +65 -0
  52. package/dist/esm/mappers/to-persistence.js.map +1 -0
  53. package/dist/esm/package.json +3 -0
  54. package/dist/esm/query-builder.d.ts +24 -0
  55. package/dist/esm/query-builder.d.ts.map +1 -0
  56. package/dist/esm/query-builder.js +142 -0
  57. package/dist/esm/query-builder.js.map +1 -0
  58. package/dist/esm/repository.d.ts +46 -0
  59. package/dist/esm/repository.d.ts.map +1 -0
  60. package/dist/esm/repository.js +188 -0
  61. package/dist/esm/repository.js.map +1 -0
  62. package/dist/esm/unit-of-work.d.ts +49 -0
  63. package/dist/esm/unit-of-work.d.ts.map +1 -0
  64. package/dist/esm/unit-of-work.js +87 -0
  65. package/dist/esm/unit-of-work.js.map +1 -0
  66. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  67. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  68. package/dist/tsconfig.types.tsbuildinfo +1 -0
  69. package/dist/types/batch-executor.d.ts +30 -0
  70. package/dist/types/batch-executor.d.ts.map +1 -0
  71. package/dist/types/errors.d.ts +31 -0
  72. package/dist/types/errors.d.ts.map +1 -0
  73. package/dist/types/index.d.ts +8 -0
  74. package/dist/types/index.d.ts.map +1 -0
  75. package/dist/types/mappers/to-domain.d.ts +11 -0
  76. package/dist/types/mappers/to-domain.d.ts.map +1 -0
  77. package/dist/types/mappers/to-persistence.d.ts +47 -0
  78. package/dist/types/mappers/to-persistence.d.ts.map +1 -0
  79. package/dist/types/query-builder.d.ts +24 -0
  80. package/dist/types/query-builder.d.ts.map +1 -0
  81. package/dist/types/repository.d.ts +46 -0
  82. package/dist/types/repository.d.ts.map +1 -0
  83. package/dist/types/unit-of-work.d.ts +49 -0
  84. package/dist/types/unit-of-work.d.ts.map +1 -0
  85. package/package.json +69 -0
  86. package/src/batch-executor.ts +317 -0
  87. package/src/errors.ts +78 -0
  88. package/src/index.ts +37 -0
  89. package/src/mappers/to-domain.ts +13 -0
  90. package/src/mappers/to-persistence.ts +101 -0
  91. package/src/query-builder.ts +217 -0
  92. package/src/repository.ts +252 -0
  93. package/src/unit-of-work.ts +123 -0
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DrizzleQueryBuilder = void 0;
4
+ const drizzle_orm_1 = require("drizzle-orm");
5
+ const errors_1 = require("./errors");
6
+ const OPERATOR_MAP = {
7
+ equals: (col, val) => (0, drizzle_orm_1.eq)(col, val),
8
+ notEquals: (col, val) => (0, drizzle_orm_1.ne)(col, val),
9
+ greaterThan: (col, val) => (0, drizzle_orm_1.gt)(col, val),
10
+ greaterThanOrEqual: (col, val) => (0, drizzle_orm_1.gte)(col, val),
11
+ lessThan: (col, val) => (0, drizzle_orm_1.lt)(col, val),
12
+ lessThanOrEqual: (col, val) => (0, drizzle_orm_1.lte)(col, val),
13
+ contains: (col, val) => (0, drizzle_orm_1.ilike)(col, `%${val}%`),
14
+ startsWith: (col, val) => (0, drizzle_orm_1.ilike)(col, `${val}%`),
15
+ endsWith: (col, val) => (0, drizzle_orm_1.ilike)(col, `%${val}`),
16
+ in: (col, val) => (0, drizzle_orm_1.inArray)(col, val),
17
+ notIn: (col, val) => (0, drizzle_orm_1.notInArray)(col, val),
18
+ isNull: (col) => (0, drizzle_orm_1.isNull)(col),
19
+ isNotNull: (col) => (0, drizzle_orm_1.isNotNull)(col),
20
+ between: (col, val) => (0, drizzle_orm_1.between)(col, val[0], val[1]),
21
+ };
22
+ class DrizzleQueryBuilder {
23
+ /**
24
+ * Apply Criteria to a Drizzle select query.
25
+ *
26
+ * @param criteria - The Criteria instance with filters, orders, pagination, search
27
+ * @param table - The Drizzle table object (e.g., usersTable)
28
+ * @param searchableFields - Fields to search when criteria.hasSearch()
29
+ * @returns Object with { where, orderBy, limit, offset } ready for Drizzle query
30
+ */
31
+ static apply(criteria, table, searchableFields) {
32
+ const result = {};
33
+ // Build filter conditions
34
+ const filterConditions = [];
35
+ for (const filter of criteria.getFilters()) {
36
+ if (filter.field.includes(".")) {
37
+ throw new errors_1.DrizzleAdapterError(`Filtering on relation field "${filter.field}" is not supported. ` +
38
+ `Drizzle requires explicit JOINs to filter across relations. ` +
39
+ `Add a custom method to your repository using the Drizzle SQL API instead.`);
40
+ }
41
+ if (filter.options?.quantifier) {
42
+ throw new errors_1.DrizzleAdapterError(`Quantifier "${filter.options.quantifier}" on field "${filter.field}" is not supported. ` +
43
+ `Drizzle does not have a built-in some/every/none operator. ` +
44
+ `Add a custom method to your repository using EXISTS subqueries instead.`);
45
+ }
46
+ const col = DrizzleQueryBuilder.resolveColumn(table, filter.field);
47
+ if (col === undefined) {
48
+ throw new errors_1.DrizzleAdapterError(`Column "${filter.field}" not found on table. ` +
49
+ `Available columns: ${Object.keys(table)
50
+ .filter((k) => typeof table[k] === "object")
51
+ .join(", ")}`);
52
+ }
53
+ const operatorFn = OPERATOR_MAP[filter.operator];
54
+ if (!operatorFn) {
55
+ throw new errors_1.DrizzleAdapterError(`Operator "${filter.operator}" is not supported by the Drizzle adapter.`);
56
+ }
57
+ filterConditions.push(operatorFn(col, filter.value));
58
+ }
59
+ // Build search conditions
60
+ let searchCondition;
61
+ if (criteria.hasSearch() &&
62
+ searchableFields &&
63
+ searchableFields.length > 0) {
64
+ const search = criteria.getSearch();
65
+ const searchConditions = [];
66
+ for (const searchField of searchableFields) {
67
+ let fieldName;
68
+ let caseSensitive = false;
69
+ if (typeof searchField === "object" && "field" in searchField) {
70
+ fieldName = searchField.field;
71
+ caseSensitive = searchField.caseSensitive ?? false;
72
+ }
73
+ else {
74
+ fieldName = String(searchField);
75
+ }
76
+ if (fieldName.includes(".")) {
77
+ throw new errors_1.DrizzleAdapterError(`Search field "${fieldName}" references a relation. ` +
78
+ `Drizzle does not support cross-table search via Criteria. ` +
79
+ `Use only top-level columns in getSearchableFields().`);
80
+ }
81
+ const col = DrizzleQueryBuilder.resolveColumn(table, fieldName);
82
+ if (col === undefined) {
83
+ throw new errors_1.DrizzleAdapterError(`Search field "${fieldName}" not found on table. ` +
84
+ `Available columns: ${Object.keys(table)
85
+ .filter((k) => typeof table[k] === "object")
86
+ .join(", ")}`);
87
+ }
88
+ if (caseSensitive) {
89
+ searchConditions.push((0, drizzle_orm_1.like)(col, `%${search}%`));
90
+ }
91
+ else {
92
+ searchConditions.push((0, drizzle_orm_1.ilike)(col, `%${search}%`));
93
+ }
94
+ }
95
+ if (searchConditions.length > 0) {
96
+ searchCondition =
97
+ searchConditions.length === 1
98
+ ? searchConditions[0]
99
+ : (0, drizzle_orm_1.or)(...searchConditions);
100
+ }
101
+ }
102
+ // Combine filter and search conditions
103
+ if (filterConditions.length > 0 || searchCondition) {
104
+ const allConditions = [...filterConditions];
105
+ if (searchCondition)
106
+ allConditions.push(searchCondition);
107
+ if (allConditions.length === 1) {
108
+ result.where = allConditions[0];
109
+ }
110
+ else {
111
+ result.where = (0, drizzle_orm_1.and)(...allConditions);
112
+ }
113
+ }
114
+ // Build order conditions
115
+ const orders = criteria.getOrders();
116
+ if (orders.length > 0) {
117
+ result.orderBy = orders.map((o) => {
118
+ if (o.field.includes(".")) {
119
+ throw new errors_1.DrizzleAdapterError(`Ordering by relation field "${o.field}" is not supported. ` +
120
+ `Drizzle requires explicit JOINs to order across relations. ` +
121
+ `Add a custom method to your repository using the Drizzle SQL API instead.`);
122
+ }
123
+ const col = DrizzleQueryBuilder.resolveColumn(table, o.field);
124
+ if (col === undefined) {
125
+ throw new errors_1.DrizzleAdapterError(`Order field "${o.field}" not found on table. ` +
126
+ `Available columns: ${Object.keys(table)
127
+ .filter((k) => typeof table[k] === "object")
128
+ .join(", ")}`);
129
+ }
130
+ return o.direction === "desc" ? (0, drizzle_orm_1.desc)(col) : (0, drizzle_orm_1.asc)(col);
131
+ });
132
+ }
133
+ // Build pagination
134
+ const pagination = criteria.getPagination();
135
+ if (pagination) {
136
+ result.limit = pagination.limit;
137
+ result.offset = pagination.offset;
138
+ }
139
+ return result;
140
+ }
141
+ static resolveColumn(table, fieldPath) {
142
+ return table[fieldPath];
143
+ }
144
+ }
145
+ exports.DrizzleQueryBuilder = DrizzleQueryBuilder;
146
+ //# sourceMappingURL=query-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../src/query-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { Aggregate, Repository, Mapper, Criteria, PaginatedResult } from "@woltz/rich-domain";
2
+ import { DrizzleClient, DrizzleUnitOfWork } from "./unit-of-work";
3
+ import { DrizzleToPersistence } from "./mappers/to-persistence";
4
+ import { SearchableField } from "./query-builder";
5
+ export interface DrizzleRepositoryConfig<TDomain, TPersistence> {
6
+ db: DrizzleClient;
7
+ table: any;
8
+ toDomainMapper: Mapper<TPersistence, TDomain>;
9
+ toPersistenceMapper: DrizzleToPersistence<TDomain>;
10
+ uow: DrizzleUnitOfWork;
11
+ }
12
+ export declare abstract class DrizzleRepository<TDomain extends Aggregate<any>, TPersistence> extends Repository<TDomain> {
13
+ protected readonly db: DrizzleClient;
14
+ protected readonly table: any;
15
+ protected readonly toDomainMapper: Mapper<TPersistence, TDomain>;
16
+ protected readonly toPersistenceMapper: DrizzleToPersistence<TDomain>;
17
+ protected readonly uow: DrizzleUnitOfWork;
18
+ constructor(config: DrizzleRepositoryConfig<TDomain, TPersistence>);
19
+ /**
20
+ * Returns tx from UOWStorage if inside a transaction, otherwise the raw db.
21
+ */
22
+ protected get context(): DrizzleClient;
23
+ /**
24
+ * The table name string used by EntitySchemaRegistry and db.query accessor.
25
+ */
26
+ protected abstract get model(): string;
27
+ /**
28
+ * Search conditions for full-text search via Criteria.search().
29
+ */
30
+ protected abstract getSearchableFields(): SearchableField<TPersistence>[];
31
+ /**
32
+ * Relations to include when fetching (for Drizzle relational query API).
33
+ */
34
+ protected getDefaultRelations(): Record<string, any>;
35
+ find(criteria: Criteria<TDomain>): Promise<PaginatedResult<TDomain>>;
36
+ findById(id: string): Promise<TDomain | null>;
37
+ findManyByIds(ids: string[]): Promise<TDomain[]>;
38
+ count(criteria?: Criteria<TDomain>): Promise<number>;
39
+ exists(id: string): Promise<boolean>;
40
+ save(entity: TDomain): Promise<void>;
41
+ delete(entity: TDomain): Promise<void>;
42
+ deleteById(id: string): Promise<void>;
43
+ transaction<T>(work: () => Promise<T>): Promise<T>;
44
+ private markArrayOfAggregateWithClean;
45
+ }
46
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,EACR,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAc,MAAM,gBAAgB,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAuB,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvE,MAAM,WAAW,uBAAuB,CAAC,OAAO,EAAE,YAAY;IAC5D,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,GAAG,CAAC;IACX,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9C,mBAAmB,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACnD,GAAG,EAAE,iBAAiB,CAAC;CACxB;AAED,8BAAsB,iBAAiB,CACrC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,EAC9B,YAAY,CACZ,SAAQ,UAAU,CAAC,OAAO,CAAC;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;IAC9B,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACtE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;gBAE9B,MAAM,EAAE,uBAAuB,CAAC,OAAO,EAAE,YAAY,CAAC;IASlE;;OAEG;IACH,SAAS,KAAK,OAAO,IAAI,aAAa,CAGrC;IAED;;OAEG;IACH,SAAS,CAAC,QAAQ,KAAK,KAAK,IAAI,MAAM,CAAC;IAEvC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,mBAAmB,IAAI,eAAe,CAAC,YAAY,CAAC,EAAE;IAEzE;;OAEG;IACH,SAAS,CAAC,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI9C,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAqDpE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA8B7C,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA4BhD,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBpD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQpC,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBtC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBrC,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIxD,OAAO,CAAC,6BAA6B;CAOtC"}
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DrizzleRepository = void 0;
4
+ const drizzle_orm_1 = require("drizzle-orm");
5
+ const rich_domain_1 = require("@woltz/rich-domain");
6
+ const unit_of_work_1 = require("./unit-of-work");
7
+ const errors_1 = require("./errors");
8
+ const query_builder_1 = require("./query-builder");
9
+ class DrizzleRepository extends rich_domain_1.Repository {
10
+ db;
11
+ table;
12
+ toDomainMapper;
13
+ toPersistenceMapper;
14
+ uow;
15
+ constructor(config) {
16
+ super();
17
+ this.db = config.db;
18
+ this.table = config.table;
19
+ this.toDomainMapper = config.toDomainMapper;
20
+ this.toPersistenceMapper = config.toPersistenceMapper;
21
+ this.uow = config.uow;
22
+ }
23
+ /**
24
+ * Returns tx from UOWStorage if inside a transaction, otherwise the raw db.
25
+ */
26
+ get context() {
27
+ const ctx = unit_of_work_1.UOWStorage.getStore()?.ctx;
28
+ return ctx?.client ?? this.db;
29
+ }
30
+ /**
31
+ * Relations to include when fetching (for Drizzle relational query API).
32
+ */
33
+ getDefaultRelations() {
34
+ return {};
35
+ }
36
+ async find(criteria) {
37
+ const { where, orderBy, limit, offset } = query_builder_1.DrizzleQueryBuilder.apply(criteria, this.table, this.getSearchableFields());
38
+ const queryModel = this.context.query?.[this.model];
39
+ let data;
40
+ let total;
41
+ if (queryModel) {
42
+ [data, total] = await Promise.all([
43
+ queryModel.findMany({
44
+ where,
45
+ orderBy,
46
+ limit,
47
+ offset,
48
+ with: this.getDefaultRelations(),
49
+ }),
50
+ this.context
51
+ .select({ value: (0, drizzle_orm_1.count)() })
52
+ .from(this.table)
53
+ .where(where)
54
+ .then((r) => Number(r[0]?.value ?? 0)),
55
+ ]);
56
+ }
57
+ else {
58
+ const selectQuery = this.context.select().from(this.table).$dynamic();
59
+ if (where)
60
+ selectQuery.where(where);
61
+ if (orderBy && orderBy.length > 0)
62
+ selectQuery.orderBy(...orderBy);
63
+ if (limit !== undefined)
64
+ selectQuery.limit(limit);
65
+ if (offset !== undefined)
66
+ selectQuery.offset(offset);
67
+ const countQuery = this.context
68
+ .select({ value: (0, drizzle_orm_1.count)() })
69
+ .from(this.table);
70
+ if (where)
71
+ countQuery.where(where);
72
+ [data, [{ value: total }]] = await Promise.all([selectQuery, countQuery]);
73
+ total = Number(total ?? 0);
74
+ }
75
+ const toDomain = data.map((item) => this.toDomainMapper.build(item));
76
+ this.markArrayOfAggregateWithClean(toDomain);
77
+ return rich_domain_1.PaginatedResult.create(toDomain, criteria.getPagination(), total);
78
+ }
79
+ async findById(id) {
80
+ const queryModel = this.context.query?.[this.model];
81
+ let data;
82
+ if (queryModel) {
83
+ data = await queryModel.findFirst({
84
+ where: (0, drizzle_orm_1.eq)(this.table.id, id),
85
+ with: this.getDefaultRelations(),
86
+ });
87
+ }
88
+ else {
89
+ const rows = await this.context
90
+ .select()
91
+ .from(this.table)
92
+ .where((0, drizzle_orm_1.eq)(this.table.id, id))
93
+ .limit(1);
94
+ data = rows[0] ?? null;
95
+ }
96
+ if (!data)
97
+ return null;
98
+ const result = this.toDomainMapper.build(data);
99
+ if (result instanceof rich_domain_1.Aggregate) {
100
+ result.markAsClean();
101
+ }
102
+ return result;
103
+ }
104
+ async findManyByIds(ids) {
105
+ if (ids.length === 0)
106
+ return [];
107
+ const queryModel = this.context.query?.[this.model];
108
+ let data;
109
+ if (queryModel) {
110
+ data = await queryModel.findMany({
111
+ where: (0, drizzle_orm_1.inArray)(this.table.id, ids),
112
+ with: this.getDefaultRelations(),
113
+ });
114
+ }
115
+ else {
116
+ data = await this.context
117
+ .select()
118
+ .from(this.table)
119
+ .where((0, drizzle_orm_1.inArray)(this.table.id, ids));
120
+ }
121
+ const toDomain = data.map((item) => this.toDomainMapper.build(item));
122
+ this.markArrayOfAggregateWithClean(toDomain);
123
+ return toDomain;
124
+ }
125
+ async count(criteria) {
126
+ let where;
127
+ if (criteria) {
128
+ ({ where } = query_builder_1.DrizzleQueryBuilder.apply(criteria, this.table, this.getSearchableFields()));
129
+ }
130
+ const query = this.context.select({ value: (0, drizzle_orm_1.count)() }).from(this.table);
131
+ if (where)
132
+ query.where(where);
133
+ const result = await query;
134
+ return Number(result[0]?.value ?? 0);
135
+ }
136
+ async exists(id) {
137
+ const result = await this.context
138
+ .select({ value: (0, drizzle_orm_1.count)() })
139
+ .from(this.table)
140
+ .where((0, drizzle_orm_1.eq)(this.table.id, id));
141
+ return Number(result[0]?.value ?? 0) > 0;
142
+ }
143
+ async save(entity) {
144
+ await this.toPersistenceMapper.build(entity);
145
+ entity.markAsPersisted();
146
+ }
147
+ async delete(entity) {
148
+ const id = entity.id.value;
149
+ try {
150
+ const result = await this.context
151
+ .delete(this.table)
152
+ .where((0, drizzle_orm_1.eq)(this.table.id, id))
153
+ .returning({ id: this.table.id });
154
+ if (!result || result.length === 0) {
155
+ throw new errors_1.NoRecordsAffectedError("Delete", this.model, String(id));
156
+ }
157
+ }
158
+ catch (error) {
159
+ if (error instanceof errors_1.NoRecordsAffectedError)
160
+ throw error;
161
+ throw error;
162
+ }
163
+ }
164
+ async deleteById(id) {
165
+ try {
166
+ const result = await this.context
167
+ .delete(this.table)
168
+ .where((0, drizzle_orm_1.eq)(this.table.id, id))
169
+ .returning({ id: this.table.id });
170
+ if (!result || result.length === 0) {
171
+ throw new errors_1.NoRecordsAffectedError("Delete", this.model, id);
172
+ }
173
+ }
174
+ catch (error) {
175
+ if (error instanceof errors_1.NoRecordsAffectedError)
176
+ throw error;
177
+ throw error;
178
+ }
179
+ }
180
+ async transaction(work) {
181
+ return this.uow.transaction(work);
182
+ }
183
+ markArrayOfAggregateWithClean(entities) {
184
+ for (const entity of entities) {
185
+ if (entity instanceof rich_domain_1.Aggregate) {
186
+ entity.markAsClean();
187
+ }
188
+ }
189
+ }
190
+ }
191
+ exports.DrizzleRepository = DrizzleRepository;
192
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":";;;AAAA,6CAAsD;AACtD,oDAM4B;AAC5B,iDAA8E;AAC9E,qCAAkD;AAElD,mDAAuE;AAUvE,MAAsB,iBAGpB,SAAQ,wBAAmB;IACR,EAAE,CAAgB;IAClB,KAAK,CAAM;IACX,cAAc,CAAgC;IAC9C,mBAAmB,CAAgC;IACnD,GAAG,CAAoB;IAE1C,YAAY,MAAsD;QAChE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;QACtD,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAc,OAAO;QACnB,MAAM,GAAG,GAAG,yBAAU,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC;QACvC,OAAO,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;IAChC,CAAC;IAYD;;OAEG;IACO,mBAAmB;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAA2B;QACpC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,mCAAmB,CAAC,KAAK,CACjE,QAAQ,EACR,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,mBAAmB,EAAE,CAC3B,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpD,IAAI,IAAoB,CAAC;QACzB,IAAI,KAAa,CAAC;QAElB,IAAI,UAAU,EAAE,CAAC;YACf,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChC,UAAU,CAAC,QAAQ,CAAC;oBAClB,KAAK;oBACL,OAAO;oBACP,KAAK;oBACL,MAAM;oBACN,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE;iBACjC,CAAC;gBACF,IAAI,CAAC,OAAO;qBACT,MAAM,CAAC,EAAE,KAAK,EAAE,IAAA,mBAAK,GAAE,EAAE,CAAC;qBAC1B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;qBAChB,KAAK,CAAC,KAAK,CAAC;qBACZ,IAAI,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;aAChD,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;YAEtE,IAAI,KAAK;gBAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;YACnE,IAAI,KAAK,KAAK,SAAS;gBAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,MAAM,KAAK,SAAS;gBAAE,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAErD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO;iBAC5B,MAAM,CAAC,EAAE,KAAK,EAAE,IAAA,mBAAK,GAAE,EAAE,CAAC;iBAC1B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,KAAK;gBAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAEnC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;YAC1E,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,QAAQ,GAAe,IAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACvD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAChC,CAAC;QAEF,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC;QAE7C,OAAO,6BAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpD,IAAI,IAAS,CAAC;QAEd,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC;gBAChC,KAAK,EAAE,IAAA,gBAAE,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;gBAC5B,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO;iBAC5B,MAAM,EAAE;iBACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;iBAChB,KAAK,CAAC,IAAA,gBAAE,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC5B,KAAK,CAAC,CAAC,CAAC,CAAC;YACZ,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACzB,CAAC;QAED,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,MAAM,YAAY,uBAAS,EAAE,CAAC;YAChC,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAa;QAC/B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEhC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpD,IAAI,IAAW,CAAC;QAEhB,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC;gBAC/B,KAAK,EAAE,IAAA,qBAAO,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC;gBAClC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO;iBACtB,MAAM,EAAE;iBACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;iBAChB,KAAK,CAAC,IAAA,qBAAO,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,QAAQ,GAAc,IAAI,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CACjD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAChC,CAAC;QAEF,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC;QAE7C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAA4B;QACtC,IAAI,KAAsB,CAAC;QAE3B,IAAI,QAAQ,EAAE,CAAC;YACb,CAAC,EAAE,KAAK,EAAE,GAAG,mCAAmB,CAAC,KAAK,CACpC,QAAQ,EACR,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,mBAAmB,EAAE,CAC3B,CAAC,CAAC;QACL,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAA,mBAAK,GAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,KAAK;YAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAE9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO;aAC9B,MAAM,CAAC,EAAE,KAAK,EAAE,IAAA,mBAAK,GAAE,EAAE,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;aAChB,KAAK,CAAC,IAAA,gBAAE,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAe;QACxB,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,eAAe,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAe;QAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO;iBAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;iBAClB,KAAK,CAAC,IAAA,gBAAE,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC5B,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YAEpC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,+BAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,YAAY,+BAAsB;gBAAE,MAAM,KAAK,CAAC;YACzD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO;iBAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;iBAClB,KAAK,CAAC,IAAA,gBAAE,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC5B,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YAEpC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,+BAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,YAAY,+BAAsB;gBAAE,MAAM,KAAK,CAAC;YACzD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAI,IAAsB;QACzC,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEO,6BAA6B,CAAC,QAAmB;QACvD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,IAAI,MAAM,YAAY,uBAAS,EAAE,CAAC;gBAChC,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAtOD,8CAsOC"}
@@ -0,0 +1,49 @@
1
+ import { AsyncLocalStorage } from "async_hooks";
2
+ /**
3
+ * Drizzle database instance type.
4
+ * Generic to support pg, mysql, sqlite, and other drivers.
5
+ */
6
+ export type DrizzleClient = {
7
+ transaction: <T>(fn: (tx: any) => Promise<T>) => Promise<T>;
8
+ query: Record<string, any>;
9
+ select: (...args: any[]) => any;
10
+ insert: (table: any) => any;
11
+ update: (table: any) => any;
12
+ delete: (table: any) => any;
13
+ [key: string]: any;
14
+ };
15
+ export type DrizzleTransactionClient = DrizzleClient;
16
+ export declare class DrizzleTransactionContext {
17
+ readonly client: DrizzleTransactionClient;
18
+ constructor(client: DrizzleTransactionClient);
19
+ }
20
+ export declare const UOWStorage: AsyncLocalStorage<{
21
+ ctx: DrizzleTransactionContext | null;
22
+ }>;
23
+ export declare class DrizzleUnitOfWork {
24
+ private readonly db;
25
+ constructor(db: DrizzleClient);
26
+ /**
27
+ * Get current transaction context (if any).
28
+ */
29
+ getCurrentContext(): DrizzleTransactionContext | null;
30
+ /**
31
+ * Check if currently inside a transaction.
32
+ */
33
+ isInTransaction(): boolean;
34
+ /**
35
+ * Execute work inside a transaction.
36
+ * If already in a transaction, reuses the existing context (idempotent nesting).
37
+ */
38
+ transaction<T>(work: () => Promise<T>): Promise<T>;
39
+ }
40
+ /**
41
+ * Decorator that wraps a method in a transaction.
42
+ * If already inside a transaction, reuses the existing one.
43
+ */
44
+ export declare function Transactional(inputUow?: DrizzleUnitOfWork): MethodDecorator;
45
+ /**
46
+ * Helper to get current transaction client from anywhere.
47
+ */
48
+ export declare function getCurrentDrizzleContext(): DrizzleTransactionClient | null;
49
+ //# sourceMappingURL=unit-of-work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work.d.ts","sourceRoot":"","sources":["../../src/unit-of-work.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;IAC5B,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;IAC5B,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAErD,qBAAa,yBAAyB;aACR,MAAM,EAAE,wBAAwB;gBAAhC,MAAM,EAAE,wBAAwB;CAC7D;AAED,eAAO,MAAM,UAAU;SAChB,yBAAyB,GAAG,IAAI;EACnC,CAAC;AAEL,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa;IAE9C;;OAEG;IACH,iBAAiB,IAAI,yBAAyB,GAAG,IAAI;IAIrD;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;;OAGG;IACG,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAazD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,eAAe,CA2B3E;AAwBD;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,wBAAwB,GAAG,IAAI,CAE1E"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DrizzleUnitOfWork = exports.UOWStorage = exports.DrizzleTransactionContext = void 0;
4
+ exports.Transactional = Transactional;
5
+ exports.getCurrentDrizzleContext = getCurrentDrizzleContext;
6
+ const async_hooks_1 = require("async_hooks");
7
+ class DrizzleTransactionContext {
8
+ client;
9
+ constructor(client) {
10
+ this.client = client;
11
+ }
12
+ }
13
+ exports.DrizzleTransactionContext = DrizzleTransactionContext;
14
+ exports.UOWStorage = new async_hooks_1.AsyncLocalStorage();
15
+ class DrizzleUnitOfWork {
16
+ db;
17
+ constructor(db) {
18
+ this.db = db;
19
+ }
20
+ /**
21
+ * Get current transaction context (if any).
22
+ */
23
+ getCurrentContext() {
24
+ return exports.UOWStorage.getStore()?.ctx ?? null;
25
+ }
26
+ /**
27
+ * Check if currently inside a transaction.
28
+ */
29
+ isInTransaction() {
30
+ return this.getCurrentContext() !== null;
31
+ }
32
+ /**
33
+ * Execute work inside a transaction.
34
+ * If already in a transaction, reuses the existing context (idempotent nesting).
35
+ */
36
+ async transaction(work) {
37
+ if (this.isInTransaction()) {
38
+ return work();
39
+ }
40
+ return this.db.transaction(async (tx) => {
41
+ const ctx = new DrizzleTransactionContext(tx);
42
+ return exports.UOWStorage.run({ ctx }, async () => {
43
+ return await work();
44
+ });
45
+ });
46
+ }
47
+ }
48
+ exports.DrizzleUnitOfWork = DrizzleUnitOfWork;
49
+ /**
50
+ * Decorator that wraps a method in a transaction.
51
+ * If already inside a transaction, reuses the existing one.
52
+ */
53
+ function Transactional(inputUow) {
54
+ return function (_target, _propertyKey, descriptor) {
55
+ const original = descriptor.value;
56
+ descriptor.value = async function (...args) {
57
+ if (exports.UOWStorage.getStore()?.ctx) {
58
+ return original.apply(this, args);
59
+ }
60
+ const uow = inputUow ?? findUnitOfWork(this);
61
+ if (!uow) {
62
+ throw new Error(`@Transactional: DrizzleUnitOfWork not found in ${this.constructor.name} instance. ` +
63
+ "Ensure your class has a 'uow' property. eg: constructor(private readonly uow: DrizzleUnitOfWork) {}");
64
+ }
65
+ return uow.transaction(() => original.apply(this, args));
66
+ };
67
+ return descriptor;
68
+ };
69
+ }
70
+ /**
71
+ * Find DrizzleUnitOfWork in instance.
72
+ */
73
+ function findUnitOfWork(instance) {
74
+ if (instance.uow instanceof DrizzleUnitOfWork) {
75
+ return instance.uow;
76
+ }
77
+ if (instance._uow instanceof DrizzleUnitOfWork) {
78
+ return instance._uow;
79
+ }
80
+ for (const key of Object.keys(instance)) {
81
+ const value = instance[key];
82
+ if (value instanceof DrizzleUnitOfWork) {
83
+ return value;
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ /**
89
+ * Helper to get current transaction client from anywhere.
90
+ */
91
+ function getCurrentDrizzleContext() {
92
+ return exports.UOWStorage.getStore()?.ctx?.client ?? null;
93
+ }
94
+ //# sourceMappingURL=unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work.js","sourceRoot":"","sources":["../../src/unit-of-work.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { AggregateChanges, EntitySchemaRegistry } from "@woltz/rich-domain";
2
+ import { DrizzleClient } from "./unit-of-work";
3
+ export interface DrizzleBatchExecutorConfig {
4
+ registry: EntitySchemaRegistry;
5
+ db: DrizzleClient;
6
+ tableMap: Map<string, any>;
7
+ }
8
+ export declare class DrizzleBatchExecutor {
9
+ private readonly config;
10
+ constructor(config: DrizzleBatchExecutorConfig);
11
+ /**
12
+ * Execute all batch operations in order:
13
+ * 1. Deletes (leaf → root, sorted by depth DESC)
14
+ * 2. Creates (root → leaf, sorted by depth ASC)
15
+ * 3. Updates (any order)
16
+ */
17
+ execute(changes: AggregateChanges): Promise<void>;
18
+ private executeDeletes;
19
+ private executeDeleteOwned;
20
+ private executeJunctionDelete;
21
+ private executeCreates;
22
+ private executeCreateOwned;
23
+ private executeJunctionCreate;
24
+ private executeUpdates;
25
+ private getTable;
26
+ private getJunctionTable;
27
+ private extractId;
28
+ }
29
+ export declare function executeBatch(db: DrizzleClient, changes: AggregateChanges, config: Omit<DrizzleBatchExecutorConfig, "db">): Promise<void>;
30
+ //# sourceMappingURL=batch-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-executor.d.ts","sourceRoot":"","sources":["../../src/batch-executor.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EAKrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO/C,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,EAAE,EAAE,aAAa,CAAC;IAClB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,0BAA0B;IAE/D;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;YAUzC,cAAc;YAgCd,kBAAkB;YAoBlB,qBAAqB;YAsCrB,cAAc;YA2Bd,kBAAkB;YA6BlB,qBAAqB;YA0DrB,cAAc;IA+B5B,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,SAAS;CASlB;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,aAAa,EACjB,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,IAAI,CAAC,0BAA0B,EAAE,IAAI,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAGf"}