@forgebase/database 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.
- package/README.md +93 -306
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,117 +1,135 @@
|
|
|
1
1
|
# ForgeBase Database
|
|
2
2
|
|
|
3
|
-
A flexible, powerful database abstraction layer for ForgeBase,
|
|
3
|
+
A flexible, powerful database abstraction layer for ForgeBase, built on top of [Kysely](https://kysely.dev/). It provides type-safe database operations, schema management, row-level security (RLS), and real-time capabilities.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- 🔄 **Multiple Database Support**: Works with SQLite, PostgreSQL, MySQL,
|
|
8
|
-
- 🔒 **Row-Level Security (RLS)**: Fine-grained access control at the row level
|
|
9
|
-
- 🔐 **Permission Management**: Role-based
|
|
10
|
-
- 📊 **Schema Management**: Create, modify, and delete tables and columns dynamically
|
|
11
|
-
- 🔍 **Query Builder**: Powerful query building with filtering, sorting, and pagination
|
|
12
|
-
- ⚡ **Real-time Updates**: Optional real-time database changes via WebSockets
|
|
13
|
-
- 🧩 **Type Safety**: Full TypeScript support
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- 🔎 **Database Inspection**: Retrieve complete database schema and structure
|
|
17
|
-
- 🔄 **Integration Options**: Use with API package, frontend SDK, REST API, or custom frameworks
|
|
7
|
+
- 🔄 **Multiple Database Support**: Works with SQLite (via Better-SQLite3 or LibSQL), PostgreSQL, MySQL, and other Kysely-supported dialects.
|
|
8
|
+
- 🔒 **Row-Level Security (RLS)**: Fine-grained access control at the row level.
|
|
9
|
+
- 🔐 **Permission Management**: Role-based, team-based, and label-based access control.
|
|
10
|
+
- 📊 **Schema Management**: Create, modify, and delete tables and columns dynamically.
|
|
11
|
+
- 🔍 **Query Builder**: Powerful query building with filtering, sorting, and pagination.
|
|
12
|
+
- ⚡ **Real-time Updates**: Optional real-time database changes via WebSockets or SSE.
|
|
13
|
+
- 🧩 **Type Safety**: Full TypeScript support.
|
|
14
|
+
- 🪝 **Event Hooks**: Pre/Post hooks for queries and mutations (handled internally).
|
|
15
|
+
- 🔎 **Database Inspection**: Retrieve database schema and structure.
|
|
18
16
|
|
|
19
17
|
## Installation
|
|
20
18
|
|
|
21
19
|
```bash
|
|
22
|
-
npm install @forgebase/database
|
|
20
|
+
npm install @forgebase/database kysely
|
|
21
|
+
# Install a driver, for example:
|
|
22
|
+
npm install better-sqlite3
|
|
23
23
|
# or
|
|
24
|
-
|
|
24
|
+
npm install @libsql/client
|
|
25
25
|
# or
|
|
26
|
-
|
|
26
|
+
npm install pg
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Basic Usage
|
|
30
30
|
|
|
31
31
|
### Initialize the Database
|
|
32
32
|
|
|
33
|
+
You can initialize `ForgeDatabase` with a Kysely instance or with specific configuration for LibSQL.
|
|
34
|
+
|
|
35
|
+
#### Option 1: Using an existing Kysely instance
|
|
36
|
+
|
|
33
37
|
```typescript
|
|
34
38
|
import { ForgeDatabase } from '@forgebase/database';
|
|
35
|
-
import
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
useNullAsDefault: true,
|
|
39
|
+
import { Kysely, SqliteDialect } from 'kysely';
|
|
40
|
+
import Database from 'better-sqlite3';
|
|
41
|
+
|
|
42
|
+
// Initialize Kysely
|
|
43
|
+
const db = new Kysely({
|
|
44
|
+
dialect: new SqliteDialect({
|
|
45
|
+
database: new Database('managed.db'),
|
|
46
|
+
}),
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
// Initialize ForgeDatabase
|
|
47
|
-
const
|
|
48
|
-
db:
|
|
50
|
+
const forgeDb = new ForgeDatabase({
|
|
51
|
+
db: db,
|
|
49
52
|
enforceRls: true, // Enable row-level security
|
|
50
53
|
realtime: true, // Enable real-time updates
|
|
51
54
|
});
|
|
52
55
|
```
|
|
53
56
|
|
|
57
|
+
#### Option 2: Using LibSQL Configuration
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { ForgeDatabase } from '@forgebase/database';
|
|
61
|
+
|
|
62
|
+
const forgeDb = new ForgeDatabase({
|
|
63
|
+
libsql: {
|
|
64
|
+
url: 'file:local.db',
|
|
65
|
+
// or
|
|
66
|
+
// url: 'libsql://your-database.turso.io',
|
|
67
|
+
// authToken: 'your-auth-token'
|
|
68
|
+
},
|
|
69
|
+
enforceRls: true,
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
54
73
|
### Schema Operations
|
|
55
74
|
|
|
56
75
|
```typescript
|
|
57
76
|
// Create a new table
|
|
58
|
-
await
|
|
77
|
+
await forgeDb.endpoints.schema.create({
|
|
59
78
|
tableName: 'users',
|
|
60
79
|
columns: [
|
|
61
|
-
{ name: 'id', type: 'increments', primary: true },
|
|
80
|
+
{ name: 'id', type: 'increments', primary: true, nullable: false },
|
|
62
81
|
{ name: 'username', type: 'string', unique: true, nullable: false },
|
|
63
82
|
{ name: 'email', type: 'string', unique: true, nullable: false },
|
|
64
|
-
{ name: '
|
|
65
|
-
{ name: 'role', type: 'string', defaultValue: 'user' },
|
|
66
|
-
{ name: 'created_at', type: 'timestamp', defaultToNow: true },
|
|
83
|
+
{ name: 'created_at', type: 'timestamp', default: 'CURRENT_TIMESTAMP', nullable: false },
|
|
67
84
|
],
|
|
68
85
|
});
|
|
69
86
|
|
|
70
87
|
// Get database schema
|
|
71
|
-
const schema = await
|
|
88
|
+
const schema = await forgeDb.endpoints.schema.get();
|
|
72
89
|
console.log(schema);
|
|
73
90
|
|
|
74
|
-
// Modify a table
|
|
75
|
-
|
|
91
|
+
// Modify a table (Add/Update/Delete columns)
|
|
92
|
+
// Note: 'action' is one of 'addColumn', 'deleteColumn', 'updateColumn'
|
|
93
|
+
await forgeDb.endpoints.schema.modify({
|
|
76
94
|
tableName: 'users',
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
modifyColumns: [{ name: 'role', type: 'string', defaultValue: 'member' }],
|
|
95
|
+
action: 'addColumn',
|
|
96
|
+
columns: [{ name: 'last_login', type: 'string', nullable: true }],
|
|
80
97
|
});
|
|
81
98
|
```
|
|
82
99
|
|
|
83
100
|
### Data Operations
|
|
84
101
|
|
|
102
|
+
All data operations can optionally take a `UserContext` for RLS enforcement and a `Transaction`.
|
|
103
|
+
|
|
85
104
|
```typescript
|
|
86
105
|
// Query data
|
|
87
|
-
const users = await
|
|
106
|
+
const users = await forgeDb.endpoints.data.query(
|
|
88
107
|
'users',
|
|
89
108
|
{
|
|
90
|
-
select: ['id', 'username', 'email'
|
|
109
|
+
select: ['id', 'username', 'email'],
|
|
91
110
|
where: { role: 'admin' },
|
|
92
111
|
orderBy: [{ column: 'created_at', direction: 'desc' }],
|
|
93
112
|
limit: 10,
|
|
94
113
|
offset: 0,
|
|
95
114
|
},
|
|
96
|
-
{
|
|
115
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] }, // User context for RLS
|
|
97
116
|
);
|
|
98
117
|
|
|
99
118
|
// Create data
|
|
100
|
-
const newUser = await
|
|
119
|
+
const newUser = await forgeDb.endpoints.data.create(
|
|
101
120
|
{
|
|
102
121
|
tableName: 'users',
|
|
103
122
|
data: {
|
|
104
123
|
username: 'johndoe',
|
|
105
124
|
email: 'john@example.com',
|
|
106
|
-
password: 'hashedpassword',
|
|
107
125
|
role: 'user',
|
|
108
126
|
},
|
|
109
127
|
},
|
|
110
|
-
{
|
|
128
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] }, // User context
|
|
111
129
|
);
|
|
112
130
|
|
|
113
131
|
// Update data
|
|
114
|
-
await
|
|
132
|
+
await forgeDb.endpoints.data.update(
|
|
115
133
|
{
|
|
116
134
|
tableName: 'users',
|
|
117
135
|
id: 1,
|
|
@@ -119,32 +137,34 @@ await db.endpoints.data.update(
|
|
|
119
137
|
role: 'moderator',
|
|
120
138
|
},
|
|
121
139
|
},
|
|
122
|
-
{
|
|
140
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] },
|
|
123
141
|
);
|
|
124
142
|
|
|
125
143
|
// Delete data
|
|
126
|
-
await
|
|
144
|
+
await forgeDb.endpoints.data.delete(
|
|
127
145
|
{
|
|
128
146
|
tableName: 'users',
|
|
129
147
|
id: 1,
|
|
130
148
|
},
|
|
131
|
-
{
|
|
149
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] },
|
|
132
150
|
);
|
|
133
151
|
```
|
|
134
152
|
|
|
135
153
|
### Permissions Management
|
|
136
154
|
|
|
155
|
+
You can define granular permissions for tables.
|
|
156
|
+
|
|
137
157
|
```typescript
|
|
138
158
|
// Get permissions for a table
|
|
139
|
-
const permissions = await
|
|
159
|
+
const permissions = await forgeDb.getPermissionService().getPermissionsForTable('users');
|
|
140
160
|
|
|
141
161
|
// Set permissions for a table
|
|
142
|
-
await
|
|
162
|
+
await forgeDb.getPermissionService().setPermissionsForTable('users', {
|
|
143
163
|
operations: {
|
|
144
164
|
SELECT: [
|
|
145
165
|
// Allow authenticated users to see their own data
|
|
146
166
|
{
|
|
147
|
-
allow: '
|
|
167
|
+
allow: 'fieldCheck',
|
|
148
168
|
fieldCheck: {
|
|
149
169
|
field: 'id',
|
|
150
170
|
operator: '===',
|
|
@@ -152,20 +172,10 @@ await db.setPermissions('users', {
|
|
|
152
172
|
value: 'userId',
|
|
153
173
|
},
|
|
154
174
|
},
|
|
155
|
-
// Allow admins
|
|
175
|
+
// Allow admins to see all data
|
|
156
176
|
{
|
|
157
177
|
allow: 'role',
|
|
158
|
-
roles: ['admin'
|
|
159
|
-
},
|
|
160
|
-
// Allow users with specific labels
|
|
161
|
-
{
|
|
162
|
-
allow: 'labels',
|
|
163
|
-
labels: ['user_manager'],
|
|
164
|
-
},
|
|
165
|
-
// Allow users in specific teams
|
|
166
|
-
{
|
|
167
|
-
allow: 'teams',
|
|
168
|
-
teams: ['support_team'],
|
|
178
|
+
roles: ['admin'],
|
|
169
179
|
},
|
|
170
180
|
],
|
|
171
181
|
INSERT: [
|
|
@@ -178,7 +188,8 @@ await db.setPermissions('users', {
|
|
|
178
188
|
UPDATE: [
|
|
179
189
|
// Users can update their own data
|
|
180
190
|
{
|
|
181
|
-
allow: 'auth',
|
|
191
|
+
allow: 'auth', // 'auth' generally means "authenticated", but combine with checks if needed,
|
|
192
|
+
// or use specific rules like 'fieldCheck'
|
|
182
193
|
fieldCheck: {
|
|
183
194
|
field: 'id',
|
|
184
195
|
operator: '===',
|
|
@@ -186,26 +197,12 @@ await db.setPermissions('users', {
|
|
|
186
197
|
value: 'userId',
|
|
187
198
|
},
|
|
188
199
|
},
|
|
189
|
-
// Admins and moderators can update any user
|
|
190
|
-
{
|
|
191
|
-
allow: 'role',
|
|
192
|
-
roles: ['admin', 'moderator'],
|
|
193
|
-
},
|
|
194
200
|
],
|
|
195
201
|
DELETE: [
|
|
196
|
-
// Only admins can delete users
|
|
197
202
|
{
|
|
198
203
|
allow: 'role',
|
|
199
204
|
roles: ['admin'],
|
|
200
205
|
},
|
|
201
|
-
// Custom SQL condition for complex rules
|
|
202
|
-
{
|
|
203
|
-
allow: 'customSql',
|
|
204
|
-
customSql: `
|
|
205
|
-
SELECT 1 WHERE
|
|
206
|
-
EXISTS (SELECT 1 FROM user_managers WHERE manager_id = :userId AND user_id = users.id)
|
|
207
|
-
`,
|
|
208
|
-
},
|
|
209
206
|
],
|
|
210
207
|
},
|
|
211
208
|
});
|
|
@@ -213,258 +210,48 @@ await db.setPermissions('users', {
|
|
|
213
210
|
|
|
214
211
|
### Transactions
|
|
215
212
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
There are two ways to use transactions:
|
|
219
|
-
|
|
220
|
-
#### Explicit Transactions
|
|
221
|
-
|
|
222
|
-
Pass a transaction object to each method:
|
|
213
|
+
You can execute operations within a transaction using the `transaction` method.
|
|
223
214
|
|
|
224
215
|
```typescript
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const user = await db.endpoints.data.create(
|
|
216
|
+
await forgeDb.transaction(async (trx) => {
|
|
217
|
+
// Pass 'trx' to operations
|
|
218
|
+
const user = await forgeDb.endpoints.data.create(
|
|
229
219
|
{
|
|
230
220
|
tableName: 'users',
|
|
231
|
-
data: { username: 'jane', email: 'jane@example.com'
|
|
221
|
+
data: { username: 'jane', email: 'jane@example.com' },
|
|
232
222
|
},
|
|
233
|
-
{
|
|
234
|
-
false, //
|
|
235
|
-
trx, // Pass the transaction
|
|
223
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] },
|
|
224
|
+
false, // isSystem
|
|
225
|
+
trx, // Pass the transaction object
|
|
236
226
|
);
|
|
237
227
|
|
|
238
|
-
|
|
239
|
-
await db.endpoints.data.create(
|
|
228
|
+
await forgeDb.endpoints.data.create(
|
|
240
229
|
{
|
|
241
230
|
tableName: 'profiles',
|
|
242
|
-
data: { user_id: user.id, bio: 'New user' },
|
|
231
|
+
data: { user_id: user[0].id, bio: 'New user' },
|
|
243
232
|
},
|
|
244
|
-
{
|
|
233
|
+
{ userId: 1, role: 'admin', labels: [], teams: [] },
|
|
245
234
|
false,
|
|
246
235
|
trx,
|
|
247
236
|
);
|
|
248
237
|
});
|
|
249
238
|
```
|
|
250
239
|
|
|
251
|
-
#### Implicit Transactions
|
|
252
|
-
|
|
253
|
-
Many methods automatically create a transaction if one isn't provided:
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
// This will automatically create a transaction internally
|
|
257
|
-
const user = await db.endpoints.data.create(
|
|
258
|
-
{
|
|
259
|
-
tableName: 'users',
|
|
260
|
-
data: { username: 'john', email: 'john@example.com', password: 'hashedpw' },
|
|
261
|
-
},
|
|
262
|
-
{ id: 1, role: 'admin' },
|
|
263
|
-
);
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Security Best Practices
|
|
267
|
-
|
|
268
|
-
### Row-Level Security (RLS)
|
|
269
|
-
|
|
270
|
-
ForgeBase Database provides powerful row-level security capabilities that allow you to define fine-grained access control rules at the row level. There are several ways to implement RLS:
|
|
271
|
-
|
|
272
|
-
#### Basic RLS with Field Checks
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
// Enable RLS
|
|
276
|
-
const db = new ForgeDatabase({
|
|
277
|
-
enforceRls: true,
|
|
278
|
-
// ...
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// Set row-level policies
|
|
282
|
-
await db.setPermissions('documents', {
|
|
283
|
-
operations: {
|
|
284
|
-
SELECT: [
|
|
285
|
-
{
|
|
286
|
-
allow: 'auth',
|
|
287
|
-
fieldCheck: {
|
|
288
|
-
field: 'owner_id',
|
|
289
|
-
operator: '===',
|
|
290
|
-
valueType: 'userContext',
|
|
291
|
-
value: 'userId',
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
},
|
|
296
|
-
});
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
#### Advanced RLS with Custom SQL
|
|
300
|
-
|
|
301
|
-
For complex permission rules that require database queries:
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
// Example: Limit free users to 5 CVs, but allow pro users unlimited CVs
|
|
305
|
-
await db.setPermissions('cvs', {
|
|
306
|
-
operations: {
|
|
307
|
-
INSERT: [
|
|
308
|
-
{
|
|
309
|
-
allow: 'customSql',
|
|
310
|
-
customSql: `
|
|
311
|
-
SELECT 1 WHERE
|
|
312
|
-
-- Check if user is on pro plan
|
|
313
|
-
EXISTS (SELECT 1 FROM subscriptions WHERE user_id = :userId AND plan_type = 'pro')
|
|
314
|
-
-- OR check if user is on free plan but has fewer than 5 CVs
|
|
315
|
-
OR (
|
|
316
|
-
NOT EXISTS (SELECT 1 FROM subscriptions WHERE user_id = :userId AND plan_type = 'pro')
|
|
317
|
-
AND (SELECT COUNT(*) FROM cvs WHERE user_id = :userId) < 5
|
|
318
|
-
)
|
|
319
|
-
`,
|
|
320
|
-
},
|
|
321
|
-
],
|
|
322
|
-
},
|
|
323
|
-
});
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
#### Advanced RLS with Custom Functions
|
|
327
|
-
|
|
328
|
-
For the most flexible permission rules, you can register custom JavaScript functions:
|
|
329
|
-
|
|
330
|
-
```typescript
|
|
331
|
-
// Register a custom RLS function
|
|
332
|
-
import { rlsFunctionRegistry } from '@forgebase/database';
|
|
333
|
-
|
|
334
|
-
// Register a function that checks subscription limits
|
|
335
|
-
rlsFunctionRegistry.register('checkSubscriptionLimits', async (userContext, row, knex) => {
|
|
336
|
-
if (!knex) return false;
|
|
337
|
-
|
|
338
|
-
// Check if user is on pro plan
|
|
339
|
-
const proSub = await knex('subscriptions').where({ user_id: userContext.userId, plan_type: 'pro' }).first();
|
|
340
|
-
|
|
341
|
-
if (proSub) return true; // Pro users can create unlimited resources
|
|
342
|
-
|
|
343
|
-
// For free users, check resource count
|
|
344
|
-
const count = await knex('cvs').where({ user_id: userContext.userId }).count('id as count').first();
|
|
345
|
-
|
|
346
|
-
return count && count.count < 5; // Allow if less than 5 resources
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
// Use the registered function in permissions
|
|
350
|
-
await db.setPermissions('cvs', {
|
|
351
|
-
operations: {
|
|
352
|
-
INSERT: [
|
|
353
|
-
{
|
|
354
|
-
allow: 'customFunction',
|
|
355
|
-
customFunction: 'checkSubscriptionLimits',
|
|
356
|
-
},
|
|
357
|
-
],
|
|
358
|
-
},
|
|
359
|
-
});
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Automatic Permission Initialization
|
|
363
|
-
|
|
364
|
-
ForgeBase Database can automatically initialize permissions for all tables in your database. This feature is useful when you want to ensure that all tables have at least basic permissions set.
|
|
365
|
-
|
|
366
|
-
#### Configuration
|
|
367
|
-
|
|
368
|
-
You can enable automatic permission initialization when creating the ForgeDatabase instance:
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
const db = new ForgeDatabase({
|
|
372
|
-
db: knexInstance,
|
|
373
|
-
// Enable automatic permission initialization
|
|
374
|
-
initializePermissions: true,
|
|
375
|
-
// Optional: Specify where to save the initialization report
|
|
376
|
-
permissionReportPath: './permission-report.md',
|
|
377
|
-
// Optional: Callback function when initialization completes
|
|
378
|
-
onPermissionInitComplete: (report) => {
|
|
379
|
-
console.log(`Initialized permissions for ${report.tablesInitialized} tables`);
|
|
380
|
-
},
|
|
381
|
-
});
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
#### Manual Initialization
|
|
385
|
-
|
|
386
|
-
You can also manually trigger permission initialization at any time:
|
|
387
|
-
|
|
388
|
-
```typescript
|
|
389
|
-
// Initialize permissions with default options from config
|
|
390
|
-
db.initializePermissions();
|
|
391
|
-
|
|
392
|
-
// Or specify custom options
|
|
393
|
-
db.initializePermissions('./custom-report-path.md', (report) => {
|
|
394
|
-
console.log('Permission initialization completed!');
|
|
395
|
-
console.log(`Tables initialized: ${report.initializedTables.join(', ')}`);
|
|
396
|
-
});
|
|
397
|
-
```
|
|
398
|
-
|
|
399
240
|
### Real-time Updates
|
|
400
241
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
```typescript
|
|
404
|
-
// Enable real-time updates when initializing
|
|
405
|
-
const db = new ForgeDatabase({
|
|
406
|
-
db: knexInstance,
|
|
407
|
-
realtime: true,
|
|
408
|
-
websocketPort: 8080, // Optional, defaults to 8080
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
// The WebSocket server will automatically broadcast changes to connected clients
|
|
412
|
-
```
|
|
242
|
+
> ⚠️ **Note**: The Real-time / WebSocket feature is currently experimental and under active development. It has not been fully tested in production environments yet. Use with caution.
|
|
413
243
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
ForgeBase Database can be easily integrated with frontend applications using the `@forgebase/sdk` package:
|
|
244
|
+
Enable real-time updates to broadcast database changes.
|
|
417
245
|
|
|
418
246
|
```typescript
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
axiosConfig: {
|
|
425
|
-
withCredentials: true, // Important for auth cookies
|
|
426
|
-
},
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
// Query data with a fluent API
|
|
430
|
-
const users = await db.table('users').select('id', 'name', 'email').where('status', 'active').orderBy('name', 'asc').query();
|
|
431
|
-
|
|
432
|
-
// Create a new record
|
|
433
|
-
const newUser = await db.table('users').create({
|
|
434
|
-
name: 'John Doe',
|
|
435
|
-
email: 'john@example.com',
|
|
436
|
-
role: 'user',
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
// Update a record
|
|
440
|
-
await db.table('users').update(123, {
|
|
441
|
-
name: 'John Smith',
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
// Delete a record
|
|
445
|
-
await db.table('users').delete(123);
|
|
446
|
-
|
|
447
|
-
// Real-time updates
|
|
448
|
-
const unsubscribe = db.table('users').subscribe((event) => {
|
|
449
|
-
if (event.type === 'create') {
|
|
450
|
-
console.log('New user created:', event.record);
|
|
451
|
-
} else if (event.type === 'update') {
|
|
452
|
-
console.log('User updated:', event.record);
|
|
453
|
-
} else if (event.type === 'delete') {
|
|
454
|
-
console.log('User deleted:', event.id);
|
|
455
|
-
}
|
|
247
|
+
const forgeDb = new ForgeDatabase({
|
|
248
|
+
db: kyselyInstance,
|
|
249
|
+
realtime: true,
|
|
250
|
+
realtimeAdapter: 'websocket', // or 'sse'
|
|
251
|
+
websocketPort: 9001,
|
|
456
252
|
});
|
|
457
|
-
|
|
458
|
-
// Later, unsubscribe when no longer needed
|
|
459
|
-
unsubscribe();
|
|
460
253
|
```
|
|
461
254
|
|
|
462
|
-
For more details on integration options, see the [Complete Integration](/database/complete-integration) guide.
|
|
463
|
-
|
|
464
|
-
## API Reference
|
|
465
|
-
|
|
466
|
-
For detailed API documentation, please refer to the [ForgeBase Documentation](https://docs.forgebase.dev/database).
|
|
467
|
-
|
|
468
255
|
## License
|
|
469
256
|
|
|
470
|
-
|
|
257
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgebase/database",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"better-sqlite3": "^11.10.0",
|
|
42
42
|
"express": "^4.21.2",
|
|
43
43
|
"pg": "^8.18.0",
|
|
44
|
-
"@forgebase/sdk": "0.0.
|
|
44
|
+
"@forgebase/sdk": "0.0.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/better-sqlite3": "^7.6.12",
|