navis.js 5.5.1 → 5.6.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 +157 -4
- package/examples/query-builder-demo.js +386 -0
- package/examples/query-builder-demo.ts +318 -0
- package/package.json +49 -49
- package/src/db/db-pool.js +24 -0
- package/src/db/mongodb-query-builder.js +512 -0
- package/src/db/query-builder.js +642 -0
- package/src/index.js +3 -1
- package/types/index.d.ts +72 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A lightweight, serverless-first, microservice API framework designed for AWS Lambda and Node.js.
|
|
4
4
|
|
|
5
5
|
**Author:** Syed Imran Ali
|
|
6
|
-
**Version:** 5.
|
|
6
|
+
**Version:** 5.6.0
|
|
7
7
|
**License:** MIT
|
|
8
8
|
|
|
9
9
|
## Philosophy
|
|
@@ -185,11 +185,18 @@ navis metrics
|
|
|
185
185
|
- ✅ **GraphQL schema builder** - Schema definition helpers
|
|
186
186
|
- ✅ **GraphQL middleware** - Easy integration with Navis.js routes
|
|
187
187
|
|
|
188
|
-
### v5.5
|
|
188
|
+
### v5.5 ✅
|
|
189
189
|
- ✅ **Extended database adapters** - SQLite and SQL Server support
|
|
190
190
|
- ✅ **Enhanced database pool** - Support for 5 database types (PostgreSQL, MySQL, MongoDB, SQLite, SQL Server)
|
|
191
191
|
- ✅ **Improved connection handling** - Better error handling and connection management
|
|
192
192
|
|
|
193
|
+
### v5.6 (Current)
|
|
194
|
+
- ✅ **Advanced query builders** - Fluent SQL query builder for all SQL databases
|
|
195
|
+
- ✅ **MongoDB query builder** - Fluent MongoDB query builder with aggregation support
|
|
196
|
+
- ✅ **Type-safe queries** - Full TypeScript support for query builders
|
|
197
|
+
- ✅ **Complex queries** - Support for JOINs, nested WHERE conditions, GROUP BY, HAVING, ORDER BY
|
|
198
|
+
- ✅ **Database-agnostic** - Automatic SQL dialect handling (PostgreSQL, MySQL, SQLite, SQL Server)
|
|
199
|
+
|
|
193
200
|
## API Reference
|
|
194
201
|
|
|
195
202
|
### NavisApp
|
|
@@ -617,6 +624,147 @@ app.get('/sqlite/users', async (req, res) => {
|
|
|
617
624
|
|
|
618
625
|
See `examples/database-adapters-demo.js` and `examples/database-adapters-demo.ts` for complete examples.
|
|
619
626
|
|
|
627
|
+
### Advanced Query Builders (v5.6)
|
|
628
|
+
|
|
629
|
+
**JavaScript Example:**
|
|
630
|
+
```javascript
|
|
631
|
+
const { NavisApp, createPool, queryBuilder, mongoQueryBuilder, response } = require('navis.js');
|
|
632
|
+
|
|
633
|
+
const app = new NavisApp();
|
|
634
|
+
|
|
635
|
+
// SQL Query Builder
|
|
636
|
+
app.get('/users', async (req, res) => {
|
|
637
|
+
const db = createPool({
|
|
638
|
+
type: 'postgres',
|
|
639
|
+
connectionString: process.env.DATABASE_URL,
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
await db.connect();
|
|
643
|
+
|
|
644
|
+
// Fluent query builder
|
|
645
|
+
const users = await queryBuilder(db, 'users')
|
|
646
|
+
.select(['id', 'name', 'email'])
|
|
647
|
+
.where('status', '=', 'active')
|
|
648
|
+
.where('age', '>', 18)
|
|
649
|
+
.whereIn('role', ['user', 'admin'])
|
|
650
|
+
.orderBy('name', 'ASC')
|
|
651
|
+
.limit(10)
|
|
652
|
+
.execute();
|
|
653
|
+
|
|
654
|
+
await db.close();
|
|
655
|
+
response.success(res, { users });
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// Complex WHERE with nested conditions
|
|
659
|
+
app.get('/products', async (req, res) => {
|
|
660
|
+
const db = createPool({ type: 'sqlite', connectionString: ':memory:' });
|
|
661
|
+
await db.connect();
|
|
662
|
+
|
|
663
|
+
const products = await queryBuilder(db, 'products')
|
|
664
|
+
.select('*')
|
|
665
|
+
.where((qb) => {
|
|
666
|
+
qb.where('category', '=', 'Electronics')
|
|
667
|
+
.orWhere('price', '<', 50);
|
|
668
|
+
})
|
|
669
|
+
.where('in_stock', '>', 0)
|
|
670
|
+
.groupBy('category')
|
|
671
|
+
.having('COUNT(*)', '>', 5)
|
|
672
|
+
.orderBy('price', 'DESC')
|
|
673
|
+
.execute();
|
|
674
|
+
|
|
675
|
+
await db.close();
|
|
676
|
+
response.success(res, { products });
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// INSERT, UPDATE, DELETE
|
|
680
|
+
app.post('/users', async (req, res) => {
|
|
681
|
+
const db = createPool({ type: 'postgres', connectionString: process.env.DATABASE_URL });
|
|
682
|
+
await db.connect();
|
|
683
|
+
|
|
684
|
+
const result = await queryBuilder(db)
|
|
685
|
+
.insert('users', {
|
|
686
|
+
name: req.body.name,
|
|
687
|
+
email: req.body.email,
|
|
688
|
+
age: req.body.age,
|
|
689
|
+
})
|
|
690
|
+
.execute();
|
|
691
|
+
|
|
692
|
+
await db.close();
|
|
693
|
+
response.success(res, { id: result.insertId });
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
// MongoDB Query Builder
|
|
697
|
+
app.get('/mongo/users', async (req, res) => {
|
|
698
|
+
const db = createPool({
|
|
699
|
+
type: 'mongodb',
|
|
700
|
+
connectionString: process.env.MONGODB_URI,
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
await db.connect();
|
|
704
|
+
|
|
705
|
+
const users = await mongoQueryBuilder(db, 'users')
|
|
706
|
+
.where('status', 'active')
|
|
707
|
+
.gt('age', 18)
|
|
708
|
+
.in('role', ['user', 'admin'])
|
|
709
|
+
.sortDesc('created_at')
|
|
710
|
+
.limit(10)
|
|
711
|
+
.find();
|
|
712
|
+
|
|
713
|
+
await db.close();
|
|
714
|
+
response.success(res, { users });
|
|
715
|
+
});
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
**TypeScript Example:**
|
|
719
|
+
```typescript
|
|
720
|
+
import { NavisApp, createPool, queryBuilder, mongoQueryBuilder, response, DatabasePool, QueryBuilder } from 'navis.js';
|
|
721
|
+
|
|
722
|
+
const app = new NavisApp();
|
|
723
|
+
|
|
724
|
+
interface User {
|
|
725
|
+
id: number;
|
|
726
|
+
name: string;
|
|
727
|
+
email: string;
|
|
728
|
+
age: number;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
app.get('/users', async (req, res) => {
|
|
732
|
+
const db: DatabasePool = createPool({
|
|
733
|
+
type: 'postgres',
|
|
734
|
+
connectionString: process.env.DATABASE_URL!,
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
await db.connect();
|
|
738
|
+
|
|
739
|
+
const users = await queryBuilder(db, 'users')
|
|
740
|
+
.select(['id', 'name', 'email'])
|
|
741
|
+
.where('status', '=', 'active')
|
|
742
|
+
.where((qb: QueryBuilder) => {
|
|
743
|
+
qb.where('age', '>', 18)
|
|
744
|
+
.orWhere('role', '=', 'admin');
|
|
745
|
+
})
|
|
746
|
+
.orderBy('name', 'ASC')
|
|
747
|
+
.limit(10)
|
|
748
|
+
.execute() as User[];
|
|
749
|
+
|
|
750
|
+
await db.close();
|
|
751
|
+
response.success(res, { users });
|
|
752
|
+
});
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
**Query Builder Features:**
|
|
756
|
+
- ✅ **SELECT** - Fluent SELECT queries with WHERE, JOIN, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET
|
|
757
|
+
- ✅ **INSERT** - Type-safe INSERT operations
|
|
758
|
+
- ✅ **UPDATE** - UPDATE with WHERE conditions
|
|
759
|
+
- ✅ **DELETE** - DELETE with WHERE conditions
|
|
760
|
+
- ✅ **JOINs** - LEFT, RIGHT, INNER, FULL JOIN support
|
|
761
|
+
- ✅ **Nested conditions** - Complex WHERE with callbacks
|
|
762
|
+
- ✅ **Database-specific** - Automatic SQL dialect handling
|
|
763
|
+
- ✅ **MongoDB** - Full MongoDB query builder with aggregation pipeline
|
|
764
|
+
- ✅ **TypeScript** - Full type definitions and IntelliSense support
|
|
765
|
+
|
|
766
|
+
See `examples/query-builder-demo.js` and `examples/query-builder-demo.ts` for complete examples.
|
|
767
|
+
|
|
620
768
|
## Examples
|
|
621
769
|
|
|
622
770
|
See the `examples/` directory:
|
|
@@ -637,6 +785,8 @@ See the `examples/` directory:
|
|
|
637
785
|
- `graphql-demo.ts` - GraphQL server example with TypeScript types (v5.4) - TypeScript
|
|
638
786
|
- `database-adapters-demo.js` - Extended database adapters example (v5.5) - JavaScript
|
|
639
787
|
- `database-adapters-demo.ts` - Extended database adapters example (v5.5) - TypeScript
|
|
788
|
+
- `query-builder-demo.js` - Advanced query builder example (v5.6) - JavaScript
|
|
789
|
+
- `query-builder-demo.ts` - Advanced query builder example (v5.6) - TypeScript
|
|
640
790
|
- `service-client-demo.js` - ServiceClient usage example
|
|
641
791
|
|
|
642
792
|
## Roadmap
|
|
@@ -668,7 +818,9 @@ TypeScript support: Full type definitions, type-safe API, IntelliSense
|
|
|
668
818
|
### v5.4 ✅
|
|
669
819
|
GraphQL support: Lightweight GraphQL server, queries, mutations, resolvers, schema builder
|
|
670
820
|
|
|
671
|
-
### v5.5 ✅
|
|
821
|
+
### v5.5 ✅
|
|
822
|
+
|
|
823
|
+
### v5.6 (Current)
|
|
672
824
|
Extended database adapters: SQLite and SQL Server support, enhanced connection pooling
|
|
673
825
|
|
|
674
826
|
## What's Next?
|
|
@@ -676,8 +828,9 @@ Extended database adapters: SQLite and SQL Server support, enhanced connection p
|
|
|
676
828
|
Future versions may include:
|
|
677
829
|
- gRPC integration
|
|
678
830
|
- Advanced caching strategies
|
|
679
|
-
- Advanced query builders
|
|
680
831
|
- Enhanced monitoring and alerting
|
|
832
|
+
- Database migrations
|
|
833
|
+
- ORM-like features
|
|
681
834
|
|
|
682
835
|
## Documentation
|
|
683
836
|
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced Query Builder Demo - Navis.js
|
|
3
|
+
* Demonstrates fluent query builder for SQL and MongoDB (v5.6)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { NavisApp, createPool, queryBuilder, mongoQueryBuilder, response } = require('../src/index');
|
|
7
|
+
|
|
8
|
+
const app = new NavisApp();
|
|
9
|
+
|
|
10
|
+
// ============================================
|
|
11
|
+
// SQL Query Builder Examples
|
|
12
|
+
// ============================================
|
|
13
|
+
|
|
14
|
+
// Example 1: SELECT with WHERE
|
|
15
|
+
app.get('/sql/select', async (req, res) => {
|
|
16
|
+
try {
|
|
17
|
+
const db = createPool({
|
|
18
|
+
type: 'sqlite',
|
|
19
|
+
connectionString: ':memory:',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await db.connect();
|
|
23
|
+
|
|
24
|
+
// Create table
|
|
25
|
+
await db.query(`
|
|
26
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
27
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
28
|
+
name TEXT NOT NULL,
|
|
29
|
+
email TEXT NOT NULL,
|
|
30
|
+
age INTEGER,
|
|
31
|
+
status TEXT DEFAULT 'active'
|
|
32
|
+
)
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
// Insert sample data
|
|
36
|
+
await db.query('INSERT INTO users (name, email, age, status) VALUES (?, ?, ?, ?)', ['Alice', 'alice@example.com', 30, 'active']);
|
|
37
|
+
await db.query('INSERT INTO users (name, email, age, status) VALUES (?, ?, ?, ?)', ['Bob', 'bob@example.com', 25, 'active']);
|
|
38
|
+
await db.query('INSERT INTO users (name, email, age, status) VALUES (?, ?, ?, ?)', ['Charlie', 'charlie@example.com', 35, 'inactive']);
|
|
39
|
+
|
|
40
|
+
// Query using query builder
|
|
41
|
+
const users = await queryBuilder(db, 'users')
|
|
42
|
+
.select(['id', 'name', 'email', 'age'])
|
|
43
|
+
.where('status', '=', 'active')
|
|
44
|
+
.where('age', '>', 20)
|
|
45
|
+
.orderBy('age', 'DESC')
|
|
46
|
+
.limit(10)
|
|
47
|
+
.execute();
|
|
48
|
+
|
|
49
|
+
await db.close();
|
|
50
|
+
|
|
51
|
+
response.success(res, {
|
|
52
|
+
method: 'SELECT with WHERE',
|
|
53
|
+
users,
|
|
54
|
+
});
|
|
55
|
+
} catch (error) {
|
|
56
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Example 2: Complex WHERE conditions
|
|
61
|
+
app.get('/sql/where-complex', async (req, res) => {
|
|
62
|
+
try {
|
|
63
|
+
const db = createPool({
|
|
64
|
+
type: 'sqlite',
|
|
65
|
+
connectionString: ':memory:',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await db.connect();
|
|
69
|
+
|
|
70
|
+
await db.query(`
|
|
71
|
+
CREATE TABLE IF NOT EXISTS products (
|
|
72
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
73
|
+
name TEXT NOT NULL,
|
|
74
|
+
price REAL,
|
|
75
|
+
category TEXT,
|
|
76
|
+
in_stock INTEGER
|
|
77
|
+
)
|
|
78
|
+
`);
|
|
79
|
+
|
|
80
|
+
await db.query('INSERT INTO products (name, price, category, in_stock) VALUES (?, ?, ?, ?)', ['Laptop', 999.99, 'Electronics', 10]);
|
|
81
|
+
await db.query('INSERT INTO products (name, price, category, in_stock) VALUES (?, ?, ?, ?)', ['Phone', 599.99, 'Electronics', 5]);
|
|
82
|
+
await db.query('INSERT INTO products (name, price, category, in_stock) VALUES (?, ?, ?, ?)', ['Book', 19.99, 'Books', 0]);
|
|
83
|
+
|
|
84
|
+
// Complex WHERE with nested conditions
|
|
85
|
+
const products = await queryBuilder(db, 'products')
|
|
86
|
+
.select('*')
|
|
87
|
+
.where((qb) => {
|
|
88
|
+
qb.where('category', '=', 'Electronics')
|
|
89
|
+
.orWhere('price', '<', 50);
|
|
90
|
+
})
|
|
91
|
+
.where('in_stock', '>', 0)
|
|
92
|
+
.whereIn('category', ['Electronics', 'Books'])
|
|
93
|
+
.orderBy('price', 'ASC')
|
|
94
|
+
.execute();
|
|
95
|
+
|
|
96
|
+
await db.close();
|
|
97
|
+
|
|
98
|
+
response.success(res, {
|
|
99
|
+
method: 'Complex WHERE conditions',
|
|
100
|
+
products,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Example 3: INSERT
|
|
108
|
+
app.get('/sql/insert', async (req, res) => {
|
|
109
|
+
try {
|
|
110
|
+
const db = createPool({
|
|
111
|
+
type: 'sqlite',
|
|
112
|
+
connectionString: ':memory:',
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await db.connect();
|
|
116
|
+
|
|
117
|
+
await db.query(`
|
|
118
|
+
CREATE TABLE IF NOT EXISTS posts (
|
|
119
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
120
|
+
title TEXT NOT NULL,
|
|
121
|
+
content TEXT,
|
|
122
|
+
author_id INTEGER,
|
|
123
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
124
|
+
)
|
|
125
|
+
`);
|
|
126
|
+
|
|
127
|
+
// Insert using query builder
|
|
128
|
+
const result = await queryBuilder(db)
|
|
129
|
+
.insert('posts', {
|
|
130
|
+
title: 'My First Post',
|
|
131
|
+
content: 'This is the content of my first post',
|
|
132
|
+
author_id: 1,
|
|
133
|
+
})
|
|
134
|
+
.execute();
|
|
135
|
+
|
|
136
|
+
const posts = await queryBuilder(db, 'posts').select('*').execute();
|
|
137
|
+
|
|
138
|
+
await db.close();
|
|
139
|
+
|
|
140
|
+
response.success(res, {
|
|
141
|
+
method: 'INSERT',
|
|
142
|
+
inserted: result,
|
|
143
|
+
posts,
|
|
144
|
+
});
|
|
145
|
+
} catch (error) {
|
|
146
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Example 4: UPDATE
|
|
151
|
+
app.get('/sql/update', async (req, res) => {
|
|
152
|
+
try {
|
|
153
|
+
const db = createPool({
|
|
154
|
+
type: 'sqlite',
|
|
155
|
+
connectionString: ':memory:',
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await db.connect();
|
|
159
|
+
|
|
160
|
+
await db.query(`
|
|
161
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
162
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
163
|
+
name TEXT NOT NULL,
|
|
164
|
+
email TEXT NOT NULL,
|
|
165
|
+
status TEXT DEFAULT 'active'
|
|
166
|
+
)
|
|
167
|
+
`);
|
|
168
|
+
|
|
169
|
+
await db.query('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com']);
|
|
170
|
+
|
|
171
|
+
// Update using query builder
|
|
172
|
+
await queryBuilder(db)
|
|
173
|
+
.update('users', {
|
|
174
|
+
status: 'inactive',
|
|
175
|
+
})
|
|
176
|
+
.where('email', '=', 'john@example.com')
|
|
177
|
+
.execute();
|
|
178
|
+
|
|
179
|
+
const users = await queryBuilder(db, 'users').select('*').execute();
|
|
180
|
+
|
|
181
|
+
await db.close();
|
|
182
|
+
|
|
183
|
+
response.success(res, {
|
|
184
|
+
method: 'UPDATE',
|
|
185
|
+
users,
|
|
186
|
+
});
|
|
187
|
+
} catch (error) {
|
|
188
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Example 5: DELETE
|
|
193
|
+
app.get('/sql/delete', async (req, res) => {
|
|
194
|
+
try {
|
|
195
|
+
const db = createPool({
|
|
196
|
+
type: 'sqlite',
|
|
197
|
+
connectionString: ':memory:',
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
await db.connect();
|
|
201
|
+
|
|
202
|
+
await db.query(`
|
|
203
|
+
CREATE TABLE IF NOT EXISTS comments (
|
|
204
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
205
|
+
text TEXT NOT NULL,
|
|
206
|
+
user_id INTEGER
|
|
207
|
+
)
|
|
208
|
+
`);
|
|
209
|
+
|
|
210
|
+
await db.query('INSERT INTO comments (text, user_id) VALUES (?, ?)', ['Comment 1', 1]);
|
|
211
|
+
await db.query('INSERT INTO comments (text, user_id) VALUES (?, ?)', ['Comment 2', 2]);
|
|
212
|
+
|
|
213
|
+
// Delete using query builder
|
|
214
|
+
await queryBuilder(db)
|
|
215
|
+
.delete('comments')
|
|
216
|
+
.where('user_id', '=', 1)
|
|
217
|
+
.execute();
|
|
218
|
+
|
|
219
|
+
const comments = await queryBuilder(db, 'comments').select('*').execute();
|
|
220
|
+
|
|
221
|
+
await db.close();
|
|
222
|
+
|
|
223
|
+
response.success(res, {
|
|
224
|
+
method: 'DELETE',
|
|
225
|
+
comments,
|
|
226
|
+
});
|
|
227
|
+
} catch (error) {
|
|
228
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Example 6: JOIN
|
|
233
|
+
app.get('/sql/join', async (req, res) => {
|
|
234
|
+
try {
|
|
235
|
+
const db = createPool({
|
|
236
|
+
type: 'sqlite',
|
|
237
|
+
connectionString: ':memory:',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await db.connect();
|
|
241
|
+
|
|
242
|
+
await db.query(`
|
|
243
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
244
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
245
|
+
name TEXT NOT NULL
|
|
246
|
+
)
|
|
247
|
+
`);
|
|
248
|
+
|
|
249
|
+
await db.query(`
|
|
250
|
+
CREATE TABLE IF NOT EXISTS orders (
|
|
251
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
252
|
+
user_id INTEGER,
|
|
253
|
+
total REAL,
|
|
254
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
255
|
+
)
|
|
256
|
+
`);
|
|
257
|
+
|
|
258
|
+
await db.query('INSERT INTO users (name) VALUES (?)', ['Alice']);
|
|
259
|
+
await db.query('INSERT INTO orders (user_id, total) VALUES (?, ?)', [1, 99.99]);
|
|
260
|
+
|
|
261
|
+
// JOIN using query builder
|
|
262
|
+
const results = await queryBuilder(db)
|
|
263
|
+
.select(['users.name', 'orders.total'])
|
|
264
|
+
.from('users')
|
|
265
|
+
.leftJoin('orders', 'users.id', '=', 'orders.user_id')
|
|
266
|
+
.execute();
|
|
267
|
+
|
|
268
|
+
await db.close();
|
|
269
|
+
|
|
270
|
+
response.success(res, {
|
|
271
|
+
method: 'JOIN',
|
|
272
|
+
results,
|
|
273
|
+
});
|
|
274
|
+
} catch (error) {
|
|
275
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// ============================================
|
|
280
|
+
// MongoDB Query Builder Examples
|
|
281
|
+
// ============================================
|
|
282
|
+
|
|
283
|
+
// Example 7: MongoDB FIND
|
|
284
|
+
app.get('/mongo/find', async (req, res) => {
|
|
285
|
+
try {
|
|
286
|
+
const db = createPool({
|
|
287
|
+
type: 'mongodb',
|
|
288
|
+
connectionString: process.env.MONGODB_URI || 'mongodb://localhost:27017/test',
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await db.connect();
|
|
292
|
+
|
|
293
|
+
const collection = db.db.collection('users');
|
|
294
|
+
|
|
295
|
+
// Insert sample data
|
|
296
|
+
await collection.insertMany([
|
|
297
|
+
{ name: 'Alice', age: 30, status: 'active' },
|
|
298
|
+
{ name: 'Bob', age: 25, status: 'active' },
|
|
299
|
+
{ name: 'Charlie', age: 35, status: 'inactive' },
|
|
300
|
+
]);
|
|
301
|
+
|
|
302
|
+
// Query using MongoDB query builder
|
|
303
|
+
const users = await mongoQueryBuilder(db, 'users')
|
|
304
|
+
.where('status', 'active')
|
|
305
|
+
.gt('age', 20)
|
|
306
|
+
.sortDesc('age')
|
|
307
|
+
.limit(10)
|
|
308
|
+
.find();
|
|
309
|
+
|
|
310
|
+
await db.close();
|
|
311
|
+
|
|
312
|
+
response.success(res, {
|
|
313
|
+
method: 'MongoDB FIND',
|
|
314
|
+
users,
|
|
315
|
+
});
|
|
316
|
+
} catch (error) {
|
|
317
|
+
response.error(res, `Error: ${error.message}`, 500);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Example 8: MongoDB INSERT
|
|
322
|
+
app.get('/mongo/insert', async (req, res) => {
|
|
323
|
+
try {
|
|
324
|
+
const db = createPool({
|
|
325
|
+
type: 'mongodb',
|
|
326
|
+
connectionString: process.env.MONGODB_URI || 'mongodb://localhost:27017/test',
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
await db.connect();
|
|
330
|
+
|
|
331
|
+
// Insert using MongoDB query builder
|
|
332
|
+
const result = await mongoQueryBuilder(db, 'posts')
|
|
333
|
+
.insert({
|
|
334
|
+
title: 'My First Post',
|
|
335
|
+
content: 'This is the content',
|
|
336
|
+
author: 'John',
|
|
337
|
+
})
|
|
338
|
+
.execute();
|
|
339
|
+
|
|
340
|
+
await db.close();
|
|
341
|
+
|
|
342
|
+
response.success(res, {
|
|
343
|
+
method: 'MongoDB INSERT',
|
|
344
|
+
result,
|
|
345
|
+
});
|
|
346
|
+
} catch (error) {
|
|
347
|
+
response.success(res, {
|
|
348
|
+
method: 'MongoDB INSERT',
|
|
349
|
+
note: 'MongoDB connection required. Install mongodb package and set MONGODB_URI environment variable.',
|
|
350
|
+
error: error.message,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Health check
|
|
356
|
+
app.get('/health', (req, res) => {
|
|
357
|
+
response.success(res, {
|
|
358
|
+
status: 'ok',
|
|
359
|
+
features: [
|
|
360
|
+
'SQL Query Builder (SELECT, INSERT, UPDATE, DELETE)',
|
|
361
|
+
'MongoDB Query Builder (FIND, INSERT, UPDATE, DELETE)',
|
|
362
|
+
'Complex WHERE conditions',
|
|
363
|
+
'JOIN support',
|
|
364
|
+
'Type-safe query building',
|
|
365
|
+
],
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Start server
|
|
370
|
+
const PORT = process.env.PORT || 3000;
|
|
371
|
+
app.listen(PORT, () => {
|
|
372
|
+
console.log(`🚀 Navis.js Query Builder Demo running on http://localhost:${PORT}`);
|
|
373
|
+
console.log('\n📊 Available endpoints:');
|
|
374
|
+
console.log(` GET http://localhost:${PORT}/sql/select - SELECT with WHERE`);
|
|
375
|
+
console.log(` GET http://localhost:${PORT}/sql/where-complex - Complex WHERE conditions`);
|
|
376
|
+
console.log(` GET http://localhost:${PORT}/sql/insert - INSERT example`);
|
|
377
|
+
console.log(` GET http://localhost:${PORT}/sql/update - UPDATE example`);
|
|
378
|
+
console.log(` GET http://localhost:${PORT}/sql/delete - DELETE example`);
|
|
379
|
+
console.log(` GET http://localhost:${PORT}/sql/join - JOIN example`);
|
|
380
|
+
console.log(` GET http://localhost:${PORT}/mongo/find - MongoDB FIND`);
|
|
381
|
+
console.log(` GET http://localhost:${PORT}/mongo/insert - MongoDB INSERT`);
|
|
382
|
+
console.log(` GET http://localhost:${PORT}/health - Health check`);
|
|
383
|
+
console.log('\n💡 Note: SQLite examples use in-memory database (no setup required)');
|
|
384
|
+
console.log('💡 MongoDB examples require mongodb package and MONGODB_URI environment variable');
|
|
385
|
+
});
|
|
386
|
+
|