@gl-life/gl-life-database 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.
Files changed (76) hide show
  1. package/API.md +1486 -0
  2. package/LICENSE +190 -0
  3. package/README.md +480 -0
  4. package/dist/cache/index.d.ts +4 -0
  5. package/dist/cache/index.d.ts.map +1 -0
  6. package/dist/cache/invalidation.d.ts +156 -0
  7. package/dist/cache/invalidation.d.ts.map +1 -0
  8. package/dist/cache/kv-cache.d.ts +79 -0
  9. package/dist/cache/kv-cache.d.ts.map +1 -0
  10. package/dist/cache/memory-cache.d.ts +68 -0
  11. package/dist/cache/memory-cache.d.ts.map +1 -0
  12. package/dist/cloudforge/d1-adapter.d.ts +67 -0
  13. package/dist/cloudforge/d1-adapter.d.ts.map +1 -0
  14. package/dist/cloudforge/do-storage.d.ts +51 -0
  15. package/dist/cloudforge/do-storage.d.ts.map +1 -0
  16. package/dist/cloudforge/index.d.ts +4 -0
  17. package/dist/cloudforge/index.d.ts.map +1 -0
  18. package/dist/cloudforge/r2-backup.d.ts +38 -0
  19. package/dist/cloudforge/r2-backup.d.ts.map +1 -0
  20. package/dist/connection/index.d.ts +2 -0
  21. package/dist/connection/index.d.ts.map +1 -0
  22. package/dist/connection/manager.d.ts +54 -0
  23. package/dist/connection/manager.d.ts.map +1 -0
  24. package/dist/index.cjs +4762 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.ts +18 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +4701 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/migration/index.d.ts +4 -0
  31. package/dist/migration/index.d.ts.map +1 -0
  32. package/dist/migration/loader.d.ts +88 -0
  33. package/dist/migration/loader.d.ts.map +1 -0
  34. package/dist/migration/runner.d.ts +91 -0
  35. package/dist/migration/runner.d.ts.map +1 -0
  36. package/dist/migration/seeder.d.ts +95 -0
  37. package/dist/migration/seeder.d.ts.map +1 -0
  38. package/dist/query/builder.d.ts +47 -0
  39. package/dist/query/builder.d.ts.map +1 -0
  40. package/dist/query/index.d.ts +3 -0
  41. package/dist/query/index.d.ts.map +1 -0
  42. package/dist/query/raw.d.ts +92 -0
  43. package/dist/query/raw.d.ts.map +1 -0
  44. package/dist/tenant/context.d.ts +52 -0
  45. package/dist/tenant/context.d.ts.map +1 -0
  46. package/dist/tenant/index.d.ts +4 -0
  47. package/dist/tenant/index.d.ts.map +1 -0
  48. package/dist/tenant/query-wrapper.d.ts +96 -0
  49. package/dist/tenant/query-wrapper.d.ts.map +1 -0
  50. package/dist/tenant/schema-manager.d.ts +185 -0
  51. package/dist/tenant/schema-manager.d.ts.map +1 -0
  52. package/dist/transaction/index.d.ts +2 -0
  53. package/dist/transaction/index.d.ts.map +1 -0
  54. package/dist/transaction/transaction.d.ts +51 -0
  55. package/dist/transaction/transaction.d.ts.map +1 -0
  56. package/dist/types/cache.d.ts +214 -0
  57. package/dist/types/cache.d.ts.map +1 -0
  58. package/dist/types/cloudforge.d.ts +753 -0
  59. package/dist/types/cloudforge.d.ts.map +1 -0
  60. package/dist/types/connection.d.ts +91 -0
  61. package/dist/types/connection.d.ts.map +1 -0
  62. package/dist/types/index.d.ts +10 -0
  63. package/dist/types/index.d.ts.map +1 -0
  64. package/dist/types/migration.d.ts +225 -0
  65. package/dist/types/migration.d.ts.map +1 -0
  66. package/dist/types/plugin.d.ts +432 -0
  67. package/dist/types/plugin.d.ts.map +1 -0
  68. package/dist/types/query-builder.d.ts +217 -0
  69. package/dist/types/query-builder.d.ts.map +1 -0
  70. package/dist/types/seed.d.ts +187 -0
  71. package/dist/types/seed.d.ts.map +1 -0
  72. package/dist/types/tenant.d.ts +140 -0
  73. package/dist/types/tenant.d.ts.map +1 -0
  74. package/dist/types/transaction.d.ts +144 -0
  75. package/dist/types/transaction.d.ts.map +1 -0
  76. package/package.json +78 -0
package/API.md ADDED
@@ -0,0 +1,1486 @@
1
+ # @gl-life/gl-life-database API Reference
2
+
3
+ **Version**: 1.0.0
4
+ **Package**: `@gl-life/gl-life-database`
5
+ **License**: Apache-2.0
6
+ **Homepage**: https://gl.life
7
+
8
+ ## Table of Contents
9
+
10
+ - [Core Types](#core-types)
11
+ - [Connection Management](#connection-management)
12
+ - [Query Builder](#query-builder)
13
+ - [Transactions](#transactions)
14
+ - [Multi-Tenancy](#multi-tenancy)
15
+ - [Caching](#caching)
16
+ - [Migrations](#migrations)
17
+ - [CloudForge Adapters](#cloudforge-adapters)
18
+ - [Error Handling](#error-handling)
19
+ - [Usage Patterns](#usage-patterns)
20
+
21
+ ---
22
+
23
+ ## Core Types
24
+
25
+ ### Result<T, E>
26
+
27
+ Functional error handling type from `@gl-life/gl-life-core`.
28
+
29
+ ```typescript
30
+ type Result<T, E> = {
31
+ isOk(): boolean;
32
+ isErr(): boolean;
33
+ unwrap(): T;
34
+ unwrapErr(): E;
35
+ unwrapOr(defaultValue: T): T;
36
+ map<U>(fn: (value: T) => U): Result<U, E>;
37
+ mapErr<F>(fn: (error: E) => F): Result<T, F>;
38
+ };
39
+ ```
40
+
41
+ **Usage**:
42
+ ```typescript
43
+ const result: Result<User[], DatabaseError> = await queryUsers();
44
+ if (result.isOk()) {
45
+ const users = result.unwrap();
46
+ } else {
47
+ const error = result.unwrapErr();
48
+ }
49
+ ```
50
+
51
+ ### Option<T>
52
+
53
+ Optional value type from `@gl-life/gl-life-core`.
54
+
55
+ ```typescript
56
+ type Option<T> = {
57
+ isSome(): boolean;
58
+ isNone(): boolean;
59
+ unwrap(): T;
60
+ unwrapOr(defaultValue: T): T;
61
+ map<U>(fn: (value: T) => U): Option<U>;
62
+ };
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Connection Management
68
+
69
+ ### ConnectionManager
70
+
71
+ Manages database connections with pooling support.
72
+
73
+ #### Constructor
74
+
75
+ ```typescript
76
+ class ConnectionManager {
77
+ constructor(logger: Logger);
78
+ }
79
+ ```
80
+
81
+ **Parameters**:
82
+ - `logger: Logger` - Logger instance from `@gl-life/gl-life-core`
83
+
84
+ #### Methods
85
+
86
+ ##### connect()
87
+
88
+ ```typescript
89
+ connect(config: DatabaseConfig): Promise<Result<DatabaseConnection, ConnectionError>>
90
+ ```
91
+
92
+ **Parameters**:
93
+ ```typescript
94
+ interface DatabaseConfig {
95
+ type: 'sqlite' | 'postgres' | 'mysql' | 'd1';
96
+ filename?: string; // SQLite only
97
+ host?: string; // Network databases
98
+ port?: number; // Network databases
99
+ database?: string; // Network databases
100
+ username?: string; // Network databases
101
+ password?: string; // Network databases
102
+ poolSize?: number; // Connection pool size (default: 10)
103
+ timeout?: number; // Connection timeout in ms (default: 30000)
104
+ }
105
+ ```
106
+
107
+ **Returns**: `Result<DatabaseConnection, ConnectionError>`
108
+
109
+ **Example**:
110
+ ```typescript
111
+ const manager = new ConnectionManager(logger);
112
+ const result = await manager.connect({
113
+ type: 'sqlite',
114
+ filename: './database.db'
115
+ });
116
+
117
+ if (result.isOk()) {
118
+ const connection = result.unwrap();
119
+ }
120
+ ```
121
+
122
+ ##### disconnect()
123
+
124
+ ```typescript
125
+ disconnect(): Promise<Result<void, ConnectionError>>
126
+ ```
127
+
128
+ Closes all connections in the pool.
129
+
130
+ ##### getConnection()
131
+
132
+ ```typescript
133
+ getConnection(): Result<DatabaseConnection, ConnectionError>
134
+ ```
135
+
136
+ Returns an available connection from the pool.
137
+
138
+ ---
139
+
140
+ ## Query Builder
141
+
142
+ ### TypeSafeQueryBuilder
143
+
144
+ Fluent API for building type-safe SQL queries.
145
+
146
+ #### Constructor
147
+
148
+ ```typescript
149
+ class TypeSafeQueryBuilder<T = any> {
150
+ constructor(
151
+ tableName: string,
152
+ metaDataService: MetaDataService | null,
153
+ logger: Logger
154
+ );
155
+ }
156
+ ```
157
+
158
+ **Parameters**:
159
+ - `tableName: string` - Target table name
160
+ - `metaDataService: MetaDataService | null` - Optional metadata service for schema validation
161
+ - `logger: Logger` - Logger instance
162
+
163
+ #### Methods
164
+
165
+ ##### select()
166
+
167
+ ```typescript
168
+ select(columns: string[]): TypeSafeQueryBuilder<T>
169
+ ```
170
+
171
+ Specify columns to SELECT.
172
+
173
+ **Example**:
174
+ ```typescript
175
+ builder.select(['id', 'name', 'email'])
176
+ ```
177
+
178
+ ##### where()
179
+
180
+ ```typescript
181
+ where(
182
+ field: string,
183
+ operator: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'IN',
184
+ value: any
185
+ ): TypeSafeQueryBuilder<T>
186
+ ```
187
+
188
+ Add WHERE condition.
189
+
190
+ **Example**:
191
+ ```typescript
192
+ builder.where('status', '=', 'active')
193
+ .where('age', '>', 18)
194
+ ```
195
+
196
+ ##### orWhere()
197
+
198
+ ```typescript
199
+ orWhere(
200
+ field: string,
201
+ operator: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'IN',
202
+ value: any
203
+ ): TypeSafeQueryBuilder<T>
204
+ ```
205
+
206
+ Add OR WHERE condition.
207
+
208
+ ##### whereIn()
209
+
210
+ ```typescript
211
+ whereIn(field: string, values: any[]): TypeSafeQueryBuilder<T>
212
+ ```
213
+
214
+ Add WHERE IN condition.
215
+
216
+ **Example**:
217
+ ```typescript
218
+ builder.whereIn('status', ['active', 'pending', 'verified'])
219
+ ```
220
+
221
+ ##### join()
222
+
223
+ ```typescript
224
+ join(
225
+ table: string,
226
+ leftColumn: string,
227
+ operator: '=' | '!=' | '>' | '<',
228
+ rightColumn: string,
229
+ joinType?: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL'
230
+ ): TypeSafeQueryBuilder<T>
231
+ ```
232
+
233
+ Add JOIN clause.
234
+
235
+ **Example**:
236
+ ```typescript
237
+ builder.join('posts', 'posts.user_id', '=', 'users.id')
238
+ ```
239
+
240
+ ##### orderBy()
241
+
242
+ ```typescript
243
+ orderBy(column: string, direction: 'ASC' | 'DESC'): TypeSafeQueryBuilder<T>
244
+ ```
245
+
246
+ Add ORDER BY clause.
247
+
248
+ ##### groupBy()
249
+
250
+ ```typescript
251
+ groupBy(column: string): TypeSafeQueryBuilder<T>
252
+ ```
253
+
254
+ Add GROUP BY clause.
255
+
256
+ ##### having()
257
+
258
+ ```typescript
259
+ having(condition: string): TypeSafeQueryBuilder<T>
260
+ ```
261
+
262
+ Add HAVING clause.
263
+
264
+ **Example**:
265
+ ```typescript
266
+ builder.groupBy('customer_id')
267
+ .having('COUNT(*) > 5')
268
+ ```
269
+
270
+ ##### limit()
271
+
272
+ ```typescript
273
+ limit(count: number): TypeSafeQueryBuilder<T>
274
+ ```
275
+
276
+ Add LIMIT clause.
277
+
278
+ ##### offset()
279
+
280
+ ```typescript
281
+ offset(count: number): TypeSafeQueryBuilder<T>
282
+ ```
283
+
284
+ Add OFFSET clause.
285
+
286
+ ##### toSQL()
287
+
288
+ ```typescript
289
+ toSQL(): string
290
+ ```
291
+
292
+ Generate SQL string with parameterized placeholders.
293
+
294
+ **Returns**: SQL string with `?` placeholders
295
+
296
+ **Example**:
297
+ ```typescript
298
+ const sql = builder
299
+ .select(['id', 'name'])
300
+ .where('status', '=', 'active')
301
+ .toSQL();
302
+ // Returns: "SELECT id, name FROM users WHERE status = ?"
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Transactions
308
+
309
+ ### TransactionManager
310
+
311
+ Handles database transactions with isolation levels.
312
+
313
+ #### Constructor
314
+
315
+ ```typescript
316
+ class TransactionManager {
317
+ constructor(
318
+ connection: DatabaseConnection,
319
+ config: TransactionConfig,
320
+ logger: Logger
321
+ );
322
+ }
323
+ ```
324
+
325
+ **Parameters**:
326
+ ```typescript
327
+ interface TransactionConfig {
328
+ isolationLevel: 'READ_UNCOMMITTED' | 'READ_COMMITTED' | 'REPEATABLE_READ' | 'SERIALIZABLE';
329
+ timeout: number; // Transaction timeout in ms
330
+ retryAttempts: number; // Number of retry attempts on conflict
331
+ }
332
+ ```
333
+
334
+ #### Methods
335
+
336
+ ##### execute()
337
+
338
+ ```typescript
339
+ execute<T>(
340
+ callback: (tx: DatabaseTransaction) => Promise<T>
341
+ ): Promise<Result<T, TransactionError>>
342
+ ```
343
+
344
+ Execute operations within a transaction.
345
+
346
+ **Example**:
347
+ ```typescript
348
+ const result = await txManager.execute(async (tx) => {
349
+ await tx.execute('INSERT INTO accounts (balance) VALUES (?)', [1000]);
350
+ await tx.execute('UPDATE accounts SET balance = balance - ? WHERE id = ?', [100, 1]);
351
+ await tx.execute('UPDATE accounts SET balance = balance + ? WHERE id = ?', [100, 2]);
352
+ return { success: true };
353
+ });
354
+ ```
355
+
356
+ ### DatabaseTransaction
357
+
358
+ Represents an active transaction.
359
+
360
+ #### Methods
361
+
362
+ ##### execute()
363
+
364
+ ```typescript
365
+ execute(sql: string, params?: any[]): Promise<Result<any, DatabaseError>>
366
+ ```
367
+
368
+ Execute SQL within the transaction.
369
+
370
+ ##### commit()
371
+
372
+ ```typescript
373
+ commit(): Promise<Result<void, TransactionError>>
374
+ ```
375
+
376
+ Commit the transaction.
377
+
378
+ ##### rollback()
379
+
380
+ ```typescript
381
+ rollback(): Promise<Result<void, TransactionError>>
382
+ ```
383
+
384
+ Rollback the transaction.
385
+
386
+ ##### getState()
387
+
388
+ ```typescript
389
+ getState(): 'PENDING' | 'ACTIVE' | 'COMMITTED' | 'ROLLED_BACK'
390
+ ```
391
+
392
+ Get current transaction state.
393
+
394
+ ---
395
+
396
+ ## Multi-Tenancy
397
+
398
+ ### TenantContext
399
+
400
+ Manages tenant context for multi-tenant applications.
401
+
402
+ #### Constructor
403
+
404
+ ```typescript
405
+ class TenantContext {
406
+ constructor(logger: Logger);
407
+ }
408
+ ```
409
+
410
+ #### Methods
411
+
412
+ ##### setTenant()
413
+
414
+ ```typescript
415
+ setTenant(context: TenantContextData): void
416
+ ```
417
+
418
+ Set the current tenant context.
419
+
420
+ **Parameters**:
421
+ ```typescript
422
+ interface TenantContextData {
423
+ tenantId: string;
424
+ isAdmin: boolean;
425
+ metadata?: Record<string, any>;
426
+ }
427
+ ```
428
+
429
+ **Example**:
430
+ ```typescript
431
+ tenantContext.setTenant({
432
+ tenantId: 'tenant-123',
433
+ isAdmin: false
434
+ });
435
+ ```
436
+
437
+ ##### getTenant()
438
+
439
+ ```typescript
440
+ getTenant(): Option<TenantContextData>
441
+ ```
442
+
443
+ Get the current tenant context.
444
+
445
+ ##### clearTenant()
446
+
447
+ ```typescript
448
+ clearTenant(): void
449
+ ```
450
+
451
+ Clear the tenant context.
452
+
453
+ ##### withTenant()
454
+
455
+ ```typescript
456
+ withTenant<T>(
457
+ context: TenantContextData,
458
+ callback: () => Promise<T>
459
+ ): Promise<T>
460
+ ```
461
+
462
+ Execute callback with temporary tenant context.
463
+
464
+ **Example**:
465
+ ```typescript
466
+ const result = await tenantContext.withTenant(
467
+ { tenantId: 'tenant-456', isAdmin: false },
468
+ async () => {
469
+ return await queryUsers();
470
+ }
471
+ );
472
+ ```
473
+
474
+ ### QueryWrapper
475
+
476
+ Wraps queries with automatic tenant filtering.
477
+
478
+ #### Constructor
479
+
480
+ ```typescript
481
+ class QueryWrapper {
482
+ constructor(
483
+ tenantContext: TenantContext,
484
+ logger: Logger
485
+ );
486
+ }
487
+ ```
488
+
489
+ #### Methods
490
+
491
+ ##### query()
492
+
493
+ ```typescript
494
+ query<T>(
495
+ table: string,
496
+ options: QueryOptions,
497
+ config?: QueryConfig
498
+ ): Promise<Result<T[], DatabaseError>>
499
+ ```
500
+
501
+ Execute query with automatic tenant filtering.
502
+
503
+ **Parameters**:
504
+ ```typescript
505
+ interface QueryOptions {
506
+ select?: string[];
507
+ where?: Record<string, any>;
508
+ orderBy?: { column: string; direction: 'ASC' | 'DESC' };
509
+ limit?: number;
510
+ offset?: number;
511
+ }
512
+
513
+ interface QueryConfig {
514
+ bypassTenantFilter?: boolean; // Admin only
515
+ }
516
+ ```
517
+
518
+ **Example**:
519
+ ```typescript
520
+ const result = await wrapper.query('products', {
521
+ where: { status: 'active' },
522
+ orderBy: { column: 'created_at', direction: 'DESC' },
523
+ limit: 10
524
+ });
525
+ // Automatically adds: WHERE tenant_id = ? AND status = ?
526
+ ```
527
+
528
+ ---
529
+
530
+ ## Caching
531
+
532
+ ### MemoryCache
533
+
534
+ In-memory LRU cache for query results.
535
+
536
+ #### Constructor
537
+
538
+ ```typescript
539
+ class MemoryCache {
540
+ constructor(config: CacheConfig, logger: Logger);
541
+ }
542
+ ```
543
+
544
+ **Parameters**:
545
+ ```typescript
546
+ interface CacheConfig {
547
+ enabled: boolean;
548
+ backend: 'MEMORY' | 'KV' | 'HYBRID';
549
+ maxItems?: number; // Max cache entries (default: 1000)
550
+ defaultTTL?: number; // Default TTL in seconds (default: 300)
551
+ evictionPolicy?: 'LRU' | 'LFU' | 'FIFO';
552
+ invalidationStrategy?: 'TIME_BASED' | 'EVENT_BASED' | 'HYBRID';
553
+ keyPrefix?: string; // Key prefix for namespacing
554
+ }
555
+ ```
556
+
557
+ #### Methods
558
+
559
+ ##### get()
560
+
561
+ ```typescript
562
+ get<T>(key: string): Promise<Option<T>>
563
+ ```
564
+
565
+ Get value from cache.
566
+
567
+ **Example**:
568
+ ```typescript
569
+ const result = await cache.get<User>('user:123');
570
+ if (result.isSome()) {
571
+ const user = result.unwrap();
572
+ }
573
+ ```
574
+
575
+ ##### set()
576
+
577
+ ```typescript
578
+ set<T>(key: string, value: T, ttl?: number): Promise<Result<void, CacheError>>
579
+ ```
580
+
581
+ Set value in cache.
582
+
583
+ **Example**:
584
+ ```typescript
585
+ await cache.set('user:123', { id: 123, name: 'Alice' }, 60);
586
+ ```
587
+
588
+ ##### delete()
589
+
590
+ ```typescript
591
+ delete(key: string): Promise<Result<void, CacheError>>
592
+ ```
593
+
594
+ Delete key from cache.
595
+
596
+ ##### has()
597
+
598
+ ```typescript
599
+ has(key: string): Promise<boolean>
600
+ ```
601
+
602
+ Check if key exists in cache.
603
+
604
+ ##### clear()
605
+
606
+ ```typescript
607
+ clear(): Promise<Result<void, CacheError>>
608
+ ```
609
+
610
+ Clear all cache entries.
611
+
612
+ ##### invalidatePattern()
613
+
614
+ ```typescript
615
+ invalidatePattern(pattern: string): Promise<Result<number, CacheError>>
616
+ ```
617
+
618
+ Invalidate all keys matching pattern (supports wildcards).
619
+
620
+ **Example**:
621
+ ```typescript
622
+ await cache.invalidatePattern('user:*');
623
+ ```
624
+
625
+ ##### getStats()
626
+
627
+ ```typescript
628
+ getStats(): CacheStats
629
+ ```
630
+
631
+ Get cache statistics.
632
+
633
+ **Returns**:
634
+ ```typescript
635
+ interface CacheStats {
636
+ hits: number;
637
+ misses: number;
638
+ hitRate: number;
639
+ size: number;
640
+ evictions: number;
641
+ }
642
+ ```
643
+
644
+ ### KVCache
645
+
646
+ Cloudflare Workers KV-backed cache.
647
+
648
+ #### Constructor
649
+
650
+ ```typescript
651
+ class KVCache {
652
+ constructor(
653
+ kv: KVNamespace,
654
+ config: CacheConfig,
655
+ logger: Logger
656
+ );
657
+ }
658
+ ```
659
+
660
+ Methods are identical to `MemoryCache`.
661
+
662
+ ---
663
+
664
+ ## Migrations
665
+
666
+ ### MigrationPlanner
667
+
668
+ Plans and validates database migrations.
669
+
670
+ #### Constructor
671
+
672
+ ```typescript
673
+ class MigrationPlanner {
674
+ constructor(config: MigrationConfig, logger: Logger);
675
+ }
676
+ ```
677
+
678
+ **Parameters**:
679
+ ```typescript
680
+ interface MigrationConfig {
681
+ enabled: boolean;
682
+ migrationTable: string; // Table to track migrations (default: 'migrations')
683
+ autoRun: boolean; // Auto-run migrations on startup (default: false)
684
+ migrationPath?: string; // Path to migration files
685
+ }
686
+ ```
687
+
688
+ #### Methods
689
+
690
+ ##### loadMigrations()
691
+
692
+ ```typescript
693
+ loadMigrations(
694
+ migrations: Migration[]
695
+ ): Promise<Result<void, MigrationError>>
696
+ ```
697
+
698
+ Load migrations from array.
699
+
700
+ **Parameters**:
701
+ ```typescript
702
+ interface Migration {
703
+ version: string;
704
+ name: string;
705
+ up: string; // SQL to apply migration
706
+ down: string; // SQL to rollback migration
707
+ dependencies?: string[];
708
+ }
709
+ ```
710
+
711
+ ##### loadFromDirectory()
712
+
713
+ ```typescript
714
+ loadFromDirectory(
715
+ path: string
716
+ ): Promise<Result<Migration[], MigrationError>>
717
+ ```
718
+
719
+ Load migrations from directory.
720
+
721
+ ##### planMigration()
722
+
723
+ ```typescript
724
+ planMigration(
725
+ targetVersion: string
726
+ ): Result<MigrationPlan, MigrationError>
727
+ ```
728
+
729
+ Plan migration to target version.
730
+
731
+ **Returns**:
732
+ ```typescript
733
+ interface MigrationPlan {
734
+ migrations: Migration[];
735
+ totalSteps: number;
736
+ estimatedDuration: number;
737
+ warnings: string[];
738
+ }
739
+ ```
740
+
741
+ ##### checkStatus()
742
+
743
+ ```typescript
744
+ checkStatus(): Promise<Result<MigrationStatus, MigrationError>>
745
+ ```
746
+
747
+ Check migration status.
748
+
749
+ **Returns**:
750
+ ```typescript
751
+ interface MigrationStatus {
752
+ currentVersion: string;
753
+ appliedMigrations: string[];
754
+ pendingMigrations: string[];
755
+ lastMigrationDate: Date;
756
+ }
757
+ ```
758
+
759
+ ### MigrationExecutor
760
+
761
+ Executes migration plans.
762
+
763
+ #### Constructor
764
+
765
+ ```typescript
766
+ class MigrationExecutor {
767
+ constructor(
768
+ connection: DatabaseConnection,
769
+ logger: Logger
770
+ );
771
+ }
772
+ ```
773
+
774
+ #### Methods
775
+
776
+ ##### executeMigration()
777
+
778
+ ```typescript
779
+ executeMigration(
780
+ plan: MigrationPlan
781
+ ): Promise<Result<MigrationResult, MigrationError>>
782
+ ```
783
+
784
+ Execute migration plan.
785
+
786
+ **Returns**:
787
+ ```typescript
788
+ interface MigrationResult {
789
+ appliedMigrations: string[];
790
+ duration: number;
791
+ success: boolean;
792
+ }
793
+ ```
794
+
795
+ ##### rollback()
796
+
797
+ ```typescript
798
+ rollback(steps?: number): Promise<Result<void, MigrationError>>
799
+ ```
800
+
801
+ Rollback migrations.
802
+
803
+ **Parameters**:
804
+ - `steps?: number` - Number of steps to rollback (default: 1)
805
+
806
+ ---
807
+
808
+ ## CloudForge Adapters
809
+
810
+ ### D1Adapter
811
+
812
+ Cloudflare D1 database adapter.
813
+
814
+ #### Constructor
815
+
816
+ ```typescript
817
+ class D1Adapter {
818
+ constructor(d1: D1Database, logger: Logger);
819
+ }
820
+ ```
821
+
822
+ **Parameters**:
823
+ - `d1: D1Database` - Cloudflare D1 database binding
824
+ - `logger: Logger` - Logger instance
825
+
826
+ #### Methods
827
+
828
+ ##### execute()
829
+
830
+ ```typescript
831
+ execute(
832
+ sql: string,
833
+ params?: any[]
834
+ ): Promise<Result<D1Result, DatabaseError>>
835
+ ```
836
+
837
+ Execute SQL query.
838
+
839
+ **Example**:
840
+ ```typescript
841
+ // In Cloudflare Worker
842
+ export default {
843
+ async fetch(request: Request, env: Env): Promise<Response> {
844
+ const adapter = new D1Adapter(env.DB, logger);
845
+ const result = await adapter.execute(
846
+ 'SELECT * FROM users WHERE id = ?',
847
+ [123]
848
+ );
849
+ return new Response(JSON.stringify(result));
850
+ }
851
+ };
852
+ ```
853
+
854
+ ##### batch()
855
+
856
+ ```typescript
857
+ batch(
858
+ statements: { sql: string; params?: any[] }[]
859
+ ): Promise<Result<D1Result[], DatabaseError>>
860
+ ```
861
+
862
+ Execute batch of statements.
863
+
864
+ ### DurableObjectStorage
865
+
866
+ Durable Objects storage adapter.
867
+
868
+ #### Constructor
869
+
870
+ ```typescript
871
+ class DurableObjectStorage {
872
+ constructor(
873
+ storage: DurableObjectStorage,
874
+ logger: Logger
875
+ );
876
+ }
877
+ ```
878
+
879
+ #### Methods
880
+
881
+ ##### get()
882
+
883
+ ```typescript
884
+ get<T>(key: string): Promise<Option<T>>
885
+ ```
886
+
887
+ Get value from Durable Object storage.
888
+
889
+ ##### put()
890
+
891
+ ```typescript
892
+ put<T>(key: string, value: T): Promise<Result<void, StorageError>>
893
+ ```
894
+
895
+ Store value in Durable Object storage.
896
+
897
+ ##### delete()
898
+
899
+ ```typescript
900
+ delete(key: string): Promise<Result<void, StorageError>>
901
+ ```
902
+
903
+ Delete key from storage.
904
+
905
+ ##### list()
906
+
907
+ ```typescript
908
+ list(options?: ListOptions): Promise<Result<Map<string, any>, StorageError>>
909
+ ```
910
+
911
+ List keys in storage.
912
+
913
+ **Parameters**:
914
+ ```typescript
915
+ interface ListOptions {
916
+ start?: string;
917
+ end?: string;
918
+ prefix?: string;
919
+ limit?: number;
920
+ reverse?: boolean;
921
+ }
922
+ ```
923
+
924
+ ---
925
+
926
+ ## Error Handling
927
+
928
+ All methods return `Result<T, E>` types for functional error handling.
929
+
930
+ ### Error Types
931
+
932
+ #### DatabaseError
933
+
934
+ ```typescript
935
+ class DatabaseError extends Error {
936
+ code: string;
937
+ query?: string;
938
+ params?: any[];
939
+ constructor(message: string, code: string, query?: string, params?: any[]);
940
+ }
941
+ ```
942
+
943
+ **Error Codes**:
944
+ - `DB_CONNECTION_FAILED` - Connection failure
945
+ - `DB_QUERY_FAILED` - Query execution failed
946
+ - `DB_CONSTRAINT_VIOLATION` - Constraint violation
947
+ - `DB_TIMEOUT` - Query timeout
948
+ - `DB_PERMISSION_DENIED` - Permission denied
949
+
950
+ #### TransactionError
951
+
952
+ ```typescript
953
+ class TransactionError extends Error {
954
+ code: string;
955
+ transactionId?: string;
956
+ constructor(message: string, code: string, transactionId?: string);
957
+ }
958
+ ```
959
+
960
+ **Error Codes**:
961
+ - `TX_ALREADY_STARTED` - Transaction already active
962
+ - `TX_NOT_ACTIVE` - Transaction not active
963
+ - `TX_COMMIT_FAILED` - Commit failed
964
+ - `TX_ROLLBACK_FAILED` - Rollback failed
965
+ - `TX_TIMEOUT` - Transaction timeout
966
+
967
+ #### CacheError
968
+
969
+ ```typescript
970
+ class CacheError extends Error {
971
+ code: string;
972
+ key?: string;
973
+ constructor(message: string, code: string, key?: string);
974
+ }
975
+ ```
976
+
977
+ **Error Codes**:
978
+ - `CACHE_GET_FAILED` - Get operation failed
979
+ - `CACHE_SET_FAILED` - Set operation failed
980
+ - `CACHE_DELETE_FAILED` - Delete operation failed
981
+ - `CACHE_FULL` - Cache is full
982
+
983
+ #### MigrationError
984
+
985
+ ```typescript
986
+ class MigrationError extends Error {
987
+ code: string;
988
+ migration?: string;
989
+ constructor(message: string, code: string, migration?: string);
990
+ }
991
+ ```
992
+
993
+ **Error Codes**:
994
+ - `MIGRATION_LOAD_FAILED` - Failed to load migrations
995
+ - `MIGRATION_EXECUTE_FAILED` - Migration execution failed
996
+ - `MIGRATION_ROLLBACK_FAILED` - Rollback failed
997
+ - `MIGRATION_VERSION_CONFLICT` - Version conflict
998
+
999
+ ---
1000
+
1001
+ ## Usage Patterns
1002
+
1003
+ ### Pattern 1: Basic Query with Error Handling
1004
+
1005
+ ```typescript
1006
+ import {
1007
+ ConnectionManager,
1008
+ TypeSafeQueryBuilder,
1009
+ Logger,
1010
+ Result,
1011
+ DatabaseError
1012
+ } from '@gl-life/gl-life-database';
1013
+
1014
+ const logger = new Logger({ level: 'info' });
1015
+ const manager = new ConnectionManager(logger);
1016
+
1017
+ const connResult = await manager.connect({
1018
+ type: 'sqlite',
1019
+ filename: './app.db'
1020
+ });
1021
+
1022
+ if (connResult.isErr()) {
1023
+ console.error('Connection failed:', connResult.unwrapErr());
1024
+ process.exit(1);
1025
+ }
1026
+
1027
+ const connection = connResult.unwrap();
1028
+ const builder = new TypeSafeQueryBuilder('users', null, logger);
1029
+ const sql = builder.select(['*']).where('active', '=', true).toSQL();
1030
+
1031
+ const queryResult = await connection.execute(sql, [true]);
1032
+ if (queryResult.isOk()) {
1033
+ const users = queryResult.unwrap();
1034
+ console.log('Users:', users);
1035
+ }
1036
+ ```
1037
+
1038
+ ### Pattern 2: Multi-Tenant Query
1039
+
1040
+ ```typescript
1041
+ import {
1042
+ TenantContext,
1043
+ QueryWrapper,
1044
+ Logger
1045
+ } from '@gl-life/gl-life-database';
1046
+
1047
+ const logger = new Logger({ level: 'info' });
1048
+ const tenantContext = new TenantContext(logger);
1049
+ const wrapper = new QueryWrapper(tenantContext, logger);
1050
+
1051
+ // Set tenant from request
1052
+ const tenantId = request.headers.get('X-Tenant-ID');
1053
+ tenantContext.setTenant({
1054
+ tenantId,
1055
+ isAdmin: false
1056
+ });
1057
+
1058
+ // Query automatically includes tenant filter
1059
+ const result = await wrapper.query('products', {
1060
+ where: { status: 'active' },
1061
+ limit: 20
1062
+ });
1063
+ // SQL: WHERE tenant_id = ? AND status = ? LIMIT 20
1064
+ ```
1065
+
1066
+ ### Pattern 3: Transaction with Retry
1067
+
1068
+ ```typescript
1069
+ import {
1070
+ TransactionManager,
1071
+ Logger
1072
+ } from '@gl-life/gl-life-database';
1073
+
1074
+ const config = {
1075
+ isolationLevel: 'READ_COMMITTED' as const,
1076
+ timeout: 30000,
1077
+ retryAttempts: 3
1078
+ };
1079
+
1080
+ const txManager = new TransactionManager(connection, config, logger);
1081
+
1082
+ const result = await txManager.execute(async (tx) => {
1083
+ // Transfer money between accounts
1084
+ const debit = await tx.execute(
1085
+ 'UPDATE accounts SET balance = balance - ? WHERE id = ?',
1086
+ [amount, fromAccountId]
1087
+ );
1088
+
1089
+ if (debit.isErr()) throw debit.unwrapErr();
1090
+
1091
+ const credit = await tx.execute(
1092
+ 'UPDATE accounts SET balance = balance + ? WHERE id = ?',
1093
+ [amount, toAccountId]
1094
+ );
1095
+
1096
+ if (credit.isErr()) throw credit.unwrapErr();
1097
+
1098
+ return { transferred: amount };
1099
+ });
1100
+ ```
1101
+
1102
+ ### Pattern 4: Cached Query
1103
+
1104
+ ```typescript
1105
+ import {
1106
+ MemoryCache,
1107
+ Logger,
1108
+ CacheConfig
1109
+ } from '@gl-life/gl-life-database';
1110
+
1111
+ const cacheConfig: CacheConfig = {
1112
+ enabled: true,
1113
+ backend: 'MEMORY',
1114
+ maxItems: 1000,
1115
+ defaultTTL: 300,
1116
+ evictionPolicy: 'LRU',
1117
+ invalidationStrategy: 'TIME_BASED',
1118
+ keyPrefix: 'app:'
1119
+ };
1120
+
1121
+ const cache = new MemoryCache(cacheConfig, logger);
1122
+
1123
+ async function getUser(id: number) {
1124
+ const cacheKey = `user:${id}`;
1125
+
1126
+ // Try cache first
1127
+ const cached = await cache.get<User>(cacheKey);
1128
+ if (cached.isSome()) {
1129
+ return cached.unwrap();
1130
+ }
1131
+
1132
+ // Query database
1133
+ const result = await queryUser(id);
1134
+ if (result.isOk()) {
1135
+ const user = result.unwrap();
1136
+ await cache.set(cacheKey, user, 60);
1137
+ return user;
1138
+ }
1139
+
1140
+ throw result.unwrapErr();
1141
+ }
1142
+
1143
+ // Invalidate on update
1144
+ async function updateUser(id: number, data: Partial<User>) {
1145
+ const result = await executeUpdate(id, data);
1146
+ if (result.isOk()) {
1147
+ await cache.delete(`user:${id}`);
1148
+ }
1149
+ return result;
1150
+ }
1151
+ ```
1152
+
1153
+ ### Pattern 5: Database Migration
1154
+
1155
+ ```typescript
1156
+ import {
1157
+ MigrationPlanner,
1158
+ MigrationExecutor,
1159
+ Logger,
1160
+ MigrationConfig
1161
+ } from '@gl-life/gl-life-database';
1162
+
1163
+ const config: MigrationConfig = {
1164
+ enabled: true,
1165
+ migrationTable: 'migrations',
1166
+ autoRun: false
1167
+ };
1168
+
1169
+ const logger = new Logger({ level: 'info' });
1170
+ const planner = new MigrationPlanner(config, logger);
1171
+ const executor = new MigrationExecutor(connection, logger);
1172
+
1173
+ // Load migrations
1174
+ const migrations = [
1175
+ {
1176
+ version: '001',
1177
+ name: 'create_users',
1178
+ up: 'CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)',
1179
+ down: 'DROP TABLE users'
1180
+ },
1181
+ {
1182
+ version: '002',
1183
+ name: 'add_users_email',
1184
+ up: 'ALTER TABLE users ADD COLUMN email TEXT',
1185
+ down: 'ALTER TABLE users DROP COLUMN email',
1186
+ dependencies: ['001']
1187
+ }
1188
+ ];
1189
+
1190
+ await planner.loadMigrations(migrations);
1191
+
1192
+ // Check status
1193
+ const status = await planner.checkStatus();
1194
+ if (status.isOk()) {
1195
+ console.log('Current version:', status.unwrap().currentVersion);
1196
+ console.log('Pending:', status.unwrap().pendingMigrations);
1197
+ }
1198
+
1199
+ // Plan and execute
1200
+ const plan = planner.planMigration('002');
1201
+ if (plan.isOk()) {
1202
+ const result = await executor.executeMigration(plan.unwrap());
1203
+ console.log('Migration result:', result);
1204
+ }
1205
+ ```
1206
+
1207
+ ### Pattern 6: Cloudflare D1 Worker
1208
+
1209
+ ```typescript
1210
+ import {
1211
+ D1Adapter,
1212
+ Logger,
1213
+ MemoryCache,
1214
+ CacheConfig
1215
+ } from '@gl-life/gl-life-database';
1216
+
1217
+ export default {
1218
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
1219
+ const logger = new Logger({ level: 'info' });
1220
+ const db = new D1Adapter(env.DB, logger);
1221
+
1222
+ // Set up cache
1223
+ const cacheConfig: CacheConfig = {
1224
+ enabled: true,
1225
+ backend: 'MEMORY',
1226
+ maxItems: 100,
1227
+ defaultTTL: 60,
1228
+ evictionPolicy: 'LRU',
1229
+ invalidationStrategy: 'TIME_BASED'
1230
+ };
1231
+ const cache = new MemoryCache(cacheConfig, logger);
1232
+
1233
+ // Parse request
1234
+ const url = new URL(request.url);
1235
+ const userId = url.searchParams.get('id');
1236
+
1237
+ if (!userId) {
1238
+ return new Response('Missing user ID', { status: 400 });
1239
+ }
1240
+
1241
+ // Try cache
1242
+ const cacheKey = `user:${userId}`;
1243
+ const cached = await cache.get(cacheKey);
1244
+
1245
+ if (cached.isSome()) {
1246
+ return new Response(JSON.stringify({
1247
+ data: cached.unwrap(),
1248
+ cached: true
1249
+ }), {
1250
+ headers: { 'Content-Type': 'application/json' }
1251
+ });
1252
+ }
1253
+
1254
+ // Query D1
1255
+ const result = await db.execute(
1256
+ 'SELECT * FROM users WHERE id = ?',
1257
+ [userId]
1258
+ );
1259
+
1260
+ if (result.isErr()) {
1261
+ return new Response(
1262
+ JSON.stringify({ error: result.unwrapErr().message }),
1263
+ { status: 500 }
1264
+ );
1265
+ }
1266
+
1267
+ const data = result.unwrap();
1268
+ await cache.set(cacheKey, data, 60);
1269
+
1270
+ return new Response(JSON.stringify({
1271
+ data,
1272
+ cached: false
1273
+ }), {
1274
+ headers: { 'Content-Type': 'application/json' }
1275
+ });
1276
+ }
1277
+ };
1278
+ ```
1279
+
1280
+ ---
1281
+
1282
+ ## Type Definitions Summary
1283
+
1284
+ ### Connection Types
1285
+
1286
+ ```typescript
1287
+ type DatabaseType = 'sqlite' | 'postgres' | 'mysql' | 'd1';
1288
+
1289
+ interface DatabaseConfig {
1290
+ type: DatabaseType;
1291
+ filename?: string;
1292
+ host?: string;
1293
+ port?: number;
1294
+ database?: string;
1295
+ username?: string;
1296
+ password?: string;
1297
+ poolSize?: number;
1298
+ timeout?: number;
1299
+ }
1300
+
1301
+ interface DatabaseConnection {
1302
+ execute(sql: string, params?: any[]): Promise<Result<any, DatabaseError>>;
1303
+ close(): Promise<Result<void, ConnectionError>>;
1304
+ }
1305
+ ```
1306
+
1307
+ ### Query Types
1308
+
1309
+ ```typescript
1310
+ type Operator = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'IN';
1311
+ type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
1312
+ type SortDirection = 'ASC' | 'DESC';
1313
+
1314
+ interface WhereCondition {
1315
+ field: string;
1316
+ operator: Operator;
1317
+ value: any;
1318
+ connector: 'AND' | 'OR';
1319
+ }
1320
+
1321
+ interface JoinClause {
1322
+ table: string;
1323
+ leftColumn: string;
1324
+ operator: string;
1325
+ rightColumn: string;
1326
+ joinType: JoinType;
1327
+ }
1328
+ ```
1329
+
1330
+ ### Transaction Types
1331
+
1332
+ ```typescript
1333
+ type IsolationLevel =
1334
+ | 'READ_UNCOMMITTED'
1335
+ | 'READ_COMMITTED'
1336
+ | 'REPEATABLE_READ'
1337
+ | 'SERIALIZABLE';
1338
+
1339
+ type TransactionState =
1340
+ | 'PENDING'
1341
+ | 'ACTIVE'
1342
+ | 'COMMITTED'
1343
+ | 'ROLLED_BACK';
1344
+
1345
+ interface TransactionConfig {
1346
+ isolationLevel: IsolationLevel;
1347
+ timeout: number;
1348
+ retryAttempts: number;
1349
+ }
1350
+ ```
1351
+
1352
+ ### Cache Types
1353
+
1354
+ ```typescript
1355
+ type CacheBackend = 'MEMORY' | 'KV' | 'HYBRID';
1356
+ type EvictionPolicy = 'LRU' | 'LFU' | 'FIFO';
1357
+ type InvalidationStrategy = 'TIME_BASED' | 'EVENT_BASED' | 'HYBRID';
1358
+
1359
+ interface CacheConfig {
1360
+ enabled: boolean;
1361
+ backend: CacheBackend;
1362
+ maxItems?: number;
1363
+ defaultTTL?: number;
1364
+ evictionPolicy?: EvictionPolicy;
1365
+ invalidationStrategy?: InvalidationStrategy;
1366
+ keyPrefix?: string;
1367
+ }
1368
+
1369
+ interface CacheStats {
1370
+ hits: number;
1371
+ misses: number;
1372
+ hitRate: number;
1373
+ size: number;
1374
+ evictions: number;
1375
+ }
1376
+ ```
1377
+
1378
+ ### Migration Types
1379
+
1380
+ ```typescript
1381
+ interface Migration {
1382
+ version: string;
1383
+ name: string;
1384
+ up: string;
1385
+ down: string;
1386
+ dependencies?: string[];
1387
+ }
1388
+
1389
+ interface MigrationConfig {
1390
+ enabled: boolean;
1391
+ migrationTable: string;
1392
+ autoRun: boolean;
1393
+ migrationPath?: string;
1394
+ }
1395
+
1396
+ interface MigrationStatus {
1397
+ currentVersion: string;
1398
+ appliedMigrations: string[];
1399
+ pendingMigrations: string[];
1400
+ lastMigrationDate: Date;
1401
+ }
1402
+
1403
+ interface MigrationPlan {
1404
+ migrations: Migration[];
1405
+ totalSteps: number;
1406
+ estimatedDuration: number;
1407
+ warnings: string[];
1408
+ }
1409
+ ```
1410
+
1411
+ ### Tenant Types
1412
+
1413
+ ```typescript
1414
+ interface TenantContextData {
1415
+ tenantId: string;
1416
+ isAdmin: boolean;
1417
+ metadata?: Record<string, any>;
1418
+ }
1419
+
1420
+ interface QueryOptions {
1421
+ select?: string[];
1422
+ where?: Record<string, any>;
1423
+ orderBy?: { column: string; direction: 'ASC' | 'DESC' };
1424
+ limit?: number;
1425
+ offset?: number;
1426
+ }
1427
+
1428
+ interface QueryConfig {
1429
+ bypassTenantFilter?: boolean;
1430
+ }
1431
+ ```
1432
+
1433
+ ---
1434
+
1435
+ ## Performance Considerations
1436
+
1437
+ ### Query Builder
1438
+
1439
+ - Query building overhead: **<1ms** (P95)
1440
+ - Supports parameterized queries to prevent SQL injection
1441
+ - Minimal memory footprint per query (~0.001 MB)
1442
+
1443
+ ### Cache
1444
+
1445
+ - GET operation: **<1ms** (P95)
1446
+ - SET operation: **<1ms** (P95)
1447
+ - Pattern invalidation (100 keys): **<10ms** (P95)
1448
+ - LRU eviction prevents unbounded memory growth
1449
+
1450
+ ### Transactions
1451
+
1452
+ - Automatic retry on conflict
1453
+ - Configurable isolation levels
1454
+ - Timeout protection
1455
+
1456
+ ---
1457
+
1458
+ ## Security Features
1459
+
1460
+ - ✅ **SQL Injection Protection** - All queries use parameterized statements
1461
+ - ✅ **Tenant Isolation** - Automatic tenant_id filtering prevents data leaks
1462
+ - ✅ **Type Safety** - TypeScript compile-time + Zod runtime validation
1463
+ - ✅ **Audit Logging** - All operations logged for security auditing
1464
+
1465
+ See [SECURITY.md](./SECURITY.md) for security audit results.
1466
+
1467
+ ---
1468
+
1469
+ ## Version Compatibility
1470
+
1471
+ - **TypeScript**: 5.0+
1472
+ - **Node.js**: 18+
1473
+ - **Cloudflare Workers**: Compatible
1474
+ - **Deno**: Compatible (use npm: imports)
1475
+
1476
+ ---
1477
+
1478
+ ## Support
1479
+
1480
+ For questions or issues:
1481
+ - Email: [packages@gl.life](mailto:packages@gl.life)
1482
+ - Website: [gl.life](https://gl.life)
1483
+
1484
+ ---
1485
+
1486
+ **Part of the GoodLife Sargam ecosystem**