@typesql/kysely 0.0.3 → 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 +26 -0
- package/README.md +34 -17
- package/dist/client.d.ts +14 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +26 -11
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +21 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -15
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/src/client.ts +31 -16
- package/src/index.ts +31 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @typesql/kysely
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Queries run from the `sql` bound to your client: `createSql<DB>(client)` then `sql("…").execute()` (or `executeTakeFirst`, `executeTakeFirstOrThrow`, `executeCount`), and `sql.transaction(async (tx) => …)` for transactions, nested with savepoints; the `query`, `one`, `maybeOne`, `many`, `execute`, `transaction` and `RowCountError` exports of `@typesql/pg` and `@typesql/postgres`, `query` and `execute` of `@typesql/kysely`, and `queryRaw` and `executeRaw` of `@typesql/prisma` are removed.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @typesql/core@0.1.0
|
|
13
|
+
|
|
14
|
+
## 0.0.4
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Queries have `executeCount()`, which resolves to the affected row count: an `Executor` may resolve to `{ rows, rowCount }` instead of the rows, as the `executor()` of `@typesql/pg`, `@typesql/postgres` and `@typesql/kysely` now do.
|
|
19
|
+
|
|
20
|
+
- `createSql(executor, { rowKeys: "camelCase" })` (and the adapters' `createSql(client, { rowKeys: "camelCase" })`) camelCases the top-level row keys the way Kysely's `CamelCasePlugin` does, in the row types and in the rows `execute*` and the `query`/`one`/`maybeOne`/`many` helpers return, leaving JSON values untouched.
|
|
21
|
+
|
|
22
|
+
- `execute(db, q)` returns the number of rows for statements Kysely reports no `numAffectedRows` for (`SELECT`), as `@typesql/pg` does, instead of 0.
|
|
23
|
+
|
|
24
|
+
- Parameters accept `null` wherever Postgres does: comparisons (`col = $1`, `IN`, `ANY`, `LIKE`), `LIMIT`/`OFFSET`, casts in comparisons and function arguments (`coalesce($1::text, 'x')`), and array elements (`(number | null)[]`); assigning `null` to a `NOT NULL` column is still an error.
|
|
25
|
+
|
|
26
|
+
- Updated dependencies:
|
|
27
|
+
- @typesql/core@0.0.4
|
|
28
|
+
|
|
3
29
|
## 0.0.3
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ pnpm add @typesql/core @typesql/kysely kysely
|
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
|
-
import { createSql
|
|
13
|
+
import { createSql } from "@typesql/kysely";
|
|
14
14
|
import type { DB } from "./db"; // kysely-codegen output
|
|
15
15
|
|
|
16
|
-
const sql = createSql<DB>();
|
|
16
|
+
const sql = createSql<DB>(db); // db: your Kysely<DB> instance, or a Transaction<DB>
|
|
17
17
|
|
|
18
18
|
const q = sql(
|
|
19
19
|
`SELECT u.id, u.email, p.title, p.views
|
|
@@ -21,19 +21,25 @@ const q = sql(
|
|
|
21
21
|
WHERE u.id = $1 AND p.published = $2`,
|
|
22
22
|
1, true,
|
|
23
23
|
);
|
|
24
|
-
// ^? Query<{ id: number; email: string; title: string; views: string }, [number, boolean]>
|
|
24
|
+
// ^? Query<{ id: number; email: string; title: string; views: string }, [number | null, boolean | null]>
|
|
25
25
|
|
|
26
|
-
const rows = await
|
|
26
|
+
const rows = await q.execute();
|
|
27
|
+
|
|
28
|
+
await sql.transaction(async (tx) => {
|
|
29
|
+
await tx("UPDATE posts SET published = true WHERE author_id = $1", 1).execute();
|
|
30
|
+
});
|
|
27
31
|
```
|
|
28
32
|
|
|
29
33
|
## API
|
|
30
34
|
|
|
31
35
|
| Export | What it is |
|
|
32
36
|
|---|---|
|
|
33
|
-
| `createSql<DB, TM = DefaultTypeMap, Overrides = {}, Options = {}>()` | core's `createSql<FromKysely<DB, Overrides, Options>, TM>()` |
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
+
| `createSql<DB, TM = DefaultTypeMap, Overrides = {}, Options = {}>(db, options?)` | core's `createSql<FromKysely<DB, Overrides, Options>, TM>()` with the queries running on `db`; `{ rowKeys: "camelCase" }` gives `CamelCasePlugin`-style row keys |
|
|
38
|
+
| `q.execute()`, `q.executeTakeFirst()`, `q.executeTakeFirstOrThrow()`, `q.executeCount()` | `Promise<Row[]>`, `Promise<Row \| undefined>`, `Promise<Row>` (`NoResultError` on 0 rows), `Promise<number>` (`numAffectedRows`; for other statements the number of rows returned, 0 for DDL) |
|
|
39
|
+
| `sql.transaction(fn)` | `db.transaction().execute(...)` with `tx` bound to the transaction; on a `Transaction`, and for `tx.transaction(fn)`, a savepoint |
|
|
40
|
+
| `FromKysely<DB, Overrides = {}, Options = {}>` | the converted schema type, for use with core's `createSql<Schema, TM>()` or the adapters' `createSql<Schema>(client)` |
|
|
41
|
+
| `KyselySql<DB, TM, Overrides, Options, Keys>` | the type `createSql` returns |
|
|
42
|
+
| `executor(db)` | an `Executor` for `q.execute(executor)` and core's `createSql(executor)`, also bypassing plugins |
|
|
37
43
|
| `InferColumn<T>` | the descriptor inferred for one Kysely column type (handy to check a mapping) |
|
|
38
44
|
| `SnakeCase<S>` | `CamelCasePlugin`'s default camelCase → snake_case mapping, at the type level |
|
|
39
45
|
| `KyselyOverrides`, `TableOverride`, `ColumnOverride`, `KyselyOptions`, `KyselyExecutor` | parameter types |
|
|
@@ -47,15 +53,16 @@ import type { PgTypeMap } from "@typesql/pg";
|
|
|
47
53
|
import { createSql, type FromKysely } from "@typesql/kysely";
|
|
48
54
|
import { createSql as createCoreSql } from "@typesql/core";
|
|
49
55
|
|
|
50
|
-
const sql = createSql<DB, PgTypeMap>();
|
|
51
|
-
const same = createCoreSql<FromKysely<DB>, PgTypeMap>();
|
|
56
|
+
const sql = createSql<DB, PgTypeMap>(db);
|
|
57
|
+
const same = createCoreSql<FromKysely<DB>, PgTypeMap>(); // types only, no client
|
|
52
58
|
```
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
Queries are sent as `CompiledQuery.raw(q.text, q.values)` through
|
|
55
61
|
`db.withoutPlugins().executeQuery(...)`. Plugins are bypassed on purpose: typesql's row types
|
|
56
62
|
describe what Postgres returns (`created_at`), and a result transformer such as
|
|
57
|
-
`CamelCasePlugin` would rename the keys
|
|
58
|
-
|
|
63
|
+
`CamelCasePlugin` would rename the keys (use `{ rowKeys: "camelCase" }` for camelCase rows).
|
|
64
|
+
Logging, the dialect and the connection pool are unaffected. Inside a Kysely transaction,
|
|
65
|
+
`createSql<DB>(trx)` binds a `sql` to it, so builder and SQL queries share the transaction.
|
|
59
66
|
|
|
60
67
|
## How columns are converted
|
|
61
68
|
|
|
@@ -103,7 +110,7 @@ const sql = createSql<DB, DefaultTypeMap, {
|
|
|
103
110
|
"auth.users": { id: "uuid" };
|
|
104
111
|
active_users: { $view: true }; // a view: INSERT/UPDATE/DELETE are rejected
|
|
105
112
|
$types: { mood: Mood; "auth.role": AuthRole }; // enum names, see below
|
|
106
|
-
}>();
|
|
113
|
+
}>(db);
|
|
107
114
|
```
|
|
108
115
|
|
|
109
116
|
A descriptor may set any of `type`, `nullable` and `hasDefault`; the others stay inferred.
|
|
@@ -135,7 +142,7 @@ under `$types` and every column whose values are **exactly** that union gets the
|
|
|
135
142
|
```ts
|
|
136
143
|
import type { Mood, AuthRole } from "./db"; // kysely-codegen exports one alias per enum
|
|
137
144
|
|
|
138
|
-
createSql<DB, DefaultTypeMap, { $types: { mood: Mood; "auth.role": AuthRole } }>();
|
|
145
|
+
createSql<DB, DefaultTypeMap, { $types: { mood: Mood; "auth.role": AuthRole } }>(db);
|
|
139
146
|
```
|
|
140
147
|
|
|
141
148
|
If two `$types` entries have the same values the column keeps its derived name; set the column's
|
|
@@ -151,14 +158,24 @@ back to the database's snake_case names the way `CamelCasePlugin` does by defaul
|
|
|
151
158
|
`created_at`, `userID` → `user_id`), so the SQL you write and the rows you get use the real names:
|
|
152
159
|
|
|
153
160
|
```ts
|
|
154
|
-
const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>();
|
|
161
|
+
const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db);
|
|
155
162
|
const q = sql("SELECT author_id, created_at FROM blog_posts WHERE id = $1", 1);
|
|
156
|
-
// ^? Query<{ author_id: number; created_at: Date }, [number]>
|
|
163
|
+
// ^? Query<{ author_id: number; created_at: Date }, [number | null]>
|
|
157
164
|
```
|
|
158
165
|
|
|
159
166
|
Overrides still use the interface's (camelCase) keys. The plugin's non-default options
|
|
160
167
|
(`upperCase`, `underscoreBeforeDigits`, `underscoreBetweenUppercaseLetters`) are not modelled.
|
|
161
168
|
|
|
169
|
+
For camelCase **rows**, add `{ rowKeys: "camelCase" }`. The top-level keys are renamed with
|
|
170
|
+
`CamelCasePlugin`'s default snake_case → camelCase mapping, in the row types and at runtime.
|
|
171
|
+
The plugin itself stays bypassed, so keys inside JSON values are left alone:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db, { rowKeys: "camelCase" });
|
|
175
|
+
const post = await sql("SELECT author_id, created_at FROM blog_posts WHERE id = $1", 1).executeTakeFirstOrThrow();
|
|
176
|
+
// ^? { authorId: number; createdAt: Date }
|
|
177
|
+
```
|
|
178
|
+
|
|
162
179
|
## Limitations
|
|
163
180
|
|
|
164
181
|
- **The TS → Postgres mapping is lossy.** `number`, `string` and `Date` each stand for several
|
package/dist/client.d.ts
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { CompiledQuery, type QueryResult } from "kysely";
|
|
2
|
-
import type
|
|
2
|
+
import { type Executor, type SqlDriver } from "@typesql/core";
|
|
3
3
|
/**
|
|
4
|
-
* What the
|
|
4
|
+
* What the adapter uses from a `Kysely<DB>` or `Transaction<DB>`. Queries run through
|
|
5
5
|
* `withoutPlugins()`: typesql's row types describe what the driver returns, so result
|
|
6
|
-
* transformers such as `CamelCasePlugin` must not rename the columns
|
|
6
|
+
* transformers such as `CamelCasePlugin` must not rename the columns (`createSql(db,
|
|
7
|
+
* { rowKeys: "camelCase" })` renames the top-level keys instead, in the types too).
|
|
7
8
|
*/
|
|
8
9
|
export interface KyselyExecutor {
|
|
9
10
|
withoutPlugins(): {
|
|
10
11
|
executeQuery<R>(query: CompiledQuery<R>): Promise<QueryResult<R>>;
|
|
11
12
|
};
|
|
13
|
+
transaction(): {
|
|
14
|
+
execute<T>(fn: (trx: KyselyExecutor) => Promise<T>): Promise<T>;
|
|
15
|
+
};
|
|
16
|
+
readonly isTransaction: boolean;
|
|
12
17
|
}
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
/**
|
|
19
|
+
* An `Executor` for core's `q.execute()`: runs queries on a Kysely instance (or transaction),
|
|
20
|
+
* without its plugins, and resolves to `{ rows, rowCount }` so `q.executeCount()` works.
|
|
21
|
+
*/
|
|
15
22
|
export declare function executor(db: KyselyExecutor): Executor;
|
|
16
|
-
/**
|
|
17
|
-
export declare
|
|
18
|
-
/** Run a statement for its side effect and return the affected row count (`numAffectedRows`, or 0). */
|
|
19
|
-
export declare function execute(db: KyselyExecutor, q: AnyQuery): Promise<number>;
|
|
20
|
-
export {};
|
|
23
|
+
/** How `createSql(db)` runs queries and transactions. */
|
|
24
|
+
export declare const driver: SqlDriver<KyselyExecutor>;
|
|
21
25
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,IAAI;QAAE,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC;IACxF,WAAW,IAAI;QAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC;IACnF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAcD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG,QAAQ,CAKrD;AAWD,yDAAyD;AACzD,eAAO,MAAM,MAAM,EAAE,SAAS,CAAC,cAAc,CAA6B,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
1
|
import { CompiledQuery } from "kysely";
|
|
2
|
+
import { runTransaction } from "@typesql/core";
|
|
2
3
|
function run(db, text, values) {
|
|
3
4
|
return db.withoutPlugins().executeQuery(CompiledQuery.raw(text, Array.from(values)));
|
|
4
5
|
}
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Kysely reports `numAffectedRows` for INSERT/UPDATE/DELETE/MERGE only; for other statements the
|
|
8
|
+
* count is the rows returned (SELECT), or 0 (DDL), as Postgres' command tag says.
|
|
9
|
+
*/
|
|
10
|
+
function rowCount(result) {
|
|
11
|
+
return result.numAffectedRows === undefined ? result.rows.length : Number(result.numAffectedRows);
|
|
8
12
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* An `Executor` for core's `q.execute()`: runs queries on a Kysely instance (or transaction),
|
|
15
|
+
* without its plugins, and resolves to `{ rows, rowCount }` so `q.executeCount()` works.
|
|
16
|
+
*/
|
|
17
|
+
export function executor(db) {
|
|
18
|
+
return async (text, values) => {
|
|
19
|
+
const result = await run(db, text, values);
|
|
20
|
+
return { rows: result.rows, rowCount: rowCount(result) };
|
|
21
|
+
};
|
|
13
22
|
}
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Run `fn` inside `db.transaction().execute()`. A Kysely `Transaction` cannot start another one,
|
|
25
|
+
* so inside one `fn` runs in a savepoint.
|
|
26
|
+
*/
|
|
27
|
+
function transaction(db, depth, fn) {
|
|
28
|
+
if (!db.isTransaction)
|
|
29
|
+
return db.transaction().execute(fn);
|
|
30
|
+
return runTransaction((statement) => run(db, statement, []), () => fn(db), { savepoint: `typesql_${depth + 1}` });
|
|
18
31
|
}
|
|
32
|
+
/** How `createSql(db)` runs queries and transactions. */
|
|
33
|
+
export const driver = { executor, transaction };
|
|
19
34
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,cAAc,EAAiC,MAAM,eAAe,CAAC;AAc9E,SAAS,GAAG,CAAI,EAAkB,EAAE,IAAY,EAAE,MAA0B;IAC1E,OAAO,EAAE,CAAC,cAAc,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAqB,CAAC,CAAC;AAC3G,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,MAA4B;IAC5C,OAAO,MAAM,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AACpG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAkB;IACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAU,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3D,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAI,EAAkB,EAAE,KAAa,EAAE,EAAuC;IAChG,IAAI,CAAC,EAAE,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,cAAc,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;AACpH,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,MAAM,GAA8B,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import { type DefaultTypeMap, type
|
|
1
|
+
import { type DefaultTypeMap, type RowKeys, type TransactionalSql } from "@typesql/core";
|
|
2
2
|
import { type KyselyExecutor } from "./client.js";
|
|
3
3
|
import type { FromKysely, KyselyOptions, KyselyOverrides } from "./from-kysely.js";
|
|
4
|
-
export { NoResultError, type Executor } from "@typesql/core";
|
|
4
|
+
export { NoResultError, type Executor, type TransactionalSql } from "@typesql/core";
|
|
5
5
|
export type { FromKysely, KyselyOverrides, KyselyOptions, TableOverride, ColumnOverride, InferColumn, SnakeCase } from "./from-kysely.js";
|
|
6
|
-
export {
|
|
6
|
+
export { executor, type KyselyExecutor } from "./client.js";
|
|
7
|
+
/** What `createSql<DB>(db)` returns: core's `Sql` over `FromKysely<DB, ...>`, with `transaction(fn)`. */
|
|
8
|
+
export type KyselySql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}, Keys extends RowKeys = "preserve"> = TransactionalSql<FromKysely<DB, Overrides, Options>, TM, Keys>;
|
|
7
9
|
/**
|
|
8
10
|
* `createSql` from core with a Kysely `DB` interface as the schema:
|
|
9
|
-
* `createSql<DB>()` is `createSql<FromKysely<DB>, DefaultTypeMap>()`.
|
|
11
|
+
* `createSql<DB>(db)` is `createSql<FromKysely<DB>, DefaultTypeMap>()` bound to `db`.
|
|
10
12
|
*
|
|
11
|
-
* const sql = createSql<DB>();
|
|
12
|
-
* const sql = createSql<DB, PgTypeMap, { users: { id: "int8" } }>();
|
|
13
|
-
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>();
|
|
13
|
+
* const sql = createSql<DB>(db);
|
|
14
|
+
* const sql = createSql<DB, PgTypeMap, { users: { id: "int8" } }>(db);
|
|
15
|
+
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db);
|
|
14
16
|
*
|
|
15
|
-
*
|
|
17
|
+
* The queries' `execute*` methods run on `db` (a `Kysely` instance or transaction), bypassing
|
|
18
|
+
* its plugins, and `sql.transaction(fn)` runs `fn` with a `sql` bound to one transaction.
|
|
19
|
+
* `{ rowKeys: "camelCase" }` camelCases the rows' top-level keys as `CamelCasePlugin` does, in
|
|
20
|
+
* the types and at runtime, without touching JSON values:
|
|
21
|
+
*
|
|
22
|
+
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db, { rowKeys: "camelCase" });
|
|
16
23
|
*/
|
|
17
|
-
export declare function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(db
|
|
24
|
+
export declare function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(db: KyselyExecutor | undefined, options: {
|
|
25
|
+
readonly rowKeys: "camelCase";
|
|
26
|
+
}): KyselySql<DB, TM, Overrides, Options, "camelCase">;
|
|
27
|
+
export declare function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(db?: KyselyExecutor, options?: {
|
|
28
|
+
readonly rowKeys?: "preserve";
|
|
29
|
+
}): KyselySql<DB, TM, Overrides, Options>;
|
|
18
30
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,cAAc,EAAE,KAAK,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClI,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACpF,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1I,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5D,yGAAyG;AACzG,MAAM,MAAM,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,EAAE,SAAS,SAAS,eAAe,GAAG,EAAE,EAAE,OAAO,SAAS,aAAa,GAAG,EAAE,EAAE,IAAI,SAAS,OAAO,GAAG,UAAU,IAC1J,gBAAgB,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;AAEjE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,EAAE,SAAS,SAAS,eAAe,GAAG,EAAE,EAAE,OAAO,SAAS,aAAa,GAAG,EAAE,EAC3H,EAAE,EAAE,cAAc,GAAG,SAAS,EAC9B,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACzC,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;AACtD,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,EAAE,SAAS,SAAS,eAAe,GAAG,EAAE,EAAE,OAAO,SAAS,aAAa,GAAG,EAAE,EAC3H,EAAE,CAAC,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,GAC1C,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createTransactionalSql } from "@typesql/core";
|
|
2
|
+
import { driver } from "./client.js";
|
|
3
3
|
export { NoResultError } from "@typesql/core";
|
|
4
|
-
export {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* `createSql<DB>()` is `createSql<FromKysely<DB>, DefaultTypeMap>()`.
|
|
8
|
-
*
|
|
9
|
-
* const sql = createSql<DB>();
|
|
10
|
-
* const sql = createSql<DB, PgTypeMap, { users: { id: "int8" } }>();
|
|
11
|
-
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>();
|
|
12
|
-
*
|
|
13
|
-
* With a `db` (a `Kysely` instance or transaction), the queries' `execute*` methods run on it.
|
|
14
|
-
*/
|
|
15
|
-
export function createSql(db) {
|
|
16
|
-
return createCoreSql(db && executor(db));
|
|
4
|
+
export { executor } from "./client.js";
|
|
5
|
+
export function createSql(db, options) {
|
|
6
|
+
return createTransactionalSql(db, driver, options);
|
|
17
7
|
}
|
|
18
8
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA6E,MAAM,eAAe,CAAC;AAClI,OAAO,EAAE,MAAM,EAAuB,MAAM,aAAa,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAwC,MAAM,eAAe,CAAC;AAEpF,OAAO,EAAE,QAAQ,EAAuB,MAAM,aAAa,CAAC;AA6B5D,MAAM,UAAU,SAAS,CACvB,EAAmB,EACnB,OAAoB;IAEpB,OAAO,sBAAsB,CAAyD,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7G,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typesql/kysely",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Use Kysely database interfaces (kysely-codegen, prisma-kysely) as a typesql schema.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,13 +28,15 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@typesql/core": "0.0
|
|
31
|
+
"@typesql/core": "0.1.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"kysely": ">=0.27"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
+
"@types/pg": "^8.23.1",
|
|
37
38
|
"kysely": "^0.29.6",
|
|
39
|
+
"pg": "^8.23.1",
|
|
38
40
|
"typescript": "7.0.2",
|
|
39
41
|
"vitest": "^5.0.4"
|
|
40
42
|
},
|
package/src/client.ts
CHANGED
|
@@ -1,34 +1,49 @@
|
|
|
1
1
|
import { CompiledQuery, type QueryResult } from "kysely";
|
|
2
|
-
import
|
|
2
|
+
import { runTransaction, type Executor, type SqlDriver } from "@typesql/core";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* What the
|
|
5
|
+
* What the adapter uses from a `Kysely<DB>` or `Transaction<DB>`. Queries run through
|
|
6
6
|
* `withoutPlugins()`: typesql's row types describe what the driver returns, so result
|
|
7
|
-
* transformers such as `CamelCasePlugin` must not rename the columns
|
|
7
|
+
* transformers such as `CamelCasePlugin` must not rename the columns (`createSql(db,
|
|
8
|
+
* { rowKeys: "camelCase" })` renames the top-level keys instead, in the types too).
|
|
8
9
|
*/
|
|
9
10
|
export interface KyselyExecutor {
|
|
10
11
|
withoutPlugins(): { executeQuery<R>(query: CompiledQuery<R>): Promise<QueryResult<R>> };
|
|
12
|
+
transaction(): { execute<T>(fn: (trx: KyselyExecutor) => Promise<T>): Promise<T> };
|
|
13
|
+
readonly isTransaction: boolean;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
type AnyQuery = Query<unknown, readonly unknown[]>;
|
|
14
|
-
|
|
15
16
|
function run<R>(db: KyselyExecutor, text: string, values: readonly unknown[]): Promise<QueryResult<R>> {
|
|
16
17
|
return db.withoutPlugins().executeQuery(CompiledQuery.raw(text, Array.from(values)) as CompiledQuery<R>);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Kysely reports `numAffectedRows` for INSERT/UPDATE/DELETE/MERGE only; for other statements the
|
|
22
|
+
* count is the rows returned (SELECT), or 0 (DDL), as Postgres' command tag says.
|
|
23
|
+
*/
|
|
24
|
+
function rowCount(result: QueryResult<unknown>): number {
|
|
25
|
+
return result.numAffectedRows === undefined ? result.rows.length : Number(result.numAffectedRows);
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
/**
|
|
29
|
+
* An `Executor` for core's `q.execute()`: runs queries on a Kysely instance (or transaction),
|
|
30
|
+
* without its plugins, and resolves to `{ rows, rowCount }` so `q.executeCount()` works.
|
|
31
|
+
*/
|
|
32
|
+
export function executor(db: KyselyExecutor): Executor {
|
|
33
|
+
return async (text, values) => {
|
|
34
|
+
const result = await run<unknown>(db, text, values);
|
|
35
|
+
return { rows: result.rows, rowCount: rowCount(result) };
|
|
36
|
+
};
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Run `fn` inside `db.transaction().execute()`. A Kysely `Transaction` cannot start another one,
|
|
41
|
+
* so inside one `fn` runs in a savepoint.
|
|
42
|
+
*/
|
|
43
|
+
function transaction<T>(db: KyselyExecutor, depth: number, fn: (trx: KyselyExecutor) => Promise<T>): Promise<T> {
|
|
44
|
+
if (!db.isTransaction) return db.transaction().execute(fn);
|
|
45
|
+
return runTransaction((statement) => run(db, statement, []), () => fn(db), { savepoint: `typesql_${depth + 1}` });
|
|
34
46
|
}
|
|
47
|
+
|
|
48
|
+
/** How `createSql(db)` runs queries and transactions. */
|
|
49
|
+
export const driver: SqlDriver<KyselyExecutor> = { executor, transaction };
|
package/src/index.ts
CHANGED
|
@@ -1,26 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createTransactionalSql, type DefaultTypeMap, type RowKeys, type SqlOptions, type TransactionalSql } from "@typesql/core";
|
|
2
|
+
import { driver, type KyselyExecutor } from "./client.js";
|
|
3
3
|
import type { FromKysely, KyselyOptions, KyselyOverrides } from "./from-kysely.js";
|
|
4
4
|
|
|
5
|
-
export { NoResultError, type Executor } from "@typesql/core";
|
|
5
|
+
export { NoResultError, type Executor, type TransactionalSql } from "@typesql/core";
|
|
6
6
|
export type { FromKysely, KyselyOverrides, KyselyOptions, TableOverride, ColumnOverride, InferColumn, SnakeCase } from "./from-kysely.js";
|
|
7
|
-
export {
|
|
7
|
+
export { executor, type KyselyExecutor } from "./client.js";
|
|
8
|
+
|
|
9
|
+
/** What `createSql<DB>(db)` returns: core's `Sql` over `FromKysely<DB, ...>`, with `transaction(fn)`. */
|
|
10
|
+
export type KyselySql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}, Keys extends RowKeys = "preserve"> =
|
|
11
|
+
TransactionalSql<FromKysely<DB, Overrides, Options>, TM, Keys>;
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* `createSql` from core with a Kysely `DB` interface as the schema:
|
|
11
|
-
* `createSql<DB>()` is `createSql<FromKysely<DB>, DefaultTypeMap>()`.
|
|
15
|
+
* `createSql<DB>(db)` is `createSql<FromKysely<DB>, DefaultTypeMap>()` bound to `db`.
|
|
16
|
+
*
|
|
17
|
+
* const sql = createSql<DB>(db);
|
|
18
|
+
* const sql = createSql<DB, PgTypeMap, { users: { id: "int8" } }>(db);
|
|
19
|
+
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db);
|
|
12
20
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
21
|
+
* The queries' `execute*` methods run on `db` (a `Kysely` instance or transaction), bypassing
|
|
22
|
+
* its plugins, and `sql.transaction(fn)` runs `fn` with a `sql` bound to one transaction.
|
|
23
|
+
* `{ rowKeys: "camelCase" }` camelCases the rows' top-level keys as `CamelCasePlugin` does, in
|
|
24
|
+
* the types and at runtime, without touching JSON values:
|
|
16
25
|
*
|
|
17
|
-
*
|
|
26
|
+
* const sql = createSql<DB, DefaultTypeMap, {}, { camelCase: true }>(db, { rowKeys: "camelCase" });
|
|
18
27
|
*/
|
|
19
|
-
export function createSql<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
export function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(
|
|
29
|
+
db: KyselyExecutor | undefined,
|
|
30
|
+
options: { readonly rowKeys: "camelCase" },
|
|
31
|
+
): KyselySql<DB, TM, Overrides, Options, "camelCase">;
|
|
32
|
+
export function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(
|
|
33
|
+
db?: KyselyExecutor,
|
|
34
|
+
options?: { readonly rowKeys?: "preserve" },
|
|
35
|
+
): KyselySql<DB, TM, Overrides, Options>;
|
|
36
|
+
export function createSql<DB, TM = DefaultTypeMap, Overrides extends KyselyOverrides = {}, Options extends KyselyOptions = {}>(
|
|
37
|
+
db?: KyselyExecutor,
|
|
38
|
+
options?: SqlOptions,
|
|
39
|
+
): KyselySql<DB, TM, Overrides, Options, RowKeys> {
|
|
40
|
+
return createTransactionalSql<FromKysely<DB, Overrides, Options>, TM, KyselyExecutor>(db, driver, options);
|
|
26
41
|
}
|