@kronos-ts/knex 0.2.3 → 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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { knexTransactionManager, type KnexInstanceLike, type KnexTransaction, } from "./knex-transaction-manager.js";
1
+ export { knexTransactionManager, type KnexInstanceLike, type KnexTransaction, type KnexTransactionManagerOptions, } from "./knex-transaction-manager.js";
2
2
  export { knexTokenStore, type KnexQueryable, } from "./knex-token-store.js";
3
3
  export { knexDeadLetterQueue, type KnexDeadLetterQueueConfig, } from "./knex-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,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,cAAc,EACd,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,mBAAmB,EACnB,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,6BAA6B,GACnC,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,cAAc,EACd,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,mBAAmB,EACnB,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,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,sBAAsB,GAGvB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,cAAc,GAEf,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,mBAAmB,GAEpB,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,GAIvB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,cAAc,GAEf,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,mBAAmB,GAEpB,MAAM,6BAA6B,CAAA"}
@@ -9,6 +9,26 @@ export interface KnexInstanceLike {
9
9
  * The Knex transaction object.
10
10
  */
11
11
  export type KnexTransaction = any;
12
+ export interface KnexTransactionManagerOptions {
13
+ /**
14
+ * Runs once on every transaction, right after it opens and before the UoW
15
+ * gets the handle. This is where a Postgres-backed deployment arms session
16
+ * GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
17
+ * (e.g. a hung dead-letter drain whose replay never returns) is aborted by
18
+ * the database instead of pinning a connection indefinitely. The Postgres
19
+ * adapter does this for its own transactions; this hook is the equivalent
20
+ * seam for the (DB-agnostic) Knex/Drizzle path. No-op by default.
21
+ *
22
+ * Example (pg client):
23
+ * ```ts
24
+ * knexTransactionManager(knex, {
25
+ * onBeginTransaction: (trx) => trx.raw(
26
+ * "SET LOCAL idle_in_transaction_session_timeout = 30000"),
27
+ * })
28
+ * ```
29
+ */
30
+ readonly onBeginTransaction?: (tx: KnexTransaction) => Promise<void>;
31
+ }
12
32
  /**
13
33
  * Creates a TransactionManager for Knex.
14
34
  *
@@ -27,5 +47,5 @@ export type KnexTransaction = any;
27
47
  * const txManager = knexTransactionManager(knex)
28
48
  * ```
29
49
  */
30
- export declare function knexTransactionManager(knex: KnexInstanceLike): TransactionManager<KnexTransaction>;
50
+ export declare function knexTransactionManager(knex: KnexInstanceLike, options?: KnexTransactionManagerOptions): TransactionManager<KnexTransaction>;
31
51
  //# sourceMappingURL=knex-transaction-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"knex-transaction-manager.d.ts","sourceRoot":"","sources":["../src/knex-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACzD;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAA;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,gBAAgB,GACrB,kBAAkB,CAAC,eAAe,CAAC,CA2CrC"}
1
+ {"version":3,"file":"knex-transaction-manager.d.ts","sourceRoot":"","sources":["../src/knex-transaction-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACzD;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAA;AAEjC,MAAM,WAAW,6BAA6B;IAC5C;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACrE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,gBAAgB,EACtB,OAAO,GAAE,6BAAkC,GAC1C,kBAAkB,CAAC,eAAe,CAAC,CA4DrC"}
@@ -16,23 +16,41 @@
16
16
  * const txManager = knexTransactionManager(knex)
17
17
  * ```
18
18
  */
19
- export function knexTransactionManager(knex) {
19
+ export function knexTransactionManager(knex, options = {}) {
20
+ const { onBeginTransaction } = options;
20
21
  return {
21
22
  async begin() {
22
23
  let resolveTx;
24
+ let rejectTx;
23
25
  let resolveCompletion;
24
26
  let rejectCompletion;
25
- const txReady = new Promise((resolve) => {
27
+ const txReady = new Promise((resolve, reject) => {
26
28
  resolveTx = resolve;
29
+ rejectTx = reject;
27
30
  });
28
31
  const completionSignal = new Promise((resolve, reject) => {
29
32
  resolveCompletion = resolve;
30
33
  rejectCompletion = reject;
31
34
  });
32
35
  const txPromise = knex.transaction(async (trx) => {
36
+ // Arm session settings (e.g. idle-in-transaction timeout) before the
37
+ // UoW gets the handle, so begin() only resolves once the tx is bounded.
38
+ if (onBeginTransaction) {
39
+ try {
40
+ await onBeginTransaction(trx);
41
+ }
42
+ catch (err) {
43
+ rejectTx(err);
44
+ throw err;
45
+ }
46
+ }
33
47
  resolveTx(trx);
34
48
  await completionSignal;
35
49
  });
50
+ // If knex.transaction() rejects before onBeginTransaction runs (e.g. the
51
+ // pool can't hand out a connection), make begin() reject instead of
52
+ // hanging on txReady forever.
53
+ txPromise.catch(rejectTx);
36
54
  const tx = await txReady;
37
55
  tx.__kronos_commit = resolveCompletion;
38
56
  tx.__kronos_rollback = rejectCompletion;
@@ -1 +1 @@
1
- {"version":3,"file":"knex-transaction-manager.js","sourceRoot":"","sources":["../src/knex-transaction-manager.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAsB;IAEtB,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,SAAyC,CAAA;YAC7C,IAAI,iBAA8B,CAAA;YAClC,IAAI,gBAA2C,CAAA;YAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAkB,CAAC,OAAO,EAAE,EAAE;gBACvD,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,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC/C,SAAS,CAAC,GAAG,CAAC,CAAA;gBACd,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,EAAmB;YAC9B,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,EAAmB;YAChC,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":"knex-transaction-manager.js","sourceRoot":"","sources":["../src/knex-transaction-manager.ts"],"names":[],"mappings":"AAmCA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAsB,EACtB,UAAyC,EAAE;IAE3C,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAA;IACtC,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,SAAyC,CAAA;YAC7C,IAAI,QAAmC,CAAA;YACvC,IAAI,iBAA8B,CAAA;YAClC,IAAI,gBAA2C,CAAA;YAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC/D,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,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC/C,qEAAqE;gBACrE,wEAAwE;gBACxE,IAAI,kBAAkB,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAA;oBAC/B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,QAAQ,CAAC,GAAG,CAAC,CAAA;wBACb,MAAM,GAAG,CAAA;oBACX,CAAC;gBACH,CAAC;gBACD,SAAS,CAAC,GAAG,CAAC,CAAA;gBACd,MAAM,gBAAgB,CAAA;YACxB,CAAC,CAAC,CAAA;YACF,yEAAyE;YACzE,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,EAAmB;YAC9B,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,EAAmB;YAChC,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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kronos-ts/knex",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Knex extension for Kronos.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@kronos-ts/common": "0.1.1",
52
- "@kronos-ts/messaging": "0.6.0"
52
+ "@kronos-ts/messaging": "0.8.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "knex": ">=3.0.0"
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export {
2
2
  knexTransactionManager,
3
3
  type KnexInstanceLike,
4
4
  type KnexTransaction,
5
+ type KnexTransactionManagerOptions,
5
6
  } from "./knex-transaction-manager.js"
6
7
 
7
8
  export {
@@ -12,6 +12,27 @@ export interface KnexInstanceLike {
12
12
  */
13
13
  export type KnexTransaction = any
14
14
 
15
+ export interface KnexTransactionManagerOptions {
16
+ /**
17
+ * Runs once on every transaction, right after it opens and before the UoW
18
+ * gets the handle. This is where a Postgres-backed deployment arms session
19
+ * GUCs — chiefly `idle_in_transaction_session_timeout` — so a stalled UoW
20
+ * (e.g. a hung dead-letter drain whose replay never returns) is aborted by
21
+ * the database instead of pinning a connection indefinitely. The Postgres
22
+ * adapter does this for its own transactions; this hook is the equivalent
23
+ * seam for the (DB-agnostic) Knex/Drizzle path. No-op by default.
24
+ *
25
+ * Example (pg client):
26
+ * ```ts
27
+ * knexTransactionManager(knex, {
28
+ * onBeginTransaction: (trx) => trx.raw(
29
+ * "SET LOCAL idle_in_transaction_session_timeout = 30000"),
30
+ * })
31
+ * ```
32
+ */
33
+ readonly onBeginTransaction?: (tx: KnexTransaction) => Promise<void>
34
+ }
35
+
15
36
  /**
16
37
  * Creates a TransactionManager for Knex.
17
38
  *
@@ -32,15 +53,19 @@ export type KnexTransaction = any
32
53
  */
33
54
  export function knexTransactionManager(
34
55
  knex: KnexInstanceLike,
56
+ options: KnexTransactionManagerOptions = {},
35
57
  ): TransactionManager<KnexTransaction> {
58
+ const { onBeginTransaction } = options
36
59
  return {
37
60
  async begin(): Promise<KnexTransaction> {
38
61
  let resolveTx!: (tx: KnexTransaction) => void
62
+ let rejectTx!: (error: unknown) => void
39
63
  let resolveCompletion!: () => void
40
64
  let rejectCompletion!: (error: unknown) => void
41
65
 
42
- const txReady = new Promise<KnexTransaction>((resolve) => {
66
+ const txReady = new Promise<KnexTransaction>((resolve, reject) => {
43
67
  resolveTx = resolve
68
+ rejectTx = reject
44
69
  })
45
70
 
46
71
  const completionSignal = new Promise<void>((resolve, reject) => {
@@ -49,9 +74,23 @@ export function knexTransactionManager(
49
74
  })
50
75
 
51
76
  const txPromise = knex.transaction(async (trx) => {
77
+ // Arm session settings (e.g. idle-in-transaction timeout) before the
78
+ // UoW gets the handle, so begin() only resolves once the tx is bounded.
79
+ if (onBeginTransaction) {
80
+ try {
81
+ await onBeginTransaction(trx)
82
+ } catch (err) {
83
+ rejectTx(err)
84
+ throw err
85
+ }
86
+ }
52
87
  resolveTx(trx)
53
88
  await completionSignal
54
89
  })
90
+ // If knex.transaction() rejects before onBeginTransaction runs (e.g. the
91
+ // pool can't hand out a connection), make begin() reject instead of
92
+ // hanging on txReady forever.
93
+ txPromise.catch(rejectTx)
55
94
 
56
95
  const tx = await txReady
57
96
  ;(tx as any).__kronos_commit = resolveCompletion