@relaybus/postgres 0.4.0 → 0.5.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/README.md +28 -15
- package/dist/chunk-5WWPAN5Q.js +26 -0
- package/dist/chunk-5WWPAN5Q.js.map +1 -0
- package/dist/chunk-FY65AUUF.js +40 -0
- package/dist/chunk-FY65AUUF.js.map +1 -0
- package/dist/chunk-UDBN4RRV.js +35 -0
- package/dist/chunk-UDBN4RRV.js.map +1 -0
- package/dist/drizzle.cjs +24 -0
- package/dist/drizzle.cjs.map +1 -1
- package/dist/drizzle.d.cts +1 -0
- package/dist/drizzle.d.ts +1 -0
- package/dist/drizzle.js +2 -1
- package/dist/drizzle.js.map +1 -1
- package/dist/{executor-CfJgktC6.d.cts → executor-Bt90w33Q.d.cts} +24 -1
- package/dist/{executor-CfJgktC6.d.ts → executor-Bt90w33Q.d.ts} +24 -1
- package/dist/index.cjs +226 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -7
- package/dist/index.d.ts +25 -7
- package/dist/index.js +194 -79
- package/dist/index.js.map +1 -1
- package/dist/knex.cjs +24 -0
- package/dist/knex.cjs.map +1 -1
- package/dist/knex.d.cts +1 -0
- package/dist/knex.d.ts +1 -0
- package/dist/knex.js +2 -1
- package/dist/knex.js.map +1 -1
- package/dist/kysely.cjs +24 -0
- package/dist/kysely.cjs.map +1 -1
- package/dist/kysely.d.cts +1 -0
- package/dist/kysely.d.ts +1 -0
- package/dist/kysely.js +2 -1
- package/dist/kysely.js.map +1 -1
- package/dist/prisma.cjs +24 -0
- package/dist/prisma.cjs.map +1 -1
- package/dist/prisma.d.cts +2 -1
- package/dist/prisma.d.ts +2 -1
- package/dist/prisma.js +2 -1
- package/dist/prisma.js.map +1 -1
- package/dist/typeorm.cjs +46 -0
- package/dist/typeorm.cjs.map +1 -1
- package/dist/typeorm.d.cts +1 -0
- package/dist/typeorm.d.ts +1 -0
- package/dist/typeorm.js +11 -1
- package/dist/typeorm.js.map +1 -1
- package/package.json +6 -5
- package/dist/chunk-NNZJR5AB.js +0 -12
- package/dist/chunk-NNZJR5AB.js.map +0 -1
package/dist/knex.cjs
CHANGED
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/transaction-timeouts.ts
|
|
4
|
+
function budgetSettingsSql({ value, sessionTimeouts, scope }) {
|
|
5
|
+
const local = scope === "transaction";
|
|
6
|
+
const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;
|
|
7
|
+
{
|
|
8
|
+
return statementTimeout;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function budgetValue(timeoutMs) {
|
|
12
|
+
return `${Math.ceil(timeoutMs)}ms`;
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
// src/adapter-executor.ts
|
|
4
16
|
function adapterExecutor(client) {
|
|
5
17
|
return {
|
|
6
18
|
transaction: client.transaction,
|
|
19
|
+
...client.transactionAt === void 0 ? {} : {
|
|
20
|
+
// The level is set by the library at BEGIN, so the budget statement can follow as the first query.
|
|
21
|
+
transactionWithIsolation: (work, { isolationLevel, timeoutMs }) => client.transactionAt(isolationLevel, async (queryable) => {
|
|
22
|
+
const sql = budgetSettingsSql({
|
|
23
|
+
value: "$1",
|
|
24
|
+
sessionTimeouts: false,
|
|
25
|
+
scope: "transaction"
|
|
26
|
+
});
|
|
27
|
+
await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });
|
|
28
|
+
return work(queryable);
|
|
29
|
+
})
|
|
30
|
+
},
|
|
7
31
|
// eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature
|
|
8
32
|
query: (sql, parameters, transaction) => client.run(transaction ?? client.root, { sql, parameters })
|
|
9
33
|
};
|
package/dist/knex.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-executor.ts","../src/positional-sql.ts","../src/knex/knex-executor.ts"],"names":[],"mappings":";;;AAqBO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA;AAAA,IAEpB,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;;;ACrBO,SAAS,mBAAmB,GAAA,EAAkC;AACnE,EAAA,MAAM,QAA6B,EAAC;AACpC,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,KAAA,MAAW,KAAA,IAAS,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,SAAA,EAAW,MAAM,KAAK,CAAA,EAAG,EAAE,cAAA,EAAgB,OAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,GAAG,CAAA;AACtF,IAAA,SAAA,GAAY,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,CAAE,MAAA;AAAA,EACrC;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAC/B,EAAA,OAAO,KAAA;AACT;;;ACAO,SAAS,mBAAmB,IAAA,EAAiD;AAClF,EAAA,OAAO,eAAA,CAA+B;AAAA,IACpC,IAAA,EAAM,IAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IAC5C,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,MAAM,KAAA,GAAQ,mBAAmB,GAAG,CAAA;AACpC,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,GAAI,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AACpF,MAAA,MAAM,WAAW,KAAA,CAAM,OAAA;AAAA,QAAQ,CAAC,IAAA,KAC9B,OAAO,IAAA,KAAS,QAAA,GAAW,EAAC,GAAI,CAAC,UAAA,CAAW,IAAA,CAAK,cAAc,CAAC;AAAA,OAClE;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,GAAA,CAAI,SAAS,QAAQ,CAAA;AACpD,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAAA,GACD,CAAA;AACH","file":"knex.cjs","sourcesContent":["import type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","/** A piece of SQL text, or a reference to the (zero-based) parameter that stands at this position. */\nexport type PositionalSqlPart = string | { readonly parameterIndex: number };\n\n/**\n * Splits SQL written with PostgreSQL `$1, $2, ...` placeholders into text and\n * parameter references, in order of appearance. A placeholder used twice\n * appears twice. Adapters for libraries with their own placeholder syntax\n * (Knex `?`, Drizzle parameter chunks) rebuild the statement from the parts.\n */\nexport function splitPositionalSql(sql: string): PositionalSqlPart[] {\n const parts: PositionalSqlPart[] = [];\n let textStart = 0;\n for (const match of sql.matchAll(/\\$(\\d+)/g)) {\n parts.push(sql.slice(textStart, match.index), { parameterIndex: Number(match[1]) - 1 });\n textStart = match.index + match[0].length;\n }\n parts.push(sql.slice(textStart));\n return parts;\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\nimport { splitPositionalSql } from '../positional-sql.js';\n\n/** What a Knex instance and a Knex transaction have in common. */\nexport interface KnexQueryable {\n raw(sql: string, bindings: readonly unknown[]): PromiseLike<{ readonly rows: PostgresRow[] }>;\n}\n\n/** The part of a `Knex` instance the executor uses. */\nexport interface KnexLike extends KnexQueryable {\n transaction<T>(work: (transaction: KnexQueryable) => Promise<T>): Promise<T>;\n}\n\n/**\n * Executor for Knex with the `pg` client. The transaction handle is a Knex\n * transaction: pass `trx` from `knex.transaction(async (trx) => ...)`.\n */\nexport function createKnexExecutor(knex: KnexLike): PostgresExecutor<KnexQueryable> {\n return adapterExecutor<KnexQueryable>({\n root: knex,\n transaction: (work) => knex.transaction(work),\n async run(queryable, { sql, parameters }) {\n const parts = splitPositionalSql(sql);\n const knexSql = parts.map((part) => (typeof part === 'string' ? part : '?')).join('');\n const bindings = parts.flatMap((part) =>\n typeof part === 'string' ? [] : [parameters[part.parameterIndex]],\n );\n const result = await queryable.raw(knexSql, bindings);\n return result.rows;\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/transaction-timeouts.ts","../src/adapter-executor.ts","../src/positional-sql.ts","../src/knex/knex-executor.ts"],"names":[],"mappings":";;;AAiBO,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,eAAA,EAAiB,OAAM,EAA2B;AAC3F,EAAA,MAAM,QAAQ,KAAA,KAAU,aAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,CAAA,uCAAA,EAA0C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAClF,EAAsB;AACpB,IAAA,OAAO,gBAAA;AAAA,EACT;AAMF;AAQO,SAAS,YAAY,SAAA,EAA2B;AACrD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA,EAAA,CAAA;AAChC;;;ACNO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,GAAI,MAAA,CAAO,aAAA,KAAkB,MAAA,GACzB,EAAC,GACD;AAAA;AAAA,MAEE,wBAAA,EAA0B,CAAC,IAAA,EAAM,EAAE,cAAA,EAAgB,SAAA,EAAU,KAC3D,MAAA,CAAO,aAAA,CAAe,cAAA,EAAgB,OAAO,SAAA,KAAc;AACzD,QAAA,MAAM,MAAM,iBAAA,CAAkB;AAAA,UAC5B,KAAA,EAAO,IAAA;AAAA,UACP,eAAA,EAAiB,KAAA;AAAA,UACjB,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA,MAAM,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,CAAA;AACzE,QAAA,OAAO,KAAK,SAAS,CAAA;AAAA,MACvB,CAAC;AAAA,KACL;AAAA;AAAA,IAEJ,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;;;AC/CO,SAAS,mBAAmB,GAAA,EAAkC;AACnE,EAAA,MAAM,QAA6B,EAAC;AACpC,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,KAAA,MAAW,KAAA,IAAS,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,EAAG;AAC5C,IAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,SAAA,EAAW,MAAM,KAAK,CAAA,EAAG,EAAE,cAAA,EAAgB,OAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,GAAG,CAAA;AACtF,IAAA,SAAA,GAAY,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,CAAE,MAAA;AAAA,EACrC;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAC/B,EAAA,OAAO,KAAA;AACT;;;ACAO,SAAS,mBAAmB,IAAA,EAAiD;AAClF,EAAA,OAAO,eAAA,CAA+B;AAAA,IACpC,IAAA,EAAM,IAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IAC5C,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,MAAM,KAAA,GAAQ,mBAAmB,GAAG,CAAA;AACpC,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,GAAI,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AACpF,MAAA,MAAM,WAAW,KAAA,CAAM,OAAA;AAAA,QAAQ,CAAC,IAAA,KAC9B,OAAO,IAAA,KAAS,QAAA,GAAW,EAAC,GAAI,CAAC,UAAA,CAAW,IAAA,CAAK,cAAc,CAAC;AAAA,OAClE;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,GAAA,CAAI,SAAS,QAAQ,CAAA;AACpD,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAAA,GACD,CAAA;AACH","file":"knex.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import type { TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /**\n * Optional. Opens a transaction at an isolation level through the library's own API, for a library\n * that runs code of its own (hooks, subscribers) right after it begins a transaction: that code\n * would otherwise run a query before the store's `SET TRANSACTION ISOLATION LEVEL`.\n */\n readonly transactionAt?: <T>(\n isolationLevel: TransactionIsolationLevel,\n work: (queryable: TQueryable) => Promise<T>,\n ) => Promise<T>;\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n ...(client.transactionAt === undefined\n ? {}\n : {\n // The level is set by the library at BEGIN, so the budget statement can follow as the first query.\n transactionWithIsolation: (work, { isolationLevel, timeoutMs }) =>\n client.transactionAt!(isolationLevel, async (queryable) => {\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: false,\n scope: 'transaction',\n });\n await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });\n return work(queryable);\n }),\n }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","/** A piece of SQL text, or a reference to the (zero-based) parameter that stands at this position. */\nexport type PositionalSqlPart = string | { readonly parameterIndex: number };\n\n/**\n * Splits SQL written with PostgreSQL `$1, $2, ...` placeholders into text and\n * parameter references, in order of appearance. A placeholder used twice\n * appears twice. Adapters for libraries with their own placeholder syntax\n * (Knex `?`, Drizzle parameter chunks) rebuild the statement from the parts.\n */\nexport function splitPositionalSql(sql: string): PositionalSqlPart[] {\n const parts: PositionalSqlPart[] = [];\n let textStart = 0;\n for (const match of sql.matchAll(/\\$(\\d+)/g)) {\n parts.push(sql.slice(textStart, match.index), { parameterIndex: Number(match[1]) - 1 });\n textStart = match.index + match[0].length;\n }\n parts.push(sql.slice(textStart));\n return parts;\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\nimport { splitPositionalSql } from '../positional-sql.js';\n\n/** What a Knex instance and a Knex transaction have in common. */\nexport interface KnexQueryable {\n raw(sql: string, bindings: readonly unknown[]): PromiseLike<{ readonly rows: PostgresRow[] }>;\n}\n\n/** The part of a `Knex` instance the executor uses. */\nexport interface KnexLike extends KnexQueryable {\n transaction<T>(work: (transaction: KnexQueryable) => Promise<T>): Promise<T>;\n}\n\n/**\n * Executor for Knex with the `pg` client. The transaction handle is a Knex\n * transaction: pass `trx` from `knex.transaction(async (trx) => ...)`.\n */\nexport function createKnexExecutor(knex: KnexLike): PostgresExecutor<KnexQueryable> {\n return adapterExecutor<KnexQueryable>({\n root: knex,\n transaction: (work) => knex.transaction(work),\n async run(queryable, { sql, parameters }) {\n const parts = splitPositionalSql(sql);\n const knexSql = parts.map((part) => (typeof part === 'string' ? part : '?')).join('');\n const bindings = parts.flatMap((part) =>\n typeof part === 'string' ? [] : [parameters[part.parameterIndex]],\n );\n const result = await queryable.raw(knexSql, bindings);\n return result.rows;\n },\n });\n}\n"]}
|
package/dist/knex.d.cts
CHANGED
package/dist/knex.d.ts
CHANGED
package/dist/knex.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { splitPositionalSql } from './chunk-UUFSUL2M.js';
|
|
2
|
-
import { adapterExecutor } from './chunk-
|
|
2
|
+
import { adapterExecutor } from './chunk-5WWPAN5Q.js';
|
|
3
|
+
import './chunk-UDBN4RRV.js';
|
|
3
4
|
|
|
4
5
|
// src/knex/knex-executor.ts
|
|
5
6
|
function createKnexExecutor(knex) {
|
package/dist/knex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/knex/knex-executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/knex/knex-executor.ts"],"names":[],"mappings":";;;;;AAkBO,SAAS,mBAAmB,IAAA,EAAiD;AAClF,EAAA,OAAO,eAAA,CAA+B;AAAA,IACpC,IAAA,EAAM,IAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IAC5C,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,MAAM,KAAA,GAAQ,mBAAmB,GAAG,CAAA;AACpC,MAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,GAAI,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AACpF,MAAA,MAAM,WAAW,KAAA,CAAM,OAAA;AAAA,QAAQ,CAAC,IAAA,KAC9B,OAAO,IAAA,KAAS,QAAA,GAAW,EAAC,GAAI,CAAC,UAAA,CAAW,IAAA,CAAK,cAAc,CAAC;AAAA,OAClE;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,GAAA,CAAI,SAAS,QAAQ,CAAA;AACpD,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAAA,GACD,CAAA;AACH","file":"knex.js","sourcesContent":["import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\nimport { splitPositionalSql } from '../positional-sql.js';\n\n/** What a Knex instance and a Knex transaction have in common. */\nexport interface KnexQueryable {\n raw(sql: string, bindings: readonly unknown[]): PromiseLike<{ readonly rows: PostgresRow[] }>;\n}\n\n/** The part of a `Knex` instance the executor uses. */\nexport interface KnexLike extends KnexQueryable {\n transaction<T>(work: (transaction: KnexQueryable) => Promise<T>): Promise<T>;\n}\n\n/**\n * Executor for Knex with the `pg` client. The transaction handle is a Knex\n * transaction: pass `trx` from `knex.transaction(async (trx) => ...)`.\n */\nexport function createKnexExecutor(knex: KnexLike): PostgresExecutor<KnexQueryable> {\n return adapterExecutor<KnexQueryable>({\n root: knex,\n transaction: (work) => knex.transaction(work),\n async run(queryable, { sql, parameters }) {\n const parts = splitPositionalSql(sql);\n const knexSql = parts.map((part) => (typeof part === 'string' ? part : '?')).join('');\n const bindings = parts.flatMap((part) =>\n typeof part === 'string' ? [] : [parameters[part.parameterIndex]],\n );\n const result = await queryable.raw(knexSql, bindings);\n return result.rows;\n },\n });\n}\n"]}
|
package/dist/kysely.cjs
CHANGED
|
@@ -2,10 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
var kysely = require('kysely');
|
|
4
4
|
|
|
5
|
+
// src/transaction-timeouts.ts
|
|
6
|
+
function budgetSettingsSql({ value, sessionTimeouts, scope }) {
|
|
7
|
+
const local = scope === "transaction";
|
|
8
|
+
const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;
|
|
9
|
+
{
|
|
10
|
+
return statementTimeout;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function budgetValue(timeoutMs) {
|
|
14
|
+
return `${Math.ceil(timeoutMs)}ms`;
|
|
15
|
+
}
|
|
16
|
+
|
|
5
17
|
// src/adapter-executor.ts
|
|
6
18
|
function adapterExecutor(client) {
|
|
7
19
|
return {
|
|
8
20
|
transaction: client.transaction,
|
|
21
|
+
...client.transactionAt === void 0 ? {} : {
|
|
22
|
+
// The level is set by the library at BEGIN, so the budget statement can follow as the first query.
|
|
23
|
+
transactionWithIsolation: (work, { isolationLevel, timeoutMs }) => client.transactionAt(isolationLevel, async (queryable) => {
|
|
24
|
+
const sql = budgetSettingsSql({
|
|
25
|
+
value: "$1",
|
|
26
|
+
sessionTimeouts: false,
|
|
27
|
+
scope: "transaction"
|
|
28
|
+
});
|
|
29
|
+
await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });
|
|
30
|
+
return work(queryable);
|
|
31
|
+
})
|
|
32
|
+
},
|
|
9
33
|
// eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature
|
|
10
34
|
query: (sql, parameters, transaction) => client.run(transaction ?? client.root, { sql, parameters })
|
|
11
35
|
};
|
package/dist/kysely.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-executor.ts","../src/kysely/kysely-executor.ts"],"names":["CompiledQuery"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"sources":["../src/transaction-timeouts.ts","../src/adapter-executor.ts","../src/kysely/kysely-executor.ts"],"names":["CompiledQuery"],"mappings":";;;;;AAiBO,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,eAAA,EAAiB,OAAM,EAA2B;AAC3F,EAAA,MAAM,QAAQ,KAAA,KAAU,aAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,CAAA,uCAAA,EAA0C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAClF,EAAsB;AACpB,IAAA,OAAO,gBAAA;AAAA,EACT;AAMF;AAQO,SAAS,YAAY,SAAA,EAA2B;AACrD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA,EAAA,CAAA;AAChC;;;ACNO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,GAAI,MAAA,CAAO,aAAA,KAAkB,MAAA,GACzB,EAAC,GACD;AAAA;AAAA,MAEE,wBAAA,EAA0B,CAAC,IAAA,EAAM,EAAE,cAAA,EAAgB,SAAA,EAAU,KAC3D,MAAA,CAAO,aAAA,CAAe,cAAA,EAAgB,OAAO,SAAA,KAAc;AACzD,QAAA,MAAM,MAAM,iBAAA,CAAkB;AAAA,UAC5B,KAAA,EAAO,IAAA;AAAA,UACP,eAAA,EAAiB,KAAA;AAAA,UACjB,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA,MAAM,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,CAAA;AACzE,QAAA,OAAO,KAAK,SAAS,CAAA;AAAA,MACvB,CAAC;AAAA,KACL;AAAA;AAAA,IAEJ,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;ACnCO,SAAS,qBAAqB,QAAA,EAAyD;AAC5F,EAAA,OAAO,eAAA,CAAiC;AAAA,IACtC,IAAA,EAAM,QAAA;AAAA,IACN,aAAa,CAAC,IAAA,KAAS,SAAS,WAAA,EAAY,CAAE,QAAQ,IAAI,CAAA;AAAA,IAC1D,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,YAAA;AAAA,QAC7BA,qBAAc,GAAA,CAAI,GAAA,EAAK,CAAC,GAAG,UAAU,CAAC;AAAA,OACxC;AACA,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAAA,GACD,CAAA;AACH","file":"kysely.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import type { TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /**\n * Optional. Opens a transaction at an isolation level through the library's own API, for a library\n * that runs code of its own (hooks, subscribers) right after it begins a transaction: that code\n * would otherwise run a query before the store's `SET TRANSACTION ISOLATION LEVEL`.\n */\n readonly transactionAt?: <T>(\n isolationLevel: TransactionIsolationLevel,\n work: (queryable: TQueryable) => Promise<T>,\n ) => Promise<T>;\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n ...(client.transactionAt === undefined\n ? {}\n : {\n // The level is set by the library at BEGIN, so the budget statement can follow as the first query.\n transactionWithIsolation: (work, { isolationLevel, timeoutMs }) =>\n client.transactionAt!(isolationLevel, async (queryable) => {\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: false,\n scope: 'transaction',\n });\n await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });\n return work(queryable);\n }),\n }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport { CompiledQuery } from 'kysely';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\n\n/** What a Kysely instance and a Kysely transaction have in common. */\nexport interface KyselyQueryable {\n executeQuery<R>(query: CompiledQuery<R>): Promise<{ readonly rows: R[] }>;\n}\n\n/** The part of a `Kysely` instance the executor uses. */\nexport interface KyselyLike extends KyselyQueryable {\n transaction(): {\n execute<T>(work: (transaction: KyselyQueryable) => Promise<T>): Promise<T>;\n };\n}\n\n/**\n * Executor for Kysely. The transaction handle is a Kysely `Transaction`: pass\n * `trx` from `db.transaction().execute(async (trx) => ...)` as the\n * `transaction` option of `publish`.\n */\nexport function createKyselyExecutor(database: KyselyLike): PostgresExecutor<KyselyQueryable> {\n return adapterExecutor<KyselyQueryable>({\n root: database,\n transaction: (work) => database.transaction().execute(work),\n async run(queryable, { sql, parameters }) {\n const result = await queryable.executeQuery<PostgresRow>(\n CompiledQuery.raw(sql, [...parameters]),\n );\n return result.rows;\n },\n });\n}\n"]}
|
package/dist/kysely.d.cts
CHANGED
package/dist/kysely.d.ts
CHANGED
package/dist/kysely.js
CHANGED
package/dist/kysely.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/kysely/kysely-executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/kysely/kysely-executor.ts"],"names":[],"mappings":";;;;AAqBO,SAAS,qBAAqB,QAAA,EAAyD;AAC5F,EAAA,OAAO,eAAA,CAAiC;AAAA,IACtC,IAAA,EAAM,QAAA;AAAA,IACN,aAAa,CAAC,IAAA,KAAS,SAAS,WAAA,EAAY,CAAE,QAAQ,IAAI,CAAA;AAAA,IAC1D,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,YAAA;AAAA,QAC7B,cAAc,GAAA,CAAI,GAAA,EAAK,CAAC,GAAG,UAAU,CAAC;AAAA,OACxC;AACA,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAAA,GACD,CAAA;AACH","file":"kysely.js","sourcesContent":["import { adapterExecutor } from '../adapter-executor.js';\nimport { CompiledQuery } from 'kysely';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\n\n/** What a Kysely instance and a Kysely transaction have in common. */\nexport interface KyselyQueryable {\n executeQuery<R>(query: CompiledQuery<R>): Promise<{ readonly rows: R[] }>;\n}\n\n/** The part of a `Kysely` instance the executor uses. */\nexport interface KyselyLike extends KyselyQueryable {\n transaction(): {\n execute<T>(work: (transaction: KyselyQueryable) => Promise<T>): Promise<T>;\n };\n}\n\n/**\n * Executor for Kysely. The transaction handle is a Kysely `Transaction`: pass\n * `trx` from `db.transaction().execute(async (trx) => ...)` as the\n * `transaction` option of `publish`.\n */\nexport function createKyselyExecutor(database: KyselyLike): PostgresExecutor<KyselyQueryable> {\n return adapterExecutor<KyselyQueryable>({\n root: database,\n transaction: (work) => database.transaction().execute(work),\n async run(queryable, { sql, parameters }) {\n const result = await queryable.executeQuery<PostgresRow>(\n CompiledQuery.raw(sql, [...parameters]),\n );\n return result.rows;\n },\n });\n}\n"]}
|
package/dist/prisma.cjs
CHANGED
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/transaction-timeouts.ts
|
|
4
|
+
function budgetSettingsSql({ value, sessionTimeouts, scope }) {
|
|
5
|
+
const local = scope === "transaction";
|
|
6
|
+
const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;
|
|
7
|
+
{
|
|
8
|
+
return statementTimeout;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function budgetValue(timeoutMs) {
|
|
12
|
+
return `${Math.ceil(timeoutMs)}ms`;
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
// src/adapter-executor.ts
|
|
4
16
|
function adapterExecutor(client) {
|
|
5
17
|
return {
|
|
6
18
|
transaction: client.transaction,
|
|
19
|
+
...client.transactionAt === void 0 ? {} : {
|
|
20
|
+
// The level is set by the library at BEGIN, so the budget statement can follow as the first query.
|
|
21
|
+
transactionWithIsolation: (work, { isolationLevel, timeoutMs }) => client.transactionAt(isolationLevel, async (queryable) => {
|
|
22
|
+
const sql = budgetSettingsSql({
|
|
23
|
+
value: "$1",
|
|
24
|
+
sessionTimeouts: false,
|
|
25
|
+
scope: "transaction"
|
|
26
|
+
});
|
|
27
|
+
await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });
|
|
28
|
+
return work(queryable);
|
|
29
|
+
})
|
|
30
|
+
},
|
|
7
31
|
// eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature
|
|
8
32
|
query: (sql, parameters, transaction) => client.run(transaction ?? client.root, { sql, parameters })
|
|
9
33
|
};
|
package/dist/prisma.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-executor.ts","../src/prisma/prisma-executor.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../src/transaction-timeouts.ts","../src/adapter-executor.ts","../src/prisma/prisma-executor.ts"],"names":[],"mappings":";;;AAiBO,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,eAAA,EAAiB,OAAM,EAA2B;AAC3F,EAAA,MAAM,QAAQ,KAAA,KAAU,aAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,CAAA,uCAAA,EAA0C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAClF,EAAsB;AACpB,IAAA,OAAO,gBAAA;AAAA,EACT;AAMF;AAQO,SAAS,YAAY,SAAA,EAA2B;AACrD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA,EAAA,CAAA;AAChC;;;ACNO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,GAAI,MAAA,CAAO,aAAA,KAAkB,MAAA,GACzB,EAAC,GACD;AAAA;AAAA,MAEE,wBAAA,EAA0B,CAAC,IAAA,EAAM,EAAE,cAAA,EAAgB,SAAA,EAAU,KAC3D,MAAA,CAAO,aAAA,CAAe,cAAA,EAAgB,OAAO,SAAA,KAAc;AACzD,QAAA,MAAM,MAAM,iBAAA,CAAkB;AAAA,UAC5B,KAAA,EAAO,IAAA;AAAA,UACP,eAAA,EAAiB,KAAA;AAAA,UACjB,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA,MAAM,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,CAAA;AACzE,QAAA,OAAO,KAAK,SAAS,CAAA;AAAA,MACvB,CAAC;AAAA,KACL;AAAA;AAAA,IAEJ,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;;;AC3BO,SAAS,oBAAA,CACd,MAAA,EACA,kBAAA,GAA+C,EAAC,EACb;AACnC,EAAA,OAAO,eAAA,CAAiC;AAAA,IACtC,IAAA,EAAM,MAAA;AAAA,IACN,aAAa,CAAC,IAAA,KAAS,MAAA,CAAO,YAAA,CAAa,MAAM,kBAAkB,CAAA;AAAA,IACnE,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,OAAQ,MAAM,SAAA,CAAU,eAAA,CAAgB,GAAA,EAAK,GAAG,UAAU,CAAA;AAAA,IAC5D;AAAA,GACD,CAAA;AACH","file":"prisma.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import type { TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /**\n * Optional. Opens a transaction at an isolation level through the library's own API, for a library\n * that runs code of its own (hooks, subscribers) right after it begins a transaction: that code\n * would otherwise run a query before the store's `SET TRANSACTION ISOLATION LEVEL`.\n */\n readonly transactionAt?: <T>(\n isolationLevel: TransactionIsolationLevel,\n work: (queryable: TQueryable) => Promise<T>,\n ) => Promise<T>;\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n ...(client.transactionAt === undefined\n ? {}\n : {\n // The level is set by the library at BEGIN, so the budget statement can follow as the first query.\n transactionWithIsolation: (work, { isolationLevel, timeoutMs }) =>\n client.transactionAt!(isolationLevel, async (queryable) => {\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: false,\n scope: 'transaction',\n });\n await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });\n return work(queryable);\n }),\n }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\n\n/** What a `PrismaClient` and an interactive-transaction client have in common. */\nexport interface PrismaQueryable {\n $queryRawUnsafe(query: string, ...values: unknown[]): PromiseLike<unknown>;\n}\n\n/** The part of a `PrismaClient` the executor uses. */\nexport interface PrismaClientLike extends PrismaQueryable {\n $transaction<T>(\n work: (transaction: PrismaQueryable) => Promise<T>,\n options?: PrismaTransactionOptions,\n ): Promise<T>;\n}\n\n/** Prisma interactive transaction limits. Prisma's defaults (2 s wait, 5 s run) are short for handlers. */\nexport interface PrismaTransactionOptions {\n readonly maxWait?: number;\n readonly timeout?: number;\n}\n\n/**\n * Executor for Prisma, typed structurally so the package has no Prisma\n * dependency. The transaction handle is the client of an interactive\n * transaction: pass `tx` from `prisma.$transaction(async (tx) => ...)`.\n *\n * Integration-tested with generated Prisma Clients 5, 6 and 7 on the `@prisma/adapter-pg` driver adapter.\n */\nexport function createPrismaExecutor(\n client: PrismaClientLike,\n transactionOptions: PrismaTransactionOptions = {},\n): PostgresExecutor<PrismaQueryable> {\n return adapterExecutor<PrismaQueryable>({\n root: client,\n transaction: (work) => client.$transaction(work, transactionOptions),\n async run(queryable, { sql, parameters }) {\n return (await queryable.$queryRawUnsafe(sql, ...parameters)) as PostgresRow[];\n },\n });\n}\n"]}
|
package/dist/prisma.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PostgresExecutor } from './index.cjs';
|
|
2
|
+
import '@relaybus/core';
|
|
2
3
|
|
|
3
4
|
/** What a `PrismaClient` and an interactive-transaction client have in common. */
|
|
4
5
|
interface PrismaQueryable {
|
|
@@ -18,7 +19,7 @@ interface PrismaTransactionOptions {
|
|
|
18
19
|
* dependency. The transaction handle is the client of an interactive
|
|
19
20
|
* transaction: pass `tx` from `prisma.$transaction(async (tx) => ...)`.
|
|
20
21
|
*
|
|
21
|
-
* Integration-tested with
|
|
22
|
+
* Integration-tested with generated Prisma Clients 5, 6 and 7 on the `@prisma/adapter-pg` driver adapter.
|
|
22
23
|
*/
|
|
23
24
|
declare function createPrismaExecutor(client: PrismaClientLike, transactionOptions?: PrismaTransactionOptions): PostgresExecutor<PrismaQueryable>;
|
|
24
25
|
|
package/dist/prisma.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PostgresExecutor } from './index.js';
|
|
2
|
+
import '@relaybus/core';
|
|
2
3
|
|
|
3
4
|
/** What a `PrismaClient` and an interactive-transaction client have in common. */
|
|
4
5
|
interface PrismaQueryable {
|
|
@@ -18,7 +19,7 @@ interface PrismaTransactionOptions {
|
|
|
18
19
|
* dependency. The transaction handle is the client of an interactive
|
|
19
20
|
* transaction: pass `tx` from `prisma.$transaction(async (tx) => ...)`.
|
|
20
21
|
*
|
|
21
|
-
* Integration-tested with
|
|
22
|
+
* Integration-tested with generated Prisma Clients 5, 6 and 7 on the `@prisma/adapter-pg` driver adapter.
|
|
22
23
|
*/
|
|
23
24
|
declare function createPrismaExecutor(client: PrismaClientLike, transactionOptions?: PrismaTransactionOptions): PostgresExecutor<PrismaQueryable>;
|
|
24
25
|
|
package/dist/prisma.js
CHANGED
package/dist/prisma.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/prisma/prisma-executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/prisma/prisma-executor.ts"],"names":[],"mappings":";;;;AA6BO,SAAS,oBAAA,CACd,MAAA,EACA,kBAAA,GAA+C,EAAC,EACb;AACnC,EAAA,OAAO,eAAA,CAAiC;AAAA,IACtC,IAAA,EAAM,MAAA;AAAA,IACN,aAAa,CAAC,IAAA,KAAS,MAAA,CAAO,YAAA,CAAa,MAAM,kBAAkB,CAAA;AAAA,IACnE,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,OAAQ,MAAM,SAAA,CAAU,eAAA,CAAgB,GAAA,EAAK,GAAG,UAAU,CAAA;AAAA,IAC5D;AAAA,GACD,CAAA;AACH","file":"prisma.js","sourcesContent":["import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\n\n/** What a `PrismaClient` and an interactive-transaction client have in common. */\nexport interface PrismaQueryable {\n $queryRawUnsafe(query: string, ...values: unknown[]): PromiseLike<unknown>;\n}\n\n/** The part of a `PrismaClient` the executor uses. */\nexport interface PrismaClientLike extends PrismaQueryable {\n $transaction<T>(\n work: (transaction: PrismaQueryable) => Promise<T>,\n options?: PrismaTransactionOptions,\n ): Promise<T>;\n}\n\n/** Prisma interactive transaction limits. Prisma's defaults (2 s wait, 5 s run) are short for handlers. */\nexport interface PrismaTransactionOptions {\n readonly maxWait?: number;\n readonly timeout?: number;\n}\n\n/**\n * Executor for Prisma, typed structurally so the package has no Prisma\n * dependency. The transaction handle is the client of an interactive\n * transaction: pass `tx` from `prisma.$transaction(async (tx) => ...)`.\n *\n * Integration-tested with generated Prisma Clients 5, 6 and 7 on the `@prisma/adapter-pg` driver adapter.\n */\nexport function createPrismaExecutor(\n client: PrismaClientLike,\n transactionOptions: PrismaTransactionOptions = {},\n): PostgresExecutor<PrismaQueryable> {\n return adapterExecutor<PrismaQueryable>({\n root: client,\n transaction: (work) => client.$transaction(work, transactionOptions),\n async run(queryable, { sql, parameters }) {\n return (await queryable.$queryRawUnsafe(sql, ...parameters)) as PostgresRow[];\n },\n });\n}\n"]}
|
package/dist/typeorm.cjs
CHANGED
|
@@ -1,19 +1,65 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var core = require('@relaybus/core');
|
|
4
|
+
|
|
5
|
+
// src/transaction-timeouts.ts
|
|
6
|
+
function budgetSettingsSql({ value, sessionTimeouts, scope }) {
|
|
7
|
+
const local = scope === "transaction";
|
|
8
|
+
const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;
|
|
9
|
+
{
|
|
10
|
+
return statementTimeout;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function budgetValue(timeoutMs) {
|
|
14
|
+
return `${Math.ceil(timeoutMs)}ms`;
|
|
15
|
+
}
|
|
16
|
+
|
|
3
17
|
// src/adapter-executor.ts
|
|
4
18
|
function adapterExecutor(client) {
|
|
5
19
|
return {
|
|
6
20
|
transaction: client.transaction,
|
|
21
|
+
...client.transactionAt === void 0 ? {} : {
|
|
22
|
+
// The level is set by the library at BEGIN, so the budget statement can follow as the first query.
|
|
23
|
+
transactionWithIsolation: (work, { isolationLevel, timeoutMs }) => client.transactionAt(isolationLevel, async (queryable) => {
|
|
24
|
+
const sql = budgetSettingsSql({
|
|
25
|
+
value: "$1",
|
|
26
|
+
sessionTimeouts: false,
|
|
27
|
+
scope: "transaction"
|
|
28
|
+
});
|
|
29
|
+
await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });
|
|
30
|
+
return work(queryable);
|
|
31
|
+
})
|
|
32
|
+
},
|
|
7
33
|
// eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature
|
|
8
34
|
query: (sql, parameters, transaction) => client.run(transaction ?? client.root, { sql, parameters })
|
|
9
35
|
};
|
|
10
36
|
}
|
|
37
|
+
var ISOLATION_KEYWORDS = {
|
|
38
|
+
"read committed": "READ COMMITTED",
|
|
39
|
+
"repeatable read": "REPEATABLE READ",
|
|
40
|
+
serializable: "SERIALIZABLE"
|
|
41
|
+
};
|
|
42
|
+
function isolationKeywords(isolationLevel) {
|
|
43
|
+
const keywords = Object.hasOwn(ISOLATION_KEYWORDS, isolationLevel) ? ISOLATION_KEYWORDS[isolationLevel] : void 0;
|
|
44
|
+
if (keywords === void 0) {
|
|
45
|
+
throw new core.ConfigurationError(`Unknown isolation level ${JSON.stringify(isolationLevel)}`);
|
|
46
|
+
}
|
|
47
|
+
return keywords;
|
|
48
|
+
}
|
|
11
49
|
|
|
12
50
|
// src/typeorm/typeorm-executor.ts
|
|
13
51
|
function createTypeOrmExecutor(dataSource) {
|
|
14
52
|
return adapterExecutor({
|
|
15
53
|
root: dataSource,
|
|
16
54
|
transaction: (work) => dataSource.transaction(work),
|
|
55
|
+
// A real DataSource takes (isolationLevel, work) and begins with the level before its subscribers
|
|
56
|
+
// run; a wrapper written for the one-argument contract does not, and gets SET TRANSACTION instead.
|
|
57
|
+
...dataSource.transaction.length >= 2 ? {
|
|
58
|
+
transactionAt: (isolationLevel, work) => dataSource.transaction(
|
|
59
|
+
isolationKeywords(isolationLevel),
|
|
60
|
+
work
|
|
61
|
+
)
|
|
62
|
+
} : {},
|
|
17
63
|
async run(queryable, { sql, parameters }) {
|
|
18
64
|
return await queryable.query(sql, [...parameters]);
|
|
19
65
|
}
|
package/dist/typeorm.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-executor.ts","../src/typeorm/typeorm-executor.ts"],"names":[],"mappings":";;;AAqBO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA;AAAA,IAEpB,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;;;ACXO,SAAS,sBACd,UAAA,EACoC;AACpC,EAAA,OAAO,eAAA,CAAkC;AAAA,IACvC,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,UAAA,CAAW,YAAY,IAAI,CAAA;AAAA,IAClD,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,OAAQ,MAAM,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,GAAG,UAAU,CAAC,CAAA;AAAA,IACpD;AAAA,GACD,CAAA;AACH","file":"typeorm.cjs","sourcesContent":["import type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\n\n/** What a TypeORM `DataSource` and an `EntityManager` have in common. */\nexport interface TypeOrmQueryable {\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n}\n\n/** The part of a `DataSource` the executor uses. */\nexport interface TypeOrmDataSourceLike extends TypeOrmQueryable {\n transaction<T>(work: (manager: TypeOrmQueryable) => Promise<T>): Promise<T>;\n}\n\n/**\n * Executor for TypeORM. The transaction handle is the `EntityManager` of a\n * transaction: pass `manager` from `dataSource.transaction(async (manager) => ...)`\n * (or the manager your transaction decorator provides). Every statement the\n * store sends is a plain SELECT or INSERT, for which `query` returns the rows.\n */\nexport function createTypeOrmExecutor(\n dataSource: TypeOrmDataSourceLike,\n): PostgresExecutor<TypeOrmQueryable> {\n return adapterExecutor<TypeOrmQueryable>({\n root: dataSource,\n transaction: (work) => dataSource.transaction(work),\n async run(queryable, { sql, parameters }) {\n return (await queryable.query(sql, [...parameters])) as PostgresRow[];\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/transaction-timeouts.ts","../src/adapter-executor.ts","../src/transaction-isolation.ts","../src/typeorm/typeorm-executor.ts"],"names":["ConfigurationError"],"mappings":";;;;;AAiBO,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,eAAA,EAAiB,OAAM,EAA2B;AAC3F,EAAA,MAAM,QAAQ,KAAA,KAAU,aAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,CAAA,uCAAA,EAA0C,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAClF,EAAsB;AACpB,IAAA,OAAO,gBAAA;AAAA,EACT;AAMF;AAQO,SAAS,YAAY,SAAA,EAA2B;AACrD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA,EAAA,CAAA;AAChC;;;ACNO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,GAAI,MAAA,CAAO,aAAA,KAAkB,MAAA,GACzB,EAAC,GACD;AAAA;AAAA,MAEE,wBAAA,EAA0B,CAAC,IAAA,EAAM,EAAE,cAAA,EAAgB,SAAA,EAAU,KAC3D,MAAA,CAAO,aAAA,CAAe,cAAA,EAAgB,OAAO,SAAA,KAAc;AACzD,QAAA,MAAM,MAAM,iBAAA,CAAkB;AAAA,UAC5B,KAAA,EAAO,IAAA;AAAA,UACP,eAAA,EAAiB,KAAA;AAAA,UACjB,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA,MAAM,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,WAAA,CAAY,SAAS,CAAC,CAAA,EAAG,CAAA;AACzE,QAAA,OAAO,KAAK,SAAS,CAAA;AAAA,MACvB,CAAC;AAAA,KACL;AAAA;AAAA,IAEJ,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF;ACnDA,IAAM,kBAAA,GAA0E;AAAA,EAC9E,gBAAA,EAAkB,gBAAA;AAAA,EAClB,iBAAA,EAAmB,iBAAA;AAAA,EACnB,YAAA,EAAc;AAChB,CAAA;AAGO,SAAS,kBAAkB,cAAA,EAAmD;AACnF,EAAA,MAAM,QAAA,GAAW,OAAO,MAAA,CAAO,kBAAA,EAAoB,cAAc,CAAA,GAC7D,kBAAA,CAAmB,cAAc,CAAA,GACjC,MAAA;AACJ,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,MAAM,IAAIA,uBAAA,CAAmB,CAAA,wBAAA,EAA2B,KAAK,SAAA,CAAU,cAAc,CAAC,CAAA,CAAE,CAAA;AAAA,EAC1F;AACA,EAAA,OAAO,QAAA;AACT;;;ACMO,SAAS,sBACd,UAAA,EACoC;AACpC,EAAA,OAAO,eAAA,CAAkC;AAAA,IACvC,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,UAAA,CAAW,YAAY,IAAI,CAAA;AAAA;AAAA;AAAA,IAGlD,GAAI,UAAA,CAAW,WAAA,CAAY,MAAA,IAAU,CAAA,GACjC;AAAA,MACE,aAAA,EAAe,CAAC,cAAA,EAAgB,IAAA,KAC7B,UAAA,CAAW,WAAA;AAAA,QACV,kBAAkB,cAAc,CAAA;AAAA,QAChC;AAAA;AACF,QAEJ,EAAC;AAAA,IACL,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,OAAQ,MAAM,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,GAAG,UAAU,CAAC,CAAA;AAAA,IACpD;AAAA,GACD,CAAA;AACH","file":"typeorm.cjs","sourcesContent":["import type { PostgresStoreState } from './postgres-store-state.js';\n\n/** What {@link budgetSettingsSql} sets and how long the settings last. */\nexport type BudgetSettings = {\n /** The value as SQL: a parameter (`$1`) or a quoted literal (`'5000ms'`). */\n readonly value: string;\n /**\n * Also `idle_in_transaction_session_timeout` and, on PostgreSQL 17+, `transaction_timeout`: the\n * server then ends the session of an overrun, so only executors that survive that get them\n * ({@link PostgresExecutor.sessionTimeouts}).\n */\n readonly sessionTimeouts: boolean;\n /** `transaction`: `SET LOCAL` semantics, gone with the transaction. `session`: kept by the connection. */\n readonly scope: 'transaction' | 'session';\n};\n\n/** The statement that holds a transaction to a time budget: `statement_timeout` and, see {@link BudgetSettings}, more. */\nexport function budgetSettingsSql({ value, sessionTimeouts, scope }: BudgetSettings): string {\n const local = scope === 'transaction';\n const statementTimeout = `SELECT set_config('statement_timeout', ${value}, ${local})`;\n if (!sessionTimeouts) {\n return statementTimeout;\n }\n return (\n `${statementTimeout}, set_config('idle_in_transaction_session_timeout', ${value}, ${local}), ` +\n \"CASE WHEN current_setting('server_version_num')::int >= 170000 \" +\n `THEN set_config('transaction_timeout', ${value}, ${local}) END`\n );\n}\n\n/** Puts the settings {@link budgetSettingsSql} keeps at session level back to the defaults of the session. */\nexport const SESSION_DEFAULTS_SQL =\n 'SELECT set_config(name, reset_val, false) FROM pg_settings ' +\n \"WHERE name IN ('statement_timeout', 'idle_in_transaction_session_timeout', 'transaction_timeout')\";\n\n/** The budget as a setting value: whole milliseconds, so nothing but digits reaches SQL text. */\nexport function budgetValue(timeoutMs: number): string {\n return `${Math.ceil(timeoutMs)}ms`;\n}\n\n/**\n * Runs `work` in a transaction of `state`'s executor that the server holds to `timeoutMs`. An executor\n * with `transactionWithBudget` (`PgExecutor`) sets the budget in the round trip of its `BEGIN`; any\n * other executor runs it with `SET LOCAL` semantics as the first statement of the transaction.\n */\nexport function inBudgetedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithBudget !== undefined) {\n return executor.transactionWithBudget(work, timeoutMs);\n }\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await state.query({ sql, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import type { TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /**\n * Optional. Opens a transaction at an isolation level through the library's own API, for a library\n * that runs code of its own (hooks, subscribers) right after it begins a transaction: that code\n * would otherwise run a query before the store's `SET TRANSACTION ISOLATION LEVEL`.\n */\n readonly transactionAt?: <T>(\n isolationLevel: TransactionIsolationLevel,\n work: (queryable: TQueryable) => Promise<T>,\n ) => Promise<T>;\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n ...(client.transactionAt === undefined\n ? {}\n : {\n // The level is set by the library at BEGIN, so the budget statement can follow as the first query.\n transactionWithIsolation: (work, { isolationLevel, timeoutMs }) =>\n client.transactionAt!(isolationLevel, async (queryable) => {\n const sql = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: false,\n scope: 'transaction',\n });\n await client.run(queryable, { sql, parameters: [budgetValue(timeoutMs)] });\n return work(queryable);\n }),\n }),\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n","import { ConfigurationError, type TransactionIsolationLevel } from '@relaybus/core';\nimport type { PostgresStoreState } from './postgres-store-state.js';\nimport { budgetSettingsSql, budgetValue } from './transaction-timeouts.js';\n\n/** The SQL keywords of each level. Only these literals ever reach SQL text. */\nconst ISOLATION_KEYWORDS: Readonly<Record<TransactionIsolationLevel, string>> = {\n 'read committed': 'READ COMMITTED',\n 'repeatable read': 'REPEATABLE READ',\n serializable: 'SERIALIZABLE',\n};\n\n/** The keywords of `isolationLevel` as SQL; an unknown level (a store called around the bus) is refused. */\nexport function isolationKeywords(isolationLevel: TransactionIsolationLevel): string {\n const keywords = Object.hasOwn(ISOLATION_KEYWORDS, isolationLevel)\n ? ISOLATION_KEYWORDS[isolationLevel]\n : undefined;\n if (keywords === undefined) {\n throw new ConfigurationError(`Unknown isolation level ${JSON.stringify(isolationLevel)}`);\n }\n return keywords;\n}\n\n/**\n * Runs `work` in a transaction at `isolationLevel` that the server holds to `timeoutMs`. An executor\n * with `transactionWithIsolation` (`PgExecutor`) sends both with its `BEGIN`; any other executor gets\n * `SET TRANSACTION ISOLATION LEVEL` as the first statement of the transaction and the budget as the\n * second: PostgreSQL refuses the level once a query ran, and the budget's `set_config` is a query.\n */\nexport function inIsolatedTransaction<TTransaction, T>(\n state: PostgresStoreState<TTransaction>,\n {\n work,\n timeoutMs,\n isolationLevel,\n }: {\n readonly work: (transaction: TTransaction) => Promise<T>;\n readonly timeoutMs: number;\n readonly isolationLevel: TransactionIsolationLevel;\n },\n): Promise<T> {\n const { executor } = state;\n if (executor.transactionWithIsolation !== undefined) {\n return executor.transactionWithIsolation(work, { isolationLevel, timeoutMs });\n }\n const keywords = isolationKeywords(isolationLevel);\n const budget = budgetSettingsSql({\n value: '$1',\n sessionTimeouts: executor.sessionTimeouts === true,\n scope: 'transaction',\n });\n return executor.transaction(async (transaction) => {\n await executor.query(`SET TRANSACTION ISOLATION LEVEL ${keywords}`, [], transaction);\n await state.query({ sql: budget, parameters: [budgetValue(timeoutMs)], transaction });\n return work(transaction);\n });\n}\n","import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\nimport { isolationKeywords } from '../transaction-isolation.js';\n\n/** What a TypeORM `DataSource` and an `EntityManager` have in common. */\nexport interface TypeOrmQueryable {\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n}\n\n/** The part of a `DataSource` the executor uses. */\nexport interface TypeOrmDataSourceLike extends TypeOrmQueryable {\n transaction<T>(work: (manager: TypeOrmQueryable) => Promise<T>): Promise<T>;\n}\n\n/** TypeORM's own `transaction(isolationLevel, work)`, which a real `DataSource` has. */\ntype IsolatedTransaction = <T>(\n isolationLevel: 'READ COMMITTED' | 'REPEATABLE READ' | 'SERIALIZABLE',\n work: (manager: TypeOrmQueryable) => Promise<T>,\n) => Promise<T>;\n\n/**\n * Executor for TypeORM. The transaction handle is the `EntityManager` of a\n * transaction: pass `manager` from `dataSource.transaction(async (manager) => ...)`\n * (or the manager your transaction decorator provides). Every statement the\n * store sends is a plain SELECT or INSERT, for which `query` returns the rows.\n */\nexport function createTypeOrmExecutor(\n dataSource: TypeOrmDataSourceLike,\n): PostgresExecutor<TypeOrmQueryable> {\n return adapterExecutor<TypeOrmQueryable>({\n root: dataSource,\n transaction: (work) => dataSource.transaction(work),\n // A real DataSource takes (isolationLevel, work) and begins with the level before its subscribers\n // run; a wrapper written for the one-argument contract does not, and gets SET TRANSACTION instead.\n ...(dataSource.transaction.length >= 2\n ? {\n transactionAt: (isolationLevel, work) =>\n (dataSource.transaction as unknown as IsolatedTransaction)(\n isolationKeywords(isolationLevel) as Parameters<IsolatedTransaction>[0],\n work,\n ),\n }\n : {}),\n async run(queryable, { sql, parameters }) {\n return (await queryable.query(sql, [...parameters])) as PostgresRow[];\n },\n });\n}\n"]}
|
package/dist/typeorm.d.cts
CHANGED
package/dist/typeorm.d.ts
CHANGED
package/dist/typeorm.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isolationKeywords } from './chunk-FY65AUUF.js';
|
|
2
|
+
import { adapterExecutor } from './chunk-5WWPAN5Q.js';
|
|
3
|
+
import './chunk-UDBN4RRV.js';
|
|
2
4
|
|
|
3
5
|
// src/typeorm/typeorm-executor.ts
|
|
4
6
|
function createTypeOrmExecutor(dataSource) {
|
|
5
7
|
return adapterExecutor({
|
|
6
8
|
root: dataSource,
|
|
7
9
|
transaction: (work) => dataSource.transaction(work),
|
|
10
|
+
// A real DataSource takes (isolationLevel, work) and begins with the level before its subscribers
|
|
11
|
+
// run; a wrapper written for the one-argument contract does not, and gets SET TRANSACTION instead.
|
|
12
|
+
...dataSource.transaction.length >= 2 ? {
|
|
13
|
+
transactionAt: (isolationLevel, work) => dataSource.transaction(
|
|
14
|
+
isolationKeywords(isolationLevel),
|
|
15
|
+
work
|
|
16
|
+
)
|
|
17
|
+
} : {},
|
|
8
18
|
async run(queryable, { sql, parameters }) {
|
|
9
19
|
return await queryable.query(sql, [...parameters]);
|
|
10
20
|
}
|
package/dist/typeorm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/typeorm/typeorm-executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/typeorm/typeorm-executor.ts"],"names":[],"mappings":";;;;;AA0BO,SAAS,sBACd,UAAA,EACoC;AACpC,EAAA,OAAO,eAAA,CAAkC;AAAA,IACvC,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,IAAA,KAAS,UAAA,CAAW,YAAY,IAAI,CAAA;AAAA;AAAA;AAAA,IAGlD,GAAI,UAAA,CAAW,WAAA,CAAY,MAAA,IAAU,CAAA,GACjC;AAAA,MACE,aAAA,EAAe,CAAC,cAAA,EAAgB,IAAA,KAC7B,UAAA,CAAW,WAAA;AAAA,QACV,kBAAkB,cAAc,CAAA;AAAA,QAChC;AAAA;AACF,QAEJ,EAAC;AAAA,IACL,MAAM,GAAA,CAAI,SAAA,EAAW,EAAE,GAAA,EAAK,YAAW,EAAG;AACxC,MAAA,OAAQ,MAAM,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,GAAG,UAAU,CAAC,CAAA;AAAA,IACpD;AAAA,GACD,CAAA;AACH","file":"typeorm.js","sourcesContent":["import { adapterExecutor } from '../adapter-executor.js';\nimport type { PostgresExecutor, PostgresRow } from '../executor.js';\nimport { isolationKeywords } from '../transaction-isolation.js';\n\n/** What a TypeORM `DataSource` and an `EntityManager` have in common. */\nexport interface TypeOrmQueryable {\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n}\n\n/** The part of a `DataSource` the executor uses. */\nexport interface TypeOrmDataSourceLike extends TypeOrmQueryable {\n transaction<T>(work: (manager: TypeOrmQueryable) => Promise<T>): Promise<T>;\n}\n\n/** TypeORM's own `transaction(isolationLevel, work)`, which a real `DataSource` has. */\ntype IsolatedTransaction = <T>(\n isolationLevel: 'READ COMMITTED' | 'REPEATABLE READ' | 'SERIALIZABLE',\n work: (manager: TypeOrmQueryable) => Promise<T>,\n) => Promise<T>;\n\n/**\n * Executor for TypeORM. The transaction handle is the `EntityManager` of a\n * transaction: pass `manager` from `dataSource.transaction(async (manager) => ...)`\n * (or the manager your transaction decorator provides). Every statement the\n * store sends is a plain SELECT or INSERT, for which `query` returns the rows.\n */\nexport function createTypeOrmExecutor(\n dataSource: TypeOrmDataSourceLike,\n): PostgresExecutor<TypeOrmQueryable> {\n return adapterExecutor<TypeOrmQueryable>({\n root: dataSource,\n transaction: (work) => dataSource.transaction(work),\n // A real DataSource takes (isolationLevel, work) and begins with the level before its subscribers\n // run; a wrapper written for the one-argument contract does not, and gets SET TRANSACTION instead.\n ...(dataSource.transaction.length >= 2\n ? {\n transactionAt: (isolationLevel, work) =>\n (dataSource.transaction as unknown as IsolatedTransaction)(\n isolationKeywords(isolationLevel) as Parameters<IsolatedTransaction>[0],\n work,\n ),\n }\n : {}),\n async run(queryable, { sql, parameters }) {\n return (await queryable.query(sql, [...parameters])) as PostgresRow[];\n },\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relaybus/postgres",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "PostgreSQL event store for relaybus: a transactional outbox written in your own transaction (pg, Prisma, TypeORM, Drizzle, Knex, Kysely) with SKIP LOCKED leasing and per-key ordering.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Berkcan Şavur <berkcansavur@gmail.com>",
|
|
@@ -119,8 +119,8 @@
|
|
|
119
119
|
"kysely": ">=0.27.0",
|
|
120
120
|
"pg": "^8.11.0",
|
|
121
121
|
"typeorm": ">=0.3.0",
|
|
122
|
-
"@prisma/client": "^6.0.0 || ^7.0.0",
|
|
123
|
-
"@relaybus/core": "^0.
|
|
122
|
+
"@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
123
|
+
"@relaybus/core": "^0.5.0"
|
|
124
124
|
},
|
|
125
125
|
"devDependencies": {
|
|
126
126
|
"@prisma/adapter-pg": "7.10.1",
|
|
@@ -132,10 +132,11 @@
|
|
|
132
132
|
"kysely": "0.29.7",
|
|
133
133
|
"pg": "8.23.1",
|
|
134
134
|
"prisma": "7.10.1",
|
|
135
|
+
"relaybus-postgres-0.4.0": "npm:@relaybus/postgres@0.4.0",
|
|
135
136
|
"testcontainers": "12.2.1",
|
|
136
137
|
"typeorm": "1.1.2",
|
|
137
|
-
"@relaybus/core": "0.
|
|
138
|
-
"@relaybus/testing": "0.
|
|
138
|
+
"@relaybus/core": "0.5.0",
|
|
139
|
+
"@relaybus/testing": "0.5.0"
|
|
139
140
|
},
|
|
140
141
|
"typesVersions": {
|
|
141
142
|
"*": {
|
package/dist/chunk-NNZJR5AB.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// src/adapter-executor.ts
|
|
2
|
-
function adapterExecutor(client) {
|
|
3
|
-
return {
|
|
4
|
-
transaction: client.transaction,
|
|
5
|
-
// eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature
|
|
6
|
-
query: (sql, parameters, transaction) => client.run(transaction ?? client.root, { sql, parameters })
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export { adapterExecutor };
|
|
11
|
-
//# sourceMappingURL=chunk-NNZJR5AB.js.map
|
|
12
|
-
//# sourceMappingURL=chunk-NNZJR5AB.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter-executor.ts"],"names":[],"mappings":";AAqBO,SAAS,gBACd,MAAA,EAC8B;AAC9B,EAAA,OAAO;AAAA,IACL,aAAa,MAAA,CAAO,WAAA;AAAA;AAAA,IAEpB,KAAA,EAAO,CAAC,GAAA,EAAK,UAAA,EAAY,WAAA,KACvB,MAAA,CAAO,GAAA,CAAI,WAAA,IAAe,MAAA,CAAO,IAAA,EAAM,EAAE,GAAA,EAAK,YAAY;AAAA,GAC9D;AACF","file":"chunk-NNZJR5AB.js","sourcesContent":["import type { PostgresExecutor, PostgresParameter, PostgresRow } from './executor.js';\n\n/** One statement the store sends, with its positional parameters. */\nexport type AdapterStatement = {\n readonly sql: string;\n readonly parameters: readonly PostgresParameter[];\n};\n\n/** What an adapter supplies: where statements run outside a transaction, and how it runs one. */\nexport type AdapterClient<TQueryable> = {\n /** The instance itself: statements outside a transaction run on it. */\n readonly root: TQueryable;\n readonly transaction: PostgresExecutor<TQueryable>['transaction'];\n /** Runs one statement on the caller's transaction, else on the root. */\n readonly run: (queryable: TQueryable, statement: AdapterStatement) => Promise<PostgresRow[]>;\n};\n\n/**\n * The executor every library adapter shares: a statement runs on the transaction it is given,\n * else on the root instance. An adapter supplies only how its library runs one statement.\n */\nexport function adapterExecutor<TQueryable>(\n client: AdapterClient<TQueryable>,\n): PostgresExecutor<TQueryable> {\n return {\n transaction: client.transaction,\n // eslint-disable-next-line relaybus/max-two-params -- PostgresExecutor port signature\n query: (sql, parameters, transaction) =>\n client.run(transaction ?? client.root, { sql, parameters }),\n };\n}\n"]}
|