@syncular/dialect-sqlite3 0.0.1-73 → 0.0.1-83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +16 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.test.ts +66 -0
- package/src/index.ts +14 -8
package/dist/index.d.ts
CHANGED
|
@@ -9,17 +9,18 @@
|
|
|
9
9
|
* into the promise-based interface Kysely expects.
|
|
10
10
|
*/
|
|
11
11
|
import { SerializePlugin } from '@syncular/core';
|
|
12
|
+
import type { DatabaseIntrospector, Dialect, DialectAdapter, Driver, QueryCompiler } from 'kysely';
|
|
12
13
|
import { Kysely } from 'kysely';
|
|
13
14
|
import sqlite3 from 'sqlite3';
|
|
14
|
-
interface Sqlite3PathOptions {
|
|
15
|
+
export interface Sqlite3PathOptions {
|
|
15
16
|
/** Path to SQLite database file, or ':memory:' for in-memory */
|
|
16
17
|
path: string;
|
|
17
18
|
}
|
|
18
|
-
interface Sqlite3InstanceOptions {
|
|
19
|
+
export interface Sqlite3InstanceOptions {
|
|
19
20
|
/** An existing sqlite3.Database instance */
|
|
20
21
|
database: sqlite3.Database;
|
|
21
22
|
}
|
|
22
|
-
type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
23
|
+
export type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
23
24
|
/**
|
|
24
25
|
* Create a Kysely instance with node-sqlite3 dialect and SerializePlugin.
|
|
25
26
|
*
|
|
@@ -28,6 +29,18 @@ type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
|
28
29
|
* const db = createSqlite3Db<MyDb>({ path: ':memory:' });
|
|
29
30
|
*/
|
|
30
31
|
export declare function createSqlite3Db<T>(options: Sqlite3Options): Kysely<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Create the sqlite3 dialect directly (without SerializePlugin).
|
|
34
|
+
*/
|
|
35
|
+
export declare function createSqlite3Dialect(options: Sqlite3Options): Sqlite3Dialect;
|
|
31
36
|
export declare function createSerializePlugin(): SerializePlugin;
|
|
37
|
+
declare class Sqlite3Dialect implements Dialect {
|
|
38
|
+
#private;
|
|
39
|
+
constructor(options: Sqlite3Options);
|
|
40
|
+
createAdapter(): DialectAdapter;
|
|
41
|
+
createDriver(): Driver;
|
|
42
|
+
createQueryCompiler(): QueryCompiler;
|
|
43
|
+
createIntrospector(db: Kysely<any>): DatabaseIntrospector;
|
|
44
|
+
}
|
|
32
45
|
export {};
|
|
33
46
|
//# 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;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAEV,oBAAoB,EACpB,OAAO,EACP,cAAc,EACd,MAAM,EACN,aAAa,EAGd,MAAM,QAAQ,CAAC;AAChB,OAAO,EAEL,MAAM,EAIP,MAAM,QAAQ,CAAC;AAChB,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,sBAAsB,CAAC;AAEzE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,CAKrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAE5E;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD;AAMD,cAAM,cAAe,YAAW,OAAO;;IAGrC,YAAY,OAAO,EAAE,cAAc,EAElC;IAED,aAAa,IAAI,cAAc,CAE9B;IAED,YAAY,IAAI,MAAM,CAErB;IAED,mBAAmB,IAAI,aAAa,CAEnC;IAED,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,oBAAoB,CAExD;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ export function createSqlite3Db(options) {
|
|
|
27
27
|
/**
|
|
28
28
|
* Create the sqlite3 dialect directly (without SerializePlugin).
|
|
29
29
|
*/
|
|
30
|
-
function createSqlite3Dialect(options) {
|
|
30
|
+
export function createSqlite3Dialect(options) {
|
|
31
31
|
return new Sqlite3Dialect(options);
|
|
32
32
|
}
|
|
33
33
|
export function createSerializePlugin() {
|
|
@@ -108,15 +108,21 @@ class Sqlite3Connection {
|
|
|
108
108
|
async executeQuery(compiledQuery) {
|
|
109
109
|
const { sql, parameters } = compiledQuery;
|
|
110
110
|
const params = [...parameters];
|
|
111
|
-
|
|
112
|
-
const
|
|
111
|
+
const hasReturning = /\breturning\b/i.test(sql);
|
|
112
|
+
const isSelectLike = /^\s*(select|pragma|explain|with)\b/i.test(sql);
|
|
113
113
|
const isInsert = /^\s*(insert|replace)\b/i.test(sql);
|
|
114
|
-
if (
|
|
114
|
+
if (isSelectLike || hasReturning) {
|
|
115
115
|
return new Promise((resolve, reject) => {
|
|
116
116
|
this.#db.all(sql, params, (err, rows) => {
|
|
117
117
|
if (err)
|
|
118
118
|
return reject(err);
|
|
119
|
-
|
|
119
|
+
const normalizedRows = rows ?? [];
|
|
120
|
+
resolve({
|
|
121
|
+
rows: normalizedRows,
|
|
122
|
+
...(hasReturning
|
|
123
|
+
? { numAffectedRows: BigInt(normalizedRows.length) }
|
|
124
|
+
: {}),
|
|
125
|
+
});
|
|
120
126
|
});
|
|
121
127
|
});
|
|
122
128
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWjD,OAAO,EACL,aAAa,EACb,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,QAAQ,CAAC;AAChB,OAAO,OAAO,MAAM,SAAS,CAAC;AAc9B;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAI,OAAuB,EAAa;IACrE,OAAO,IAAI,MAAM,CAAI;QACnB,OAAO,EAAE,oBAAoB,CAAC,OAAO,CAAC;QACtC,OAAO,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;KACjC,CAAC,CAAC;AAAA,CACJ;AAED;;GAEG;AACH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
|
2
|
+
import { Kysely, type Kysely as KyselyType } from 'kysely';
|
|
3
|
+
import { createSqlite3Db, createSqlite3Dialect } from './index';
|
|
4
|
+
|
|
5
|
+
interface TestDb {
|
|
6
|
+
tasks: {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe('sqlite3 dialect RETURNING behavior', () => {
|
|
13
|
+
let db: KyselyType<TestDb>;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
db = createSqlite3Db<TestDb>({ path: ':memory:' });
|
|
17
|
+
await db.schema
|
|
18
|
+
.createTable('tasks')
|
|
19
|
+
.addColumn('id', 'text', (col) => col.primaryKey())
|
|
20
|
+
.addColumn('title', 'text', (col) => col.notNull())
|
|
21
|
+
.execute();
|
|
22
|
+
await db
|
|
23
|
+
.insertInto('tasks')
|
|
24
|
+
.values({ id: 'task-1', title: 'before' })
|
|
25
|
+
.execute();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
await db.destroy();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('returns rows for non-select UPDATE ... RETURNING queries', async () => {
|
|
33
|
+
const updated = await db
|
|
34
|
+
.updateTable('tasks')
|
|
35
|
+
.set({ title: 'after' })
|
|
36
|
+
.where('id', '=', 'task-1')
|
|
37
|
+
.returning(['id', 'title'])
|
|
38
|
+
.executeTakeFirstOrThrow();
|
|
39
|
+
|
|
40
|
+
expect(updated).toEqual({ id: 'task-1', title: 'after' });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('supports direct dialect construction via createSqlite3Dialect', async () => {
|
|
44
|
+
const directDb = new Kysely<TestDb>({
|
|
45
|
+
dialect: createSqlite3Dialect({ path: ':memory:' }),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await directDb.schema
|
|
50
|
+
.createTable('tasks')
|
|
51
|
+
.addColumn('id', 'text', (col) => col.primaryKey())
|
|
52
|
+
.addColumn('title', 'text', (col) => col.notNull())
|
|
53
|
+
.execute();
|
|
54
|
+
|
|
55
|
+
const inserted = await directDb
|
|
56
|
+
.insertInto('tasks')
|
|
57
|
+
.values({ id: 'task-2', title: 'before' })
|
|
58
|
+
.returning(['id', 'title'])
|
|
59
|
+
.executeTakeFirstOrThrow();
|
|
60
|
+
|
|
61
|
+
expect(inserted).toEqual({ id: 'task-2', title: 'before' });
|
|
62
|
+
} finally {
|
|
63
|
+
await directDb.destroy();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -29,17 +29,17 @@ import {
|
|
|
29
29
|
} from 'kysely';
|
|
30
30
|
import sqlite3 from 'sqlite3';
|
|
31
31
|
|
|
32
|
-
interface Sqlite3PathOptions {
|
|
32
|
+
export interface Sqlite3PathOptions {
|
|
33
33
|
/** Path to SQLite database file, or ':memory:' for in-memory */
|
|
34
34
|
path: string;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
interface Sqlite3InstanceOptions {
|
|
37
|
+
export interface Sqlite3InstanceOptions {
|
|
38
38
|
/** An existing sqlite3.Database instance */
|
|
39
39
|
database: sqlite3.Database;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
42
|
+
export type Sqlite3Options = Sqlite3PathOptions | Sqlite3InstanceOptions;
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Create a Kysely instance with node-sqlite3 dialect and SerializePlugin.
|
|
@@ -58,7 +58,7 @@ export function createSqlite3Db<T>(options: Sqlite3Options): Kysely<T> {
|
|
|
58
58
|
/**
|
|
59
59
|
* Create the sqlite3 dialect directly (without SerializePlugin).
|
|
60
60
|
*/
|
|
61
|
-
function createSqlite3Dialect(options: Sqlite3Options): Sqlite3Dialect {
|
|
61
|
+
export function createSqlite3Dialect(options: Sqlite3Options): Sqlite3Dialect {
|
|
62
62
|
return new Sqlite3Dialect(options);
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -162,15 +162,21 @@ class Sqlite3Connection implements DatabaseConnection {
|
|
|
162
162
|
const { sql, parameters } = compiledQuery;
|
|
163
163
|
const params = [...parameters];
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
const
|
|
165
|
+
const hasReturning = /\breturning\b/i.test(sql);
|
|
166
|
+
const isSelectLike = /^\s*(select|pragma|explain|with)\b/i.test(sql);
|
|
167
167
|
const isInsert = /^\s*(insert|replace)\b/i.test(sql);
|
|
168
168
|
|
|
169
|
-
if (
|
|
169
|
+
if (isSelectLike || hasReturning) {
|
|
170
170
|
return new Promise<QueryResult<R>>((resolve, reject) => {
|
|
171
171
|
this.#db.all(sql, params, (err: Error | null, rows: R[]) => {
|
|
172
172
|
if (err) return reject(err);
|
|
173
|
-
|
|
173
|
+
const normalizedRows = rows ?? [];
|
|
174
|
+
resolve({
|
|
175
|
+
rows: normalizedRows,
|
|
176
|
+
...(hasReturning
|
|
177
|
+
? { numAffectedRows: BigInt(normalizedRows.length) }
|
|
178
|
+
: {}),
|
|
179
|
+
});
|
|
174
180
|
});
|
|
175
181
|
});
|
|
176
182
|
}
|