@pikku/kysely-node-sqlite 0.12.1
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 +9 -0
- package/dist/src/coercion-plugin.d.ts +24 -0
- package/dist/src/coercion-plugin.js +77 -0
- package/dist/src/create-node-sqlite-kysely.d.ts +10 -0
- package/dist/src/create-node-sqlite-kysely.js +15 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +3 -0
- package/dist/src/node-sqlite-adapter.d.ts +8 -0
- package/dist/src/node-sqlite-adapter.js +58 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +27 -0
- package/src/coercion-plugin.ts +92 -0
- package/src/create-node-sqlite-kysely.ts +31 -0
- package/src/index.ts +11 -0
- package/src/node-sqlite-adapter.ts +62 -0
- package/tsconfig.json +12 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @pikku/kysely-node-sqlite
|
|
2
|
+
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9060165: New `@pikku/kysely-node-sqlite` provides a Kysely dialect and migrator for Node's built-in `node:sqlite`. `@pikku/kysely-sqlite` adds a `LibsqlWebDialect` for running Kysely against Cloudflare Workers and Turso databases over HTTP.
|
|
8
|
+
- Updated dependencies [9060165]
|
|
9
|
+
- @pikku/kysely-sqlite@0.12.5
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { KyselyPlugin } from 'kysely';
|
|
2
|
+
export type ColumnKind = 'date' | 'bool' | 'json';
|
|
3
|
+
/**
|
|
4
|
+
* Per-table column kind map. Keys are snake_case table names matching the
|
|
5
|
+
* physical SQLite tables; inner keys are snake_case column names.
|
|
6
|
+
* Generated by `pikku db migrate` from `-- @date|@bool|@json` annotations
|
|
7
|
+
* and naming conventions (col ends in _at/_on → date; starts with is_/has_/can_ → bool).
|
|
8
|
+
*/
|
|
9
|
+
export type CoercionMap = Record<string, Record<string, ColumnKind>>;
|
|
10
|
+
export interface CreateCoercionPluginOptions {
|
|
11
|
+
map: CoercionMap;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Convert SQLite-stored values (TEXT/INTEGER) back into the logical types
|
|
15
|
+
* app code expects (Date / boolean / parsed JSON).
|
|
16
|
+
*
|
|
17
|
+
* Write-side coercion (Date → ISO string, boolean → 0/1, object → JSON) is
|
|
18
|
+
* handled in the NodeSqliteDatabase adapter (always-on), so this plugin is
|
|
19
|
+
* read-only.
|
|
20
|
+
*
|
|
21
|
+
* Place AFTER CamelCasePlugin in the plugin array (or it handles both
|
|
22
|
+
* orderings via the dual-keyed global map).
|
|
23
|
+
*/
|
|
24
|
+
export declare function createCoercionPlugin(options: CreateCoercionPluginOptions): KyselyPlugin;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function fromDb(value, kind) {
|
|
2
|
+
if (value == null)
|
|
3
|
+
return value;
|
|
4
|
+
switch (kind) {
|
|
5
|
+
case 'date':
|
|
6
|
+
if (typeof value === 'string') {
|
|
7
|
+
const d = new Date(value);
|
|
8
|
+
return Number.isNaN(d.getTime()) ? value : d;
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
case 'bool':
|
|
12
|
+
if (typeof value === 'number')
|
|
13
|
+
return value !== 0;
|
|
14
|
+
if (typeof value === 'bigint')
|
|
15
|
+
return value !== 0n;
|
|
16
|
+
return value;
|
|
17
|
+
case 'json':
|
|
18
|
+
if (typeof value !== 'string')
|
|
19
|
+
return value;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function snakeToCamel(name) {
|
|
29
|
+
return name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Flatten the per-table map into a single column-name → kind lookup.
|
|
33
|
+
* Indexed by BOTH snake_case and camelCase so it works regardless of
|
|
34
|
+
* CamelCasePlugin ordering in the plugin array.
|
|
35
|
+
*/
|
|
36
|
+
function buildGlobalMap(map) {
|
|
37
|
+
const out = {};
|
|
38
|
+
for (const tbl of Object.values(map)) {
|
|
39
|
+
for (const [col, kind] of Object.entries(tbl)) {
|
|
40
|
+
out[col] = kind;
|
|
41
|
+
out[snakeToCamel(col)] = kind;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert SQLite-stored values (TEXT/INTEGER) back into the logical types
|
|
48
|
+
* app code expects (Date / boolean / parsed JSON).
|
|
49
|
+
*
|
|
50
|
+
* Write-side coercion (Date → ISO string, boolean → 0/1, object → JSON) is
|
|
51
|
+
* handled in the NodeSqliteDatabase adapter (always-on), so this plugin is
|
|
52
|
+
* read-only.
|
|
53
|
+
*
|
|
54
|
+
* Place AFTER CamelCasePlugin in the plugin array (or it handles both
|
|
55
|
+
* orderings via the dual-keyed global map).
|
|
56
|
+
*/
|
|
57
|
+
export function createCoercionPlugin(options) {
|
|
58
|
+
const globalMap = buildGlobalMap(options.map);
|
|
59
|
+
return {
|
|
60
|
+
transformQuery(args) {
|
|
61
|
+
return args.node;
|
|
62
|
+
},
|
|
63
|
+
async transformResult(args) {
|
|
64
|
+
const out = [];
|
|
65
|
+
for (const row of args.result.rows) {
|
|
66
|
+
const next = { ...row };
|
|
67
|
+
for (const [col, val] of Object.entries(row)) {
|
|
68
|
+
const kind = globalMap[col];
|
|
69
|
+
if (kind)
|
|
70
|
+
next[col] = fromDb(val, kind);
|
|
71
|
+
}
|
|
72
|
+
out.push(next);
|
|
73
|
+
}
|
|
74
|
+
return { ...args.result, rows: out };
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Kysely, type KyselyPlugin } from 'kysely';
|
|
2
|
+
export interface CreateNodeSqliteKyselyOptions {
|
|
3
|
+
/** Path to the SQLite file. Use ':memory:' for an in-memory DB. */
|
|
4
|
+
filename: string;
|
|
5
|
+
/** Apply CamelCasePlugin so DB columns map to camelCase TS fields. Default true. */
|
|
6
|
+
camelCase?: boolean;
|
|
7
|
+
/** Extra plugins to layer on top. */
|
|
8
|
+
plugins?: KyselyPlugin[];
|
|
9
|
+
}
|
|
10
|
+
export declare function createNodeSqliteKysely<DB>(options: CreateNodeSqliteKyselyOptions): Kysely<DB>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { Kysely, SqliteDialect, CamelCasePlugin, } from 'kysely';
|
|
3
|
+
import { NodeSqliteDatabase } from './node-sqlite-adapter.js';
|
|
4
|
+
export function createNodeSqliteKysely(options) {
|
|
5
|
+
const db = new DatabaseSync(options.filename);
|
|
6
|
+
const plugins = [];
|
|
7
|
+
if (options.camelCase ?? true)
|
|
8
|
+
plugins.push(new CamelCasePlugin());
|
|
9
|
+
if (options.plugins)
|
|
10
|
+
plugins.push(...options.plugins);
|
|
11
|
+
return new Kysely({
|
|
12
|
+
dialect: new SqliteDialect({ database: new NodeSqliteDatabase(db) }),
|
|
13
|
+
plugins,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { NodeSqliteDatabase } from './node-sqlite-adapter.js';
|
|
2
|
+
export { createNodeSqliteKysely, type CreateNodeSqliteKyselyOptions, } from './create-node-sqlite-kysely.js';
|
|
3
|
+
export { createCoercionPlugin, type CoercionMap, type ColumnKind, type CreateCoercionPluginOptions, } from './coercion-plugin.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { SqliteDatabase, SqliteStatement } from 'kysely';
|
|
3
|
+
export declare class NodeSqliteDatabase implements SqliteDatabase {
|
|
4
|
+
private readonly db;
|
|
5
|
+
constructor(db: DatabaseSync);
|
|
6
|
+
prepare(sql: string): SqliteStatement;
|
|
7
|
+
close(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Always-on write-side coercion: converts JS values that SQLite's node:sqlite
|
|
3
|
+
* binding cannot accept into their storable equivalents.
|
|
4
|
+
* boolean → 0 | 1
|
|
5
|
+
* Date → ISO 8601 string
|
|
6
|
+
* object → JSON string (covers arrays and plain objects)
|
|
7
|
+
*/
|
|
8
|
+
function coerce(v) {
|
|
9
|
+
if (v === null || v === undefined)
|
|
10
|
+
return null;
|
|
11
|
+
if (typeof v === 'boolean')
|
|
12
|
+
return v ? 1 : 0;
|
|
13
|
+
if (v instanceof Date)
|
|
14
|
+
return v.toISOString();
|
|
15
|
+
if (typeof v === 'object')
|
|
16
|
+
return JSON.stringify(v);
|
|
17
|
+
return v;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Wraps node:sqlite's DatabaseSync as Kysely's SqliteDatabase. The shapes
|
|
21
|
+
* are close but not identical: node:sqlite's Statement methods take
|
|
22
|
+
* variadic positional params and always return bigint counters; Kysely's
|
|
23
|
+
* dialect passes parameters as a ReadonlyArray and expects number|bigint.
|
|
24
|
+
*/
|
|
25
|
+
class NodeSqliteStatement {
|
|
26
|
+
stmt;
|
|
27
|
+
reader = true;
|
|
28
|
+
constructor(stmt) {
|
|
29
|
+
this.stmt = stmt;
|
|
30
|
+
}
|
|
31
|
+
all(parameters) {
|
|
32
|
+
return this.stmt.all(...parameters.map(coerce));
|
|
33
|
+
}
|
|
34
|
+
*iterate(parameters) {
|
|
35
|
+
for (const row of this.stmt.iterate(...parameters.map(coerce))) {
|
|
36
|
+
yield row;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
run(parameters) {
|
|
40
|
+
const result = this.stmt.run(...parameters.map(coerce));
|
|
41
|
+
return {
|
|
42
|
+
changes: result.changes,
|
|
43
|
+
lastInsertRowid: result.lastInsertRowid,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class NodeSqliteDatabase {
|
|
48
|
+
db;
|
|
49
|
+
constructor(db) {
|
|
50
|
+
this.db = db;
|
|
51
|
+
}
|
|
52
|
+
prepare(sql) {
|
|
53
|
+
return new NodeSqliteStatement(this.db.prepare(sql));
|
|
54
|
+
}
|
|
55
|
+
close() {
|
|
56
|
+
this.db.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/coercion-plugin.ts","../src/create-node-sqlite-kysely.ts","../src/index.ts","../src/node-sqlite-adapter.ts"],"version":"5.9.3"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pikku/kysely-node-sqlite",
|
|
3
|
+
"version": "0.12.1",
|
|
4
|
+
"author": "yasser.fadl@gmail.com",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"module": "dist/src/index.js",
|
|
7
|
+
"main": "dist/src/index.js",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"tsc": "tsc",
|
|
11
|
+
"ncu": "npx npm-check-updates",
|
|
12
|
+
"build": "tsc -b",
|
|
13
|
+
"prepublishOnly": "yarn build"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=22.10"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@pikku/kysely": "^0.12.0",
|
|
20
|
+
"@pikku/kysely-sqlite": "^0.12.5",
|
|
21
|
+
"kysely": "^0.28.12"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22",
|
|
25
|
+
"typescript": "^5.9"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { KyselyPlugin, UnknownRow } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export type ColumnKind = 'date' | 'bool' | 'json'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Per-table column kind map. Keys are snake_case table names matching the
|
|
7
|
+
* physical SQLite tables; inner keys are snake_case column names.
|
|
8
|
+
* Generated by `pikku db migrate` from `-- @date|@bool|@json` annotations
|
|
9
|
+
* and naming conventions (col ends in _at/_on → date; starts with is_/has_/can_ → bool).
|
|
10
|
+
*/
|
|
11
|
+
export type CoercionMap = Record<string, Record<string, ColumnKind>>
|
|
12
|
+
|
|
13
|
+
export interface CreateCoercionPluginOptions {
|
|
14
|
+
map: CoercionMap
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fromDb(value: unknown, kind: ColumnKind): unknown {
|
|
18
|
+
if (value == null) return value
|
|
19
|
+
switch (kind) {
|
|
20
|
+
case 'date':
|
|
21
|
+
if (typeof value === 'string') {
|
|
22
|
+
const d = new Date(value)
|
|
23
|
+
return Number.isNaN(d.getTime()) ? value : d
|
|
24
|
+
}
|
|
25
|
+
return value
|
|
26
|
+
case 'bool':
|
|
27
|
+
if (typeof value === 'number') return value !== 0
|
|
28
|
+
if (typeof value === 'bigint') return value !== 0n
|
|
29
|
+
return value
|
|
30
|
+
case 'json':
|
|
31
|
+
if (typeof value !== 'string') return value
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(value)
|
|
34
|
+
} catch {
|
|
35
|
+
return value
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function snakeToCamel(name: string): string {
|
|
41
|
+
return name.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Flatten the per-table map into a single column-name → kind lookup.
|
|
46
|
+
* Indexed by BOTH snake_case and camelCase so it works regardless of
|
|
47
|
+
* CamelCasePlugin ordering in the plugin array.
|
|
48
|
+
*/
|
|
49
|
+
function buildGlobalMap(map: CoercionMap): Record<string, ColumnKind> {
|
|
50
|
+
const out: Record<string, ColumnKind> = {}
|
|
51
|
+
for (const tbl of Object.values(map)) {
|
|
52
|
+
for (const [col, kind] of Object.entries(tbl)) {
|
|
53
|
+
out[col] = kind
|
|
54
|
+
out[snakeToCamel(col)] = kind
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Convert SQLite-stored values (TEXT/INTEGER) back into the logical types
|
|
62
|
+
* app code expects (Date / boolean / parsed JSON).
|
|
63
|
+
*
|
|
64
|
+
* Write-side coercion (Date → ISO string, boolean → 0/1, object → JSON) is
|
|
65
|
+
* handled in the NodeSqliteDatabase adapter (always-on), so this plugin is
|
|
66
|
+
* read-only.
|
|
67
|
+
*
|
|
68
|
+
* Place AFTER CamelCasePlugin in the plugin array (or it handles both
|
|
69
|
+
* orderings via the dual-keyed global map).
|
|
70
|
+
*/
|
|
71
|
+
export function createCoercionPlugin(
|
|
72
|
+
options: CreateCoercionPluginOptions
|
|
73
|
+
): KyselyPlugin {
|
|
74
|
+
const globalMap = buildGlobalMap(options.map)
|
|
75
|
+
return {
|
|
76
|
+
transformQuery(args) {
|
|
77
|
+
return args.node
|
|
78
|
+
},
|
|
79
|
+
async transformResult(args) {
|
|
80
|
+
const out: UnknownRow[] = []
|
|
81
|
+
for (const row of args.result.rows as UnknownRow[]) {
|
|
82
|
+
const next: UnknownRow = { ...row }
|
|
83
|
+
for (const [col, val] of Object.entries(row)) {
|
|
84
|
+
const kind = globalMap[col]
|
|
85
|
+
if (kind) next[col] = fromDb(val, kind)
|
|
86
|
+
}
|
|
87
|
+
out.push(next)
|
|
88
|
+
}
|
|
89
|
+
return { ...args.result, rows: out }
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
2
|
+
import {
|
|
3
|
+
Kysely,
|
|
4
|
+
SqliteDialect,
|
|
5
|
+
CamelCasePlugin,
|
|
6
|
+
type KyselyPlugin,
|
|
7
|
+
} from 'kysely'
|
|
8
|
+
import { NodeSqliteDatabase } from './node-sqlite-adapter.js'
|
|
9
|
+
|
|
10
|
+
export interface CreateNodeSqliteKyselyOptions {
|
|
11
|
+
/** Path to the SQLite file. Use ':memory:' for an in-memory DB. */
|
|
12
|
+
filename: string
|
|
13
|
+
/** Apply CamelCasePlugin so DB columns map to camelCase TS fields. Default true. */
|
|
14
|
+
camelCase?: boolean
|
|
15
|
+
/** Extra plugins to layer on top. */
|
|
16
|
+
plugins?: KyselyPlugin[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createNodeSqliteKysely<DB>(
|
|
20
|
+
options: CreateNodeSqliteKyselyOptions
|
|
21
|
+
): Kysely<DB> {
|
|
22
|
+
const db = new DatabaseSync(options.filename)
|
|
23
|
+
const plugins: KyselyPlugin[] = []
|
|
24
|
+
if (options.camelCase ?? true) plugins.push(new CamelCasePlugin())
|
|
25
|
+
if (options.plugins) plugins.push(...options.plugins)
|
|
26
|
+
|
|
27
|
+
return new Kysely<DB>({
|
|
28
|
+
dialect: new SqliteDialect({ database: new NodeSqliteDatabase(db) }),
|
|
29
|
+
plugins,
|
|
30
|
+
})
|
|
31
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { NodeSqliteDatabase } from './node-sqlite-adapter.js'
|
|
2
|
+
export {
|
|
3
|
+
createNodeSqliteKysely,
|
|
4
|
+
type CreateNodeSqliteKyselyOptions,
|
|
5
|
+
} from './create-node-sqlite-kysely.js'
|
|
6
|
+
export {
|
|
7
|
+
createCoercionPlugin,
|
|
8
|
+
type CoercionMap,
|
|
9
|
+
type ColumnKind,
|
|
10
|
+
type CreateCoercionPluginOptions,
|
|
11
|
+
} from './coercion-plugin.js'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { DatabaseSync, StatementSync, SQLInputValue } from 'node:sqlite'
|
|
2
|
+
import type { SqliteDatabase, SqliteStatement } from 'kysely'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Always-on write-side coercion: converts JS values that SQLite's node:sqlite
|
|
6
|
+
* binding cannot accept into their storable equivalents.
|
|
7
|
+
* boolean → 0 | 1
|
|
8
|
+
* Date → ISO 8601 string
|
|
9
|
+
* object → JSON string (covers arrays and plain objects)
|
|
10
|
+
*/
|
|
11
|
+
function coerce(v: unknown): SQLInputValue {
|
|
12
|
+
if (v === null || v === undefined) return null as unknown as SQLInputValue
|
|
13
|
+
if (typeof v === 'boolean') return v ? 1 : 0
|
|
14
|
+
if (v instanceof Date) return v.toISOString()
|
|
15
|
+
if (typeof v === 'object') return JSON.stringify(v)
|
|
16
|
+
return v as SQLInputValue
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Wraps node:sqlite's DatabaseSync as Kysely's SqliteDatabase. The shapes
|
|
21
|
+
* are close but not identical: node:sqlite's Statement methods take
|
|
22
|
+
* variadic positional params and always return bigint counters; Kysely's
|
|
23
|
+
* dialect passes parameters as a ReadonlyArray and expects number|bigint.
|
|
24
|
+
*/
|
|
25
|
+
class NodeSqliteStatement implements SqliteStatement {
|
|
26
|
+
readonly reader = true
|
|
27
|
+
|
|
28
|
+
constructor(private readonly stmt: StatementSync) {}
|
|
29
|
+
|
|
30
|
+
all(parameters: ReadonlyArray<unknown>): unknown[] {
|
|
31
|
+
return this.stmt.all(...parameters.map(coerce)) as unknown[]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
*iterate(parameters: ReadonlyArray<unknown>): IterableIterator<unknown> {
|
|
35
|
+
for (const row of this.stmt.iterate(...parameters.map(coerce))) {
|
|
36
|
+
yield row
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
run(parameters: ReadonlyArray<unknown>): {
|
|
41
|
+
changes: number | bigint
|
|
42
|
+
lastInsertRowid: number | bigint
|
|
43
|
+
} {
|
|
44
|
+
const result = this.stmt.run(...parameters.map(coerce))
|
|
45
|
+
return {
|
|
46
|
+
changes: result.changes,
|
|
47
|
+
lastInsertRowid: result.lastInsertRowid,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class NodeSqliteDatabase implements SqliteDatabase {
|
|
53
|
+
constructor(private readonly db: DatabaseSync) {}
|
|
54
|
+
|
|
55
|
+
prepare(sql: string): SqliteStatement {
|
|
56
|
+
return new NodeSqliteStatement(this.db.prepare(sql))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
close(): void {
|
|
60
|
+
this.db.close()
|
|
61
|
+
}
|
|
62
|
+
}
|
package/tsconfig.json
ADDED