@dqcai/sqlite 2.0.5 → 2.1.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.
package/README.md CHANGED
@@ -4,50 +4,51 @@
4
4
  ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)
5
5
  ![Cross Platform](https://img.shields.io/badge/Platform-Universal-green)
6
6
 
7
- UniversalSQLite một thư viện SQLite toàn diện, hỗ trợ đa nền tảng, được thiết kế để hoạt động mượt mà trên các môi trường như Browser, Node.js, Deno, Bun React Native. Thư viện cung cấp giao diện thống nhất để quản lý cơ sở dữ liệu SQLite, bao gồm tạo schema, CRUD, query nâng cao, migration, import/export dữ liệu, quản transaction. sử dụng mô hình DAO (Data Access Object) để tách biệt logic truy cập dữ liệu, hỗ trợ role-based access control, tích hợp dễ dàng với các framework.
7
+ UniversalSQLite is a comprehensive, cross-platform SQLite library designed to work seamlessly across environments like Browser, Node.js, Deno, Bun, and React Native. The library provides a unified interface for managing SQLite databases, including schema creation, CRUD operations, advanced queries, migrations, data import/export, transaction management, and service lifecycle management. It uses the DAO (Data Access Object) pattern to separate data access logic, supports role-based access control, and integrates easily with various frameworks.
8
8
 
9
9
  ## Features
10
10
 
11
- - **Cross-Platform Support**: Hoạt động trên Browser, Node.js, Deno, Bun, React Native (iOS/Android/Windows).
12
- - **Schema-Based Management**: Tạo quản database từ JSON schema.
13
- - **DAO Pattern**: UniversalDAO để thực hiện CRUD, query, transaction.
14
- - **Query Builder**: Xây dựng query phức tạp với join, where, group by, having, union, CTE.
15
- - **Migration System**: Quản migration với up/down scripts.
16
- - **Data Import/Export**: Hỗ trợ import từ CSV/JSON với mapping, validation, export to CSV.
17
- - **Role-Based Access**: Quản kết nối dựa trên role người dùng.
18
- - **Transaction Management**: Hỗ trợ transaction đơn và cross-schema.
19
- - **Adapters**: Tự động detect môi trường, hỗ trợ register adapter tùy chỉnh.
20
- - **Type-Safe**: Đầy đủ types TypeScript cho schema, query, và operations.
21
- - **Utilities**: CSVImporter, MigrationManager, BaseService cho service layer.
22
- - **DatabaseManager**: Quản lý kết nối, schema vai trò người dùng
23
- - **BaseService**: Lớp sở cho CRUD operations
11
+ - **Cross-Platform Support**: Works on Browser, Node.js, Deno, Bun, React Native (iOS/Android/Windows).
12
+ - **Schema-Based Management**: Create and manage databases from JSON schemas.
13
+ - **DAO Pattern**: UniversalDAO for CRUD operations, queries, and transactions.
14
+ - **Query Builder**: Build complex queries with join, where, group by, having, union, CTE.
15
+ - **Migration System**: Manage migrations with up/down scripts.
16
+ - **Data Import/Export**: Support import from CSV/JSON with mapping, validation, and export to CSV.
17
+ - **Role-Based Access**: Manage connections based on user roles.
18
+ - **Transaction Management**: Support single and cross-schema transactions.
19
+ - **Service Management**: Lifecycle management for service instances with ServiceManager.
20
+ - **Adapters**: Auto-detect environment, support custom adapter registration.
21
+ - **Type-Safe**: Full TypeScript types for schema, queries, and operations.
22
+ - **Utilities**: CSVImporter, MigrationManager, BaseService for service layer.
23
+ - **DatabaseManager**: Manage connections, schemas, and user roles.
24
+ - **BaseService**: Base class for CRUD operations with built-in optimization.
24
25
 
25
26
  ## Installation
26
27
 
27
- Cài đặt qua npm hoặc yarn:
28
+ Install via npm or yarn:
28
29
 
29
30
  ```bash
30
- npm install @dqcai/sqlite@2.0.0
31
- # hoặc
32
- yarn add @dqcai/sqlite@2.0.0
31
+ npm install @dqcai/sqlite@2.1.0
32
+ # or
33
+ yarn add @dqcai/sqlite@2.1.0
33
34
  ```
34
35
 
35
- Đối với React Native, đảm bảo cài đặt các dependencies cần thiết cho adapter (nếu sử dụng adapter cụ thể như react-native-sqlite-storage).
36
+ For React Native, ensure you install the necessary dependencies for the adapter (if using specific adapters like react-native-sqlite-storage).
36
37
 
37
- ## Cài đặt
38
+ ## Quick Start
38
39
 
39
40
  ```bash
40
41
  npm install @dqcai/sqlite
41
42
  ```
42
43
 
43
- ## 1. Cấu hình Schema Database
44
+ ## 1. Database Schema Configuration
44
45
 
45
- Trước tiên, định nghĩa schema cho sở dữ liệu:
46
+ First, define the schema for your database:
46
47
 
47
48
  ```typescript
48
49
  import { DatabaseSchema } from '@dqcai/sqlite';
49
50
 
50
- // Schema cho database users
51
+ // Schema for users database
51
52
  const userSchema: DatabaseSchema = {
52
53
  version: "1.0.0",
53
54
  database_name: "users",
@@ -158,7 +159,7 @@ const userSchema: DatabaseSchema = {
158
159
  }
159
160
  };
160
161
 
161
- // Schema core cho hệ thống
162
+ // Core schema for system
162
163
  const coreSchema: DatabaseSchema = {
163
164
  version: "1.0.0",
164
165
  database_name: "core",
@@ -187,17 +188,211 @@ const coreSchema: DatabaseSchema = {
187
188
  };
188
189
  ```
189
190
 
190
- ## 2. Setup cho React Native
191
+ ## 2. Service Management with ServiceManager
191
192
 
192
- ### Cài đặt dependencies
193
+ ### Service Configuration and Registration
194
+
195
+ The ServiceManager provides centralized lifecycle management for service instances:
196
+
197
+ ```typescript
198
+ // services/ServiceRegistration.ts
199
+ import { ServiceManager, ServiceConfig } from '@dqcai/sqlite';
200
+ import { UserService, ProfileService } from './UserService';
201
+ import { SettingsService } from './CoreService';
202
+
203
+ export class ServiceRegistration {
204
+ private static serviceManager = ServiceManager.getInstance();
205
+
206
+ static registerAllServices(): void {
207
+ const serviceConfigs: ServiceConfig[] = [
208
+ // User services
209
+ {
210
+ schemaName: 'users',
211
+ tableName: 'users',
212
+ primaryKeyFields: ['id'],
213
+ serviceClass: UserService
214
+ },
215
+ {
216
+ schemaName: 'users',
217
+ tableName: 'profiles',
218
+ primaryKeyFields: ['id'],
219
+ serviceClass: ProfileService
220
+ },
221
+ // Core services
222
+ {
223
+ schemaName: 'core',
224
+ tableName: 'settings',
225
+ primaryKeyFields: ['key'],
226
+ serviceClass: SettingsService
227
+ }
228
+ ];
229
+
230
+ // Register all services at once
231
+ this.serviceManager.registerServices(serviceConfigs);
232
+
233
+ console.log('All services registered successfully');
234
+ }
235
+
236
+ static async getService<T = BaseService>(
237
+ schemaName: string,
238
+ tableName: string
239
+ ): Promise<T> {
240
+ const service = await this.serviceManager.getService(schemaName, tableName);
241
+ return service as T;
242
+ }
243
+
244
+ static async initializeService<T = BaseService>(
245
+ schemaName: string,
246
+ tableName: string
247
+ ): Promise<T> {
248
+ const service = await this.serviceManager.initializeService(schemaName, tableName);
249
+ return service as T;
250
+ }
251
+
252
+ static async destroyService(schemaName: string, tableName: string): Promise<boolean> {
253
+ return await this.serviceManager.destroyService(schemaName, tableName);
254
+ }
255
+
256
+ static async getHealthReport() {
257
+ return await this.serviceManager.healthCheck();
258
+ }
259
+
260
+ static getServiceInfo() {
261
+ return this.serviceManager.getAllServiceInfo();
262
+ }
263
+ }
264
+ ```
265
+
266
+ ### Advanced Service Management
267
+
268
+ ```typescript
269
+ // services/ServiceMonitor.ts
270
+ import { ServiceManager, ServiceManagerEvent } from '@dqcai/sqlite';
271
+
272
+ export class ServiceMonitor {
273
+ private serviceManager = ServiceManager.getInstance();
274
+
275
+ constructor() {
276
+ this.setupEventHandlers();
277
+ }
278
+
279
+ private setupEventHandlers(): void {
280
+ // Monitor service lifecycle events
281
+ this.serviceManager.on('SERVICE_CREATED', this.onServiceCreated);
282
+ this.serviceManager.on('SERVICE_DESTROYED', this.onServiceDestroyed);
283
+ this.serviceManager.on('SERVICE_ERROR', this.onServiceError);
284
+ this.serviceManager.on('HEALTH_CHECK_COMPLETED', this.onHealthCheckCompleted);
285
+ }
286
+
287
+ private onServiceCreated = (event: ServiceManagerEvent): void => {
288
+ console.log(`Service created: ${event.serviceKey}`, {
289
+ schema: event.schemaName,
290
+ table: event.tableName,
291
+ timestamp: event.timestamp
292
+ });
293
+ };
294
+
295
+ private onServiceDestroyed = (event: ServiceManagerEvent): void => {
296
+ console.log(`Service destroyed: ${event.serviceKey}`, {
297
+ schema: event.schemaName,
298
+ table: event.tableName,
299
+ timestamp: event.timestamp
300
+ });
301
+ };
302
+
303
+ private onServiceError = (event: ServiceManagerEvent): void => {
304
+ console.error(`Service error in ${event.serviceKey}:`, {
305
+ error: event.error?.message,
306
+ schema: event.schemaName,
307
+ table: event.tableName,
308
+ timestamp: event.timestamp
309
+ });
310
+ };
311
+
312
+ private onHealthCheckCompleted = (event: ServiceManagerEvent): void => {
313
+ const report = event.data;
314
+ console.log('Health check completed:', {
315
+ totalServices: report.totalServices,
316
+ healthyServices: report.healthyServices,
317
+ unhealthyServices: report.unhealthyServices,
318
+ overallHealth: report.overallHealth,
319
+ timestamp: event.timestamp
320
+ });
321
+
322
+ // Alert if unhealthy services found
323
+ if (!report.overallHealth) {
324
+ console.warn('Unhealthy services detected!', report.services.filter(s => !s.healthy));
325
+ }
326
+ };
327
+
328
+ // Periodic health monitoring
329
+ async startPeriodicHealthCheck(intervalMs: number = 60000): Promise<void> {
330
+ setInterval(async () => {
331
+ try {
332
+ await this.serviceManager.healthCheck();
333
+ } catch (error) {
334
+ console.error('Periodic health check failed:', error);
335
+ }
336
+ }, intervalMs);
337
+ }
338
+
339
+ // Get service statistics
340
+ getServiceStats() {
341
+ const infos = this.serviceManager.getAllServiceInfo();
342
+ const schemas = this.serviceManager.getSchemas();
343
+
344
+ return {
345
+ totalServices: this.serviceManager.getServiceCount(),
346
+ registeredServices: this.serviceManager.getRegisteredCount(),
347
+ activeSchemas: schemas,
348
+ serviceBreakdown: schemas.map(schema => ({
349
+ schema,
350
+ serviceCount: infos.filter(info => info.schemaName === schema).length
351
+ })),
352
+ recentlyAccessed: infos
353
+ .filter(info => info.lastAccessed)
354
+ .sort((a, b) =>
355
+ new Date(b.lastAccessed!).getTime() - new Date(a.lastAccessed!).getTime()
356
+ )
357
+ .slice(0, 10)
358
+ };
359
+ }
360
+
361
+ // Cleanup unused services
362
+ async cleanupUnusedServices(schemaName?: string): Promise<void> {
363
+ if (schemaName) {
364
+ await this.serviceManager.destroyServicesBySchema(schemaName);
365
+ console.log(`Cleaned up services for schema: ${schemaName}`);
366
+ } else {
367
+ // Custom cleanup logic based on access time
368
+ const infos = this.serviceManager.getAllServiceInfo();
369
+ const cutoffTime = Date.now() - (30 * 60 * 1000); // 30 minutes ago
370
+
371
+ for (const info of infos) {
372
+ if (info.lastAccessed) {
373
+ const lastAccess = new Date(info.lastAccessed).getTime();
374
+ if (lastAccess < cutoffTime) {
375
+ await this.serviceManager.destroyService(info.schemaName, info.tableName);
376
+ console.log(`Cleaned up unused service: ${info.key}`);
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ }
383
+ ```
384
+
385
+ ## 3. Setup for React Native
386
+
387
+ ### Install dependencies
193
388
 
194
389
  ```bash
195
390
  npm install react-native-sqlite-2
196
- # Hoặc
391
+ # Or
197
392
  npm install react-native-sqlite-storage
198
393
  ```
199
394
 
200
- ### Tạo Adapter cho React Native
395
+ ### Create Adapter for React Native
201
396
 
202
397
  ```typescript
203
398
  // adapters/ReactNativeAdapter.ts
@@ -256,18 +451,19 @@ class ReactNativeConnection {
256
451
  }
257
452
 
258
453
  async close(): Promise<void> {
259
- // React Native SQLite không cần close thủ công
454
+ // React Native SQLite doesn't need manual close
260
455
  return Promise.resolve();
261
456
  }
262
457
  }
263
458
  ```
264
459
 
265
- ### Khởi tạo DatabaseManager (React Native)
460
+ ### Initialize DatabaseManager (React Native)
266
461
 
267
462
  ```typescript
268
463
  // services/DatabaseService.ts
269
464
  import { DatabaseManager, DatabaseFactory } from '@dqcai/sqlite';
270
465
  import { ReactNativeAdapter } from '../adapters/ReactNativeAdapter';
466
+ import { ServiceRegistration } from './ServiceRegistration';
271
467
 
272
468
  export class DatabaseService {
273
469
  private static isInitialized = false;
@@ -275,16 +471,16 @@ export class DatabaseService {
275
471
  static async initialize() {
276
472
  if (this.isInitialized) return;
277
473
 
278
- // Đăng adapter
474
+ // Register adapter
279
475
  DatabaseFactory.registerAdapter(new ReactNativeAdapter());
280
476
 
281
- // Đăng schemas
477
+ // Register schemas
282
478
  DatabaseManager.registerSchemas({
283
479
  core: coreSchema,
284
480
  users: userSchema
285
481
  });
286
482
 
287
- // Đăng roles
483
+ // Register roles
288
484
  DatabaseManager.registerRoles([
289
485
  {
290
486
  roleName: 'admin',
@@ -299,9 +495,12 @@ export class DatabaseService {
299
495
  }
300
496
  ]);
301
497
 
302
- // Khởi tạo core database
498
+ // Initialize core database
303
499
  await DatabaseManager.initializeCoreConnection();
304
500
 
501
+ // Register all services
502
+ ServiceRegistration.registerAllServices();
503
+
305
504
  this.isInitialized = true;
306
505
  console.log('DatabaseService initialized for React Native');
307
506
  }
@@ -321,17 +520,17 @@ export class DatabaseService {
321
520
  }
322
521
  ```
323
522
 
324
- ## 3. Setup cho Node.js
523
+ ## 4. Setup for Node.js
325
524
 
326
- ### Cài đặt dependencies
525
+ ### Install dependencies
327
526
 
328
527
  ```bash
329
528
  npm install sqlite3
330
- # Hoặc
529
+ # Or
331
530
  npm install better-sqlite3
332
531
  ```
333
532
 
334
- ### Tạo Adapter cho Node.js
533
+ ### Create Adapter for Node.js
335
534
 
336
535
  ```typescript
337
536
  // adapters/NodeAdapter.ts
@@ -348,7 +547,7 @@ export class NodeAdapter extends BaseAdapter {
348
547
  async connect(dbPath: string): Promise<any> {
349
548
  const fullPath = path.resolve(dbPath);
350
549
 
351
- // Tạo thư mục nếu chưa tồn tại
550
+ // Create directory if it doesn't exist
352
551
  const dir = path.dirname(fullPath);
353
552
  if (!fs.existsSync(dir)) {
354
553
  fs.mkdirSync(dir, { recursive: true });
@@ -414,12 +613,13 @@ class NodeConnection {
414
613
  }
415
614
  ```
416
615
 
417
- ### Khởi tạo DatabaseManager (Node.js)
616
+ ### Initialize DatabaseManager (Node.js)
418
617
 
419
618
  ```typescript
420
619
  // services/DatabaseService.ts
421
620
  import { DatabaseManager, DatabaseFactory } from '@dqcai/sqlite';
422
621
  import { NodeAdapter } from '../adapters/NodeAdapter';
622
+ import { ServiceRegistration } from './ServiceRegistration';
423
623
  import path from 'path';
424
624
 
425
625
  export class DatabaseService {
@@ -429,16 +629,16 @@ export class DatabaseService {
429
629
  static async initialize() {
430
630
  if (this.isInitialized) return;
431
631
 
432
- // Đăng adapter
632
+ // Register adapter
433
633
  DatabaseFactory.registerAdapter(new NodeAdapter());
434
634
 
435
- // Đăng schemas
635
+ // Register schemas
436
636
  DatabaseManager.registerSchemas({
437
637
  core: coreSchema,
438
638
  users: userSchema
439
639
  });
440
640
 
441
- // Đăng roles
641
+ // Register roles
442
642
  DatabaseManager.registerRoles([
443
643
  {
444
644
  roleName: 'admin',
@@ -453,9 +653,12 @@ export class DatabaseService {
453
653
  }
454
654
  ]);
455
655
 
456
- // Khởi tạo core database
656
+ // Initialize core database
457
657
  await DatabaseManager.initializeCoreConnection();
458
658
 
659
+ // Register all services
660
+ ServiceRegistration.registerAllServices();
661
+
459
662
  this.isInitialized = true;
460
663
  console.log('DatabaseService initialized for Node.js');
461
664
  }
@@ -475,7 +678,7 @@ export class DatabaseService {
475
678
  }
476
679
  ```
477
680
 
478
- ## 4. Tạo Services với BaseService
681
+ ## 5. Creating Services with BaseService
479
682
 
480
683
  ### User Service
481
684
 
@@ -502,21 +705,21 @@ interface Profile {
502
705
  }
503
706
 
504
707
  export class UserService extends BaseService<User> {
505
- constructor() {
506
- super('users', 'users'); // schema name, table name
708
+ constructor(schemaName?: string, tableName?: string) {
709
+ super(schemaName || 'users', tableName || 'users');
507
710
  this.setPrimaryKeyFields(['id']);
508
711
  }
509
712
 
510
- // Tạo user mới
713
+ // Create new user
511
714
  async createUser(userData: Omit<User, 'id' | 'created_at' | 'updated_at'>): Promise<User | null> {
512
715
  try {
513
- // Kiểm tra email đã tồn tại chưa
716
+ // Check if email already exists
514
717
  const existingUser = await this.findFirst({ email: userData.email });
515
718
  if (existingUser) {
516
719
  throw new Error('Email already exists');
517
720
  }
518
721
 
519
- // Kiểm tra username đã tồn tại chưa
722
+ // Check if username already exists
520
723
  const existingUsername = await this.findFirst({ username: userData.username });
521
724
  if (existingUsername) {
522
725
  throw new Error('Username already exists');
@@ -534,7 +737,7 @@ export class UserService extends BaseService<User> {
534
737
  }
535
738
  }
536
739
 
537
- // Cập nhật user
740
+ // Update user
538
741
  async updateUser(id: number, userData: Partial<User>): Promise<User | null> {
539
742
  try {
540
743
  const updatedUser = await this.update(id, {
@@ -548,17 +751,17 @@ export class UserService extends BaseService<User> {
548
751
  }
549
752
  }
550
753
 
551
- // Tìm user theo email
754
+ // Find user by email
552
755
  async findByEmail(email: string): Promise<User | null> {
553
756
  return await this.findFirst({ email });
554
757
  }
555
758
 
556
- // Tìm user theo username
759
+ // Find user by username
557
760
  async findByUsername(username: string): Promise<User | null> {
558
761
  return await this.findFirst({ username });
559
762
  }
560
763
 
561
- // Lấy tất cả users với phân trang
764
+ // Get all users with pagination
562
765
  async getAllUsers(page: number = 1, limit: number = 10): Promise<User[]> {
563
766
  const offset = (page - 1) * limit;
564
767
  return await this.findAll({}, {
@@ -568,21 +771,21 @@ export class UserService extends BaseService<User> {
568
771
  });
569
772
  }
570
773
 
571
- // Xóa user (soft delete bằng cách cập nhật trường deleted_at)
774
+ // Soft delete user
572
775
  async softDeleteUser(id: number): Promise<boolean> {
573
776
  const result = await this.update(id, {
574
777
  updated_at: new Date().toISOString(),
575
- // deleted_at: new Date().toISOString() // nếu field này trong schema
778
+ // deleted_at: new Date().toISOString() // if this field exists in schema
576
779
  });
577
780
  return result !== null;
578
781
  }
579
782
 
580
- // Đếm tổng số users
783
+ // Count total users
581
784
  async getTotalUsers(): Promise<number> {
582
785
  return await this.count();
583
786
  }
584
787
 
585
- // Tìm kiếm users
788
+ // Search users
586
789
  async searchUsers(searchTerm: string): Promise<User[]> {
587
790
  const dao = await this.init().then(() => this.dao!);
588
791
  const sql = `
@@ -597,27 +800,27 @@ export class UserService extends BaseService<User> {
597
800
  }
598
801
 
599
802
  export class ProfileService extends BaseService<Profile> {
600
- constructor() {
601
- super('users', 'profiles');
803
+ constructor(schemaName?: string, tableName?: string) {
804
+ super(schemaName || 'users', tableName || 'profiles');
602
805
  this.setPrimaryKeyFields(['id']);
603
806
  }
604
807
 
605
- // Tạo profile cho user
808
+ // Create profile for user
606
809
  async createProfile(profileData: Omit<Profile, 'id'>): Promise<Profile | null> {
607
810
  return await this.create(profileData);
608
811
  }
609
812
 
610
- // Lấy profile theo user_id
813
+ // Get profile by user_id
611
814
  async getProfileByUserId(userId: number): Promise<Profile | null> {
612
815
  return await this.findFirst({ user_id: userId });
613
816
  }
614
817
 
615
- // Cập nhật profile
818
+ // Update profile
616
819
  async updateProfile(id: number, profileData: Partial<Profile>): Promise<Profile | null> {
617
820
  return await this.update(id, profileData);
618
821
  }
619
822
 
620
- // Lấy thông tin user profile
823
+ // Get user with profile
621
824
  async getUserWithProfile(userId: number): Promise<any> {
622
825
  const dao = await this.init().then(() => this.dao!);
623
826
  const sql = `
@@ -647,18 +850,18 @@ interface Setting {
647
850
  }
648
851
 
649
852
  export class SettingsService extends BaseService<Setting> {
650
- constructor() {
651
- super('core', 'settings');
853
+ constructor(schemaName?: string, tableName?: string) {
854
+ super(schemaName || 'core', tableName || 'settings');
652
855
  this.setPrimaryKeyFields(['key']);
653
856
  }
654
857
 
655
- // Lấy giá trị setting
858
+ // Get setting value
656
859
  async getSetting(key: string): Promise<string | null> {
657
860
  const setting = await this.findById(key);
658
861
  return setting?.value || null;
659
862
  }
660
863
 
661
- // Đặt giá trị setting
864
+ // Set setting value
662
865
  async setSetting(key: string, value: string, description?: string): Promise<void> {
663
866
  const existing = await this.findById(key);
664
867
 
@@ -669,19 +872,19 @@ export class SettingsService extends BaseService<Setting> {
669
872
  }
670
873
  }
671
874
 
672
- // Lấy tất cả settings
875
+ // Get all settings
673
876
  async getAllSettings(): Promise<Setting[]> {
674
877
  return await this.findAll({}, {
675
878
  orderBy: [{ name: 'key', direction: 'ASC' }]
676
879
  });
677
880
  }
678
881
 
679
- // Xóa setting
882
+ // Delete setting
680
883
  async deleteSetting(key: string): Promise<boolean> {
681
884
  return await this.delete(key);
682
885
  }
683
886
 
684
- // Lấy nhiều settings cùng lúc
887
+ // Get multiple settings at once
685
888
  async getMultipleSettings(keys: string[]): Promise<Record<string, string>> {
686
889
  const dao = await this.init().then(() => this.dao!);
687
890
  const placeholders = keys.map(() => '?').join(',');
@@ -698,45 +901,43 @@ export class SettingsService extends BaseService<Setting> {
698
901
  }
699
902
  ```
700
903
 
701
- ## 5. Sử dụng trong ứng dụng
904
+ ## 6. Using in Applications
702
905
 
703
- ### Trong React Native
906
+ ### In React Native
704
907
 
705
908
  ```typescript
706
- // App.tsx hoặc index.js
909
+ // App.tsx or index.js
707
910
  import React, { useEffect, useState } from 'react';
708
911
  import { View, Text, Button, Alert } from 'react-native';
709
912
  import { DatabaseService } from './services/DatabaseService';
913
+ import { ServiceRegistration } from './services/ServiceRegistration';
914
+ import { ServiceMonitor } from './services/ServiceMonitor';
710
915
  import { UserService, ProfileService } from './services/UserService';
711
916
  import { SettingsService } from './services/CoreService';
712
917
 
713
918
  const App = () => {
714
919
  const [isDbReady, setIsDbReady] = useState(false);
715
- const [userService] = useState(new UserService());
716
- const [profileService] = useState(new ProfileService());
717
- const [settingsService] = useState(new SettingsService());
920
+ const [serviceMonitor] = useState(new ServiceMonitor());
718
921
 
719
922
  useEffect(() => {
720
923
  initializeDatabase();
721
924
 
722
925
  return () => {
723
- // Cleanup khi component unmount
926
+ // Cleanup when component unmounts
724
927
  DatabaseService.closeAll();
725
928
  };
726
929
  }, []);
727
930
 
728
931
  const initializeDatabase = async () => {
729
932
  try {
730
- // Khởi tạo database
933
+ // Initialize database
731
934
  await DatabaseService.initialize();
732
935
 
733
- // Đặt role cho user hiện tại
936
+ // Set role for current user
734
937
  await DatabaseService.setUserRole(['user']);
735
938
 
736
- // Khởi tạo services
737
- await userService.init();
738
- await profileService.init();
739
- await settingsService.init();
939
+ // Start service monitoring
940
+ await serviceMonitor.startPeriodicHealthCheck(60000); // Every minute
740
941
 
741
942
  setIsDbReady(true);
742
943
  console.log('Database ready!');
@@ -750,6 +951,9 @@ const App = () => {
750
951
  if (!isDbReady) return;
751
952
 
752
953
  try {
954
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
955
+ const profileService = await ServiceRegistration.getService<ProfileService>('users', 'profiles');
956
+
753
957
  const newUser = await userService.createUser({
754
958
  username: 'john_doe',
755
959
  email: 'john@example.com',
@@ -757,7 +961,7 @@ const App = () => {
757
961
  });
758
962
 
759
963
  if (newUser) {
760
- // Tạo profile cho user
964
+ // Create profile for user
761
965
  await profileService.createProfile({
762
966
  user_id: newUser.id!,
763
967
  first_name: 'John',
@@ -777,6 +981,7 @@ const App = () => {
777
981
  if (!isDbReady) return;
778
982
 
779
983
  try {
984
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
780
985
  const users = await userService.getAllUsers(1, 10);
781
986
  console.log('Users:', users);
782
987
  Alert.alert('Users', `Found ${users.length} users`);
@@ -789,6 +994,8 @@ const App = () => {
789
994
  if (!isDbReady) return;
790
995
 
791
996
  try {
997
+ const settingsService = await ServiceRegistration.getService<SettingsService>('core', 'settings');
998
+
792
999
  await settingsService.setSetting(
793
1000
  'app_version',
794
1001
  '1.0.0',
@@ -802,6 +1009,21 @@ const App = () => {
802
1009
  }
803
1010
  };
804
1011
 
1012
+ const handleGetServiceStats = async () => {
1013
+ if (!isDbReady) return;
1014
+
1015
+ try {
1016
+ const stats = serviceMonitor.getServiceStats();
1017
+ const healthReport = await ServiceRegistration.getHealthReport();
1018
+
1019
+ Alert.alert('Service Stats',
1020
+ `Total: ${stats.totalServices}, Healthy: ${healthReport.healthyServices}/${healthReport.totalServices}`
1021
+ );
1022
+ } catch (error) {
1023
+ console.error('Error getting service stats:', error);
1024
+ }
1025
+ };
1026
+
805
1027
  return (
806
1028
  <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
807
1029
  <Text>Database Status: {isDbReady ? 'Ready' : 'Initializing...'}</Text>
@@ -823,6 +1045,12 @@ const App = () => {
823
1045
  onPress={handleSetSetting}
824
1046
  disabled={!isDbReady}
825
1047
  />
1048
+
1049
+ <Button
1050
+ title="Get Service Stats"
1051
+ onPress={handleGetServiceStats}
1052
+ disabled={!isDbReady}
1053
+ />
826
1054
  </View>
827
1055
  );
828
1056
  };
@@ -830,38 +1058,36 @@ const App = () => {
830
1058
  export default App;
831
1059
  ```
832
1060
 
833
- ### Trong Node.js
1061
+ ### In Node.js
834
1062
 
835
1063
  ```typescript
836
1064
  // app.ts
837
1065
  import express from 'express';
838
1066
  import { DatabaseService } from './services/DatabaseService';
1067
+ import { ServiceRegistration } from './services/ServiceRegistration';
1068
+ import { ServiceMonitor } from './services/ServiceMonitor';
839
1069
  import { UserService, ProfileService } from './services/UserService';
840
1070
  import { SettingsService } from './services/CoreService';
841
1071
 
842
1072
  const app = express();
843
1073
  app.use(express.json());
844
1074
 
845
- // Services
846
- const userService = new UserService();
847
- const profileService = new ProfileService();
848
- const settingsService = new SettingsService();
1075
+ // Service monitor
1076
+ const serviceMonitor = new ServiceMonitor();
849
1077
 
850
- // Khởi tạo database khi start server
1078
+ // Initialize database when starting server
851
1079
  async function initializeApp() {
852
1080
  try {
853
1081
  console.log('Initializing database...');
854
1082
 
855
- // Khởi tạo DatabaseService
1083
+ // Initialize DatabaseService
856
1084
  await DatabaseService.initialize();
857
1085
 
858
- // Set role admin cho server
1086
+ // Set admin role for server
859
1087
  await DatabaseService.setUserRole(['admin']);
860
1088
 
861
- // Khởi tạo services
862
- await userService.init();
863
- await profileService.init();
864
- await settingsService.init();
1089
+ // Start service monitoring
1090
+ await serviceMonitor.startPeriodicHealthCheck(60000); // Every minute
865
1091
 
866
1092
  console.log('Database initialized successfully');
867
1093
  } catch (error) {
@@ -872,7 +1098,7 @@ async function initializeApp() {
872
1098
 
873
1099
  // API Routes
874
1100
 
875
- // POST /users - Tạo user mới
1101
+ // POST /users - Create new user
876
1102
  app.post('/users', async (req, res) => {
877
1103
  try {
878
1104
  const { username, email, password } = req.body;
@@ -881,10 +1107,11 @@ app.post('/users', async (req, res) => {
881
1107
  return res.status(400).json({ error: 'Missing required fields' });
882
1108
  }
883
1109
 
1110
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
884
1111
  const user = await userService.createUser({
885
1112
  username,
886
1113
  email,
887
- password // Nên hash password trước khi lưu
1114
+ password // Should hash password before saving
888
1115
  });
889
1116
 
890
1117
  res.status(201).json({ success: true, user });
@@ -894,12 +1121,13 @@ app.post('/users', async (req, res) => {
894
1121
  }
895
1122
  });
896
1123
 
897
- // GET /users - Lấy danh sách users
1124
+ // GET /users - Get list of users
898
1125
  app.get('/users', async (req, res) => {
899
1126
  try {
900
1127
  const page = parseInt(req.query.page as string) || 1;
901
1128
  const limit = parseInt(req.query.limit as string) || 10;
902
1129
 
1130
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
903
1131
  const users = await userService.getAllUsers(page, limit);
904
1132
  const total = await userService.getTotalUsers();
905
1133
 
@@ -919,10 +1147,11 @@ app.get('/users', async (req, res) => {
919
1147
  }
920
1148
  });
921
1149
 
922
- // GET /users/:id - Lấy user theo ID
1150
+ // GET /users/:id - Get user by ID
923
1151
  app.get('/users/:id', async (req, res) => {
924
1152
  try {
925
1153
  const id = parseInt(req.params.id);
1154
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
926
1155
  const user = await userService.findById(id);
927
1156
 
928
1157
  if (!user) {
@@ -936,12 +1165,13 @@ app.get('/users/:id', async (req, res) => {
936
1165
  }
937
1166
  });
938
1167
 
939
- // PUT /users/:id - Cập nhật user
1168
+ // PUT /users/:id - Update user
940
1169
  app.put('/users/:id', async (req, res) => {
941
1170
  try {
942
1171
  const id = parseInt(req.params.id);
943
1172
  const updates = req.body;
944
1173
 
1174
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
945
1175
  const user = await userService.updateUser(id, updates);
946
1176
 
947
1177
  if (!user) {
@@ -955,10 +1185,11 @@ app.put('/users/:id', async (req, res) => {
955
1185
  }
956
1186
  });
957
1187
 
958
- // DELETE /users/:id - Xóa user
1188
+ // DELETE /users/:id - Delete user
959
1189
  app.delete('/users/:id', async (req, res) => {
960
1190
  try {
961
1191
  const id = parseInt(req.params.id);
1192
+ const userService = await ServiceRegistration.getService<UserService>('users', 'users');
962
1193
  const success = await userService.delete(id);
963
1194
 
964
1195
  if (!success) {
@@ -972,12 +1203,13 @@ app.delete('/users/:id', async (req, res) => {
972
1203
  }
973
1204
  });
974
1205
 
975
- // POST /users/:id/profile - Tạo profile cho user
1206
+ // POST /users/:id/profile - Create profile for user
976
1207
  app.post('/users/:id/profile', async (req, res) => {
977
1208
  try {
978
1209
  const user_id = parseInt(req.params.id);
979
1210
  const profileData = { ...req.body, user_id };
980
1211
 
1212
+ const profileService = await ServiceRegistration.getService<ProfileService>('users', 'profiles');
981
1213
  const profile = await profileService.createProfile(profileData);
982
1214
  res.status(201).json({ success: true, profile });
983
1215
  } catch (error: any) {
@@ -986,10 +1218,11 @@ app.post('/users/:id/profile', async (req, res) => {
986
1218
  }
987
1219
  });
988
1220
 
989
- // GET /users/:id/full - Lấy user với profile
1221
+ // GET /users/:id/full - Get user with profile
990
1222
  app.get('/users/:id/full', async (req, res) => {
991
1223
  try {
992
1224
  const user_id = parseInt(req.params.id);
1225
+ const profileService = await ServiceRegistration.getService<ProfileService>('users', 'profiles');
993
1226
  const userWithProfile = await profileService.getUserWithProfile(user_id);
994
1227
 
995
1228
  if (!userWithProfile) {
@@ -1006,6 +1239,7 @@ app.get('/users/:id/full', async (req, res) => {
1006
1239
  // Settings API
1007
1240
  app.get('/settings/:key', async (req, res) => {
1008
1241
  try {
1242
+ const settingsService = await ServiceRegistration.getService<SettingsService>('core', 'settings');
1009
1243
  const value = await settingsService.getSetting(req.params.key);
1010
1244
  res.json({ success: true, value });
1011
1245
  } catch (error: any) {
@@ -1017,6 +1251,7 @@ app.get('/settings/:key', async (req, res) => {
1017
1251
  app.post('/settings', async (req, res) => {
1018
1252
  try {
1019
1253
  const { key, value, description } = req.body;
1254
+ const settingsService = await ServiceRegistration.getService<SettingsService>('core', 'settings');
1020
1255
  await settingsService.setSetting(key, value, description);
1021
1256
  res.json({ success: true, message: 'Setting saved' });
1022
1257
  } catch (error: any) {
@@ -1025,6 +1260,36 @@ app.post('/settings', async (req, res) => {
1025
1260
  }
1026
1261
  });
1027
1262
 
1263
+ // Service management API
1264
+ app.get('/admin/services', async (req, res) => {
1265
+ try {
1266
+ const serviceInfo = ServiceRegistration.getServiceInfo();
1267
+ const healthReport = await ServiceRegistration.getHealthReport();
1268
+ const stats = serviceMonitor.getServiceStats();
1269
+
1270
+ res.json({
1271
+ success: true,
1272
+ services: serviceInfo,
1273
+ health: healthReport,
1274
+ stats
1275
+ });
1276
+ } catch (error: any) {
1277
+ console.error('Error getting service info:', error);
1278
+ res.status(500).json({ error: error.message });
1279
+ }
1280
+ });
1281
+
1282
+ app.post('/admin/services/cleanup/:schema?', async (req, res) => {
1283
+ try {
1284
+ const schema = req.params.schema;
1285
+ await serviceMonitor.cleanupUnusedServices(schema);
1286
+ res.json({ success: true, message: 'Cleanup completed' });
1287
+ } catch (error: any) {
1288
+ console.error('Error cleaning up services:', error);
1289
+ res.status(500).json({ error: error.message });
1290
+ }
1291
+ });
1292
+
1028
1293
  // Graceful shutdown
1029
1294
  process.on('SIGINT', async () => {
1030
1295
  console.log('Shutting down server...');
@@ -1048,9 +1313,9 @@ initializeApp().then(() => {
1048
1313
  });
1049
1314
  ```
1050
1315
 
1051
- ## 6. Quản Database với DatabaseManager
1316
+ ## 7. Database Management with DatabaseManager
1052
1317
 
1053
- ### Mở/Đóng Connections
1318
+ ### Opening/Closing Connections
1054
1319
 
1055
1320
  ```typescript
1056
1321
  // DatabaseHelper.ts
@@ -1058,7 +1323,7 @@ import { DatabaseManager } from '@dqcai/sqlite';
1058
1323
 
1059
1324
  export class DatabaseHelper {
1060
1325
 
1061
- // Kiểm tra trạng thái kết nối
1326
+ // Check connection status
1062
1327
  static checkConnectionStatus(): void {
1063
1328
  const connections = DatabaseManager.getConnections();
1064
1329
  const count = DatabaseManager.getConnectionCount();
@@ -1069,7 +1334,7 @@ export class DatabaseHelper {
1069
1334
  console.log('Connection details:', connections);
1070
1335
  }
1071
1336
 
1072
- // Đóng kết nối cụ thể
1337
+ // Close specific connection
1073
1338
  static async closeSpecificConnection(dbKey: string): Promise<void> {
1074
1339
  try {
1075
1340
  await DatabaseManager.closeConnection(dbKey);
@@ -1079,7 +1344,7 @@ export class DatabaseHelper {
1079
1344
  }
1080
1345
  }
1081
1346
 
1082
- // Mở lại kết nối
1347
+ // Reopen connection
1083
1348
  static async reopenConnection(dbKey: string): Promise<void> {
1084
1349
  try {
1085
1350
  const dao = await DatabaseManager.getLazyLoading(dbKey);
@@ -1091,7 +1356,7 @@ export class DatabaseHelper {
1091
1356
  }
1092
1357
  }
1093
1358
 
1094
- // Đảm bảo kết nối tồn tại
1359
+ // Ensure connection exists
1095
1360
  static async ensureConnection(dbKey: string): Promise<void> {
1096
1361
  try {
1097
1362
  const dao = await DatabaseManager.ensureDatabaseConnection(dbKey);
@@ -1103,7 +1368,7 @@ export class DatabaseHelper {
1103
1368
  }
1104
1369
  }
1105
1370
 
1106
- // Thực hiện transaction cross-schema
1371
+ // Execute cross-schema transaction
1107
1372
  static async executeTransactionAcrossSchemas(
1108
1373
  schemas: string[],
1109
1374
  operations: (daos: Record<string, any>) => Promise<void>
@@ -1117,11 +1382,11 @@ export class DatabaseHelper {
1117
1382
  }
1118
1383
  }
1119
1384
 
1120
- // Event listeners cho reconnection
1385
+ // Event listeners for reconnection
1121
1386
  static setupReconnectionHandlers(): void {
1122
1387
  DatabaseManager.onDatabaseReconnect('users', (dao) => {
1123
1388
  console.log('Users database reconnected');
1124
- // Re-initialize services nếu cần
1389
+ // Re-initialize services if needed
1125
1390
  });
1126
1391
 
1127
1392
  DatabaseManager.onDatabaseReconnect('core', (dao) => {
@@ -1130,7 +1395,7 @@ export class DatabaseHelper {
1130
1395
  });
1131
1396
  }
1132
1397
 
1133
- // Health check tất cả connections
1398
+ // Health check all connections
1134
1399
  static async performHealthCheck(): Promise<void> {
1135
1400
  const connections = DatabaseManager.getConnections();
1136
1401
 
@@ -1141,7 +1406,7 @@ export class DatabaseHelper {
1141
1406
  } catch (error) {
1142
1407
  console.error(`${dbKey}: Unhealthy -`, error);
1143
1408
 
1144
- // Thử reconnect nếu cần
1409
+ // Try reconnect if needed
1145
1410
  try {
1146
1411
  await DatabaseManager.ensureDatabaseConnection(dbKey);
1147
1412
  console.log(`${dbKey}: Reconnected successfully`);
@@ -1154,9 +1419,9 @@ export class DatabaseHelper {
1154
1419
  }
1155
1420
  ```
1156
1421
 
1157
- ## 7. Import/Export Dữ liệu
1422
+ ## 8. Data Import/Export
1158
1423
 
1159
- ### Import từ CSV
1424
+ ### Import from CSV
1160
1425
 
1161
1426
  ```typescript
1162
1427
  // services/DataImportService.ts
@@ -1164,7 +1429,7 @@ import { DatabaseManager, ImportResult, ColumnMapping } from '@dqcai/sqlite';
1164
1429
 
1165
1430
  export class DataImportService {
1166
1431
 
1167
- // Import users từ CSV
1432
+ // Import users from CSV
1168
1433
  static async importUsersFromCSV(csvData: string): Promise<ImportResult> {
1169
1434
  try {
1170
1435
  const result = await DatabaseManager.importFromCSV(
@@ -1200,7 +1465,7 @@ export class DataImportService {
1200
1465
  }
1201
1466
  }
1202
1467
 
1203
- // Import với column mapping
1468
+ // Import with column mapping
1204
1469
  static async importUsersWithMapping(
1205
1470
  data: Record<string, any>[],
1206
1471
  columnMappings: ColumnMapping[]
@@ -1226,7 +1491,7 @@ export class DataImportService {
1226
1491
  }
1227
1492
  }
1228
1493
 
1229
- // Bulk import nhiều bảng cùng lúc
1494
+ // Bulk import multiple tables at once
1230
1495
  static async bulkImportData(importConfigs: Array<{
1231
1496
  databaseKey: string;
1232
1497
  tableName: string;
@@ -1241,12 +1506,12 @@ export class DataImportService {
1241
1506
  executionTime: result.executionTime
1242
1507
  });
1243
1508
 
1244
- // Log chi tiết từng bảng
1509
+ // Log details for each table
1245
1510
  Object.entries(result.results).forEach(([key, importResult]) => {
1246
1511
  console.log(`${key}: ${importResult.successRows}/${importResult.totalRows} rows imported`);
1247
1512
  });
1248
1513
 
1249
- // Log lỗi nếu
1514
+ // Log errors if any
1250
1515
  if (Object.keys(result.errors).length > 0) {
1251
1516
  console.error('Import errors:', result.errors);
1252
1517
  }
@@ -1258,20 +1523,20 @@ export class DataImportService {
1258
1523
  }
1259
1524
  }
1260
1525
 
1261
- // dụ sử dụng import service
1526
+ // Example import usage
1262
1527
  async function exampleImportUsage() {
1263
- // CSV data mẫu
1528
+ // Sample CSV data
1264
1529
  const csvData = `username,email,password,first_name,last_name
1265
1530
  john_doe,john@example.com,password123,John,Doe
1266
1531
  jane_smith,jane@example.com,password456,Jane,Smith
1267
1532
  bob_wilson,bob@example.com,password789,Bob,Wilson`;
1268
1533
 
1269
1534
  try {
1270
- // Import từ CSV
1535
+ // Import from CSV
1271
1536
  const importResult = await DataImportService.importUsersFromCSV(csvData);
1272
1537
  console.log('CSV Import result:', importResult);
1273
1538
 
1274
- // Import với column mapping
1539
+ // Import with column mapping
1275
1540
  const mappedData = [
1276
1541
  { user_name: 'alice', user_email: 'alice@test.com', pwd: 'pass123' },
1277
1542
  { user_name: 'charlie', user_email: 'charlie@test.com', pwd: 'pass456' }
@@ -1299,7 +1564,7 @@ bob_wilson,bob@example.com,password789,Bob,Wilson`;
1299
1564
  }
1300
1565
  ```
1301
1566
 
1302
- ### Export dữ liệu
1567
+ ### Export Data
1303
1568
 
1304
1569
  ```typescript
1305
1570
  // services/DataExportService.ts
@@ -1307,7 +1572,7 @@ import { DatabaseManager } from '@dqcai/sqlite';
1307
1572
 
1308
1573
  export class DataExportService {
1309
1574
 
1310
- // Export users ra CSV
1575
+ // Export users to CSV
1311
1576
  static async exportUsersToCSV(): Promise<string> {
1312
1577
  try {
1313
1578
  const dao = DatabaseManager.get('users');
@@ -1325,15 +1590,15 @@ export class DataExportService {
1325
1590
  return 'No data to export';
1326
1591
  }
1327
1592
 
1328
- // Tạo CSV header
1593
+ // Create CSV header
1329
1594
  const headers = Object.keys(result.rows[0]);
1330
1595
  let csvContent = headers.join(',') + '\n';
1331
1596
 
1332
- // Thêm data rows
1597
+ // Add data rows
1333
1598
  result.rows.forEach(row => {
1334
1599
  const values = headers.map(header => {
1335
1600
  const value = row[header];
1336
- // Escape quotes wrap trong quotes nếu chứa comma
1601
+ // Escape quotes and wrap in quotes if contains comma
1337
1602
  if (value === null || value === undefined) {
1338
1603
  return '';
1339
1604
  }
@@ -1353,7 +1618,7 @@ export class DataExportService {
1353
1618
  }
1354
1619
  }
1355
1620
 
1356
- // Export với điều kiện tùy chỉnh
1621
+ // Export with custom conditions
1357
1622
  static async exportUsersWithConditions(
1358
1623
  whereClause?: string,
1359
1624
  params?: any[]
@@ -1380,7 +1645,7 @@ export class DataExportService {
1380
1645
  }
1381
1646
  }
1382
1647
 
1383
- // Export dữ liệu backup toàn bộ database
1648
+ // Create full database backup
1384
1649
  static async createDatabaseBackup(dbKey: string): Promise<{
1385
1650
  tables: Record<string, any[]>;
1386
1651
  metadata: any;
@@ -1388,21 +1653,21 @@ export class DataExportService {
1388
1653
  try {
1389
1654
  const dao = DatabaseManager.get(dbKey);
1390
1655
 
1391
- // Lấy danh sách tables
1656
+ // Get list of tables
1392
1657
  const tablesResult = await dao.execute(
1393
1658
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1394
1659
  );
1395
1660
 
1396
1661
  const backup: Record<string, any[]> = {};
1397
1662
 
1398
- // Export từng table
1663
+ // Export each table
1399
1664
  for (const tableRow of tablesResult.rows) {
1400
1665
  const tableName = tableRow.name;
1401
1666
  const dataResult = await dao.execute(`SELECT * FROM ${tableName}`);
1402
1667
  backup[tableName] = dataResult.rows;
1403
1668
  }
1404
1669
 
1405
- // Thêm metadata
1670
+ // Add metadata
1406
1671
  const dbInfo = await dao.getDatabaseInfo();
1407
1672
 
1408
1673
  return {
@@ -1420,21 +1685,21 @@ export class DataExportService {
1420
1685
  }
1421
1686
  }
1422
1687
 
1423
- // dụ sử dụng export
1688
+ // Example export usage
1424
1689
  async function exampleExportUsage() {
1425
1690
  try {
1426
- // Export users ra CSV
1691
+ // Export users to CSV
1427
1692
  const csvContent = await DataExportService.exportUsersToCSV();
1428
1693
  console.log('CSV Export:', csvContent);
1429
1694
 
1430
- // Export users với điều kiện
1695
+ // Export users with conditions
1431
1696
  const recentUsers = await DataExportService.exportUsersWithConditions(
1432
1697
  "u.created_at > ?",
1433
- [new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString()] // 30 ngày gần đây
1698
+ [new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString()] // Last 30 days
1434
1699
  );
1435
1700
  console.log('Recent users:', recentUsers);
1436
1701
 
1437
- // Backup toàn bộ database users
1702
+ // Backup entire users database
1438
1703
  const backup = await DataExportService.createDatabaseBackup('users');
1439
1704
  console.log('Database backup:', backup);
1440
1705
 
@@ -1444,7 +1709,7 @@ async function exampleExportUsage() {
1444
1709
  }
1445
1710
  ```
1446
1711
 
1447
- ## 8. Best Practices & Tips
1712
+ ## 9. Best Practices & Tips
1448
1713
 
1449
1714
  ### Error Handling
1450
1715
 
@@ -1497,7 +1762,7 @@ export class DatabaseErrorHandler {
1497
1762
  }
1498
1763
  }
1499
1764
 
1500
- // Sử dụng error handler
1765
+ // Using error handler
1501
1766
  class SafeUserService extends UserService {
1502
1767
  async createUser(userData: Omit<User, 'id' | 'created_at' | 'updated_at'>): Promise<User | null> {
1503
1768
  return DatabaseErrorHandler.withRetry(async () => {
@@ -1505,7 +1770,7 @@ class SafeUserService extends UserService {
1505
1770
  return await super.createUser(userData);
1506
1771
  } catch (error) {
1507
1772
  DatabaseErrorHandler.handleServiceError(error, 'createUser');
1508
- throw error; // Re-throw sau khi handle
1773
+ throw error; // Re-throw after handling
1509
1774
  }
1510
1775
  });
1511
1776
  }
@@ -1518,7 +1783,7 @@ class SafeUserService extends UserService {
1518
1783
  // utils/PerformanceOptimizer.ts
1519
1784
  export class PerformanceOptimizer {
1520
1785
 
1521
- // Batch operations để giảm số lần gọi database
1786
+ // Batch operations to reduce database calls
1522
1787
  static async batchCreateUsers(
1523
1788
  userService: UserService,
1524
1789
  users: Array<Omit<User, 'id' | 'created_at' | 'updated_at'>>
@@ -1575,7 +1840,7 @@ export class PerformanceOptimizer {
1575
1840
 
1576
1841
  ```typescript
1577
1842
  // utils/TestHelpers.ts
1578
- import { DatabaseManager } from '@dqcai/sqlite';
1843
+ import { DatabaseManager, ServiceManager } from '@dqcai/sqlite';
1579
1844
 
1580
1845
  export class DatabaseTestHelpers {
1581
1846
 
@@ -1609,15 +1874,22 @@ export class DatabaseTestHelpers {
1609
1874
 
1610
1875
  return createdUsers;
1611
1876
  }
1877
+
1878
+ static async teardownTest(): Promise<void> {
1879
+ await DatabaseManager.closeAll();
1880
+ ServiceManager.resetInstance();
1881
+ }
1612
1882
  }
1613
1883
 
1614
1884
  // Example test
1615
1885
  describe('UserService Tests', () => {
1886
+ let serviceManager: ServiceManager;
1616
1887
  let userService: UserService;
1617
1888
 
1618
1889
  beforeAll(async () => {
1619
1890
  await DatabaseTestHelpers.setupTestDatabase();
1620
- userService = new UserService();
1891
+ serviceManager = ServiceManager.getInstance();
1892
+ userService = await serviceManager.getService('test_users', 'users') as UserService;
1621
1893
  await userService.init();
1622
1894
  });
1623
1895
 
@@ -1626,7 +1898,7 @@ describe('UserService Tests', () => {
1626
1898
  });
1627
1899
 
1628
1900
  afterAll(async () => {
1629
- await DatabaseManager.closeAll();
1901
+ await DatabaseTestHelpers.teardownTest();
1630
1902
  });
1631
1903
 
1632
1904
  test('should create user successfully', async () => {
@@ -1641,21 +1913,29 @@ describe('UserService Tests', () => {
1641
1913
  expect(user?.username).toBe(userData.username);
1642
1914
  expect(user?.email).toBe(userData.email);
1643
1915
  });
1916
+
1917
+ test('should manage service lifecycle', async () => {
1918
+ const serviceInfo = serviceManager.getAllServiceInfo();
1919
+ expect(serviceInfo.length).toBeGreaterThan(0);
1920
+
1921
+ const healthReport = await serviceManager.healthCheck();
1922
+ expect(healthReport.overallHealth).toBe(true);
1923
+ });
1644
1924
  });
1645
1925
  ```
1646
1926
 
1647
- ## 9. Troubleshooting Common Issues
1927
+ ## 10. Troubleshooting Common Issues
1648
1928
 
1649
1929
  ### Database Locked
1650
1930
 
1651
1931
  ```typescript
1652
- // Giải quyết database locked
1932
+ // Resolve database locked issues
1653
1933
  const handleDatabaseLocked = async () => {
1654
1934
  try {
1655
- // Enable WAL mode để tránh lock
1935
+ // Enable WAL mode to avoid locks
1656
1936
  const dao = DatabaseManager.get('users');
1657
1937
  await dao.execute('PRAGMA journal_mode = WAL');
1658
- await dao.execute('PRAGMA busy_timeout = 30000'); // 30 giây timeout
1938
+ await dao.execute('PRAGMA busy_timeout = 30000'); // 30 second timeout
1659
1939
  } catch (error) {
1660
1940
  console.error('Error setting WAL mode:', error);
1661
1941
  }
@@ -1665,7 +1945,7 @@ const handleDatabaseLocked = async () => {
1665
1945
  ### Connection Issues
1666
1946
 
1667
1947
  ```typescript
1668
- // Kiểm tra khôi phục kết nối
1948
+ // Check and restore connections
1669
1949
  const ensureConnectionHealth = async (dbKey: string) => {
1670
1950
  try {
1671
1951
  const dao = DatabaseManager.get(dbKey);
@@ -1679,7 +1959,33 @@ const ensureConnectionHealth = async (dbKey: string) => {
1679
1959
  };
1680
1960
  ```
1681
1961
 
1682
- ## 10. Migration & Schema Updates
1962
+ ### Service Management Issues
1963
+
1964
+ ```typescript
1965
+ // Service troubleshooting
1966
+ const troubleshootServices = async () => {
1967
+ const serviceManager = ServiceManager.getInstance();
1968
+
1969
+ // Get service health report
1970
+ const healthReport = await serviceManager.healthCheck();
1971
+ console.log('Service Health:', healthReport);
1972
+
1973
+ // Clean up problematic services
1974
+ if (!healthReport.overallHealth) {
1975
+ const unhealthyServices = healthReport.services.filter(s => !s.healthy);
1976
+
1977
+ for (const service of unhealthyServices) {
1978
+ const [schemaName, tableName] = service.serviceKey.split(':');
1979
+ console.log(`Attempting to restart service: ${service.serviceKey}`);
1980
+
1981
+ await serviceManager.destroyService(schemaName, tableName);
1982
+ await serviceManager.getService(schemaName, tableName);
1983
+ }
1984
+ }
1985
+ };
1986
+ ```
1987
+
1988
+ ## 11. Migration & Schema Updates
1683
1989
 
1684
1990
  ```typescript
1685
1991
  // migrations/001_add_user_status.ts
@@ -1705,7 +2011,7 @@ export const migration_001 = {
1705
2011
  DROP INDEX IF EXISTS idx_user_status
1706
2012
  `);
1707
2013
 
1708
- // SQLite không hỗ trợ DROP COLUMN, cần recreate table
2014
+ // SQLite doesn't support DROP COLUMN, need to recreate table
1709
2015
  await dao.execute(`
1710
2016
  CREATE TABLE users_backup AS
1711
2017
  SELECT id, username, email, password, created_at, updated_at
@@ -1733,7 +2039,7 @@ export const migration_001 = {
1733
2039
  }
1734
2040
  };
1735
2041
 
1736
- // Chạy migration
2042
+ // Run migration
1737
2043
  const runMigration = async () => {
1738
2044
  const dao = DatabaseManager.get('users');
1739
2045
  const currentVersion = await dao.getSchemaVersion();
@@ -1746,56 +2052,512 @@ const runMigration = async () => {
1746
2052
  };
1747
2053
  ```
1748
2054
 
1749
- ## Kết luận
2055
+ ## 12. Advanced Features
1750
2056
 
1751
- Universal SQLite cung cấp một giải pháp mạnh mẽ và linh hoạt để quản lý cơ sở dữ liệu SQLite across platforms. Với DatabaseManager và BaseService, bạn có thể:
2057
+ ### Cross-Schema Transactions with ServiceManager
1752
2058
 
1753
- - Dễ dàng quản lý nhiều database connections
1754
- - Thực hiện CRUD operations một cách type-safe
1755
- - Import/Export dữ liệu hiệu quả
1756
- - Quản schema và migrations
1757
- - Handle errors và performance optimization
2059
+ ```typescript
2060
+ // Advanced transaction management across multiple services
2061
+ export class TransactionManager {
2062
+ private serviceManager = ServiceManager.getInstance();
2063
+
2064
+ async executeUserProfileTransaction(
2065
+ userData: Omit<User, 'id' | 'created_at' | 'updated_at'>,
2066
+ profileData: Omit<Profile, 'id' | 'user_id'>
2067
+ ): Promise<{ user: User; profile: Profile }> {
2068
+
2069
+ // Execute transaction within the same schema (users)
2070
+ return await this.serviceManager.executeSchemaTransaction('users', async (services) => {
2071
+ const userService = services.find(s => s.tableName === 'users') as UserService;
2072
+ const profileService = services.find(s => s.tableName === 'profiles') as ProfileService;
1758
2073
 
1759
- Thư viện hỗ trợ tốt cho cả React Native và Node.js, giúp bạn xây dựng ứng dụng database-driven một cách nhất quán và maintainable.
2074
+ // Create user first
2075
+ const user = await userService.createUser(userData);
2076
+ if (!user) {
2077
+ throw new Error('Failed to create user');
2078
+ }
1760
2079
 
1761
- ## API Reference
2080
+ // Create profile for the user
2081
+ const profile = await profileService.createProfile({
2082
+ ...profileData,
2083
+ user_id: user.id!
2084
+ });
2085
+
2086
+ if (!profile) {
2087
+ throw new Error('Failed to create profile');
2088
+ }
2089
+
2090
+ return { user, profile };
2091
+ });
2092
+ }
2093
+
2094
+ async executeMultiSchemaOperation(): Promise<void> {
2095
+ // For operations across different schemas (databases)
2096
+ await DatabaseManager.executeCrossSchemaTransaction(['users', 'core'], async (daos) => {
2097
+ const usersDao = daos.users;
2098
+ const coreDao = daos.core;
2099
+
2100
+ // Update user count in settings
2101
+ const userCount = await usersDao.execute('SELECT COUNT(*) as count FROM users');
2102
+ await coreDao.execute(
2103
+ 'INSERT OR REPLACE INTO settings (key, value, description) VALUES (?, ?, ?)',
2104
+ ['user_count', userCount.rows[0].count.toString(), 'Total number of users']
2105
+ );
1762
2106
 
1763
- - **UniversalSQLite**: Singleton chính, methods: initialize, connect, getDAO, query, execute, importData, etc.
1764
- - **UniversalDAO**: Core DAO cho CRUD, execute, importData.
1765
- - **QueryBuilder**: Xây dựng query với fluent API.
1766
- - **MigrationManager**: Quản migration.
1767
- - **CSVImporter**: Import/export CSV.
1768
- - **BaseService**: Base cho service layer.
1769
- - **DatabaseFactory**: Factory để tạo DAO.
1770
- - **DatabaseManager**: Quản lý connections, roles.
2107
+ // Log system activity
2108
+ await coreDao.execute(
2109
+ 'INSERT OR REPLACE INTO settings (key, value, description) VALUES (?, ?, ?)',
2110
+ ['last_user_sync', new Date().toISOString(), 'Last user count sync']
2111
+ );
2112
+ });
2113
+ }
2114
+ }
2115
+ ```
1771
2116
 
1772
- Xem source code để biết chi tiết types và methods.
2117
+ ### Service Composition and Dependency Injection
1773
2118
 
2119
+ ```typescript
2120
+ // Advanced service composition
2121
+ export class ServiceComposer {
2122
+ private serviceManager = ServiceManager.getInstance();
1774
2123
 
1775
- ## Best Practices
2124
+ // Compose services with dependencies
2125
+ async createUserManagementService(): Promise<UserManagementService> {
2126
+ const userService = await this.serviceManager.getService('users', 'users') as UserService;
2127
+ const profileService = await this.serviceManager.getService('users', 'profiles') as ProfileService;
2128
+ const settingsService = await this.serviceManager.getService('core', 'settings') as SettingsService;
1776
2129
 
1777
- 1. **Always use transactions for multi-step operations**
1778
- 2. **Define schemas for type safety and validation**
1779
- 3. **Use parameterized queries to prevent SQL injection**
1780
- 4. **Implement proper error handling**
1781
- 5. **Close connections when done**
1782
- 6. **Use migrations for schema changes**
1783
- 7. **Batch large operations for better performance**
2130
+ return new UserManagementService(userService, profileService, settingsService);
2131
+ }
2132
+ }
2133
+
2134
+ // Composite service example
2135
+ export class UserManagementService {
2136
+ constructor(
2137
+ private userService: UserService,
2138
+ private profileService: ProfileService,
2139
+ private settingsService: SettingsService
2140
+ ) {}
2141
+
2142
+ async createCompleteUser(
2143
+ userData: Omit<User, 'id' | 'created_at' | 'updated_at'>,
2144
+ profileData: Omit<Profile, 'id' | 'user_id'>
2145
+ ): Promise<any> {
2146
+ // Get default settings
2147
+ const defaultRole = await this.settingsService.getSetting('default_user_role') || 'user';
2148
+
2149
+ return await this.userService.executeTransaction(async () => {
2150
+ // Create user
2151
+ const user = await this.userService.createUser(userData);
2152
+ if (!user) throw new Error('Failed to create user');
2153
+
2154
+ // Create profile
2155
+ const profile = await this.profileService.createProfile({
2156
+ ...profileData,
2157
+ user_id: user.id!
2158
+ });
2159
+
2160
+ // Update user count
2161
+ const currentCount = await this.userService.count();
2162
+ await this.settingsService.setSetting(
2163
+ 'total_users',
2164
+ currentCount.toString(),
2165
+ 'Total registered users'
2166
+ );
2167
+
2168
+ return { user, profile, defaultRole };
2169
+ });
2170
+ }
2171
+
2172
+ async getUserDashboardData(userId: number): Promise<any> {
2173
+ const [user, profile, recentSettings] = await Promise.all([
2174
+ this.userService.findById(userId),
2175
+ this.profileService.getProfileByUserId(userId),
2176
+ this.settingsService.getMultipleSettings(['app_version', 'maintenance_mode', 'user_count'])
2177
+ ]);
2178
+
2179
+ return {
2180
+ user,
2181
+ profile,
2182
+ settings: recentSettings,
2183
+ isComplete: !!(user && profile)
2184
+ };
2185
+ }
2186
+ }
2187
+ ```
2188
+
2189
+ ### Real-time Monitoring and Alerting
2190
+
2191
+ ```typescript
2192
+ // Real-time service monitoring
2193
+ export class ServiceHealthMonitor {
2194
+ private serviceManager = ServiceManager.getInstance();
2195
+ private alerts: Array<{ timestamp: string; level: string; message: string }> = [];
2196
+ private healthCheckInterval: NodeJS.Timeout | null = null;
2197
+
2198
+ startMonitoring(intervalMs: number = 30000): void {
2199
+ this.setupEventHandlers();
2200
+
2201
+ this.healthCheckInterval = setInterval(async () => {
2202
+ await this.performHealthCheck();
2203
+ }, intervalMs);
2204
+
2205
+ console.log('Service health monitoring started');
2206
+ }
2207
+
2208
+ stopMonitoring(): void {
2209
+ if (this.healthCheckInterval) {
2210
+ clearInterval(this.healthCheckInterval);
2211
+ this.healthCheckInterval = null;
2212
+ }
2213
+ console.log('Service health monitoring stopped');
2214
+ }
2215
+
2216
+ private setupEventHandlers(): void {
2217
+ this.serviceManager.on('SERVICE_ERROR', (event) => {
2218
+ this.addAlert('ERROR', `Service error in ${event.serviceKey}: ${event.error?.message}`);
2219
+ });
2220
+
2221
+ this.serviceManager.on('SERVICE_CREATED', (event) => {
2222
+ this.addAlert('INFO', `Service created: ${event.serviceKey}`);
2223
+ });
2224
+
2225
+ this.serviceManager.on('SERVICE_DESTROYED', (event) => {
2226
+ this.addAlert('WARNING', `Service destroyed: ${event.serviceKey}`);
2227
+ });
2228
+ }
2229
+
2230
+ private async performHealthCheck(): Promise<void> {
2231
+ try {
2232
+ const healthReport = await this.serviceManager.healthCheck();
2233
+
2234
+ if (!healthReport.overallHealth) {
2235
+ this.addAlert('CRITICAL', `System unhealthy: ${healthReport.unhealthyServices}/${healthReport.totalServices} services down`);
2236
+
2237
+ // Attempt automatic recovery
2238
+ await this.attemptAutoRecovery(healthReport);
2239
+ } else {
2240
+ this.addAlert('INFO', `System healthy: All ${healthReport.totalServices} services operational`);
2241
+ }
2242
+ } catch (error) {
2243
+ this.addAlert('ERROR', `Health check failed: ${error}`);
2244
+ }
2245
+ }
2246
+
2247
+ private async attemptAutoRecovery(healthReport: any): Promise<void> {
2248
+ const unhealthyServices = healthReport.services.filter((s: any) => !s.healthy);
2249
+
2250
+ for (const service of unhealthyServices) {
2251
+ try {
2252
+ const [schemaName, tableName] = service.serviceKey.split(':');
2253
+
2254
+ // Try to restart the service
2255
+ await this.serviceManager.destroyService(schemaName, tableName);
2256
+ await this.serviceManager.initializeService(schemaName, tableName);
2257
+
2258
+ this.addAlert('INFO', `Auto-recovery successful for ${service.serviceKey}`);
2259
+ } catch (error) {
2260
+ this.addAlert('ERROR', `Auto-recovery failed for ${service.serviceKey}: ${error}`);
2261
+ }
2262
+ }
2263
+ }
2264
+
2265
+ private addAlert(level: string, message: string): void {
2266
+ const alert = {
2267
+ timestamp: new Date().toISOString(),
2268
+ level,
2269
+ message
2270
+ };
2271
+
2272
+ this.alerts.unshift(alert);
2273
+
2274
+ // Keep only last 100 alerts
2275
+ if (this.alerts.length > 100) {
2276
+ this.alerts = this.alerts.slice(0, 100);
2277
+ }
2278
+
2279
+ // Log based on severity
2280
+ switch (level) {
2281
+ case 'CRITICAL':
2282
+ case 'ERROR':
2283
+ console.error(`[${level}] ${message}`);
2284
+ break;
2285
+ case 'WARNING':
2286
+ console.warn(`[${level}] ${message}`);
2287
+ break;
2288
+ default:
2289
+ console.log(`[${level}] ${message}`);
2290
+ }
2291
+ }
2292
+
2293
+ getRecentAlerts(limit: number = 20): typeof this.alerts {
2294
+ return this.alerts.slice(0, limit);
2295
+ }
2296
+
2297
+ getSystemMetrics(): any {
2298
+ const now = Date.now();
2299
+ const hourAgo = now - (60 * 60 * 1000);
2300
+
2301
+ const recentAlerts = this.alerts.filter(
2302
+ alert => new Date(alert.timestamp).getTime() > hourAgo
2303
+ );
2304
+
2305
+ const alertsByLevel = recentAlerts.reduce((acc, alert) => {
2306
+ acc[alert.level] = (acc[alert.level] || 0) + 1;
2307
+ return acc;
2308
+ }, {} as Record<string, number>);
2309
+
2310
+ return {
2311
+ serviceCount: this.serviceManager.getServiceCount(),
2312
+ activeSchemas: this.serviceManager.getSchemas(),
2313
+ recentAlerts: alertsByLevel,
2314
+ systemUptime: process.uptime?.() || 0,
2315
+ memoryUsage: process.memoryUsage?.() || null
2316
+ };
2317
+ }
2318
+ }
2319
+ ```
2320
+
2321
+ ## 13. Production Deployment Considerations
2322
+
2323
+ ### Configuration Management
2324
+
2325
+ ```typescript
2326
+ // config/DatabaseConfig.ts
2327
+ export interface DatabaseConfig {
2328
+ environment: 'development' | 'production' | 'test';
2329
+ databases: {
2330
+ [key: string]: {
2331
+ path: string;
2332
+ maxConnections?: number;
2333
+ timeout?: number;
2334
+ enableWAL?: boolean;
2335
+ };
2336
+ };
2337
+ services: {
2338
+ autoCleanupInterval?: number;
2339
+ healthCheckInterval?: number;
2340
+ maxIdleTime?: number;
2341
+ };
2342
+ monitoring: {
2343
+ enabled: boolean;
2344
+ alertThreshold?: number;
2345
+ logLevel: 'debug' | 'info' | 'warn' | 'error';
2346
+ };
2347
+ }
2348
+
2349
+ export const productionConfig: DatabaseConfig = {
2350
+ environment: 'production',
2351
+ databases: {
2352
+ users: {
2353
+ path: '/data/users.db',
2354
+ maxConnections: 10,
2355
+ timeout: 30000,
2356
+ enableWAL: true
2357
+ },
2358
+ core: {
2359
+ path: '/data/core.db',
2360
+ maxConnections: 5,
2361
+ timeout: 30000,
2362
+ enableWAL: true
2363
+ }
2364
+ },
2365
+ services: {
2366
+ autoCleanupInterval: 10 * 60 * 1000, // 10 minutes
2367
+ healthCheckInterval: 30 * 1000, // 30 seconds
2368
+ maxIdleTime: 30 * 60 * 1000 // 30 minutes
2369
+ },
2370
+ monitoring: {
2371
+ enabled: true,
2372
+ alertThreshold: 80, // Alert when 80% of services are unhealthy
2373
+ logLevel: 'info'
2374
+ }
2375
+ };
2376
+
2377
+ export const developmentConfig: DatabaseConfig = {
2378
+ environment: 'development',
2379
+ databases: {
2380
+ users: {
2381
+ path: './dev/users.db',
2382
+ enableWAL: false
2383
+ },
2384
+ core: {
2385
+ path: './dev/core.db',
2386
+ enableWAL: false
2387
+ }
2388
+ },
2389
+ services: {
2390
+ autoCleanupInterval: 5 * 60 * 1000, // 5 minutes
2391
+ healthCheckInterval: 60 * 1000, // 1 minute
2392
+ maxIdleTime: 10 * 60 * 1000 // 10 minutes
2393
+ },
2394
+ monitoring: {
2395
+ enabled: true,
2396
+ logLevel: 'debug'
2397
+ }
2398
+ };
2399
+ ```
2400
+
2401
+ ### Production Service Setup
2402
+
2403
+ ```typescript
2404
+ // production/ProductionSetup.ts
2405
+ import { DatabaseConfig, productionConfig } from '../config/DatabaseConfig';
2406
+
2407
+ export class ProductionSetup {
2408
+ static async initializeForProduction(config: DatabaseConfig = productionConfig): Promise<void> {
2409
+ try {
2410
+ // Apply production optimizations
2411
+ await this.applyProductionOptimizations();
2412
+
2413
+ // Initialize with config
2414
+ await DatabaseService.initialize();
2415
+
2416
+ // Setup monitoring
2417
+ if (config.monitoring.enabled) {
2418
+ const monitor = new ServiceHealthMonitor();
2419
+ monitor.startMonitoring(config.services.healthCheckInterval);
2420
+ }
2421
+
2422
+ // Setup graceful shutdown
2423
+ this.setupGracefulShutdown();
2424
+
2425
+ console.log('Production setup completed successfully');
2426
+ } catch (error) {
2427
+ console.error('Production setup failed:', error);
2428
+ process.exit(1);
2429
+ }
2430
+ }
2431
+
2432
+ private static async applyProductionOptimizations(): Promise<void> {
2433
+ // Apply SQLite production settings
2434
+ const connections = DatabaseManager.getConnections();
2435
+
2436
+ for (const [dbKey, dao] of Object.entries(connections)) {
2437
+ try {
2438
+ // Enable WAL mode for better concurrency
2439
+ await dao.execute('PRAGMA journal_mode = WAL');
2440
+
2441
+ // Set aggressive timeout for busy database
2442
+ await dao.execute('PRAGMA busy_timeout = 30000');
2443
+
2444
+ // Optimize cache size
2445
+ await dao.execute('PRAGMA cache_size = -64000'); // 64MB cache
2446
+
2447
+ // Enable foreign key constraints
2448
+ await dao.execute('PRAGMA foreign_keys = ON');
2449
+
2450
+ // Optimize for faster queries
2451
+ await dao.execute('PRAGMA synchronous = NORMAL');
2452
+ await dao.execute('PRAGMA temp_store = MEMORY');
2453
+
2454
+ console.log(`Production optimizations applied to ${dbKey}`);
2455
+ } catch (error) {
2456
+ console.error(`Failed to optimize ${dbKey}:`, error);
2457
+ }
2458
+ }
2459
+ }
2460
+
2461
+ private static setupGracefulShutdown(): void {
2462
+ const shutdown = async (signal: string) => {
2463
+ console.log(`Received ${signal}. Starting graceful shutdown...`);
2464
+
2465
+ try {
2466
+ // Close all database connections
2467
+ await DatabaseManager.closeAll();
2468
+
2469
+ // Destroy service manager
2470
+ const serviceManager = ServiceManager.getInstance();
2471
+ await serviceManager.destroy();
2472
+
2473
+ console.log('Graceful shutdown completed');
2474
+ process.exit(0);
2475
+ } catch (error) {
2476
+ console.error('Error during shutdown:', error);
2477
+ process.exit(1);
2478
+ }
2479
+ };
2480
+
2481
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
2482
+ process.on('SIGINT', () => shutdown('SIGINT'));
2483
+ process.on('SIGHUP', () => shutdown('SIGHUP'));
2484
+
2485
+ // Handle uncaught exceptions
2486
+ process.on('uncaughtException', (error) => {
2487
+ console.error('Uncaught Exception:', error);
2488
+ shutdown('uncaughtException');
2489
+ });
2490
+
2491
+ process.on('unhandledRejection', (reason, promise) => {
2492
+ console.error('Unhandled Rejection at:', promise, 'reason:', reason);
2493
+ shutdown('unhandledRejection');
2494
+ });
2495
+ }
2496
+ }
2497
+ ```
2498
+
2499
+ ## Conclusion
2500
+
2501
+ Universal SQLite provides a powerful and flexible solution for managing SQLite databases across platforms. With DatabaseManager, ServiceManager, and BaseService, you can:
2502
+
2503
+ - Easily manage multiple database connections and service lifecycles
2504
+ - Perform type-safe CRUD operations with automatic optimization
2505
+ - Import/Export data efficiently with built-in validation
2506
+ - Manage schemas and migrations systematically
2507
+ - Handle errors and performance optimization gracefully
2508
+ - Monitor service health and automate recovery
2509
+ - Deploy confidently in production environments
2510
+
2511
+ The library supports both React Native and Node.js well, helping you build database-driven applications consistently and maintainably across different platforms.
2512
+
2513
+ ## Key Features Summary
2514
+
2515
+ - **Cross-Platform**: Browser, Node.js, Deno, Bun, React Native (iOS/Android/Windows)
2516
+ - **Service Management**: Centralized lifecycle management with ServiceManager
2517
+ - **Type Safety**: Full TypeScript support for schemas, queries, and operations
2518
+ - **Performance**: Built-in optimization, connection pooling, and batch operations
2519
+ - **Monitoring**: Real-time health monitoring and automatic recovery
2520
+ - **Production Ready**: Comprehensive error handling and graceful shutdown
2521
+ - **Flexible**: Custom adapters, role-based access, and extensible architecture
2522
+
2523
+ ## Best Practices Summary
2524
+
2525
+ 1. **Always use ServiceManager for service lifecycle management**
2526
+ 2. **Register services at application startup for better organization**
2527
+ 3. **Use transactions for multi-step operations**
2528
+ 4. **Implement proper error handling with retry mechanisms**
2529
+ 5. **Monitor service health in production environments**
2530
+ 6. **Use batch operations for better performance**
2531
+ 7. **Enable WAL mode for production deployments**
2532
+ 8. **Implement graceful shutdown procedures**
2533
+
2534
+ ## API Reference
2535
+
2536
+ - **ServiceManager**: Centralized service lifecycle management
2537
+ - **DatabaseManager**: Connection and schema management
2538
+ - **BaseService**: Base class for CRUD operations with optimization
2539
+ - **UniversalDAO**: Core DAO for database operations
2540
+ - **QueryBuilder**: Fluent API for complex queries
2541
+ - **DatabaseFactory**: Factory for creating adapters and connections
2542
+ - **MigrationManager**: Schema versioning and migrations
2543
+ - **CSVImporter**: Data import/export utilities
2544
+
2545
+ See source code for detailed types and method signatures.
1784
2546
 
1785
2547
  ## Contributing
1786
2548
 
1787
2549
  1. Fork the repository
1788
2550
  2. Create a feature branch
1789
- 3. Make your changes
1790
- 4. Add tests
1791
- 5. Submit a pull request
1792
-
2551
+ 3. Make your changes with proper TypeScript types
2552
+ 4. Add comprehensive tests
2553
+ 5. Update documentation
2554
+ 6. Submit a pull request
1793
2555
 
1794
- ## 📄 License
2556
+ ## License
1795
2557
 
1796
2558
  MIT © [Cuong Doan](https://github.com/cuongdqpayment)
1797
2559
 
1798
- ## 🙏 Acknowledgments
2560
+ ## Acknowledgments
1799
2561
 
1800
2562
  - [sqlite3](https://www.npmjs.com/package/sqlite3) - Node.js SQLite bindings
1801
2563
  - [sql.js](https://github.com/sql-js/sql.js) - SQLite compiled to WebAssembly
@@ -1803,14 +2565,14 @@ MIT © [Cuong Doan](https://github.com/cuongdqpayment)
1803
2565
  - [react-native-sqlite-storage](https://github.com/andpor/react-native-sqlite-storage) - React Native SQLite
1804
2566
  - [Deno SQLite](https://deno.land/x/sqlite) - Deno SQLite module
1805
2567
 
1806
- ## 🔗 Links
2568
+ ## Links
1807
2569
 
1808
2570
  - [Documentation](https://github.com/cuongdqpayment/dqcai-sqlite/docs)
1809
2571
  - [Examples Repository](https://github.com/cuongdqpayment/dqcai-sqlite)
1810
2572
  - [Issue Tracker](https://github.com/cuongdqpayment/dqcai-sqlite/issues)
1811
- - [Issue Facebook](https://www.facebook.com/share/p/19esHGbaGj/)
2573
+ - [Facebook Page](https://www.facebook.com/share/p/19esHGbaGj/)
1812
2574
  - [NPM Package](https://www.npmjs.com/package/@dqcai/sqlite)
1813
2575
 
1814
2576
  ---
1815
2577
 
1816
- 🔥 **@dqcai/sqlite** — One library, all platforms! 🚀
2578
+ 🚀 **@dqcai/sqlite** — One library, all platforms! 🎯