navis.js 5.4.1 → 5.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -4
- package/examples/database-adapters-demo.js +138 -0
- package/examples/database-adapters-demo.ts +145 -0
- package/package.json +1 -1
- package/src/db/db-pool.js +164 -1
- package/types/index.d.ts +1 -1
package/README.md
CHANGED
|
@@ -171,20 +171,25 @@ navis metrics
|
|
|
171
171
|
|
|
172
172
|
- ✅ **WebSocket support** - Real-time bidirectional communication
|
|
173
173
|
- ✅ **Server-Sent Events** - One-way real-time streaming
|
|
174
|
-
- ✅ **Database integration** - Connection pooling for PostgreSQL, MySQL, MongoDB
|
|
174
|
+
- ✅ **Database integration** - Connection pooling for PostgreSQL, MySQL, MongoDB, SQLite, SQL Server
|
|
175
175
|
|
|
176
176
|
### v5.3 ✅
|
|
177
177
|
- ✅ **TypeScript support** - Full type definitions for all features
|
|
178
178
|
- ✅ **Type-safe API** - Complete IntelliSense and type checking
|
|
179
179
|
- ✅ **TypeScript examples** - Ready-to-use TypeScript examples
|
|
180
180
|
|
|
181
|
-
### v5.4
|
|
181
|
+
### v5.4 ✅
|
|
182
182
|
- ✅ **GraphQL support** - Lightweight GraphQL server implementation
|
|
183
183
|
- ✅ **GraphQL queries & mutations** - Full query and mutation support
|
|
184
184
|
- ✅ **GraphQL resolvers** - Flexible resolver system with utilities
|
|
185
185
|
- ✅ **GraphQL schema builder** - Schema definition helpers
|
|
186
186
|
- ✅ **GraphQL middleware** - Easy integration with Navis.js routes
|
|
187
187
|
|
|
188
|
+
### v5.5 (Current)
|
|
189
|
+
- ✅ **Extended database adapters** - SQLite and SQL Server support
|
|
190
|
+
- ✅ **Enhanced database pool** - Support for 5 database types (PostgreSQL, MySQL, MongoDB, SQLite, SQL Server)
|
|
191
|
+
- ✅ **Improved connection handling** - Better error handling and connection management
|
|
192
|
+
|
|
188
193
|
## API Reference
|
|
189
194
|
|
|
190
195
|
### NavisApp
|
|
@@ -545,6 +550,73 @@ curl -X POST http://localhost:3000/graphql \
|
|
|
545
550
|
|
|
546
551
|
See `examples/graphql-demo.js` for a complete GraphQL example.
|
|
547
552
|
|
|
553
|
+
### Extended Database Adapters (v5.5)
|
|
554
|
+
|
|
555
|
+
**JavaScript Example:**
|
|
556
|
+
```javascript
|
|
557
|
+
const { NavisApp, createPool, response } = require('navis.js');
|
|
558
|
+
|
|
559
|
+
const app = new NavisApp();
|
|
560
|
+
|
|
561
|
+
// SQLite Database
|
|
562
|
+
app.get('/sqlite/users', async (req, res) => {
|
|
563
|
+
const db = createPool({
|
|
564
|
+
type: 'sqlite',
|
|
565
|
+
connectionString: ':memory:', // or path to .db file
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
await db.connect();
|
|
569
|
+
const users = await db.query('SELECT * FROM users');
|
|
570
|
+
await db.close();
|
|
571
|
+
|
|
572
|
+
response.success(res, { users });
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// SQL Server Database
|
|
576
|
+
app.get('/sqlserver/users', async (req, res) => {
|
|
577
|
+
const db = createPool({
|
|
578
|
+
type: 'mssql',
|
|
579
|
+
connectionString: 'Server=localhost;Database=testdb;User Id=sa;Password=pass',
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
await db.connect();
|
|
583
|
+
const users = await db.query('SELECT TOP 10 * FROM users');
|
|
584
|
+
await db.close();
|
|
585
|
+
|
|
586
|
+
response.success(res, { users });
|
|
587
|
+
});
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**TypeScript Example:**
|
|
591
|
+
```typescript
|
|
592
|
+
import { NavisApp, createPool, response, DatabasePool } from 'navis.js';
|
|
593
|
+
|
|
594
|
+
const app = new NavisApp();
|
|
595
|
+
|
|
596
|
+
// SQLite with TypeScript
|
|
597
|
+
app.get('/sqlite/users', async (req, res) => {
|
|
598
|
+
const db: DatabasePool = createPool({
|
|
599
|
+
type: 'sqlite',
|
|
600
|
+
connectionString: ':memory:',
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
await db.connect();
|
|
604
|
+
const users = await db.query('SELECT * FROM users') as User[];
|
|
605
|
+
await db.close();
|
|
606
|
+
|
|
607
|
+
response.success(res, { users });
|
|
608
|
+
});
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
**Supported Databases:**
|
|
612
|
+
- ✅ PostgreSQL (`postgres` or `postgresql`)
|
|
613
|
+
- ✅ MySQL/MariaDB (`mysql` or `mariadb`)
|
|
614
|
+
- ✅ MongoDB (`mongodb`)
|
|
615
|
+
- ✅ SQLite (`sqlite` or `sqlite3`) - **NEW in v5.5**
|
|
616
|
+
- ✅ SQL Server (`mssql` or `sqlserver`) - **NEW in v5.5**
|
|
617
|
+
|
|
618
|
+
See `examples/database-adapters-demo.js` and `examples/database-adapters-demo.ts` for complete examples.
|
|
619
|
+
|
|
548
620
|
## Examples
|
|
549
621
|
|
|
550
622
|
See the `examples/` directory:
|
|
@@ -563,6 +635,8 @@ See the `examples/` directory:
|
|
|
563
635
|
- `v5.2-features-demo.js` - v5.2 features demonstration (WebSocket, SSE, database)
|
|
564
636
|
- `graphql-demo.js` - GraphQL server example with queries and mutations (v5.4) - JavaScript
|
|
565
637
|
- `graphql-demo.ts` - GraphQL server example with TypeScript types (v5.4) - TypeScript
|
|
638
|
+
- `database-adapters-demo.js` - Extended database adapters example (v5.5) - JavaScript
|
|
639
|
+
- `database-adapters-demo.ts` - Extended database adapters example (v5.5) - TypeScript
|
|
566
640
|
- `service-client-demo.js` - ServiceClient usage example
|
|
567
641
|
|
|
568
642
|
## Roadmap
|
|
@@ -591,15 +665,18 @@ Real-time features: WebSocket, Server-Sent Events, database integration
|
|
|
591
665
|
### v5.3 ✅
|
|
592
666
|
TypeScript support: Full type definitions, type-safe API, IntelliSense
|
|
593
667
|
|
|
594
|
-
### v5.4 ✅
|
|
668
|
+
### v5.4 ✅
|
|
595
669
|
GraphQL support: Lightweight GraphQL server, queries, mutations, resolvers, schema builder
|
|
596
670
|
|
|
671
|
+
### v5.5 ✅ (Current)
|
|
672
|
+
Extended database adapters: SQLite and SQL Server support, enhanced connection pooling
|
|
673
|
+
|
|
597
674
|
## What's Next?
|
|
598
675
|
|
|
599
676
|
Future versions may include:
|
|
600
677
|
- gRPC integration
|
|
601
678
|
- Advanced caching strategies
|
|
602
|
-
-
|
|
679
|
+
- Advanced query builders
|
|
603
680
|
- Enhanced monitoring and alerting
|
|
604
681
|
|
|
605
682
|
## Documentation
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Adapters Demo - Navis.js
|
|
3
|
+
* Demonstrates extended database adapter support (SQLite, SQL Server)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { NavisApp, createPool, response } = require('../src/index');
|
|
7
|
+
|
|
8
|
+
const app = new NavisApp();
|
|
9
|
+
|
|
10
|
+
// Example: SQLite Database
|
|
11
|
+
app.get('/sqlite/users', async (req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
const db = createPool({
|
|
14
|
+
type: 'sqlite',
|
|
15
|
+
connectionString: ':memory:', // In-memory database for demo
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await db.connect();
|
|
19
|
+
|
|
20
|
+
// Create table (if not exists)
|
|
21
|
+
await db.query(`
|
|
22
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
23
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
24
|
+
name TEXT NOT NULL,
|
|
25
|
+
email TEXT NOT NULL
|
|
26
|
+
)
|
|
27
|
+
`);
|
|
28
|
+
|
|
29
|
+
// Insert sample data
|
|
30
|
+
await db.query('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', 'alice@example.com']);
|
|
31
|
+
await db.query('INSERT INTO users (name, email) VALUES (?, ?)', ['Bob', 'bob@example.com']);
|
|
32
|
+
|
|
33
|
+
// Query users
|
|
34
|
+
const users = await db.query('SELECT * FROM users');
|
|
35
|
+
|
|
36
|
+
await db.close();
|
|
37
|
+
|
|
38
|
+
response.success(res, {
|
|
39
|
+
database: 'SQLite',
|
|
40
|
+
users,
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
response.error(res, `SQLite error: ${error.message}`, 500);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Example: SQL Server Database
|
|
48
|
+
app.get('/sqlserver/users', async (req, res) => {
|
|
49
|
+
try {
|
|
50
|
+
const db = createPool({
|
|
51
|
+
type: 'mssql',
|
|
52
|
+
connectionString: process.env.SQL_SERVER_CONNECTION_STRING || 'Server=localhost;Database=testdb;User Id=sa;Password=YourPassword123',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await db.connect();
|
|
56
|
+
|
|
57
|
+
// Query users (assuming table exists)
|
|
58
|
+
const users = await db.query('SELECT TOP 10 * FROM users');
|
|
59
|
+
|
|
60
|
+
await db.close();
|
|
61
|
+
|
|
62
|
+
response.success(res, {
|
|
63
|
+
database: 'SQL Server',
|
|
64
|
+
users,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
response.error(res, `SQL Server error: ${error.message}`, 500);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Example: PostgreSQL (existing)
|
|
72
|
+
app.get('/postgres/users', async (req, res) => {
|
|
73
|
+
try {
|
|
74
|
+
const db = createPool({
|
|
75
|
+
type: 'postgres',
|
|
76
|
+
connectionString: process.env.DATABASE_URL || 'postgresql://user:password@localhost:5432/mydb',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await db.connect();
|
|
80
|
+
const users = await db.query('SELECT * FROM users LIMIT 10');
|
|
81
|
+
await db.close();
|
|
82
|
+
|
|
83
|
+
response.success(res, {
|
|
84
|
+
database: 'PostgreSQL',
|
|
85
|
+
users,
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
response.error(res, `PostgreSQL error: ${error.message}`, 500);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Example: MySQL (existing)
|
|
93
|
+
app.get('/mysql/users', async (req, res) => {
|
|
94
|
+
try {
|
|
95
|
+
const db = createPool({
|
|
96
|
+
type: 'mysql',
|
|
97
|
+
connectionString: process.env.MYSQL_URL || 'mysql://user:password@localhost:3306/mydb',
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await db.connect();
|
|
101
|
+
const users = await db.query('SELECT * FROM users LIMIT 10');
|
|
102
|
+
await db.close();
|
|
103
|
+
|
|
104
|
+
response.success(res, {
|
|
105
|
+
database: 'MySQL',
|
|
106
|
+
users,
|
|
107
|
+
});
|
|
108
|
+
} catch (error) {
|
|
109
|
+
response.error(res, `MySQL error: ${error.message}`, 500);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Health check
|
|
114
|
+
app.get('/health', (req, res) => {
|
|
115
|
+
response.success(res, {
|
|
116
|
+
status: 'ok',
|
|
117
|
+
databases: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'SQL Server'],
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Start server
|
|
122
|
+
const PORT = process.env.PORT || 3000;
|
|
123
|
+
app.listen(PORT, () => {
|
|
124
|
+
console.log(`🚀 Navis.js Database Adapters Demo running on http://localhost:${PORT}`);
|
|
125
|
+
console.log('\n📊 Available endpoints:');
|
|
126
|
+
console.log(` GET http://localhost:${PORT}/sqlite/users - SQLite example`);
|
|
127
|
+
console.log(` GET http://localhost:${PORT}/sqlserver/users - SQL Server example`);
|
|
128
|
+
console.log(` GET http://localhost:${PORT}/postgres/users - PostgreSQL example`);
|
|
129
|
+
console.log(` GET http://localhost:${PORT}/mysql/users - MySQL example`);
|
|
130
|
+
console.log(` GET http://localhost:${PORT}/health - Health check`);
|
|
131
|
+
console.log('\n💡 Note: Make sure to install the required database drivers:');
|
|
132
|
+
console.log(' - SQLite: npm install better-sqlite3 (or sqlite3 sqlite)');
|
|
133
|
+
console.log(' - SQL Server: npm install mssql');
|
|
134
|
+
console.log(' - PostgreSQL: npm install pg');
|
|
135
|
+
console.log(' - MySQL: npm install mysql2');
|
|
136
|
+
console.log(' - MongoDB: npm install mongodb');
|
|
137
|
+
});
|
|
138
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Adapters Demo - Navis.js (TypeScript)
|
|
3
|
+
* Demonstrates extended database adapter support with TypeScript types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { NavisApp, createPool, response, DatabasePool } from '../src/index';
|
|
7
|
+
|
|
8
|
+
const app = new NavisApp();
|
|
9
|
+
|
|
10
|
+
interface User {
|
|
11
|
+
id: number;
|
|
12
|
+
name: string;
|
|
13
|
+
email: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Example: SQLite Database
|
|
17
|
+
app.get('/sqlite/users', async (req, res) => {
|
|
18
|
+
try {
|
|
19
|
+
const db: DatabasePool = createPool({
|
|
20
|
+
type: 'sqlite',
|
|
21
|
+
connectionString: ':memory:', // In-memory database for demo
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await db.connect();
|
|
25
|
+
|
|
26
|
+
// Create table (if not exists)
|
|
27
|
+
await db.query(`
|
|
28
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
29
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
30
|
+
name TEXT NOT NULL,
|
|
31
|
+
email TEXT NOT NULL
|
|
32
|
+
)
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
// Insert sample data
|
|
36
|
+
await db.query('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', 'alice@example.com']);
|
|
37
|
+
await db.query('INSERT INTO users (name, email) VALUES (?, ?)', ['Bob', 'bob@example.com']);
|
|
38
|
+
|
|
39
|
+
// Query users
|
|
40
|
+
const users = await db.query('SELECT * FROM users') as User[];
|
|
41
|
+
|
|
42
|
+
await db.close();
|
|
43
|
+
|
|
44
|
+
response.success(res, {
|
|
45
|
+
database: 'SQLite',
|
|
46
|
+
users,
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
response.error(res, `SQLite error: ${(error as Error).message}`, 500);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Example: SQL Server Database
|
|
54
|
+
app.get('/sqlserver/users', async (req, res) => {
|
|
55
|
+
try {
|
|
56
|
+
const db: DatabasePool = createPool({
|
|
57
|
+
type: 'mssql',
|
|
58
|
+
connectionString: process.env.SQL_SERVER_CONNECTION_STRING || 'Server=localhost;Database=testdb;User Id=sa;Password=YourPassword123',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await db.connect();
|
|
62
|
+
|
|
63
|
+
// Query users (assuming table exists)
|
|
64
|
+
const users = await db.query('SELECT TOP 10 * FROM users') as User[];
|
|
65
|
+
|
|
66
|
+
await db.close();
|
|
67
|
+
|
|
68
|
+
response.success(res, {
|
|
69
|
+
database: 'SQL Server',
|
|
70
|
+
users,
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
response.error(res, `SQL Server error: ${(error as Error).message}`, 500);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Example: PostgreSQL (existing)
|
|
78
|
+
app.get('/postgres/users', async (req, res) => {
|
|
79
|
+
try {
|
|
80
|
+
const db: DatabasePool = createPool({
|
|
81
|
+
type: 'postgres',
|
|
82
|
+
connectionString: process.env.DATABASE_URL || 'postgresql://user:password@localhost:5432/mydb',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
await db.connect();
|
|
86
|
+
const users = await db.query('SELECT * FROM users LIMIT 10') as User[];
|
|
87
|
+
await db.close();
|
|
88
|
+
|
|
89
|
+
response.success(res, {
|
|
90
|
+
database: 'PostgreSQL',
|
|
91
|
+
users,
|
|
92
|
+
});
|
|
93
|
+
} catch (error) {
|
|
94
|
+
response.error(res, `PostgreSQL error: ${(error as Error).message}`, 500);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Example: MySQL (existing)
|
|
99
|
+
app.get('/mysql/users', async (req, res) => {
|
|
100
|
+
try {
|
|
101
|
+
const db: DatabasePool = createPool({
|
|
102
|
+
type: 'mysql',
|
|
103
|
+
connectionString: process.env.MYSQL_URL || 'mysql://user:password@localhost:3306/mydb',
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await db.connect();
|
|
107
|
+
const users = await db.query('SELECT * FROM users LIMIT 10') as User[];
|
|
108
|
+
await db.close();
|
|
109
|
+
|
|
110
|
+
response.success(res, {
|
|
111
|
+
database: 'MySQL',
|
|
112
|
+
users,
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
response.error(res, `MySQL error: ${(error as Error).message}`, 500);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Health check
|
|
120
|
+
app.get('/health', (req, res) => {
|
|
121
|
+
response.success(res, {
|
|
122
|
+
status: 'ok',
|
|
123
|
+
databases: ['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'SQL Server'],
|
|
124
|
+
typescript: true,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Start server
|
|
129
|
+
const PORT = process.env.PORT || 3000;
|
|
130
|
+
app.listen(PORT, () => {
|
|
131
|
+
console.log(`🚀 Navis.js Database Adapters Demo (TypeScript) running on http://localhost:${PORT}`);
|
|
132
|
+
console.log('\n📊 Available endpoints:');
|
|
133
|
+
console.log(` GET http://localhost:${PORT}/sqlite/users - SQLite example`);
|
|
134
|
+
console.log(` GET http://localhost:${PORT}/sqlserver/users - SQL Server example`);
|
|
135
|
+
console.log(` GET http://localhost:${PORT}/postgres/users - PostgreSQL example`);
|
|
136
|
+
console.log(` GET http://localhost:${PORT}/mysql/users - MySQL example`);
|
|
137
|
+
console.log(` GET http://localhost:${PORT}/health - Health check`);
|
|
138
|
+
console.log('\n💡 Note: Make sure to install the required database drivers:');
|
|
139
|
+
console.log(' - SQLite: npm install better-sqlite3 (or sqlite3 sqlite)');
|
|
140
|
+
console.log(' - SQL Server: npm install mssql');
|
|
141
|
+
console.log(' - PostgreSQL: npm install pg');
|
|
142
|
+
console.log(' - MySQL: npm install mysql2');
|
|
143
|
+
console.log(' - MongoDB: npm install mongodb');
|
|
144
|
+
});
|
|
145
|
+
|
package/package.json
CHANGED
package/src/db/db-pool.js
CHANGED
|
@@ -33,6 +33,14 @@ class DatabasePool {
|
|
|
33
33
|
case 'mongodb':
|
|
34
34
|
await this._connectMongoDB();
|
|
35
35
|
break;
|
|
36
|
+
case 'sqlite':
|
|
37
|
+
case 'sqlite3':
|
|
38
|
+
await this._connectSQLite();
|
|
39
|
+
break;
|
|
40
|
+
case 'mssql':
|
|
41
|
+
case 'sqlserver':
|
|
42
|
+
await this._connectSQLServer();
|
|
43
|
+
break;
|
|
36
44
|
default:
|
|
37
45
|
throw new Error(`Unsupported database type: ${this.type}`);
|
|
38
46
|
}
|
|
@@ -90,6 +98,111 @@ class DatabasePool {
|
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Connect to SQLite
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
async _connectSQLite() {
|
|
106
|
+
try {
|
|
107
|
+
const sqlite3 = require('better-sqlite3');
|
|
108
|
+
// SQLite connection string is a file path
|
|
109
|
+
const dbPath = this.connectionString || ':memory:';
|
|
110
|
+
this.pool = sqlite3(dbPath, {
|
|
111
|
+
timeout: this.idleTimeout,
|
|
112
|
+
});
|
|
113
|
+
// SQLite doesn't use connection pooling, but we store the db instance
|
|
114
|
+
this.db = this.pool;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
// Fallback to sqlite3 if better-sqlite3 is not available
|
|
117
|
+
try {
|
|
118
|
+
const sqlite3 = require('sqlite3');
|
|
119
|
+
const { open } = require('sqlite');
|
|
120
|
+
const dbPath = this.connectionString || ':memory:';
|
|
121
|
+
this.pool = await open({
|
|
122
|
+
filename: dbPath,
|
|
123
|
+
driver: sqlite3.Database,
|
|
124
|
+
});
|
|
125
|
+
this.db = this.pool;
|
|
126
|
+
} catch (fallbackError) {
|
|
127
|
+
throw new Error('SQLite package not installed. Install with: npm install better-sqlite3 or npm install sqlite3 sqlite');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Connect to SQL Server
|
|
134
|
+
* @private
|
|
135
|
+
*/
|
|
136
|
+
async _connectSQLServer() {
|
|
137
|
+
try {
|
|
138
|
+
const sql = require('mssql');
|
|
139
|
+
const config = this._parseSQLServerConfig(this.connectionString);
|
|
140
|
+
this.pool = await sql.connect(config);
|
|
141
|
+
this.db = this.pool;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw new Error('mssql package not installed. Install with: npm install mssql');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Parse SQL Server connection string to config object
|
|
149
|
+
* @private
|
|
150
|
+
*/
|
|
151
|
+
_parseSQLServerConfig(connectionString) {
|
|
152
|
+
if (!connectionString) {
|
|
153
|
+
throw new Error('SQL Server connection string is required');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// If it's already an object, return it
|
|
157
|
+
if (typeof connectionString === 'object') {
|
|
158
|
+
return {
|
|
159
|
+
...connectionString,
|
|
160
|
+
pool: {
|
|
161
|
+
max: this.maxConnections,
|
|
162
|
+
min: this.minConnections,
|
|
163
|
+
idleTimeoutMillis: this.idleTimeout,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Parse connection string format: Server=host;Database=db;User Id=user;Password=pass
|
|
169
|
+
const config = {};
|
|
170
|
+
connectionString.split(';').forEach(part => {
|
|
171
|
+
const [key, value] = part.split('=');
|
|
172
|
+
if (key && value) {
|
|
173
|
+
const normalizedKey = key.trim().toLowerCase();
|
|
174
|
+
switch (normalizedKey) {
|
|
175
|
+
case 'server':
|
|
176
|
+
config.server = value.trim();
|
|
177
|
+
break;
|
|
178
|
+
case 'database':
|
|
179
|
+
config.database = value.trim();
|
|
180
|
+
break;
|
|
181
|
+
case 'user id':
|
|
182
|
+
case 'userid':
|
|
183
|
+
case 'uid':
|
|
184
|
+
config.user = value.trim();
|
|
185
|
+
break;
|
|
186
|
+
case 'password':
|
|
187
|
+
case 'pwd':
|
|
188
|
+
config.password = value.trim();
|
|
189
|
+
break;
|
|
190
|
+
case 'port':
|
|
191
|
+
config.port = parseInt(value.trim(), 10);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
config.pool = {
|
|
198
|
+
max: this.maxConnections,
|
|
199
|
+
min: this.minConnections,
|
|
200
|
+
idleTimeoutMillis: this.idleTimeout,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
return config;
|
|
204
|
+
}
|
|
205
|
+
|
|
93
206
|
/**
|
|
94
207
|
* Execute a query
|
|
95
208
|
* @param {string} query - SQL query or MongoDB operation
|
|
@@ -113,6 +226,36 @@ class DatabasePool {
|
|
|
113
226
|
// MongoDB uses different query syntax
|
|
114
227
|
// This is a placeholder - implement based on your needs
|
|
115
228
|
return await this.db.collection(query).find(params[0] || {}).toArray();
|
|
229
|
+
case 'sqlite':
|
|
230
|
+
case 'sqlite3':
|
|
231
|
+
// SQLite with better-sqlite3 (synchronous) or sqlite (async)
|
|
232
|
+
if (this.pool.prepare) {
|
|
233
|
+
// better-sqlite3
|
|
234
|
+
const stmt = this.pool.prepare(query);
|
|
235
|
+
return stmt.all(...params);
|
|
236
|
+
} else {
|
|
237
|
+
// sqlite (async)
|
|
238
|
+
return await this.pool.all(query, params);
|
|
239
|
+
}
|
|
240
|
+
case 'mssql':
|
|
241
|
+
case 'sqlserver':
|
|
242
|
+
const sql = require('mssql');
|
|
243
|
+
const request = this.pool.request();
|
|
244
|
+
// For parameterized queries, use proper SQL Server parameter syntax
|
|
245
|
+
// If params is an array, bind them as @p0, @p1, etc.
|
|
246
|
+
if (Array.isArray(params) && params.length > 0) {
|
|
247
|
+
params.forEach((param, index) => {
|
|
248
|
+
request.input(`p${index}`, param);
|
|
249
|
+
});
|
|
250
|
+
// Replace ? with @p0, @p1, etc. in query
|
|
251
|
+
let paramIndex = 0;
|
|
252
|
+
const modifiedQuery = query.replace(/\?/g, () => `@p${paramIndex++}`);
|
|
253
|
+
const result = await request.query(modifiedQuery);
|
|
254
|
+
return result.recordset;
|
|
255
|
+
} else {
|
|
256
|
+
const result = await request.query(query);
|
|
257
|
+
return result.recordset;
|
|
258
|
+
}
|
|
116
259
|
default:
|
|
117
260
|
throw new Error(`Unsupported database type: ${this.type}`);
|
|
118
261
|
}
|
|
@@ -127,7 +270,11 @@ class DatabasePool {
|
|
|
127
270
|
await this.connect();
|
|
128
271
|
}
|
|
129
272
|
|
|
130
|
-
if (this.type === 'mongodb') {
|
|
273
|
+
if (this.type === 'mongodb' || this.type === 'sqlite' || this.type === 'sqlite3') {
|
|
274
|
+
return this.pool;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (this.type === 'mssql' || this.type === 'sqlserver') {
|
|
131
278
|
return this.pool;
|
|
132
279
|
}
|
|
133
280
|
|
|
@@ -143,6 +290,9 @@ class DatabasePool {
|
|
|
143
290
|
await this.pool.end();
|
|
144
291
|
} else if (this.pool.close) {
|
|
145
292
|
await this.pool.close();
|
|
293
|
+
} else if (typeof this.pool.close === 'function') {
|
|
294
|
+
// SQLite better-sqlite3
|
|
295
|
+
this.pool.close();
|
|
146
296
|
}
|
|
147
297
|
this.pool = null;
|
|
148
298
|
}
|
|
@@ -170,6 +320,19 @@ class DatabasePool {
|
|
|
170
320
|
case 'mongodb':
|
|
171
321
|
await this.db.admin().ping();
|
|
172
322
|
return true;
|
|
323
|
+
case 'sqlite':
|
|
324
|
+
case 'sqlite3':
|
|
325
|
+
// SQLite ping - just check if database is accessible
|
|
326
|
+
if (this.pool.prepare) {
|
|
327
|
+
this.pool.prepare('SELECT 1').get();
|
|
328
|
+
} else {
|
|
329
|
+
await this.pool.get('SELECT 1');
|
|
330
|
+
}
|
|
331
|
+
return true;
|
|
332
|
+
case 'mssql':
|
|
333
|
+
case 'sqlserver':
|
|
334
|
+
await this.pool.request().query('SELECT 1');
|
|
335
|
+
return true;
|
|
173
336
|
default:
|
|
174
337
|
return false;
|
|
175
338
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -537,7 +537,7 @@ export interface SSEServer {
|
|
|
537
537
|
}
|
|
538
538
|
|
|
539
539
|
export interface DatabasePoolOptions {
|
|
540
|
-
type?: 'postgres' | 'postgresql' | 'mysql' | 'mariadb' | 'mongodb';
|
|
540
|
+
type?: 'postgres' | 'postgresql' | 'mysql' | 'mariadb' | 'mongodb' | 'sqlite' | 'sqlite3' | 'mssql' | 'sqlserver';
|
|
541
541
|
connectionString?: string;
|
|
542
542
|
maxConnections?: number;
|
|
543
543
|
minConnections?: number;
|