@forgebase/sdk 0.0.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/LICENSE +21 -0
- package/README.md +390 -0
- package/dist/cjs/database/client/client.d.ts +470 -0
- package/dist/cjs/database/client/client.d.ts.map +1 -0
- package/dist/cjs/database/client/client.js +812 -0
- package/dist/cjs/database/client/client.js.map +1 -0
- package/dist/cjs/database/client/index.d.ts +2 -0
- package/dist/cjs/database/client/index.d.ts.map +1 -0
- package/dist/cjs/database/client/index.js +18 -0
- package/dist/cjs/database/client/index.js.map +1 -0
- package/dist/cjs/database/examples.d.ts +70 -0
- package/dist/cjs/database/examples.d.ts.map +1 -0
- package/dist/cjs/database/examples.js +239 -0
- package/dist/cjs/database/examples.js.map +1 -0
- package/dist/cjs/database/server/index.d.ts +2 -0
- package/dist/cjs/database/server/index.d.ts.map +1 -0
- package/dist/cjs/database/server/index.js +18 -0
- package/dist/cjs/database/server/index.js.map +1 -0
- package/dist/cjs/database/server/server.d.ts +2 -0
- package/dist/cjs/database/server/server.d.ts.map +1 -0
- package/dist/cjs/database/server/server.js +6 -0
- package/dist/cjs/database/server/server.js.map +1 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/database/client/client.d.ts +470 -0
- package/dist/esm/database/client/client.d.ts.map +1 -0
- package/dist/esm/database/client/client.js +805 -0
- package/dist/esm/database/client/client.js.map +1 -0
- package/dist/esm/database/client/index.d.ts +2 -0
- package/dist/esm/database/client/index.d.ts.map +1 -0
- package/dist/esm/database/client/index.js +2 -0
- package/dist/esm/database/client/index.js.map +1 -0
- package/dist/esm/database/examples.d.ts +70 -0
- package/dist/esm/database/examples.d.ts.map +1 -0
- package/dist/esm/database/examples.js +236 -0
- package/dist/esm/database/examples.js.map +1 -0
- package/dist/esm/database/server/index.d.ts +2 -0
- package/dist/esm/database/server/index.d.ts.map +1 -0
- package/dist/esm/database/server/index.js +2 -0
- package/dist/esm/database/server/index.js.map +1 -0
- package/dist/esm/database/server/server.d.ts +2 -0
- package/dist/esm/database/server/server.d.ts.map +1 -0
- package/dist/esm/database/server/server.js +2 -0
- package/dist/esm/database/server/server.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ForgeBase
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# ForgeBase TypeScript SDK
|
|
2
|
+
|
|
3
|
+
A powerful, type-safe TypeScript SDK for interacting with ForgeBase services, providing comprehensive database operations, real-time features, and advanced query capabilities.
|
|
4
|
+
|
|
5
|
+
## Core Features
|
|
6
|
+
|
|
7
|
+
- **Type-Safe Query Builder**:
|
|
8
|
+
- Fluent API design
|
|
9
|
+
- Advanced filtering
|
|
10
|
+
- Complex joins and relations
|
|
11
|
+
- Aggregations and window functions
|
|
12
|
+
- Transaction support
|
|
13
|
+
- Raw query support
|
|
14
|
+
- Query optimization
|
|
15
|
+
|
|
16
|
+
- **Database Operations**:
|
|
17
|
+
- CRUD operations
|
|
18
|
+
- Batch operations
|
|
19
|
+
- Pagination
|
|
20
|
+
- Sorting
|
|
21
|
+
- Custom queries
|
|
22
|
+
- Schema validation
|
|
23
|
+
- Error handling
|
|
24
|
+
|
|
25
|
+
- **Security Features**:
|
|
26
|
+
|
|
27
|
+
<!-- - JWKS support
|
|
28
|
+
- Token validation
|
|
29
|
+
- Request signing -->
|
|
30
|
+
- Input sanitization
|
|
31
|
+
- Type validation
|
|
32
|
+
- Error boundaries
|
|
33
|
+
<!-- - Rate limiting -->
|
|
34
|
+
|
|
35
|
+
- **Advanced Querying**:
|
|
36
|
+
- Window functions
|
|
37
|
+
- Common Table Expressions (CTEs)
|
|
38
|
+
- Recursive queries
|
|
39
|
+
- Complex filtering
|
|
40
|
+
- Advanced joins
|
|
41
|
+
- Subqueries
|
|
42
|
+
- Aggregations
|
|
43
|
+
|
|
44
|
+
<!-- - **Real-time Features**:
|
|
45
|
+
|
|
46
|
+
- Live queries
|
|
47
|
+
- Change notifications
|
|
48
|
+
- WebSocket integration
|
|
49
|
+
- Presence tracking
|
|
50
|
+
- Subscription management
|
|
51
|
+
- Connection handling
|
|
52
|
+
- Event buffering -->
|
|
53
|
+
|
|
54
|
+
<!-- - **Performance Features**:
|
|
55
|
+
- Query caching
|
|
56
|
+
- Connection pooling
|
|
57
|
+
- Batch operations
|
|
58
|
+
- Lazy loading
|
|
59
|
+
- Query optimization
|
|
60
|
+
- Result transformation
|
|
61
|
+
- Memory management -->
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install @forgebase/sdk
|
|
67
|
+
# or
|
|
68
|
+
yarn add @forgebase/sdk
|
|
69
|
+
# or
|
|
70
|
+
pnpm add @forgebase/sdk
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Basic Usage
|
|
74
|
+
|
|
75
|
+
### Database Operations
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { DatabaseSDK } from '@forgebase/sdk/client';
|
|
79
|
+
|
|
80
|
+
// Initialize with your API URL
|
|
81
|
+
const db = new DatabaseSDK('http://localhost:3000', {
|
|
82
|
+
credentials: 'include',
|
|
83
|
+
headers: {
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Basic CRUD Operations
|
|
89
|
+
const users = await db
|
|
90
|
+
.table('users')
|
|
91
|
+
.select('id', 'name', 'email')
|
|
92
|
+
.where('status', 'active')
|
|
93
|
+
.execute({
|
|
94
|
+
headers: {
|
|
95
|
+
'some-stuff': 'true',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Create a new record
|
|
100
|
+
const newUser = await db.table('users').create({
|
|
101
|
+
name: 'John Doe',
|
|
102
|
+
email: 'john@example.com',
|
|
103
|
+
role: 'user',
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Update a record
|
|
107
|
+
await db.table('users').update(1, {
|
|
108
|
+
status: 'inactive',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Delete a record
|
|
112
|
+
await db.table('users').delete(1);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Advanced Queries
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Complex filtering with type safety
|
|
119
|
+
interface User {
|
|
120
|
+
id: number;
|
|
121
|
+
name: string;
|
|
122
|
+
email: string;
|
|
123
|
+
role: string;
|
|
124
|
+
department: string;
|
|
125
|
+
salary: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const results = await db
|
|
129
|
+
.table<User>('users')
|
|
130
|
+
.where('status', 'active')
|
|
131
|
+
.andWhere((query) => {
|
|
132
|
+
query.where('role', 'manager').where('department', 'IT').orWhere('salary', '>', 100000);
|
|
133
|
+
})
|
|
134
|
+
.orderBy('name', 'asc')
|
|
135
|
+
.limit(10)
|
|
136
|
+
.execute();
|
|
137
|
+
|
|
138
|
+
// Aggregations
|
|
139
|
+
const stats = await db.table<User>('users').groupBy('department').select('department').count('id', 'total_users').avg('salary', 'avg_salary').having('total_users', '>', 5).execute();
|
|
140
|
+
|
|
141
|
+
// Window Functions
|
|
142
|
+
const rankedUsers = await db
|
|
143
|
+
.table<User>('users')
|
|
144
|
+
.select('name', 'department', 'salary')
|
|
145
|
+
.window('rank', 'salary_rank', {
|
|
146
|
+
partitionBy: ['department'],
|
|
147
|
+
orderBy: [{ field: 'salary', direction: 'desc' }],
|
|
148
|
+
})
|
|
149
|
+
.execute();
|
|
150
|
+
|
|
151
|
+
// Advanced Window Functions
|
|
152
|
+
const analysis = await db
|
|
153
|
+
.table<User>('users')
|
|
154
|
+
.windowAdvanced('sum', 'running_total', {
|
|
155
|
+
field: 'salary',
|
|
156
|
+
over: {
|
|
157
|
+
partitionBy: ['department'],
|
|
158
|
+
orderBy: [{ field: 'hire_date', direction: 'asc' }],
|
|
159
|
+
frame: {
|
|
160
|
+
type: 'ROWS',
|
|
161
|
+
start: 'UNBOUNDED PRECEDING',
|
|
162
|
+
end: 'CURRENT ROW',
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
.execute();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### CTEs and Recursive Queries
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// Simple CTE
|
|
173
|
+
const highPaidUsers = db.table<User>('users').where('salary', '>', 100000);
|
|
174
|
+
|
|
175
|
+
const result = await db.table<User>('users').with('high_paid', highPaidUsers).execute();
|
|
176
|
+
|
|
177
|
+
// Recursive CTE
|
|
178
|
+
interface Category {
|
|
179
|
+
id: number;
|
|
180
|
+
parent_id: number | null;
|
|
181
|
+
name: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const categories = await db
|
|
185
|
+
.table<Category>('categories')
|
|
186
|
+
.withRecursive(
|
|
187
|
+
'category_tree',
|
|
188
|
+
// Initial query
|
|
189
|
+
db.table('categories').where('parent_id', null),
|
|
190
|
+
// Recursive query
|
|
191
|
+
db.table('categories').join('category_tree', 'parent_id', 'id'),
|
|
192
|
+
{ unionAll: true },
|
|
193
|
+
)
|
|
194
|
+
.execute();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
<!-- ### Real-time Subscriptions
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Subscribe to changes
|
|
201
|
+
const unsubscribe = await db
|
|
202
|
+
.table<User>('users')
|
|
203
|
+
.where('department', 'IT')
|
|
204
|
+
.subscribe({
|
|
205
|
+
onAdd: (user) => console.log('New user:', user),
|
|
206
|
+
onChange: (user) => console.log('User updated:', user),
|
|
207
|
+
onDelete: (id) => console.log('User deleted:', id),
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Later: cleanup subscription
|
|
211
|
+
unsubscribe();
|
|
212
|
+
``` -->
|
|
213
|
+
|
|
214
|
+
<!-- ### Security Features
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
// JWKS Configuration
|
|
218
|
+
const db = new DatabaseSDK('http://localhost:3000', {
|
|
219
|
+
auth: {
|
|
220
|
+
jwksUrl: '/.well-known/jwks.json',
|
|
221
|
+
audience: 'your-api',
|
|
222
|
+
issuer: 'your-auth-server',
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Request Signing
|
|
227
|
+
const db = new DatabaseSDK('http://localhost:3000', {
|
|
228
|
+
security: {
|
|
229
|
+
signRequests: true,
|
|
230
|
+
privateKey: 'your-private-key',
|
|
231
|
+
keyId: 'your-key-id',
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Rate Limiting
|
|
236
|
+
const db = new DatabaseSDK('http://localhost:3000', {
|
|
237
|
+
rateLimit: {
|
|
238
|
+
maxRequests: 100,
|
|
239
|
+
windowMs: 60000, // 1 minute
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
``` -->
|
|
243
|
+
|
|
244
|
+
## Error Handling
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
try {
|
|
248
|
+
const result = await db.table('users').where('id', 1).execute();
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error instanceof QueryError) {
|
|
251
|
+
// Handle query-related errors
|
|
252
|
+
console.error('Query Error:', error.message);
|
|
253
|
+
} else if (error instanceof ValidationError) {
|
|
254
|
+
// Handle validation errors
|
|
255
|
+
console.error('Validation Error:', error.details);
|
|
256
|
+
} else if (error instanceof AuthorizationError) {
|
|
257
|
+
// Handle authorization errors
|
|
258
|
+
console.error('Authorization Error:', error.message);
|
|
259
|
+
} else {
|
|
260
|
+
// Handle other errors
|
|
261
|
+
console.error('Unknown Error:', error);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
<!--
|
|
267
|
+
## Advanced Configuration
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
const db = new DatabaseSDK('http://localhost:3000', {
|
|
271
|
+
// Authentication
|
|
272
|
+
credentials: 'include',
|
|
273
|
+
headers: {
|
|
274
|
+
Authorization: 'Bearer your-token',
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
// Query Options
|
|
278
|
+
queryConfig: {
|
|
279
|
+
maxLimit: 1000,
|
|
280
|
+
defaultLimit: 50,
|
|
281
|
+
maxComplexity: 10,
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
// Cache Configuration
|
|
285
|
+
cache: {
|
|
286
|
+
enabled: true,
|
|
287
|
+
ttl: 300, // 5 minutes
|
|
288
|
+
maxSize: 100, // Maximum number of cached queries
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
// Real-time Configuration
|
|
292
|
+
realtime: {
|
|
293
|
+
enabled: true,
|
|
294
|
+
reconnectDelay: 1000,
|
|
295
|
+
maxRetries: 5,
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
// Performance Tuning
|
|
299
|
+
performance: {
|
|
300
|
+
batchSize: 1000,
|
|
301
|
+
poolSize: 10,
|
|
302
|
+
timeout: 5000,
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
``` -->
|
|
306
|
+
|
|
307
|
+
## Type Safety
|
|
308
|
+
|
|
309
|
+
The SDK provides full TypeScript support with generic types:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
interface User {
|
|
313
|
+
id: number;
|
|
314
|
+
name: string;
|
|
315
|
+
email: string;
|
|
316
|
+
role: string;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
interface Order {
|
|
320
|
+
id: number;
|
|
321
|
+
userId: number;
|
|
322
|
+
total: number;
|
|
323
|
+
status: string;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Type-safe queries
|
|
327
|
+
const users = await db.table<User>('users').select('id', 'name', 'email').where('role', 'admin').execute();
|
|
328
|
+
|
|
329
|
+
// Type-safe joins
|
|
330
|
+
const orders = await db.table<Order>('orders').join<User>('users', 'userId', 'id').select('orders.id', 'users.name', 'orders.total').execute();
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Performance Optimization
|
|
334
|
+
|
|
335
|
+
### Query Optimization
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// Use select to limit returned fields
|
|
339
|
+
const users = await db.table('users').select('id', 'name').where('active', true).execute();
|
|
340
|
+
|
|
341
|
+
// Use indexes effectively
|
|
342
|
+
const result = await db
|
|
343
|
+
.table('users')
|
|
344
|
+
.where('email', 'user@example.com') // Assuming email is indexed
|
|
345
|
+
.first()
|
|
346
|
+
.execute();
|
|
347
|
+
|
|
348
|
+
// Batch operations (WIP*)
|
|
349
|
+
await db.table('users').createMany([
|
|
350
|
+
{ name: 'User 1', email: 'user1@example.com' },
|
|
351
|
+
{ name: 'User 2', email: 'user2@example.com' },
|
|
352
|
+
]);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
<!-- ### Caching
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// Enable caching for specific queries
|
|
359
|
+
const users = await db
|
|
360
|
+
.table('users')
|
|
361
|
+
.cache({
|
|
362
|
+
ttl: 300, // 5 minutes
|
|
363
|
+
tags: ['users'],
|
|
364
|
+
})
|
|
365
|
+
.execute();
|
|
366
|
+
|
|
367
|
+
// Invalidate cache
|
|
368
|
+
await db.invalidateCache('users');
|
|
369
|
+
``` -->
|
|
370
|
+
|
|
371
|
+
## Building
|
|
372
|
+
|
|
373
|
+
Run `nx build sdk` to build the library.
|
|
374
|
+
|
|
375
|
+
## Running Tests
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# Run unit tests
|
|
379
|
+
nx test sdk
|
|
380
|
+
|
|
381
|
+
# Run integration tests
|
|
382
|
+
nx test sdk --config=integration
|
|
383
|
+
|
|
384
|
+
# Run tests with coverage
|
|
385
|
+
nx test sdk --coverage
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT
|