@bhushanpawar/sqldb 1.0.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/LICENSE +21 -0
- package/README.md +811 -0
- package/dist/best-practice-example.d.ts +35 -0
- package/dist/best-practice-example.d.ts.map +1 -0
- package/dist/best-practice-example.js +171 -0
- package/dist/best-practice-example.js.map +1 -0
- package/dist/cache/cache-key-builder.d.ts +17 -0
- package/dist/cache/cache-key-builder.d.ts.map +1 -0
- package/dist/cache/cache-key-builder.js +100 -0
- package/dist/cache/cache-key-builder.js.map +1 -0
- package/dist/cache/cache-manager.d.ts +22 -0
- package/dist/cache/cache-manager.d.ts.map +1 -0
- package/dist/cache/cache-manager.js +124 -0
- package/dist/cache/cache-manager.js.map +1 -0
- package/dist/cache/invalidation.d.ts +15 -0
- package/dist/cache/invalidation.d.ts.map +1 -0
- package/dist/cache/invalidation.js +59 -0
- package/dist/cache/invalidation.js.map +1 -0
- package/dist/client.d.ts +40 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +146 -0
- package/dist/client.js.map +1 -0
- package/dist/connection/mariadb.d.ts +17 -0
- package/dist/connection/mariadb.d.ts.map +1 -0
- package/dist/connection/mariadb.js +116 -0
- package/dist/connection/mariadb.js.map +1 -0
- package/dist/connection/redis.d.ts +20 -0
- package/dist/connection/redis.d.ts.map +1 -0
- package/dist/connection/redis.js +168 -0
- package/dist/connection/redis.js.map +1 -0
- package/dist/demo-debug.d.ts +2 -0
- package/dist/demo-debug.d.ts.map +1 -0
- package/dist/demo-debug.js +36 -0
- package/dist/demo-debug.js.map +1 -0
- package/dist/discovery/dependency-graph.d.ts +20 -0
- package/dist/discovery/dependency-graph.d.ts.map +1 -0
- package/dist/discovery/dependency-graph.js +89 -0
- package/dist/discovery/dependency-graph.js.map +1 -0
- package/dist/discovery/relationship-parser.d.ts +10 -0
- package/dist/discovery/relationship-parser.d.ts.map +1 -0
- package/dist/discovery/relationship-parser.js +40 -0
- package/dist/discovery/relationship-parser.js.map +1 -0
- package/dist/discovery/schema-reader.d.ts +15 -0
- package/dist/discovery/schema-reader.d.ts.map +1 -0
- package/dist/discovery/schema-reader.js +82 -0
- package/dist/discovery/schema-reader.js.map +1 -0
- package/dist/hooks/hooks-manager.d.ts +22 -0
- package/dist/hooks/hooks-manager.d.ts.map +1 -0
- package/dist/hooks/hooks-manager.js +117 -0
- package/dist/hooks/hooks-manager.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/query/operations.d.ts +31 -0
- package/dist/query/operations.d.ts.map +1 -0
- package/dist/query/operations.js +204 -0
- package/dist/query/operations.js.map +1 -0
- package/dist/query/query-builder.d.ts +15 -0
- package/dist/query/query-builder.d.ts.map +1 -0
- package/dist/query/query-builder.js +169 -0
- package/dist/query/query-builder.js.map +1 -0
- package/dist/query/query-tracker.d.ts +13 -0
- package/dist/query/query-tracker.d.ts.map +1 -0
- package/dist/query/query-tracker.js +84 -0
- package/dist/query/query-tracker.js.map +1 -0
- package/dist/query/table-proxy.d.ts +11 -0
- package/dist/query/table-proxy.d.ts.map +1 -0
- package/dist/query/table-proxy.js +25 -0
- package/dist/query/table-proxy.js.map +1 -0
- package/dist/smart-cache/cache/cache-key-builder.d.ts +17 -0
- package/dist/smart-cache/cache/cache-key-builder.d.ts.map +1 -0
- package/dist/smart-cache/cache/cache-key-builder.js +100 -0
- package/dist/smart-cache/cache/cache-key-builder.js.map +1 -0
- package/dist/smart-cache/cache/cache-manager.d.ts +22 -0
- package/dist/smart-cache/cache/cache-manager.d.ts.map +1 -0
- package/dist/smart-cache/cache/cache-manager.js +124 -0
- package/dist/smart-cache/cache/cache-manager.js.map +1 -0
- package/dist/smart-cache/cache/invalidation.d.ts +15 -0
- package/dist/smart-cache/cache/invalidation.d.ts.map +1 -0
- package/dist/smart-cache/cache/invalidation.js +59 -0
- package/dist/smart-cache/cache/invalidation.js.map +1 -0
- package/dist/smart-cache/client.d.ts +36 -0
- package/dist/smart-cache/client.d.ts.map +1 -0
- package/dist/smart-cache/client.js +138 -0
- package/dist/smart-cache/client.js.map +1 -0
- package/dist/smart-cache/connection/mariadb.d.ts +14 -0
- package/dist/smart-cache/connection/mariadb.d.ts.map +1 -0
- package/dist/smart-cache/connection/mariadb.js +82 -0
- package/dist/smart-cache/connection/mariadb.js.map +1 -0
- package/dist/smart-cache/connection/redis.d.ts +20 -0
- package/dist/smart-cache/connection/redis.d.ts.map +1 -0
- package/dist/smart-cache/connection/redis.js +168 -0
- package/dist/smart-cache/connection/redis.js.map +1 -0
- package/dist/smart-cache/discovery/dependency-graph.d.ts +20 -0
- package/dist/smart-cache/discovery/dependency-graph.d.ts.map +1 -0
- package/dist/smart-cache/discovery/dependency-graph.js +89 -0
- package/dist/smart-cache/discovery/dependency-graph.js.map +1 -0
- package/dist/smart-cache/discovery/relationship-parser.d.ts +10 -0
- package/dist/smart-cache/discovery/relationship-parser.d.ts.map +1 -0
- package/dist/smart-cache/discovery/relationship-parser.js +40 -0
- package/dist/smart-cache/discovery/relationship-parser.js.map +1 -0
- package/dist/smart-cache/discovery/schema-reader.d.ts +15 -0
- package/dist/smart-cache/discovery/schema-reader.d.ts.map +1 -0
- package/dist/smart-cache/discovery/schema-reader.js +82 -0
- package/dist/smart-cache/discovery/schema-reader.js.map +1 -0
- package/dist/smart-cache/examples/basic-usage.d.ts +3 -0
- package/dist/smart-cache/examples/basic-usage.d.ts.map +1 -0
- package/dist/smart-cache/examples/basic-usage.js +105 -0
- package/dist/smart-cache/examples/basic-usage.js.map +1 -0
- package/dist/smart-cache/examples/hooks-example.d.ts +3 -0
- package/dist/smart-cache/examples/hooks-example.d.ts.map +1 -0
- package/dist/smart-cache/examples/hooks-example.js +133 -0
- package/dist/smart-cache/examples/hooks-example.js.map +1 -0
- package/dist/smart-cache/examples/relationships-example.d.ts +3 -0
- package/dist/smart-cache/examples/relationships-example.d.ts.map +1 -0
- package/dist/smart-cache/examples/relationships-example.js +88 -0
- package/dist/smart-cache/examples/relationships-example.js.map +1 -0
- package/dist/smart-cache/hooks/hooks-manager.d.ts +22 -0
- package/dist/smart-cache/hooks/hooks-manager.d.ts.map +1 -0
- package/dist/smart-cache/hooks/hooks-manager.js +117 -0
- package/dist/smart-cache/hooks/hooks-manager.js.map +1 -0
- package/dist/smart-cache/index.d.ts +19 -0
- package/dist/smart-cache/index.d.ts.map +1 -0
- package/dist/smart-cache/index.js +49 -0
- package/dist/smart-cache/index.js.map +1 -0
- package/dist/smart-cache/query/operations.d.ts +31 -0
- package/dist/smart-cache/query/operations.d.ts.map +1 -0
- package/dist/smart-cache/query/operations.js +187 -0
- package/dist/smart-cache/query/operations.js.map +1 -0
- package/dist/smart-cache/query/query-builder.d.ts +15 -0
- package/dist/smart-cache/query/query-builder.d.ts.map +1 -0
- package/dist/smart-cache/query/query-builder.js +169 -0
- package/dist/smart-cache/query/query-builder.js.map +1 -0
- package/dist/smart-cache/query/table-proxy.d.ts +11 -0
- package/dist/smart-cache/query/table-proxy.d.ts.map +1 -0
- package/dist/smart-cache/query/table-proxy.js +25 -0
- package/dist/smart-cache/query/table-proxy.js.map +1 -0
- package/dist/smart-cache/types/cache.d.ts +29 -0
- package/dist/smart-cache/types/cache.d.ts.map +1 -0
- package/dist/smart-cache/types/cache.js +10 -0
- package/dist/smart-cache/types/cache.js.map +1 -0
- package/dist/smart-cache/types/config.d.ts +47 -0
- package/dist/smart-cache/types/config.d.ts.map +1 -0
- package/dist/smart-cache/types/config.js +27 -0
- package/dist/smart-cache/types/config.js.map +1 -0
- package/dist/smart-cache/types/query.d.ts +36 -0
- package/dist/smart-cache/types/query.d.ts.map +1 -0
- package/dist/smart-cache/types/query.js +3 -0
- package/dist/smart-cache/types/query.js.map +1 -0
- package/dist/smart-cache/types/schema.d.ts +25 -0
- package/dist/smart-cache/types/schema.d.ts.map +1 -0
- package/dist/smart-cache/types/schema.js +3 -0
- package/dist/smart-cache/types/schema.js.map +1 -0
- package/dist/trial.d.ts +7 -0
- package/dist/trial.d.ts.map +1 -0
- package/dist/trial.js +30 -0
- package/dist/trial.js.map +1 -0
- package/dist/types/cache.d.ts +29 -0
- package/dist/types/cache.d.ts.map +1 -0
- package/dist/types/cache.js +10 -0
- package/dist/types/cache.js.map +1 -0
- package/dist/types/config.d.ts +47 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +27 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/query.d.ts +55 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/query.js +3 -0
- package/dist/types/query.js.map +1 -0
- package/dist/types/schema.d.ts +25 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +3 -0
- package/dist/types/schema.js.map +1 -0
- package/package.json +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
# @bhushanpawar/sqldb
|
|
2
|
+
|
|
3
|
+
An intelligent MariaDB client with **Redis-backed caching**, **automatic schema discovery**, **relationship mapping**, and **smart cache invalidation**. Optimized for high-performance applications with read-heavy workloads.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Core Features
|
|
8
|
+
- **Redis-Backed Distributed Caching** - Fast, distributed caching with configurable TTL
|
|
9
|
+
- **Automatic Schema Discovery** - Auto-discovers tables, columns, and relationships
|
|
10
|
+
- **Smart Cache Invalidation** - Cascading invalidation based on foreign key relationships
|
|
11
|
+
- **Query Builder** - Type-safe CRUD operations with fluent API
|
|
12
|
+
- **Raw Query Caching** - Cache custom SQL queries with configurable TTL
|
|
13
|
+
- **Query Tracking** - Track queries with correlation IDs for debugging and performance analysis
|
|
14
|
+
- **Dependency Graph** - Automatic relationship mapping for cascade invalidation
|
|
15
|
+
- **TypeScript Support** - Full TypeScript support with type inference
|
|
16
|
+
|
|
17
|
+
### Advanced Features
|
|
18
|
+
- Configurable TTL per operation type
|
|
19
|
+
- LRU cache eviction with max keys limit
|
|
20
|
+
- Cache warming and preloading
|
|
21
|
+
- Performance statistics and monitoring
|
|
22
|
+
- Hooks system for extensibility
|
|
23
|
+
- Connection pooling
|
|
24
|
+
- Transaction support
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @bhushanpawar/sqldb mariadb redis
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### Basic Usage with SmartDB
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { createSmartDB } from '@bhushanpawar/sqldb';
|
|
38
|
+
|
|
39
|
+
const db = await createSmartDB({
|
|
40
|
+
mariadb: {
|
|
41
|
+
host: 'localhost',
|
|
42
|
+
port: 3306,
|
|
43
|
+
user: 'root',
|
|
44
|
+
password: 'password',
|
|
45
|
+
database: 'mydb',
|
|
46
|
+
connectionLimit: 10,
|
|
47
|
+
},
|
|
48
|
+
redis: {
|
|
49
|
+
host: 'localhost',
|
|
50
|
+
port: 6379,
|
|
51
|
+
keyPrefix: 'myapp:',
|
|
52
|
+
},
|
|
53
|
+
cache: {
|
|
54
|
+
enabled: true,
|
|
55
|
+
defaultTTL: 60, // 60 seconds
|
|
56
|
+
maxKeys: 1000,
|
|
57
|
+
invalidateOnWrite: true,
|
|
58
|
+
cascadeInvalidation: true,
|
|
59
|
+
},
|
|
60
|
+
discovery: {
|
|
61
|
+
autoDiscover: true,
|
|
62
|
+
refreshInterval: 3600000, // Refresh schema every hour
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Get table operations
|
|
67
|
+
const users = db.getTableOperations('users');
|
|
68
|
+
|
|
69
|
+
// Find operations with automatic caching
|
|
70
|
+
const allUsers = await users.findMany();
|
|
71
|
+
const activeUsers = await users.findMany({ status: 'active' });
|
|
72
|
+
const user = await users.findById(1);
|
|
73
|
+
|
|
74
|
+
// Create/Update/Delete with automatic cache invalidation
|
|
75
|
+
await users.insertOne({ name: 'John', email: 'john@example.com' });
|
|
76
|
+
await users.updateById(1, { status: 'inactive' });
|
|
77
|
+
await users.deleteById(1);
|
|
78
|
+
|
|
79
|
+
// Close connection
|
|
80
|
+
await db.close();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Raw Query Caching
|
|
84
|
+
|
|
85
|
+
The `raw` method supports caching custom SQL queries with a configurable TTL (default: 1 minute):
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const users = db.getTableOperations('users');
|
|
89
|
+
|
|
90
|
+
// First call - queries database and caches result for 60 seconds
|
|
91
|
+
const results = await users.raw(
|
|
92
|
+
'SELECT * FROM users WHERE status = ? ORDER BY created_at DESC LIMIT 10',
|
|
93
|
+
['active']
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Subsequent calls within 60 seconds - served from cache
|
|
97
|
+
const cachedResults = await users.raw(
|
|
98
|
+
'SELECT * FROM users WHERE status = ? ORDER BY created_at DESC LIMIT 10',
|
|
99
|
+
['active']
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Cache stats show hits and misses
|
|
103
|
+
const stats = db.getCacheManager().getStats();
|
|
104
|
+
console.log(stats);
|
|
105
|
+
// { hits: 99, misses: 1, evictions: 0, hitRate: '99.00%' }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The raw query cache:
|
|
109
|
+
- Uses the full SQL query and parameters as the cache key
|
|
110
|
+
- Has a fixed 60-second TTL (optimized for dynamic queries)
|
|
111
|
+
- Automatically expires when the table is modified
|
|
112
|
+
- Supports correlation IDs for query tracking
|
|
113
|
+
|
|
114
|
+
## Table of Contents
|
|
115
|
+
|
|
116
|
+
- [Core Concepts](#core-concepts)
|
|
117
|
+
- [Configuration](#configuration)
|
|
118
|
+
- [CRUD Operations](#crud-operations)
|
|
119
|
+
- [Cache Management](#cache-management)
|
|
120
|
+
- [Query Tracking](#query-tracking)
|
|
121
|
+
- [Smart Cache Invalidation](#smart-cache-invalidation)
|
|
122
|
+
- [Performance Optimization](#performance-optimization)
|
|
123
|
+
- [API Reference](#api-reference)
|
|
124
|
+
|
|
125
|
+
## Core Concepts
|
|
126
|
+
|
|
127
|
+
### Schema Discovery
|
|
128
|
+
|
|
129
|
+
SmartDB automatically discovers your database schema on initialization:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const db = await createSmartDB({
|
|
133
|
+
discovery: {
|
|
134
|
+
autoDiscover: true,
|
|
135
|
+
includedTables: ['users', 'posts', 'comments'], // Optional: specific tables
|
|
136
|
+
excludedTables: ['temp_*'], // Optional: exclude patterns
|
|
137
|
+
refreshInterval: 3600000, // Refresh every hour
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Get discovered tables
|
|
142
|
+
const tables = db.getDiscoveredTables();
|
|
143
|
+
console.log(tables); // ['users', 'posts', 'comments', ...]
|
|
144
|
+
|
|
145
|
+
// Get dependency graph
|
|
146
|
+
const graph = db.getDependencyGraph();
|
|
147
|
+
const deps = graph.getDependencies('users'); // Tables that depend on users
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Relationship Mapping
|
|
151
|
+
|
|
152
|
+
SmartDB automatically maps foreign key relationships:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Schema example:
|
|
156
|
+
// posts (id, user_id, title)
|
|
157
|
+
// comments (id, post_id, user_id, content)
|
|
158
|
+
|
|
159
|
+
// Updating a user invalidates related posts and comments
|
|
160
|
+
await users.updateById(1, { name: 'Jane' });
|
|
161
|
+
// Cache invalidated: users:*, posts:*, comments:*
|
|
162
|
+
|
|
163
|
+
// With cascadeInvalidation: false, only users cache is invalidated
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Cache Invalidation Strategies
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// 1. Automatic invalidation on write (recommended)
|
|
170
|
+
await createSmartDB({
|
|
171
|
+
cache: {
|
|
172
|
+
invalidateOnWrite: true,
|
|
173
|
+
cascadeInvalidation: true, // Invalidate related tables
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// 2. Manual invalidation
|
|
178
|
+
const users = db.getTableOperations('users');
|
|
179
|
+
await users.invalidateCache();
|
|
180
|
+
|
|
181
|
+
// 3. Invalidation via manager
|
|
182
|
+
const invalidationManager = db.getInvalidationManager();
|
|
183
|
+
await invalidationManager.invalidateTable('users', { cascade: true });
|
|
184
|
+
|
|
185
|
+
// 4. Clear entire cache
|
|
186
|
+
const cacheManager = db.getCacheManager();
|
|
187
|
+
await cacheManager.clear();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Configuration
|
|
191
|
+
|
|
192
|
+
### Complete Configuration Example
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { createSmartDB, SmartDBConfig } from '@bhushanpawar/sqldb';
|
|
196
|
+
|
|
197
|
+
const config: SmartDBConfig = {
|
|
198
|
+
// MariaDB connection
|
|
199
|
+
mariadb: {
|
|
200
|
+
host: 'localhost',
|
|
201
|
+
port: 3306,
|
|
202
|
+
user: 'root',
|
|
203
|
+
password: 'password',
|
|
204
|
+
database: 'mydb',
|
|
205
|
+
connectionLimit: 10,
|
|
206
|
+
acquireTimeout: 10000,
|
|
207
|
+
connectTimeout: 10000,
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
// Redis connection
|
|
211
|
+
redis: {
|
|
212
|
+
host: 'localhost',
|
|
213
|
+
port: 6379,
|
|
214
|
+
password: 'redis-password', // Optional
|
|
215
|
+
db: 0,
|
|
216
|
+
keyPrefix: 'myapp:',
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// Cache configuration
|
|
220
|
+
cache: {
|
|
221
|
+
enabled: true,
|
|
222
|
+
defaultTTL: 60, // Default: 60 seconds
|
|
223
|
+
maxKeys: 1000, // Max cached queries
|
|
224
|
+
invalidateOnWrite: true, // Auto-invalidate on INSERT/UPDATE/DELETE
|
|
225
|
+
cascadeInvalidation: true, // Invalidate related tables
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// Schema discovery
|
|
229
|
+
discovery: {
|
|
230
|
+
autoDiscover: true,
|
|
231
|
+
includedTables: [], // Empty = all tables
|
|
232
|
+
excludedTables: [],
|
|
233
|
+
maxGraphDepth: 3, // Cascade depth
|
|
234
|
+
refreshInterval: 3600000, // 1 hour
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
// Logging
|
|
238
|
+
logging: {
|
|
239
|
+
level: 'info', // 'debug' | 'info' | 'warn' | 'error'
|
|
240
|
+
logger: (level, message, meta) => {
|
|
241
|
+
console.log(`[${level}] ${message}`, meta);
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const db = await createSmartDB(config);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Configuration Options
|
|
250
|
+
|
|
251
|
+
#### Cache Options
|
|
252
|
+
|
|
253
|
+
| Option | Type | Default | Description |
|
|
254
|
+
|--------|------|---------|-------------|
|
|
255
|
+
| `enabled` | boolean | true | Enable/disable caching |
|
|
256
|
+
| `defaultTTL` | number | 60 | Default cache TTL in seconds |
|
|
257
|
+
| `maxKeys` | number | 1000 | Maximum cached keys (LRU eviction) |
|
|
258
|
+
| `invalidateOnWrite` | boolean | true | Auto-invalidate on writes |
|
|
259
|
+
| `cascadeInvalidation` | boolean | true | Cascade invalidation to related tables |
|
|
260
|
+
|
|
261
|
+
#### Discovery Options
|
|
262
|
+
|
|
263
|
+
| Option | Type | Default | Description |
|
|
264
|
+
|--------|------|---------|-------------|
|
|
265
|
+
| `autoDiscover` | boolean | true | Auto-discover schema on init |
|
|
266
|
+
| `includedTables` | string[] | [] | Tables to include (empty = all) |
|
|
267
|
+
| `excludedTables` | string[] | [] | Tables to exclude (supports patterns) |
|
|
268
|
+
| `maxGraphDepth` | number | 3 | Max cascade depth for relationships |
|
|
269
|
+
| `refreshInterval` | number | 0 | Schema refresh interval (0 = disabled) |
|
|
270
|
+
|
|
271
|
+
## CRUD Operations
|
|
272
|
+
|
|
273
|
+
### Find Operations
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const users = db.getTableOperations<User>('users');
|
|
277
|
+
|
|
278
|
+
// Find all
|
|
279
|
+
const all = await users.findMany();
|
|
280
|
+
|
|
281
|
+
// Find with conditions
|
|
282
|
+
const active = await users.findMany({
|
|
283
|
+
status: 'active'
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Find with options
|
|
287
|
+
const paginated = await users.findMany(
|
|
288
|
+
{ status: 'active' },
|
|
289
|
+
{
|
|
290
|
+
limit: 10,
|
|
291
|
+
offset: 20,
|
|
292
|
+
orderBy: 'created_at',
|
|
293
|
+
order: 'DESC',
|
|
294
|
+
skipCache: false, // Force cache bypass
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
// Find one
|
|
299
|
+
const user = await users.findOne({ email: 'john@example.com' });
|
|
300
|
+
|
|
301
|
+
// Find by ID
|
|
302
|
+
const userById = await users.findById(1);
|
|
303
|
+
|
|
304
|
+
// Count
|
|
305
|
+
const count = await users.count({ status: 'active' });
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Insert Operations
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
// Insert one
|
|
312
|
+
const newUser = await users.insertOne({
|
|
313
|
+
name: 'John Doe',
|
|
314
|
+
email: 'john@example.com',
|
|
315
|
+
status: 'active',
|
|
316
|
+
});
|
|
317
|
+
console.log(newUser.id); // Auto-generated ID
|
|
318
|
+
|
|
319
|
+
// Insert many
|
|
320
|
+
const newUsers = await users.insertMany([
|
|
321
|
+
{ name: 'Alice', email: 'alice@example.com' },
|
|
322
|
+
{ name: 'Bob', email: 'bob@example.com' },
|
|
323
|
+
]);
|
|
324
|
+
console.log(newUsers.map(u => u.id)); // [1, 2]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Update Operations
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// Update one
|
|
331
|
+
const updated = await users.updateOne(
|
|
332
|
+
{ id: 1 },
|
|
333
|
+
{ status: 'inactive' }
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
// Update many
|
|
337
|
+
const count = await users.updateMany(
|
|
338
|
+
{ status: 'pending' },
|
|
339
|
+
{ status: 'active' }
|
|
340
|
+
);
|
|
341
|
+
console.log(`Updated ${count} users`);
|
|
342
|
+
|
|
343
|
+
// Update by ID
|
|
344
|
+
const user = await users.updateById(1, { name: 'Jane Doe' });
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Delete Operations
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
// Delete one
|
|
351
|
+
const deleted = await users.deleteOne({ id: 1 });
|
|
352
|
+
console.log(deleted); // true/false
|
|
353
|
+
|
|
354
|
+
// Delete many
|
|
355
|
+
const count = await users.deleteMany({ status: 'inactive' });
|
|
356
|
+
console.log(`Deleted ${count} users`);
|
|
357
|
+
|
|
358
|
+
// Delete by ID
|
|
359
|
+
const deleted = await users.deleteById(1);
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Raw SQL Queries
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
// Raw query with caching (60s TTL)
|
|
366
|
+
const results = await users.raw<User[]>(
|
|
367
|
+
'SELECT * FROM users WHERE created_at > ? ORDER BY id DESC',
|
|
368
|
+
['2024-01-01']
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
// With correlation ID for tracking
|
|
372
|
+
const correlationId = 'request-123';
|
|
373
|
+
const results = await users.raw(
|
|
374
|
+
'SELECT COUNT(*) as total FROM users',
|
|
375
|
+
[],
|
|
376
|
+
correlationId
|
|
377
|
+
);
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Cache Management
|
|
381
|
+
|
|
382
|
+
### Cache Statistics
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
const cacheManager = db.getCacheManager();
|
|
386
|
+
const stats = cacheManager.getStats();
|
|
387
|
+
|
|
388
|
+
console.log(stats);
|
|
389
|
+
// {
|
|
390
|
+
// hits: 1500,
|
|
391
|
+
// misses: 100,
|
|
392
|
+
// evictions: 50,
|
|
393
|
+
// size: 0,
|
|
394
|
+
// hitRate: '93.75%'
|
|
395
|
+
// }
|
|
396
|
+
|
|
397
|
+
// Reset stats
|
|
398
|
+
cacheManager.resetStats();
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Manual Cache Control
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// Check if cache is enabled
|
|
405
|
+
if (cacheManager.isEnabled()) {
|
|
406
|
+
// Get cached value
|
|
407
|
+
const value = await cacheManager.get('cache:key');
|
|
408
|
+
|
|
409
|
+
// Set cached value
|
|
410
|
+
await cacheManager.set('cache:key', data, 120); // 120s TTL
|
|
411
|
+
|
|
412
|
+
// Delete specific key
|
|
413
|
+
await cacheManager.delete('cache:key');
|
|
414
|
+
|
|
415
|
+
// Delete by pattern
|
|
416
|
+
const count = await cacheManager.deletePattern('users:*');
|
|
417
|
+
|
|
418
|
+
// Clear all cache
|
|
419
|
+
await cacheManager.clear();
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Cache Warming
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
const users = db.getTableOperations('users');
|
|
427
|
+
|
|
428
|
+
// Pre-warm cache with common queries
|
|
429
|
+
await users.warmCache({ status: 'active' });
|
|
430
|
+
|
|
431
|
+
// This will now be served from cache
|
|
432
|
+
const active = await users.findMany({ status: 'active' });
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Query Tracking
|
|
436
|
+
|
|
437
|
+
Track queries with correlation IDs for debugging and performance monitoring:
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import { generateQueryId } from '@bhushanpawar/sqldb';
|
|
441
|
+
|
|
442
|
+
// Generate correlation ID for a request
|
|
443
|
+
const correlationId = generateQueryId();
|
|
444
|
+
|
|
445
|
+
// Use across multiple operations
|
|
446
|
+
const users = db.getTableOperations('users');
|
|
447
|
+
await users.findMany({ status: 'active' }, { correlationId });
|
|
448
|
+
await users.count({ status: 'active' }, correlationId);
|
|
449
|
+
await users.findById(1, correlationId);
|
|
450
|
+
|
|
451
|
+
// Get all queries for this correlation
|
|
452
|
+
const queries = db.getQueries(correlationId);
|
|
453
|
+
|
|
454
|
+
queries.forEach(q => {
|
|
455
|
+
console.log({
|
|
456
|
+
queryId: q.queryId,
|
|
457
|
+
sql: q.sql,
|
|
458
|
+
executionTime: q.executionTimeMs,
|
|
459
|
+
cached: q.resultCount,
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// Performance analysis
|
|
464
|
+
const totalTime = queries.reduce((sum, q) => sum + (q.executionTimeMs || 0), 0);
|
|
465
|
+
const avgTime = totalTime / queries.length;
|
|
466
|
+
console.log(`Total: ${totalTime}ms, Average: ${avgTime}ms`);
|
|
467
|
+
|
|
468
|
+
// Clean up
|
|
469
|
+
db.clearQueries(correlationId);
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Query Metadata
|
|
473
|
+
|
|
474
|
+
Each tracked query includes:
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
interface QueryMetadata {
|
|
478
|
+
queryId: string; // Unique UUID
|
|
479
|
+
correlationId?: string; // Optional correlation ID
|
|
480
|
+
sql: string; // SQL query
|
|
481
|
+
params?: any[]; // Query parameters
|
|
482
|
+
startTime: number; // Unix timestamp
|
|
483
|
+
endTime?: number; // Unix timestamp
|
|
484
|
+
executionTimeMs?: number; // Execution time
|
|
485
|
+
resultCount?: number; // Rows returned/affected
|
|
486
|
+
error?: string; // Error message if failed
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
## Smart Cache Invalidation
|
|
491
|
+
|
|
492
|
+
### How It Works
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
// Database schema:
|
|
496
|
+
// users (id, name)
|
|
497
|
+
// posts (id, user_id, title) -- FK to users
|
|
498
|
+
// comments (id, post_id, content) -- FK to posts
|
|
499
|
+
|
|
500
|
+
// When you update a user:
|
|
501
|
+
await users.updateById(1, { name: 'Updated Name' });
|
|
502
|
+
|
|
503
|
+
// SmartDB invalidates:
|
|
504
|
+
// 1. users:* (direct table)
|
|
505
|
+
// 2. posts:* (depends on users via user_id)
|
|
506
|
+
// 3. comments:* (depends on posts via post_id)
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Dependency Graph
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
const graph = db.getDependencyGraph();
|
|
513
|
+
|
|
514
|
+
// Get tables that depend on 'users'
|
|
515
|
+
const deps = graph.getDependencies('users');
|
|
516
|
+
console.log(deps); // ['posts', 'comments']
|
|
517
|
+
|
|
518
|
+
// Get all tables 'comments' depends on
|
|
519
|
+
const parents = graph.getParents('comments');
|
|
520
|
+
console.log(parents); // ['posts', 'users']
|
|
521
|
+
|
|
522
|
+
// Check if there's a path
|
|
523
|
+
const hasPath = graph.hasPath('users', 'comments');
|
|
524
|
+
console.log(hasPath); // true
|
|
525
|
+
|
|
526
|
+
// Get graph info
|
|
527
|
+
const info = graph.getGraphInfo();
|
|
528
|
+
console.log(info); // { tables: 3, relationships: 2 }
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Manual Invalidation
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
const invalidationManager = db.getInvalidationManager();
|
|
535
|
+
|
|
536
|
+
// Invalidate single table
|
|
537
|
+
await invalidationManager.invalidateTable('users');
|
|
538
|
+
|
|
539
|
+
// Invalidate with cascade
|
|
540
|
+
await invalidationManager.invalidateTable('users', {
|
|
541
|
+
cascade: true
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
// Invalidate multiple tables
|
|
545
|
+
await invalidationManager.invalidateTables(['users', 'posts']);
|
|
546
|
+
|
|
547
|
+
// Invalidate by operation
|
|
548
|
+
const cacheManager = db.getCacheManager();
|
|
549
|
+
await cacheManager.deletePattern('users:findMany:*');
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## Performance Optimization
|
|
553
|
+
|
|
554
|
+
### Best Practices
|
|
555
|
+
|
|
556
|
+
1. **Configure Appropriate TTL**
|
|
557
|
+
```typescript
|
|
558
|
+
// High-churn data: short TTL
|
|
559
|
+
cache: { defaultTTL: 30 }
|
|
560
|
+
|
|
561
|
+
// Stable data: longer TTL
|
|
562
|
+
cache: { defaultTTL: 300 }
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
2. **Use Selective Caching**
|
|
566
|
+
```typescript
|
|
567
|
+
// Skip cache for real-time data
|
|
568
|
+
const users = await users.findMany(
|
|
569
|
+
{ status: 'online' },
|
|
570
|
+
{ skipCache: true }
|
|
571
|
+
);
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
3. **Warm Cache for Common Queries**
|
|
575
|
+
```typescript
|
|
576
|
+
// Pre-warm after deployment
|
|
577
|
+
await users.warmCache({ status: 'active' });
|
|
578
|
+
await posts.warmCache({ published: true });
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
4. **Monitor Cache Performance**
|
|
582
|
+
```typescript
|
|
583
|
+
const stats = db.getCacheManager().getStats();
|
|
584
|
+
|
|
585
|
+
if (parseFloat(stats.hitRate) < 80) {
|
|
586
|
+
console.warn('Low cache hit rate:', stats);
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
5. **Use Correlation IDs**
|
|
591
|
+
```typescript
|
|
592
|
+
// Track request performance
|
|
593
|
+
app.use((req, res, next) => {
|
|
594
|
+
req.correlationId = generateQueryId();
|
|
595
|
+
next();
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Log slow requests
|
|
599
|
+
app.use((req, res, next) => {
|
|
600
|
+
const queries = db.getQueries(req.correlationId);
|
|
601
|
+
const totalTime = queries.reduce((sum, q) =>
|
|
602
|
+
sum + (q.executionTimeMs || 0), 0);
|
|
603
|
+
|
|
604
|
+
if (totalTime > 1000) {
|
|
605
|
+
console.warn('Slow request:', {
|
|
606
|
+
path: req.path,
|
|
607
|
+
time: totalTime,
|
|
608
|
+
queries: queries.length
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
next();
|
|
612
|
+
});
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Performance Testing
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
// Example performance test
|
|
619
|
+
const iterations = 100;
|
|
620
|
+
const correlationId = generateQueryId();
|
|
621
|
+
|
|
622
|
+
console.time('100 queries');
|
|
623
|
+
for (let i = 0; i < iterations; i++) {
|
|
624
|
+
await users.findMany({ status: 'active' }, { correlationId });
|
|
625
|
+
}
|
|
626
|
+
console.timeEnd('100 queries');
|
|
627
|
+
|
|
628
|
+
// Check cache effectiveness
|
|
629
|
+
const stats = db.getCacheManager().getStats();
|
|
630
|
+
console.log(`Hit rate: ${stats.hitRate}`);
|
|
631
|
+
console.log(`Hits: ${stats.hits}, Misses: ${stats.misses}`);
|
|
632
|
+
|
|
633
|
+
// Analyze query performance
|
|
634
|
+
const queries = db.getQueries(correlationId);
|
|
635
|
+
console.log(`Total queries executed: ${queries.length}`); // Should be 1 if cache works
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## API Reference
|
|
639
|
+
|
|
640
|
+
### SmartDBClient
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
class SmartDBClient {
|
|
644
|
+
// Initialize client
|
|
645
|
+
async initialize(): Promise<void>;
|
|
646
|
+
|
|
647
|
+
// Get table operations
|
|
648
|
+
getTableOperations<T>(tableName: string): TableOperations<T>;
|
|
649
|
+
|
|
650
|
+
// Get managers
|
|
651
|
+
getCacheManager(): CacheManager;
|
|
652
|
+
getInvalidationManager(): InvalidationManager;
|
|
653
|
+
getDependencyGraph(): DependencyGraph;
|
|
654
|
+
|
|
655
|
+
// Schema discovery
|
|
656
|
+
getDiscoveredTables(): string[];
|
|
657
|
+
async refreshSchema(): Promise<void>;
|
|
658
|
+
|
|
659
|
+
// Query tracking
|
|
660
|
+
getQueries(correlationId?: string): QueryMetadata[];
|
|
661
|
+
clearQueries(correlationId?: string): void;
|
|
662
|
+
|
|
663
|
+
// Health and lifecycle
|
|
664
|
+
async healthCheck(): Promise<HealthStatus>;
|
|
665
|
+
async close(): Promise<void>;
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
### TableOperations
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
interface TableOperations<T> {
|
|
673
|
+
// Find operations
|
|
674
|
+
findOne(where: WhereClause<T>, options?: FindOptions): Promise<T | null>;
|
|
675
|
+
findMany(where?: WhereClause<T>, options?: FindOptions): Promise<T[]>;
|
|
676
|
+
findById(id: string | number, correlationId?: string): Promise<T | null>;
|
|
677
|
+
count(where?: WhereClause<T>, correlationId?: string): Promise<number>;
|
|
678
|
+
|
|
679
|
+
// Insert operations
|
|
680
|
+
insertOne(data: Omit<T, 'id'>, correlationId?: string): Promise<T>;
|
|
681
|
+
insertMany(data: Omit<T, 'id'>[], correlationId?: string): Promise<T[]>;
|
|
682
|
+
|
|
683
|
+
// Update operations
|
|
684
|
+
updateOne(where: WhereClause<T>, data: Partial<T>, correlationId?: string): Promise<T | null>;
|
|
685
|
+
updateMany(where: WhereClause<T>, data: Partial<T>, correlationId?: string): Promise<number>;
|
|
686
|
+
updateById(id: string | number, data: Partial<T>, correlationId?: string): Promise<T | null>;
|
|
687
|
+
|
|
688
|
+
// Delete operations
|
|
689
|
+
deleteOne(where: WhereClause<T>, correlationId?: string): Promise<boolean>;
|
|
690
|
+
deleteMany(where: WhereClause<T>, correlationId?: string): Promise<number>;
|
|
691
|
+
deleteById(id: string | number, correlationId?: string): Promise<boolean>;
|
|
692
|
+
|
|
693
|
+
// Raw queries
|
|
694
|
+
raw<R = any>(sql: string, params?: any[], correlationId?: string): Promise<R>;
|
|
695
|
+
|
|
696
|
+
// Cache management
|
|
697
|
+
invalidateCache(): Promise<void>;
|
|
698
|
+
warmCache(where?: WhereClause<T>, correlationId?: string): Promise<void>;
|
|
699
|
+
}
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### CacheManager
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
class CacheManager {
|
|
706
|
+
async get<T>(key: string): Promise<T | null>;
|
|
707
|
+
async set(key: string, value: any, ttl?: number): Promise<void>;
|
|
708
|
+
async delete(key: string): Promise<void>;
|
|
709
|
+
async deletePattern(pattern: string): Promise<number>;
|
|
710
|
+
async exists(key: string): Promise<boolean>;
|
|
711
|
+
async clear(): Promise<void>;
|
|
712
|
+
|
|
713
|
+
getStats(): CacheStats;
|
|
714
|
+
resetStats(): void;
|
|
715
|
+
isEnabled(): boolean;
|
|
716
|
+
getKeyBuilder(): CacheKeyBuilder;
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
## Migration from mariadb
|
|
721
|
+
|
|
722
|
+
### Before (mariadb)
|
|
723
|
+
|
|
724
|
+
```typescript
|
|
725
|
+
import mariadb from 'mariadb';
|
|
726
|
+
|
|
727
|
+
const pool = mariadb.createPool(config);
|
|
728
|
+
|
|
729
|
+
const conn = await pool.getConnection();
|
|
730
|
+
const users = await conn.query('SELECT * FROM users WHERE status = ?', ['active']);
|
|
731
|
+
conn.release();
|
|
732
|
+
|
|
733
|
+
await pool.end();
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### After (@bhushanpawar/sqldb)
|
|
737
|
+
|
|
738
|
+
```typescript
|
|
739
|
+
import { createSmartDB } from '@bhushanpawar/sqldb';
|
|
740
|
+
|
|
741
|
+
const db = await createSmartDB({ mariadb: config, redis: redisConfig });
|
|
742
|
+
|
|
743
|
+
const users = db.getTableOperations('users');
|
|
744
|
+
const activeUsers = await users.findMany({ status: 'active' });
|
|
745
|
+
// Automatically cached, invalidated on writes, type-safe
|
|
746
|
+
|
|
747
|
+
await db.close();
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
## Testing
|
|
751
|
+
|
|
752
|
+
```bash
|
|
753
|
+
# Run all tests
|
|
754
|
+
npm test
|
|
755
|
+
|
|
756
|
+
# Run with coverage
|
|
757
|
+
npm run test:coverage
|
|
758
|
+
|
|
759
|
+
# Run performance tests
|
|
760
|
+
npm run usage perf
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
## Performance Results
|
|
764
|
+
|
|
765
|
+
Based on real-world testing:
|
|
766
|
+
|
|
767
|
+
- **Cache Hit Rate**: 99%+ for read-heavy workloads
|
|
768
|
+
- **Query Time**: <1ms for cached queries vs 50-300ms for database queries
|
|
769
|
+
- **Throughput**: 10,000+ queries/second with Redis cache
|
|
770
|
+
- **Memory**: ~1KB per cached query
|
|
771
|
+
|
|
772
|
+
See [PERFORMANCE_RESULTS.md](./PERFORMANCE_RESULTS.md) for detailed benchmarks.
|
|
773
|
+
|
|
774
|
+
## Examples
|
|
775
|
+
|
|
776
|
+
See the [examples](./examples) directory for complete examples:
|
|
777
|
+
|
|
778
|
+
- [usage.ts](./examples/usage.ts) - Basic CRUD operations
|
|
779
|
+
- [query-tracking.ts](./examples/query-tracking.ts) - Query tracking with correlation IDs
|
|
780
|
+
- [simple-query-tracking.ts](./examples/simple-query-tracking.ts) - Simple tracking example
|
|
781
|
+
|
|
782
|
+
## Documentation
|
|
783
|
+
|
|
784
|
+
- [Query Tracking Guide](./QUERY_TRACKING.md)
|
|
785
|
+
- [Performance Testing](./PERFORMANCE_TESTING.md)
|
|
786
|
+
- [Changelog](./CHANGELOG_QUERY_TRACKING.md)
|
|
787
|
+
|
|
788
|
+
## License
|
|
789
|
+
|
|
790
|
+
MIT
|
|
791
|
+
|
|
792
|
+
## Contributing
|
|
793
|
+
|
|
794
|
+
Contributions welcome! Please open an issue or PR.
|
|
795
|
+
|
|
796
|
+
## Support
|
|
797
|
+
|
|
798
|
+
For issues and questions:
|
|
799
|
+
- GitHub Issues: [sqldb/issues](https://github.com/erBhushanPawar/sqldb/issues)
|
|
800
|
+
- Documentation: See docs above
|
|
801
|
+
|
|
802
|
+
## Roadmap
|
|
803
|
+
|
|
804
|
+
- [ ] Support for more complex WHERE clauses (IN, LIKE, etc.)
|
|
805
|
+
- [ ] Query result transformation and mapping
|
|
806
|
+
- [ ] Built-in pagination helpers
|
|
807
|
+
- [ ] Redis Cluster support
|
|
808
|
+
- [ ] GraphQL integration
|
|
809
|
+
- [ ] Prisma-like schema definition
|
|
810
|
+
- [ ] Migration tools
|
|
811
|
+
- [ ] Admin UI for cache monitoring
|