@nexusts/kysely 0.9.5
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/bun-sqlite-dialect.d.ts +50 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +445 -0
- package/dist/index.js.map +14 -0
- package/dist/kysely.module.d.ts +19 -0
- package/dist/raw-query.d.ts +36 -0
- package/dist/repository/index.d.ts +1 -0
- package/dist/types.d.ts +86 -0
- package/package.json +52 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `BunSqliteDialect` — a Kysely dialect for Bun's built-in `bun:sqlite`.
|
|
3
|
+
*
|
|
4
|
+
* Kysely's built-in `SqliteDialect` requires `better-sqlite3`, which
|
|
5
|
+
* does not work in Bun. This lightweight wrapper patches the `.reader`
|
|
6
|
+
* property onto prepared statements, so Kysely's `SqliteDialect` can
|
|
7
|
+
* distinguish SELECT queries from INSERT/UPDATE/DELETE.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Kysely, SqliteDialect } from "kysely";
|
|
12
|
+
* import { Database } from "bun:sqlite";
|
|
13
|
+
* import { BunSqliteDialect } from "@nexusts/kysely";
|
|
14
|
+
*
|
|
15
|
+
* const db = new Kysely({
|
|
16
|
+
* dialect: new SqliteDialect({
|
|
17
|
+
* database: BunSqliteDialect.wrap(new Database("app.db")),
|
|
18
|
+
* }),
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class BunSqliteDialect {
|
|
23
|
+
/**
|
|
24
|
+
* Wrap a Bun SQLite `Database` instance so it works with Kysely's
|
|
25
|
+
* `SqliteDialect`.
|
|
26
|
+
*
|
|
27
|
+
* The returned object has the same interface as a
|
|
28
|
+
* `better-sqlite3.Database` — Kysely's SqliteDriver checks
|
|
29
|
+
* `stmt.reader` to decide whether to call `stmt.all()` (SELECT) or
|
|
30
|
+
* `stmt.run()` (INSERT/UPDATE/DELETE). Bun's `bun:sqlite` doesn't
|
|
31
|
+
* expose this property, so we inject it by analyzing the SQL text.
|
|
32
|
+
*
|
|
33
|
+
* @param db - A `bun:sqlite` `Database` instance
|
|
34
|
+
* @returns A wrapped database compatible with `SqliteDialect`
|
|
35
|
+
*/
|
|
36
|
+
static wrap(db: any): any;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new in-memory Bun SQLite database, pre-wrapped for Kysely.
|
|
39
|
+
*
|
|
40
|
+
* @returns A wrapped `Database(":memory:")` instance
|
|
41
|
+
*/
|
|
42
|
+
static inMemory(): any;
|
|
43
|
+
/**
|
|
44
|
+
* Create a new file-based Bun SQLite database, pre-wrapped for Kysely.
|
|
45
|
+
*
|
|
46
|
+
* @param filename - Path to the SQLite database file
|
|
47
|
+
* @returns A wrapped `Database(filename)` instance
|
|
48
|
+
*/
|
|
49
|
+
static file(filename: string): any;
|
|
50
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry point for `@nexusts/kysely`.
|
|
3
|
+
*
|
|
4
|
+
* Kysely is a type-safe SQL query builder for TypeScript.
|
|
5
|
+
* This integration provides:
|
|
6
|
+
* - `KyselyService` — wraps a Kysely instance with DI support
|
|
7
|
+
* - `KyselyModule` — `forRoot()` / `forRootAsync()` module registration
|
|
8
|
+
* - `KyselyRepository` — Lucid-style repository pattern
|
|
9
|
+
*
|
|
10
|
+
* Kysely is an optional peer dependency. Install it with `bun add kysely`.
|
|
11
|
+
*/
|
|
12
|
+
export * from "./types.js";
|
|
13
|
+
export { KyselyService } from "./kysely.service.js";
|
|
14
|
+
export type { KyselyTransaction } from "./kysely.service.js";
|
|
15
|
+
export { KyselyModule } from "./kysely.module.js";
|
|
16
|
+
export { KyselyRepository } from "./repository/index.js";
|
|
17
|
+
export { RawQuery } from "./raw-query.js";
|
|
18
|
+
export type { RawExecutor } from "./raw-query.js";
|
|
19
|
+
export { BunSqliteDialect } from "./bun-sqlite-dialect.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
21
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
22
|
+
else
|
|
23
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
24
|
+
if (d = decorators[i])
|
|
25
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
26
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
27
|
+
};
|
|
28
|
+
var __legacyMetadataTS = (k, v) => {
|
|
29
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
30
|
+
return Reflect.metadata(k, v);
|
|
31
|
+
};
|
|
32
|
+
var __require = import.meta.require;
|
|
33
|
+
// packages/kysely/src/kysely.service.ts
|
|
34
|
+
import { Injectable } from "@nexusts/core";
|
|
35
|
+
class KyselyService {
|
|
36
|
+
static TOKEN = Symbol.for("nexus:KyselyService");
|
|
37
|
+
_db = null;
|
|
38
|
+
_config;
|
|
39
|
+
_options;
|
|
40
|
+
_opened = false;
|
|
41
|
+
_logger = null;
|
|
42
|
+
constructor(config, options) {
|
|
43
|
+
this._config = config;
|
|
44
|
+
this._options = options ?? {};
|
|
45
|
+
if (options?.logging) {
|
|
46
|
+
const log = options.logging;
|
|
47
|
+
this._logger = typeof log === "function" ? log : (q, p) => {
|
|
48
|
+
const trimmed = q.replace(/\s+/g, " ").trim();
|
|
49
|
+
if (p.length === 0)
|
|
50
|
+
console.log(`[kysely] ${trimmed}`);
|
|
51
|
+
else
|
|
52
|
+
console.log(`[kysely] ${trimmed} -- params: ${JSON.stringify(p)}`);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
this._autoOpenSync();
|
|
56
|
+
}
|
|
57
|
+
_autoOpenSync() {
|
|
58
|
+
try {
|
|
59
|
+
const mod = __require("kysely");
|
|
60
|
+
if (!mod?.Kysely)
|
|
61
|
+
return;
|
|
62
|
+
const { Kysely } = mod;
|
|
63
|
+
const mergedConfig = { ...this._config };
|
|
64
|
+
if (this._logger) {
|
|
65
|
+
mergedConfig.log = (event) => {
|
|
66
|
+
if (event.level === "query" && event.query) {
|
|
67
|
+
this._logger(event.query.sql, event.query.parameters);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
this._db = new Kysely(mergedConfig);
|
|
72
|
+
this._opened = true;
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
async open() {
|
|
76
|
+
if (this._opened)
|
|
77
|
+
return;
|
|
78
|
+
const { Kysely } = await loadKysely();
|
|
79
|
+
const mergedConfig = { ...this._config };
|
|
80
|
+
if (this._logger) {
|
|
81
|
+
mergedConfig.log = (event) => {
|
|
82
|
+
if (event.level === "query" && event.query) {
|
|
83
|
+
this._logger(event.query.sql, event.query.parameters);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
this._db = new Kysely(mergedConfig);
|
|
88
|
+
this._opened = true;
|
|
89
|
+
if (this._options.migrations?.autoMigrate) {
|
|
90
|
+
await this.migrate();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async getDb() {
|
|
94
|
+
if (!this._opened)
|
|
95
|
+
await this.open();
|
|
96
|
+
return this._db;
|
|
97
|
+
}
|
|
98
|
+
get db() {
|
|
99
|
+
if (!this._db) {
|
|
100
|
+
throw new Error("[kysely] service not opened. Call open() or await getDb() first.");
|
|
101
|
+
}
|
|
102
|
+
return this._db;
|
|
103
|
+
}
|
|
104
|
+
selectFrom(table) {
|
|
105
|
+
this.ensureOpen();
|
|
106
|
+
return this.db.selectFrom(table);
|
|
107
|
+
}
|
|
108
|
+
insertInto(table) {
|
|
109
|
+
this.ensureOpen();
|
|
110
|
+
return this.db.insertInto(table);
|
|
111
|
+
}
|
|
112
|
+
updateTable(table) {
|
|
113
|
+
this.ensureOpen();
|
|
114
|
+
return this.db.updateTable(table);
|
|
115
|
+
}
|
|
116
|
+
deleteFrom(table) {
|
|
117
|
+
this.ensureOpen();
|
|
118
|
+
return this.db.deleteFrom(table);
|
|
119
|
+
}
|
|
120
|
+
get schema() {
|
|
121
|
+
this.ensureOpen();
|
|
122
|
+
return this.db.schema;
|
|
123
|
+
}
|
|
124
|
+
async executeRaw(query) {
|
|
125
|
+
this.ensureOpen();
|
|
126
|
+
const result = await query.execute(this.db);
|
|
127
|
+
return result.rows;
|
|
128
|
+
}
|
|
129
|
+
async transaction(fn) {
|
|
130
|
+
this.ensureOpen();
|
|
131
|
+
return this.db.transaction().execute(async (trx) => {
|
|
132
|
+
const txWrapper = {
|
|
133
|
+
selectFrom: (table) => trx.selectFrom(table),
|
|
134
|
+
insertInto: (table) => trx.insertInto(table),
|
|
135
|
+
updateTable: (table) => trx.updateTable(table),
|
|
136
|
+
deleteFrom: (table) => trx.deleteFrom(table),
|
|
137
|
+
executeRaw: async (query) => {
|
|
138
|
+
const result = await query.execute(trx);
|
|
139
|
+
return result.rows;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
return fn(txWrapper);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async migrate() {
|
|
146
|
+
if (!this._options.migrations?.provider) {
|
|
147
|
+
throw new Error("[kysely] No migration provider configured. " + "Pass `migrations: { provider: new FileMigrationProvider(...) }` to KyselyModule.forRoot().");
|
|
148
|
+
}
|
|
149
|
+
this.ensureOpen();
|
|
150
|
+
const { Migrator } = await importKysely();
|
|
151
|
+
const migrator = new Migrator({
|
|
152
|
+
db: this.db,
|
|
153
|
+
provider: this._options.migrations.provider,
|
|
154
|
+
...this._options.migrations.tableName ? { migrationTableName: this._options.migrations.tableName } : {}
|
|
155
|
+
});
|
|
156
|
+
const { results, error } = await migrator.migrateToLatest();
|
|
157
|
+
if (error) {
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
const applied = (results ?? []).filter((r) => r.status === "Success" || r.status === "MigratedAbove").map((r) => ({
|
|
161
|
+
name: r.migrationName ?? String(r.name ?? ""),
|
|
162
|
+
appliedAt: new Date
|
|
163
|
+
}));
|
|
164
|
+
const errors = (results ?? []).filter((r) => r.status === "Error").map((r) => ({
|
|
165
|
+
name: r.migrationName ?? String(r.name ?? ""),
|
|
166
|
+
error: r.error ?? new Error("Unknown migration error")
|
|
167
|
+
}));
|
|
168
|
+
return {
|
|
169
|
+
applied,
|
|
170
|
+
total: (results ?? []).length,
|
|
171
|
+
errors
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async close() {
|
|
175
|
+
if (this._db) {
|
|
176
|
+
await this._db.destroy();
|
|
177
|
+
}
|
|
178
|
+
this._db = null;
|
|
179
|
+
this._opened = false;
|
|
180
|
+
}
|
|
181
|
+
ensureOpen() {
|
|
182
|
+
if (!this._db) {
|
|
183
|
+
throw new Error("[kysely] service not opened. Call open() or await getDb() first.");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
KyselyService = __legacyDecorateClassTS([
|
|
188
|
+
Injectable(),
|
|
189
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
190
|
+
typeof KyselyConfig === "undefined" ? Object : KyselyConfig,
|
|
191
|
+
typeof KyselyServiceOptions === "undefined" ? Object : KyselyServiceOptions
|
|
192
|
+
])
|
|
193
|
+
], KyselyService);
|
|
194
|
+
var _kyselyMod = null;
|
|
195
|
+
var _kyselyAttempted = false;
|
|
196
|
+
async function loadKysely() {
|
|
197
|
+
if (_kyselyMod)
|
|
198
|
+
return _kyselyMod;
|
|
199
|
+
if (_kyselyAttempted) {
|
|
200
|
+
throw new Error("[@nexusts/kysely] `kysely` failed to load. Install with `bun add kysely`.");
|
|
201
|
+
}
|
|
202
|
+
_kyselyAttempted = true;
|
|
203
|
+
try {
|
|
204
|
+
const mod = await import("kysely");
|
|
205
|
+
_kyselyMod = { Kysely: mod.Kysely };
|
|
206
|
+
return _kyselyMod;
|
|
207
|
+
} catch (err) {
|
|
208
|
+
throw new Error("[@nexusts/kysely] `kysely` is required. Install with `bun add kysely`.\nOriginal error: " + err.message);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
var _kyselyFullMod = null;
|
|
212
|
+
async function importKysely() {
|
|
213
|
+
if (_kyselyFullMod)
|
|
214
|
+
return _kyselyFullMod;
|
|
215
|
+
try {
|
|
216
|
+
_kyselyFullMod = await import("kysely");
|
|
217
|
+
return _kyselyFullMod;
|
|
218
|
+
} catch (err) {
|
|
219
|
+
throw new Error("[@nexusts/kysely] `kysely` is required. Install with `bun add kysely`.\nOriginal error: " + err.message);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// packages/kysely/src/kysely.module.ts
|
|
223
|
+
import { Module } from "@nexusts/core";
|
|
224
|
+
class KyselyModule {
|
|
225
|
+
static forRoot(opts) {
|
|
226
|
+
class ConfiguredKyselyModule {
|
|
227
|
+
}
|
|
228
|
+
ConfiguredKyselyModule = __legacyDecorateClassTS([
|
|
229
|
+
Module({
|
|
230
|
+
providers: [
|
|
231
|
+
{
|
|
232
|
+
provide: KyselyService.TOKEN,
|
|
233
|
+
useFactory: () => new KyselyService(opts.config, {
|
|
234
|
+
migrations: opts.migrations,
|
|
235
|
+
logging: opts.logging
|
|
236
|
+
})
|
|
237
|
+
},
|
|
238
|
+
{ provide: KyselyService, useExisting: KyselyService.TOKEN },
|
|
239
|
+
{ provide: "KYSELY_CONFIG", useValue: opts.config },
|
|
240
|
+
{ provide: "KYSELY_OPTIONS", useValue: { migrations: opts.migrations, logging: opts.logging } }
|
|
241
|
+
],
|
|
242
|
+
exports: [KyselyService.TOKEN, KyselyService, "KYSELY_CONFIG", "KYSELY_OPTIONS"]
|
|
243
|
+
})
|
|
244
|
+
], ConfiguredKyselyModule);
|
|
245
|
+
Object.defineProperty(ConfiguredKyselyModule, "name", { value: "ConfiguredKyselyModule" });
|
|
246
|
+
return ConfiguredKyselyModule;
|
|
247
|
+
}
|
|
248
|
+
static forRootAsync(opts) {
|
|
249
|
+
|
|
250
|
+
class ConfiguredKyselyModuleAsync {
|
|
251
|
+
}
|
|
252
|
+
ConfiguredKyselyModuleAsync = __legacyDecorateClassTS([
|
|
253
|
+
Module({
|
|
254
|
+
imports: opts.imports ?? [],
|
|
255
|
+
providers: [
|
|
256
|
+
{
|
|
257
|
+
provide: "KYSELY_ASYNC_CONFIG",
|
|
258
|
+
useFactory: opts.useFactory,
|
|
259
|
+
inject: opts.inject ?? []
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
provide: KyselyService.TOKEN,
|
|
263
|
+
useFactory: async (...args) => {
|
|
264
|
+
const resolvedConfig = args[args.length - 1];
|
|
265
|
+
return new KyselyService(resolvedConfig.config, {
|
|
266
|
+
migrations: resolvedConfig.migrations,
|
|
267
|
+
logging: resolvedConfig.logging
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
inject: [...opts.inject ?? [], "KYSELY_ASYNC_CONFIG"]
|
|
271
|
+
},
|
|
272
|
+
{ provide: KyselyService, useExisting: KyselyService.TOKEN }
|
|
273
|
+
],
|
|
274
|
+
exports: [KyselyService.TOKEN, KyselyService]
|
|
275
|
+
})
|
|
276
|
+
], ConfiguredKyselyModuleAsync);
|
|
277
|
+
Object.defineProperty(ConfiguredKyselyModuleAsync, "name", { value: "ConfiguredKyselyModuleAsync" });
|
|
278
|
+
return ConfiguredKyselyModuleAsync;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// packages/kysely/src/repository/repository.ts
|
|
282
|
+
class KyselyRepository {
|
|
283
|
+
db;
|
|
284
|
+
tableName;
|
|
285
|
+
constructor(db, tableName) {
|
|
286
|
+
if (db !== undefined)
|
|
287
|
+
this.db = db;
|
|
288
|
+
if (tableName !== undefined)
|
|
289
|
+
this.tableName = tableName;
|
|
290
|
+
}
|
|
291
|
+
get qb() {
|
|
292
|
+
return this.db.selectFrom(this.tableName);
|
|
293
|
+
}
|
|
294
|
+
async findAll(opts = {}) {
|
|
295
|
+
let query = this.qb.selectAll();
|
|
296
|
+
if (opts.where) {
|
|
297
|
+
query = query.where(opts.where);
|
|
298
|
+
}
|
|
299
|
+
if (opts.orderBy) {
|
|
300
|
+
const arr = Array.isArray(opts.orderBy) ? opts.orderBy : [opts.orderBy];
|
|
301
|
+
query = query.orderBy(arr);
|
|
302
|
+
}
|
|
303
|
+
if (opts.limit !== undefined) {
|
|
304
|
+
query = query.limit(opts.limit);
|
|
305
|
+
}
|
|
306
|
+
if (opts.offset !== undefined) {
|
|
307
|
+
query = query.offset(opts.offset);
|
|
308
|
+
}
|
|
309
|
+
return query.execute();
|
|
310
|
+
}
|
|
311
|
+
async findOne(where) {
|
|
312
|
+
const rows = await this.findAll({ where, limit: 1 });
|
|
313
|
+
return rows[0];
|
|
314
|
+
}
|
|
315
|
+
async findById(id) {
|
|
316
|
+
const rows = await this.qb.selectAll().where("id", "=", id).limit(1).execute();
|
|
317
|
+
return rows[0];
|
|
318
|
+
}
|
|
319
|
+
async create(values) {
|
|
320
|
+
const rows = await this.db.insertInto(this.tableName).values(values).returningAll().execute();
|
|
321
|
+
return rows[0];
|
|
322
|
+
}
|
|
323
|
+
async createMany(values) {
|
|
324
|
+
if (values.length === 0)
|
|
325
|
+
return [];
|
|
326
|
+
const rows = await this.db.insertInto(this.tableName).values(values).returningAll().execute();
|
|
327
|
+
return rows;
|
|
328
|
+
}
|
|
329
|
+
async update(where, patch) {
|
|
330
|
+
const rows = await this.db.updateTable(this.tableName).set(patch).where(where).returningAll().execute();
|
|
331
|
+
return rows;
|
|
332
|
+
}
|
|
333
|
+
async updateById(id, patch) {
|
|
334
|
+
const rows = await this.db.updateTable(this.tableName).set(patch).where("id", "=", id).returningAll().execute();
|
|
335
|
+
return rows[0];
|
|
336
|
+
}
|
|
337
|
+
async delete(where) {
|
|
338
|
+
const result = await this.db.deleteFrom(this.tableName).where(where).execute();
|
|
339
|
+
return Number(result[0]?.numDeletedRows ?? 0);
|
|
340
|
+
}
|
|
341
|
+
async deleteById(id) {
|
|
342
|
+
const result = await this.db.deleteFrom(this.tableName).where("id", "=", id).executeTakeFirst();
|
|
343
|
+
return Number(result?.numDeletedRows ?? 0) > 0;
|
|
344
|
+
}
|
|
345
|
+
async count(where) {
|
|
346
|
+
let query = this.db.selectFrom(this.tableName);
|
|
347
|
+
query = query.select((qb) => qb.fn.countAll().as("count"));
|
|
348
|
+
if (where) {
|
|
349
|
+
query = query.where(where);
|
|
350
|
+
}
|
|
351
|
+
const row = await query.executeTakeFirst();
|
|
352
|
+
return Number(row?.count ?? 0);
|
|
353
|
+
}
|
|
354
|
+
async transaction(fn) {
|
|
355
|
+
return this.db.transaction(async (trx) => {
|
|
356
|
+
const txRepo = Object.create(this);
|
|
357
|
+
Object.defineProperty(txRepo, "db", { value: { ...this.db, selectFrom: trx.selectFrom, insertInto: trx.insertInto, updateTable: trx.updateTable, deleteFrom: trx.deleteFrom }, writable: false });
|
|
358
|
+
Object.defineProperty(txRepo, "qb", {
|
|
359
|
+
get() {
|
|
360
|
+
return trx.selectFrom(this.tableName);
|
|
361
|
+
},
|
|
362
|
+
enumerable: true,
|
|
363
|
+
configurable: true
|
|
364
|
+
});
|
|
365
|
+
return fn(txRepo);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// packages/kysely/src/raw-query.ts
|
|
370
|
+
class RawQuery {
|
|
371
|
+
text;
|
|
372
|
+
params;
|
|
373
|
+
executor;
|
|
374
|
+
logger;
|
|
375
|
+
constructor(text, params, executor, logger) {
|
|
376
|
+
this.text = text;
|
|
377
|
+
this.params = params;
|
|
378
|
+
this.executor = executor;
|
|
379
|
+
this.logger = logger;
|
|
380
|
+
}
|
|
381
|
+
async all() {
|
|
382
|
+
this.logger?.(this.text, this.params);
|
|
383
|
+
const result = await this.executor.query(this.text, this.params);
|
|
384
|
+
return result.rows;
|
|
385
|
+
}
|
|
386
|
+
async first() {
|
|
387
|
+
const rows = await this.all();
|
|
388
|
+
return rows[0];
|
|
389
|
+
}
|
|
390
|
+
async execute() {
|
|
391
|
+
this.logger?.(this.text, this.params);
|
|
392
|
+
return this.executor.query(this.text, this.params);
|
|
393
|
+
}
|
|
394
|
+
toSQL() {
|
|
395
|
+
return this.text;
|
|
396
|
+
}
|
|
397
|
+
getParameters() {
|
|
398
|
+
return [...this.params];
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
// packages/kysely/src/bun-sqlite-dialect.ts
|
|
402
|
+
class BunSqliteDialect {
|
|
403
|
+
static wrap(db) {
|
|
404
|
+
const proto = Object.getPrototypeOf(db);
|
|
405
|
+
const origPrepare = proto.prepare.bind(db);
|
|
406
|
+
db.prepare = function(sql) {
|
|
407
|
+
const stmt = origPrepare(sql);
|
|
408
|
+
Object.defineProperty(stmt, "reader", {
|
|
409
|
+
value: /^\s*(?:select|pragma|with|explain)\b/i.test(sql),
|
|
410
|
+
writable: false
|
|
411
|
+
});
|
|
412
|
+
return stmt;
|
|
413
|
+
};
|
|
414
|
+
return db;
|
|
415
|
+
}
|
|
416
|
+
static inMemory() {
|
|
417
|
+
const { Database } = requireBunSqlite();
|
|
418
|
+
return BunSqliteDialect.wrap(new Database(":memory:"));
|
|
419
|
+
}
|
|
420
|
+
static file(filename) {
|
|
421
|
+
const { Database } = requireBunSqlite();
|
|
422
|
+
return BunSqliteDialect.wrap(new Database(filename));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
var _mod = null;
|
|
426
|
+
function requireBunSqlite() {
|
|
427
|
+
if (_mod)
|
|
428
|
+
return _mod;
|
|
429
|
+
try {
|
|
430
|
+
_mod = __require("bun:sqlite");
|
|
431
|
+
return _mod;
|
|
432
|
+
} catch {
|
|
433
|
+
throw new Error("[@nexusts/kysely] `bun:sqlite` is only available in Bun. " + "This dialect requires the Bun runtime.");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
export {
|
|
437
|
+
RawQuery,
|
|
438
|
+
KyselyService,
|
|
439
|
+
KyselyRepository,
|
|
440
|
+
KyselyModule,
|
|
441
|
+
BunSqliteDialect
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
//# debugId=632F65564441275864756E2164756E21
|
|
445
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/kysely.service.ts", "../src/kysely.module.ts", "../src/repository/repository.ts", "../src/raw-query.ts", "../src/bun-sqlite-dialect.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * `KyselyService` — typed SQL query builder service.\n *\n * Wraps a Kysely instance with:\n * - `selectFrom()`, `insertInto()`, `updateTable()`, `deleteFrom()` — passthroughs\n * - `transaction(fn)` — ACID transaction support via Kysely\n * - `sql\\`SELECT ...\\`` — Kysely's raw SQL template tag\n * - `schema` — Kysely schema builder for DDL\n * - `migrate()` — run schema migrations via Kysely Migrator\n * - `close()` — release the connection\n *\n * Usage:\n * import { SqliteDialect } from \"kysely\";\n * import Database from \"better-sqlite3\";\n *\n * interface DB {\n * users: { id: Generated<number>; email: string; name: string };\n * }\n *\n * const db = new KyselyService<DB>({\n * dialect: new SqliteDialect({ database: new Database(\":memory:\") }),\n * });\n *\n * const rows = await db.selectFrom(\"users\")\n * .where(\"email\", \"=\", \"a@b.com\")\n * .selectAll()\n * .execute();\n */\nimport type { KyselyConfig, Kysely, Transaction } from \"kysely\";\nimport { Injectable } from \"@nexusts/core\";\nimport type { KyselyServiceOptions, MigrateResult, DatabaseSchema } from \"./types.js\";\n\n@Injectable()\nexport class KyselyService<DB extends DatabaseSchema = any> {\n /** DI token. */\n static readonly TOKEN = Symbol.for(\"nexus:KyselyService\");\n\n /** The underlying Kysely instance. */\n private _db: Kysely<DB> | null = null;\n private _config: KyselyConfig;\n private _options: KyselyServiceOptions;\n private _opened = false;\n private _logger: ((query: string, params: unknown[]) => void) | null = null;\n\n constructor(\n config: KyselyConfig,\n options?: KyselyServiceOptions,\n ) {\n this._config = config;\n this._options = options ?? {};\n\n if (options?.logging) {\n const log = options.logging;\n this._logger = typeof log === \"function\" ? log : (q, p) => {\n const trimmed = q.replace(/\\s+/g, \" \").trim();\n if (p.length === 0) console.log(`[kysely] ${trimmed}`);\n else console.log(`[kysely] ${trimmed} -- params: ${JSON.stringify(p)}`);\n };\n }\n\n // Auto-open synchronously when Kysely is already available (e.g.\n // from an in-memory or bun:sqlite dialect). The dynamic import\n // will succeed instantly if the package is in node_modules.\n this._autoOpenSync();\n }\n\n /** Try to open synchronously — useful for bun:sqlite dialects. */\n private _autoOpenSync(): void {\n try {\n // We need to dynamically require \"kysely\" here. We use require\n // (not import) because we're in a synchronous context.\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require(\"kysely\");\n if (!mod?.Kysely) return;\n const { Kysely } = mod;\n\n const mergedConfig: any = { ...this._config };\n if (this._logger) {\n mergedConfig.log = (event: any) => {\n if (event.level === \"query\" && event.query) {\n this._logger!(event.query.sql, event.query.parameters as unknown[]);\n }\n };\n }\n\n this._db = new Kysely<DB>(mergedConfig);\n this._opened = true;\n } catch {\n // If require fails (e.g. kysely is not installed yet, or the\n // module is ESM-only), fall through to lazy async open().\n }\n }\n\n /** Lazy-initialize the Kysely instance. */\n async open(): Promise<void> {\n if (this._opened) return;\n\n // Dynamically import Kysely — it's an optional peer dep.\n const { Kysely } = await loadKysely();\n\n // Build config with optional logging via Kysely's built-in log option.\n const mergedConfig: any = { ...this._config };\n if (this._logger) {\n mergedConfig.log = (event: any) => {\n if (event.level === \"query\" && event.query) {\n this._logger!(event.query.sql, event.query.parameters as unknown[]);\n }\n };\n }\n\n this._db = new Kysely<DB>(mergedConfig);\n this._opened = true;\n\n // Auto-migrate if configured.\n if (this._options.migrations?.autoMigrate) {\n await this.migrate();\n }\n }\n\n /**\n * The underlying Kysely instance. Use this for direct Kysely API access.\n * Opens lazily on first access if not already opened.\n */\n async getDb(): Promise<Kysely<DB>> {\n if (!this._opened) await this.open();\n return this._db!;\n }\n\n /**\n * Synchronous access to Kysely — throws if not opened.\n * Used internally when we know open() has been called.\n */\n private get db(): Kysely<DB> {\n if (!this._db) {\n throw new Error(\"[kysely] service not opened. Call open() or await getDb() first.\");\n }\n return this._db;\n }\n\n // ===========================================================================\n // Query API (passthrough to Kysely)\n // ===========================================================================\n\n /**\n * Start a SELECT query for the given table.\n *\n * const users = await db.selectFrom(\"users\")\n * .where(\"id\", \"=\", 42)\n * .selectAll()\n * .execute();\n */\n selectFrom<TB extends keyof DB & string>(table: TB) {\n this.ensureOpen();\n return this.db.selectFrom(table);\n }\n\n /**\n * Start an INSERT INTO query.\n *\n * await db.insertInto(\"users\")\n * .values({ email: \"a@b.com\", name: \"Alice\" })\n * .execute();\n */\n insertInto<TB extends keyof DB & string>(table: TB) {\n this.ensureOpen();\n return this.db.insertInto(table);\n }\n\n /**\n * Start an UPDATE query for the given table.\n *\n * await db.updateTable(\"users\")\n * .set({ name: \"Bob\" })\n * .where(\"id\", \"=\", 42)\n * .execute();\n */\n updateTable<TB extends keyof DB & string>(table: TB) {\n this.ensureOpen();\n return this.db.updateTable(table);\n }\n\n /**\n * Start a DELETE FROM query.\n *\n * await db.deleteFrom(\"users\")\n * .where(\"id\", \"=\", 42)\n * .execute();\n */\n deleteFrom<TB extends keyof DB & string>(table: TB) {\n this.ensureOpen();\n return this.db.deleteFrom(table);\n }\n\n // ===========================================================================\n // Schema API\n // ===========================================================================\n\n /**\n * Access Kysely's schema builder for DDL operations.\n *\n * await db.schema\n * .createTable(\"users\")\n * .addColumn(\"id\", \"integer\", (col) => col.primaryKey().autoIncrement())\n * .addColumn(\"email\", \"varchar(255)\", (col) => col.notNull().unique())\n * .execute();\n */\n get schema() {\n this.ensureOpen();\n return this.db.schema;\n }\n\n // ===========================================================================\n // Raw SQL\n // ===========================================================================\n\n /**\n * Execute a raw SQL query via Kysely's sql template tag.\n *\n * const { rows } = await db.executeRaw(\n * sql\\`SELECT * FROM users WHERE email = ${email}\\`\n * );\n */\n async executeRaw<R = any>(query: any): Promise<R[]> {\n this.ensureOpen();\n const result = await query.execute(this.db);\n return result.rows as R[];\n }\n\n // ===========================================================================\n // Transactions\n // ===========================================================================\n\n /**\n * Run a callback inside a Kysely transaction.\n *\n * const result = await db.transaction(async (trx) => {\n * const user = await trx.insertInto(\"users\")\n * .values({ email: \"a@b.com\", name: \"Alice\" })\n * .returningAll()\n * .executeTakeFirst();\n * return user;\n * });\n */\n async transaction<T>(fn: (trx: KyselyTransaction<DB>) => Promise<T>): Promise<T> {\n this.ensureOpen();\n return this.db.transaction().execute(async (trx: Transaction<DB>) => {\n const txWrapper: KyselyTransaction<DB> = {\n selectFrom: (table) => trx.selectFrom(table),\n insertInto: (table) => trx.insertInto(table),\n updateTable: (table) => trx.updateTable(table),\n deleteFrom: (table) => trx.deleteFrom(table),\n executeRaw: async (query) => {\n const result = await query.execute(trx);\n return result.rows as any[];\n },\n };\n return fn(txWrapper);\n });\n }\n\n // ===========================================================================\n // Migrations\n // ===========================================================================\n\n /**\n * Run all pending migrations. Requires `migrations.provider` in config.\n *\n * const result = await db.migrate();\n * console.log(`Applied ${result.applied.length} migrations`);\n */\n async migrate(): Promise<MigrateResult> {\n if (!this._options.migrations?.provider) {\n throw new Error(\n \"[kysely] No migration provider configured. \" +\n \"Pass `migrations: { provider: new FileMigrationProvider(...) }` to KyselyModule.forRoot().\",\n );\n }\n\n this.ensureOpen();\n\n const { Migrator } = await importKysely();\n const migrator = new Migrator({\n db: this.db,\n provider: this._options.migrations.provider,\n ...(this._options.migrations.tableName ? { migrationTableName: this._options.migrations.tableName } : {}),\n });\n\n const { results, error } = await migrator.migrateToLatest();\n\n if (error) {\n throw error;\n }\n\n const applied = (results ?? [])\n .filter((r: any) => r.status === \"Success\" || r.status === \"MigratedAbove\")\n .map((r: any) => ({\n name: r.migrationName ?? String(r.name ?? \"\"),\n appliedAt: new Date(),\n }));\n\n const errors = (results ?? [])\n .filter((r: any) => r.status === \"Error\")\n .map((r: any) => ({\n name: r.migrationName ?? String(r.name ?? \"\"),\n error: r.error ?? new Error(\"Unknown migration error\"),\n }));\n\n return {\n applied,\n total: (results ?? []).length,\n errors,\n };\n }\n\n // ===========================================================================\n // Lifecycle\n // ===========================================================================\n\n /** Close the database connection. */\n async close(): Promise<void> {\n if (this._db) {\n await this._db.destroy();\n }\n this._db = null;\n this._opened = false;\n }\n\n // ===========================================================================\n // Internal\n // ===========================================================================\n\n private ensureOpen(): void {\n if (!this._db) {\n throw new Error(\"[kysely] service not opened. Call open() or await getDb() first.\");\n }\n }\n}\n\n/**\n * Transaction-scoped query builder.\n * Provides a subset of KyselyService methods within a transaction.\n */\nexport interface KyselyTransaction<DB extends DatabaseSchema = any> {\n selectFrom<TB extends keyof DB & string>(table: TB): ReturnType<Kysely<DB>[\"selectFrom\"]>;\n insertInto<TB extends keyof DB & string>(table: TB): ReturnType<Kysely<DB>[\"insertInto\"]>;\n updateTable<TB extends keyof DB & string>(table: TB): ReturnType<Kysely<DB>[\"updateTable\"]>;\n deleteFrom<TB extends keyof DB & string>(table: TB): ReturnType<Kysely<DB>[\"deleteFrom\"]>;\n executeRaw<R = any>(query: any): Promise<R[]>;\n}\n\n// ===========================================================================\n// Lazy imports (optional peer dependencies)\n// ===========================================================================\n\nlet _kyselyMod: any = null;\nlet _kyselyAttempted = false;\n\nasync function loadKysely(): Promise<{ Kysely: any }> {\n if (_kyselyMod) return _kyselyMod;\n if (_kyselyAttempted) {\n throw new Error(\n \"[@nexusts/kysely] `kysely` failed to load. Install with `bun add kysely`.\",\n );\n }\n _kyselyAttempted = true;\n try {\n const mod = await import(\"kysely\");\n _kyselyMod = { Kysely: mod.Kysely };\n return _kyselyMod;\n } catch (err) {\n throw new Error(\n \"[@nexusts/kysely] `kysely` is required. Install with `bun add kysely`.\\n\" +\n \"Original error: \" + (err as Error).message,\n );\n }\n}\n\nlet _kyselyFullMod: any = null;\nasync function importKysely(): Promise<any> {\n if (_kyselyFullMod) return _kyselyFullMod;\n try {\n _kyselyFullMod = await import(\"kysely\");\n return _kyselyFullMod;\n } catch (err) {\n throw new Error(\n \"[@nexusts/kysely] `kysely` is required. Install with `bun add kysely`.\\n\" +\n \"Original error: \" + (err as Error).message,\n );\n }\n}\n",
|
|
6
|
+
"/**\n * `KyselyModule` — typed SQL query builder integration.\n *\n * @example\n * ```ts\n * import { Module } from \"@nexusts/core\";\n * import { KyselyModule, KyselyService } from \"@nexusts/kysely\";\n * import { SqliteDialect } from \"kysely\";\n * import Database from \"better-sqlite3\";\n *\n * @Module({\n * imports: [\n * KyselyModule.forRoot({\n * config: { dialect: new SqliteDialect({ database: new Database(\"app.db\") }) },\n * logging: true,\n * }),\n * ],\n * })\n * class AppModule {}\n * ```\n *\n * Then inject into any service:\n *\n * @Injectable()\n * class UserService {\n * @Inject(KyselyService.TOKEN) declare db: KyselyService<MyDB>;\n *\n * async findAll() {\n * return this.db.selectFrom(\"users\").selectAll().execute();\n * }\n * }\n */\nimport { Module } from \"@nexusts/core\";\nimport { KyselyService } from \"./kysely.service.js\";\nimport type { KyselyModuleConfig } from \"./types.js\";\n\nexport class KyselyModule {\n /**\n * Register Kysely with configuration.\n *\n * @param opts - Module configuration (KyselyConfig + migrations + logging)\n * @returns A dynamic module class to be listed in `@Module({ imports: [...] })`\n */\n static forRoot(opts: KyselyModuleConfig): any {\n @Module({\n providers: [\n {\n provide: KyselyService.TOKEN,\n useFactory: () => new KyselyService(opts.config, {\n migrations: opts.migrations,\n logging: opts.logging,\n }),\n },\n { provide: KyselyService, useExisting: KyselyService.TOKEN },\n { provide: \"KYSELY_CONFIG\", useValue: opts.config },\n { provide: \"KYSELY_OPTIONS\", useValue: { migrations: opts.migrations, logging: opts.logging } },\n ],\n exports: [KyselyService.TOKEN, KyselyService, \"KYSELY_CONFIG\", \"KYSELY_OPTIONS\"],\n })\n class ConfiguredKyselyModule {}\n\n Object.defineProperty(ConfiguredKyselyModule, \"name\", { value: \"ConfiguredKyselyModule\" });\n return ConfiguredKyselyModule;\n }\n\n /**\n * Async variant using `useFactory` with dynamic import.\n * Useful when the dialect requires async initialization (e.g. PostgreSQL pool).\n */\n static forRootAsync(opts: {\n imports?: any[];\n useFactory: (...args: any[]) => KyselyModuleConfig | Promise<KyselyModuleConfig>;\n inject?: any[];\n }): any {\n @Module({\n imports: opts.imports ?? [],\n providers: [\n {\n provide: \"KYSELY_ASYNC_CONFIG\",\n useFactory: opts.useFactory,\n inject: opts.inject ?? [],\n },\n {\n provide: KyselyService.TOKEN,\n useFactory: async (...args: any[]) => {\n const resolvedConfig = args[args.length - 1] as KyselyModuleConfig;\n return new KyselyService(resolvedConfig.config, {\n migrations: resolvedConfig.migrations,\n logging: resolvedConfig.logging,\n });\n },\n inject: [...(opts.inject ?? []), \"KYSELY_ASYNC_CONFIG\"],\n },\n { provide: KyselyService, useExisting: KyselyService.TOKEN },\n ],\n exports: [KyselyService.TOKEN, KyselyService],\n })\n class ConfiguredKyselyModuleAsync {}\n\n Object.defineProperty(ConfiguredKyselyModuleAsync, \"name\", { value: \"ConfiguredKyselyModuleAsync\" });\n return ConfiguredKyselyModuleAsync;\n }\n}\n",
|
|
7
|
+
"/**\n * `KyselyRepository` — Lucid-style repository pattern for Kysely.\n *\n * Subclass it with your DB schema type to get typed CRUD operations.\n * Works with Kysely's type-safe query builder.\n *\n * @example\n * ```ts\n * interface DB {\n * users: {\n * id: Generated<number>;\n * email: string;\n * name: string;\n * };\n * }\n *\n * @Injectable()\n * class UserRepository extends KyselyRepository<DB, \"users\"> {\n * @Inject(KyselyService.TOKEN) declare db: KyselyService<DB>;\n * protected readonly tableName = \"users\";\n * }\n * ```\n */\nimport type { KyselyService } from \"../kysely.service.js\";\nimport type { DatabaseSchema } from \"../types.js\";\n\nexport type WhereCallback = (qb: any) => any;\n\nexport interface FindAllOptions {\n where?: WhereCallback;\n limit?: number;\n offset?: number;\n orderBy?: any | any[];\n}\n\nexport class KyselyRepository<\n DB extends DatabaseSchema = any,\n TB extends keyof DB & string = string,\n> {\n /**\n * Kysely service instance. Subclasses must inject this via `@Inject`.\n */\n protected readonly db!: KyselyService<DB>;\n\n /**\n * Table name for this repository. Subclasses must set this.\n */\n protected readonly tableName!: TB;\n\n constructor(db?: KyselyService<DB>, tableName?: TB) {\n if (db !== undefined) (this as any).db = db;\n if (tableName !== undefined) (this as any).tableName = tableName;\n }\n\n /** Kysely select query builder for this table. */\n protected get qb() {\n return this.db.selectFrom(this.tableName);\n }\n\n /** Returns all rows matching the given options. */\n async findAll(opts: FindAllOptions = {}): Promise<DB[TB][]> {\n let query = this.qb.selectAll();\n\n if (opts.where) {\n query = query.where(opts.where) as any;\n }\n if (opts.orderBy) {\n const arr = Array.isArray(opts.orderBy) ? opts.orderBy : [opts.orderBy];\n query = query.orderBy(arr) as any;\n }\n if (opts.limit !== undefined) {\n query = query.limit(opts.limit) as any;\n }\n if (opts.offset !== undefined) {\n query = query.offset(opts.offset) as any;\n }\n\n return query.execute() as Promise<DB[TB][]>;\n }\n\n /** Returns the first row matching the where callback. */\n async findOne(where: WhereCallback): Promise<DB[TB] | undefined> {\n const rows = await this.findAll({ where, limit: 1 });\n return rows[0];\n }\n\n /** Find by primary key (assumes `id` column). */\n async findById(id: number | string): Promise<DB[TB] | undefined> {\n const rows = await this.qb.selectAll()\n .where(\"id\" as any, \"=\", id)\n .limit(1)\n .execute();\n return rows[0] as DB[TB] | undefined;\n }\n\n /** Insert a row and return it (requires RETURNING support). */\n async create(values: Partial<DB[TB]>): Promise<DB[TB] | undefined> {\n const rows = await this.db\n .insertInto(this.tableName)\n .values(values as any)\n .returningAll()\n .execute();\n return rows[0] as DB[TB] | undefined;\n }\n\n /** Insert multiple rows and return them. */\n async createMany(values: Array<Partial<DB[TB]>>): Promise<DB[TB][] | undefined> {\n if (values.length === 0) return [];\n const rows = await this.db\n .insertInto(this.tableName)\n .values(values as any)\n .returningAll()\n .execute();\n return rows as DB[TB][];\n }\n\n /** Update rows matching the where callback. */\n async update(where: WhereCallback, patch: Partial<DB[TB]>): Promise<DB[TB][]> {\n const rows = await this.db\n .updateTable(this.tableName)\n .set(patch as any)\n .where(where)\n .returningAll()\n .execute();\n return rows as DB[TB][];\n }\n\n /** Update by primary key (assumes `id` column). */\n async updateById(id: number | string, patch: Partial<DB[TB]>): Promise<DB[TB] | undefined> {\n const rows = await this.db\n .updateTable(this.tableName)\n .set(patch as any)\n .where(\"id\" as any, \"=\", id)\n .returningAll()\n .execute();\n return rows[0] as DB[TB] | undefined;\n }\n\n /** Delete rows matching the where callback. */\n async delete(where: WhereCallback): Promise<number> {\n const result = await this.db\n .deleteFrom(this.tableName)\n .where(where)\n .execute();\n return Number(result[0]?.numDeletedRows ?? 0);\n }\n\n /** Delete by primary key (assumes `id` column). */\n async deleteById(id: number | string): Promise<boolean> {\n const result = await this.db\n .deleteFrom(this.tableName)\n .where(\"id\" as any, \"=\", id)\n .executeTakeFirst();\n return Number((result as any)?.numDeletedRows ?? 0) > 0;\n }\n\n /** Count all rows (or matching the where callback). */\n async count(where?: WhereCallback): Promise<number> {\n let query = this.db.selectFrom(this.tableName) as any;\n query = query.select((qb: any) => qb.fn.countAll<number>().as(\"count\"));\n if (where) {\n query = query.where(where);\n }\n const row = await query.executeTakeFirst();\n return Number((row as any)?.count ?? 0);\n }\n\n /** Run a callback inside a transaction. */\n async transaction<T>(\n fn: (tx: KyselyRepository<DB, TB>) => Promise<T>,\n ): Promise<T> {\n return this.db.transaction(async (trx) => {\n const txRepo = Object.create(this) as KyselyRepository<DB, TB>;\n Object.defineProperty(txRepo, \"db\", { value: { ...this.db, selectFrom: trx.selectFrom, insertInto: trx.insertInto, updateTable: trx.updateTable, deleteFrom: trx.deleteFrom }, writable: false });\n // Override the qb getter to use the transaction\n Object.defineProperty(txRepo, \"qb\", {\n get() {\n return (trx as any).selectFrom(this.tableName);\n },\n enumerable: true,\n configurable: true,\n });\n return fn(txRepo);\n });\n }\n}\n",
|
|
8
|
+
"/**\n * `RawQuery` — parameterized raw SQL execution.\n *\n * Returned by `KyselyService.raw()` (not yet exposed on the service,\n * but available as a utility) and used internally by the repository\n * for COUNT queries.\n *\n * @example\n * ```ts\n * const rq = new RawQuery(\"SELECT * FROM users WHERE id = ?\", [42], executor);\n * const rows = await rq.all();\n * const first = await rq.first();\n * ```\n */\nimport type { RawQueryResult } from \"./types.js\";\n\nexport interface RawExecutor {\n query: (sql: string, params: unknown[]) => Promise<RawQueryResult>;\n placeholder: (index: number) => string;\n}\n\nexport class RawQuery<T = Record<string, unknown>> {\n readonly text: string;\n readonly params: unknown[];\n private readonly executor: RawExecutor;\n private readonly logger?: (sql: string, params: unknown[]) => void;\n\n constructor(\n text: string,\n params: unknown[],\n executor: RawExecutor,\n logger?: (sql: string, params: unknown[]) => void,\n ) {\n this.text = text;\n this.params = params;\n this.executor = executor;\n this.logger = logger;\n }\n\n /** Execute and return all rows. */\n async all<R = T>(): Promise<R[]> {\n this.logger?.(this.text, this.params);\n const result = await this.executor.query(this.text, this.params);\n return result.rows as R[];\n }\n\n /** Execute and return the first row, or undefined. */\n async first<R = T>(): Promise<R | undefined> {\n const rows = await this.all<R>();\n return rows[0];\n }\n\n /** Execute (for INSERT/UPDATE/DELETE) and return the result metadata. */\n async execute<R = T>(): Promise<RawQueryResult<R>> {\n this.logger?.(this.text, this.params);\n return this.executor.query(this.text, this.params) as Promise<RawQueryResult<R>>;\n }\n\n /** Return the SQL text with `?` placeholders. */\n toSQL(): string {\n return this.text;\n }\n\n /** Return the parameter values. */\n getParameters(): unknown[] {\n return [...this.params];\n }\n}\n",
|
|
9
|
+
"/**\n * `BunSqliteDialect` — a Kysely dialect for Bun's built-in `bun:sqlite`.\n *\n * Kysely's built-in `SqliteDialect` requires `better-sqlite3`, which\n * does not work in Bun. This lightweight wrapper patches the `.reader`\n * property onto prepared statements, so Kysely's `SqliteDialect` can\n * distinguish SELECT queries from INSERT/UPDATE/DELETE.\n *\n * @example\n * ```ts\n * import { Kysely, SqliteDialect } from \"kysely\";\n * import { Database } from \"bun:sqlite\";\n * import { BunSqliteDialect } from \"@nexusts/kysely\";\n *\n * const db = new Kysely({\n * dialect: new SqliteDialect({\n * database: BunSqliteDialect.wrap(new Database(\"app.db\")),\n * }),\n * });\n * ```\n */\nexport class BunSqliteDialect {\n /**\n * Wrap a Bun SQLite `Database` instance so it works with Kysely's\n * `SqliteDialect`.\n *\n * The returned object has the same interface as a\n * `better-sqlite3.Database` — Kysely's SqliteDriver checks\n * `stmt.reader` to decide whether to call `stmt.all()` (SELECT) or\n * `stmt.run()` (INSERT/UPDATE/DELETE). Bun's `bun:sqlite` doesn't\n * expose this property, so we inject it by analyzing the SQL text.\n *\n * @param db - A `bun:sqlite` `Database` instance\n * @returns A wrapped database compatible with `SqliteDialect`\n */\n static wrap(db: any): any {\n const proto = Object.getPrototypeOf(db);\n const origPrepare = proto.prepare.bind(db);\n\n // Override `prepare` on the instance so each Statement gets a\n // synthetic `.reader` property matching Kysely's expectations.\n db.prepare = function (this: any, sql: string) {\n const stmt = origPrepare(sql);\n Object.defineProperty(stmt, \"reader\", {\n value: /^\\s*(?:select|pragma|with|explain)\\b/i.test(sql),\n writable: false,\n });\n return stmt;\n };\n\n return db;\n }\n\n /**\n * Create a new in-memory Bun SQLite database, pre-wrapped for Kysely.\n *\n * @returns A wrapped `Database(\":memory:\")` instance\n */\n static inMemory(): any {\n const { Database } = requireBunSqlite();\n return BunSqliteDialect.wrap(new Database(\":memory:\"));\n }\n\n /**\n * Create a new file-based Bun SQLite database, pre-wrapped for Kysely.\n *\n * @param filename - Path to the SQLite database file\n * @returns A wrapped `Database(filename)` instance\n */\n static file(filename: string): any {\n const { Database } = requireBunSqlite();\n return BunSqliteDialect.wrap(new Database(filename));\n }\n}\n\nlet _mod: any = null;\nfunction requireBunSqlite(): { Database: any } {\n if (_mod) return _mod;\n try {\n _mod = require(\"bun:sqlite\");\n return _mod;\n } catch {\n throw new Error(\n \"[@nexusts/kysely] `bun:sqlite` is only available in Bun. \" +\n \"This dialect requires the Bun runtime.\",\n );\n }\n}\n"
|
|
10
|
+
],
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "632F65564441275864756E2164756E21",
|
|
13
|
+
"names": []
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { KyselyModuleConfig } from "./types.js";
|
|
2
|
+
export declare class KyselyModule {
|
|
3
|
+
/**
|
|
4
|
+
* Register Kysely with configuration.
|
|
5
|
+
*
|
|
6
|
+
* @param opts - Module configuration (KyselyConfig + migrations + logging)
|
|
7
|
+
* @returns A dynamic module class to be listed in `@Module({ imports: [...] })`
|
|
8
|
+
*/
|
|
9
|
+
static forRoot(opts: KyselyModuleConfig): any;
|
|
10
|
+
/**
|
|
11
|
+
* Async variant using `useFactory` with dynamic import.
|
|
12
|
+
* Useful when the dialect requires async initialization (e.g. PostgreSQL pool).
|
|
13
|
+
*/
|
|
14
|
+
static forRootAsync(opts: {
|
|
15
|
+
imports?: any[];
|
|
16
|
+
useFactory: (...args: any[]) => KyselyModuleConfig | Promise<KyselyModuleConfig>;
|
|
17
|
+
inject?: any[];
|
|
18
|
+
}): any;
|
|
19
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RawQuery` — parameterized raw SQL execution.
|
|
3
|
+
*
|
|
4
|
+
* Returned by `KyselyService.raw()` (not yet exposed on the service,
|
|
5
|
+
* but available as a utility) and used internally by the repository
|
|
6
|
+
* for COUNT queries.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const rq = new RawQuery("SELECT * FROM users WHERE id = ?", [42], executor);
|
|
11
|
+
* const rows = await rq.all();
|
|
12
|
+
* const first = await rq.first();
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
import type { RawQueryResult } from "./types.js";
|
|
16
|
+
export interface RawExecutor {
|
|
17
|
+
query: (sql: string, params: unknown[]) => Promise<RawQueryResult>;
|
|
18
|
+
placeholder: (index: number) => string;
|
|
19
|
+
}
|
|
20
|
+
export declare class RawQuery<T = Record<string, unknown>> {
|
|
21
|
+
readonly text: string;
|
|
22
|
+
readonly params: unknown[];
|
|
23
|
+
private readonly executor;
|
|
24
|
+
private readonly logger?;
|
|
25
|
+
constructor(text: string, params: unknown[], executor: RawExecutor, logger?: (sql: string, params: unknown[]) => void);
|
|
26
|
+
/** Execute and return all rows. */
|
|
27
|
+
all<R = T>(): Promise<R[]>;
|
|
28
|
+
/** Execute and return the first row, or undefined. */
|
|
29
|
+
first<R = T>(): Promise<R | undefined>;
|
|
30
|
+
/** Execute (for INSERT/UPDATE/DELETE) and return the result metadata. */
|
|
31
|
+
execute<R = T>(): Promise<RawQueryResult<R>>;
|
|
32
|
+
/** Return the SQL text with `?` placeholders. */
|
|
33
|
+
toSQL(): string;
|
|
34
|
+
/** Return the parameter values. */
|
|
35
|
+
getParameters(): unknown[];
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KyselyRepository } from "./repository.js";
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for `@nexusts/kysely` — typed SQL query builder integration.
|
|
3
|
+
*/
|
|
4
|
+
import type { KyselyConfig, MigrationProvider } from "kysely";
|
|
5
|
+
/**
|
|
6
|
+
* Kysely database schema type — maps table names to their row types.
|
|
7
|
+
* Users define this interface and pass it as a generic parameter.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* interface DB {
|
|
12
|
+
* users: {
|
|
13
|
+
* id: Generated<number>;
|
|
14
|
+
* email: string;
|
|
15
|
+
* name: string;
|
|
16
|
+
* created_at: Generated<string>;
|
|
17
|
+
* };
|
|
18
|
+
* posts: {
|
|
19
|
+
* id: Generated<number>;
|
|
20
|
+
* title: string;
|
|
21
|
+
* user_id: number;
|
|
22
|
+
* };
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* const db = new KyselyService<DB>({ dialect: new SqliteDialect({...}) });
|
|
26
|
+
* const user = await db.selectFrom('users')
|
|
27
|
+
* .where('id', '=', 42)
|
|
28
|
+
* .selectAll()
|
|
29
|
+
* .executeTakeFirst();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export type DatabaseSchema = Record<string, any>;
|
|
33
|
+
export interface KyselyMigrationsConfig {
|
|
34
|
+
/** Migration provider (e.g. FileMigrationProvider). */
|
|
35
|
+
provider: MigrationProvider;
|
|
36
|
+
/** Table name for the migrations tracking table (default: 'kysely_migration'). */
|
|
37
|
+
tableName?: string;
|
|
38
|
+
/** Whether to auto-run migrations on boot. */
|
|
39
|
+
autoMigrate?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface KyselyModuleConfig {
|
|
42
|
+
/** Kysely configuration (dialect + pool). */
|
|
43
|
+
config: KyselyConfig;
|
|
44
|
+
/** Optional migration configuration. */
|
|
45
|
+
migrations?: KyselyMigrationsConfig;
|
|
46
|
+
/** Enable query logging. */
|
|
47
|
+
logging?: boolean | ((query: string, params: unknown[]) => void);
|
|
48
|
+
}
|
|
49
|
+
export interface KyselyServiceOptions {
|
|
50
|
+
/** Optional migration configuration. */
|
|
51
|
+
migrations?: KyselyMigrationsConfig;
|
|
52
|
+
/** Enable query logging. */
|
|
53
|
+
logging?: boolean | ((query: string, params: unknown[]) => void);
|
|
54
|
+
}
|
|
55
|
+
export interface RawQueryResult<T = Record<string, unknown>> {
|
|
56
|
+
rows: T[];
|
|
57
|
+
/** Number of affected rows (UPDATE/DELETE/INSERT). */
|
|
58
|
+
affectedRows: number;
|
|
59
|
+
/** Insert ID (MySQL/SQLite/Postgres RETURNING). */
|
|
60
|
+
insertId?: number | string | bigint;
|
|
61
|
+
}
|
|
62
|
+
export interface MigrationRecord {
|
|
63
|
+
name: string;
|
|
64
|
+
/** Timestamp when this migration was applied. */
|
|
65
|
+
appliedAt: Date;
|
|
66
|
+
}
|
|
67
|
+
export interface MigrateResult {
|
|
68
|
+
/** Newly-applied migrations. */
|
|
69
|
+
applied: MigrationRecord[];
|
|
70
|
+
/** Total migrations run. */
|
|
71
|
+
total: number;
|
|
72
|
+
/** Any migration errors. */
|
|
73
|
+
errors: Array<{
|
|
74
|
+
name: string;
|
|
75
|
+
error: unknown;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
export type WhereExpression = any;
|
|
79
|
+
export type OrderByExpression = any;
|
|
80
|
+
export type ExpressionOrFactory = any;
|
|
81
|
+
export interface FindAllOptions {
|
|
82
|
+
where?: (qb: any) => any;
|
|
83
|
+
limit?: number;
|
|
84
|
+
offset?: number;
|
|
85
|
+
orderBy?: OrderByExpression | OrderByExpression[];
|
|
86
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nexusts/kysely",
|
|
3
|
+
"version": "0.9.5",
|
|
4
|
+
"description": "Kysely typed SQL query builder integration — first-party module",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun run ../../build.ts"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"nexusts",
|
|
24
|
+
"framework",
|
|
25
|
+
"bun",
|
|
26
|
+
"kysely",
|
|
27
|
+
"orm",
|
|
28
|
+
"sql",
|
|
29
|
+
"query-builder"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"kysely": "^0.27.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"kysely": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@nexusts/core": "^0.9.5"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/nexus-ts/nexusts.git",
|
|
46
|
+
"directory": "packages/kysely"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/nexus-ts/nexusts#readme",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/nexus-ts/nexusts/issues"
|
|
51
|
+
}
|
|
52
|
+
}
|