@gl-life/gl-life-database 1.0.0 → 1.1.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.
Files changed (75) hide show
  1. package/API.md +450 -1
  2. package/README.md +173 -3
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +21 -3
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/dist/cache/index.d.ts +0 -4
  10. package/dist/cache/index.d.ts.map +0 -1
  11. package/dist/cache/invalidation.d.ts +0 -156
  12. package/dist/cache/invalidation.d.ts.map +0 -1
  13. package/dist/cache/kv-cache.d.ts +0 -79
  14. package/dist/cache/kv-cache.d.ts.map +0 -1
  15. package/dist/cache/memory-cache.d.ts +0 -68
  16. package/dist/cache/memory-cache.d.ts.map +0 -1
  17. package/dist/cloudforge/d1-adapter.d.ts +0 -67
  18. package/dist/cloudforge/d1-adapter.d.ts.map +0 -1
  19. package/dist/cloudforge/do-storage.d.ts +0 -51
  20. package/dist/cloudforge/do-storage.d.ts.map +0 -1
  21. package/dist/cloudforge/index.d.ts +0 -4
  22. package/dist/cloudforge/index.d.ts.map +0 -1
  23. package/dist/cloudforge/r2-backup.d.ts +0 -38
  24. package/dist/cloudforge/r2-backup.d.ts.map +0 -1
  25. package/dist/connection/index.d.ts +0 -2
  26. package/dist/connection/index.d.ts.map +0 -1
  27. package/dist/connection/manager.d.ts +0 -54
  28. package/dist/connection/manager.d.ts.map +0 -1
  29. package/dist/index.d.ts.map +0 -1
  30. package/dist/migration/index.d.ts +0 -4
  31. package/dist/migration/index.d.ts.map +0 -1
  32. package/dist/migration/loader.d.ts +0 -88
  33. package/dist/migration/loader.d.ts.map +0 -1
  34. package/dist/migration/runner.d.ts +0 -91
  35. package/dist/migration/runner.d.ts.map +0 -1
  36. package/dist/migration/seeder.d.ts +0 -95
  37. package/dist/migration/seeder.d.ts.map +0 -1
  38. package/dist/query/builder.d.ts +0 -47
  39. package/dist/query/builder.d.ts.map +0 -1
  40. package/dist/query/index.d.ts +0 -3
  41. package/dist/query/index.d.ts.map +0 -1
  42. package/dist/query/raw.d.ts +0 -92
  43. package/dist/query/raw.d.ts.map +0 -1
  44. package/dist/tenant/context.d.ts +0 -52
  45. package/dist/tenant/context.d.ts.map +0 -1
  46. package/dist/tenant/index.d.ts +0 -4
  47. package/dist/tenant/index.d.ts.map +0 -1
  48. package/dist/tenant/query-wrapper.d.ts +0 -96
  49. package/dist/tenant/query-wrapper.d.ts.map +0 -1
  50. package/dist/tenant/schema-manager.d.ts +0 -185
  51. package/dist/tenant/schema-manager.d.ts.map +0 -1
  52. package/dist/transaction/index.d.ts +0 -2
  53. package/dist/transaction/index.d.ts.map +0 -1
  54. package/dist/transaction/transaction.d.ts +0 -51
  55. package/dist/transaction/transaction.d.ts.map +0 -1
  56. package/dist/types/cache.d.ts +0 -214
  57. package/dist/types/cache.d.ts.map +0 -1
  58. package/dist/types/cloudforge.d.ts +0 -753
  59. package/dist/types/cloudforge.d.ts.map +0 -1
  60. package/dist/types/connection.d.ts +0 -91
  61. package/dist/types/connection.d.ts.map +0 -1
  62. package/dist/types/index.d.ts +0 -10
  63. package/dist/types/index.d.ts.map +0 -1
  64. package/dist/types/migration.d.ts +0 -225
  65. package/dist/types/migration.d.ts.map +0 -1
  66. package/dist/types/plugin.d.ts +0 -432
  67. package/dist/types/plugin.d.ts.map +0 -1
  68. package/dist/types/query-builder.d.ts +0 -217
  69. package/dist/types/query-builder.d.ts.map +0 -1
  70. package/dist/types/seed.d.ts +0 -187
  71. package/dist/types/seed.d.ts.map +0 -1
  72. package/dist/types/tenant.d.ts +0 -140
  73. package/dist/types/tenant.d.ts.map +0 -1
  74. package/dist/types/transaction.d.ts +0 -144
  75. package/dist/types/transaction.d.ts.map +0 -1
package/API.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @gl-life/gl-life-database API Reference
2
2
 
3
- **Version**: 1.0.0
3
+ **Version**: 1.1.1
4
4
  **Package**: `@gl-life/gl-life-database`
5
5
  **License**: Apache-2.0
6
6
  **Homepage**: https://gl.life
@@ -9,11 +9,13 @@
9
9
 
10
10
  - [Core Types](#core-types)
11
11
  - [Connection Management](#connection-management)
12
+ - [Enterprise Database Support](#enterprise-database-support)
12
13
  - [Query Builder](#query-builder)
13
14
  - [Transactions](#transactions)
14
15
  - [Multi-Tenancy](#multi-tenancy)
15
16
  - [Caching](#caching)
16
17
  - [Migrations](#migrations)
18
+ - [Flex Table System](#flex-table-system)
17
19
  - [CloudForge Adapters](#cloudforge-adapters)
18
20
  - [Error Handling](#error-handling)
19
21
  - [Usage Patterns](#usage-patterns)
@@ -137,6 +139,205 @@ Returns an available connection from the pool.
137
139
 
138
140
  ---
139
141
 
142
+ ## Enterprise Database Support
143
+
144
+ Full support for enterprise databases with bring-your-own-database (BYOD) deployments.
145
+
146
+ ### Supported Databases
147
+
148
+ #### SQL Server (Microsoft)
149
+
150
+ ```typescript
151
+ interface SQLServerConfig {
152
+ type: 'sqlserver';
153
+ host: string;
154
+ port?: number; // Default: 1433
155
+ database: string;
156
+ username: string;
157
+ password: string;
158
+ options?: {
159
+ encrypt?: boolean; // Required for Azure SQL
160
+ trustServerCertificate?: boolean;
161
+ connectionTimeout?: number;
162
+ requestTimeout?: number;
163
+ pool?: {
164
+ max?: number;
165
+ min?: number;
166
+ idleTimeoutMillis?: number;
167
+ };
168
+ };
169
+ }
170
+ ```
171
+
172
+ **Example**:
173
+ ```typescript
174
+ const connection = await manager.connect({
175
+ type: 'sqlserver',
176
+ host: 'sql-server.database.windows.net',
177
+ port: 1433,
178
+ database: 'production',
179
+ username: 'admin',
180
+ password: process.env.DB_PASSWORD,
181
+ options: {
182
+ encrypt: true,
183
+ trustServerCertificate: false,
184
+ connectionTimeout: 30000,
185
+ pool: {
186
+ max: 20,
187
+ min: 5,
188
+ idleTimeoutMillis: 30000
189
+ }
190
+ }
191
+ });
192
+ ```
193
+
194
+ #### PostgreSQL
195
+
196
+ ```typescript
197
+ interface PostgreSQLConfig {
198
+ type: 'postgres';
199
+ host: string;
200
+ port?: number; // Default: 5432
201
+ database: string;
202
+ username: string;
203
+ password: string;
204
+ options?: {
205
+ ssl?: boolean | object;
206
+ poolSize?: number;
207
+ idleTimeoutMillis?: number;
208
+ connectionTimeoutMillis?: number;
209
+ schema?: string;
210
+ };
211
+ }
212
+ ```
213
+
214
+ **Example**:
215
+ ```typescript
216
+ const connection = await manager.connect({
217
+ type: 'postgres',
218
+ host: 'postgres-cluster.company.com',
219
+ port: 5432,
220
+ database: 'production',
221
+ username: 'dbuser',
222
+ password: process.env.DB_PASSWORD,
223
+ options: {
224
+ ssl: { rejectUnauthorized: false },
225
+ poolSize: 20,
226
+ schema: 'public'
227
+ }
228
+ });
229
+ ```
230
+
231
+ #### MySQL / MariaDB
232
+
233
+ ```typescript
234
+ interface MySQLConfig {
235
+ type: 'mysql';
236
+ host: string;
237
+ port?: number; // Default: 3306
238
+ database: string;
239
+ username: string;
240
+ password: string;
241
+ options?: {
242
+ connectionLimit?: number;
243
+ charset?: string;
244
+ timezone?: string;
245
+ ssl?: boolean | object;
246
+ };
247
+ }
248
+ ```
249
+
250
+ **Example**:
251
+ ```typescript
252
+ const connection = await manager.connect({
253
+ type: 'mysql',
254
+ host: 'mysql-primary.internal.com',
255
+ port: 3306,
256
+ database: 'production',
257
+ username: 'app_user',
258
+ password: process.env.DB_PASSWORD,
259
+ options: {
260
+ connectionLimit: 10,
261
+ charset: 'utf8mb4',
262
+ timezone: 'Z'
263
+ }
264
+ });
265
+ ```
266
+
267
+ #### Oracle Database
268
+
269
+ ```typescript
270
+ interface OracleConfig {
271
+ type: 'oracle';
272
+ host: string;
273
+ port?: number; // Default: 1521
274
+ database: string; // Service name
275
+ username: string;
276
+ password: string;
277
+ options?: {
278
+ poolMax?: number;
279
+ poolMin?: number;
280
+ poolIncrement?: number;
281
+ poolTimeout?: number;
282
+ };
283
+ }
284
+ ```
285
+
286
+ **Example**:
287
+ ```typescript
288
+ const connection = await manager.connect({
289
+ type: 'oracle',
290
+ host: 'oracle-db.company.com',
291
+ port: 1521,
292
+ database: 'ORCL',
293
+ username: 'system',
294
+ password: process.env.DB_PASSWORD,
295
+ options: {
296
+ poolMax: 10,
297
+ poolMin: 2,
298
+ poolIncrement: 1
299
+ }
300
+ });
301
+ ```
302
+
303
+ ### Enterprise Features
304
+
305
+ All features work identically across all database engines:
306
+
307
+ - ✅ **Flex Table System** - Dynamic schemas work on any database
308
+ - ✅ **Multi-Tenancy** - Row-Level Security on all engines
309
+ - ✅ **Caching** - Cache layer independent of database type
310
+ - ✅ **Migrations** - Version control for any database
311
+ - ✅ **Transactions** - ACID compliance on all supported databases
312
+ - ✅ **Connection Pooling** - Automatic connection management
313
+
314
+ ### Hybrid Deployments
315
+
316
+ Mix cloud and on-premise databases in the same application:
317
+
318
+ ```typescript
319
+ // Cloud database for non-sensitive data
320
+ const cloudConn = await manager.connect({
321
+ type: 'd1',
322
+ binding: env.DB
323
+ });
324
+
325
+ // Enterprise database for sensitive data
326
+ const enterpriseConn = await manager.connect({
327
+ type: 'sqlserver',
328
+ host: 'on-premise-sql.company.local',
329
+ database: 'customer_data',
330
+ username: 'app_user',
331
+ password: process.env.DB_PASSWORD
332
+ });
333
+
334
+ // Use both in same application
335
+ const products = await cloudConn.execute('SELECT * FROM products');
336
+ const customers = await enterpriseConn.execute('SELECT * FROM customers WHERE tenant_id = ?', [tenantId]);
337
+ ```
338
+
339
+ ---
340
+
140
341
  ## Query Builder
141
342
 
142
343
  ### TypeSafeQueryBuilder
@@ -805,6 +1006,254 @@ Rollback migrations.
805
1006
 
806
1007
  ---
807
1008
 
1009
+ ## Flex Table System
1010
+
1011
+ The Flex Table System provides dynamic schema capabilities without ALTER TABLE operations. From `gl-life-data`.
1012
+
1013
+ ### MetaDataService
1014
+
1015
+ Manages metadata mappings between logical and physical field names.
1016
+
1017
+ #### Constructor
1018
+
1019
+ ```typescript
1020
+ class MetaDataService {
1021
+ constructor(dbPath: string);
1022
+ }
1023
+ ```
1024
+
1025
+ **Parameters**:
1026
+ - `dbPath: string` - Path to SQLite database containing metadata
1027
+
1028
+ #### Methods
1029
+
1030
+ ##### createMapping()
1031
+
1032
+ ```typescript
1033
+ createMapping(input: CreateMappingInput): Promise<MetadataSelect>
1034
+ ```
1035
+
1036
+ Creates a new metadata mapping, automatically assigning the next available physical field.
1037
+
1038
+ **Parameters**:
1039
+ ```typescript
1040
+ interface CreateMappingInput {
1041
+ tableName: string;
1042
+ logicalFieldName: string;
1043
+ dataType: 'string' | 'int' | 'decimal' | 'date' | 'boolean' | 'text' | 'datetime' | 'float' | 'bigint' | 'uuid';
1044
+ isRequired?: boolean;
1045
+ defaultValue?: string | null;
1046
+ validationRules?: ValidationRules;
1047
+ description?: string;
1048
+ displayOrder?: number;
1049
+ isIndexed?: boolean;
1050
+ isUnique?: boolean;
1051
+ foreignKeyRef?: string | null;
1052
+ createdBy?: string;
1053
+ }
1054
+ ```
1055
+
1056
+ **Returns**: `Promise<MetadataSelect>` - Created metadata entry
1057
+
1058
+ **Example**:
1059
+ ```typescript
1060
+ const metaDataService = new MetaDataService('./database.db');
1061
+
1062
+ await metaDataService.createMapping({
1063
+ tableName: 'products',
1064
+ logicalFieldName: 'productName',
1065
+ dataType: 'string', // Will map to string_field_1
1066
+ isRequired: true,
1067
+ description: 'Product name'
1068
+ });
1069
+ ```
1070
+
1071
+ ##### getMappingByLogicalField()
1072
+
1073
+ ```typescript
1074
+ getMappingByLogicalField(tableName: string, logicalFieldName: string): MetadataSelect | null
1075
+ ```
1076
+
1077
+ **Parameters**:
1078
+ - `tableName: string` - Entity table name
1079
+ - `logicalFieldName: string` - Logical field name to look up
1080
+
1081
+ **Returns**: `MetadataSelect | null` - Metadata entry or null if not found
1082
+
1083
+ ##### getTableMappings()
1084
+
1085
+ ```typescript
1086
+ getTableMappings(tableName: string): MetadataSelect[]
1087
+ ```
1088
+
1089
+ **Parameters**:
1090
+ - `tableName: string` - Entity table name
1091
+
1092
+ **Returns**: `MetadataSelect[]` - All metadata mappings for the table
1093
+
1094
+ ### Using Flex Tables with TypeSafeQueryBuilder
1095
+
1096
+ ```typescript
1097
+ import { TypeSafeQueryBuilder, Logger } from '@gl-life/gl-life-database';
1098
+ import { MetaDataService } from 'gl-life-data';
1099
+
1100
+ const logger = new Logger({ level: 'info' });
1101
+ const metaDataService = new MetaDataService('./database.db');
1102
+
1103
+ // Create mappings
1104
+ await metaDataService.createMapping({
1105
+ tableName: 'products',
1106
+ logicalFieldName: 'name',
1107
+ dataType: 'string' // Maps to string_field_1
1108
+ });
1109
+
1110
+ await metaDataService.createMapping({
1111
+ tableName: 'products',
1112
+ logicalFieldName: 'price',
1113
+ dataType: 'decimal' // Maps to decimal_field_1
1114
+ });
1115
+
1116
+ // Query using logical field names
1117
+ const builder = new TypeSafeQueryBuilder('products', metaDataService, logger);
1118
+ const sql = builder
1119
+ .select(['name', 'price']) // Logical names
1120
+ .where('price', '>', 100)
1121
+ .toSQL();
1122
+
1123
+ // Generates: SELECT string_field_1, decimal_field_1
1124
+ // FROM flex_table
1125
+ // WHERE decimal_field_1 > ?
1126
+ ```
1127
+
1128
+ ### Flex Table Schema
1129
+
1130
+ Universal schema for all Flex tables:
1131
+
1132
+ ```sql
1133
+ CREATE TABLE flex_table (
1134
+ id TEXT PRIMARY KEY,
1135
+ tenant_id TEXT,
1136
+
1137
+ -- String fields (10 slots)
1138
+ string_field_1 TEXT,
1139
+ string_field_2 TEXT,
1140
+ string_field_3 TEXT,
1141
+ ...
1142
+ string_field_10 TEXT,
1143
+
1144
+ -- Integer fields (10 slots)
1145
+ int_field_1 INTEGER,
1146
+ int_field_2 INTEGER,
1147
+ ...
1148
+ int_field_10 INTEGER,
1149
+
1150
+ -- Decimal fields (10 slots)
1151
+ decimal_field_1 REAL,
1152
+ ...
1153
+ decimal_field_10 REAL,
1154
+
1155
+ -- Date fields (10 slots)
1156
+ date_field_1 TEXT,
1157
+ ...
1158
+ date_field_10 TEXT,
1159
+
1160
+ -- Boolean fields (10 slots)
1161
+ boolean_field_1 INTEGER,
1162
+ ...
1163
+ boolean_field_10 INTEGER,
1164
+
1165
+ -- Text fields (10 slots)
1166
+ text_field_1 TEXT,
1167
+ ...
1168
+ text_field_10 TEXT,
1169
+
1170
+ -- Additional field types (10 slots each):
1171
+ -- datetime_field_1 through datetime_field_10
1172
+ -- float_field_1 through float_field_10
1173
+ -- bigint_field_1 through bigint_field_10
1174
+ -- uuid_field_1 through uuid_field_10
1175
+
1176
+ -- Overflow for extra fields
1177
+ json_data TEXT,
1178
+
1179
+ -- Timestamps
1180
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
1181
+ updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
1182
+ );
1183
+ ```
1184
+
1185
+ ### Metadata Table Schema
1186
+
1187
+ ```sql
1188
+ CREATE TABLE metadata (
1189
+ id TEXT PRIMARY KEY,
1190
+ tenant_id TEXT, -- NULL for shared, or specific tenant ID
1191
+ table_name TEXT NOT NULL,
1192
+ logical_field_name TEXT NOT NULL,
1193
+ physical_column_name TEXT NOT NULL,
1194
+ data_type TEXT NOT NULL,
1195
+ is_required INTEGER NOT NULL DEFAULT 0,
1196
+ default_value TEXT,
1197
+ validation_rules TEXT, -- JSON
1198
+ description TEXT,
1199
+ display_order INTEGER,
1200
+ is_indexed INTEGER NOT NULL DEFAULT 0,
1201
+ is_unique INTEGER NOT NULL DEFAULT 0,
1202
+ foreign_key_ref TEXT,
1203
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
1204
+ updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
1205
+ created_by TEXT,
1206
+ updated_by TEXT,
1207
+ UNIQUE(tenant_id, table_name, logical_field_name),
1208
+ UNIQUE(tenant_id, table_name, physical_column_name)
1209
+ );
1210
+ ```
1211
+
1212
+ ### Flex Tables + Multi-Tenancy
1213
+
1214
+ Combine Flex tables with multi-tenancy for per-tenant custom fields:
1215
+
1216
+ ```typescript
1217
+ // Shared field for all tenants
1218
+ await metaDataService.createMapping({
1219
+ tableName: 'products',
1220
+ logicalFieldName: 'name',
1221
+ dataType: 'string'
1222
+ });
1223
+
1224
+ // Tenant-specific field (Tenant A only)
1225
+ await connection.execute(`
1226
+ INSERT INTO metadata (
1227
+ id, tenant_id, table_name, logical_field_name,
1228
+ physical_column_name, data_type
1229
+ ) VALUES (?, ?, ?, ?, ?, ?)
1230
+ `, [
1231
+ 'tenantA_products_warranty',
1232
+ 'tenant-A',
1233
+ 'products',
1234
+ 'warrantyMonths',
1235
+ 'int_field_1', // Tenant A uses int_field_1
1236
+ 'int'
1237
+ ]);
1238
+
1239
+ // Tenant-specific field (Tenant B only)
1240
+ await connection.execute(`
1241
+ INSERT INTO metadata (
1242
+ id, tenant_id, table_name, logical_field_name,
1243
+ physical_column_name, data_type
1244
+ ) VALUES (?, ?, ?, ?, ?, ?)
1245
+ `, [
1246
+ 'tenantB_products_size',
1247
+ 'tenant-B',
1248
+ 'products',
1249
+ 'size',
1250
+ 'string_field_2', // Tenant B uses string_field_2
1251
+ 'string'
1252
+ ]);
1253
+ ```
1254
+
1255
+ ---
1256
+
808
1257
  ## CloudForge Adapters
809
1258
 
810
1259
  ### D1Adapter
package/README.md CHANGED
@@ -4,15 +4,17 @@ Enhanced gl-life-data wrapper with CloudForge features - Type-safe database abst
4
4
 
5
5
  ## About
6
6
 
7
- `@gl-life/gl-life-database` is a comprehensive database abstraction layer that extends gl-life-data with enterprise features for multi-tenant SaaS applications running on Cloudflare Workers. Built with TypeScript and designed for type safety, it provides a robust foundation for building scalable database-driven applications.
7
+ `@gl-life/gl-life-database` is a comprehensive database abstraction layer that extends gl-life-data with enterprise features for multi-tenant SaaS applications. Built with TypeScript and designed for type safety, it supports both cloud-native deployments (Cloudflare Workers) and enterprise bring-your-own-database (BYOD) scenarios with SQL Server, MySQL, PostgreSQL, Oracle, and more. Perfect for pro users who want to leverage their existing infrastructure while gaining powerful features like Flex tables, multi-tenancy, and intelligent caching.
8
8
 
9
9
  ### Key Features
10
10
 
11
11
  - 🗄️ **Type-Safe Query Builder** - Fluent API with full TypeScript support extending gl-life-data
12
+ - 🔀 **Flex Table System** - Dynamic schema without ALTER TABLE, metadata-driven field mapping
13
+ - 🏢 **Enterprise Database Support** - Full support for SQL Server, MySQL, PostgreSQL, Oracle, and more
12
14
  - 👥 **Multi-Tenancy** - Built-in tenant isolation with Row-Level Security (RLS)
13
- - ⚡ **Caching Layer** - High-performance query result caching with memory and Cloudflare KV backends
15
+ - ⚡ **Flexible Caching** - Memory cache, Redis, or Cloudflare KV backends
14
16
  - 🔄 **Migrations** - Version-controlled database migrations with rollback support
15
- - ☁️ **CloudForge Integration** - Native support for D1, Durable Objects, Workers KV, and R2
17
+ - ☁️ **Cloud + On-Premise** - Deploy on Cloudflare Workers OR bring your own infrastructure
16
18
  - 🔒 **SQL Injection Protection** - Parameterized queries with automatic sanitization
17
19
  - 🧪 **Well-Tested** - >95% test coverage with comprehensive security tests
18
20
  - 📊 **Performance Optimized** - Query building overhead <1ms (P95)
@@ -180,6 +182,174 @@ export default {
180
182
  };
181
183
  ```
182
184
 
185
+ ### Enterprise Database Support (BYOD - Bring Your Own Database)
186
+
187
+ Pro users can connect to their existing enterprise databases instead of using Cloudflare Workers. Full support for:
188
+
189
+ #### SQL Server (Microsoft)
190
+
191
+ ```typescript
192
+ import { ConnectionManager, Logger } from '@gl-life/gl-life-database';
193
+
194
+ const logger = new Logger({ level: 'info' });
195
+ const manager = new ConnectionManager(logger);
196
+
197
+ const connection = await manager.connect({
198
+ type: 'sqlserver',
199
+ host: 'your-sql-server.database.windows.net',
200
+ port: 1433,
201
+ database: 'production_db',
202
+ username: 'admin',
203
+ password: process.env.DB_PASSWORD,
204
+ options: {
205
+ encrypt: true, // Azure SQL requires encryption
206
+ trustServerCertificate: false,
207
+ connectionTimeout: 30000
208
+ }
209
+ });
210
+
211
+ // All features work identically: Flex tables, multi-tenancy, caching, migrations
212
+ const builder = new TypeSafeQueryBuilder('users', metaDataService, logger);
213
+ // ... same as any other database
214
+ ```
215
+
216
+ #### PostgreSQL
217
+
218
+ ```typescript
219
+ const connection = await manager.connect({
220
+ type: 'postgres',
221
+ host: 'your-postgres-instance.com',
222
+ port: 5432,
223
+ database: 'production_db',
224
+ username: 'dbuser',
225
+ password: process.env.DB_PASSWORD,
226
+ options: {
227
+ ssl: { rejectUnauthorized: false },
228
+ poolSize: 20,
229
+ idleTimeoutMillis: 30000
230
+ }
231
+ });
232
+ ```
233
+
234
+ #### MySQL / MariaDB
235
+
236
+ ```typescript
237
+ const connection = await manager.connect({
238
+ type: 'mysql',
239
+ host: 'mysql-cluster.internal.com',
240
+ port: 3306,
241
+ database: 'production_db',
242
+ username: 'dbuser',
243
+ password: process.env.DB_PASSWORD,
244
+ options: {
245
+ connectionLimit: 10,
246
+ charset: 'utf8mb4',
247
+ timezone: 'Z'
248
+ }
249
+ });
250
+ ```
251
+
252
+ #### Oracle Database
253
+
254
+ ```typescript
255
+ const connection = await manager.connect({
256
+ type: 'oracle',
257
+ host: 'oracle-enterprise.company.com',
258
+ port: 1521,
259
+ database: 'ORCL', // Service name
260
+ username: 'system',
261
+ password: process.env.DB_PASSWORD,
262
+ options: {
263
+ poolMax: 10,
264
+ poolMin: 2,
265
+ poolIncrement: 1
266
+ }
267
+ });
268
+ ```
269
+
270
+ #### SQLite (Development/Testing)
271
+
272
+ ```typescript
273
+ const connection = await manager.connect({
274
+ type: 'sqlite',
275
+ filename: './dev.db' // Or ':memory:' for in-memory
276
+ });
277
+ ```
278
+
279
+ **Key Benefits for Enterprise Users:**
280
+ - ✅ **Use Existing Infrastructure** - No migration required, connect to your current databases
281
+ - ✅ **All Features Work** - Flex tables, multi-tenancy, caching, migrations work on any database
282
+ - ✅ **Security Compliant** - Keep data on-premise, meet regulatory requirements
283
+ - ✅ **Cost Control** - Use your existing database licenses and hardware
284
+ - ✅ **Hybrid Deployments** - Mix cloud (D1) and on-premise databases in same application
285
+ - ✅ **Connection Pooling** - Built-in connection management for all enterprise databases
286
+
287
+ ### Flex Table System
288
+
289
+ The Flex Table System is a powerful feature from gl-life-data that provides dynamic schema capabilities without ALTER TABLE operations. Perfect for multi-tenant SaaS applications where each tenant needs custom fields.
290
+
291
+ ```typescript
292
+ import { TypeSafeQueryBuilder, Logger } from '@gl-life/gl-life-database';
293
+ import { MetaDataService } from 'gl-life-data';
294
+
295
+ // Initialize metadata service
296
+ const metaDataService = new MetaDataService('./database.db');
297
+
298
+ // Create metadata mapping: logical field → physical column
299
+ await metaDataService.createMapping({
300
+ tableName: 'products',
301
+ logicalFieldName: 'productName',
302
+ dataType: 'string', // Maps to string_field_1
303
+ isRequired: true,
304
+ description: 'Product name'
305
+ });
306
+
307
+ await metaDataService.createMapping({
308
+ tableName: 'products',
309
+ logicalFieldName: 'price',
310
+ dataType: 'decimal', // Maps to decimal_field_1
311
+ isRequired: true
312
+ });
313
+
314
+ // Query using logical field names
315
+ const builder = new TypeSafeQueryBuilder('products', metaDataService, logger);
316
+ const sql = builder
317
+ .select(['productName', 'price']) // Uses logical names
318
+ .where('price', '>', 100)
319
+ .toSQL();
320
+ // Generates: SELECT string_field_1, decimal_field_1 FROM flex_table WHERE decimal_field_1 > ?
321
+ ```
322
+
323
+ **Key Benefits:**
324
+ - **Universal Schema**: All tables use same physical structure (string_field_1, int_field_1, etc.)
325
+ - **No ALTER TABLE**: Add fields by creating metadata entries
326
+ - **Type Safety**: 10 fields per data type (string, int, decimal, date, boolean, text, datetime, float, bigint, uuid)
327
+ - **Multi-Tenant Ready**: Different tenants can have different custom fields
328
+ - **Query Transparency**: Use logical field names, metadata handles physical mapping
329
+
330
+ **Flex Table Schema:**
331
+ ```sql
332
+ CREATE TABLE flex_table (
333
+ id TEXT PRIMARY KEY,
334
+ tenant_id TEXT,
335
+ -- 10 string fields
336
+ string_field_1 TEXT,
337
+ string_field_2 TEXT,
338
+ ...
339
+ string_field_10 TEXT,
340
+ -- 10 int fields
341
+ int_field_1 INTEGER,
342
+ ...
343
+ int_field_10 INTEGER,
344
+ -- Plus: decimal, date, boolean, text, datetime, float, bigint, uuid fields
345
+ json_data TEXT, -- Overflow for extra fields
346
+ created_at TEXT,
347
+ updated_at TEXT
348
+ );
349
+ ```
350
+
351
+ See [examples/06-flex-tables.ts](./examples/06-flex-tables.ts) and [examples/07-flex-with-multi-tenancy.ts](./examples/07-flex-with-multi-tenancy.ts) for complete workflows.
352
+
183
353
  ## Usage
184
354
 
185
355
  ### Query Builder
package/dist/index.cjs CHANGED
@@ -4719,7 +4719,7 @@ var R2BackupAdapter = class {
4719
4719
  };
4720
4720
 
4721
4721
  // src/index.ts
4722
- var version = "1.0.0";
4722
+ var version = "1.1.0";
4723
4723
 
4724
4724
  Object.defineProperty(exports, "Config", {
4725
4725
  enumerable: true,