vasuzex 2.1.26 → 2.1.29

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.
@@ -13,6 +13,7 @@
13
13
 
14
14
  const CACHE_KEY = 'app-config';
15
15
  const CACHE_EXPIRY_KEY = 'app-config-expiry';
16
+ const CACHE_VERSION_KEY = 'app-config-version';
16
17
  const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
17
18
  const BACKGROUND_REFRESH_KEY = 'app-config-last-background-refresh';
18
19
  const BACKGROUND_REFRESH_INTERVAL = 60 * 60 * 1000; // 1 hour - only refresh once per hour
@@ -25,18 +26,33 @@ const BACKGROUND_REFRESH_INTERVAL = 60 * 60 * 1000; // 1 hour - only refresh onc
25
26
  * @param {boolean} options.forceRefresh - Skip cache and fetch fresh
26
27
  * @param {number} options.cacheDuration - Cache duration in milliseconds
27
28
  * @param {string} options.configUrl - Custom config endpoint path (default: '/config/app-settings')
29
+ * @param {boolean} options.versionCheck - Enable version-based cache invalidation (default: false)
30
+ * @param {string} options.versionUrl - Custom version endpoint path (default: '/config/version')
28
31
  * @returns {Promise<Object>} Configuration object
29
32
  */
30
33
  export async function loadAppConfig(apiBaseUrl, options = {}) {
31
34
  const {
32
35
  forceRefresh = false,
33
36
  cacheDuration = DEFAULT_CACHE_DURATION,
34
- configUrl = '/config/app-settings'
37
+ configUrl = '/config/app-settings',
38
+ versionCheck = false,
39
+ versionUrl = '/config/version'
35
40
  } = options;
36
41
 
37
42
  try {
43
+ let shouldForceRefresh = forceRefresh;
44
+
45
+ // Check version if enabled
46
+ if (versionCheck && !forceRefresh) {
47
+ const versionChanged = await checkConfigVersion(apiBaseUrl, versionUrl);
48
+ if (versionChanged) {
49
+ console.log('🔄 Config version changed, clearing cache');
50
+ shouldForceRefresh = true;
51
+ }
52
+ }
53
+
38
54
  // Check cache first (unless force refresh)
39
- if (!forceRefresh) {
55
+ if (!shouldForceRefresh) {
40
56
  const cached = getCachedConfig();
41
57
  if (cached) {
42
58
  console.log('📦 Using cached app config');
@@ -52,6 +68,11 @@ export async function loadAppConfig(apiBaseUrl, options = {}) {
52
68
  console.log('🌐 Fetching app config from API...');
53
69
  const config = await fetchConfigFromAPI(apiBaseUrl, configUrl);
54
70
 
71
+ // Extract and store version from response if present
72
+ if (versionCheck && config._meta?.version) {
73
+ localStorage.setItem(CACHE_VERSION_KEY, config._meta.version);
74
+ }
75
+
55
76
  // Cache the result
56
77
  cacheConfig(config, cacheDuration);
57
78
 
@@ -196,6 +217,69 @@ async function refreshConfigInBackground(apiBaseUrl, cacheDuration, configUrl =
196
217
  }
197
218
  }
198
219
 
220
+ /**
221
+ * Check if config version has changed on server
222
+ * @param {string} apiBaseUrl - API base URL
223
+ * @param {string} versionUrl - Version endpoint path
224
+ * @returns {Promise<boolean>} True if version changed, false otherwise
225
+ */
226
+ async function checkConfigVersion(apiBaseUrl, versionUrl) {
227
+ try {
228
+ const baseUrl = apiBaseUrl.replace(/\/$/, '');
229
+ const path = versionUrl.startsWith('/') ? versionUrl : `/${versionUrl}`;
230
+ const url = `${baseUrl}${path}`;
231
+
232
+ // Fetch version from server
233
+ const response = await fetch(url, {
234
+ method: 'GET',
235
+ headers: { 'Content-Type': 'application/json' },
236
+ });
237
+
238
+ // If endpoint doesn't exist, silently continue (backward compatible)
239
+ if (response.status === 404) {
240
+ console.debug('[ConfigLoader] Version endpoint not found (backward compatible mode)');
241
+ return false;
242
+ }
243
+
244
+ if (!response.ok) {
245
+ throw new Error(`Version check failed: ${response.status}`);
246
+ }
247
+
248
+ const result = await response.json();
249
+
250
+ // Extract version from standardized response: { success, data: { version } }
251
+ const serverVersion = result.data?.version || result.version;
252
+
253
+ if (!serverVersion) {
254
+ console.warn('[ConfigLoader] No version found in response');
255
+ return false;
256
+ }
257
+
258
+ // Get cached version
259
+ const cachedVersion = localStorage.getItem(CACHE_VERSION_KEY);
260
+
261
+ // First time - store version
262
+ if (!cachedVersion) {
263
+ localStorage.setItem(CACHE_VERSION_KEY, serverVersion);
264
+ return false; // Don't force refresh on first load
265
+ }
266
+
267
+ // Compare versions
268
+ if (cachedVersion !== serverVersion) {
269
+ console.log(`[ConfigLoader] Version changed: ${cachedVersion} → ${serverVersion}`);
270
+ localStorage.setItem(CACHE_VERSION_KEY, serverVersion);
271
+ clearConfigCache(); // Clear cache to force fresh fetch
272
+ return true;
273
+ }
274
+
275
+ return false; // Version unchanged
276
+ } catch (error) {
277
+ // Non-critical error - don't break the app
278
+ console.debug('[ConfigLoader] Version check failed (non-critical):', error.message);
279
+ return false;
280
+ }
281
+ }
282
+
199
283
  /**
200
284
  * Clear cached configuration
201
285
  */
@@ -203,6 +287,7 @@ export function clearConfigCache() {
203
287
  localStorage.removeItem(CACHE_KEY);
204
288
  localStorage.removeItem(CACHE_EXPIRY_KEY);
205
289
  localStorage.removeItem(BACKGROUND_REFRESH_KEY);
290
+ // Note: We don't clear CACHE_VERSION_KEY - it's needed for next comparison
206
291
  console.log('🗑️ Config cache cleared');
207
292
  }
208
293
 
@@ -62,7 +62,9 @@ export function AppConfigProvider({
62
62
  errorComponent,
63
63
  showLoadingScreen = true,
64
64
  showErrorScreen = true,
65
- cacheDuration
65
+ cacheDuration,
66
+ versionCheck = false,
67
+ versionUrl
66
68
  }) {
67
69
  const [config, setConfig] = useState(defaultConfig);
68
70
  const [loading, setLoading] = useState(true);
@@ -108,6 +110,8 @@ export function AppConfigProvider({
108
110
  forceRefresh,
109
111
  cacheDuration,
110
112
  configUrl,
113
+ versionCheck,
114
+ versionUrl,
111
115
  });
112
116
 
113
117
  setConfig(fetchedConfig);
@@ -119,7 +123,7 @@ export function AppConfigProvider({
119
123
  } finally {
120
124
  setLoading(false);
121
125
  }
122
- }, [getApiBaseUrl, cacheDuration, configUrl]); // Removed defaultConfig from deps
126
+ }, [getApiBaseUrl, cacheDuration, configUrl, versionCheck, versionUrl]); // Removed defaultConfig from deps
123
127
 
124
128
  // Load config only once on mount
125
129
  useEffect(() => {
@@ -255,6 +259,8 @@ AppConfigProvider.propTypes = {
255
259
  showLoadingScreen: PropTypes.bool,
256
260
  showErrorScreen: PropTypes.bool,
257
261
  cacheDuration: PropTypes.number,
262
+ versionCheck: PropTypes.bool,
263
+ versionUrl: PropTypes.string,
258
264
  };
259
265
 
260
266
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vasuzex",
3
- "version": "2.1.26",
3
+ "version": "2.1.29",
4
4
  "description": "Laravel-inspired framework for Node.js monorepos - V2 with optimized dependencies",
5
5
  "type": "module",
6
6
  "main": "./framework/index.js",