navis.js 5.4.0 → 5.5.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 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 (Current)
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
@@ -437,6 +442,7 @@ exports.handler = async (event, context) => {
437
442
 
438
443
  ### GraphQL Support (v5.4)
439
444
 
445
+ **JavaScript Example:**
440
446
  ```javascript
441
447
  const { NavisApp, graphql, createResolver } = require('navis.js');
442
448
 
@@ -478,6 +484,56 @@ app.use(graphql({
478
484
  app.listen(3000);
479
485
  ```
480
486
 
487
+ **TypeScript Example:**
488
+ ```typescript
489
+ import {
490
+ NavisApp,
491
+ graphql,
492
+ createResolver,
493
+ GraphQLContext,
494
+ } from 'navis.js';
495
+
496
+ interface User {
497
+ id: string;
498
+ name: string;
499
+ email: string;
500
+ }
501
+
502
+ const app = new NavisApp();
503
+
504
+ // Define resolvers with TypeScript types
505
+ const resolvers = {
506
+ Query: {
507
+ users: createResolver<User[]>(async (variables, context: GraphQLContext) => {
508
+ return [{ id: '1', name: 'Alice', email: 'alice@example.com' }];
509
+ }),
510
+
511
+ user: createResolver<User | null>(async (variables, context: GraphQLContext) => {
512
+ const { id } = variables as { id: string };
513
+ return { id, name: 'Alice', email: 'alice@example.com' };
514
+ }),
515
+ },
516
+
517
+ Mutation: {
518
+ createUser: createResolver<User>(async (variables, context: GraphQLContext) => {
519
+ const { name, email } = variables as { name: string; email: string };
520
+ return { id: '3', name, email };
521
+ }),
522
+ },
523
+ };
524
+
525
+ // Add GraphQL middleware
526
+ app.use(graphql({
527
+ path: '/graphql',
528
+ resolvers,
529
+ context: (req) => ({
530
+ userId: (req.headers['x-user-id'] as string) || null,
531
+ }),
532
+ }));
533
+
534
+ app.listen(3000);
535
+ ```
536
+
481
537
  **GraphQL Query Example:**
482
538
  ```bash
483
539
  curl -X POST http://localhost:3000/graphql \
@@ -494,6 +550,73 @@ curl -X POST http://localhost:3000/graphql \
494
550
 
495
551
  See `examples/graphql-demo.js` for a complete GraphQL example.
496
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
+
497
620
  ## Examples
498
621
 
499
622
  See the `examples/` directory:
@@ -510,7 +633,10 @@ See the `examples/` directory:
510
633
  - `v5-features-demo.js` - v5 features demonstration (caching, CORS, security, compression, health checks, etc.)
511
634
  - `v5.1-features-demo.js` - v5.1 features demonstration (Swagger, versioning, upload, testing)
512
635
  - `v5.2-features-demo.js` - v5.2 features demonstration (WebSocket, SSE, database)
513
- - `graphql-demo.js` - GraphQL server example with queries and mutations (v5.4)
636
+ - `graphql-demo.js` - GraphQL server example with queries and mutations (v5.4) - JavaScript
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
514
640
  - `service-client-demo.js` - ServiceClient usage example
515
641
 
516
642
  ## Roadmap
@@ -539,15 +665,18 @@ Real-time features: WebSocket, Server-Sent Events, database integration
539
665
  ### v5.3 ✅
540
666
  TypeScript support: Full type definitions, type-safe API, IntelliSense
541
667
 
542
- ### v5.4 ✅ (Current)
668
+ ### v5.4 ✅
543
669
  GraphQL support: Lightweight GraphQL server, queries, mutations, resolvers, schema builder
544
670
 
671
+ ### v5.5 ✅ (Current)
672
+ Extended database adapters: SQLite and SQL Server support, enhanced connection pooling
673
+
545
674
  ## What's Next?
546
675
 
547
676
  Future versions may include:
548
677
  - gRPC integration
549
678
  - Advanced caching strategies
550
- - More database adapters
679
+ - Advanced query builders
551
680
  - Enhanced monitoring and alerting
552
681
 
553
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
+
@@ -0,0 +1,158 @@
1
+ /**
2
+ * GraphQL Demo - Navis.js (TypeScript)
3
+ * Demonstrates GraphQL query and mutation support with TypeScript
4
+ */
5
+
6
+ import {
7
+ NavisApp,
8
+ graphql,
9
+ createResolver,
10
+ GraphQLResolver,
11
+ GraphQLContext,
12
+ response,
13
+ } from '../src/index';
14
+
15
+ interface User {
16
+ id: string;
17
+ name: string;
18
+ email: string;
19
+ age?: number;
20
+ }
21
+
22
+ interface Post {
23
+ id: string;
24
+ title: string;
25
+ content: string;
26
+ authorId: string;
27
+ }
28
+
29
+ // Sample data store
30
+ const users: User[] = [
31
+ { id: '1', name: 'Alice', email: 'alice@example.com', age: 30 },
32
+ { id: '2', name: 'Bob', email: 'bob@example.com', age: 25 },
33
+ { id: '3', name: 'Charlie', email: 'charlie@example.com', age: 35 },
34
+ ];
35
+
36
+ const posts: Post[] = [
37
+ { id: '1', title: 'First Post', content: 'Content 1', authorId: '1' },
38
+ { id: '2', title: 'Second Post', content: 'Content 2', authorId: '2' },
39
+ { id: '3', title: 'Third Post', content: 'Content 3', authorId: '1' },
40
+ ];
41
+
42
+ // Define resolvers with TypeScript types
43
+ const resolvers = {
44
+ Query: {
45
+ // Get all users
46
+ users: createResolver(async (variables, context: GraphQLContext): Promise<User[]> => {
47
+ return users;
48
+ }),
49
+
50
+ // Get user by ID
51
+ user: createResolver(async (variables, context: GraphQLContext): Promise<User | null> => {
52
+ const { id } = variables as { id: string };
53
+ const user = users.find(u => u.id === id);
54
+ if (!user) {
55
+ throw new Error(`User with id ${id} not found`);
56
+ }
57
+ return user;
58
+ }),
59
+
60
+ // Get all posts
61
+ posts: createResolver(async (variables, context: GraphQLContext): Promise<Post[]> => {
62
+ return posts;
63
+ }),
64
+
65
+ // Get posts by author
66
+ postsByAuthor: createResolver(async (variables, context: GraphQLContext): Promise<Post[]> => {
67
+ const { authorId } = variables as { authorId: string };
68
+ return posts.filter(p => p.authorId === authorId);
69
+ }),
70
+ },
71
+
72
+ Mutation: {
73
+ // Create user
74
+ createUser: createResolver(async (variables, context: GraphQLContext): Promise<User> => {
75
+ const { name, email, age } = variables as { name: string; email: string; age?: number };
76
+ const newUser: User = {
77
+ id: String(users.length + 1),
78
+ name,
79
+ email,
80
+ age: age || 0,
81
+ };
82
+ users.push(newUser);
83
+ return newUser;
84
+ }),
85
+
86
+ // Update user
87
+ updateUser: createResolver(async (variables, context: GraphQLContext): Promise<User> => {
88
+ const { id, name, email, age } = variables as {
89
+ id: string;
90
+ name?: string;
91
+ email?: string;
92
+ age?: number;
93
+ };
94
+ const user = users.find(u => u.id === id);
95
+ if (!user) {
96
+ throw new Error(`User with id ${id} not found`);
97
+ }
98
+ if (name) user.name = name;
99
+ if (email) user.email = email;
100
+ if (age !== undefined) user.age = age;
101
+ return user;
102
+ }),
103
+
104
+ // Delete user
105
+ deleteUser: createResolver(async (variables, context: GraphQLContext): Promise<User> => {
106
+ const { id } = variables as { id: string };
107
+ const index = users.findIndex(u => u.id === id);
108
+ if (index === -1) {
109
+ throw new Error(`User with id ${id} not found`);
110
+ }
111
+ const deleted = users.splice(index, 1)[0];
112
+ return deleted;
113
+ }),
114
+ },
115
+ };
116
+
117
+ const app = new NavisApp();
118
+
119
+ // Add GraphQL middleware with TypeScript types
120
+ app.use(
121
+ graphql({
122
+ path: '/graphql',
123
+ resolvers,
124
+ context: (req) => {
125
+ // Add custom context with TypeScript types
126
+ return {
127
+ userId: (req.headers['x-user-id'] as string) || null,
128
+ timestamp: new Date().toISOString(),
129
+ };
130
+ },
131
+ })
132
+ );
133
+
134
+ // Health check endpoint
135
+ app.get('/health', (req, res) => {
136
+ response.success(res, { status: 'ok', graphql: true, typescript: true });
137
+ });
138
+
139
+ // Start server
140
+ const PORT = process.env.PORT || 3000;
141
+ app.listen(PORT, () => {
142
+ console.log(`🚀 Navis.js GraphQL server (TypeScript) running on http://localhost:${PORT}`);
143
+ console.log(`📊 GraphQL endpoint: http://localhost:${PORT}/graphql`);
144
+ console.log('\n📝 Example queries:');
145
+ console.log('\n1. Get all users:');
146
+ console.log(`curl -X POST http://localhost:${PORT}/graphql \\`);
147
+ console.log(` -H "Content-Type: application/json" \\`);
148
+ console.log(` -d '{"query": "query { users { id name email age } }"}'`);
149
+ console.log('\n2. Get user by ID:');
150
+ console.log(`curl -X POST http://localhost:${PORT}/graphql \\`);
151
+ console.log(` -H "Content-Type: application/json" \\`);
152
+ console.log(` -d '{"query": "query { user(id: \\"1\\") { id name email } }"}'`);
153
+ console.log('\n3. Create user:');
154
+ console.log(`curl -X POST http://localhost:${PORT}/graphql \\`);
155
+ console.log(` -H "Content-Type: application/json" \\`);
156
+ console.log(` -d '{"query": "mutation { createUser(name: \\"Dave\\", email: \\"dave@example.com\\", age: 28) { id name email } }"}'`);
157
+ });
158
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navis.js",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "A lightweight, serverless-first, microservice API framework designed for AWS Lambda and Node.js",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
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;
@@ -807,7 +807,7 @@ export function createGraphQLServer(options?: GraphQLServerOptions): GraphQLServ
807
807
  export function graphql(options?: GraphQLServerOptions): Middleware;
808
808
  export function createSchema(): GraphQLSchema;
809
809
  export function type(name: string, definition: any): GraphQLSchema;
810
- export function createResolver(resolverFn: GraphQLResolver, options?: GraphQLResolverOptions): GraphQLResolver;
810
+ export function createResolver<T = any>(resolverFn: GraphQLResolver, options?: GraphQLResolverOptions): GraphQLResolver;
811
811
  export function fieldResolver(fieldName: string, resolverFn: GraphQLResolver): Record<string, GraphQLResolver>;
812
812
  export function combineResolvers(...resolvers: any[]): any;
813
813
  export function createAsyncResolver(resolverFn: GraphQLResolver, options?: GraphQLAsyncResolverOptions): GraphQLResolver;