@buenojs/bueno 0.8.4 → 0.8.6

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 (234) hide show
  1. package/README.md +264 -17
  2. package/dist/cli/{index.js → bin.js} +413 -332
  3. package/dist/container/index.js +273 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/graphql/index.js +2156 -0
  8. package/dist/health/index.js +364 -0
  9. package/dist/i18n/index.js +345 -0
  10. package/dist/index.js +9694 -5047
  11. package/dist/jobs/index.js +819 -0
  12. package/dist/lock/index.js +367 -0
  13. package/dist/logger/index.js +281 -0
  14. package/dist/metrics/index.js +289 -0
  15. package/dist/middleware/index.js +77 -0
  16. package/dist/migrations/index.js +571 -0
  17. package/dist/modules/index.js +3411 -0
  18. package/dist/notification/index.js +484 -0
  19. package/dist/observability/index.js +331 -0
  20. package/dist/openapi/index.js +795 -0
  21. package/dist/orm/index.js +1356 -0
  22. package/dist/router/index.js +886 -0
  23. package/dist/rpc/index.js +691 -0
  24. package/dist/schema/index.js +400 -0
  25. package/dist/telemetry/index.js +595 -0
  26. package/dist/template/index.js +640 -0
  27. package/dist/templates/index.js +640 -0
  28. package/dist/testing/index.js +1111 -0
  29. package/dist/types/index.js +60 -0
  30. package/llms.txt +231 -0
  31. package/package.json +125 -27
  32. package/src/cache/index.ts +2 -1
  33. package/src/cli/ARCHITECTURE.md +3 -3
  34. package/src/cli/bin.ts +2 -2
  35. package/src/cli/commands/build.ts +183 -165
  36. package/src/cli/commands/dev.ts +96 -89
  37. package/src/cli/commands/generate.ts +142 -111
  38. package/src/cli/commands/help.ts +20 -16
  39. package/src/cli/commands/index.ts +3 -6
  40. package/src/cli/commands/migration.ts +124 -105
  41. package/src/cli/commands/new.ts +294 -232
  42. package/src/cli/commands/start.ts +81 -79
  43. package/src/cli/core/args.ts +68 -50
  44. package/src/cli/core/console.ts +89 -95
  45. package/src/cli/core/index.ts +4 -4
  46. package/src/cli/core/prompt.ts +65 -62
  47. package/src/cli/core/spinner.ts +23 -20
  48. package/src/cli/index.ts +46 -38
  49. package/src/cli/templates/database/index.ts +37 -18
  50. package/src/cli/templates/database/mysql.ts +3 -3
  51. package/src/cli/templates/database/none.ts +2 -2
  52. package/src/cli/templates/database/postgresql.ts +3 -3
  53. package/src/cli/templates/database/sqlite.ts +3 -3
  54. package/src/cli/templates/deploy.ts +29 -26
  55. package/src/cli/templates/docker.ts +41 -30
  56. package/src/cli/templates/frontend/index.ts +33 -15
  57. package/src/cli/templates/frontend/none.ts +2 -2
  58. package/src/cli/templates/frontend/react.ts +18 -18
  59. package/src/cli/templates/frontend/solid.ts +15 -15
  60. package/src/cli/templates/frontend/svelte.ts +17 -17
  61. package/src/cli/templates/frontend/vue.ts +15 -15
  62. package/src/cli/templates/generators/index.ts +29 -29
  63. package/src/cli/templates/generators/types.ts +21 -21
  64. package/src/cli/templates/index.ts +6 -6
  65. package/src/cli/templates/project/api.ts +37 -36
  66. package/src/cli/templates/project/default.ts +25 -25
  67. package/src/cli/templates/project/fullstack.ts +28 -26
  68. package/src/cli/templates/project/index.ts +55 -16
  69. package/src/cli/templates/project/minimal.ts +17 -12
  70. package/src/cli/templates/project/types.ts +10 -5
  71. package/src/cli/templates/project/website.ts +15 -15
  72. package/src/cli/utils/fs.ts +55 -41
  73. package/src/cli/utils/index.ts +3 -3
  74. package/src/cli/utils/strings.ts +47 -33
  75. package/src/cli/utils/version.ts +14 -8
  76. package/src/config/env-validation.ts +100 -0
  77. package/src/config/env.ts +169 -41
  78. package/src/config/index.ts +28 -20
  79. package/src/config/loader.ts +25 -16
  80. package/src/config/merge.ts +21 -10
  81. package/src/config/types.ts +566 -25
  82. package/src/config/validation.ts +215 -7
  83. package/src/container/forward-ref.ts +22 -22
  84. package/src/container/index.ts +34 -12
  85. package/src/context/index.ts +11 -1
  86. package/src/database/index.ts +7 -190
  87. package/src/database/orm/builder.ts +457 -0
  88. package/src/database/orm/casts/index.ts +130 -0
  89. package/src/database/orm/casts/types.ts +25 -0
  90. package/src/database/orm/compiler.ts +304 -0
  91. package/src/database/orm/hooks/index.ts +114 -0
  92. package/src/database/orm/index.ts +61 -0
  93. package/src/database/orm/model-registry.ts +59 -0
  94. package/src/database/orm/model.ts +821 -0
  95. package/src/database/orm/relationships/base.ts +146 -0
  96. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  97. package/src/database/orm/relationships/belongs-to.ts +56 -0
  98. package/src/database/orm/relationships/has-many.ts +45 -0
  99. package/src/database/orm/relationships/has-one.ts +41 -0
  100. package/src/database/orm/relationships/index.ts +11 -0
  101. package/src/database/orm/scopes/index.ts +55 -0
  102. package/src/events/__tests__/event-system.test.ts +235 -0
  103. package/src/events/config.ts +238 -0
  104. package/src/events/example-usage.ts +185 -0
  105. package/src/events/index.ts +278 -0
  106. package/src/events/manager.ts +385 -0
  107. package/src/events/registry.ts +182 -0
  108. package/src/events/types.ts +124 -0
  109. package/src/frontend/api-routes.ts +65 -23
  110. package/src/frontend/bundler.ts +76 -34
  111. package/src/frontend/console-client.ts +2 -2
  112. package/src/frontend/console-stream.ts +94 -38
  113. package/src/frontend/dev-server.ts +94 -46
  114. package/src/frontend/file-router.ts +61 -19
  115. package/src/frontend/frameworks/index.ts +37 -10
  116. package/src/frontend/frameworks/react.ts +10 -8
  117. package/src/frontend/frameworks/solid.ts +11 -9
  118. package/src/frontend/frameworks/svelte.ts +15 -9
  119. package/src/frontend/frameworks/vue.ts +13 -11
  120. package/src/frontend/hmr-client.ts +12 -10
  121. package/src/frontend/hmr.ts +146 -103
  122. package/src/frontend/index.ts +14 -5
  123. package/src/frontend/islands.ts +41 -22
  124. package/src/frontend/isr.ts +59 -37
  125. package/src/frontend/layout.ts +36 -21
  126. package/src/frontend/ssr/react.ts +74 -27
  127. package/src/frontend/ssr/solid.ts +54 -20
  128. package/src/frontend/ssr/svelte.ts +48 -14
  129. package/src/frontend/ssr/vue.ts +50 -18
  130. package/src/frontend/ssr.ts +83 -39
  131. package/src/frontend/types.ts +91 -56
  132. package/src/graphql/built-in-engine.ts +598 -0
  133. package/src/graphql/context-builder.ts +110 -0
  134. package/src/graphql/decorators.ts +358 -0
  135. package/src/graphql/execution-pipeline.ts +227 -0
  136. package/src/graphql/graphql-module.ts +563 -0
  137. package/src/graphql/index.ts +101 -0
  138. package/src/graphql/metadata.ts +237 -0
  139. package/src/graphql/schema-builder.ts +319 -0
  140. package/src/graphql/subscription-handler.ts +283 -0
  141. package/src/graphql/types.ts +324 -0
  142. package/src/health/index.ts +21 -9
  143. package/src/i18n/engine.ts +305 -0
  144. package/src/i18n/index.ts +38 -0
  145. package/src/i18n/loader.ts +218 -0
  146. package/src/i18n/middleware.ts +164 -0
  147. package/src/i18n/negotiator.ts +162 -0
  148. package/src/i18n/types.ts +158 -0
  149. package/src/index.ts +182 -27
  150. package/src/jobs/drivers/memory.ts +315 -0
  151. package/src/jobs/drivers/redis.ts +459 -0
  152. package/src/jobs/index.ts +30 -0
  153. package/src/jobs/queue.ts +281 -0
  154. package/src/jobs/types.ts +295 -0
  155. package/src/jobs/worker.ts +380 -0
  156. package/src/logger/index.ts +1 -3
  157. package/src/logger/transports/index.ts +62 -22
  158. package/src/metrics/index.ts +25 -16
  159. package/src/migrations/index.ts +9 -0
  160. package/src/modules/filters.ts +13 -17
  161. package/src/modules/guards.ts +49 -26
  162. package/src/modules/index.ts +457 -299
  163. package/src/modules/interceptors.ts +58 -20
  164. package/src/modules/lazy.ts +11 -19
  165. package/src/modules/lifecycle.ts +15 -7
  166. package/src/modules/metadata.ts +15 -5
  167. package/src/modules/pipes.ts +94 -72
  168. package/src/notification/channels/base.ts +68 -0
  169. package/src/notification/channels/email.ts +105 -0
  170. package/src/notification/channels/push.ts +104 -0
  171. package/src/notification/channels/sms.ts +105 -0
  172. package/src/notification/channels/whatsapp.ts +104 -0
  173. package/src/notification/index.ts +48 -0
  174. package/src/notification/service.ts +354 -0
  175. package/src/notification/types.ts +344 -0
  176. package/src/observability/__tests__/observability.test.ts +483 -0
  177. package/src/observability/breadcrumbs.ts +114 -0
  178. package/src/observability/index.ts +136 -0
  179. package/src/observability/interceptor.ts +85 -0
  180. package/src/observability/service.ts +303 -0
  181. package/src/observability/trace.ts +37 -0
  182. package/src/observability/types.ts +196 -0
  183. package/src/openapi/__tests__/decorators.test.ts +335 -0
  184. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  185. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  186. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  187. package/src/openapi/decorators.ts +328 -0
  188. package/src/openapi/document-builder.ts +274 -0
  189. package/src/openapi/index.ts +112 -0
  190. package/src/openapi/metadata.ts +112 -0
  191. package/src/openapi/route-scanner.ts +289 -0
  192. package/src/openapi/schema-generator.ts +256 -0
  193. package/src/openapi/swagger-module.ts +166 -0
  194. package/src/openapi/types.ts +398 -0
  195. package/src/orm/index.ts +10 -0
  196. package/src/rpc/index.ts +3 -1
  197. package/src/schema/index.ts +9 -0
  198. package/src/security/index.ts +15 -6
  199. package/src/ssg/index.ts +9 -8
  200. package/src/telemetry/index.ts +76 -22
  201. package/src/template/index.ts +7 -0
  202. package/src/templates/engine.ts +224 -0
  203. package/src/templates/index.ts +9 -0
  204. package/src/templates/loader.ts +331 -0
  205. package/src/templates/renderers/markdown.ts +212 -0
  206. package/src/templates/renderers/simple.ts +269 -0
  207. package/src/templates/types.ts +154 -0
  208. package/src/testing/index.ts +100 -27
  209. package/src/types/optional-deps.d.ts +347 -187
  210. package/src/validation/index.ts +92 -2
  211. package/src/validation/schemas.ts +536 -0
  212. package/tests/integration/cli.test.ts +19 -19
  213. package/tests/integration/fullstack.test.ts +4 -4
  214. package/tests/unit/cli.test.ts +1 -1
  215. package/tests/unit/database.test.ts +2 -72
  216. package/tests/unit/env-validation.test.ts +166 -0
  217. package/tests/unit/events.test.ts +910 -0
  218. package/tests/unit/graphql.test.ts +991 -0
  219. package/tests/unit/i18n.test.ts +455 -0
  220. package/tests/unit/jobs.test.ts +493 -0
  221. package/tests/unit/notification.test.ts +988 -0
  222. package/tests/unit/observability.test.ts +453 -0
  223. package/tests/unit/orm/builder.test.ts +323 -0
  224. package/tests/unit/orm/casts.test.ts +179 -0
  225. package/tests/unit/orm/compiler.test.ts +220 -0
  226. package/tests/unit/orm/eager-loading.test.ts +285 -0
  227. package/tests/unit/orm/hooks.test.ts +191 -0
  228. package/tests/unit/orm/model.test.ts +373 -0
  229. package/tests/unit/orm/relationships.test.ts +303 -0
  230. package/tests/unit/orm/scopes.test.ts +74 -0
  231. package/tests/unit/templates-simple.test.ts +53 -0
  232. package/tests/unit/templates.test.ts +454 -0
  233. package/tests/unit/validation.test.ts +18 -24
  234. package/tsconfig.json +11 -3
@@ -0,0 +1,493 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
15
+ r = Reflect.decorate(decorators, target, key, desc);
16
+ else
17
+ for (var i = decorators.length - 1;i >= 0; i--)
18
+ if (d = decorators[i])
19
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ };
22
+ var __legacyMetadataTS = (k, v) => {
23
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
24
+ return Reflect.metadata(k, v);
25
+ };
26
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
27
+ var __require = import.meta.require;
28
+
29
+ // src/database/index.ts
30
+ function detectDriver(url) {
31
+ if (url.startsWith("mysql://") || url.startsWith("mysql2://")) {
32
+ return "mysql";
33
+ }
34
+ if (url.startsWith("sqlite://") || url.startsWith("file://") || url.startsWith("file:") || url === ":memory:" || url.endsWith(".db") || url.endsWith(".sqlite") || url.endsWith(".sqlite3")) {
35
+ return "sqlite";
36
+ }
37
+ return "postgresql";
38
+ }
39
+ function detectOperationType(sql) {
40
+ const normalizedSql = sql.trim().toUpperCase();
41
+ if (normalizedSql.startsWith("SELECT"))
42
+ return "query";
43
+ if (normalizedSql.startsWith("INSERT"))
44
+ return "insert";
45
+ if (normalizedSql.startsWith("UPDATE"))
46
+ return "update";
47
+ if (normalizedSql.startsWith("DELETE"))
48
+ return "delete";
49
+ return "other";
50
+ }
51
+
52
+ class Database {
53
+ config;
54
+ driver;
55
+ sql = null;
56
+ _isConnected = false;
57
+ enableMetrics;
58
+ slowQueryThreshold;
59
+ metrics = {
60
+ queries: 0,
61
+ inserts: 0,
62
+ updates: 0,
63
+ deletes: 0,
64
+ errors: 0,
65
+ avgLatency: 0,
66
+ totalLatency: 0,
67
+ slowQueries: 0,
68
+ totalOperations: 0
69
+ };
70
+ eventListeners = new Map;
71
+ constructor(config) {
72
+ this.config = typeof config === "string" ? { url: config } : config;
73
+ this.driver = this.config.driver ?? detectDriver(this.config.url);
74
+ this.enableMetrics = this.config.enableMetrics ?? true;
75
+ this.slowQueryThreshold = this.config.slowQueryThreshold ?? 100;
76
+ }
77
+ getTimestamp() {
78
+ try {
79
+ return Bun.nanoseconds() / 1e6;
80
+ } catch {
81
+ return performance.now();
82
+ }
83
+ }
84
+ getMetrics() {
85
+ return { ...this.metrics };
86
+ }
87
+ resetMetrics() {
88
+ this.metrics = {
89
+ queries: 0,
90
+ inserts: 0,
91
+ updates: 0,
92
+ deletes: 0,
93
+ errors: 0,
94
+ avgLatency: 0,
95
+ totalLatency: 0,
96
+ slowQueries: 0,
97
+ totalOperations: 0
98
+ };
99
+ }
100
+ updateMetrics(operationType, latency, error) {
101
+ if (!this.enableMetrics)
102
+ return;
103
+ this.metrics.totalOperations++;
104
+ this.metrics.totalLatency += latency;
105
+ this.metrics.avgLatency = this.metrics.totalLatency / this.metrics.totalOperations;
106
+ if (latency > this.slowQueryThreshold) {
107
+ this.metrics.slowQueries++;
108
+ }
109
+ if (error) {
110
+ this.metrics.errors++;
111
+ }
112
+ switch (operationType) {
113
+ case "query":
114
+ this.metrics.queries++;
115
+ break;
116
+ case "insert":
117
+ this.metrics.inserts++;
118
+ break;
119
+ case "update":
120
+ this.metrics.updates++;
121
+ break;
122
+ case "delete":
123
+ this.metrics.deletes++;
124
+ break;
125
+ }
126
+ }
127
+ emitEvent(event) {
128
+ const listeners = this.eventListeners.get(event.type);
129
+ if (listeners) {
130
+ for (const listener of listeners) {
131
+ try {
132
+ listener(event);
133
+ } catch (e) {
134
+ console.error("Database event listener error:", e);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ on(eventType, listener) {
140
+ if (!this.eventListeners.has(eventType)) {
141
+ this.eventListeners.set(eventType, new Set);
142
+ }
143
+ this.eventListeners.get(eventType)?.add(listener);
144
+ }
145
+ off(eventType, listener) {
146
+ this.eventListeners.get(eventType)?.delete(listener);
147
+ }
148
+ removeAllListeners(eventType) {
149
+ if (eventType) {
150
+ this.eventListeners.delete(eventType);
151
+ } else {
152
+ this.eventListeners.clear();
153
+ }
154
+ }
155
+ getDriver() {
156
+ return this.driver;
157
+ }
158
+ async connect() {
159
+ if (this._isConnected)
160
+ return;
161
+ try {
162
+ const { SQL } = await Promise.resolve(globalThis.Bun);
163
+ const options = {};
164
+ if (this.driver === "sqlite") {
165
+ options.adapter = "sqlite";
166
+ if (!this.config.url.startsWith("sqlite://") && !this.config.url.startsWith("file:") && this.config.url !== ":memory:") {
167
+ options.filename = this.config.url;
168
+ }
169
+ }
170
+ if (this.config.pool) {
171
+ if (this.config.pool.max)
172
+ options.max = this.config.pool.max;
173
+ if (this.config.pool.idleTimeout)
174
+ options.idleTimeout = this.config.pool.idleTimeout;
175
+ if (this.config.pool.maxLifetime)
176
+ options.maxLifetime = this.config.pool.maxLifetime;
177
+ if (this.config.pool.connectionTimeout)
178
+ options.connectionTimeout = this.config.pool.connectionTimeout;
179
+ }
180
+ if (this.config.tls !== undefined) {
181
+ options.tls = this.config.tls;
182
+ }
183
+ if (this.config.bigint !== undefined) {
184
+ options.bigint = this.config.bigint;
185
+ }
186
+ if (this.config.prepare !== undefined) {
187
+ options.prepare = this.config.prepare;
188
+ }
189
+ if (Object.keys(options).length > 0 && !this.config.url.startsWith("sqlite://")) {
190
+ this.sql = new SQL(this.config.url, options);
191
+ } else {
192
+ this.sql = new SQL(this.config.url);
193
+ }
194
+ this._isConnected = true;
195
+ } catch (error) {
196
+ throw new Error(`Failed to connect to database: ${error instanceof Error ? error.message : String(error)}`);
197
+ }
198
+ }
199
+ get isConnected() {
200
+ return this._isConnected;
201
+ }
202
+ getSql() {
203
+ return this.sql;
204
+ }
205
+ async query(strings, ...values) {
206
+ this.ensureConnection();
207
+ const sql = strings.join("?");
208
+ const operationType = detectOperationType(sql);
209
+ const startTime = this.getTimestamp();
210
+ this.emitEvent({
211
+ type: "query:start",
212
+ sql,
213
+ params: values,
214
+ operationType
215
+ });
216
+ try {
217
+ const sqlFn = this.sql;
218
+ const results = await sqlFn(strings, ...values);
219
+ const latency = this.getTimestamp() - startTime;
220
+ this.updateMetrics(operationType, latency, false);
221
+ this.emitEvent({
222
+ type: "query:end",
223
+ sql,
224
+ params: values,
225
+ latency,
226
+ operationType
227
+ });
228
+ return results;
229
+ } catch (error) {
230
+ const latency = this.getTimestamp() - startTime;
231
+ this.updateMetrics(operationType, latency, true);
232
+ this.emitEvent({
233
+ type: "query:error",
234
+ sql,
235
+ params: values,
236
+ latency,
237
+ error: error instanceof Error ? error : new Error(String(error)),
238
+ operationType
239
+ });
240
+ throw error;
241
+ }
242
+ }
243
+ async queryOne(strings, ...values) {
244
+ const results = await this.query(strings, ...values);
245
+ return results.length > 0 ? results[0] : null;
246
+ }
247
+ async execute(strings, ...values) {
248
+ this.ensureConnection();
249
+ const sql = strings.join("?");
250
+ const operationType = detectOperationType(sql);
251
+ const startTime = this.getTimestamp();
252
+ this.emitEvent({
253
+ type: "query:start",
254
+ sql,
255
+ params: values,
256
+ operationType
257
+ });
258
+ try {
259
+ const sqlFn = this.sql;
260
+ const results = await sqlFn(strings, ...values);
261
+ const latency = this.getTimestamp() - startTime;
262
+ this.updateMetrics(operationType, latency, false);
263
+ this.emitEvent({
264
+ type: "query:end",
265
+ sql,
266
+ params: values,
267
+ latency,
268
+ operationType
269
+ });
270
+ return {
271
+ rows: results,
272
+ rowCount: results.length
273
+ };
274
+ } catch (error) {
275
+ const latency = this.getTimestamp() - startTime;
276
+ this.updateMetrics(operationType, latency, true);
277
+ this.emitEvent({
278
+ type: "query:error",
279
+ sql,
280
+ params: values,
281
+ latency,
282
+ error: error instanceof Error ? error : new Error(String(error)),
283
+ operationType
284
+ });
285
+ throw error;
286
+ }
287
+ }
288
+ async raw(sqlString, params = []) {
289
+ this.ensureConnection();
290
+ const operationType = detectOperationType(sqlString);
291
+ const startTime = this.getTimestamp();
292
+ this.emitEvent({
293
+ type: "query:start",
294
+ sql: sqlString,
295
+ params,
296
+ operationType
297
+ });
298
+ try {
299
+ const sql = this.sql;
300
+ let results;
301
+ if (sql.unsafe) {
302
+ if (this.driver === "sqlite") {
303
+ let query = sqlString;
304
+ let i = 1;
305
+ while (query.includes(`$${i}`)) {
306
+ query = query.replace(`$${i}`, "?");
307
+ i++;
308
+ }
309
+ results = await sql.unsafe(query, params);
310
+ } else {
311
+ results = await sql.unsafe(sqlString, params);
312
+ }
313
+ } else {
314
+ throw new Error("Raw SQL not supported");
315
+ }
316
+ const latency = this.getTimestamp() - startTime;
317
+ this.updateMetrics(operationType, latency, false);
318
+ this.emitEvent({
319
+ type: "query:end",
320
+ sql: sqlString,
321
+ params,
322
+ latency,
323
+ operationType
324
+ });
325
+ return results;
326
+ } catch (error) {
327
+ const latency = this.getTimestamp() - startTime;
328
+ this.updateMetrics(operationType, latency, true);
329
+ this.emitEvent({
330
+ type: "query:error",
331
+ sql: sqlString,
332
+ params,
333
+ latency,
334
+ error: error instanceof Error ? error : new Error(String(error)),
335
+ operationType
336
+ });
337
+ throw error;
338
+ }
339
+ }
340
+ async transaction(callback) {
341
+ this.ensureConnection();
342
+ const sql = this.sql;
343
+ return sql.begin(async (tx) => {
344
+ const txWrapper = {
345
+ query: async (strings, ...values) => {
346
+ const t = tx;
347
+ return t(strings, ...values);
348
+ },
349
+ queryOne: async (strings, ...values) => {
350
+ const results = await txWrapper.query(strings, ...values);
351
+ return results.length > 0 ? results[0] : null;
352
+ },
353
+ execute: async (strings, ...values) => {
354
+ const t = tx;
355
+ const results = await t(strings, ...values);
356
+ return { rows: results, rowCount: results.length };
357
+ }
358
+ };
359
+ return callback(txWrapper);
360
+ });
361
+ }
362
+ async beginDistributed(name, callback) {
363
+ this.ensureConnection();
364
+ const sql = this.sql;
365
+ if (!sql.beginDistributed) {
366
+ throw new Error("Distributed transactions not supported for this database");
367
+ }
368
+ return sql.beginDistributed(name, async (tx) => {
369
+ const txWrapper = {
370
+ query: async (strings, ...values) => {
371
+ const t = tx;
372
+ return t(strings, ...values);
373
+ },
374
+ queryOne: async (strings, ...values) => {
375
+ const results = await txWrapper.query(strings, ...values);
376
+ return results.length > 0 ? results[0] : null;
377
+ },
378
+ execute: async (strings, ...values) => {
379
+ const t = tx;
380
+ const results = await t(strings, ...values);
381
+ return { rows: results, rowCount: results.length };
382
+ }
383
+ };
384
+ return callback(txWrapper);
385
+ });
386
+ }
387
+ async commitDistributed(name) {
388
+ const sql = this.sql;
389
+ if (sql.commitDistributed) {
390
+ await sql.commitDistributed(name);
391
+ }
392
+ }
393
+ async rollbackDistributed(name) {
394
+ const sql = this.sql;
395
+ if (sql.rollbackDistributed) {
396
+ await sql.rollbackDistributed(name);
397
+ }
398
+ }
399
+ async reserve() {
400
+ this.ensureConnection();
401
+ const sql = this.sql;
402
+ if (!sql.reserve) {
403
+ throw new Error("Connection reservation not supported");
404
+ }
405
+ const reserved = await sql.reserve();
406
+ return new ReservedConnection(reserved);
407
+ }
408
+ async close(options) {
409
+ if (!this._isConnected)
410
+ return;
411
+ const sql = this.sql;
412
+ if (sql.close) {
413
+ await sql.close(options);
414
+ }
415
+ this.sql = null;
416
+ this._isConnected = false;
417
+ }
418
+ async values(strings, ...values) {
419
+ this.ensureConnection();
420
+ const sql = this.sql;
421
+ return sql(strings, ...values).values();
422
+ }
423
+ async rawFormat(strings, ...values) {
424
+ this.ensureConnection();
425
+ const sql = this.sql;
426
+ return sql(strings, ...values).raw();
427
+ }
428
+ async simple(strings, ...values) {
429
+ this.ensureConnection();
430
+ const sql = this.sql;
431
+ return sql(strings, ...values).simple();
432
+ }
433
+ async file(path, params = []) {
434
+ this.ensureConnection();
435
+ const sql = this.sql;
436
+ if (sql.file) {
437
+ return sql.file(path, params);
438
+ }
439
+ throw new Error("File execution not supported");
440
+ }
441
+ ensureConnection() {
442
+ if (!this._isConnected || !this.sql) {
443
+ throw new Error("Database not connected. Call connect() first.");
444
+ }
445
+ }
446
+ }
447
+
448
+ class ReservedConnection {
449
+ connection;
450
+ constructor(connection) {
451
+ this.connection = connection;
452
+ }
453
+ async query(strings, ...values) {
454
+ const conn = this.connection;
455
+ return conn(strings, ...values);
456
+ }
457
+ async queryOne(strings, ...values) {
458
+ const results = await this.query(strings, ...values);
459
+ return results.length > 0 ? results[0] : null;
460
+ }
461
+ release() {
462
+ const conn = this.connection;
463
+ if (conn.release) {
464
+ conn.release();
465
+ }
466
+ }
467
+ [Symbol.dispose]() {
468
+ this.release();
469
+ }
470
+ }
471
+ async function createConnection(config) {
472
+ const db = new Database(config);
473
+ await db.connect();
474
+ return db;
475
+ }
476
+ function sqlFragment(name) {
477
+ return name.replace(/"/g, '""');
478
+ }
479
+ function buildInClause(values) {
480
+ const placeholders = values.map(() => "?").join(", ");
481
+ return {
482
+ placeholder: `(${placeholders})`,
483
+ params: values
484
+ };
485
+ }
486
+ export {
487
+ sqlFragment,
488
+ detectDriver,
489
+ createConnection,
490
+ buildInClause,
491
+ ReservedConnection,
492
+ Database
493
+ };