@voyant-travel/db 0.108.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 (336) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +60 -0
  3. package/dist/aggregate-snapshots.d.ts +66 -0
  4. package/dist/aggregate-snapshots.d.ts.map +1 -0
  5. package/dist/aggregate-snapshots.js +110 -0
  6. package/dist/aggregate-snapshots.js.map +1 -0
  7. package/dist/columns/collection.d.ts +37 -0
  8. package/dist/columns/collection.d.ts.map +1 -0
  9. package/dist/columns/collection.js +44 -0
  10. package/dist/columns/collection.js.map +1 -0
  11. package/dist/columns/cruise.d.ts +26 -0
  12. package/dist/columns/cruise.d.ts.map +1 -0
  13. package/dist/columns/cruise.js +31 -0
  14. package/dist/columns/cruise.js.map +1 -0
  15. package/dist/columns/departure-sub-tables.d.ts +179 -0
  16. package/dist/columns/departure-sub-tables.d.ts.map +1 -0
  17. package/dist/columns/departure-sub-tables.js +214 -0
  18. package/dist/columns/departure-sub-tables.js.map +1 -0
  19. package/dist/columns/departure.d.ts +20 -0
  20. package/dist/columns/departure.d.ts.map +1 -0
  21. package/dist/columns/departure.js +23 -0
  22. package/dist/columns/departure.js.map +1 -0
  23. package/dist/columns/destinations.d.ts +21 -0
  24. package/dist/columns/destinations.d.ts.map +1 -0
  25. package/dist/columns/destinations.js +24 -0
  26. package/dist/columns/destinations.js.map +1 -0
  27. package/dist/columns/index.d.ts +31 -0
  28. package/dist/columns/index.d.ts.map +1 -0
  29. package/dist/columns/index.js +57 -0
  30. package/dist/columns/index.js.map +1 -0
  31. package/dist/columns/itinerary-sub-tables.d.ts +177 -0
  32. package/dist/columns/itinerary-sub-tables.d.ts.map +1 -0
  33. package/dist/columns/itinerary-sub-tables.js +122 -0
  34. package/dist/columns/itinerary-sub-tables.js.map +1 -0
  35. package/dist/columns/itinerary.d.ts +17 -0
  36. package/dist/columns/itinerary.d.ts.map +1 -0
  37. package/dist/columns/itinerary.js +20 -0
  38. package/dist/columns/itinerary.js.map +1 -0
  39. package/dist/columns/lodging.d.ts +143 -0
  40. package/dist/columns/lodging.d.ts.map +1 -0
  41. package/dist/columns/lodging.js +164 -0
  42. package/dist/columns/lodging.js.map +1 -0
  43. package/dist/columns/offers.d.ts +31 -0
  44. package/dist/columns/offers.d.ts.map +1 -0
  45. package/dist/columns/offers.js +43 -0
  46. package/dist/columns/offers.js.map +1 -0
  47. package/dist/columns/pricing.d.ts +60 -0
  48. package/dist/columns/pricing.d.ts.map +1 -0
  49. package/dist/columns/pricing.js +71 -0
  50. package/dist/columns/pricing.js.map +1 -0
  51. package/dist/columns/product-accommodation.d.ts +99 -0
  52. package/dist/columns/product-accommodation.d.ts.map +1 -0
  53. package/dist/columns/product-accommodation.js +65 -0
  54. package/dist/columns/product-accommodation.js.map +1 -0
  55. package/dist/columns/product-addons.d.ts +18 -0
  56. package/dist/columns/product-addons.d.ts.map +1 -0
  57. package/dist/columns/product-addons.js +21 -0
  58. package/dist/columns/product-addons.js.map +1 -0
  59. package/dist/columns/product-availability-states.d.ts +65 -0
  60. package/dist/columns/product-availability-states.d.ts.map +1 -0
  61. package/dist/columns/product-availability-states.js +81 -0
  62. package/dist/columns/product-availability-states.js.map +1 -0
  63. package/dist/columns/product-availability.d.ts +21 -0
  64. package/dist/columns/product-availability.d.ts.map +1 -0
  65. package/dist/columns/product-availability.js +24 -0
  66. package/dist/columns/product-availability.js.map +1 -0
  67. package/dist/columns/product-booking-rules.d.ts +45 -0
  68. package/dist/columns/product-booking-rules.d.ts.map +1 -0
  69. package/dist/columns/product-booking-rules.js +55 -0
  70. package/dist/columns/product-booking-rules.js.map +1 -0
  71. package/dist/columns/product-category-assignments.d.ts +17 -0
  72. package/dist/columns/product-category-assignments.d.ts.map +1 -0
  73. package/dist/columns/product-category-assignments.js +20 -0
  74. package/dist/columns/product-category-assignments.js.map +1 -0
  75. package/dist/columns/product-extensions.d.ts +24 -0
  76. package/dist/columns/product-extensions.d.ts.map +1 -0
  77. package/dist/columns/product-extensions.js +27 -0
  78. package/dist/columns/product-extensions.js.map +1 -0
  79. package/dist/columns/product-media.d.ts +19 -0
  80. package/dist/columns/product-media.d.ts.map +1 -0
  81. package/dist/columns/product-media.js +22 -0
  82. package/dist/columns/product-media.js.map +1 -0
  83. package/dist/columns/product-overrides.d.ts +19 -0
  84. package/dist/columns/product-overrides.d.ts.map +1 -0
  85. package/dist/columns/product-overrides.js +22 -0
  86. package/dist/columns/product-overrides.js.map +1 -0
  87. package/dist/columns/product-preferences.d.ts +51 -0
  88. package/dist/columns/product-preferences.d.ts.map +1 -0
  89. package/dist/columns/product-preferences.js +59 -0
  90. package/dist/columns/product-preferences.js.map +1 -0
  91. package/dist/columns/product-publish-settings.d.ts +18 -0
  92. package/dist/columns/product-publish-settings.d.ts.map +1 -0
  93. package/dist/columns/product-publish-settings.js +21 -0
  94. package/dist/columns/product-publish-settings.js.map +1 -0
  95. package/dist/columns/product-rate-plans.d.ts +28 -0
  96. package/dist/columns/product-rate-plans.d.ts.map +1 -0
  97. package/dist/columns/product-rate-plans.js +33 -0
  98. package/dist/columns/product-rate-plans.js.map +1 -0
  99. package/dist/columns/product-translations.d.ts +24 -0
  100. package/dist/columns/product-translations.d.ts.map +1 -0
  101. package/dist/columns/product-translations.js +27 -0
  102. package/dist/columns/product-translations.js.map +1 -0
  103. package/dist/columns/product-versions.d.ts +19 -0
  104. package/dist/columns/product-versions.d.ts.map +1 -0
  105. package/dist/columns/product-versions.js +22 -0
  106. package/dist/columns/product-versions.js.map +1 -0
  107. package/dist/columns/product-visibility.d.ts +16 -0
  108. package/dist/columns/product-visibility.d.ts.map +1 -0
  109. package/dist/columns/product-visibility.js +19 -0
  110. package/dist/columns/product-visibility.js.map +1 -0
  111. package/dist/columns/product.d.ts +56 -0
  112. package/dist/columns/product.d.ts.map +1 -0
  113. package/dist/columns/product.js +44 -0
  114. package/dist/columns/product.js.map +1 -0
  115. package/dist/columns/room.d.ts +117 -0
  116. package/dist/columns/room.d.ts.map +1 -0
  117. package/dist/columns/room.js +86 -0
  118. package/dist/columns/room.js.map +1 -0
  119. package/dist/columns/ship.d.ts +22 -0
  120. package/dist/columns/ship.d.ts.map +1 -0
  121. package/dist/columns/ship.js +25 -0
  122. package/dist/columns/ship.js.map +1 -0
  123. package/dist/columns/tags.d.ts +33 -0
  124. package/dist/columns/tags.d.ts.map +1 -0
  125. package/dist/columns/tags.js +38 -0
  126. package/dist/columns/tags.js.map +1 -0
  127. package/dist/columns/transport.d.ts +53 -0
  128. package/dist/columns/transport.d.ts.map +1 -0
  129. package/dist/columns/transport.js +62 -0
  130. package/dist/columns/transport.js.map +1 -0
  131. package/dist/connection-config.d.ts +101 -0
  132. package/dist/connection-config.d.ts.map +1 -0
  133. package/dist/connection-config.js +106 -0
  134. package/dist/connection-config.js.map +1 -0
  135. package/dist/crud.d.ts +87 -0
  136. package/dist/crud.d.ts.map +1 -0
  137. package/dist/crud.js +190 -0
  138. package/dist/crud.js.map +1 -0
  139. package/dist/helpers.d.ts +33 -0
  140. package/dist/helpers.d.ts.map +1 -0
  141. package/dist/helpers.js +49 -0
  142. package/dist/helpers.js.map +1 -0
  143. package/dist/index.d.ts +109 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +155 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/lib/index.d.ts +3 -0
  148. package/dist/lib/index.d.ts.map +1 -0
  149. package/dist/lib/index.js +5 -0
  150. package/dist/lib/index.js.map +1 -0
  151. package/dist/lib/typeid-column.d.ts +75 -0
  152. package/dist/lib/typeid-column.d.ts.map +1 -0
  153. package/dist/lib/typeid-column.js +92 -0
  154. package/dist/lib/typeid-column.js.map +1 -0
  155. package/dist/lib/typeid-core.d.ts +36 -0
  156. package/dist/lib/typeid-core.d.ts.map +1 -0
  157. package/dist/lib/typeid-core.js +67 -0
  158. package/dist/lib/typeid-core.js.map +1 -0
  159. package/dist/lib/typeid-prefixes.d.ts +342 -0
  160. package/dist/lib/typeid-prefixes.d.ts.map +1 -0
  161. package/dist/lib/typeid-prefixes.js +379 -0
  162. package/dist/lib/typeid-prefixes.js.map +1 -0
  163. package/dist/lib/typeid-schemas.d.ts +206 -0
  164. package/dist/lib/typeid-schemas.d.ts.map +1 -0
  165. package/dist/lib/typeid-schemas.js +207 -0
  166. package/dist/lib/typeid-schemas.js.map +1 -0
  167. package/dist/lib/typeid-zod.d.ts +16 -0
  168. package/dist/lib/typeid-zod.d.ts.map +1 -0
  169. package/dist/lib/typeid-zod.js +29 -0
  170. package/dist/lib/typeid-zod.js.map +1 -0
  171. package/dist/lib/typeid.d.ts +2 -0
  172. package/dist/lib/typeid.d.ts.map +1 -0
  173. package/dist/lib/typeid.js +6 -0
  174. package/dist/lib/typeid.js.map +1 -0
  175. package/dist/lifecycle.d.ts +24 -0
  176. package/dist/lifecycle.d.ts.map +1 -0
  177. package/dist/lifecycle.js +30 -0
  178. package/dist/lifecycle.js.map +1 -0
  179. package/dist/links.d.ts +22 -0
  180. package/dist/links.d.ts.map +1 -0
  181. package/dist/links.js +281 -0
  182. package/dist/links.js.map +1 -0
  183. package/dist/operators.d.ts +9 -0
  184. package/dist/operators.d.ts.map +1 -0
  185. package/dist/operators.js +9 -0
  186. package/dist/operators.js.map +1 -0
  187. package/dist/outbox.d.ts +87 -0
  188. package/dist/outbox.d.ts.map +1 -0
  189. package/dist/outbox.js +245 -0
  190. package/dist/outbox.js.map +1 -0
  191. package/dist/primitives/catalog-schemas.d.ts +101 -0
  192. package/dist/primitives/catalog-schemas.d.ts.map +1 -0
  193. package/dist/primitives/catalog-schemas.js +69 -0
  194. package/dist/primitives/catalog-schemas.js.map +1 -0
  195. package/dist/primitives/catalog.d.ts +47 -0
  196. package/dist/primitives/catalog.d.ts.map +1 -0
  197. package/dist/primitives/catalog.js +94 -0
  198. package/dist/primitives/catalog.js.map +1 -0
  199. package/dist/primitives/index.d.ts +4 -0
  200. package/dist/primitives/index.d.ts.map +1 -0
  201. package/dist/primitives/index.js +4 -0
  202. package/dist/primitives/index.js.map +1 -0
  203. package/dist/primitives/offers.d.ts +224 -0
  204. package/dist/primitives/offers.d.ts.map +1 -0
  205. package/dist/primitives/offers.js +132 -0
  206. package/dist/primitives/offers.js.map +1 -0
  207. package/dist/queries/index.d.ts +18 -0
  208. package/dist/queries/index.d.ts.map +1 -0
  209. package/dist/queries/index.js +30 -0
  210. package/dist/queries/index.js.map +1 -0
  211. package/dist/runtime/index.d.ts +4 -0
  212. package/dist/runtime/index.d.ts.map +1 -0
  213. package/dist/runtime/index.js +5 -0
  214. package/dist/runtime/index.js.map +1 -0
  215. package/dist/runtime/locks.d.ts +5 -0
  216. package/dist/runtime/locks.d.ts.map +1 -0
  217. package/dist/runtime/locks.js +36 -0
  218. package/dist/runtime/locks.js.map +1 -0
  219. package/dist/schema/00_ensure_schemas.d.ts +5 -0
  220. package/dist/schema/00_ensure_schemas.d.ts.map +1 -0
  221. package/dist/schema/00_ensure_schemas.js +6 -0
  222. package/dist/schema/00_ensure_schemas.js.map +1 -0
  223. package/dist/schema/aggregate-snapshots.d.ts +97 -0
  224. package/dist/schema/aggregate-snapshots.d.ts.map +1 -0
  225. package/dist/schema/aggregate-snapshots.js +27 -0
  226. package/dist/schema/aggregate-snapshots.js.map +1 -0
  227. package/dist/schema/iam/apikey.d.ts +396 -0
  228. package/dist/schema/iam/apikey.d.ts.map +1 -0
  229. package/dist/schema/iam/apikey.js +41 -0
  230. package/dist/schema/iam/apikey.js.map +1 -0
  231. package/dist/schema/iam/auth.d.ts +1026 -0
  232. package/dist/schema/iam/auth.d.ts.map +1 -0
  233. package/dist/schema/iam/auth.js +138 -0
  234. package/dist/schema/iam/auth.js.map +1 -0
  235. package/dist/schema/iam/cloud_auth.d.ts +446 -0
  236. package/dist/schema/iam/cloud_auth.d.ts.map +1 -0
  237. package/dist/schema/iam/cloud_auth.js +46 -0
  238. package/dist/schema/iam/cloud_auth.js.map +1 -0
  239. package/dist/schema/iam/index.d.ts +8 -0
  240. package/dist/schema/iam/index.d.ts.map +1 -0
  241. package/dist/schema/iam/index.js +8 -0
  242. package/dist/schema/iam/index.js.map +1 -0
  243. package/dist/schema/iam/invitations.d.ts +173 -0
  244. package/dist/schema/iam/invitations.d.ts.map +1 -0
  245. package/dist/schema/iam/invitations.js +27 -0
  246. package/dist/schema/iam/invitations.js.map +1 -0
  247. package/dist/schema/iam/kms.d.ts +53 -0
  248. package/dist/schema/iam/kms.d.ts.map +1 -0
  249. package/dist/schema/iam/kms.js +40 -0
  250. package/dist/schema/iam/kms.js.map +1 -0
  251. package/dist/schema/iam/roles.d.ts +12 -0
  252. package/dist/schema/iam/roles.d.ts.map +1 -0
  253. package/dist/schema/iam/roles.js +12 -0
  254. package/dist/schema/iam/roles.js.map +1 -0
  255. package/dist/schema/iam/user_profiles.d.ts +442 -0
  256. package/dist/schema/iam/user_profiles.d.ts.map +1 -0
  257. package/dist/schema/iam/user_profiles.js +125 -0
  258. package/dist/schema/iam/user_profiles.js.map +1 -0
  259. package/dist/schema/index.d.ts +5 -0
  260. package/dist/schema/index.d.ts.map +1 -0
  261. package/dist/schema/index.js +5 -0
  262. package/dist/schema/index.js.map +1 -0
  263. package/dist/schema/infra/domains.d.ts +609 -0
  264. package/dist/schema/infra/domains.d.ts.map +1 -0
  265. package/dist/schema/infra/domains.js +108 -0
  266. package/dist/schema/infra/domains.js.map +1 -0
  267. package/dist/schema/infra/email_domain_records.d.ts +255 -0
  268. package/dist/schema/infra/email_domain_records.d.ts.map +1 -0
  269. package/dist/schema/infra/email_domain_records.js +65 -0
  270. package/dist/schema/infra/email_domain_records.js.map +1 -0
  271. package/dist/schema/infra/event_outbox.d.ts +232 -0
  272. package/dist/schema/infra/event_outbox.d.ts.map +1 -0
  273. package/dist/schema/infra/event_outbox.js +59 -0
  274. package/dist/schema/infra/event_outbox.js.map +1 -0
  275. package/dist/schema/infra/idempotency_keys.d.ts +186 -0
  276. package/dist/schema/infra/idempotency_keys.d.ts.map +1 -0
  277. package/dist/schema/infra/idempotency_keys.js +40 -0
  278. package/dist/schema/infra/idempotency_keys.js.map +1 -0
  279. package/dist/schema/infra/index.d.ts +9 -0
  280. package/dist/schema/infra/index.d.ts.map +1 -0
  281. package/dist/schema/infra/index.js +10 -0
  282. package/dist/schema/infra/index.js.map +1 -0
  283. package/dist/schema/infra/public_document_delivery_grants.d.ts +356 -0
  284. package/dist/schema/infra/public_document_delivery_grants.d.ts.map +1 -0
  285. package/dist/schema/infra/public_document_delivery_grants.js +36 -0
  286. package/dist/schema/infra/public_document_delivery_grants.js.map +1 -0
  287. package/dist/schema/infra/rate_limit_buckets.d.ts +138 -0
  288. package/dist/schema/infra/rate_limit_buckets.d.ts.map +1 -0
  289. package/dist/schema/infra/rate_limit_buckets.js +52 -0
  290. package/dist/schema/infra/rate_limit_buckets.js.map +1 -0
  291. package/dist/schema/infra/webhook_deliveries.d.ts +572 -0
  292. package/dist/schema/infra/webhook_deliveries.d.ts.map +1 -0
  293. package/dist/schema/infra/webhook_deliveries.js +136 -0
  294. package/dist/schema/infra/webhook_deliveries.js.map +1 -0
  295. package/dist/schema/infra/webhook_subscriptions.d.ts +284 -0
  296. package/dist/schema/infra/webhook_subscriptions.d.ts.map +1 -0
  297. package/dist/schema/infra/webhook_subscriptions.js +64 -0
  298. package/dist/schema/infra/webhook_subscriptions.js.map +1 -0
  299. package/dist/schema/infra/write_intents.d.ts +185 -0
  300. package/dist/schema/infra/write_intents.d.ts.map +1 -0
  301. package/dist/schema/infra/write_intents.js +50 -0
  302. package/dist/schema/infra/write_intents.js.map +1 -0
  303. package/dist/schema/voyant/bookings.d.ts +2 -0
  304. package/dist/schema/voyant/bookings.d.ts.map +1 -0
  305. package/dist/schema/voyant/bookings.js +2 -0
  306. package/dist/schema/voyant/bookings.js.map +1 -0
  307. package/dist/schema/voyant/finance.d.ts +2 -0
  308. package/dist/schema/voyant/finance.d.ts.map +1 -0
  309. package/dist/schema/voyant/finance.js +2 -0
  310. package/dist/schema/voyant/finance.js.map +1 -0
  311. package/dist/test-utils.d.ts +17 -0
  312. package/dist/test-utils.d.ts.map +1 -0
  313. package/dist/test-utils.js +56 -0
  314. package/dist/test-utils.js.map +1 -0
  315. package/dist/transaction-capability.d.ts +11 -0
  316. package/dist/transaction-capability.d.ts.map +1 -0
  317. package/dist/transaction-capability.js +17 -0
  318. package/dist/transaction-capability.js.map +1 -0
  319. package/dist/transaction.d.ts +31 -0
  320. package/dist/transaction.d.ts.map +1 -0
  321. package/dist/transaction.js +72 -0
  322. package/dist/transaction.js.map +1 -0
  323. package/dist/tsconfig.tsbuildinfo +1 -0
  324. package/dist/types.d.ts +10 -0
  325. package/dist/types.d.ts.map +1 -0
  326. package/dist/types.js +2 -0
  327. package/dist/types.js.map +1 -0
  328. package/dist/utils.d.ts +2 -0
  329. package/dist/utils.d.ts.map +1 -0
  330. package/dist/utils.js +19 -0
  331. package/dist/utils.js.map +1 -0
  332. package/dist/write-intents.d.ts +51 -0
  333. package/dist/write-intents.d.ts.map +1 -0
  334. package/dist/write-intents.js +95 -0
  335. package/dist/write-intents.js.map +1 -0
  336. package/package.json +306 -0
package/dist/crud.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ import { type SQL } from "drizzle-orm";
2
+ import type { AnyPgTable } from "drizzle-orm/pg-core";
3
+ import type { z } from "zod";
4
+ import type { DrizzleClient } from "./types.js";
5
+ /**
6
+ * Options accepted by {@link createCrudService}.
7
+ */
8
+ export interface CrudServiceOptions<TInsertSchema extends z.ZodTypeAny = z.ZodTypeAny, TUpdateSchema extends z.ZodTypeAny = z.ZodTypeAny> {
9
+ /** Optional Zod schema run against inputs passed to `create`. */
10
+ insertSchema?: TInsertSchema;
11
+ /** Optional Zod schema run against inputs passed to `update`. */
12
+ updateSchema?: TUpdateSchema;
13
+ }
14
+ /**
15
+ * Options for list-style queries.
16
+ */
17
+ export interface ListOptions {
18
+ /** WHERE clause, typically composed with `and()`. */
19
+ where?: SQL;
20
+ /** Max number of rows to return. */
21
+ limit?: number;
22
+ /** Offset for pagination. */
23
+ offset?: number;
24
+ /**
25
+ * ORDER BY clauses. Accept a single clause or array. Consumers pass
26
+ * `asc(table.column)` / `desc(table.column)` builders.
27
+ */
28
+ orderBy?: SQL | SQL[];
29
+ /**
30
+ * When the table has a `deletedAt` column, soft-deleted rows are filtered
31
+ * out by default. Pass `true` to include them — useful for admin recycle
32
+ * bins, audit reports, or background reconciliation jobs.
33
+ */
34
+ includeDeleted?: boolean;
35
+ }
36
+ /**
37
+ * Options for retrieve-style lookups by id.
38
+ */
39
+ export interface RetrieveOptions {
40
+ /** Include soft-deleted rows. Default: false. */
41
+ includeDeleted?: boolean;
42
+ }
43
+ /**
44
+ * A generic CRUD service bound to a single Drizzle table.
45
+ *
46
+ * Generated methods:
47
+ * - `list(db, opts)` — returns rows
48
+ * - `count(db, where?)` — returns integer count
49
+ * - `listAndCount(db, opts)` — returns `{ data, total }`
50
+ * - `retrieve(db, id)` — returns row or `null`
51
+ * - `create(db, data)` — inserts and returns the row
52
+ * - `update(db, id, data)` — updates and returns the row (or `null` if missing);
53
+ * automatically sets `updatedAt: new Date()` when the table has that column
54
+ * - `delete(db, id)` — hard-deletes and returns `{ id }` or `null`
55
+ * - `softDelete(db, id)` — sets `deletedAt: new Date()` when the column exists
56
+ * - `restore(db, id)` — clears `deletedAt` when the column exists
57
+ *
58
+ * Consumers compose custom methods by spreading the result:
59
+ * ```ts
60
+ * const crud = createCrudService(peopleTable)
61
+ * export const peopleService = {
62
+ * ...crud,
63
+ * async findByEmail(db: DrizzleClient, email: string) { ... },
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function createCrudService<TTable extends AnyPgTable, TInsertSchema extends z.ZodTypeAny = z.ZodTypeAny, TUpdateSchema extends z.ZodTypeAny = z.ZodTypeAny>(table: TTable, options?: CrudServiceOptions<TInsertSchema, TUpdateSchema>): {
68
+ table: TTable;
69
+ list: (db: DrizzleClient, opts?: ListOptions) => Promise<({ [Key in keyof TTable["_"]["columns"] & string as Key]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } extends infer T ? { [K in keyof T]: T[K]; } : never)[]>;
70
+ count: (db: DrizzleClient, where?: SQL, opts?: {
71
+ includeDeleted?: boolean;
72
+ }) => Promise<number>;
73
+ listAndCount: (db: DrizzleClient, opts?: ListOptions) => Promise<{
74
+ data: ({ [Key in keyof TTable["_"]["columns"] & string as Key]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } extends infer T ? { [K in keyof T]: T[K]; } : never)[];
75
+ total: number;
76
+ }>;
77
+ retrieve: (db: DrizzleClient, id: string, opts?: RetrieveOptions) => Promise<({ [Key in keyof TTable["_"]["columns"] & string as Key]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } extends infer T ? { [K in keyof T]: T[K]; } : never) | null>;
78
+ create: (db: DrizzleClient, data: { [Key in keyof TTable["_"]["columns"] & string as import("drizzle-orm").RequiredKeyOnly<Key, TTable["_"]["columns"][Key]>]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } & { [Key_1 in keyof TTable["_"]["columns"] & string as import("drizzle-orm").OptionalKeyOnly<Key_1, TTable["_"]["columns"][Key_1], false>]?: (TTable["_"]["columns"][Key_1]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key_1]["_"]["data"] : TTable["_"]["columns"][Key_1]["_"]["data"] | null) | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never) => Promise<{ [Key_2 in keyof TTable["_"]["columns"] & string as Key_2]: TTable["_"]["columns"][Key_2]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key_2]["_"]["data"] : TTable["_"]["columns"][Key_2]["_"]["data"] | null; } extends infer T_1 ? { [K_1 in keyof T_1]: T_1[K_1]; } : never>;
79
+ update: (db: DrizzleClient, id: string, data: Partial<{ [Key in keyof TTable["_"]["columns"] & string as import("drizzle-orm").RequiredKeyOnly<Key, TTable["_"]["columns"][Key]>]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } & { [Key_1 in keyof TTable["_"]["columns"] & string as import("drizzle-orm").OptionalKeyOnly<Key_1, TTable["_"]["columns"][Key_1], false>]?: (TTable["_"]["columns"][Key_1]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key_1]["_"]["data"] : TTable["_"]["columns"][Key_1]["_"]["data"] | null) | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never>) => Promise<({ [Key_2 in keyof TTable["_"]["columns"] & string as Key_2]: TTable["_"]["columns"][Key_2]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key_2]["_"]["data"] : TTable["_"]["columns"][Key_2]["_"]["data"] | null; } extends infer T_1 ? { [K_1 in keyof T_1]: T_1[K_1]; } : never) | null>;
80
+ delete: (db: DrizzleClient, id: string) => Promise<{
81
+ id: string;
82
+ } | null>;
83
+ softDelete: (db: DrizzleClient, id: string) => Promise<({ [Key in keyof TTable["_"]["columns"] & string as Key]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } extends infer T ? { [K in keyof T]: T[K]; } : never) | null>;
84
+ restore: (db: DrizzleClient, id: string) => Promise<({ [Key in keyof TTable["_"]["columns"] & string as Key]: TTable["_"]["columns"][Key]["_"]["notNull"] extends true ? TTable["_"]["columns"][Key]["_"]["data"] : TTable["_"]["columns"][Key]["_"]["data"] | null; } extends infer T ? { [K in keyof T]: T[K]; } : never) | null>;
85
+ hasSoftDelete: boolean;
86
+ };
87
+ //# sourceMappingURL=crud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../src/crud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,GAAG,EAAO,MAAM,aAAa,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;GAEG;AACH,MAAM,WAAW,kBAAkB,CACjC,aAAa,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,EACjD,aAAa,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;IAEjD,iEAAiE;IACjE,YAAY,CAAC,EAAE,aAAa,CAAA;IAC5B,iEAAiE;IACjE,YAAY,CAAC,EAAE,aAAa,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,CAAA;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,SAAS,UAAU,EACzB,aAAa,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,EACjD,aAAa,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,EACjD,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAM;;eA4BrD,aAAa,SAAQ,WAAW,KAAQ,OAAO,CAAC,yQAAK,CAAC;gBAexE,aAAa,UACT,GAAG,SACL;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KACjC,OAAO,CAAC,MAAM,CAAC;uBAkBZ,aAAa,SACX,WAAW,KAChB,OAAO,CAAC;QAAE,IAAI,EAAE,yQAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;mBAmCpC,aAAa,MACb,MAAM,SACJ,eAAe,KACpB,OAAO,CAAC,0QAAM,IAAI,CAAC;iBAMI,aAAa,gpBAAsB,OAAO,2RAAK;iBAanE,aAAa,MACb,MAAM,QACJ,OAAO,qoBAAa,KACzB,OAAO,CAAC,8RAAM,IAAI,CAAC;iBAgBI,aAAa,MAAM,MAAM,KAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;qBAQtD,aAAa,MAAM,MAAM,KAAG,OAAO,CAAC,0QAAM,IAAI,CAAC;kBAYlD,aAAa,MAAM,MAAM,KAAG,OAAO,CAAC,0QAAM,IAAI,CAAC;;EAyB3E"}
package/dist/crud.js ADDED
@@ -0,0 +1,190 @@
1
+ import { and, eq, getTableColumns, isNull, sql } from "drizzle-orm";
2
+ /**
3
+ * A generic CRUD service bound to a single Drizzle table.
4
+ *
5
+ * Generated methods:
6
+ * - `list(db, opts)` — returns rows
7
+ * - `count(db, where?)` — returns integer count
8
+ * - `listAndCount(db, opts)` — returns `{ data, total }`
9
+ * - `retrieve(db, id)` — returns row or `null`
10
+ * - `create(db, data)` — inserts and returns the row
11
+ * - `update(db, id, data)` — updates and returns the row (or `null` if missing);
12
+ * automatically sets `updatedAt: new Date()` when the table has that column
13
+ * - `delete(db, id)` — hard-deletes and returns `{ id }` or `null`
14
+ * - `softDelete(db, id)` — sets `deletedAt: new Date()` when the column exists
15
+ * - `restore(db, id)` — clears `deletedAt` when the column exists
16
+ *
17
+ * Consumers compose custom methods by spreading the result:
18
+ * ```ts
19
+ * const crud = createCrudService(peopleTable)
20
+ * export const peopleService = {
21
+ * ...crud,
22
+ * async findByEmail(db: DrizzleClient, email: string) { ... },
23
+ * }
24
+ * ```
25
+ */
26
+ export function createCrudService(table, options = {}) {
27
+ const columns = getTableColumns(table);
28
+ if (!columns.id) {
29
+ throw new Error("createCrudService: table must declare an 'id' column");
30
+ }
31
+ const idColumn = columns.id;
32
+ const updatedAtColumn = columns.updatedAt;
33
+ const deletedAtColumn = columns.deletedAt;
34
+ // Drizzle's query builder types lose fidelity under generic TTable — cast
35
+ // db to AnyDb only at the Drizzle call site; return types stay strict.
36
+ const asDb = (db) => db;
37
+ function activeFilter() {
38
+ return deletedAtColumn ? isNull(deletedAtColumn) : undefined;
39
+ }
40
+ function composeWhere(opts) {
41
+ if (opts.includeDeleted)
42
+ return opts.where;
43
+ const active = activeFilter();
44
+ if (!active)
45
+ return opts.where;
46
+ if (!opts.where)
47
+ return active;
48
+ return and(opts.where, active);
49
+ }
50
+ async function list(db, opts = {}) {
51
+ let query = asDb(db).select().from(table);
52
+ const where = composeWhere(opts);
53
+ if (where)
54
+ query = query.where(where);
55
+ if (opts.orderBy) {
56
+ const orders = Array.isArray(opts.orderBy) ? opts.orderBy : [opts.orderBy];
57
+ query = query.orderBy(...orders);
58
+ }
59
+ if (typeof opts.limit === "number")
60
+ query = query.limit(opts.limit);
61
+ if (typeof opts.offset === "number")
62
+ query = query.offset(opts.offset);
63
+ const rows = (await query);
64
+ return rows;
65
+ }
66
+ async function count(db, where, opts = {}) {
67
+ const base = asDb(db).select({ count: sql `count(*)::int` }).from(table);
68
+ const composed = composeWhere({ where, includeDeleted: opts.includeDeleted });
69
+ const rows = (composed ? await base.where(composed) : await base);
70
+ return rows[0]?.count ?? 0;
71
+ }
72
+ /**
73
+ * One roundtrip instead of two: the total rides along as a
74
+ * `count(*) OVER ()` window column and is stripped from the returned
75
+ * rows. The separate-count approach paid the full filtered scan in
76
+ * `count()` anyway — the window adds no scan cost, and on per-query
77
+ * transports (neon-http: one fetch per query) it halves the
78
+ * roundtrips/subrequests per list endpoint. The only case needing a
79
+ * fallback query is an offset pointing past the last row, where the
80
+ * page is empty and the window total is unobservable.
81
+ */
82
+ async function listAndCount(db, opts = {}) {
83
+ let query = asDb(db)
84
+ .select({
85
+ ...getTableColumns(table),
86
+ __voyantWindowTotal: sql `count(*) over()::int`,
87
+ })
88
+ .from(table);
89
+ const where = composeWhere(opts);
90
+ if (where)
91
+ query = query.where(where);
92
+ if (opts.orderBy) {
93
+ const orders = Array.isArray(opts.orderBy) ? opts.orderBy : [opts.orderBy];
94
+ query = query.orderBy(...orders);
95
+ }
96
+ if (typeof opts.limit === "number")
97
+ query = query.limit(opts.limit);
98
+ if (typeof opts.offset === "number")
99
+ query = query.offset(opts.offset);
100
+ const rows = (await query);
101
+ const first = rows[0];
102
+ if (!first) {
103
+ // Empty page. Without an offset the filtered set is genuinely
104
+ // empty; with one, the offset may simply point past the end.
105
+ const total = opts.offset
106
+ ? await count(db, opts.where, { includeDeleted: opts.includeDeleted })
107
+ : 0;
108
+ return { data: [], total };
109
+ }
110
+ const total = first.__voyantWindowTotal;
111
+ const data = rows.map(({ __voyantWindowTotal: _total, ...rest }) => {
112
+ return Object.fromEntries(Object.entries(rest));
113
+ });
114
+ return { data, total };
115
+ }
116
+ async function retrieve(db, id, opts = {}) {
117
+ const where = composeWhere({ where: eq(idColumn, id), includeDeleted: opts.includeDeleted });
118
+ const rows = (await asDb(db).select().from(table).where(where).limit(1));
119
+ return rows[0] ?? null;
120
+ }
121
+ async function create(db, data) {
122
+ const validated = options.insertSchema
123
+ ? options.insertSchema.parse(data)
124
+ : data;
125
+ const rows = (await asDb(db).insert(table).values(validated).returning());
126
+ const row = rows[0];
127
+ if (!row) {
128
+ throw new Error("createCrudService: insert returned no rows");
129
+ }
130
+ return row;
131
+ }
132
+ async function update(db, id, data) {
133
+ const validated = options.updateSchema
134
+ ? options.updateSchema.parse(data)
135
+ : data;
136
+ const patch = { ...validated };
137
+ if (updatedAtColumn) {
138
+ patch.updatedAt = new Date();
139
+ }
140
+ const rows = (await asDb(db)
141
+ .update(table)
142
+ .set(patch)
143
+ .where(eq(idColumn, id))
144
+ .returning());
145
+ return rows[0] ?? null;
146
+ }
147
+ async function remove(db, id) {
148
+ const rows = (await asDb(db)
149
+ .delete(table)
150
+ .where(eq(idColumn, id))
151
+ .returning({ id: idColumn }));
152
+ return rows[0] ?? null;
153
+ }
154
+ async function softDelete(db, id) {
155
+ if (!deletedAtColumn) {
156
+ throw new Error("createCrudService: softDelete requires a 'deletedAt' column");
157
+ }
158
+ const rows = (await asDb(db)
159
+ .update(table)
160
+ .set({ deletedAt: new Date() })
161
+ .where(eq(idColumn, id))
162
+ .returning());
163
+ return rows[0] ?? null;
164
+ }
165
+ async function restore(db, id) {
166
+ if (!deletedAtColumn) {
167
+ throw new Error("createCrudService: restore requires a 'deletedAt' column");
168
+ }
169
+ const rows = (await asDb(db)
170
+ .update(table)
171
+ .set({ deletedAt: null })
172
+ .where(eq(idColumn, id))
173
+ .returning());
174
+ return rows[0] ?? null;
175
+ }
176
+ return {
177
+ table,
178
+ list,
179
+ count,
180
+ listAndCount,
181
+ retrieve,
182
+ create,
183
+ update,
184
+ delete: remove,
185
+ softDelete,
186
+ restore,
187
+ hasSoftDelete: Boolean(deletedAtColumn),
188
+ };
189
+ }
190
+ //# sourceMappingURL=crud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crud.js","sourceRoot":"","sources":["../src/crud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { InferInsertModel, InferSelectModel } from "drizzle-orm";
2
+ import type { AnyPgTable } from "drizzle-orm/pg-core";
3
+ export { booleanQueryParam } from "@voyant-travel/schema-kit/query-params";
4
+ /**
5
+ * A more readable alias for Drizzle's InferSelectModel.
6
+ */
7
+ export type SelectModel<T extends AnyPgTable> = InferSelectModel<T>;
8
+ /**
9
+ * A more readable alias for Drizzle's InferInsertModel.
10
+ */
11
+ export type InsertModel<T extends AnyPgTable> = InferInsertModel<T>;
12
+ /**
13
+ * A simple type guard to check if an error is an instance of Error.
14
+ */
15
+ export declare function isDatabaseError(error: unknown): error is Error;
16
+ /**
17
+ * Wraps a Drizzle query promise to provide consistent error logging.
18
+ * Use this for critical operations that should throw an error on failure.
19
+ *
20
+ * @example
21
+ * const user = await executeQuery(db.query.users.findFirst());
22
+ */
23
+ export declare function executeQuery<T>(query: Promise<T>): Promise<T>;
24
+ /**
25
+ * Wraps a database operation in a try/catch block.
26
+ * Returns the result on success or a fallback value (defaulting to null) on error.
27
+ * Use this for non-critical operations that should not crash the application.
28
+ *
29
+ * @example
30
+ * await safeDbOperation(() => db.insert(logs).values({ message: 'User logged in' }));
31
+ */
32
+ export declare function safeDbOperation<T>(operation: () => Promise<T>, fallback?: T): Promise<T | null>;
33
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAIrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAE1E;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,UAAU,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAEnE;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,UAAU,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAEnE;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAE9D;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUnE;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,QAAQ,CAAC,EAAE,CAAC,GACX,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CASnB"}
@@ -0,0 +1,49 @@
1
+ // /packages/db/src/helpers.ts
2
+ // `booleanQueryParam` now lives in @voyant-travel/schema-kit (pure, below the data
3
+ // layer). Re-exported here to keep the @voyant-travel/db/helpers import path stable.
4
+ export { booleanQueryParam } from "@voyant-travel/schema-kit/query-params";
5
+ /**
6
+ * A simple type guard to check if an error is an instance of Error.
7
+ */
8
+ export function isDatabaseError(error) {
9
+ return error instanceof Error;
10
+ }
11
+ /**
12
+ * Wraps a Drizzle query promise to provide consistent error logging.
13
+ * Use this for critical operations that should throw an error on failure.
14
+ *
15
+ * @example
16
+ * const user = await executeQuery(db.query.users.findFirst());
17
+ */
18
+ export async function executeQuery(query) {
19
+ try {
20
+ return await query;
21
+ }
22
+ catch (error) {
23
+ if (isDatabaseError(error)) {
24
+ console.error("Database query error:", error.message);
25
+ }
26
+ // Re-throw the error to be handled by the caller
27
+ throw error;
28
+ }
29
+ }
30
+ /**
31
+ * Wraps a database operation in a try/catch block.
32
+ * Returns the result on success or a fallback value (defaulting to null) on error.
33
+ * Use this for non-critical operations that should not crash the application.
34
+ *
35
+ * @example
36
+ * await safeDbOperation(() => db.insert(logs).values({ message: 'User logged in' }));
37
+ */
38
+ export async function safeDbOperation(operation, fallback) {
39
+ try {
40
+ return await operation();
41
+ }
42
+ catch (error) {
43
+ if (isDatabaseError(error)) {
44
+ console.error("Database operation error:", error.message);
45
+ }
46
+ return fallback ?? null;
47
+ }
48
+ }
49
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAK9B,mFAAmF;AACnF,qFAAqF;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAY1E;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,KAAK,CAAA;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,KAAiB;IACrD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAA;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QACvD,CAAC;QACD,iDAAiD;QACjD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAA2B,EAC3B,QAAY;IAEZ,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAA;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QAC3D,CAAC;QACD,OAAO,QAAQ,IAAI,IAAI,CAAA;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { type PoolConfig } from "@neondatabase/serverless";
2
+ import type { NeonHttpDatabase } from "drizzle-orm/neon-http";
3
+ import type { NeonDatabase as NeonWsDatabase } from "drizzle-orm/neon-serverless";
4
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
5
+ import postgres from "postgres";
6
+ import { type DbTimeoutOptions } from "./connection-config.js";
7
+ export type DbAdapter = "edge" | "node" | "serverless";
8
+ export interface DisposableDbClient<TDb = AnyDrizzleDb> {
9
+ db: TDb;
10
+ dispose: () => Promise<void>;
11
+ }
12
+ export interface DbClientOptions<TSchema extends Record<string, unknown> = Record<string, never>> {
13
+ schema?: TSchema;
14
+ adapter?: DbAdapter;
15
+ replicas?: string[];
16
+ nodeMaxConnections?: number;
17
+ serverlessPool?: Omit<PoolConfig, "connectionString">;
18
+ /**
19
+ * Query/connection timeouts (ms) applied per adapter. Defaults:
20
+ * `statementMs: 10_000`, `queryMs: 15_000`, `connectMs: 10_000` — queries
21
+ * now fail fast instead of pinning a Worker isolate for its full lifetime.
22
+ * Pass `false` per field to disable. The `edge` (neon-http) adapter does
23
+ * not support client-side timeouts and ignores this option entirely —
24
+ * http queries rely on the server-side default `statement_timeout` and
25
+ * the Workers runtime's own limits. See {@link DbTimeoutOptions}.
26
+ */
27
+ timeouts?: DbTimeoutOptions;
28
+ }
29
+ /**
30
+ * Union of the drizzle driver flavors a Voyant deployment can wire up:
31
+ * `PostgresJsDatabase` (node adapter / direct TCP), `NeonHttpDatabase`
32
+ * (edge adapter / Neon HTTP), and `NeonWsDatabase` (edge adapter / Neon
33
+ * serverless WebSocket — the only Workers-compatible flavor that
34
+ * supports real Postgres transactions). Use this as the parameter type
35
+ * for `resolveDb`-style callbacks in module factories so consumers
36
+ * don't need `as unknown as ...` casts when wiring different drivers.
37
+ */
38
+ export type AnyDrizzleDb<TSchema extends Record<string, unknown> = Record<string, never>> = PostgresJsDatabase<TSchema> | NeonHttpDatabase<TSchema> | NeonWsDatabase<TSchema>;
39
+ export declare function createDbClient<TSchema extends Record<string, unknown> = Record<string, never>>(connectionString: string, options?: DbClientOptions<TSchema>): (PostgresJsDatabase<TSchema> & {
40
+ $client: postgres.Sql<{}>;
41
+ }) | (PostgresJsDatabase<Record<string, never>> & {
42
+ $client: postgres.Sql<{}>;
43
+ }) | NeonWsDatabase<TSchema> | (NeonHttpDatabase<TSchema> & {
44
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
45
+ }) | (NeonHttpDatabase<Record<string, never>> & {
46
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
47
+ });
48
+ /**
49
+ * Create a per-request Neon WebSocket pool + drizzle client.
50
+ *
51
+ * Timeout defaults (overridable via `timeouts`, or per-field via `pool`):
52
+ * `statement_timeout: 10_000`, `query_timeout: 15_000`,
53
+ * `connectionTimeoutMillis: 10_000`. Both `statement_timeout` (server-side)
54
+ * and `query_timeout` (client-side) are set because transaction-mode poolers
55
+ * (PgBouncer) may ignore `statement_timeout` as a startup parameter — see
56
+ * {@link resolveServerlessPoolConfig}.
57
+ *
58
+ * Warns (once per connection string) when pointed at a Neon direct endpoint
59
+ * instead of the `-pooler` host.
60
+ */
61
+ export declare function createServerlessDbClient<TSchema extends Record<string, unknown> = Record<string, never>>(connectionString: string, options?: {
62
+ schema?: TSchema;
63
+ pool?: Omit<PoolConfig, "connectionString">;
64
+ timeouts?: DbTimeoutOptions;
65
+ }): DisposableDbClient<NeonWsDatabase<TSchema>>;
66
+ /**
67
+ * Run `fn` with a scoped transaction-capable client (Neon WebSocket
68
+ * Pool), disposing it on settle. For code paths that need
69
+ * `db.transaction(...)` but run outside the request middleware that
70
+ * normally provides the transactional client — event handlers, workflow
71
+ * steps, scheduled jobs, scripts.
72
+ *
73
+ * const result = await withServerlessDb(env.DATABASE_URL, (db) =>
74
+ * db.transaction(async (tx) => { ... }),
75
+ * )
76
+ */
77
+ export declare function withServerlessDb<T, TSchema extends Record<string, unknown> = Record<string, never>>(connectionString: string, fn: (db: NeonWsDatabase<TSchema>) => Promise<T>, options?: {
78
+ schema?: TSchema;
79
+ pool?: Omit<PoolConfig, "connectionString">;
80
+ timeouts?: DbTimeoutOptions;
81
+ }): Promise<T>;
82
+ /**
83
+ * Get the main database instance for the configured `DATABASE_URL`.
84
+ * (Single-database deployments; region is chosen per deployment.)
85
+ */
86
+ export declare function getDb(adapter?: DbAdapter): (PostgresJsDatabase<Record<string, never>> & {
87
+ $client: postgres.Sql<{}>;
88
+ }) | (NeonHttpDatabase<Record<string, never>> & {
89
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
90
+ }) | NeonWsDatabase<Record<string, never>>;
91
+ export declare const db: (PostgresJsDatabase<Record<string, never>> & {
92
+ $client: postgres.Sql<{}>;
93
+ }) | (NeonHttpDatabase<Record<string, never>> & {
94
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
95
+ }) | (PostgresJsDatabase<Record<string, unknown>> & {
96
+ $client: postgres.Sql<{}>;
97
+ }) | NeonWsDatabase<Record<string, unknown>> | (NeonHttpDatabase<Record<string, unknown>> & {
98
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
99
+ });
100
+ export * from "./connection-config.js";
101
+ export * from "./helpers.js";
102
+ export * from "./lib/index.js";
103
+ export * from "./lifecycle.js";
104
+ export * from "./queries/index.js";
105
+ export { withOptionalTransaction } from "./transaction.js";
106
+ export * from "./transaction-capability.js";
107
+ export * from "./types.js";
108
+ export * from "./utils.js";
109
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}