@dqcai/sqlite 3.1.0 → 3.2.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 +581 -439
- package/lib/adapters/base-adapter.d.ts +2 -2
- package/lib/adapters/base-adapter.d.ts.map +1 -1
- package/lib/adapters/index.d.ts +2 -1
- package/lib/adapters/index.d.ts.map +1 -1
- package/lib/adapters/nodejs-adapter.d.ts +8 -0
- package/lib/adapters/nodejs-adapter.d.ts.map +1 -0
- package/lib/adapters/reactnative-adapter.d.ts +9 -0
- package/lib/adapters/reactnative-adapter.d.ts.map +1 -0
- package/lib/core/base-service.d.ts +25 -1
- package/lib/core/base-service.d.ts.map +1 -1
- package/lib/core/database-factory.d.ts +2 -2
- package/lib/core/database-factory.d.ts.map +1 -1
- package/lib/core/database-manager.d.ts.map +1 -1
- package/lib/core/service-manager.d.ts +1 -1
- package/lib/core/service-manager.d.ts.map +1 -1
- package/lib/core/universal-dao.d.ts +1 -2
- package/lib/core/universal-dao.d.ts.map +1 -1
- package/lib/index.d.ts +5 -319
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +11 -11
- package/lib/index.mjs.map +1 -1
- package/lib/logger/{logger-config.d.ts → index.d.ts} +4 -1
- package/lib/logger/index.d.ts.map +1 -0
- package/lib/types.d.ts +37 -3
- package/lib/types.d.ts.map +1 -1
- package/package.json +27 -3
- package/lib/index.umd.js +0 -1
- package/lib/index.umd.js.map +0 -1
- package/lib/logger/logger-config.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -30,575 +30,717 @@ yarn add @dqcai/sqlite @dqcai/logger
|
|
|
30
30
|
pnpm add @dqcai/sqlite @dqcai/logger
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
### Cài đặt dependencies theo môi trường
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
import { DatabaseManager, ServiceManager, BaseService } from '@dqcai/sqlite';
|
|
37
|
-
|
|
38
|
-
// 1. Define your schema
|
|
39
|
-
const userSchema = {
|
|
40
|
-
version: "1.0.0",
|
|
41
|
-
database_name: "users",
|
|
42
|
-
schemas: {
|
|
43
|
-
users: {
|
|
44
|
-
cols: [
|
|
45
|
-
{ name: "id", type: "integer", primary_key: true, auto_increment: true },
|
|
46
|
-
{ name: "username", type: "varchar", length: 50, unique: true },
|
|
47
|
-
{ name: "email", type: "varchar", length: 100, unique: true },
|
|
48
|
-
{ name: "created_at", type: "datetime", default: "CURRENT_TIMESTAMP" }
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// 2. Initialize database
|
|
55
|
-
await DatabaseManager.registerSchema('users', userSchema);
|
|
56
|
-
await DatabaseManager.initializeCoreConnection();
|
|
57
|
-
|
|
58
|
-
// 3. Create service
|
|
59
|
-
class UserService extends BaseService {
|
|
60
|
-
async createUser(data) {
|
|
61
|
-
return await this.create(data);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async getAllUsers() {
|
|
65
|
-
return await this.findAll();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
35
|
+
**React Native:**
|
|
68
36
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const user = await service.createUser({
|
|
72
|
-
username: 'john',
|
|
73
|
-
email: 'john@example.com'
|
|
74
|
-
});
|
|
37
|
+
```bash
|
|
38
|
+
npm install react-native-sqlite-storage
|
|
75
39
|
```
|
|
76
40
|
|
|
77
|
-
|
|
41
|
+
**Node.js:**
|
|
78
42
|
|
|
79
|
-
|
|
43
|
+
```bash
|
|
44
|
+
npm install better-sqlite3
|
|
45
|
+
```
|
|
80
46
|
|
|
81
|
-
|
|
47
|
+
## 2. Lựa chọn Adapter theo môi trường
|
|
82
48
|
|
|
83
|
-
|
|
49
|
+
### React Native Adapter
|
|
84
50
|
|
|
85
51
|
```typescript
|
|
86
|
-
|
|
87
|
-
import {
|
|
88
|
-
LogLevel,
|
|
89
|
-
LoggerConfigBuilder,
|
|
90
|
-
createModuleLogger,
|
|
91
|
-
CommonLoggerConfig,
|
|
92
|
-
} from "@dqcai/logger";
|
|
93
|
-
|
|
94
|
-
import { SQLiteModules } from "@dqcai/sqlite"; // version 3.1.0+
|
|
95
|
-
|
|
96
|
-
// Define your application modules
|
|
97
|
-
const AppModules = {
|
|
98
|
-
...SQLiteModules, // Includes: UNIVERSAL_SQLITE, UNIVERSAL_DAO, etc.
|
|
99
|
-
MIDDLEWARE: "middleware",
|
|
100
|
-
API: "api",
|
|
101
|
-
AUTH: "auth",
|
|
102
|
-
// Add your custom modules here
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Configure logger settings
|
|
106
|
-
const config = new LoggerConfigBuilder()
|
|
107
|
-
.setEnabled(true) // Enable logging globally
|
|
108
|
-
.setDefaultLevel('trace') // Set default log level: trace, debug, info, warn, error
|
|
109
|
-
// Optional: Configure specific modules
|
|
110
|
-
.addModule(SQLiteModules.UNIVERSAL_SQLITE, true, ['info', 'warn', 'error'], ['console'])
|
|
111
|
-
.addModule(SQLiteModules.UNIVERSAL_DAO, true, ['debug', 'info', 'warn', 'error'], ['console'])
|
|
112
|
-
.addModule(AppModules.MIDDLEWARE, true, ['trace', 'debug', 'info', 'warn', 'error'], ['console'])
|
|
113
|
-
.build();
|
|
114
|
-
|
|
115
|
-
// Apply configuration
|
|
116
|
-
CommonLoggerConfig.updateConfiguration(config);
|
|
52
|
+
import { ReactNativeAdapter, DatabaseFactory } from "@dqcai/sqlite";
|
|
117
53
|
|
|
118
|
-
|
|
54
|
+
// Đăng ký adapter
|
|
55
|
+
DatabaseFactory.registerAdapter(new ReactNativeAdapter());
|
|
119
56
|
```
|
|
120
57
|
|
|
121
|
-
###
|
|
122
|
-
|
|
123
|
-
Replace `console.log/debug/warn/error` with the module logger:
|
|
58
|
+
### Node.js Adapter
|
|
124
59
|
|
|
125
60
|
```typescript
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
export function authMiddleware(req, res, next) {
|
|
132
|
-
logger.trace("Middleware importing...");
|
|
133
|
-
logger.debug("Processing authentication", { userId: req.userId });
|
|
134
|
-
logger.info("User authenticated successfully");
|
|
135
|
-
logger.warn("Token expires soon", { expiresIn: 300 });
|
|
136
|
-
logger.error("Authentication failed", { reason: "Invalid token" });
|
|
137
|
-
|
|
138
|
-
next();
|
|
139
|
-
}
|
|
61
|
+
import { NodeJSAdapter, DatabaseFactory } from "@dqcai/sqlite";
|
|
62
|
+
|
|
63
|
+
// Đăng ký adapter
|
|
64
|
+
DatabaseFactory.registerAdapter(new NodeJSAdapter());
|
|
140
65
|
```
|
|
141
66
|
|
|
142
|
-
###
|
|
67
|
+
### Adapter tự động phát hiện
|
|
143
68
|
|
|
144
69
|
```typescript
|
|
145
|
-
|
|
146
|
-
import {
|
|
147
|
-
import {
|
|
148
|
-
|
|
149
|
-
const logger = createModuleLogger(AppModules.API);
|
|
150
|
-
|
|
151
|
-
interface User {
|
|
152
|
-
id?: number;
|
|
153
|
-
username: string;
|
|
154
|
-
email: string;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
class UserService extends BaseService<User> {
|
|
158
|
-
constructor() {
|
|
159
|
-
super('users', 'users');
|
|
160
|
-
logger.info("UserService initialized");
|
|
161
|
-
}
|
|
70
|
+
import { DatabaseFactory } from "@dqcai/sqlite";
|
|
71
|
+
import { ReactNativeAdapter } from "@dqcai/sqlite";
|
|
72
|
+
import { NodeJSAdapter } from "@dqcai/sqlite";
|
|
162
73
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
const user = await this.create(data);
|
|
168
|
-
logger.info("User created successfully", { userId: user?.id });
|
|
169
|
-
return user;
|
|
170
|
-
} catch (error) {
|
|
171
|
-
logger.error("Failed to create user", { error, data });
|
|
172
|
-
throw error;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
74
|
+
// Đăng ký cả hai adapter - thư viện sẽ tự chọn adapter phù hợp
|
|
75
|
+
DatabaseFactory.registerAdapter(new ReactNativeAdapter());
|
|
76
|
+
DatabaseFactory.registerAdapter(new NodeJSAdapter());
|
|
175
77
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return await this.findFirst({ email });
|
|
179
|
-
}
|
|
180
|
-
}
|
|
78
|
+
// Kiểm tra môi trường hiện tại
|
|
79
|
+
console.log("Environment:", DatabaseFactory.getEnvironmentInfo());
|
|
181
80
|
```
|
|
182
81
|
|
|
183
|
-
|
|
82
|
+
## 3. Quản lý Database với DatabaseManager
|
|
184
83
|
|
|
185
|
-
|
|
84
|
+
### Khai báo Schema
|
|
186
85
|
|
|
187
86
|
```typescript
|
|
188
|
-
|
|
189
|
-
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
190
|
-
const logLevel = process.env.LOG_LEVEL || (isDevelopment ? 'trace' : 'info');
|
|
191
|
-
const logEnabled = process.env.LOG_ENABLED !== 'false';
|
|
192
|
-
|
|
193
|
-
const config = new LoggerConfigBuilder()
|
|
194
|
-
.setEnabled(logEnabled)
|
|
195
|
-
.setDefaultLevel(logLevel as LogLevel)
|
|
196
|
-
.build();
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
#### File Transport
|
|
87
|
+
import { DatabaseSchema, SQLITE_TYPE_MAPPING } from "@dqcai/sqlite";
|
|
200
88
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
89
|
+
const coreSchema: DatabaseSchema = {
|
|
90
|
+
version: "v1",
|
|
91
|
+
database_name: "core.db",
|
|
92
|
+
description: "Core database schema",
|
|
93
|
+
type_mapping: SQLITE_TYPE_MAPPING,
|
|
94
|
+
schemas: {
|
|
95
|
+
users: {
|
|
96
|
+
description: "User management table",
|
|
97
|
+
cols: [
|
|
98
|
+
{
|
|
99
|
+
name: "id",
|
|
100
|
+
type: "uuid",
|
|
101
|
+
constraints: "NOT NULL UNIQUE PRIMARY KEY",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "username",
|
|
105
|
+
type: "varchar",
|
|
106
|
+
length: 50,
|
|
107
|
+
constraints: "NOT NULL UNIQUE",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "email",
|
|
111
|
+
type: "email",
|
|
112
|
+
constraints: "UNIQUE",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "created_at",
|
|
116
|
+
type: "timestamp",
|
|
117
|
+
constraints: "DEFAULT CURRENT_TIMESTAMP",
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
indexes: [
|
|
121
|
+
{
|
|
122
|
+
name: "idx_users_username",
|
|
123
|
+
columns: ["username"],
|
|
124
|
+
unique: true,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
219
130
|
```
|
|
220
131
|
|
|
221
|
-
|
|
132
|
+
### Đăng ký Schema và khởi tạo Database
|
|
222
133
|
|
|
223
134
|
```typescript
|
|
224
|
-
import {
|
|
225
|
-
|
|
226
|
-
const config = new LoggerConfigBuilder()
|
|
227
|
-
.setEnabled(true)
|
|
228
|
-
.setDefaultLevel('info')
|
|
229
|
-
.addTransport(new APITransport({
|
|
230
|
-
url: 'https://your-logging-service.com/logs',
|
|
231
|
-
method: 'POST',
|
|
232
|
-
headers: {
|
|
233
|
-
'Authorization': 'Bearer YOUR_TOKEN'
|
|
234
|
-
}
|
|
235
|
-
}))
|
|
236
|
-
.build();
|
|
237
|
-
```
|
|
135
|
+
import { DatabaseManager } from "@dqcai/sqlite";
|
|
238
136
|
|
|
239
|
-
|
|
137
|
+
// Đăng ký schema
|
|
138
|
+
DatabaseManager.registerSchema("core", coreSchema);
|
|
240
139
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
- `debug`: Diagnostic information
|
|
244
|
-
- `info`: General informational messages
|
|
245
|
-
- `warn`: Warning messages for potentially harmful situations
|
|
246
|
-
- `error`: Error messages for serious problems
|
|
140
|
+
// Khởi tạo kết nối core database
|
|
141
|
+
await DatabaseManager.initializeCoreConnection();
|
|
247
142
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
logger.info("User action completed", {
|
|
251
|
-
userId: user.id,
|
|
252
|
-
action: 'profile_update',
|
|
253
|
-
timestamp: Date.now()
|
|
254
|
-
});
|
|
143
|
+
// Lazy loading cho database khác
|
|
144
|
+
const dao = await DatabaseManager.getLazyLoading("core");
|
|
255
145
|
```
|
|
256
146
|
|
|
257
|
-
|
|
147
|
+
### Quản lý kết nối theo Role
|
|
148
|
+
|
|
258
149
|
```typescript
|
|
259
|
-
//
|
|
260
|
-
|
|
150
|
+
// Đăng ký role configuration
|
|
151
|
+
DatabaseManager.registerRole({
|
|
152
|
+
roleName: "admin",
|
|
153
|
+
requiredDatabases: ["core", "inventory"],
|
|
154
|
+
optionalDatabases: ["reports"],
|
|
155
|
+
priority: 1,
|
|
156
|
+
});
|
|
261
157
|
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
```
|
|
158
|
+
// Set user roles - tự động khởi tạo databases cần thiết
|
|
159
|
+
await DatabaseManager.setCurrentUserRoles(["admin"]);
|
|
265
160
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// Create separate loggers for different parts of your app
|
|
269
|
-
const authLogger = createModuleLogger(AppModules.AUTH);
|
|
270
|
-
const apiLogger = createModuleLogger(AppModules.API);
|
|
271
|
-
const dbLogger = createModuleLogger(AppModules.UNIVERSAL_SQLITE);
|
|
161
|
+
// Lấy database đã được khởi tạo
|
|
162
|
+
const coreDao = DatabaseManager.get("core");
|
|
272
163
|
```
|
|
273
164
|
|
|
274
|
-
##
|
|
165
|
+
## 4. Định nghĩa Service từ BaseService
|
|
275
166
|
|
|
276
|
-
###
|
|
277
|
-
Central database connection and schema management.
|
|
167
|
+
### Service đơn giản (sử dụng DefaultService)
|
|
278
168
|
|
|
279
169
|
```typescript
|
|
280
|
-
import {
|
|
281
|
-
|
|
282
|
-
// Register schemas
|
|
283
|
-
DatabaseManager.registerSchemas({
|
|
284
|
-
users: userSchema,
|
|
285
|
-
products: productSchema
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
// Initialize connections
|
|
289
|
-
await DatabaseManager.initializeCoreConnection();
|
|
170
|
+
import { BaseService } from "@dqcai/sqlite";
|
|
290
171
|
|
|
291
|
-
//
|
|
292
|
-
const
|
|
172
|
+
// Sử dụng BaseService trực tiếp cho CRUD cơ bản
|
|
173
|
+
const userService = new BaseService("core", "users");
|
|
174
|
+
await userService.init();
|
|
293
175
|
```
|
|
294
176
|
|
|
295
|
-
###
|
|
296
|
-
Centralized service lifecycle management with automatic optimization.
|
|
177
|
+
### Service mở rộng với logic nghiệp vụ
|
|
297
178
|
|
|
298
179
|
```typescript
|
|
299
|
-
import {
|
|
180
|
+
import { BaseService } from "@dqcai/sqlite";
|
|
300
181
|
|
|
301
|
-
|
|
182
|
+
export class UserService extends BaseService<User> {
|
|
183
|
+
constructor() {
|
|
184
|
+
super("core", "users");
|
|
185
|
+
this.setPrimaryKeyFields(["id"]);
|
|
186
|
+
}
|
|
302
187
|
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
188
|
+
// Business logic method
|
|
189
|
+
async findByStoreId(storeId: string): Promise<User[]> {
|
|
190
|
+
await this._ensureInitialized();
|
|
191
|
+
return await this.findAll({ store_id: storeId });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async findActiveUsers(): Promise<User[]> {
|
|
195
|
+
await this._ensureInitialized();
|
|
196
|
+
return await this.findAll({ is_active: true });
|
|
197
|
+
}
|
|
309
198
|
|
|
310
|
-
|
|
311
|
-
|
|
199
|
+
async updateLastLogin(userId: string): Promise<void> {
|
|
200
|
+
await this._ensureInitialized();
|
|
201
|
+
await this.update(userId, {
|
|
202
|
+
last_login: new Date().toISOString(),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
312
205
|
|
|
313
|
-
|
|
314
|
-
|
|
206
|
+
async lockUser(userId: string, duration: number): Promise<void> {
|
|
207
|
+
await this._ensureInitialized();
|
|
208
|
+
const lockedUntil = new Date(Date.now() + duration);
|
|
209
|
+
await this.update(userId, {
|
|
210
|
+
is_active: false,
|
|
211
|
+
locked_until: lockedUntil.toISOString(),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
315
215
|
```
|
|
316
216
|
|
|
317
|
-
###
|
|
318
|
-
Type-safe CRUD operations with built-in optimization.
|
|
217
|
+
### Service với validation và events
|
|
319
218
|
|
|
320
219
|
```typescript
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
interface User {
|
|
324
|
-
id?: number;
|
|
325
|
-
username: string;
|
|
326
|
-
email: string;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
class UserService extends BaseService<User> {
|
|
220
|
+
export class StoreService extends BaseService<Store> {
|
|
330
221
|
constructor() {
|
|
331
|
-
super(
|
|
222
|
+
super("core", "stores");
|
|
223
|
+
this.setupEventHandlers();
|
|
332
224
|
}
|
|
333
225
|
|
|
334
|
-
|
|
335
|
-
|
|
226
|
+
private setupEventHandlers() {
|
|
227
|
+
// Lắng nghe events
|
|
228
|
+
this.on("dataCreated", (event) => {
|
|
229
|
+
console.log("Store created:", event.data);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
this.on("dataUpdated", (event) => {
|
|
233
|
+
console.log("Store updated:", event.id);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Custom error handler
|
|
237
|
+
this.setErrorHandler("CREATE_ERROR", (error) => {
|
|
238
|
+
console.error("Failed to create store:", error.message);
|
|
239
|
+
});
|
|
336
240
|
}
|
|
337
241
|
|
|
338
|
-
|
|
339
|
-
|
|
242
|
+
// Override create để thêm validation
|
|
243
|
+
async create(data: Partial<Store>): Promise<Store | null> {
|
|
244
|
+
// Validate
|
|
245
|
+
if (!data.enterprise_id) {
|
|
246
|
+
throw new Error("Enterprise ID is required");
|
|
247
|
+
}
|
|
248
|
+
if (!data.name?.trim()) {
|
|
249
|
+
throw new Error("Store name is required");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Set defaults
|
|
253
|
+
data.currency = data.currency || "VND";
|
|
254
|
+
data.timezone = data.timezone || "Asia/Ho_Chi_Minh";
|
|
255
|
+
data.status = data.status || "active";
|
|
256
|
+
|
|
257
|
+
return await super.create(data);
|
|
340
258
|
}
|
|
341
259
|
|
|
342
|
-
async
|
|
343
|
-
return await this.
|
|
260
|
+
async findByEnterpriseId(enterpriseId: string): Promise<Store[]> {
|
|
261
|
+
return await this.findAll({ enterprise_id: enterpriseId });
|
|
344
262
|
}
|
|
345
263
|
|
|
346
|
-
async
|
|
347
|
-
return await this.
|
|
264
|
+
async getActiveStores(enterpriseId: string): Promise<Store[]> {
|
|
265
|
+
return await this.findAll(
|
|
266
|
+
{ enterprise_id: enterpriseId, status: "active" },
|
|
267
|
+
{ orderBy: [{ name: "name", direction: "ASC" }] }
|
|
268
|
+
);
|
|
348
269
|
}
|
|
349
270
|
}
|
|
350
271
|
```
|
|
351
272
|
|
|
352
|
-
##
|
|
273
|
+
## 5. Quản lý Service với ServiceManager
|
|
274
|
+
|
|
275
|
+
### Đăng ký Services
|
|
353
276
|
|
|
354
|
-
### Browser
|
|
355
277
|
```typescript
|
|
356
|
-
import {
|
|
278
|
+
import { ServiceManager } from "@dqcai/sqlite";
|
|
279
|
+
import { UserService } from "./services/UserService";
|
|
280
|
+
import { StoreService } from "./services/StoreService";
|
|
357
281
|
|
|
358
|
-
|
|
359
|
-
```
|
|
282
|
+
const serviceManager = ServiceManager.getInstance();
|
|
360
283
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
284
|
+
// Đăng ký service với custom class
|
|
285
|
+
serviceManager.registerService({
|
|
286
|
+
schemaName: "core",
|
|
287
|
+
tableName: "users",
|
|
288
|
+
primaryKeyFields: ["id"],
|
|
289
|
+
serviceClass: UserService,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
serviceManager.registerService({
|
|
293
|
+
schemaName: "core",
|
|
294
|
+
tableName: "stores",
|
|
295
|
+
serviceClass: StoreService,
|
|
296
|
+
});
|
|
364
297
|
|
|
365
|
-
|
|
298
|
+
// Đăng ký nhiều services cùng lúc
|
|
299
|
+
serviceManager.registerServices([
|
|
300
|
+
{
|
|
301
|
+
schemaName: "core",
|
|
302
|
+
tableName: "enterprises",
|
|
303
|
+
primaryKeyFields: ["id"],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
schemaName: "core",
|
|
307
|
+
tableName: "settings",
|
|
308
|
+
primaryKeyFields: ["id"],
|
|
309
|
+
},
|
|
310
|
+
]);
|
|
366
311
|
```
|
|
367
312
|
|
|
368
|
-
###
|
|
313
|
+
### Lấy và sử dụng Service
|
|
314
|
+
|
|
369
315
|
```typescript
|
|
370
|
-
|
|
371
|
-
|
|
316
|
+
// Lấy service - tự động khởi tạo nếu chưa tồn tại
|
|
317
|
+
const userService = (await serviceManager.getService(
|
|
318
|
+
"core",
|
|
319
|
+
"users"
|
|
320
|
+
)) as UserService;
|
|
372
321
|
|
|
373
|
-
|
|
322
|
+
// Khởi tạo service ngay lập tức
|
|
323
|
+
const storeService = await serviceManager.initializeService("core", "stores");
|
|
324
|
+
|
|
325
|
+
// Lấy service đã tồn tại (không tự động tạo)
|
|
326
|
+
const existingService = serviceManager.getExistingService("core", "users");
|
|
374
327
|
```
|
|
375
328
|
|
|
376
|
-
###
|
|
377
|
-
```typescript
|
|
378
|
-
import { DatabaseFactory, DenoAdapter } from '@dqcai/sqlite';
|
|
329
|
+
### Quản lý lifecycle
|
|
379
330
|
|
|
380
|
-
|
|
381
|
-
|
|
331
|
+
```typescript
|
|
332
|
+
// Kiểm tra sức khỏe tất cả services
|
|
333
|
+
const healthReport = await serviceManager.healthCheck();
|
|
334
|
+
console.log("Overall health:", healthReport.overallHealth);
|
|
335
|
+
console.log("Healthy services:", healthReport.healthyServices);
|
|
382
336
|
|
|
383
|
-
|
|
337
|
+
// Lấy thông tin services
|
|
338
|
+
const allServices = serviceManager.getAllServiceInfo();
|
|
339
|
+
console.log("Total services:", allServices.length);
|
|
384
340
|
|
|
385
|
-
|
|
341
|
+
// Destroy service
|
|
342
|
+
await serviceManager.destroyService("core", "users");
|
|
386
343
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
version: "1.0.0",
|
|
390
|
-
database_name: "myapp",
|
|
391
|
-
description: "Application database",
|
|
392
|
-
schemas: {
|
|
393
|
-
users: {
|
|
394
|
-
description: "User accounts",
|
|
395
|
-
cols: [
|
|
396
|
-
{
|
|
397
|
-
name: "id",
|
|
398
|
-
type: "integer",
|
|
399
|
-
primary_key: true,
|
|
400
|
-
auto_increment: true
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
name: "username",
|
|
404
|
-
type: "varchar",
|
|
405
|
-
length: 50,
|
|
406
|
-
nullable: false,
|
|
407
|
-
unique: true
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
name: "email",
|
|
411
|
-
type: "varchar",
|
|
412
|
-
length: 100,
|
|
413
|
-
nullable: false,
|
|
414
|
-
unique: true
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
name: "password",
|
|
418
|
-
type: "varchar",
|
|
419
|
-
length: 255,
|
|
420
|
-
nullable: false
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
name: "created_at",
|
|
424
|
-
type: "datetime",
|
|
425
|
-
nullable: false,
|
|
426
|
-
default: "CURRENT_TIMESTAMP"
|
|
427
|
-
}
|
|
428
|
-
],
|
|
429
|
-
indexes: [
|
|
430
|
-
{
|
|
431
|
-
name: "idx_username",
|
|
432
|
-
columns: ["username"],
|
|
433
|
-
unique: true
|
|
434
|
-
}
|
|
435
|
-
]
|
|
436
|
-
},
|
|
437
|
-
posts: {
|
|
438
|
-
description: "User posts",
|
|
439
|
-
cols: [
|
|
440
|
-
{ name: "id", type: "integer", primary_key: true, auto_increment: true },
|
|
441
|
-
{ name: "user_id", type: "integer", nullable: false },
|
|
442
|
-
{ name: "title", type: "varchar", length: 200 },
|
|
443
|
-
{ name: "content", type: "text" },
|
|
444
|
-
{ name: "created_at", type: "datetime", default: "CURRENT_TIMESTAMP" }
|
|
445
|
-
],
|
|
446
|
-
foreign_keys: [
|
|
447
|
-
{
|
|
448
|
-
name: "fk_post_user",
|
|
449
|
-
column: "user_id",
|
|
450
|
-
references: { table: "users", column: "id" },
|
|
451
|
-
on_delete: "CASCADE"
|
|
452
|
-
}
|
|
453
|
-
]
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
};
|
|
344
|
+
// Destroy tất cả services trong một schema
|
|
345
|
+
await serviceManager.destroyServicesBySchema("core");
|
|
457
346
|
```
|
|
458
347
|
|
|
459
|
-
##
|
|
348
|
+
## 6. Thực thi CRUD và Logic nghiệp vụ
|
|
349
|
+
|
|
350
|
+
### CRUD cơ bản
|
|
460
351
|
|
|
461
|
-
### Transaction Management
|
|
462
352
|
```typescript
|
|
463
|
-
//
|
|
464
|
-
await userService.
|
|
465
|
-
|
|
466
|
-
|
|
353
|
+
// Create
|
|
354
|
+
const newUser = await userService.create({
|
|
355
|
+
id: crypto.randomUUID(),
|
|
356
|
+
username: "john_doe",
|
|
357
|
+
email: "john@example.com",
|
|
358
|
+
full_name: "John Doe",
|
|
359
|
+
store_id: storeId,
|
|
360
|
+
role: "staff",
|
|
467
361
|
});
|
|
468
362
|
|
|
469
|
-
//
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
363
|
+
// Read
|
|
364
|
+
const user = await userService.findById(userId);
|
|
365
|
+
const allUsers = await userService.findAll();
|
|
366
|
+
const activeUsers = await userService.findAll({ is_active: true });
|
|
367
|
+
|
|
368
|
+
// Update
|
|
369
|
+
await userService.update(userId, {
|
|
370
|
+
email: "newemail@example.com",
|
|
371
|
+
updated_at: new Date().toISOString(),
|
|
473
372
|
});
|
|
373
|
+
|
|
374
|
+
// Delete
|
|
375
|
+
await userService.delete(userId);
|
|
376
|
+
|
|
377
|
+
// Count
|
|
378
|
+
const userCount = await userService.count({ is_active: true });
|
|
379
|
+
|
|
380
|
+
// Exists
|
|
381
|
+
const exists = await userService.exists(userId);
|
|
474
382
|
```
|
|
475
383
|
|
|
476
|
-
### Query
|
|
384
|
+
### Query nâng cao
|
|
385
|
+
|
|
477
386
|
```typescript
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
387
|
+
// Tìm kiếm với options
|
|
388
|
+
const users = await userService.findAll(
|
|
389
|
+
{ role: "staff", is_active: true },
|
|
390
|
+
{
|
|
391
|
+
orderBy: [{ name: "created_at", direction: "DESC" }],
|
|
392
|
+
limit: 10,
|
|
393
|
+
offset: 0,
|
|
394
|
+
columns: ["id", "username", "email", "full_name"],
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Pagination
|
|
399
|
+
const page = 1;
|
|
400
|
+
const perPage = 20;
|
|
401
|
+
const offset = (page - 1) * perPage;
|
|
402
|
+
|
|
403
|
+
const paginatedUsers = await userService.findAll(
|
|
404
|
+
{},
|
|
405
|
+
{ limit: perPage, offset }
|
|
406
|
+
);
|
|
484
407
|
```
|
|
485
408
|
|
|
486
|
-
###
|
|
409
|
+
### Bulk operations
|
|
410
|
+
|
|
487
411
|
```typescript
|
|
412
|
+
// Bulk insert
|
|
488
413
|
const users = [
|
|
489
|
-
{
|
|
490
|
-
|
|
414
|
+
{
|
|
415
|
+
id: uuid(),
|
|
416
|
+
username: "user1",
|
|
417
|
+
email: "user1@example.com",
|
|
418
|
+
store_id: storeId,
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
id: uuid(),
|
|
422
|
+
username: "user2",
|
|
423
|
+
email: "user2@example.com",
|
|
424
|
+
store_id: storeId,
|
|
425
|
+
},
|
|
491
426
|
];
|
|
492
427
|
|
|
493
|
-
await userService.
|
|
428
|
+
const importResult = await userService.bulkInsert(users);
|
|
429
|
+
console.log(`Imported ${importResult.successRows} users`);
|
|
430
|
+
|
|
431
|
+
// Bulk create with transaction
|
|
432
|
+
const createdUsers = await userService.bulkCreate(users);
|
|
494
433
|
```
|
|
495
434
|
|
|
496
|
-
###
|
|
435
|
+
### Transaction
|
|
436
|
+
|
|
497
437
|
```typescript
|
|
498
|
-
|
|
438
|
+
// Single service transaction
|
|
439
|
+
await userService.executeTransaction(async () => {
|
|
440
|
+
await userService.create(user1);
|
|
441
|
+
await userService.create(user2);
|
|
442
|
+
await userService.update(userId, { status: "active" });
|
|
443
|
+
});
|
|
499
444
|
|
|
500
|
-
|
|
501
|
-
|
|
445
|
+
// Cross-service transaction (same schema)
|
|
446
|
+
await serviceManager.executeSchemaTransaction("core", async (services) => {
|
|
447
|
+
const [userSvc, storeSvc] = services;
|
|
502
448
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
449
|
+
const store = await storeSvc.create(storeData);
|
|
450
|
+
await userSvc.create({
|
|
451
|
+
...userData,
|
|
452
|
+
store_id: store.id,
|
|
453
|
+
});
|
|
454
|
+
});
|
|
506
455
|
```
|
|
507
456
|
|
|
508
|
-
|
|
457
|
+
### Import/Export
|
|
509
458
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
459
|
+
```typescript
|
|
460
|
+
// Import from CSV
|
|
461
|
+
const csvData = `username,email,role
|
|
462
|
+
john,john@example.com,staff
|
|
463
|
+
jane,jane@example.com,manager`;
|
|
464
|
+
|
|
465
|
+
const result = await userService.importFromCSV(csvData, {
|
|
466
|
+
hasHeader: true,
|
|
467
|
+
delimiter: ",",
|
|
468
|
+
skipErrors: false,
|
|
469
|
+
});
|
|
516
470
|
|
|
517
|
-
|
|
471
|
+
// Import with column mapping
|
|
472
|
+
const columnMappings = [
|
|
473
|
+
{ sourceColumn: "user_name", targetColumn: "username" },
|
|
474
|
+
{ sourceColumn: "mail", targetColumn: "email" },
|
|
475
|
+
{
|
|
476
|
+
sourceColumn: "created",
|
|
477
|
+
targetColumn: "created_at",
|
|
478
|
+
transform: (value) => new Date(value).toISOString(),
|
|
479
|
+
},
|
|
480
|
+
];
|
|
518
481
|
|
|
519
|
-
|
|
482
|
+
await userService.importDataWithMapping(data, columnMappings);
|
|
483
|
+
```
|
|
520
484
|
|
|
521
|
-
##
|
|
485
|
+
## 7. Ví dụ hoàn chỉnh với Core Schema
|
|
522
486
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
487
|
+
```typescript
|
|
488
|
+
import {
|
|
489
|
+
DatabaseFactory,
|
|
490
|
+
DatabaseManager,
|
|
491
|
+
ServiceManager,
|
|
492
|
+
BaseService,
|
|
493
|
+
} from "@dqcai/sqlite";
|
|
494
|
+
import { NodeJSAdapter } from "@dqcai/sqlite";
|
|
495
|
+
import { coreSchema } from "./schemas/core";
|
|
527
496
|
|
|
528
|
-
|
|
497
|
+
// ========== BƯỚC 1: Setup Adapters ==========
|
|
498
|
+
DatabaseFactory.registerAdapter(new NodeJSAdapter());
|
|
529
499
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
- **Performance optimization**: Built-in query optimization and connection pooling
|
|
533
|
-
- **Memory management**: Automatic cleanup of unused services
|
|
534
|
-
- **Graceful shutdown**: Proper resource cleanup on application termination
|
|
535
|
-
- **Comprehensive logging**: Integrated logger for debugging and monitoring
|
|
500
|
+
// ========== BƯỚC 2: Đăng ký Schemas ==========
|
|
501
|
+
DatabaseManager.registerSchema("core", coreSchema);
|
|
536
502
|
|
|
537
|
-
|
|
503
|
+
// ========== BƯỚC 3: Định nghĩa Services ==========
|
|
504
|
+
class UserService extends BaseService {
|
|
505
|
+
constructor() {
|
|
506
|
+
super("core", "users");
|
|
507
|
+
}
|
|
538
508
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
const migration = {
|
|
542
|
-
version: '1.0.1',
|
|
543
|
-
description: 'Add user status column',
|
|
544
|
-
|
|
545
|
-
async up(dao) {
|
|
546
|
-
await dao.execute('ALTER TABLE users ADD COLUMN status VARCHAR(20) DEFAULT "active"');
|
|
547
|
-
},
|
|
548
|
-
|
|
549
|
-
async down(dao) {
|
|
550
|
-
// Rollback logic
|
|
509
|
+
async findByStoreId(storeId: string) {
|
|
510
|
+
return await this.findAll({ store_id: storeId });
|
|
551
511
|
}
|
|
552
|
-
};
|
|
553
512
|
|
|
554
|
-
|
|
555
|
-
await
|
|
556
|
-
|
|
513
|
+
async authenticate(username: string, password: string) {
|
|
514
|
+
const user = await this.findFirst({ username });
|
|
515
|
+
if (!user) return null;
|
|
557
516
|
|
|
558
|
-
|
|
517
|
+
// Verify password (simplified)
|
|
518
|
+
if (user.password_hash === password) {
|
|
519
|
+
await this.update(user.id, {
|
|
520
|
+
last_login: new Date().toISOString(),
|
|
521
|
+
failed_login_attempts: 0,
|
|
522
|
+
});
|
|
523
|
+
return user;
|
|
524
|
+
}
|
|
559
525
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
526
|
+
// Increment failed attempts
|
|
527
|
+
await this.update(user.id, {
|
|
528
|
+
failed_login_attempts: (user.failed_login_attempts || 0) + 1,
|
|
529
|
+
});
|
|
564
530
|
|
|
565
|
-
|
|
566
|
-
|
|
531
|
+
return null;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
567
534
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
535
|
+
class StoreService extends BaseService {
|
|
536
|
+
constructor() {
|
|
537
|
+
super("core", "stores");
|
|
538
|
+
}
|
|
571
539
|
|
|
572
|
-
|
|
573
|
-
await
|
|
574
|
-
|
|
575
|
-
const allUsers = await userService.getAllUsers();
|
|
576
|
-
setUsers(allUsers);
|
|
577
|
-
};
|
|
540
|
+
async findByEnterpriseId(enterpriseId: string) {
|
|
541
|
+
return await this.findAll({ enterprise_id: enterpriseId });
|
|
542
|
+
}
|
|
578
543
|
|
|
579
|
-
|
|
544
|
+
async getActiveStores(enterpriseId: string) {
|
|
545
|
+
return await this.findAll(
|
|
546
|
+
{ enterprise_id: enterpriseId, status: "active" },
|
|
547
|
+
{ orderBy: [{ name: "name", direction: "ASC" }] }
|
|
548
|
+
);
|
|
549
|
+
}
|
|
580
550
|
}
|
|
581
|
-
```
|
|
582
551
|
|
|
583
|
-
|
|
552
|
+
// ========== BƯỚC 4: Đăng ký Services ==========
|
|
553
|
+
const serviceManager = ServiceManager.getInstance();
|
|
584
554
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
555
|
+
serviceManager.registerServices([
|
|
556
|
+
{
|
|
557
|
+
schemaName: "core",
|
|
558
|
+
tableName: "enterprises",
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
schemaName: "core",
|
|
562
|
+
tableName: "stores",
|
|
563
|
+
serviceClass: StoreService,
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
schemaName: "core",
|
|
567
|
+
tableName: "users",
|
|
568
|
+
serviceClass: UserService,
|
|
569
|
+
},
|
|
570
|
+
]);
|
|
571
|
+
|
|
572
|
+
// ========== BƯỚC 5: Khởi tạo và sử dụng ==========
|
|
573
|
+
async function main() {
|
|
574
|
+
try {
|
|
575
|
+
// Khởi tạo core database
|
|
576
|
+
await DatabaseManager.initializeCoreConnection();
|
|
577
|
+
|
|
578
|
+
// Lấy services
|
|
579
|
+
const enterpriseService = await serviceManager.getService(
|
|
580
|
+
"core",
|
|
581
|
+
"enterprises"
|
|
582
|
+
);
|
|
583
|
+
const storeService = (await serviceManager.getService(
|
|
584
|
+
"core",
|
|
585
|
+
"stores"
|
|
586
|
+
)) as StoreService;
|
|
587
|
+
const userService = (await serviceManager.getService(
|
|
588
|
+
"core",
|
|
589
|
+
"users"
|
|
590
|
+
)) as UserService;
|
|
591
|
+
|
|
592
|
+
// ========== TEST CRUD Operations ==========
|
|
593
|
+
|
|
594
|
+
// 1. Create Enterprise
|
|
595
|
+
const enterprise = await enterpriseService.create({
|
|
596
|
+
id: crypto.randomUUID(),
|
|
597
|
+
name: "My Company",
|
|
598
|
+
business_type: "ltd",
|
|
599
|
+
email: "contact@mycompany.com",
|
|
600
|
+
status: "active",
|
|
601
|
+
subscription_plan: "premium",
|
|
602
|
+
});
|
|
603
|
+
console.log("✅ Enterprise created:", enterprise?.name);
|
|
604
|
+
|
|
605
|
+
// 2. Create Store
|
|
606
|
+
const store = await storeService.create({
|
|
607
|
+
id: crypto.randomUUID(),
|
|
608
|
+
enterprise_id: enterprise!.id,
|
|
609
|
+
name: "Main Store",
|
|
610
|
+
store_type: "retail",
|
|
611
|
+
address: "123 Main St",
|
|
612
|
+
status: "active",
|
|
613
|
+
});
|
|
614
|
+
console.log("✅ Store created:", store?.name);
|
|
615
|
+
|
|
616
|
+
// 3. Create Users
|
|
617
|
+
const users = [
|
|
618
|
+
{
|
|
619
|
+
id: crypto.randomUUID(),
|
|
620
|
+
store_id: store!.id,
|
|
621
|
+
username: "admin",
|
|
622
|
+
password_hash: "hashed_password",
|
|
623
|
+
full_name: "Admin User",
|
|
624
|
+
email: "admin@mycompany.com",
|
|
625
|
+
role: "admin",
|
|
626
|
+
is_active: true,
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
id: crypto.randomUUID(),
|
|
630
|
+
store_id: store!.id,
|
|
631
|
+
username: "staff1",
|
|
632
|
+
password_hash: "hashed_password",
|
|
633
|
+
full_name: "Staff One",
|
|
634
|
+
email: "staff1@mycompany.com",
|
|
635
|
+
role: "staff",
|
|
636
|
+
is_active: true,
|
|
637
|
+
},
|
|
638
|
+
];
|
|
639
|
+
|
|
640
|
+
const importResult = await userService.bulkInsert(users);
|
|
641
|
+
console.log(`✅ Users imported: ${importResult.successRows} successful`);
|
|
642
|
+
|
|
643
|
+
// 4. Query data
|
|
644
|
+
const allUsers = await userService.findByStoreId(store!.id);
|
|
645
|
+
console.log(`✅ Users in store: ${allUsers.length}`);
|
|
646
|
+
|
|
647
|
+
const activeStores = await storeService.getActiveStores(enterprise!.id);
|
|
648
|
+
console.log(`✅ Active stores: ${activeStores.length}`);
|
|
649
|
+
|
|
650
|
+
// 5. Update
|
|
651
|
+
await userService.update(users[0].id, {
|
|
652
|
+
last_login: new Date().toISOString(),
|
|
653
|
+
});
|
|
654
|
+
console.log("✅ User login updated");
|
|
655
|
+
|
|
656
|
+
// 6. Transaction example
|
|
657
|
+
await serviceManager.executeSchemaTransaction("core", async (services) => {
|
|
658
|
+
const [entSvc, storeSvc, userSvc] = services;
|
|
659
|
+
|
|
660
|
+
// Create another store and user in transaction
|
|
661
|
+
const newStore = await storeSvc.create({
|
|
662
|
+
id: crypto.randomUUID(),
|
|
663
|
+
enterprise_id: enterprise!.id,
|
|
664
|
+
name: "Branch Store",
|
|
665
|
+
status: "active",
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
await userSvc.create({
|
|
669
|
+
id: crypto.randomUUID(),
|
|
670
|
+
store_id: newStore.id,
|
|
671
|
+
username: "branch_manager",
|
|
672
|
+
password_hash: "hashed_password",
|
|
673
|
+
full_name: "Branch Manager",
|
|
674
|
+
email: "manager@branch.com",
|
|
675
|
+
role: "manager",
|
|
676
|
+
is_active: true,
|
|
677
|
+
});
|
|
678
|
+
});
|
|
679
|
+
console.log("✅ Transaction completed");
|
|
680
|
+
|
|
681
|
+
// 7. Health check
|
|
682
|
+
const health = await serviceManager.healthCheck();
|
|
683
|
+
console.log("✅ System health:", health.overallHealth);
|
|
684
|
+
console.log(
|
|
685
|
+
` Healthy services: ${health.healthyServices}/${health.totalServices}`
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
// 8. Statistics
|
|
689
|
+
const enterpriseCount = await enterpriseService.count();
|
|
690
|
+
const storeCount = await storeService.count();
|
|
691
|
+
const userCount = await userService.count();
|
|
692
|
+
|
|
693
|
+
console.log("\n📊 Statistics:");
|
|
694
|
+
console.log(` Enterprises: ${enterpriseCount}`);
|
|
695
|
+
console.log(` Stores: ${storeCount}`);
|
|
696
|
+
console.log(` Users: ${userCount}`);
|
|
697
|
+
} catch (error) {
|
|
698
|
+
console.error("❌ Error:", error);
|
|
699
|
+
} finally {
|
|
700
|
+
// Cleanup
|
|
701
|
+
await DatabaseManager.closeAll();
|
|
702
|
+
console.log("\n✅ Database connections closed");
|
|
703
|
+
}
|
|
704
|
+
}
|
|
589
705
|
|
|
590
|
-
|
|
706
|
+
// Run test
|
|
707
|
+
main().catch(console.error);
|
|
708
|
+
```
|
|
591
709
|
|
|
592
|
-
|
|
593
|
-
const userService = await ServiceManager.getService('users', 'users');
|
|
594
|
-
const users = await userService.getAllUsers();
|
|
595
|
-
res.json(users);
|
|
596
|
-
});
|
|
710
|
+
### Kết quả mong đợi:
|
|
597
711
|
|
|
598
|
-
// Initialize database before starting server
|
|
599
|
-
await DatabaseService.initialize();
|
|
600
|
-
app.listen(3000);
|
|
601
712
|
```
|
|
713
|
+
✅ Enterprise created: My Company
|
|
714
|
+
✅ Store created: Main Store
|
|
715
|
+
✅ Users imported: 2 successful
|
|
716
|
+
✅ Users in store: 2
|
|
717
|
+
✅ Active stores: 1
|
|
718
|
+
✅ User login updated
|
|
719
|
+
✅ Transaction completed
|
|
720
|
+
✅ System health: true
|
|
721
|
+
Healthy services: 3/3
|
|
722
|
+
|
|
723
|
+
📊 Statistics:
|
|
724
|
+
Enterprises: 1
|
|
725
|
+
Stores: 2
|
|
726
|
+
Users: 3
|
|
727
|
+
|
|
728
|
+
✅ Database connections closed
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
## Tổng kết
|
|
732
|
+
|
|
733
|
+
Thư viện @dqcai/sqlite cung cấp:
|
|
734
|
+
|
|
735
|
+
- ✅ **Cross-platform**: Hỗ trợ React Native và Node.js
|
|
736
|
+
- ✅ **Type-safe**: TypeScript support đầy đủ
|
|
737
|
+
- ✅ **Schema-driven**: Quản lý database qua JSON schema
|
|
738
|
+
- ✅ **Service-based**: Architecture rõ ràng, dễ mở rộng
|
|
739
|
+
- ✅ **Lazy loading**: Tối ưu performance trên mobile
|
|
740
|
+
- ✅ **Transaction support**: ACID compliance
|
|
741
|
+
- ✅ **Event system**: Lắng nghe và xử lý events
|
|
742
|
+
- ✅ **Import/Export**: CSV, JSON, bulk operations
|
|
743
|
+
- ✅ **Logging**: Tích hợp @dqcai/logger để trace/debug
|
|
602
744
|
|
|
603
745
|
## 🤝 Community & Support
|
|
604
746
|
|
|
@@ -622,4 +764,4 @@ Transform your data management with the most powerful universal SQLite library f
|
|
|
622
764
|
|
|
623
765
|
---
|
|
624
766
|
|
|
625
|
-
**@dqcai/sqlite** - One library, all platforms! 🌟
|
|
767
|
+
**@dqcai/sqlite** - One library, all platforms! 🌟
|