@fragno-dev/db 0.0.1 → 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 (200) hide show
  1. package/.turbo/turbo-build.log +137 -13
  2. package/.turbo/turbo-test.log +36 -0
  3. package/CHANGELOG.md +7 -0
  4. package/dist/adapters/adapters.d.ts +18 -0
  5. package/dist/adapters/adapters.d.ts.map +1 -0
  6. package/dist/adapters/drizzle/drizzle-adapter.d.ts +21 -0
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -0
  8. package/dist/adapters/drizzle/drizzle-adapter.js +62 -0
  9. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -0
  10. package/dist/adapters/drizzle/drizzle-query.d.ts +17 -0
  11. package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/drizzle-query.js +139 -0
  13. package/dist/adapters/drizzle/drizzle-query.js.map +1 -0
  14. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +9 -0
  15. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/drizzle-uow-compiler.js +300 -0
  17. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -0
  18. package/dist/adapters/drizzle/drizzle-uow-decoder.js +82 -0
  19. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -0
  20. package/dist/adapters/drizzle/drizzle-uow-executor.js +125 -0
  21. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -0
  22. package/dist/adapters/drizzle/generate.js +273 -0
  23. package/dist/adapters/drizzle/generate.js.map +1 -0
  24. package/dist/adapters/drizzle/join-column-utils.js +28 -0
  25. package/dist/adapters/drizzle/join-column-utils.js.map +1 -0
  26. package/dist/adapters/drizzle/shared.js +11 -0
  27. package/dist/adapters/drizzle/shared.js.map +1 -0
  28. package/dist/adapters/kysely/kysely-adapter.d.ts +23 -0
  29. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -0
  30. package/dist/adapters/kysely/kysely-adapter.js +119 -0
  31. package/dist/adapters/kysely/kysely-adapter.js.map +1 -0
  32. package/dist/adapters/kysely/kysely-query-builder.js +306 -0
  33. package/dist/adapters/kysely/kysely-query-builder.js.map +1 -0
  34. package/dist/adapters/kysely/kysely-query-compiler.js +67 -0
  35. package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -0
  36. package/dist/adapters/kysely/kysely-query.js +158 -0
  37. package/dist/adapters/kysely/kysely-query.js.map +1 -0
  38. package/dist/adapters/kysely/kysely-uow-compiler.js +139 -0
  39. package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -0
  40. package/dist/adapters/kysely/kysely-uow-executor.js +89 -0
  41. package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -0
  42. package/dist/adapters/kysely/migration/execute.js +176 -0
  43. package/dist/adapters/kysely/migration/execute.js.map +1 -0
  44. package/dist/fragment.d.ts +54 -0
  45. package/dist/fragment.d.ts.map +1 -0
  46. package/dist/fragment.js +92 -0
  47. package/dist/fragment.js.map +1 -0
  48. package/dist/id.d.ts +2 -0
  49. package/dist/migration-engine/auto-from-schema.js +116 -0
  50. package/dist/migration-engine/auto-from-schema.js.map +1 -0
  51. package/dist/migration-engine/create.d.ts +41 -0
  52. package/dist/migration-engine/create.d.ts.map +1 -0
  53. package/dist/migration-engine/create.js +58 -0
  54. package/dist/migration-engine/create.js.map +1 -0
  55. package/dist/migration-engine/shared.d.ts +90 -0
  56. package/dist/migration-engine/shared.d.ts.map +1 -0
  57. package/dist/migration-engine/shared.js +8 -0
  58. package/dist/migration-engine/shared.js.map +1 -0
  59. package/dist/mod.d.ts +55 -2
  60. package/dist/mod.d.ts.map +1 -1
  61. package/dist/mod.js +111 -2
  62. package/dist/mod.js.map +1 -1
  63. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js +108 -0
  64. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js.map +1 -0
  65. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js +55 -0
  66. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js.map +1 -0
  67. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js +18 -0
  68. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js.map +1 -0
  69. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js +183 -0
  70. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js.map +1 -0
  71. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js +58 -0
  72. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js.map +1 -0
  73. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js +68 -0
  74. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +1 -0
  75. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js +56 -0
  76. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +1 -0
  77. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js +65 -0
  78. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js.map +1 -0
  79. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js +81 -0
  80. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js.map +1 -0
  81. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js +13 -0
  82. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js.map +1 -0
  83. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js +10 -0
  84. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js.map +1 -0
  85. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js +372 -0
  86. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js.map +1 -0
  87. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js +23 -0
  88. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js.map +1 -0
  89. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js +62 -0
  90. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js.map +1 -0
  91. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js +6 -0
  92. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js.map +1 -0
  93. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js +8 -0
  94. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js.map +1 -0
  95. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js +8 -0
  96. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js.map +1 -0
  97. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js +6 -0
  98. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js.map +1 -0
  99. package/dist/query/condition-builder.d.ts +41 -0
  100. package/dist/query/condition-builder.d.ts.map +1 -0
  101. package/dist/query/condition-builder.js +93 -0
  102. package/dist/query/condition-builder.js.map +1 -0
  103. package/dist/query/cursor.d.ts +88 -0
  104. package/dist/query/cursor.d.ts.map +1 -0
  105. package/dist/query/cursor.js +103 -0
  106. package/dist/query/cursor.js.map +1 -0
  107. package/dist/query/orm/orm.d.ts +18 -0
  108. package/dist/query/orm/orm.d.ts.map +1 -0
  109. package/dist/query/orm/orm.js +48 -0
  110. package/dist/query/orm/orm.js.map +1 -0
  111. package/dist/query/query.d.ts +79 -0
  112. package/dist/query/query.d.ts.map +1 -0
  113. package/dist/query/query.js +1 -0
  114. package/dist/query/result-transform.js +155 -0
  115. package/dist/query/result-transform.js.map +1 -0
  116. package/dist/query/unit-of-work.d.ts +435 -0
  117. package/dist/query/unit-of-work.d.ts.map +1 -0
  118. package/dist/query/unit-of-work.js +549 -0
  119. package/dist/query/unit-of-work.js.map +1 -0
  120. package/dist/schema/create.d.ts +273 -116
  121. package/dist/schema/create.d.ts.map +1 -1
  122. package/dist/schema/create.js +410 -222
  123. package/dist/schema/create.js.map +1 -1
  124. package/dist/schema/serialize.js +101 -0
  125. package/dist/schema/serialize.js.map +1 -0
  126. package/dist/schema-generator/schema-generator.d.ts +15 -0
  127. package/dist/schema-generator/schema-generator.d.ts.map +1 -0
  128. package/dist/shared/providers.d.ts +6 -0
  129. package/dist/shared/providers.d.ts.map +1 -0
  130. package/dist/util/import-generator.js +26 -0
  131. package/dist/util/import-generator.js.map +1 -0
  132. package/dist/util/parse.js +15 -0
  133. package/dist/util/parse.js.map +1 -0
  134. package/dist/util/types.d.ts +8 -0
  135. package/dist/util/types.d.ts.map +1 -0
  136. package/package.json +63 -2
  137. package/src/adapters/adapters.ts +22 -0
  138. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +433 -0
  139. package/src/adapters/drizzle/drizzle-adapter.test.ts +122 -0
  140. package/src/adapters/drizzle/drizzle-adapter.ts +118 -0
  141. package/src/adapters/drizzle/drizzle-query.ts +234 -0
  142. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +1084 -0
  143. package/src/adapters/drizzle/drizzle-uow-compiler.ts +546 -0
  144. package/src/adapters/drizzle/drizzle-uow-decoder.ts +165 -0
  145. package/src/adapters/drizzle/drizzle-uow-executor.ts +213 -0
  146. package/src/adapters/drizzle/generate.test.ts +643 -0
  147. package/src/adapters/drizzle/generate.ts +481 -0
  148. package/src/adapters/drizzle/join-column-utils.test.ts +79 -0
  149. package/src/adapters/drizzle/join-column-utils.ts +39 -0
  150. package/src/adapters/drizzle/migrate-drizzle.test.ts +226 -0
  151. package/src/adapters/drizzle/shared.ts +22 -0
  152. package/src/adapters/drizzle/test-utils.ts +56 -0
  153. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +789 -0
  154. package/src/adapters/kysely/kysely-adapter.ts +196 -0
  155. package/src/adapters/kysely/kysely-query-builder.test.ts +1344 -0
  156. package/src/adapters/kysely/kysely-query-builder.ts +611 -0
  157. package/src/adapters/kysely/kysely-query-compiler.ts +124 -0
  158. package/src/adapters/kysely/kysely-query.ts +254 -0
  159. package/src/adapters/kysely/kysely-uow-compiler.test.ts +916 -0
  160. package/src/adapters/kysely/kysely-uow-compiler.ts +271 -0
  161. package/src/adapters/kysely/kysely-uow-executor.ts +149 -0
  162. package/src/adapters/kysely/kysely-uow-joins.test.ts +811 -0
  163. package/src/adapters/kysely/migration/execute-mysql.test.ts +1173 -0
  164. package/src/adapters/kysely/migration/execute-postgres.test.ts +2657 -0
  165. package/src/adapters/kysely/migration/execute.ts +382 -0
  166. package/src/adapters/kysely/migration/kysely-migrator.test.ts +197 -0
  167. package/src/fragment.test.ts +287 -0
  168. package/src/fragment.ts +198 -0
  169. package/src/migration-engine/auto-from-schema.test.ts +118 -58
  170. package/src/migration-engine/auto-from-schema.ts +103 -32
  171. package/src/migration-engine/create.test.ts +34 -46
  172. package/src/migration-engine/create.ts +41 -26
  173. package/src/migration-engine/shared.ts +26 -6
  174. package/src/mod.ts +197 -1
  175. package/src/query/condition-builder.test.ts +379 -0
  176. package/src/query/condition-builder.ts +294 -0
  177. package/src/query/cursor.test.ts +296 -0
  178. package/src/query/cursor.ts +147 -0
  179. package/src/query/orm/orm.ts +92 -0
  180. package/src/query/query-type.test.ts +429 -0
  181. package/src/query/query.ts +200 -0
  182. package/src/query/result-transform.test.ts +795 -0
  183. package/src/query/result-transform.ts +247 -0
  184. package/src/query/unit-of-work-types.test.ts +192 -0
  185. package/src/query/unit-of-work.test.ts +947 -0
  186. package/src/query/unit-of-work.ts +1199 -0
  187. package/src/schema/create.test.ts +653 -110
  188. package/src/schema/create.ts +708 -337
  189. package/src/schema/serialize.test.ts +559 -0
  190. package/src/schema/serialize.ts +359 -0
  191. package/src/schema-generator/schema-generator.ts +12 -0
  192. package/src/shared/config.ts +0 -8
  193. package/src/util/import-generator.ts +28 -0
  194. package/src/util/parse.ts +16 -0
  195. package/src/util/types.ts +4 -0
  196. package/tsconfig.json +1 -1
  197. package/tsdown.config.ts +11 -1
  198. package/vitest.config.ts +3 -0
  199. /package/dist/{cuid.js → id.js} +0 -0
  200. /package/src/{cuid.ts → id.ts} +0 -0
@@ -0,0 +1,213 @@
1
+ import { SQL, StringChunk, sql, type SQLChunk } from "drizzle-orm";
2
+ import type { CompiledMutation, MutationResult } from "../../query/unit-of-work";
3
+ import type { DBType } from "./shared";
4
+ import type { DrizzleCompiledQuery } from "./drizzle-uow-compiler";
5
+ import type { DrizzleResult } from "./drizzle-query";
6
+
7
+ /**
8
+ * Convert a DrizzleCompiledQuery (SQL string + params) to a Drizzle SQL object
9
+ *
10
+ * This reconstructs the SQL object with proper parameter chunks by parsing
11
+ * the SQL string and replacing placeholders ($1, $2, etc.) with Param objects.
12
+ * Uses Drizzle's exported classes (StringChunk, Param, SQL) to build the queryChunks.
13
+ */
14
+ function toSQL(query: DrizzleCompiledQuery): SQL {
15
+ const { sql: sqlString, params } = query;
16
+
17
+ // Match parameter placeholders like $1, $2, etc.
18
+ const placeholderRegex = /\$(\d+)/g;
19
+ const queryChunks: SQLChunk[] = [];
20
+ let lastIndex = 0;
21
+ let match: RegExpExecArray | null;
22
+
23
+ while ((match = placeholderRegex.exec(sqlString)) !== null) {
24
+ // Add the string chunk before the placeholder
25
+ const textBefore = sqlString.substring(lastIndex, match.index);
26
+ if (textBefore) {
27
+ queryChunks.push(new StringChunk(textBefore));
28
+ }
29
+
30
+ // Add the parameter value as a Param
31
+ const paramIndex = parseInt(match[1]!, 10) - 1; // $1 is index 0
32
+ queryChunks.push(sql.param(params[paramIndex]));
33
+
34
+ lastIndex = match.index + match[0].length;
35
+ }
36
+
37
+ // Add any remaining string after the last placeholder
38
+ const textAfter = sqlString.substring(lastIndex);
39
+ if (textAfter) {
40
+ queryChunks.push(new StringChunk(textAfter));
41
+ }
42
+
43
+ // Construct SQL object directly with queryChunks (same pattern as sql`` tagged template)
44
+ // Safe: We're reusing Drizzle's SQL constructor the same way the sql`` function does
45
+ return new SQL(queryChunks);
46
+ }
47
+
48
+ /**
49
+ * Get the number of affected rows from a Drizzle query result
50
+ */
51
+ function getAffectedRows(result: unknown): number {
52
+ // Drizzle returns different formats depending on the database
53
+ // For MySQL: array with affectedRows property
54
+ // For PostgreSQL/SQLite: array with rowCount or similar
55
+ if (Array.isArray(result)) {
56
+ // This is likely a select/returning result
57
+ return result.length;
58
+ }
59
+
60
+ // Check for MySQL-style result
61
+ if (
62
+ result &&
63
+ typeof result === "object" &&
64
+ "affectedRows" in result &&
65
+ typeof result["affectedRows"] === "number"
66
+ ) {
67
+ return result["affectedRows"];
68
+ }
69
+
70
+ // Check for PostgreSQL-style result with rowCount
71
+ if (
72
+ result &&
73
+ typeof result === "object" &&
74
+ "rowCount" in result &&
75
+ (typeof result["rowCount"] === "number" || typeof result["rowCount"] === "bigint")
76
+ ) {
77
+ const rowCount = result["rowCount"];
78
+ if (rowCount > Number.MAX_SAFE_INTEGER) {
79
+ throw new Error(`rowCount BigInt value ${rowCount.toString()} exceeds JS safe integer range`);
80
+ }
81
+ return Number(rowCount);
82
+ }
83
+
84
+ // For update/delete operations, Drizzle might return an object with affected rows info
85
+ // Try to extract it from common patterns
86
+ if (result && typeof result === "object") {
87
+ // Check for changes/changes count
88
+ if ("changes" in result && typeof result["changes"] === "number") {
89
+ return result["changes"];
90
+ }
91
+ }
92
+
93
+ throw new Error(`Unable to determine affected rows from result: ${JSON.stringify(result)}`);
94
+ }
95
+
96
+ /**
97
+ * Execute the retrieval phase of a Unit of Work using Drizzle
98
+ *
99
+ * All retrieval queries are executed inside a single transaction to ensure
100
+ * snapshot isolation - all reads see a consistent view of the database.
101
+ *
102
+ * @param db - The Drizzle database instance
103
+ * @param retrievalBatch - Array of Drizzle SQL queries
104
+ * @returns Array of query results matching the retrieval operations order
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * const retrievalResults = await executeDrizzleRetrievalPhase(db, compiled.retrievalBatch);
109
+ * const [users, posts] = retrievalResults;
110
+ * ```
111
+ */
112
+ export async function executeDrizzleRetrievalPhase(
113
+ db: DBType,
114
+ retrievalBatch: DrizzleCompiledQuery[],
115
+ ): Promise<DrizzleResult[]> {
116
+ // If no retrieval operations, return empty array immediately
117
+ if (retrievalBatch.length === 0) {
118
+ return [];
119
+ }
120
+
121
+ const retrievalResults: DrizzleResult[] = [];
122
+
123
+ // Execute all retrieval queries inside a transaction for snapshot isolation
124
+ await db.transaction(async (tx) => {
125
+ for (const query of retrievalBatch) {
126
+ const result = (await tx.execute(toSQL(query))) as DrizzleResult;
127
+ retrievalResults.push(result);
128
+ }
129
+ });
130
+
131
+ return retrievalResults;
132
+ }
133
+
134
+ /**
135
+ * Execute the mutation phase of a Unit of Work using Drizzle
136
+ *
137
+ * All mutation queries are executed in a transaction with optimistic locking.
138
+ * If any version check fails, the entire transaction is rolled back and
139
+ * success=false is returned.
140
+ *
141
+ * @param db - The Drizzle database instance
142
+ * @param mutationBatch - Array of compiled mutation SQL queries with expected affected rows
143
+ * @returns Object with success flag and internal IDs from create operations
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * const { success } = await executeDrizzleMutationPhase(db, compiled.mutationBatch);
148
+ * if (!success) {
149
+ * console.log("Version conflict detected, retrying...");
150
+ * }
151
+ * ```
152
+ */
153
+ export async function executeDrizzleMutationPhase(
154
+ db: DBType,
155
+ mutationBatch: CompiledMutation<DrizzleCompiledQuery>[],
156
+ ): Promise<MutationResult> {
157
+ // If there are no mutations, return success immediately
158
+ if (mutationBatch.length === 0) {
159
+ return { success: true, createdInternalIds: [] };
160
+ }
161
+
162
+ const createdInternalIds: (bigint | null)[] = [];
163
+
164
+ // Execute mutation batch in a transaction
165
+ try {
166
+ await db.transaction(async (tx) => {
167
+ for (const compiledMutation of mutationBatch) {
168
+ const result = await tx.execute(toSQL(compiledMutation.query));
169
+
170
+ // For creates (expectedAffectedRows === null), try to extract internal ID
171
+ if (compiledMutation.expectedAffectedRows === null) {
172
+ // Check if result is an array with rows (RETURNING clause supported)
173
+ if (Array.isArray(result) && result.length > 0) {
174
+ const row = result[0] as Record<string, unknown>;
175
+ // Look for _internalId column in the returned row
176
+ if ("_internalId" in row || "_internal_id" in row) {
177
+ const internalId = (row["_internalId"] ?? row["_internal_id"]) as bigint;
178
+ createdInternalIds.push(internalId);
179
+ } else {
180
+ // RETURNING supported but _internalId not found
181
+ createdInternalIds.push(null);
182
+ }
183
+ } else {
184
+ // No RETURNING support (e.g., MySQL)
185
+ createdInternalIds.push(null);
186
+ }
187
+ } else {
188
+ // Check affected rows for updates/deletes
189
+ const affectedRows = getAffectedRows(result);
190
+
191
+ if (affectedRows !== compiledMutation.expectedAffectedRows) {
192
+ // Version conflict detected - the UPDATE/DELETE didn't affect the expected number of rows
193
+ // This means either the row doesn't exist or the version has changed
194
+ throw new Error(
195
+ `Version conflict: expected ${compiledMutation.expectedAffectedRows} rows affected, but got ${affectedRows}`,
196
+ );
197
+ }
198
+ }
199
+ }
200
+ });
201
+
202
+ return { success: true, createdInternalIds };
203
+ } catch (error) {
204
+ // Transaction failed - could be version conflict or other constraint violation
205
+ // Return success=false to indicate the UOW should be retried
206
+ if (error instanceof Error && error.message.includes("Version conflict")) {
207
+ return { success: false };
208
+ }
209
+
210
+ // Other database errors should be thrown
211
+ throw error;
212
+ }
213
+ }