@typesql/core 0.0.4 → 0.1.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/CHANGELOG.md +6 -0
- package/README.md +3 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/query.d.ts +6 -3
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +8 -5
- package/dist/query.js.map +1 -1
- package/dist/transaction.d.ts +43 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +45 -0
- package/dist/transaction.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/query.ts +12 -7
- package/src/transaction.ts +70 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @typesql/core
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Adapters build their `sql` with `createTransactionalSql(client, driver)`, typed `TransactionalSql` (core's `Sql` plus `transaction(fn)`), and `runTransaction` sends BEGIN/COMMIT/ROLLBACK or savepoints; an `Executor` may have a `count(text, values)` method, which `executeCount` runs instead.
|
|
8
|
+
|
|
3
9
|
## 0.0.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -70,7 +70,9 @@ checked against their context.
|
|
|
70
70
|
your migrations.
|
|
71
71
|
- **Running queries**: with `createSql(executor)` (or an adapter's `createSql(client)`), queries
|
|
72
72
|
have `execute()`, `executeTakeFirst()`, `executeTakeFirstOrThrow()` and `executeCount()` (the
|
|
73
|
-
affected row count). An `Executor` resolves to the rows or to `{ rows, rowCount }`.
|
|
73
|
+
affected row count). An `Executor` resolves to the rows or to `{ rows, rowCount }`. An
|
|
74
|
+
adapter's `sql` also has `sql.transaction(fn)`, which runs `fn` with a `sql` bound to one
|
|
75
|
+
transaction (`TransactionalSql`).
|
|
74
76
|
- **camelCase rows**: `createSql(executor, { rowKeys: "camelCase" })` renames the rows'
|
|
75
77
|
top-level keys (`created_at` → `createdAt`, as Kysely's `CamelCasePlugin` does) in the types
|
|
76
78
|
and at runtime, leaving JSON values alone.
|
package/dist/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export type { Tok, Toks, WordTok, IdTok, NumTok, StrTok, ParamTok, OpTok } from
|
|
|
18
18
|
export type { ParseProgram, ParseStatement } from "./engine/parser/stmt.js";
|
|
19
19
|
export type * as Ast from "./engine/ast.js";
|
|
20
20
|
export type { ColInfo, ColMap, Cols, Scope, ScopeItem, ScopeLevel, Ctx, CteMap } from "./engine/types.js";
|
|
21
|
+
export { createTransactionalSql, runTransaction, type TransactionalSql, type SqlDriver } from "./transaction.js";
|
|
21
22
|
export { Migrations, migrations, runMigrations, type MigrationClient, type SchemaOf, type ValidateDdl } from "./migrations.js";
|
|
22
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACnI,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,GAAG,EAAE,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACrP,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACrJ,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5J,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChI,YAAY,EACV,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EACrI,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,kBAAkB,EAAE,0BAA0B,GACvG,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChJ,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACpH,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxJ,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACjF,YAAY,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAChF,YAAY,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACjD,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAC3G,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC5E,YAAY,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC1G,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,5 +4,6 @@ export { makeQuery, makeFragment, mapRows, rowKeysOf, NoResultError } from "./qu
|
|
|
4
4
|
export { param, valueOrDefault } from "./runtime/inline.js";
|
|
5
5
|
export { json, JsonParam } from "./runtime/json.js";
|
|
6
6
|
export { splice, renumberParams, maxParam, quoteIdent, joinFragments, hasSlots, rewriteNamed } from "./runtime/splice.js";
|
|
7
|
+
export { createTransactionalSql, runTransaction } from "./transaction.js";
|
|
7
8
|
export { Migrations, migrations, runMigrations } from "./migrations.js";
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyF,MAAM,iBAAiB,CAAC;AACnI,OAAO,EAAE,SAAS,EAAoF,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAA+J,MAAM,YAAY,CAAC;AACrP,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAoC,MAAM,qBAAqB,CAAC;AAiB5J,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAyD,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyF,MAAM,iBAAiB,CAAC;AACnI,OAAO,EAAE,SAAS,EAAoF,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAA+J,MAAM,YAAY,CAAC;AACrP,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAoC,MAAM,qBAAqB,CAAC;AAiB5J,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAyC,MAAM,kBAAkB,CAAC;AACjH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAyD,MAAM,iBAAiB,CAAC"}
|
package/dist/query.d.ts
CHANGED
|
@@ -21,9 +21,12 @@ export interface ExecutorResult {
|
|
|
21
21
|
* Runs a statement and resolves to its rows, or to `{ rows, rowCount }`. Adapters build one from a
|
|
22
22
|
* driver client (`executor(pool)` in `@typesql/pg`, which reports `rowCount`); pass it to
|
|
23
23
|
* `createSql(executor)` or to `q.execute(executor)`. An executor that resolves to the rows alone
|
|
24
|
-
* works for everything except `executeCount
|
|
24
|
+
* works for everything except `executeCount`, unless it also has a `count` method.
|
|
25
25
|
*/
|
|
26
|
-
export type Executor = (text: string, values: readonly unknown[]) => PromiseLike<readonly unknown[] | ExecutorResult
|
|
26
|
+
export type Executor = ((text: string, values: readonly unknown[]) => PromiseLike<readonly unknown[] | ExecutorResult>) & {
|
|
27
|
+
/** Runs the statement for its row count; `executeCount` uses it when present (Prisma's `$executeRaw`). */
|
|
28
|
+
readonly count?: (text: string, values: readonly unknown[]) => PromiseLike<number>;
|
|
29
|
+
};
|
|
27
30
|
/** Thrown by `executeTakeFirstOrThrow` when the query returns no rows. */
|
|
28
31
|
export declare class NoResultError extends Error {
|
|
29
32
|
readonly name = "NoResultError";
|
|
@@ -71,7 +74,7 @@ export type TextType<Q> = Q extends {
|
|
|
71
74
|
/**
|
|
72
75
|
* Turn rows a driver returned for `q` into the rows `q`'s type describes: a fresh array, with
|
|
73
76
|
* the keys renamed when `q` comes from `createSql(executor, { rowKeys: "camelCase" })`. For
|
|
74
|
-
* helpers that run `q.text` themselves
|
|
77
|
+
* helpers that run `q.text` themselves instead of through an `Executor`.
|
|
75
78
|
*/
|
|
76
79
|
export declare function mapRows<Q extends {
|
|
77
80
|
readonly text: string;
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,OAAO,MAAM,CAAC;AACxC,MAAM,CAAC,OAAO,CAAC,MAAM,MAAM,EAAE,OAAO,MAAM,CAAC;AAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,OAAO,MAAM,CAAC;AACzC,MAAM,CAAC,OAAO,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,OAAO,EAAE,KAAK,WAAW,CAAC,SAAS,OAAO,EAAE,GAAG,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/query.js
CHANGED
|
@@ -17,7 +17,7 @@ const ROW_KEYS = Symbol.for("typesql.rowKeys");
|
|
|
17
17
|
/**
|
|
18
18
|
* Turn rows a driver returned for `q` into the rows `q`'s type describes: a fresh array, with
|
|
19
19
|
* the keys renamed when `q` comes from `createSql(executor, { rowKeys: "camelCase" })`. For
|
|
20
|
-
* helpers that run `q.text` themselves
|
|
20
|
+
* helpers that run `q.text` themselves instead of through an `Executor`.
|
|
21
21
|
*/
|
|
22
22
|
export function mapRows(q, rows) {
|
|
23
23
|
return applyRowKeys(rows, rowKeysOf(q));
|
|
@@ -31,14 +31,14 @@ export function rowKeysOf(q) {
|
|
|
31
31
|
* `{ text, values }` (strictly, too). `rowKeys` renames the keys of the rows `execute*` return.
|
|
32
32
|
*/
|
|
33
33
|
export function makeQuery(text, values, executor, rowKeys = "preserve") {
|
|
34
|
-
const
|
|
34
|
+
const pick = (given) => {
|
|
35
35
|
const exec = given ?? executor;
|
|
36
36
|
if (!exec)
|
|
37
37
|
throw new Error("typesql: no executor: pass one to createSql(executor) or to execute(executor)");
|
|
38
|
-
return exec
|
|
38
|
+
return exec;
|
|
39
39
|
};
|
|
40
40
|
const execute = async (given) => {
|
|
41
|
-
const result = await
|
|
41
|
+
const result = await pick(given)(text, values);
|
|
42
42
|
return applyRowKeys(isRows(result) ? result : result.rows, rowKeys);
|
|
43
43
|
};
|
|
44
44
|
return Object.defineProperties({ text, values }, {
|
|
@@ -46,7 +46,10 @@ export function makeQuery(text, values, executor, rowKeys = "preserve") {
|
|
|
46
46
|
execute: { value: execute },
|
|
47
47
|
executeCount: {
|
|
48
48
|
value: async (given) => {
|
|
49
|
-
const
|
|
49
|
+
const exec = pick(given);
|
|
50
|
+
if (exec.count)
|
|
51
|
+
return exec.count(text, values);
|
|
52
|
+
const result = await exec(text, values);
|
|
50
53
|
if (isRows(result) || result.rowCount === undefined) {
|
|
51
54
|
throw new Error("typesql: the executor did not report a row count: resolve to { rows, rowCount } (the adapters' executor() do)");
|
|
52
55
|
}
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAgB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the adapters' `createSql(client)` returns: a `sql` whose queries run on `client`, and
|
|
3
|
+
* `sql.transaction(fn)`, which runs `fn` with a `sql` bound to one transaction.
|
|
4
|
+
*/
|
|
5
|
+
import { type Sql } from "./create-sql.js";
|
|
6
|
+
import type { Executor } from "./query.js";
|
|
7
|
+
import type { RowKeys, SqlOptions } from "./row-keys.js";
|
|
8
|
+
/**
|
|
9
|
+
* Core's `Sql` plus `transaction(fn)`: `fn` gets `tx`, the same `sql` bound to one transaction.
|
|
10
|
+
* The transaction commits when `fn` resolves and rolls back when it throws (the error is
|
|
11
|
+
* rethrown). `tx.transaction(fn)` nests with a savepoint.
|
|
12
|
+
*/
|
|
13
|
+
export interface TransactionalSql<DB, TM, Keys extends RowKeys = "preserve"> extends Sql<DB, TM, Keys> {
|
|
14
|
+
transaction<T>(fn: (tx: TransactionalSql<DB, TM, Keys>) => Promise<T>): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
/** How an adapter runs statements and transactions on its driver's client `C`. */
|
|
17
|
+
export interface SqlDriver<C> {
|
|
18
|
+
executor(client: C): Executor;
|
|
19
|
+
/**
|
|
20
|
+
* Run `fn` inside a transaction on `client` and resolve to its result: commit when `fn`
|
|
21
|
+
* resolves, roll back and rethrow when it throws. `fn` gets the client bound to the
|
|
22
|
+
* transaction. `depth` is how many `transaction` calls enclose this one (0 at the top), so a
|
|
23
|
+
* client that cannot tell can use a savepoint when `depth > 0`.
|
|
24
|
+
*/
|
|
25
|
+
transaction<T>(client: C, depth: number, fn: (tx: C) => Promise<T>): Promise<T>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* For adapters: core's `createSql` bound to `driver.executor(client)`, with `transaction(fn)`
|
|
29
|
+
* running on `driver.transaction`. Without a `client`, `execute*` and `transaction` reject.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createTransactionalSql<DB, TM, C>(client: C | undefined, driver: SqlDriver<C>, options?: SqlOptions, depth?: number): TransactionalSql<DB, TM, RowKeys>;
|
|
32
|
+
/**
|
|
33
|
+
* For drivers without a transaction API: run `fn` between `BEGIN` and `COMMIT` sent with `run`
|
|
34
|
+
* on one connection, or between `SAVEPOINT name` and `RELEASE SAVEPOINT name` when `savepoint`
|
|
35
|
+
* is given (inside a transaction). When `fn` or the commit throws, it rolls back (`ROLLBACK`,
|
|
36
|
+
* `ROLLBACK TO SAVEPOINT name`) and rethrows that error; if the rollback fails too, its error is
|
|
37
|
+
* passed to `onRollbackError` and the original is still thrown. A failing `BEGIN` is thrown as is.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runTransaction<T>(run: (statement: string) => PromiseLike<unknown>, fn: () => Promise<T>, options?: {
|
|
40
|
+
readonly savepoint?: string;
|
|
41
|
+
readonly onRollbackError?: (err: unknown) => void;
|
|
42
|
+
}): Promise<T>;
|
|
43
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAa,KAAK,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,SAAS,OAAO,GAAG,UAAU,CAAE,SAAQ,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC;IACpG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACpF;AAED,kFAAkF;AAClF,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC;IAC9B;;;;;OAKG;IACH,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,KAAK,SAAI,GAAG,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAQjK;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,CAAC,OAAO,CAAC,EAChD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CAAO,GAC/F,OAAO,CAAC,CAAC,CAAC,CAeZ"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the adapters' `createSql(client)` returns: a `sql` whose queries run on `client`, and
|
|
3
|
+
* `sql.transaction(fn)`, which runs `fn` with a `sql` bound to one transaction.
|
|
4
|
+
*/
|
|
5
|
+
import { createSql } from "./create-sql.js";
|
|
6
|
+
/**
|
|
7
|
+
* For adapters: core's `createSql` bound to `driver.executor(client)`, with `transaction(fn)`
|
|
8
|
+
* running on `driver.transaction`. Without a `client`, `execute*` and `transaction` reject.
|
|
9
|
+
*/
|
|
10
|
+
export function createTransactionalSql(client, driver, options, depth = 0) {
|
|
11
|
+
const sql = createSql(client === undefined ? undefined : driver.executor(client), options);
|
|
12
|
+
return Object.assign(sql, {
|
|
13
|
+
transaction: async (fn) => {
|
|
14
|
+
if (client === undefined)
|
|
15
|
+
throw new Error("typesql: no client: pass one to createSql(client) to use sql.transaction()");
|
|
16
|
+
return driver.transaction(client, depth, (tx) => fn(createTransactionalSql(tx, driver, options, depth + 1)));
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* For drivers without a transaction API: run `fn` between `BEGIN` and `COMMIT` sent with `run`
|
|
22
|
+
* on one connection, or between `SAVEPOINT name` and `RELEASE SAVEPOINT name` when `savepoint`
|
|
23
|
+
* is given (inside a transaction). When `fn` or the commit throws, it rolls back (`ROLLBACK`,
|
|
24
|
+
* `ROLLBACK TO SAVEPOINT name`) and rethrows that error; if the rollback fails too, its error is
|
|
25
|
+
* passed to `onRollbackError` and the original is still thrown. A failing `BEGIN` is thrown as is.
|
|
26
|
+
*/
|
|
27
|
+
export async function runTransaction(run, fn, options = {}) {
|
|
28
|
+
const sp = options.savepoint;
|
|
29
|
+
await run(sp ? `SAVEPOINT ${sp}` : "BEGIN");
|
|
30
|
+
try {
|
|
31
|
+
const result = await fn();
|
|
32
|
+
await run(sp ? `RELEASE SAVEPOINT ${sp}` : "COMMIT");
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
try {
|
|
37
|
+
await run(sp ? `ROLLBACK TO SAVEPOINT ${sp}` : "ROLLBACK");
|
|
38
|
+
}
|
|
39
|
+
catch (rollbackErr) {
|
|
40
|
+
options.onRollbackError?.(rollbackErr);
|
|
41
|
+
}
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAY,MAAM,iBAAiB,CAAC;AAyBtD;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAY,MAAqB,EAAE,MAAoB,EAAE,OAAoB,EAAE,KAAK,GAAG,CAAC;IAC5H,MAAM,GAAG,GAAG,SAAS,CAAS,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAA4C,CAAC,CAAC;IACxI,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;QACxB,WAAW,EAAE,KAAK,EAAK,EAAyD,EAAc,EAAE;YAC9F,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;YACxH,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,sBAAsB,CAAY,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1H,CAAC;KACF,CAAiD,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAgD,EAChD,EAAoB,EACpB,OAAO,GAAuF,EAAE;IAEhG,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAC7B,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;QAC1B,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -21,4 +21,5 @@ export type { Tok, Toks, WordTok, IdTok, NumTok, StrTok, ParamTok, OpTok } from
|
|
|
21
21
|
export type { ParseProgram, ParseStatement } from "./engine/parser/stmt.js";
|
|
22
22
|
export type * as Ast from "./engine/ast.js";
|
|
23
23
|
export type { ColInfo, ColMap, Cols, Scope, ScopeItem, ScopeLevel, Ctx, CteMap } from "./engine/types.js";
|
|
24
|
+
export { createTransactionalSql, runTransaction, type TransactionalSql, type SqlDriver } from "./transaction.js";
|
|
24
25
|
export { Migrations, migrations, runMigrations, type MigrationClient, type SchemaOf, type ValidateDdl } from "./migrations.js";
|
package/src/query.ts
CHANGED
|
@@ -24,9 +24,12 @@ export interface ExecutorResult {
|
|
|
24
24
|
* Runs a statement and resolves to its rows, or to `{ rows, rowCount }`. Adapters build one from a
|
|
25
25
|
* driver client (`executor(pool)` in `@typesql/pg`, which reports `rowCount`); pass it to
|
|
26
26
|
* `createSql(executor)` or to `q.execute(executor)`. An executor that resolves to the rows alone
|
|
27
|
-
* works for everything except `executeCount
|
|
27
|
+
* works for everything except `executeCount`, unless it also has a `count` method.
|
|
28
28
|
*/
|
|
29
|
-
export type Executor = (text: string, values: readonly unknown[]) => PromiseLike<readonly unknown[] | ExecutorResult
|
|
29
|
+
export type Executor = ((text: string, values: readonly unknown[]) => PromiseLike<readonly unknown[] | ExecutorResult>) & {
|
|
30
|
+
/** Runs the statement for its row count; `executeCount` uses it when present (Prisma's `$executeRaw`). */
|
|
31
|
+
readonly count?: (text: string, values: readonly unknown[]) => PromiseLike<number>;
|
|
32
|
+
};
|
|
30
33
|
|
|
31
34
|
/** Thrown by `executeTakeFirstOrThrow` when the query returns no rows. */
|
|
32
35
|
export class NoResultError extends Error {
|
|
@@ -81,7 +84,7 @@ const ROW_KEYS = Symbol.for("typesql.rowKeys");
|
|
|
81
84
|
/**
|
|
82
85
|
* Turn rows a driver returned for `q` into the rows `q`'s type describes: a fresh array, with
|
|
83
86
|
* the keys renamed when `q` comes from `createSql(executor, { rowKeys: "camelCase" })`. For
|
|
84
|
-
* helpers that run `q.text` themselves
|
|
87
|
+
* helpers that run `q.text` themselves instead of through an `Executor`.
|
|
85
88
|
*/
|
|
86
89
|
export function mapRows<Q extends { readonly text: string }>(q: Q, rows: readonly unknown[]): RowType<Q>[] {
|
|
87
90
|
return applyRowKeys(rows, rowKeysOf(q)) as RowType<Q>[];
|
|
@@ -102,13 +105,13 @@ export function makeQuery<Row, Params extends readonly unknown[], Text extends s
|
|
|
102
105
|
executor?: Executor,
|
|
103
106
|
rowKeys: RowKeys = "preserve",
|
|
104
107
|
): Query<Row, Params, Text> {
|
|
105
|
-
const
|
|
108
|
+
const pick = (given?: Executor): Executor => {
|
|
106
109
|
const exec = given ?? executor;
|
|
107
110
|
if (!exec) throw new Error("typesql: no executor: pass one to createSql(executor) or to execute(executor)");
|
|
108
|
-
return exec
|
|
111
|
+
return exec;
|
|
109
112
|
};
|
|
110
113
|
const execute = async (given?: Executor): Promise<unknown[]> => {
|
|
111
|
-
const result = await
|
|
114
|
+
const result = await pick(given)(text, values);
|
|
112
115
|
return applyRowKeys(isRows(result) ? result : result.rows, rowKeys);
|
|
113
116
|
};
|
|
114
117
|
return Object.defineProperties({ text, values }, {
|
|
@@ -116,7 +119,9 @@ export function makeQuery<Row, Params extends readonly unknown[], Text extends s
|
|
|
116
119
|
execute: { value: execute },
|
|
117
120
|
executeCount: {
|
|
118
121
|
value: async (given?: Executor) => {
|
|
119
|
-
const
|
|
122
|
+
const exec = pick(given);
|
|
123
|
+
if (exec.count) return exec.count(text, values);
|
|
124
|
+
const result = await exec(text, values);
|
|
120
125
|
if (isRows(result) || result.rowCount === undefined) {
|
|
121
126
|
throw new Error("typesql: the executor did not report a row count: resolve to { rows, rowCount } (the adapters' executor() do)");
|
|
122
127
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the adapters' `createSql(client)` returns: a `sql` whose queries run on `client`, and
|
|
3
|
+
* `sql.transaction(fn)`, which runs `fn` with a `sql` bound to one transaction.
|
|
4
|
+
*/
|
|
5
|
+
import { createSql, type Sql } from "./create-sql.js";
|
|
6
|
+
import type { Executor } from "./query.js";
|
|
7
|
+
import type { RowKeys, SqlOptions } from "./row-keys.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Core's `Sql` plus `transaction(fn)`: `fn` gets `tx`, the same `sql` bound to one transaction.
|
|
11
|
+
* The transaction commits when `fn` resolves and rolls back when it throws (the error is
|
|
12
|
+
* rethrown). `tx.transaction(fn)` nests with a savepoint.
|
|
13
|
+
*/
|
|
14
|
+
export interface TransactionalSql<DB, TM, Keys extends RowKeys = "preserve"> extends Sql<DB, TM, Keys> {
|
|
15
|
+
transaction<T>(fn: (tx: TransactionalSql<DB, TM, Keys>) => Promise<T>): Promise<T>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** How an adapter runs statements and transactions on its driver's client `C`. */
|
|
19
|
+
export interface SqlDriver<C> {
|
|
20
|
+
executor(client: C): Executor;
|
|
21
|
+
/**
|
|
22
|
+
* Run `fn` inside a transaction on `client` and resolve to its result: commit when `fn`
|
|
23
|
+
* resolves, roll back and rethrow when it throws. `fn` gets the client bound to the
|
|
24
|
+
* transaction. `depth` is how many `transaction` calls enclose this one (0 at the top), so a
|
|
25
|
+
* client that cannot tell can use a savepoint when `depth > 0`.
|
|
26
|
+
*/
|
|
27
|
+
transaction<T>(client: C, depth: number, fn: (tx: C) => Promise<T>): Promise<T>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* For adapters: core's `createSql` bound to `driver.executor(client)`, with `transaction(fn)`
|
|
32
|
+
* running on `driver.transaction`. Without a `client`, `execute*` and `transaction` reject.
|
|
33
|
+
*/
|
|
34
|
+
export function createTransactionalSql<DB, TM, C>(client: C | undefined, driver: SqlDriver<C>, options?: SqlOptions, depth = 0): TransactionalSql<DB, TM, RowKeys> {
|
|
35
|
+
const sql = createSql<DB, TM>(client === undefined ? undefined : driver.executor(client), options as { readonly rowKeys: "camelCase" });
|
|
36
|
+
return Object.assign(sql, {
|
|
37
|
+
transaction: async <T>(fn: (tx: TransactionalSql<DB, TM, RowKeys>) => Promise<T>): Promise<T> => {
|
|
38
|
+
if (client === undefined) throw new Error("typesql: no client: pass one to createSql(client) to use sql.transaction()");
|
|
39
|
+
return driver.transaction(client, depth, (tx) => fn(createTransactionalSql<DB, TM, C>(tx, driver, options, depth + 1)));
|
|
40
|
+
},
|
|
41
|
+
}) as unknown as TransactionalSql<DB, TM, RowKeys>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* For drivers without a transaction API: run `fn` between `BEGIN` and `COMMIT` sent with `run`
|
|
46
|
+
* on one connection, or between `SAVEPOINT name` and `RELEASE SAVEPOINT name` when `savepoint`
|
|
47
|
+
* is given (inside a transaction). When `fn` or the commit throws, it rolls back (`ROLLBACK`,
|
|
48
|
+
* `ROLLBACK TO SAVEPOINT name`) and rethrows that error; if the rollback fails too, its error is
|
|
49
|
+
* passed to `onRollbackError` and the original is still thrown. A failing `BEGIN` is thrown as is.
|
|
50
|
+
*/
|
|
51
|
+
export async function runTransaction<T>(
|
|
52
|
+
run: (statement: string) => PromiseLike<unknown>,
|
|
53
|
+
fn: () => Promise<T>,
|
|
54
|
+
options: { readonly savepoint?: string; readonly onRollbackError?: (err: unknown) => void } = {},
|
|
55
|
+
): Promise<T> {
|
|
56
|
+
const sp = options.savepoint;
|
|
57
|
+
await run(sp ? `SAVEPOINT ${sp}` : "BEGIN");
|
|
58
|
+
try {
|
|
59
|
+
const result = await fn();
|
|
60
|
+
await run(sp ? `RELEASE SAVEPOINT ${sp}` : "COMMIT");
|
|
61
|
+
return result;
|
|
62
|
+
} catch (err) {
|
|
63
|
+
try {
|
|
64
|
+
await run(sp ? `ROLLBACK TO SAVEPOINT ${sp}` : "ROLLBACK");
|
|
65
|
+
} catch (rollbackErr) {
|
|
66
|
+
options.onRollbackError?.(rollbackErr);
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|