@petradb/knex 1.2.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/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @petradb/knex
2
+
3
+ Knex.js dialect for [PetraDB](https://petradb.dev) — use Knex's query builder, schema builder, and migrations with PetraDB's embeddable SQL engine.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @petradb/knex @petradb/engine knex
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import Knex from "knex";
15
+ import PetraDBClient from "@petradb/knex";
16
+
17
+ const knex = Knex({
18
+ client: PetraDBClient,
19
+ connection: { storage: "memory" },
20
+ useNullAsDefault: true,
21
+ });
22
+
23
+ // Schema
24
+ await knex.schema.createTable("users", (t) => {
25
+ t.increments("id");
26
+ t.string("name");
27
+ t.integer("age");
28
+ });
29
+
30
+ // Insert
31
+ await knex("users").insert({ name: "Alice", age: 30 });
32
+
33
+ // Query
34
+ const users = await knex("users").where("age", ">", 25);
35
+
36
+ // Clean up
37
+ await knex.destroy();
38
+ ```
39
+
40
+ ## Storage Modes
41
+
42
+ Configure via `connection`:
43
+
44
+ ```typescript
45
+ // In-memory (default)
46
+ { storage: "memory" }
47
+
48
+ // File-backed persistent storage
49
+ { storage: "persistent", path: "./mydb.petra" }
50
+ ```
51
+
52
+ ## Features
53
+
54
+ - Full Knex query builder support (select, insert, update, delete, joins, aggregates)
55
+ - Schema builder (createTable, dropTable, hasTable, hasColumn, alterTable)
56
+ - RETURNING clause support
57
+ - Transaction support (BEGIN/COMMIT/ROLLBACK)
58
+ - PostgreSQL-style `$1, $2, ...` parameter binding
59
+
60
+ ## Documentation
61
+
62
+ See [petradb.dev](https://petradb.dev) for full PetraDB documentation.
@@ -0,0 +1,78 @@
1
+ declare const ClientBase: any;
2
+ declare const QueryCompilerBase: any;
3
+ declare const SchemaCompilerBase: any;
4
+ declare const TableCompilerBase: any;
5
+ declare const ColumnCompilerBase: any;
6
+ declare class ColumnCompiler_PetraDB extends ColumnCompilerBase {
7
+ constructor(client: any, tableCompiler: any, columnBuilder: any);
8
+ increments(options?: any): string;
9
+ bigincrements(options?: any): string;
10
+ integer(): string;
11
+ text(): string;
12
+ tinyint(): string;
13
+ smallint(): string;
14
+ mediumint(): string;
15
+ bigint(): string;
16
+ varchar(length: number): string;
17
+ floating(): string;
18
+ double(): string;
19
+ decimal(precision: number | null, scale: number): string;
20
+ boolean(): string;
21
+ date(): string;
22
+ time(): string;
23
+ datetime(): string;
24
+ timestamp(): string;
25
+ uuid(options?: any): string;
26
+ json(): string;
27
+ jsonb(): string;
28
+ binary(): string;
29
+ enu(allowed: string[], options?: any): string;
30
+ }
31
+ declare class TableCompiler_PetraDB extends TableCompilerBase {
32
+ constructor(client: any, tableBuilder: any);
33
+ createQuery(columns: any, ifNot: boolean, like: any): void;
34
+ addColumns(columns: any, prefix: string, colCompilers: any): void;
35
+ primaryKeys(): string | undefined;
36
+ index(columns: any, indexName: any): void;
37
+ unique(columns: any, indexName: any): void;
38
+ dropIndex(columns: any, indexName: any): void;
39
+ dropUnique(columns: any, indexName: any): void;
40
+ dropForeign(columns: any, indexName: any): void;
41
+ }
42
+ declare class SchemaCompiler_PetraDB extends SchemaCompilerBase {
43
+ constructor(client: any, builder: any);
44
+ hasTable(tableName: string): void;
45
+ hasColumn(tableName: string, columnName: string): void;
46
+ renameTable(from: string, to: string): void;
47
+ }
48
+ declare class QueryCompiler_PetraDB extends QueryCompilerBase {
49
+ constructor(client: any, builder: any, formatter: any);
50
+ truncate(): string;
51
+ insert(): any;
52
+ update(): {
53
+ sql: string;
54
+ returning: any;
55
+ };
56
+ del(): {
57
+ sql: string;
58
+ returning: any;
59
+ };
60
+ _returning(value: any): string;
61
+ }
62
+ declare class PetraDBClient extends ClientBase {
63
+ constructor(config: any);
64
+ _driver(): any;
65
+ queryCompiler(builder: any, formatter: any): QueryCompiler_PetraDB;
66
+ schemaCompiler(): SchemaCompiler_PetraDB;
67
+ tableCompiler(): TableCompiler_PetraDB;
68
+ columnCompiler(): ColumnCompiler_PetraDB;
69
+ wrapIdentifierImpl(value: string): string;
70
+ acquireRawConnection(): Promise<any>;
71
+ destroyRawConnection(connection: any): Promise<void>;
72
+ validateConnection(connection: any): boolean;
73
+ positionBindings(sql: string): string;
74
+ _query(connection: any, obj: any): Promise<any>;
75
+ processResponse(obj: any, runner: any): any;
76
+ poolDefaults(): any;
77
+ }
78
+ export default PetraDBClient;
package/dist/index.js ADDED
@@ -0,0 +1,387 @@
1
+ // @ts-nocheck — Knex internals are untyped CJS; we extend them at runtime.
2
+ import { createRequire } from "node:module";
3
+ const _require = createRequire(import.meta.url);
4
+ const ClientBase = _require("knex/lib/client.js");
5
+ const QueryCompilerBase = _require("knex/lib/query/querycompiler.js");
6
+ const SchemaCompilerBase = _require("knex/lib/schema/compiler.js");
7
+ const TableCompilerBase = _require("knex/lib/schema/tablecompiler.js");
8
+ const ColumnCompilerBase = _require("knex/lib/schema/columncompiler.js");
9
+ // ---------------------------------------------------------------------------
10
+ // Column Compiler
11
+ // ---------------------------------------------------------------------------
12
+ class ColumnCompiler_PetraDB extends ColumnCompilerBase {
13
+ constructor(client, tableCompiler, columnBuilder) {
14
+ super(client, tableCompiler, columnBuilder);
15
+ this.modifiers = ["nullable", "defaultTo"];
16
+ }
17
+ increments(options = { primaryKey: true }) {
18
+ return ("serial" +
19
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : ""));
20
+ }
21
+ bigincrements(options = { primaryKey: true }) {
22
+ return ("bigserial" +
23
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : ""));
24
+ }
25
+ integer() {
26
+ return "integer";
27
+ }
28
+ text() {
29
+ return "text";
30
+ }
31
+ tinyint() {
32
+ return "smallint";
33
+ }
34
+ smallint() {
35
+ return "smallint";
36
+ }
37
+ mediumint() {
38
+ return "integer";
39
+ }
40
+ bigint() {
41
+ return "bigint";
42
+ }
43
+ varchar(length) {
44
+ return `varchar(${length || 255})`;
45
+ }
46
+ floating() {
47
+ return "double";
48
+ }
49
+ double() {
50
+ return "double";
51
+ }
52
+ decimal(precision, scale) {
53
+ if (precision === null)
54
+ return "numeric";
55
+ return `numeric(${precision ?? 8}, ${scale ?? 2})`;
56
+ }
57
+ boolean() {
58
+ return "boolean";
59
+ }
60
+ date() {
61
+ return "date";
62
+ }
63
+ time() {
64
+ return "time";
65
+ }
66
+ datetime() {
67
+ return "timestamp";
68
+ }
69
+ timestamp() {
70
+ return "timestamp";
71
+ }
72
+ uuid(options = { primaryKey: false }) {
73
+ return ("uuid" +
74
+ (this.tableCompiler._canBeAddPrimaryKey(options) ? " primary key" : ""));
75
+ }
76
+ json() {
77
+ return "json";
78
+ }
79
+ jsonb() {
80
+ return "jsonb";
81
+ }
82
+ binary() {
83
+ return "bytea";
84
+ }
85
+ enu(allowed, options = {}) {
86
+ if (options.useNative) {
87
+ const enumName = options.enumName
88
+ ? `"${options.enumName}"`
89
+ : `"${this.args[0]}_enum"`;
90
+ if (!options.existingType) {
91
+ const values = allowed.map((v) => `'${v}'`).join(", ");
92
+ this.tableCompiler.unshiftQuery(`create type ${enumName} as enum (${values})`);
93
+ }
94
+ return enumName;
95
+ }
96
+ const values = allowed.map((v) => `'${v}'`).join(", ");
97
+ return `text check (${this.formatter.wrap(this.args[0])} in (${values}))`;
98
+ }
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // Table Compiler
102
+ // ---------------------------------------------------------------------------
103
+ class TableCompiler_PetraDB extends TableCompilerBase {
104
+ constructor(client, tableBuilder) {
105
+ super(client, tableBuilder);
106
+ }
107
+ createQuery(columns, ifNot, like) {
108
+ const createStatement = ifNot
109
+ ? "create table if not exists "
110
+ : "create table ";
111
+ const columnsSql = ` (${columns.sql.join(", ")}${this.primaryKeys() || ""}${this._addChecks()})`;
112
+ const sql = createStatement +
113
+ this.tableName() +
114
+ (like && this.tableNameLike()
115
+ ? " (like " +
116
+ this.tableNameLike() +
117
+ " including all" +
118
+ (columns.sql.length ? ", " + columns.sql.join(", ") : "") +
119
+ ")"
120
+ : columnsSql);
121
+ this.pushQuery({
122
+ sql,
123
+ bindings: columns.bindings,
124
+ });
125
+ }
126
+ // PetraDB supports ALTER TABLE ADD COLUMN
127
+ addColumns(columns, prefix, colCompilers) {
128
+ if (prefix === this.alterColumnsPrefix) {
129
+ for (const col of colCompilers) {
130
+ const quotedTableName = this.tableName();
131
+ const type = col.getColumnType();
132
+ const colName = this.client.wrapIdentifier(col.getColumnName(), col.columnBuilder.queryContext());
133
+ this.pushQuery({
134
+ sql: `alter table ${quotedTableName} alter column ${colName} type ${type}`,
135
+ bindings: [],
136
+ });
137
+ }
138
+ }
139
+ else {
140
+ super.addColumns(columns, prefix);
141
+ }
142
+ }
143
+ primaryKeys() {
144
+ const pks = (this.grouped.alterTable || []).filter((k) => k.method === "primary");
145
+ if (pks.length > 0 && pks[0].args.length > 0) {
146
+ const columns = pks[0].args[0];
147
+ let constraintName = pks[0].args[1] || "";
148
+ if (typeof constraintName === "object") {
149
+ constraintName = constraintName.constraintName || "";
150
+ }
151
+ constraintName = constraintName
152
+ ? this.formatter.wrap(constraintName)
153
+ : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
154
+ return `, constraint ${constraintName} primary key (${this.formatter.columnize(columns)})`;
155
+ }
156
+ }
157
+ index(columns, indexName) {
158
+ indexName = indexName
159
+ ? this.formatter.wrap(indexName)
160
+ : this._indexCommand("index", this.tableNameRaw, columns);
161
+ this.pushQuery(`create index ${indexName} on ${this.tableName()} (${this.formatter.columnize(columns)})`);
162
+ }
163
+ unique(columns, indexName) {
164
+ indexName = indexName
165
+ ? this.formatter.wrap(indexName)
166
+ : this._indexCommand("unique", this.tableNameRaw, columns);
167
+ this.pushQuery(`alter table ${this.tableName()} add constraint ${indexName} unique (${this.formatter.columnize(columns)})`);
168
+ }
169
+ dropIndex(columns, indexName) {
170
+ indexName = indexName
171
+ ? this.formatter.wrap(indexName)
172
+ : this._indexCommand("index", this.tableNameRaw, columns);
173
+ this.pushQuery(`drop index ${indexName}`);
174
+ }
175
+ dropUnique(columns, indexName) {
176
+ indexName = indexName
177
+ ? this.formatter.wrap(indexName)
178
+ : this._indexCommand("unique", this.tableNameRaw, columns);
179
+ this.pushQuery(`alter table ${this.tableName()} drop constraint ${indexName}`);
180
+ }
181
+ dropForeign(columns, indexName) {
182
+ indexName = indexName
183
+ ? this.formatter.wrap(indexName)
184
+ : this._indexCommand("foreign", this.tableNameRaw, columns);
185
+ this.pushQuery(`alter table ${this.tableName()} drop constraint ${indexName}`);
186
+ }
187
+ }
188
+ // ---------------------------------------------------------------------------
189
+ // Schema Compiler
190
+ // ---------------------------------------------------------------------------
191
+ class SchemaCompiler_PetraDB extends SchemaCompilerBase {
192
+ constructor(client, builder) {
193
+ super(client, builder);
194
+ }
195
+ hasTable(tableName) {
196
+ this.pushQuery({
197
+ sql: "SHOW TABLES",
198
+ output(resp) {
199
+ const rows = resp.rows || resp;
200
+ return rows.some((r) => (r.table_name || r.TABLE_NAME || "").toLowerCase() ===
201
+ tableName.toLowerCase());
202
+ },
203
+ });
204
+ }
205
+ hasColumn(tableName, columnName) {
206
+ const wrapped = this.formatter.wrap(tableName);
207
+ this.pushQuery({
208
+ sql: `SHOW COLUMNS FROM ${wrapped}`,
209
+ output(resp) {
210
+ const rows = resp.rows || resp;
211
+ return rows.some((r) => (r.name || r.column_name || r.NAME || "").toLowerCase() ===
212
+ columnName.toLowerCase());
213
+ },
214
+ });
215
+ }
216
+ renameTable(from, to) {
217
+ this.pushQuery(`alter table ${this.formatter.wrap(from)} rename to ${this.formatter.wrap(to)}`);
218
+ }
219
+ }
220
+ // ---------------------------------------------------------------------------
221
+ // Query Compiler
222
+ // ---------------------------------------------------------------------------
223
+ class QueryCompiler_PetraDB extends QueryCompilerBase {
224
+ constructor(client, builder, formatter) {
225
+ super(client, builder, formatter);
226
+ this._defaultInsertValue = "default";
227
+ }
228
+ truncate() {
229
+ return `truncate table ${this.tableName}`;
230
+ }
231
+ insert() {
232
+ let sql = super.insert();
233
+ if (sql === "")
234
+ return sql;
235
+ const { returning } = this.single;
236
+ if (returning)
237
+ sql += this._returning(returning);
238
+ return { sql, returning };
239
+ }
240
+ update() {
241
+ const withSQL = this.with();
242
+ const updateData = this._prepUpdate(this.single.update);
243
+ const wheres = this.where();
244
+ const { returning } = this.single;
245
+ return {
246
+ sql: withSQL +
247
+ `update ${this.tableName} set ${updateData.join(", ")}` +
248
+ (wheres ? ` ${wheres}` : "") +
249
+ this._returning(returning),
250
+ returning,
251
+ };
252
+ }
253
+ del() {
254
+ const { tableName } = this;
255
+ const withSQL = this.with();
256
+ const wheres = this.where() || "";
257
+ const { returning } = this.single;
258
+ return {
259
+ sql: withSQL +
260
+ `delete from ${tableName}` +
261
+ (wheres ? ` ${wheres}` : "") +
262
+ this._returning(returning),
263
+ returning,
264
+ };
265
+ }
266
+ _returning(value) {
267
+ return value ? ` returning ${this.formatter.columnize(value)}` : "";
268
+ }
269
+ }
270
+ // ---------------------------------------------------------------------------
271
+ // Client
272
+ // ---------------------------------------------------------------------------
273
+ class PetraDBClient extends ClientBase {
274
+ constructor(config) {
275
+ super({ ...config, client: "petradb" });
276
+ }
277
+ _driver() {
278
+ return _require("@petradb/engine");
279
+ }
280
+ queryCompiler(builder, formatter) {
281
+ return new QueryCompiler_PetraDB(this, builder, formatter);
282
+ }
283
+ schemaCompiler() {
284
+ return new SchemaCompiler_PetraDB(this, ...arguments);
285
+ }
286
+ tableCompiler() {
287
+ return new TableCompiler_PetraDB(this, ...arguments);
288
+ }
289
+ columnCompiler() {
290
+ return new ColumnCompiler_PetraDB(this, ...arguments);
291
+ }
292
+ wrapIdentifierImpl(value) {
293
+ if (value === "*")
294
+ return value;
295
+ return `"${value.replace(/"/g, '""')}"`;
296
+ }
297
+ async acquireRawConnection() {
298
+ const { Session } = this.driver;
299
+ const settings = this.connectionSettings || {};
300
+ return new Session({
301
+ storage: settings.storage || "memory",
302
+ ...(settings.path ? { path: settings.path } : {}),
303
+ ...(settings.pageSize ? { pageSize: settings.pageSize } : {}),
304
+ });
305
+ }
306
+ async destroyRawConnection(connection) {
307
+ connection.close();
308
+ }
309
+ validateConnection(connection) {
310
+ return true;
311
+ }
312
+ // Convert ? placeholders → $1, $2, ...
313
+ positionBindings(sql) {
314
+ let questionCount = 0;
315
+ return sql.replace(/(\\*)(\?)/g, function (_match, escapes) {
316
+ if (escapes.length % 2) {
317
+ return "?";
318
+ }
319
+ else {
320
+ questionCount++;
321
+ return `$${questionCount}`;
322
+ }
323
+ });
324
+ }
325
+ async _query(connection, obj) {
326
+ if (!obj.sql)
327
+ throw new Error("The query is empty");
328
+ const sql = obj.sql;
329
+ const bindings = obj.bindings || [];
330
+ let results;
331
+ if (bindings.length > 0) {
332
+ const stmt = connection.prepare(sql);
333
+ results = await stmt.execute(bindings);
334
+ }
335
+ else {
336
+ results = await connection.execute(sql);
337
+ }
338
+ // Take the first result (one statement per knex query)
339
+ obj.response = results[0];
340
+ return obj;
341
+ }
342
+ processResponse(obj, runner) {
343
+ const resp = obj.response;
344
+ if (obj.output)
345
+ return obj.output.call(runner, resp);
346
+ if (obj.method === "raw")
347
+ return resp;
348
+ const { returning } = obj;
349
+ // PetraDB returns { command, rows, fields } for selects,
350
+ // { command, result, rows, fields } for inserts,
351
+ // { command, rowCount } for update/delete.
352
+ const command = resp && resp.command;
353
+ switch (obj.method) {
354
+ case "select":
355
+ return resp.rows || [];
356
+ case "first":
357
+ return (resp.rows || [])[0];
358
+ case "pluck":
359
+ return (resp.rows || []).map((r) => r[obj.pluck]);
360
+ case "insert":
361
+ if (returning) {
362
+ return resp.rows || [];
363
+ }
364
+ // Return the auto-generated values (e.g. serial id)
365
+ return [resp.result];
366
+ case "update":
367
+ case "del":
368
+ case "counter":
369
+ if (returning) {
370
+ return resp.rows || [];
371
+ }
372
+ return resp.rowCount ?? 0;
373
+ default:
374
+ return resp;
375
+ }
376
+ }
377
+ poolDefaults() {
378
+ const defaults = super.poolDefaults();
379
+ // In-process engine — one connection is fine
380
+ return { ...defaults, min: 1, max: 1 };
381
+ }
382
+ }
383
+ Object.assign(PetraDBClient.prototype, {
384
+ dialect: "petradb",
385
+ driverName: "petradb",
386
+ });
387
+ export default PetraDBClient;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@petradb/knex",
3
+ "version": "1.2.0",
4
+ "description": "Knex.js dialect for PetraDB",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ }
11
+ },
12
+ "main": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist/",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "clean": "rm -rf dist"
21
+ },
22
+ "peerDependencies": {
23
+ "@petradb/engine": ">=1.2.0",
24
+ "knex": ">=2.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@adonisjs/lucid": "^22.0.0",
28
+ "@petradb/engine": "file:../engine/npm",
29
+ "knex": "^3.1.0",
30
+ "luxon": "^3.7.2",
31
+ "typescript": "^5.9.3"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/edadma/petradb.git"
36
+ },
37
+ "keywords": [
38
+ "knex",
39
+ "petradb",
40
+ "SQL",
41
+ "database",
42
+ "dialect"
43
+ ],
44
+ "author": "Edward A. Maxedon, Sr.",
45
+ "license": "ISC",
46
+ "homepage": "https://petradb.dev"
47
+ }