@devbro/neko-sql 0.1.31 → 0.1.32

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/databases/sqlite/SqliteQueryGrammar.mts"],"sourcesContent":["import { Query } from '../../Query.mjs';\nimport { QueryGrammar } from '../../QueryGrammar.mjs';\nimport { CompiledSql, Parameter } from '../../types.mjs';\nimport { Arr } from '@devbro/neko-helper';\n\nexport class SqliteQueryGrammar extends QueryGrammar {\n constructor() {\n super();\n }\n\n toSql(query: Query): CompiledSql {\n return super.toSql(query);\n }\n\n compileInsert(query: Query, data: Record<string, any>): CompiledSql {\n return super.compileInsert(query, data);\n }\n\n compileInsertGetId(\n query: Query,\n data: Record<string, any>,\n options: { primaryKey: string[] } = { primaryKey: ['id'] }\n ): CompiledSql {\n const rc = super.compileInsert(query, data);\n rc.sql += ` RETURNING ${options.primaryKey.join(', ')}`;\n rc.parts = rc.parts.concat(['RETURNING', ...Arr.intersperse(options.primaryKey, ',')]);\n return rc;\n }\n\n compileUpdate(query: Query, data: Record<string, any>): CompiledSql {\n return super.compileUpdate(query, data);\n }\n\n compileDelete(query: Query): CompiledSql {\n return super.compileDelete(query);\n }\n\n compileUpsert(\n query: Query,\n data: Record<string, Parameter>,\n conflictFields: string[],\n updateFields: string[]\n ): CompiledSql {\n return super.compileUpsert(query, data, conflictFields, updateFields);\n }\n\n compileCount(query: Query): CompiledSql {\n return super.compileCount(query);\n }\n}\n"],"mappings":";;AACA,SAAS,oBAAoB;AAE7B,SAAS,WAAW;AAEb,MAAM,2BAA2B,aAAa;AAAA,EALrD,OAKqD;AAAA;AAAA;AAAA,EACnD,cAAc;AACZ,UAAM;AAAA,EACR;AAAA,EAEA,MAAM,OAA2B;AAC/B,WAAO,MAAM,MAAM,KAAK;AAAA,EAC1B;AAAA,EAEA,cAAc,OAAc,MAAwC;AAClE,WAAO,MAAM,cAAc,OAAO,IAAI;AAAA,EACxC;AAAA,EAEA,mBACE,OACA,MACA,UAAoC,EAAE,YAAY,CAAC,IAAI,EAAE,GAC5C;AACb,UAAM,KAAK,MAAM,cAAc,OAAO,IAAI;AAC1C,OAAG,OAAO,cAAc,QAAQ,WAAW,KAAK,IAAI,CAAC;AACrD,OAAG,QAAQ,GAAG,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,YAAY,QAAQ,YAAY,GAAG,CAAC,CAAC;AACrF,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAc,MAAwC;AAClE,WAAO,MAAM,cAAc,OAAO,IAAI;AAAA,EACxC;AAAA,EAEA,cAAc,OAA2B;AACvC,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC;AAAA,EAEA,cACE,OACA,MACA,gBACA,cACa;AACb,WAAO,MAAM,cAAc,OAAO,MAAM,gBAAgB,YAAY;AAAA,EACtE;AAAA,EAEA,aAAa,OAA2B;AACtC,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC;AACF;","names":[]}
@@ -0,0 +1,7 @@
1
+ import { f as SchemaGrammar } from '../../Blueprint-D3WHeqRS.mjs';
2
+ import '@devbro/neko-helper';
3
+
4
+ declare class SqliteSchemaGrammar extends SchemaGrammar {
5
+ }
6
+
7
+ export { SqliteSchemaGrammar };
@@ -0,0 +1,12 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { SchemaGrammar } from "../../SchemaGrammar.mjs";
4
+ class SqliteSchemaGrammar extends SchemaGrammar {
5
+ static {
6
+ __name(this, "SqliteSchemaGrammar");
7
+ }
8
+ }
9
+ export {
10
+ SqliteSchemaGrammar
11
+ };
12
+ //# sourceMappingURL=SqliteSchemaGrammar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/databases/sqlite/SqliteSchemaGrammar.mts"],"sourcesContent":["import { SchemaGrammar } from '../../SchemaGrammar.mjs';\n\nexport class SqliteSchemaGrammar extends SchemaGrammar {}\n"],"mappings":";;AAAA,SAAS,qBAAqB;AAEvB,MAAM,4BAA4B,cAAc;AAAA,EAFvD,OAEuD;AAAA;AAAA;AAAC;","names":[]}
@@ -0,0 +1,6 @@
1
+ export { SqliteConfig, SqliteConnection } from './SqliteConnection.mjs';
2
+ export { SqliteQueryGrammar } from './SqliteQueryGrammar.mjs';
3
+ export { SqliteSchemaGrammar } from './SqliteSchemaGrammar.mjs';
4
+ import '../../Blueprint-D3WHeqRS.mjs';
5
+ import '@devbro/neko-helper';
6
+ import 'better-sqlite3';
@@ -0,0 +1,4 @@
1
+ export * from "./SqliteConnection.mjs";
2
+ export * from "./SqliteQueryGrammar.mjs";
3
+ export * from "./SqliteSchemaGrammar.mjs";
4
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/databases/sqlite/index.mts"],"sourcesContent":["export * from './SqliteConnection.mjs';\nexport * from './SqliteQueryGrammar.mjs';\nexport * from './SqliteSchemaGrammar.mjs';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,11 @@
1
1
  export { PostgresqlConnection } from './databases/postgresql/PostgresqlConnection.mjs';
2
2
  export { PostgresqlQueryGrammar } from './databases/postgresql/PostgresqlQueryGrammar.mjs';
3
3
  export { PostgresqlSchemaGrammar } from './databases/postgresql/PostgresqlSchemaGrammar.mjs';
4
+ export { SqliteConfig, SqliteConnection } from './databases/sqlite/SqliteConnection.mjs';
5
+ export { SqliteQueryGrammar } from './databases/sqlite/SqliteQueryGrammar.mjs';
6
+ export { SqliteSchemaGrammar } from './databases/sqlite/SqliteSchemaGrammar.mjs';
4
7
  export { B as Blueprint, a as Column, C as ColumnPropertiesType, m as CompiledSql, b as Connection, F as ForeignKeyConstraint, I as IndexConstraint, J as JoinCondition, P as Parameter, d as Query, e as QueryGrammar, Q as QueryParts, S as Schema, f as SchemaGrammar, c as connection_events, n as havingType, o as joinType, s as selectType, w as whereBasic, i as whereNested, k as whereNull, g as whereOp, h as whereOpColumn, j as whereRaw, l as whereType } from './Blueprint-D3WHeqRS.mjs';
5
8
  export { Migration } from './Migration.mjs';
6
9
  import 'pg';
10
+ import 'better-sqlite3';
7
11
  import '@devbro/neko-helper';
package/dist/index.js CHANGED
@@ -43,7 +43,10 @@ __export(index_exports, {
43
43
  Query: () => Query,
44
44
  QueryGrammar: () => QueryGrammar,
45
45
  Schema: () => Schema,
46
- SchemaGrammar: () => SchemaGrammar
46
+ SchemaGrammar: () => SchemaGrammar,
47
+ SqliteConnection: () => SqliteConnection,
48
+ SqliteQueryGrammar: () => SqliteQueryGrammar,
49
+ SqliteSchemaGrammar: () => SqliteSchemaGrammar
47
50
  });
48
51
  module.exports = __toCommonJS(index_exports);
49
52
 
@@ -1221,7 +1224,8 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1221
1224
  }
1222
1225
  }
1223
1226
  async connect() {
1224
- this.eventManager.emit("connect");
1227
+ this.eventManager.emit("connect").catch(() => {
1228
+ });
1225
1229
  this.connection = await _PostgresqlConnection.pool.connect();
1226
1230
  return true;
1227
1231
  }
@@ -1234,7 +1238,8 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1234
1238
  if (sql.parts && sql.parts.length > 0) {
1235
1239
  sql2 = sql.parts.map((v) => v === "?" ? "$" + counter++ : v).join(" ");
1236
1240
  }
1237
- this.eventManager.emit("query", { sql: sql2, bindings: sql.bindings });
1241
+ this.eventManager.emit("query", { sql: sql2, bindings: sql.bindings }).catch(() => {
1242
+ });
1238
1243
  if (!this.isConnected()) {
1239
1244
  await this.connect();
1240
1245
  }
@@ -1250,7 +1255,8 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1250
1255
  }
1251
1256
  await this.connection?.release();
1252
1257
  this.connection = void 0;
1253
- this.eventManager.emit("disconnect");
1258
+ this.eventManager.emit("disconnect").catch(() => {
1259
+ });
1254
1260
  return true;
1255
1261
  }
1256
1262
  getQuery() {
@@ -1274,9 +1280,8 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1274
1280
  async rollback() {
1275
1281
  await this.runQuery({ sql: "ROLLBACK", bindings: [], parts: ["ROLLBACK"] });
1276
1282
  }
1277
- static async destroy() {
1278
- _PostgresqlConnection.pool.end();
1279
- return;
1283
+ static destroy() {
1284
+ return _PostgresqlConnection.pool.end();
1280
1285
  }
1281
1286
  isConnected() {
1282
1287
  return this.connection !== void 0;
@@ -1313,7 +1318,7 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1313
1318
  if (this.isConnected()) {
1314
1319
  throw new Error("Cannot create database while connected.");
1315
1320
  }
1316
- let conn = new import_pg.Client({
1321
+ const conn = new import_pg.Client({
1317
1322
  ..._PostgresqlConnection.pool.options,
1318
1323
  database: "postgres"
1319
1324
  });
@@ -1326,7 +1331,7 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1326
1331
  if (this.isConnected()) {
1327
1332
  throw new Error("Cannot drop database while connected.");
1328
1333
  }
1329
- let conn = new import_pg.Client({
1334
+ const conn = new import_pg.Client({
1330
1335
  ..._PostgresqlConnection.pool.options,
1331
1336
  database: "postgres"
1332
1337
  // connect to default 'postgres' database to drop others
@@ -1356,6 +1361,283 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1356
1361
  }
1357
1362
  };
1358
1363
 
1364
+ // src/databases/sqlite/SqliteConnection.mts
1365
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
1366
+
1367
+ // src/databases/sqlite/SqliteQueryGrammar.mts
1368
+ var import_neko_helper4 = require("@devbro/neko-helper");
1369
+ var SqliteQueryGrammar = class extends QueryGrammar {
1370
+ static {
1371
+ __name(this, "SqliteQueryGrammar");
1372
+ }
1373
+ constructor() {
1374
+ super();
1375
+ }
1376
+ toSql(query) {
1377
+ return super.toSql(query);
1378
+ }
1379
+ compileInsert(query, data) {
1380
+ return super.compileInsert(query, data);
1381
+ }
1382
+ compileInsertGetId(query, data, options = { primaryKey: ["id"] }) {
1383
+ const rc = super.compileInsert(query, data);
1384
+ rc.sql += ` RETURNING ${options.primaryKey.join(", ")}`;
1385
+ rc.parts = rc.parts.concat(["RETURNING", ...import_neko_helper4.Arr.intersperse(options.primaryKey, ",")]);
1386
+ return rc;
1387
+ }
1388
+ compileUpdate(query, data) {
1389
+ return super.compileUpdate(query, data);
1390
+ }
1391
+ compileDelete(query) {
1392
+ return super.compileDelete(query);
1393
+ }
1394
+ compileUpsert(query, data, conflictFields, updateFields) {
1395
+ return super.compileUpsert(query, data, conflictFields, updateFields);
1396
+ }
1397
+ compileCount(query) {
1398
+ return super.compileCount(query);
1399
+ }
1400
+ };
1401
+
1402
+ // src/databases/sqlite/SqliteSchemaGrammar.mts
1403
+ var SqliteSchemaGrammar = class extends SchemaGrammar {
1404
+ static {
1405
+ __name(this, "SqliteSchemaGrammar");
1406
+ }
1407
+ };
1408
+
1409
+ // src/databases/sqlite/SqliteConnection.mts
1410
+ var import_neko_helper5 = require("@devbro/neko-helper");
1411
+ var fs = __toESM(require("fs"), 1);
1412
+ var SqliteConnection = class _SqliteConnection extends Connection {
1413
+ static {
1414
+ __name(this, "SqliteConnection");
1415
+ }
1416
+ eventManager = new import_neko_helper5.EventManager();
1417
+ on(event, listener) {
1418
+ this.eventManager.on(event, listener);
1419
+ return this;
1420
+ }
1421
+ off(event, listener) {
1422
+ this.eventManager.off(event, listener);
1423
+ return this;
1424
+ }
1425
+ emit(event, ...args) {
1426
+ return this.eventManager.emit(event, ...args);
1427
+ }
1428
+ connection;
1429
+ config;
1430
+ /** Default configuration values for SQLite connections */
1431
+ static defaults = {
1432
+ readonly: false,
1433
+ fileMustExist: false,
1434
+ timeout: 5e3
1435
+ };
1436
+ constructor(params) {
1437
+ super();
1438
+ this.config = { ..._SqliteConnection.defaults, ...params };
1439
+ }
1440
+ /**
1441
+ * Establishes a connection to the SQLite database
1442
+ * Creates or opens the database file specified in the configuration
1443
+ */
1444
+ async connect() {
1445
+ this.eventManager.emit("connect").catch(() => {
1446
+ });
1447
+ this.connection = new import_better_sqlite3.default(this.config.filename, {
1448
+ readonly: this.config.readonly,
1449
+ fileMustExist: this.config.fileMustExist,
1450
+ timeout: this.config.timeout,
1451
+ verbose: this.config.verbose
1452
+ });
1453
+ return true;
1454
+ }
1455
+ /**
1456
+ * Executes a SQL query against the database
1457
+ * Automatically detects SELECT queries and queries with RETURNING clauses
1458
+ *
1459
+ * @param sql - Compiled SQL or raw SQL string to execute
1460
+ * @returns Query results (rows for SELECT, run info for INSERT/UPDATE/DELETE)
1461
+ */
1462
+ async runQuery(sql) {
1463
+ if (typeof sql === "string") {
1464
+ sql = { sql, bindings: [], parts: [sql] };
1465
+ }
1466
+ this.eventManager.emit("query", { sql: sql.sql, bindings: sql.bindings }).catch(() => {
1467
+ });
1468
+ if (!this.isConnected()) {
1469
+ await this.connect();
1470
+ }
1471
+ try {
1472
+ const stmt = this.connection.prepare(sql.sql);
1473
+ const sqlUpper = sql.sql.trim().toUpperCase();
1474
+ if (sqlUpper.startsWith("SELECT") || sqlUpper.includes("RETURNING")) {
1475
+ return stmt.all(...sql.bindings);
1476
+ } else {
1477
+ const result = stmt.run(...sql.bindings);
1478
+ return result;
1479
+ }
1480
+ } catch (error) {
1481
+ this.eventManager.emit("error", error).catch(() => {
1482
+ });
1483
+ throw error;
1484
+ }
1485
+ }
1486
+ /**
1487
+ * Executes a query and returns an iterator for streaming results
1488
+ * Useful for large result sets to avoid loading all rows into memory
1489
+ *
1490
+ * @param sql - Compiled SQL to execute
1491
+ * @returns Iterator over query results
1492
+ */
1493
+ async runCursor(sql) {
1494
+ if (!this.isConnected()) {
1495
+ await this.connect();
1496
+ }
1497
+ const stmt = this.connection.prepare(sql.sql);
1498
+ return stmt.iterate(...sql.bindings);
1499
+ }
1500
+ /**
1501
+ * Closes the database connection
1502
+ */
1503
+ async disconnect() {
1504
+ if (this.connection === void 0) {
1505
+ return true;
1506
+ }
1507
+ this.connection.close();
1508
+ this.connection = void 0;
1509
+ this.eventManager.emit("disconnect").catch(() => {
1510
+ });
1511
+ return true;
1512
+ }
1513
+ /**
1514
+ * Creates a new query builder instance for this connection
1515
+ */
1516
+ getQuery() {
1517
+ return new Query(this, new SqliteQueryGrammar());
1518
+ }
1519
+ /**
1520
+ * Creates a new schema builder instance for this connection
1521
+ */
1522
+ getSchema() {
1523
+ return new Schema(this, new SqliteSchemaGrammar());
1524
+ }
1525
+ /**
1526
+ * Gets the query grammar for building SQL statements
1527
+ */
1528
+ getQueryGrammar() {
1529
+ return new SqliteQueryGrammar();
1530
+ }
1531
+ /**
1532
+ * Gets the schema grammar for building DDL statements
1533
+ */
1534
+ getSchemaGrammar() {
1535
+ return new SqliteSchemaGrammar();
1536
+ }
1537
+ /**
1538
+ * Starts a new database transaction
1539
+ */
1540
+ async beginTransaction() {
1541
+ await this.runQuery({
1542
+ sql: "BEGIN TRANSACTION",
1543
+ bindings: [],
1544
+ parts: ["BEGIN", "TRANSACTION"]
1545
+ });
1546
+ }
1547
+ /**
1548
+ * Commits the current transaction
1549
+ */
1550
+ async commit() {
1551
+ await this.runQuery({ sql: "COMMIT", bindings: [], parts: ["COMMIT"] });
1552
+ }
1553
+ /**
1554
+ * Rolls back the current transaction
1555
+ */
1556
+ async rollback() {
1557
+ await this.runQuery({ sql: "ROLLBACK", bindings: [], parts: ["ROLLBACK"] });
1558
+ }
1559
+ /**
1560
+ * Checks if the database connection is active
1561
+ */
1562
+ isConnected() {
1563
+ return this.connection !== void 0 && this.connection.open;
1564
+ }
1565
+ /**
1566
+ * Validates and escapes a SQLite identifier (database name, table name, etc.)
1567
+ * Uses a whitelist approach to ensure only safe characters are allowed
1568
+ *
1569
+ * @param name - The identifier to validate and escape
1570
+ * @returns The escaped identifier, quoted if it's a reserved keyword
1571
+ * @throws Error if the identifier contains invalid characters
1572
+ */
1573
+ validateAndEscapeIdentifier(name) {
1574
+ const validIdentifierPattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
1575
+ if (!validIdentifierPattern.test(name)) {
1576
+ throw new Error(
1577
+ `Invalid identifier: "${name}". Identifiers must start with a letter or underscore and contain only letters, digits, and underscores.`
1578
+ );
1579
+ }
1580
+ const reservedKeywords = /* @__PURE__ */ new Set([
1581
+ "table",
1582
+ "database",
1583
+ "order",
1584
+ "group",
1585
+ "select",
1586
+ "insert",
1587
+ "update",
1588
+ "delete",
1589
+ "index",
1590
+ "from",
1591
+ "where"
1592
+ ]);
1593
+ if (reservedKeywords.has(name.toLowerCase())) {
1594
+ const escapedName = name.replace(/"/g, '""');
1595
+ return `"${escapedName}"`;
1596
+ }
1597
+ return name;
1598
+ }
1599
+ /**
1600
+ * Creates a new SQLite database file
1601
+ *
1602
+ * @param name - Name or path of the database file to create
1603
+ */
1604
+ async createDatabase(name) {
1605
+ const dbPath = name.endsWith(".db") ? name : `${name}.db`;
1606
+ const tempDb = new import_better_sqlite3.default(dbPath);
1607
+ tempDb.close();
1608
+ }
1609
+ /**
1610
+ * Deletes a SQLite database file
1611
+ *
1612
+ * @param name - Name or path of the database file to delete
1613
+ */
1614
+ async dropDatabase(name) {
1615
+ const dbPath = name.endsWith(".db") ? name : `${name}.db`;
1616
+ if (fs.existsSync(dbPath)) {
1617
+ fs.unlinkSync(dbPath);
1618
+ }
1619
+ }
1620
+ /**
1621
+ * Lists available databases
1622
+ * For SQLite, this returns the current database filename
1623
+ *
1624
+ * @returns Array containing the current database filename
1625
+ */
1626
+ async listDatabases() {
1627
+ return [this.config.filename];
1628
+ }
1629
+ /**
1630
+ * Checks if a database file exists
1631
+ *
1632
+ * @param name - Name or path of the database file to check
1633
+ * @returns True if the database file exists, false otherwise
1634
+ */
1635
+ async existsDatabase(name) {
1636
+ const dbPath = name.endsWith(".db") ? name : `${name}.db`;
1637
+ return fs.existsSync(dbPath);
1638
+ }
1639
+ };
1640
+
1359
1641
  // src/Migration.mts
1360
1642
  var Migration = class {
1361
1643
  static {
@@ -1376,6 +1658,9 @@ var Migration = class {
1376
1658
  Query,
1377
1659
  QueryGrammar,
1378
1660
  Schema,
1379
- SchemaGrammar
1661
+ SchemaGrammar,
1662
+ SqliteConnection,
1663
+ SqliteQueryGrammar,
1664
+ SqliteSchemaGrammar
1380
1665
  });
1381
1666
  //# sourceMappingURL=index.js.map