Skip to content

Commit be93315

Browse files
Claudehotlong
andauthored
docs: add comprehensive driver configuration guide and tests
- Add multi-driver.test.ts with tests for all 5 driver types - Add driver-factory.test.ts with cache key tests - Add DRIVER_CONFIG.md with complete usage guide - Document migration path from hardcoded Turso - Include examples for dev/staging/prod scenarios - Add type safety and troubleshooting sections Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/ad2ea41d-bf29-42ea-af00-fcc7d6deea5f Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 8fafcdd commit be93315

3 files changed

Lines changed: 612 additions & 0 deletions

File tree

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
# Organization Database Driver Configuration
2+
3+
## Overview
4+
5+
Organizations in ObjectStack can now choose their own database driver, enabling flexible deployment scenarios:
6+
7+
- **Development/Testing**: Use `memory` driver for fast, ephemeral data
8+
- **Production Cloud**: Use `turso` driver for edge-ready cloud deployment
9+
- **Enterprise On-Premise**: Use `sql` driver with PostgreSQL/MySQL/etc.
10+
- **Local Development**: Use `sqlite` driver for file-based storage
11+
- **Custom Solutions**: Use `custom` driver for proprietary implementations
12+
13+
## Supported Drivers
14+
15+
### 1. Turso Driver (Production Cloud)
16+
17+
```typescript
18+
const driverConfig = {
19+
driver: 'turso',
20+
databaseUrl: 'libsql://uuid.turso.io',
21+
authToken: process.env.TURSO_AUTH_TOKEN!,
22+
region: 'us-east-1', // optional
23+
syncUrl: 'libsql://sync.turso.io', // optional for embedded replicas
24+
};
25+
```
26+
27+
**Use Cases:**
28+
- Production SaaS deployments
29+
- Edge-ready applications
30+
- Global distribution
31+
32+
### 2. Memory Driver (Development/Testing)
33+
34+
```typescript
35+
const driverConfig = {
36+
driver: 'memory',
37+
persistent: false, // data lost on restart
38+
dataFile: '/tmp/org-dev.db', // optional for persistence
39+
};
40+
```
41+
42+
**Use Cases:**
43+
- Unit testing
44+
- Integration testing
45+
- Rapid prototyping
46+
- Metadata schema development
47+
48+
### 3. SQL Driver (Enterprise)
49+
50+
```typescript
51+
const driverConfig = {
52+
driver: 'sql',
53+
dialect: 'postgresql', // or 'mysql', 'mariadb', 'mssql'
54+
host: 'localhost',
55+
port: 5432,
56+
database: 'org_enterprise_001',
57+
username: 'app_user',
58+
password: process.env.DB_PASSWORD!,
59+
ssl: true,
60+
pool: {
61+
min: 2,
62+
max: 10,
63+
},
64+
};
65+
```
66+
67+
**Use Cases:**
68+
- Enterprise on-premise deployments
69+
- Regulatory/compliance requirements
70+
- Existing PostgreSQL/MySQL infrastructure
71+
72+
### 4. SQLite Driver (Local Development)
73+
74+
```typescript
75+
const driverConfig = {
76+
driver: 'sqlite',
77+
filename: '/data/org-local.db',
78+
readonly: false,
79+
};
80+
```
81+
82+
**Use Cases:**
83+
- Local development
84+
- Embedded applications
85+
- Portable database files
86+
87+
### 5. Custom Driver
88+
89+
```typescript
90+
const driverConfig = {
91+
driver: 'custom',
92+
driverName: 'my-custom-driver',
93+
config: {
94+
endpoint: 'https://api.custom-db.com',
95+
apiKey: process.env.CUSTOM_API_KEY!,
96+
// ... driver-specific config
97+
},
98+
};
99+
```
100+
101+
**Use Cases:**
102+
- Proprietary database systems
103+
- Third-party integrations
104+
- Specialized storage solutions
105+
106+
## Usage Examples
107+
108+
### Provision Organization with Driver
109+
110+
```typescript
111+
import { TenantProvisioningService } from '@objectstack/service-tenant';
112+
113+
const provisioningService = new TenantProvisioningService({
114+
controlPlaneDriver: globalDriver,
115+
defaultStorageLimitMb: 1024,
116+
});
117+
118+
// Production: Turso driver
119+
const result = await provisioningService.provisionTenant({
120+
organizationId: 'org-prod-001',
121+
driverConfig: {
122+
driver: 'turso',
123+
databaseUrl: 'libsql://550e8400.turso.io',
124+
authToken: process.env.TURSO_TOKEN!,
125+
},
126+
plan: 'pro',
127+
storageLimitMb: 5120,
128+
});
129+
130+
console.log('Tenant provisioned:', result.tenant.id);
131+
```
132+
133+
### Get Driver for Organization
134+
135+
```typescript
136+
import { TenantContextService } from '@objectstack/service-tenant';
137+
138+
const tenantContext = new TenantContextService({
139+
enabled: true,
140+
controlPlaneDriver: globalDriver,
141+
driverFactoryConfig: {
142+
driverConstructors: new Map([
143+
['turso', TursoDriver],
144+
['memory', InMemoryDriver],
145+
['sql', SQLDriver],
146+
]),
147+
},
148+
});
149+
150+
// Get driver instance for an organization
151+
const driver = await tenantContext.getDriverForOrganization('org-001');
152+
153+
// Use driver for data operations
154+
const users = await driver.find('user', {
155+
filter: { status: 'active' },
156+
});
157+
```
158+
159+
### Driver Factory Setup
160+
161+
```typescript
162+
import { DriverFactory } from '@objectstack/service-tenant';
163+
import { TursoDriver } from '@objectstack/driver-turso';
164+
import { InMemoryDriver } from '@objectstack/driver-memory';
165+
import { SQLDriver } from '@objectstack/driver-sql';
166+
167+
const factory = new DriverFactory({
168+
driverConstructors: new Map([
169+
['turso', TursoDriver],
170+
['memory', InMemoryDriver],
171+
['sql', SQLDriver],
172+
]),
173+
});
174+
175+
// Create driver from config
176+
const driver = await factory.create(driverConfig);
177+
```
178+
179+
## Migration Guide
180+
181+
### From Hardcoded Turso to Flexible Drivers
182+
183+
**Before:**
184+
```typescript
185+
const tenant = {
186+
id: 'uuid',
187+
organizationId: 'org-001',
188+
databaseName: 'uuid',
189+
databaseUrl: 'libsql://uuid.turso.io',
190+
authToken: 'encrypted-token',
191+
region: 'us-east-1',
192+
// ...
193+
};
194+
```
195+
196+
**After:**
197+
```typescript
198+
const tenant = {
199+
id: 'uuid',
200+
organizationId: 'org-001',
201+
driverConfig: {
202+
driver: 'turso',
203+
databaseUrl: 'libsql://uuid.turso.io',
204+
authToken: 'encrypted-token',
205+
region: 'us-east-1',
206+
},
207+
// ...
208+
};
209+
```
210+
211+
### Updating Control Plane Schema
212+
213+
The `sys_tenant_database` object now uses `driver_config` instead of separate fields:
214+
215+
```sql
216+
-- Old schema (deprecated)
217+
database_name TEXT
218+
database_url TEXT
219+
auth_token TEXT
220+
region TEXT
221+
222+
-- New schema
223+
driver_config TEXT -- JSON-serialized DriverConfig
224+
```
225+
226+
## Best Practices
227+
228+
### 1. Development Setup
229+
```typescript
230+
// Use memory driver for fast tests
231+
const devConfig = {
232+
driver: 'memory',
233+
persistent: false,
234+
};
235+
```
236+
237+
### 2. Staging Environment
238+
```typescript
239+
// Use SQLite for staging
240+
const stagingConfig = {
241+
driver: 'sqlite',
242+
filename: '/data/staging.db',
243+
};
244+
```
245+
246+
### 3. Production Multi-Region
247+
```typescript
248+
// Use Turso with regional endpoints
249+
const prodConfig = {
250+
driver: 'turso',
251+
databaseUrl: 'libsql://org-us-east.turso.io',
252+
authToken: process.env.TURSO_TOKEN!,
253+
region: 'us-east-1',
254+
};
255+
```
256+
257+
### 4. Enterprise Compliance
258+
```typescript
259+
// Use on-premise PostgreSQL
260+
const enterpriseConfig = {
261+
driver: 'sql',
262+
dialect: 'postgresql',
263+
host: 'internal-db.company.com',
264+
database: 'org_data',
265+
ssl: true,
266+
};
267+
```
268+
269+
## Architecture Benefits
270+
271+
1. **Flexibility**: Choose the right storage for each use case
272+
2. **Development Speed**: Use memory driver for rapid iteration
273+
3. **Cost Optimization**: Scale storage based on needs
274+
4. **Compliance**: Meet data residency requirements
275+
5. **Future-Proof**: Easy to add new driver types
276+
277+
## Type Safety
278+
279+
All driver configurations are type-safe using discriminated unions:
280+
281+
```typescript
282+
type DriverConfig =
283+
| TursoDriverConfig
284+
| MemoryDriverConfig
285+
| SQLDriverConfig
286+
| SQLiteDriverConfig
287+
| CustomDriverConfig;
288+
289+
// TypeScript knows which fields are available
290+
if (config.driver === 'turso') {
291+
console.log(config.databaseUrl); // ✅ OK
292+
console.log(config.host); // ❌ Error: Property 'host' does not exist
293+
}
294+
```
295+
296+
## Testing
297+
298+
```typescript
299+
import { describe, it, expect } from 'vitest';
300+
import { TenantProvisioningService } from '@objectstack/service-tenant';
301+
302+
describe('Multi-Driver Support', () => {
303+
it('should provision with memory driver', async () => {
304+
const service = new TenantProvisioningService();
305+
306+
const result = await service.provisionTenant({
307+
organizationId: 'test-org',
308+
driverConfig: {
309+
driver: 'memory',
310+
persistent: false,
311+
},
312+
});
313+
314+
expect(result.tenant.driverConfig.driver).toBe('memory');
315+
});
316+
});
317+
```
318+
319+
## Troubleshooting
320+
321+
### Driver Constructor Not Registered
322+
323+
```typescript
324+
// Error: "Turso driver constructor not registered"
325+
326+
// Solution: Register constructor in factory
327+
const factory = new DriverFactory({
328+
driverConstructors: new Map([
329+
['turso', TursoDriver], // Add this
330+
]),
331+
});
332+
```
333+
334+
### Cache Issues
335+
336+
```typescript
337+
// Clear driver cache if needed
338+
factory.clearCache();
339+
340+
// Or invalidate specific driver
341+
factory.invalidateDriver('turso:libsql://uuid.turso.io');
342+
```
343+
344+
## Further Reading
345+
346+
- [Turso Driver Documentation](../driver-turso/README.md)
347+
- [Memory Driver Documentation](../driver-memory/README.md)
348+
- [SQL Driver Documentation](../driver-sql/README.md)
349+
- [Multi-Tenant Architecture](../../docs/MULTI_TENANT.md)

0 commit comments

Comments
 (0)