vasuzex 2.1.21 → 2.1.22
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.
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DatabaseConfigService
|
|
3
|
-
* Loads runtime configurations from database (app_configs
|
|
3
|
+
* Loads runtime configurations from database (app_configs table ONLY)
|
|
4
4
|
* and merges them into the ConfigRepository
|
|
5
5
|
*
|
|
6
|
+
* UNIFIED: system_configs has been merged into app_configs with scope column
|
|
7
|
+
* - scope='app' → Frontend configs (for web/mobile apps)
|
|
8
|
+
* - scope='api' → Backend configs (loaded into Config facade)
|
|
9
|
+
*
|
|
6
10
|
* Similar to Laravel's database-driven config but integrated with Vasuzex's ConfigRepository
|
|
7
11
|
*
|
|
8
12
|
* @example
|
|
@@ -12,7 +16,7 @@
|
|
|
12
16
|
* await dbConfigService.load();
|
|
13
17
|
*
|
|
14
18
|
* // Now access via config()
|
|
15
|
-
* app.config('
|
|
19
|
+
* app.config('PLATFORM_FEES'); // From database (scope='api')
|
|
16
20
|
* app.config('app.name'); // From file-based config
|
|
17
21
|
*/
|
|
18
22
|
|
|
@@ -28,8 +32,8 @@ export class DatabaseConfigService {
|
|
|
28
32
|
* @private
|
|
29
33
|
*/
|
|
30
34
|
#cache = {
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
apiConfigs: null, // Backend configs (scope='api')
|
|
36
|
+
appConfigs: null, // Frontend configs (scope='app') - for reference only
|
|
33
37
|
lastLoadTime: null,
|
|
34
38
|
};
|
|
35
39
|
|
|
@@ -71,9 +75,8 @@ export class DatabaseConfigService {
|
|
|
71
75
|
|
|
72
76
|
console.log('[DatabaseConfigService] Loading configs from database...');
|
|
73
77
|
|
|
74
|
-
// Load configs
|
|
75
|
-
await this.#
|
|
76
|
-
await this.#loadSystemConfigs();
|
|
78
|
+
// Load API configs (scope='api') - for backend/Config facade
|
|
79
|
+
await this.#loadApiConfigs();
|
|
77
80
|
|
|
78
81
|
// Update cache timestamp
|
|
79
82
|
this.#cache.lastLoadTime = Date.now();
|
|
@@ -100,28 +103,16 @@ export class DatabaseConfigService {
|
|
|
100
103
|
/**
|
|
101
104
|
* Get config value directly from database (bypass ConfigRepository)
|
|
102
105
|
* @param {string} key - Config key
|
|
106
|
+
* @param {string} scope - Config scope ('app' or 'api')
|
|
103
107
|
* @param {*} defaultValue - Default value
|
|
104
108
|
* @returns {Promise<*>}
|
|
105
109
|
*/
|
|
106
|
-
async getDirect(key, defaultValue = null) {
|
|
107
|
-
// Try app_configs first
|
|
110
|
+
async getDirect(key, scope = 'api', defaultValue = null) {
|
|
108
111
|
const AppConfig = await this.#getModel('AppConfig');
|
|
109
112
|
if (AppConfig) {
|
|
110
|
-
const value = await AppConfig.
|
|
111
|
-
|
|
112
|
-
return value;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Try system_configs
|
|
117
|
-
const SystemConfig = await this.#getModel('SystemConfig');
|
|
118
|
-
if (SystemConfig) {
|
|
119
|
-
const value = await SystemConfig.getValue(key, this.#environment, null);
|
|
120
|
-
if (value !== null) {
|
|
121
|
-
return value;
|
|
122
|
-
}
|
|
113
|
+
const value = await AppConfig.getTypedValue(key, scope, defaultValue);
|
|
114
|
+
return value;
|
|
123
115
|
}
|
|
124
|
-
|
|
125
116
|
return defaultValue;
|
|
126
117
|
}
|
|
127
118
|
|
|
@@ -129,32 +120,65 @@ export class DatabaseConfigService {
|
|
|
129
120
|
* Set config value in database
|
|
130
121
|
* @param {string} key - Config key
|
|
131
122
|
* @param {*} value - Config value
|
|
132
|
-
* @param {Object} options - Additional options (category, description, etc.)
|
|
123
|
+
* @param {Object} options - Additional options (scope, category, description, etc.)
|
|
133
124
|
* @returns {Promise<void>}
|
|
134
125
|
*/
|
|
135
126
|
async set(key, value, options = {}) {
|
|
136
127
|
const {
|
|
137
|
-
|
|
128
|
+
scope = 'api', // 'app' or 'api'
|
|
138
129
|
category = 'app',
|
|
139
130
|
description = '',
|
|
140
|
-
|
|
131
|
+
access_level = 'internal',
|
|
132
|
+
data_type = 'string',
|
|
141
133
|
is_active = true,
|
|
142
134
|
environment = this.#environment,
|
|
143
135
|
} = options;
|
|
144
136
|
|
|
145
|
-
const
|
|
137
|
+
const AppConfig = await this.#getModel('AppConfig');
|
|
138
|
+
|
|
139
|
+
if (!AppConfig) {
|
|
140
|
+
throw new Error('AppConfig model not found');
|
|
141
|
+
}
|
|
146
142
|
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
// Serialize value based on type
|
|
144
|
+
let serializedValue = value;
|
|
145
|
+
if (data_type === 'array' || data_type === 'object') {
|
|
146
|
+
serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
147
|
+
} else if (data_type === 'boolean') {
|
|
148
|
+
serializedValue = value ? 'true' : 'false';
|
|
149
|
+
} else {
|
|
150
|
+
serializedValue = String(value);
|
|
149
151
|
}
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
// Upsert the config
|
|
154
|
+
const existing = await AppConfig.query()
|
|
155
|
+
.where('key', key)
|
|
156
|
+
.where('scope', scope)
|
|
157
|
+
.where('environment', environment)
|
|
158
|
+
.first();
|
|
159
|
+
|
|
160
|
+
if (existing) {
|
|
161
|
+
await AppConfig.where('id', existing.id).update({
|
|
162
|
+
value: serializedValue,
|
|
163
|
+
category,
|
|
164
|
+
description,
|
|
165
|
+
access_level,
|
|
166
|
+
data_type,
|
|
167
|
+
is_active,
|
|
168
|
+
});
|
|
169
|
+
} else {
|
|
170
|
+
await AppConfig.create({
|
|
171
|
+
key,
|
|
172
|
+
value: serializedValue,
|
|
173
|
+
scope,
|
|
174
|
+
category,
|
|
175
|
+
description,
|
|
176
|
+
access_level,
|
|
177
|
+
data_type,
|
|
178
|
+
is_active,
|
|
179
|
+
environment,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
158
182
|
|
|
159
183
|
// Invalidate cache
|
|
160
184
|
this.#cache.lastLoadTime = null;
|
|
@@ -166,22 +190,26 @@ export class DatabaseConfigService {
|
|
|
166
190
|
/**
|
|
167
191
|
* Delete config from database
|
|
168
192
|
* @param {string} key - Config key
|
|
169
|
-
* @param {string}
|
|
193
|
+
* @param {string} scope - Config scope ('app' or 'api')
|
|
170
194
|
* @returns {Promise<boolean>}
|
|
171
195
|
*/
|
|
172
|
-
async delete(key,
|
|
173
|
-
const
|
|
196
|
+
async delete(key, scope = 'api') {
|
|
197
|
+
const AppConfig = await this.#getModel('AppConfig');
|
|
174
198
|
|
|
175
|
-
if (!
|
|
199
|
+
if (!AppConfig) {
|
|
176
200
|
return false;
|
|
177
201
|
}
|
|
178
202
|
|
|
179
|
-
|
|
203
|
+
await AppConfig.query()
|
|
204
|
+
.where('key', key)
|
|
205
|
+
.where('scope', scope)
|
|
206
|
+
.where('environment', this.#environment)
|
|
207
|
+
.delete();
|
|
180
208
|
|
|
181
209
|
// Invalidate cache
|
|
182
210
|
this.#cache.lastLoadTime = null;
|
|
183
211
|
|
|
184
|
-
return
|
|
212
|
+
return true;
|
|
185
213
|
}
|
|
186
214
|
|
|
187
215
|
/**
|
|
@@ -190,47 +218,47 @@ export class DatabaseConfigService {
|
|
|
190
218
|
*/
|
|
191
219
|
getAllDatabaseConfigs() {
|
|
192
220
|
return {
|
|
221
|
+
api: this.#cache.apiConfigs || {},
|
|
193
222
|
app: this.#cache.appConfigs || {},
|
|
194
|
-
system: this.#cache.systemConfigs || {},
|
|
195
223
|
};
|
|
196
224
|
}
|
|
197
225
|
|
|
198
226
|
/**
|
|
199
|
-
* Load
|
|
227
|
+
* Load API configs (scope='api') from database
|
|
228
|
+
* These are the backend configs that get loaded into Config facade
|
|
200
229
|
* @private
|
|
201
230
|
*/
|
|
202
|
-
async #
|
|
231
|
+
async #loadApiConfigs() {
|
|
203
232
|
const AppConfig = await this.#getModel('AppConfig');
|
|
204
233
|
|
|
205
234
|
if (!AppConfig) {
|
|
206
235
|
console.warn('[DatabaseConfigService] AppConfig model not found');
|
|
207
|
-
this.#cache.
|
|
236
|
+
this.#cache.apiConfigs = {};
|
|
208
237
|
return;
|
|
209
238
|
}
|
|
210
239
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return;
|
|
240
|
+
// Load only API-scoped configs for backend
|
|
241
|
+
const configs = await AppConfig.query()
|
|
242
|
+
.where('scope', 'api')
|
|
243
|
+
.where('is_active', true)
|
|
244
|
+
.where((query) => {
|
|
245
|
+
query.where('environment', this.#environment)
|
|
246
|
+
.orWhere('environment', 'all');
|
|
247
|
+
})
|
|
248
|
+
.get();
|
|
249
|
+
|
|
250
|
+
// Transform to key-value object with type casting
|
|
251
|
+
const result = {};
|
|
252
|
+
for (const config of configs) {
|
|
253
|
+
result[config.key] = AppConfig.castValue(config.value, config.data_type);
|
|
226
254
|
}
|
|
227
255
|
|
|
228
|
-
|
|
229
|
-
this.#cache.systemConfigs = configs;
|
|
256
|
+
this.#cache.apiConfigs = result;
|
|
230
257
|
}
|
|
231
258
|
|
|
232
259
|
/**
|
|
233
260
|
* Merge database configs into ConfigRepository
|
|
261
|
+
* Only API-scoped configs are merged (frontend configs stay in DB)
|
|
234
262
|
* @private
|
|
235
263
|
*/
|
|
236
264
|
#mergeIntoConfigRepository() {
|
|
@@ -240,16 +268,9 @@ export class DatabaseConfigService {
|
|
|
240
268
|
throw new Error('[DatabaseConfigService] ConfigRepository not found in container');
|
|
241
269
|
}
|
|
242
270
|
|
|
243
|
-
// Merge
|
|
244
|
-
if (this.#cache.
|
|
245
|
-
for (const [key, value] of Object.entries(this.#cache.
|
|
246
|
-
config.set(key, value);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Merge system_configs
|
|
251
|
-
if (this.#cache.systemConfigs) {
|
|
252
|
-
for (const [key, value] of Object.entries(this.#cache.systemConfigs)) {
|
|
271
|
+
// Merge only API configs (backend configs)
|
|
272
|
+
if (this.#cache.apiConfigs) {
|
|
273
|
+
for (const [key, value] of Object.entries(this.#cache.apiConfigs)) {
|
|
253
274
|
config.set(key, value);
|
|
254
275
|
}
|
|
255
276
|
}
|
|
@@ -323,8 +344,8 @@ export class DatabaseConfigService {
|
|
|
323
344
|
*/
|
|
324
345
|
clearCache() {
|
|
325
346
|
this.#cache = {
|
|
347
|
+
apiConfigs: null,
|
|
326
348
|
appConfigs: null,
|
|
327
|
-
systemConfigs: null,
|
|
328
349
|
lastLoadTime: null,
|
|
329
350
|
};
|
|
330
351
|
}
|
|
@@ -337,8 +358,7 @@ export class DatabaseConfigService {
|
|
|
337
358
|
return {
|
|
338
359
|
isValid: this.#isCacheValid(),
|
|
339
360
|
lastLoadTime: this.#cache.lastLoadTime,
|
|
340
|
-
|
|
341
|
-
systemConfigsCount: Object.keys(this.#cache.systemConfigs || {}).length,
|
|
361
|
+
apiConfigsCount: Object.keys(this.#cache.apiConfigs || {}).length,
|
|
342
362
|
cacheAge: this.#cache.lastLoadTime ? Date.now() - this.#cache.lastLoadTime : null,
|
|
343
363
|
cacheDuration: this.#cacheDuration,
|
|
344
364
|
};
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
* DatabaseConfigServiceProvider
|
|
3
3
|
* Service provider for database-driven configuration
|
|
4
4
|
*
|
|
5
|
-
* Loads configurations from
|
|
6
|
-
*
|
|
5
|
+
* UNIFIED: Loads configurations from app_configs table ONLY
|
|
6
|
+
* (system_configs has been merged into app_configs with scope column)
|
|
7
|
+
*
|
|
8
|
+
* - scope='api' configs are loaded into Config facade for backend use
|
|
9
|
+
* - scope='app' configs stay in DB for frontend API endpoints
|
|
7
10
|
*
|
|
8
11
|
* @example
|
|
9
12
|
* // In app.js
|
|
@@ -39,23 +42,22 @@ export class DatabaseConfigServiceProvider extends ServiceProvider {
|
|
|
39
42
|
|
|
40
43
|
/**
|
|
41
44
|
* Bootstrap services
|
|
42
|
-
* Load database configs and merge into ConfigRepository
|
|
45
|
+
* Load database configs (scope='api') and merge into ConfigRepository
|
|
43
46
|
*/
|
|
44
47
|
async boot() {
|
|
45
48
|
try {
|
|
46
49
|
const dbConfigService = this.make('db.config');
|
|
47
50
|
|
|
48
|
-
// Load configs from
|
|
51
|
+
// Load API-scoped configs from unified app_configs table
|
|
49
52
|
await dbConfigService.load();
|
|
50
53
|
|
|
51
|
-
console.log('[DatabaseConfigServiceProvider] Database configs loaded');
|
|
54
|
+
console.log('[DatabaseConfigServiceProvider] Database configs loaded (unified app_configs table)');
|
|
52
55
|
|
|
53
56
|
// Log cache stats in debug mode
|
|
54
57
|
if (this.config('app.debug', false)) {
|
|
55
58
|
const stats = dbConfigService.getCacheStats();
|
|
56
59
|
console.log('[DatabaseConfigServiceProvider] Cache stats:', {
|
|
57
|
-
|
|
58
|
-
systemConfigs: stats.systemConfigsCount,
|
|
60
|
+
apiConfigs: stats.apiConfigsCount,
|
|
59
61
|
cacheValid: stats.isValid,
|
|
60
62
|
});
|
|
61
63
|
}
|