@kronos-ts/drizzle 0.2.4 → 0.3.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.
@@ -10,6 +10,26 @@ export interface DrizzleDatabaseLike {
10
10
  * The Drizzle transaction object — has the same query API as the database.
11
11
  */
12
12
  export type DrizzleTransaction = any;
13
+ export interface DrizzleTransactionManagerOptions {
14
+ /**
15
+ * Runs once on every transaction, right after it opens and before the UoW
16
+ * gets the handle. This is where a Postgres-backed deployment arms session
17
+ * GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
18
+ * (e.g. a hung dead-letter drain whose replay never returns) is aborted by
19
+ * the database instead of pinning a connection indefinitely. The Postgres
20
+ * adapter does this for its own transactions; this hook is the equivalent
21
+ * seam for the (DB-agnostic) Drizzle/Knex path. No-op by default.
22
+ *
23
+ * Example (postgres-js driver):
24
+ * ```ts
25
+ * drizzleTransactionManager(db, {
26
+ * onBeginTransaction: (tx) => tx.execute(sql.raw(
27
+ * "SET LOCAL idle_in_transaction_session_timeout = 30000")),
28
+ * })
29
+ * ```
30
+ */
31
+ readonly onBeginTransaction?: (tx: DrizzleTransaction) => Promise<void>;
32
+ }
13
33
  /**
14
34
  * Creates a TransactionManager for Drizzle ORM.
15
35
  *
@@ -32,5 +52,5 @@ export type DrizzleTransaction = any;
32
52
  * const txManager = drizzleTransactionManager(db)
33
53
  * ```
34
54
  */
35
- export declare function drizzleTransactionManager(db: DrizzleDatabaseLike): TransactionManager<DrizzleTransaction>;
55
+ export declare function drizzleTransactionManager(db: DrizzleDatabaseLike, options?: DrizzleTransactionManagerOptions): TransactionManager<DrizzleTransaction>;
36
56
  //# sourceMappingURL=drizzle-transaction-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle-transaction-manager.d.ts","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAEpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,mBAAmB,GACtB,kBAAkB,CAAC,kBAAkB,CAAC,CA2CxC"}
1
+ {"version":3,"file":"drizzle-transaction-manager.d.ts","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAEpC,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACxE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,mBAAmB,EACvB,OAAO,GAAE,gCAAqC,GAC7C,kBAAkB,CAAC,kBAAkB,CAAC,CA6DxC"}
@@ -20,23 +20,42 @@
20
20
  * const txManager = drizzleTransactionManager(db)
21
21
  * ```
22
22
  */
23
- export function drizzleTransactionManager(db) {
23
+ export function drizzleTransactionManager(db, options = {}) {
24
+ const { onBeginTransaction } = options;
24
25
  return {
25
26
  async begin() {
26
27
  let resolveTx;
28
+ let rejectTx;
27
29
  let resolveCompletion;
28
30
  let rejectCompletion;
29
- const txReady = new Promise((resolve) => {
31
+ const txReady = new Promise((resolve, reject) => {
30
32
  resolveTx = resolve;
33
+ rejectTx = reject;
31
34
  });
32
35
  const completionSignal = new Promise((resolve, reject) => {
33
36
  resolveCompletion = resolve;
34
37
  rejectCompletion = reject;
35
38
  });
36
39
  const txPromise = db.transaction(async (tx) => {
40
+ // Arm session settings (e.g. idle-in-transaction timeout) before the
41
+ // UoW gets the handle, so begin() only resolves once the tx is bounded.
42
+ if (onBeginTransaction) {
43
+ try {
44
+ await onBeginTransaction(tx);
45
+ }
46
+ catch (err) {
47
+ // Surface as a begin() rejection rather than hanging on txReady.
48
+ rejectTx(err);
49
+ throw err;
50
+ }
51
+ }
37
52
  resolveTx(tx);
38
53
  await completionSignal;
39
54
  });
55
+ // If db.transaction() rejects before onBeginTransaction runs (e.g. the
56
+ // pool can't hand out a connection), make begin() reject instead of
57
+ // hanging on txReady forever.
58
+ txPromise.catch(rejectTx);
40
59
  const tx = await txReady;
41
60
  tx.__kronos_commit = resolveCompletion;
42
61
  tx.__kronos_rollback = rejectCompletion;
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle-transaction-manager.js","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,yBAAyB,CACvC,EAAuB;IAEvB,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,SAA4C,CAAA;YAChD,IAAI,iBAA8B,CAAA;YAClC,IAAI,gBAA2C,CAAA;YAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,EAAE;gBAC1D,SAAS,GAAG,OAAO,CAAA;YACrB,CAAC,CAAC,CAAA;YAEF,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7D,iBAAiB,GAAG,OAAO,CAAA;gBAC3B,gBAAgB,GAAG,MAAM,CAAA;YAC3B,CAAC,CAAC,CAAA;YAEF,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAC5C,SAAS,CAAC,EAAE,CAAC,CAAA;gBACb,MAAM,gBAAgB,CAAA;YACxB,CAAC,CAAC,CAAA;YAEF,MAAM,EAAE,GAAG,MAAM,OAAO,CACvB;YAAC,EAAU,CAAC,eAAe,GAAG,iBAAiB,CAC/C;YAAC,EAAU,CAAC,iBAAiB,GAAG,gBAAgB,CAChD;YAAC,EAAU,CAAC,kBAAkB,GAAG,SAAS,CAAA;YAE3C,OAAO,EAAE,CAAA;QACX,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAsB;YACjC,MAAM,MAAM,GAAI,EAAU,CAAC,eAA6B,CAAA;YACxD,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,MAAM,EAAE,CAAA;YACR,MAAM,SAAS,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,EAAsB;YACnC,MAAM,QAAQ,GAAI,EAAU,CAAC,iBAA6C,CAAA;YAC1E,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,QAAQ,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAA;YAC9C,IAAI,CAAC;gBAAC,MAAM,SAAS,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;QAClD,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"drizzle-transaction-manager.js","sourceRoot":"","sources":["../src/drizzle-transaction-manager.ts"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,yBAAyB,CACvC,EAAuB,EACvB,UAA4C,EAAE;IAE9C,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAA;IACtC,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,SAA4C,CAAA;YAChD,IAAI,QAAmC,CAAA;YACvC,IAAI,iBAA8B,CAAA;YAClC,IAAI,gBAA2C,CAAA;YAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAClE,SAAS,GAAG,OAAO,CAAA;gBACnB,QAAQ,GAAG,MAAM,CAAA;YACnB,CAAC,CAAC,CAAA;YAEF,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7D,iBAAiB,GAAG,OAAO,CAAA;gBAC3B,gBAAgB,GAAG,MAAM,CAAA;YAC3B,CAAC,CAAC,CAAA;YAEF,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAC5C,qEAAqE;gBACrE,wEAAwE;gBACxE,IAAI,kBAAkB,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,kBAAkB,CAAC,EAAE,CAAC,CAAA;oBAC9B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,iEAAiE;wBACjE,QAAQ,CAAC,GAAG,CAAC,CAAA;wBACb,MAAM,GAAG,CAAA;oBACX,CAAC;gBACH,CAAC;gBACD,SAAS,CAAC,EAAE,CAAC,CAAA;gBACb,MAAM,gBAAgB,CAAA;YACxB,CAAC,CAAC,CAAA;YACF,uEAAuE;YACvE,oEAAoE;YACpE,8BAA8B;YAC9B,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAEzB,MAAM,EAAE,GAAG,MAAM,OAAO,CACvB;YAAC,EAAU,CAAC,eAAe,GAAG,iBAAiB,CAC/C;YAAC,EAAU,CAAC,iBAAiB,GAAG,gBAAgB,CAChD;YAAC,EAAU,CAAC,kBAAkB,GAAG,SAAS,CAAA;YAE3C,OAAO,EAAE,CAAA;QACX,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAsB;YACjC,MAAM,MAAM,GAAI,EAAU,CAAC,eAA6B,CAAA;YACxD,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,MAAM,EAAE,CAAA;YACR,MAAM,SAAS,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,EAAsB;YACnC,MAAM,QAAQ,GAAI,EAAU,CAAC,iBAA6C,CAAA;YAC1E,MAAM,SAAS,GAAI,EAAU,CAAC,kBAAmC,CAAA;YACjE,QAAQ,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAA;YAC9C,IAAI,CAAC;gBAAC,MAAM,SAAS,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;QAClD,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { drizzleTransactionManager, type DrizzleDatabaseLike, type DrizzleTransaction, } from "./drizzle-transaction-manager.js";
1
+ export { drizzleTransactionManager, type DrizzleDatabaseLike, type DrizzleTransaction, type DrizzleTransactionManagerOptions, } from "./drizzle-transaction-manager.js";
2
2
  export { drizzleTokenStore, type DrizzleTokenStoreConfig, } from "./drizzle-token-store.js";
3
3
  export { drizzleDeadLetterQueue, type DrizzleDeadLetterQueueConfig, } from "./drizzle-dead-letter-queue.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,EACjB,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,GAClC,MAAM,gCAAgC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,EACjB,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,GAClC,MAAM,gCAAgC,CAAA"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAG1B,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,GAElB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,GAEvB,MAAM,gCAAgC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAI1B,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EACL,iBAAiB,GAElB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,GAEvB,MAAM,gCAAgC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kronos-ts/drizzle",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "Drizzle ORM extension for Kronos.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@kronos-ts/common": "0.1.1",
53
- "@kronos-ts/messaging": "0.7.0"
53
+ "@kronos-ts/messaging": "0.8.0"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "drizzle-orm": ">=0.30.0"
@@ -13,6 +13,27 @@ export interface DrizzleDatabaseLike {
13
13
  */
14
14
  export type DrizzleTransaction = any
15
15
 
16
+ export interface DrizzleTransactionManagerOptions {
17
+ /**
18
+ * Runs once on every transaction, right after it opens and before the UoW
19
+ * gets the handle. This is where a Postgres-backed deployment arms session
20
+ * GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
21
+ * (e.g. a hung dead-letter drain whose replay never returns) is aborted by
22
+ * the database instead of pinning a connection indefinitely. The Postgres
23
+ * adapter does this for its own transactions; this hook is the equivalent
24
+ * seam for the (DB-agnostic) Drizzle/Knex path. No-op by default.
25
+ *
26
+ * Example (postgres-js driver):
27
+ * ```ts
28
+ * drizzleTransactionManager(db, {
29
+ * onBeginTransaction: (tx) => tx.execute(sql.raw(
30
+ * "SET LOCAL idle_in_transaction_session_timeout = 30000")),
31
+ * })
32
+ * ```
33
+ */
34
+ readonly onBeginTransaction?: (tx: DrizzleTransaction) => Promise<void>
35
+ }
36
+
16
37
  /**
17
38
  * Creates a TransactionManager for Drizzle ORM.
18
39
  *
@@ -37,15 +58,19 @@ export type DrizzleTransaction = any
37
58
  */
38
59
  export function drizzleTransactionManager(
39
60
  db: DrizzleDatabaseLike,
61
+ options: DrizzleTransactionManagerOptions = {},
40
62
  ): TransactionManager<DrizzleTransaction> {
63
+ const { onBeginTransaction } = options
41
64
  return {
42
65
  async begin(): Promise<DrizzleTransaction> {
43
66
  let resolveTx!: (tx: DrizzleTransaction) => void
67
+ let rejectTx!: (error: unknown) => void
44
68
  let resolveCompletion!: () => void
45
69
  let rejectCompletion!: (error: unknown) => void
46
70
 
47
- const txReady = new Promise<DrizzleTransaction>((resolve) => {
71
+ const txReady = new Promise<DrizzleTransaction>((resolve, reject) => {
48
72
  resolveTx = resolve
73
+ rejectTx = reject
49
74
  })
50
75
 
51
76
  const completionSignal = new Promise<void>((resolve, reject) => {
@@ -54,9 +79,24 @@ export function drizzleTransactionManager(
54
79
  })
55
80
 
56
81
  const txPromise = db.transaction(async (tx) => {
82
+ // Arm session settings (e.g. idle-in-transaction timeout) before the
83
+ // UoW gets the handle, so begin() only resolves once the tx is bounded.
84
+ if (onBeginTransaction) {
85
+ try {
86
+ await onBeginTransaction(tx)
87
+ } catch (err) {
88
+ // Surface as a begin() rejection rather than hanging on txReady.
89
+ rejectTx(err)
90
+ throw err
91
+ }
92
+ }
57
93
  resolveTx(tx)
58
94
  await completionSignal
59
95
  })
96
+ // If db.transaction() rejects before onBeginTransaction runs (e.g. the
97
+ // pool can't hand out a connection), make begin() reject instead of
98
+ // hanging on txReady forever.
99
+ txPromise.catch(rejectTx)
60
100
 
61
101
  const tx = await txReady
62
102
  ;(tx as any).__kronos_commit = resolveCompletion
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export {
2
2
  drizzleTransactionManager,
3
3
  type DrizzleDatabaseLike,
4
4
  type DrizzleTransaction,
5
+ type DrizzleTransactionManagerOptions,
5
6
  } from "./drizzle-transaction-manager.js"
6
7
 
7
8
  export {