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 and system_configs tables)
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('phonepe.merchantId'); // From database
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
- appConfigs: null,
32
- systemConfigs: null,
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 from database
75
- await this.#loadAppConfigs();
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.getValue(key, this.#environment, null);
111
- if (value !== null) {
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
- type = 'app', // 'app' or 'system'
128
+ scope = 'api', // 'app' or 'api'
138
129
  category = 'app',
139
130
  description = '',
140
- is_public = false,
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 Model = await this.#getModel(type === 'app' ? 'AppConfig' : 'SystemConfig');
137
+ const AppConfig = await this.#getModel('AppConfig');
138
+
139
+ if (!AppConfig) {
140
+ throw new Error('AppConfig model not found');
141
+ }
146
142
 
147
- if (!Model) {
148
- throw new Error(`Model not found for type: ${type}`);
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
- await Model.setValue(key, value, {
152
- category,
153
- description,
154
- is_public,
155
- is_active,
156
- environment,
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} type - Config type ('app' or 'system')
193
+ * @param {string} scope - Config scope ('app' or 'api')
170
194
  * @returns {Promise<boolean>}
171
195
  */
172
- async delete(key, type = 'app') {
173
- const Model = await this.#getModel(type === 'app' ? 'AppConfig' : 'SystemConfig');
196
+ async delete(key, scope = 'api') {
197
+ const AppConfig = await this.#getModel('AppConfig');
174
198
 
175
- if (!Model) {
199
+ if (!AppConfig) {
176
200
  return false;
177
201
  }
178
202
 
179
- const result = await Model.deleteByKey(key, this.#environment);
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 result;
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 app_configs from database
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 #loadAppConfigs() {
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.appConfigs = {};
236
+ this.#cache.apiConfigs = {};
208
237
  return;
209
238
  }
210
239
 
211
- const configs = await AppConfig.getAllAsObject(this.#environment);
212
- this.#cache.appConfigs = configs;
213
- }
214
-
215
- /**
216
- * Load system_configs from database
217
- * @private
218
- */
219
- async #loadSystemConfigs() {
220
- const SystemConfig = await this.#getModel('SystemConfig');
221
-
222
- if (!SystemConfig) {
223
- console.warn('[DatabaseConfigService] SystemConfig model not found');
224
- this.#cache.systemConfigs = {};
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
- const configs = await SystemConfig.getAllAsObject(this.#environment);
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 app_configs
244
- if (this.#cache.appConfigs) {
245
- for (const [key, value] of Object.entries(this.#cache.appConfigs)) {
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
- appConfigsCount: Object.keys(this.#cache.appConfigs || {}).length,
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 database (app_configs and system_configs)
6
- * and merges them into the ConfigRepository during boot phase
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 database
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
- appConfigs: stats.appConfigsCount,
58
- systemConfigs: stats.systemConfigsCount,
60
+ apiConfigs: stats.apiConfigsCount,
59
61
  cacheValid: stats.isValid,
60
62
  });
61
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vasuzex",
3
- "version": "2.1.21",
3
+ "version": "2.1.22",
4
4
  "description": "Laravel-inspired framework for Node.js monorepos - V2 with optimized dependencies",
5
5
  "type": "module",
6
6
  "main": "./framework/index.js",