@forgebase/sdk 0.0.1 → 0.0.2

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.
Files changed (2) hide show
  1. package/README.md +88 -299
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -1,64 +1,27 @@
1
1
  # ForgeBase TypeScript SDK
2
2
 
3
- A powerful, type-safe TypeScript SDK for interacting with ForgeBase services, providing comprehensive database operations, real-time features, and advanced query capabilities.
3
+ A powerful, type-safe TypeScript SDK for interacting with ForgeBase services, providing comprehensive database operations, advanced query capabilities, and type safety.
4
4
 
5
5
  ## Core Features
6
6
 
7
7
  - **Type-Safe Query Builder**:
8
8
  - Fluent API design
9
- - Advanced filtering
9
+ - Advanced filtering (`where`, `whereIn`, `whereExists`, etc.)
10
10
  - Complex joins and relations
11
- - Aggregations and window functions
12
- - Transaction support
13
- - Raw query support
14
- - Query optimization
11
+ - Aggregations (`count`, `sum`, `avg`, `min`, `max`)
12
+ - Window functions (`rowNumber`, `rank`, `lag`, `lead`)
13
+ - Recursive CTEs
14
+ - Result transformations (`pivot`, `compute`)
15
15
 
16
16
  - **Database Operations**:
17
- - CRUD operations
17
+ - CRUD operations (`create`, `update`, `delete`)
18
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 -->
19
+ - Pagination (`limit`, `offset`)
20
+ - Sorting (`orderBy`)
21
+
22
+ - **Security & Validation**:
23
+ - Input validation
24
+ - Type inference from your interfaces
62
25
 
63
26
  ## Installation
64
27
 
@@ -72,35 +35,59 @@ pnpm add @forgebase/sdk
72
35
 
73
36
  ## Basic Usage
74
37
 
75
- ### Database Operations
38
+ ### Initialization
39
+
40
+ First, define your database schema and initialize the SDK. This provides automatic type safety across your entire application.
76
41
 
77
42
  ```typescript
78
43
  import { DatabaseSDK } from '@forgebase/sdk/client';
79
44
 
80
- // Initialize with your API URL
81
- const db = new DatabaseSDK('http://localhost:3000', {
82
- credentials: 'include',
83
- headers: {
84
- 'Content-Type': 'application/json',
45
+ // 1. Define your entity types
46
+ interface User {
47
+ id: number;
48
+ name: string;
49
+ email: string;
50
+ role: 'admin' | 'user';
51
+ status: 'active' | 'inactive';
52
+ }
53
+
54
+ interface Order {
55
+ id: number;
56
+ user_id: number;
57
+ amount: number;
58
+ status: 'pending' | 'completed';
59
+ }
60
+
61
+ // 2. Define your Database Schema
62
+ interface Schema {
63
+ users: User;
64
+ orders: Order;
65
+ }
66
+
67
+ // 3. Initialize the SDK with your Schema
68
+ const db = new DatabaseSDK<Schema>({
69
+ baseUrl: 'http://localhost:3000',
70
+ axiosConfig: {
71
+ withCredentials: true,
72
+ headers: { 'Content-Type': 'application/json' },
85
73
  },
86
74
  });
75
+ ```
87
76
 
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
- });
77
+ ### Database Operations
98
78
 
99
- // Create a new record
79
+ The SDK automatically infers types based on your Schema.
80
+
81
+ ```typescript
82
+ // Query users (Type is inferred as User[])
83
+ const users = await db.table('users').select('id', 'name', 'email').where('status', 'active').query();
84
+
85
+ // Create a new record (Type checking ensures payload matches User)
100
86
  const newUser = await db.table('users').create({
101
87
  name: 'John Doe',
102
88
  email: 'john@example.com',
103
89
  role: 'user',
90
+ status: 'active',
104
91
  });
105
92
 
106
93
  // Update a record
@@ -115,74 +102,33 @@ await db.table('users').delete(1);
115
102
  ### Advanced Queries
116
103
 
117
104
  ```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
-
105
+ // Complex filtering
128
106
  const results = await db
129
- .table<User>('users')
107
+ .table('users') // Type inferred automatically
130
108
  .where('status', 'active')
131
109
  .andWhere((query) => {
132
- query.where('role', 'manager').where('department', 'IT').orWhere('salary', '>', 100000);
110
+ query.where('role', 'admin').orWhere('email', 'like', '%@company.com');
133
111
  })
134
112
  .orderBy('name', 'asc')
135
113
  .limit(10)
136
- .execute();
114
+ .query();
137
115
 
138
116
  // 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();
117
+ const stats = await db.table('orders').groupBy('status').sum('amount', 'total_amount').count('id', 'order_count').having('total_amount', '>', 5000).query();
118
+
119
+ // Result type is narrowed:
120
+ // stats.data -> { status: string, total_amount: number, order_count: number }[]
140
121
 
141
122
  // Window Functions
142
123
  const rankedUsers = await db
143
- .table<User>('users')
124
+ .table('users')
144
125
  .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
- }
126
+ .rank('salary_rank', ['department'], [{ field: 'salary', direction: 'desc' }])
127
+ .query();
183
128
 
129
+ // Recursive CTEs (e.g., for hierarchical data)
184
130
  const categories = await db
185
- .table<Category>('categories')
131
+ .table('categories')
186
132
  .withRecursive(
187
133
  'category_tree',
188
134
  // Initial query
@@ -191,199 +137,42 @@ const categories = await db
191
137
  db.table('categories').join('category_tree', 'parent_id', 'id'),
192
138
  { unionAll: true },
193
139
  )
194
- .execute();
140
+ .query();
195
141
  ```
196
142
 
197
- <!-- ### Real-time Subscriptions
143
+ ### Transformations
198
144
 
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
145
+ You can transform the result set on the client side using `pivot` or `compute`.
215
146
 
216
147
  ```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
- ``` -->
148
+ // Pivot data
149
+ const pivoted = await db.table('sales').pivot('month', ['Jan', 'Feb', 'Mar'], { type: 'sum', field: 'amount' }).query();
150
+
151
+ // Compute new fields
152
+ const computed = await db
153
+ .table('employees')
154
+ .compute({
155
+ fullName: (row) => `${row.firstName} ${row.lastName}`,
156
+ tax: (row) => row.salary * 0.2,
157
+ })
158
+ .query();
159
+ ```
243
160
 
244
161
  ## Error Handling
245
162
 
163
+ The SDK throws standard errors that you can catch and handle.
164
+
246
165
  ```typescript
247
166
  try {
248
- const result = await db.table('users').where('id', 1).execute();
167
+ await db.table('users').create(data);
249
168
  } 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
- }
169
+ console.error('Failed to create user:', error.message);
263
170
  }
264
171
  ```
265
172
 
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:
173
+ ## Real-time Updates
310
174
 
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
- ```
175
+ > ⚠️ **Note**: Real-time features (WebSockets/SSE) are currently experimental and under active development. They are not yet fully documented or recommended for production use.
387
176
 
388
177
  ## License
389
178
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgebase/sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -49,10 +49,10 @@
49
49
  "dependencies": {
50
50
  "axios": "^1.7.9",
51
51
  "kysely": "^0.28.11",
52
- "@forgebase/database": "0.0.1"
52
+ "@forgebase/database": "0.0.2"
53
53
  },
54
54
  "peerDependencies": {
55
- "@forgebase/database": "0.0.1"
55
+ "@forgebase/database": "0.0.2"
56
56
  },
57
57
  "devDependencies": {
58
58
  "tslib": "^2.3.0",