@soham20/smart-offline-sdk 0.2.1 โ†’ 1.0.1

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
@@ -1,63 +1,229 @@
1
- # Hackvision2026 SDK (JavaScript)
1
+ # SmartOffline SDK
2
2
 
3
- This repository contains the JavaScript SDK for Hackvision2026.
3
+ A complete, reliable offline-first caching SDK for web applications. Provides intelligent priority-based caching with configurable algorithms.
4
4
 
5
- ## Quickstart
5
+ ## Features
6
6
 
7
- ```javascript
8
- import { SmartOffline } from "./src/index.js";
7
+ - ๐Ÿš€ **Easy Setup** - Single function call to initialize
8
+ - ๐ŸŽฏ **Priority-Based Caching** - Intelligent frequency and recency scoring
9
+ - ๐ŸŒ **Network Aware** - Adapts caching strategy based on connection quality
10
+ - ๐Ÿ“Š **Usage Tracking** - Tracks access patterns to optimize caching
11
+ - ๐Ÿ”ง **Highly Configurable** - Customize every aspect of the caching algorithm
12
+ - ๐Ÿ“ **TypeScript Support** - Full type definitions included
13
+ - ๐Ÿงช **Test Utilities** - Built-in testing and inspection tools
9
14
 
10
- SmartOffline.init({
11
- pages: ["/dashboard", "/profile"],
12
- apis: ["/api/user", "/api/data"],
13
- debug: true,
14
- });
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @soham20/smart-offline-sdk
15
19
  ```
16
20
 
17
- See `examples/` for a runnable example.
21
+ Or directly from GitHub:
18
22
 
19
- ## Priority Tuning Options
23
+ ```bash
24
+ npm install git+https://github.com/OwaisShaikh1/Hackvision2026.git
25
+ ```
20
26
 
21
- You can fine-tune how the SDK decides caching priority:
27
+ ## Quick Start
28
+
29
+ ```javascript
30
+ import { setupSmartOffline } from "@soham20/smart-offline-sdk";
22
31
 
23
- | Option | Type | Default | Description |
24
- |---------------------|-------------------------------------------|---------------|-----------------------------------------------------------------------------|
25
- | `frequencyThreshold`| `number` | `3` | Number of accesses before a resource is considered "frequent" |
26
- | `recencyThreshold` | `number` (ms) | `86400000` (24h) | Milliseconds within which a resource is considered "recent" |
27
- | `maxResourceSize` | `number` (bytes) | `Infinity` | Max bytes to cache per resource; larger resources are skipped |
28
- | `networkQuality` | `'auto'` \| `'fast'` \| `'slow'` | `'auto'` | Affects caching aggressiveness; `'auto'` uses Network Information API |
29
- | `significance` | `{ [urlPattern: string]: 'high' \| 'normal' \| 'low' }` | `{}` | Manual priority overrides per URL pattern |
32
+ // Initialize early in your app
33
+ await setupSmartOffline({
34
+ pages: ["/dashboard/*", "/products/*"],
35
+ apis: ["/api/v1/*"],
36
+ debug: true,
37
+ });
38
+ ```
30
39
 
31
- ### Example with all options
40
+ ## Configuration Options
41
+
42
+ | Option | Type | Default | Description |
43
+ | -------------------- | --------------------------------- | ------------------------ | ------------------------------------------------------- |
44
+ | `pages` | `string[]` | `[]` | URL patterns for pages to cache (supports `*` wildcard) |
45
+ | `apis` | `string[]` | `[]` | URL patterns for API endpoints to cache |
46
+ | `debug` | `boolean` | `false` | Enable debug logging in console |
47
+ | `frequencyThreshold` | `number` | `3` | Number of accesses before URL is high priority |
48
+ | `recencyThreshold` | `number` | `86400000` | Time in ms for "recent" access (default: 24h) |
49
+ | `maxResourceSize` | `number` | `10485760` | Max bytes to cache per resource (default: 10MB) |
50
+ | `networkQuality` | `'auto' \| 'slow' \| 'fast'` | `'auto'` | Network quality detection mode |
51
+ | `significance` | `Record<string, 'high' \| 'low'>` | `{}` | Priority overrides for URL patterns |
52
+ | `weights` | `{ frequency, recency, size }` | `{ 1, 1, 1 }` | Weights for priority calculation |
53
+ | `customPriorityFn` | `Function` | `null` | Custom priority function (0-100) |
54
+ | `enableDetailedLogs` | `boolean` | `false` | Enable detailed event logging |
55
+ | `onCacheEvent` | `Function` | `undefined` | Callback for cache events |
56
+ | `serviceWorkerPath` | `string` | `'/smart-offline-sw.js'` | Path to service worker file |
57
+ | `serviceWorkerScope` | `string` | `'/'` | Service worker scope |
58
+
59
+ ## Complete Example
32
60
 
33
61
  ```javascript
34
- SmartOffline.init({
35
- pages: ["/dashboard"],
36
- apis: ["/api/"],
62
+ import { setupSmartOffline, SmartOffline } from "@soham20/smart-offline-sdk";
63
+
64
+ // Full configuration example
65
+ const result = await setupSmartOffline({
66
+ // URL patterns to cache
67
+ pages: ["/admin/*", "/dashboard", "/products/*"],
68
+ apis: ["/api/v1/*", "/graphql"],
69
+
70
+ // Enable debug logging
37
71
  debug: true,
38
72
 
39
73
  // Priority tuning
40
- frequencyThreshold: 5, // require 5 accesses to be "frequent"
74
+ frequencyThreshold: 5, // 5 accesses = high priority
41
75
  recencyThreshold: 12 * 60 * 60 * 1000, // 12 hours
42
- maxResourceSize: 500 * 1024, // skip caching resources > 500 KB
43
- networkQuality: "auto", // or 'fast' / 'slow'
76
+ maxResourceSize: 5 * 1024 * 1024, // 5MB max
77
+
78
+ // Network detection
79
+ networkQuality: "auto",
80
+
81
+ // Manual priority overrides
44
82
  significance: {
45
- "/api/critical": "high", // always high priority
46
- "/api/analytics": "low", // always low priority
83
+ "/api/critical/*": "high", // Always cache
84
+ "/api/logs/*": "low", // Never cache
85
+ },
86
+
87
+ // Weight configuration
88
+ weights: {
89
+ frequency: 2, // Frequency is 2x more important
90
+ recency: 1,
91
+ size: 1,
92
+ },
93
+
94
+ // Custom priority function
95
+ customPriorityFn: (usage, url, config) => {
96
+ if (url.includes("vip")) return 100;
97
+ if (!usage) return 0;
98
+ return usage.count >= 5 ? 100 : 25;
99
+ },
100
+
101
+ // Event callback
102
+ onCacheEvent: (event) => {
103
+ console.log(`Cache event: ${event.type}`, event.url);
47
104
  },
48
105
  });
106
+
107
+ if (result.success) {
108
+ console.log("SmartOffline ready!");
109
+ }
49
110
  ```
50
111
 
51
- ## Installation
112
+ ## API Reference
52
113
 
53
- ### From npm (after publishing)
114
+ ### Main Functions
54
115
 
55
- ```bash
56
- npm install @soham20/smart-offline-sdk
116
+ ```javascript
117
+ import {
118
+ setupSmartOffline, // Initialize SDK (async)
119
+ updateConfig, // Update config at runtime
120
+ getConfig, // Get current configuration
121
+ isSmartOfflineReady, // Check if initialized
122
+ clearAllCache, // Clear all cached data
123
+ getCacheStats, // Get cache statistics
124
+ forceUpdate, // Force SW update
125
+ uninstall, // Uninstall SDK
126
+ } from "@soham20/smart-offline-sdk";
127
+ ```
128
+
129
+ ### Event Handling
130
+
131
+ ```javascript
132
+ import { on, off } from "@soham20/smart-offline-sdk";
133
+
134
+ // Listen for cache events
135
+ on("cache", (event) => console.log("Cached:", event.url));
136
+ on("skip", (event) => console.log("Skipped:", event.url));
137
+ on("serve", (event) => console.log("Served from cache:", event.url));
138
+ on("error", (event) => console.log("Error:", event.url));
139
+
140
+ // Remove listener
141
+ off("cache", myCallback);
142
+ ```
143
+
144
+ ### SmartOffline Object
145
+
146
+ ```javascript
147
+ import { SmartOffline } from "@soham20/smart-offline-sdk";
148
+
149
+ // All methods available on SmartOffline object
150
+ SmartOffline.setup(config); // setupSmartOffline
151
+ SmartOffline.updateConfig(cfg); // Update configuration
152
+ SmartOffline.getConfig(); // Get current config
153
+ SmartOffline.isReady(); // Check if ready
154
+ SmartOffline.clearCache(); // Clear all cache
155
+ SmartOffline.getStats(); // Get cache stats
156
+ SmartOffline.forceUpdate(); // Force SW update
157
+ SmartOffline.uninstall(); // Clean uninstall
158
+ ```
159
+
160
+ ## Test Utilities
161
+
162
+ ```javascript
163
+ import {
164
+ SmartOfflineTestSuite,
165
+ runSmartOfflineTests,
166
+ CacheInspector,
167
+ } from "@soham20/smart-offline-sdk";
168
+
169
+ // Run all tests
170
+ const results = await runSmartOfflineTests();
171
+
172
+ // Or use the test suite directly
173
+ const suite = new SmartOfflineTestSuite({ pages: ["/test/*"] });
174
+ await suite.runAll();
175
+ suite.printResults();
176
+
177
+ // Inspect cache
178
+ const inspector = new CacheInspector();
179
+ await inspector.showAll();
180
+ const data = await inspector.getAllData();
57
181
  ```
58
182
 
59
- ### Directly from GitHub
183
+ ## Browser Console Testing
184
+
185
+ ```javascript
186
+ // After SDK is loaded, these are available globally:
187
+ await runSmartOfflineTests();
188
+ await SmartOffline.getStats();
189
+ new CacheInspector().showAll();
190
+ ```
191
+
192
+ ## How the Algorithm Works
193
+
194
+ 1. **URL Pattern Matching**: Caches pages/APIs matching configured patterns
195
+ 2. **Frequency Scoring**: URLs accessed >= `frequencyThreshold` times get higher score
196
+ 3. **Recency Scoring**: URLs accessed within `recencyThreshold` get higher score
197
+ 4. **Weighted Calculation**:
198
+ - `frequencyScore = min(100, (accessCount / threshold) * 100)`
199
+ - `recencyScore = max(0, 100 - (timeSinceAccess / threshold) * 100)`
200
+ - `weightedScore = (freqScore * freqWeight + recencyScore * recencyWeight) / totalWeight`
201
+ - HIGH priority if `weightedScore > 50`
202
+ 5. **Network Awareness**: On slow networks, only HIGH priority resources are cached
203
+ 6. **Size Limits**: Resources exceeding `maxResourceSize` are skipped
204
+
205
+ ## Service Worker Setup
206
+
207
+ Copy `smart-offline-sw.js` to your public directory:
60
208
 
61
209
  ```bash
62
- npm install git+https://github.com/OwaisShaikh1/Hackvision2026.git
210
+ cp node_modules/@soham20/smart-offline-sdk/smart-offline-sw.js public/
63
211
  ```
212
+
213
+ ## TypeScript
214
+
215
+ Full TypeScript support with exported types:
216
+
217
+ ```typescript
218
+ import type {
219
+ SmartOfflineConfig,
220
+ CacheEvent,
221
+ UsageData,
222
+ SetupResult,
223
+ CacheStats,
224
+ } from "@soham20/smart-offline-sdk";
225
+ ```
226
+
227
+ ## License
228
+
229
+ MIT
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@soham20/smart-offline-sdk",
3
- "version": "0.2.1",
3
+ "version": "1.0.1",
4
4
  "description": "Smart offline-first JavaScript SDK with intelligent caching for web applications",
5
- "main": "./src/index.cjs.js",
5
+ "main": "./src/index.cjs",
6
6
  "module": "./src/index.js",
7
7
  "browser": "./src/index.js",
8
8
  "types": "./src/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./src/index.js",
12
- "require": "./src/index.cjs.js",
12
+ "require": "./src/index.cjs",
13
13
  "browser": "./src/index.js",
14
+ "types": "./src/index.d.ts",
14
15
  "default": "./src/index.js"
15
16
  },
16
17
  "./client": {
@@ -20,6 +20,141 @@ let SDK_CONFIG = {
20
20
  enableDetailedLogs: false
21
21
  };
22
22
 
23
+ /**
24
+ * -------- CONSOLE LOGGING UTILITIES --------
25
+ * Rich, colorful debug logs for caching activity
26
+ */
27
+ const LOG_STYLES = {
28
+ banner: 'background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); color: white; font-size: 14px; padding: 8px 16px; border-radius: 4px; font-weight: bold;',
29
+ cached: 'background: #10B981; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;',
30
+ skipped: 'background: #F59E0B; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;',
31
+ served: 'background: #3B82F6; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;',
32
+ error: 'background: #EF4444; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;',
33
+ intercept: 'background: #8B5CF6; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;',
34
+ url: 'color: #6366F1; font-weight: bold;',
35
+ reason: 'color: #059669; font-style: italic;',
36
+ metadata: 'color: #6B7280;',
37
+ priority_high: 'background: #DC2626; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;',
38
+ priority_normal: 'background: #9CA3AF; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;',
39
+ type_api: 'background: #7C3AED; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;',
40
+ type_page: 'background: #2563EB; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;'
41
+ };
42
+
43
+ function formatBytes(bytes) {
44
+ if (bytes === 0 || !bytes) return '0 B';
45
+ const k = 1024;
46
+ const sizes = ['B', 'KB', 'MB', 'GB'];
47
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
48
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
49
+ }
50
+
51
+ function formatTimestamp(ts) {
52
+ return new Date(ts).toLocaleTimeString();
53
+ }
54
+
55
+ /**
56
+ * Print rich cache log to console
57
+ */
58
+ function printCacheLog(action, url, reason, details = {}) {
59
+ if (!SDK_CONFIG.debug) return;
60
+
61
+ const time = formatTimestamp(Date.now());
62
+ const shortUrl = url.length > 60 ? url.substring(0, 57) + '...' : url;
63
+
64
+ switch (action) {
65
+ case 'CACHED':
66
+ console.groupCollapsed(
67
+ `%c๐Ÿ’พ CACHED %c${shortUrl}`,
68
+ LOG_STYLES.cached,
69
+ LOG_STYLES.url
70
+ );
71
+ console.log(`%cโฐ Time: %c${time}`, 'font-weight: bold;', 'color: #6B7280;');
72
+ console.log(`%c๐Ÿ“ URL: %c${url}`, 'font-weight: bold;', LOG_STYLES.url);
73
+ console.log(`%c๐Ÿ“ Reason: %c${reason}`, 'font-weight: bold;', LOG_STYLES.reason);
74
+ if (details.type) {
75
+ console.log(`%c๐Ÿ“ฆ Type: %c${details.type}`, 'font-weight: bold;', details.type === 'API' ? LOG_STYLES.type_api : LOG_STYLES.type_page);
76
+ }
77
+ if (details.priority) {
78
+ console.log(`%cโšก Priority: %c${details.priority.toUpperCase()}`, 'font-weight: bold;', details.priority === 'high' ? LOG_STYLES.priority_high : LOG_STYLES.priority_normal);
79
+ }
80
+ if (details.size) {
81
+ console.log(`%c๐Ÿ“Š Size: %c${formatBytes(details.size)}`, 'font-weight: bold;', 'color: #6B7280;');
82
+ }
83
+ if (details.usage) {
84
+ console.log(`%c๐Ÿ“ˆ Usage Stats:`, 'font-weight: bold;', details.usage);
85
+ }
86
+ console.log('%cโœ… Object cached successfully', 'color: #10B981; font-weight: bold;');
87
+ console.groupEnd();
88
+ break;
89
+
90
+ case 'SKIPPED':
91
+ console.groupCollapsed(
92
+ `%cโญ๏ธ SKIPPED %c${shortUrl}`,
93
+ LOG_STYLES.skipped,
94
+ LOG_STYLES.url
95
+ );
96
+ console.log(`%cโฐ Time: %c${time}`, 'font-weight: bold;', 'color: #6B7280;');
97
+ console.log(`%c๐Ÿ“ URL: %c${url}`, 'font-weight: bold;', LOG_STYLES.url);
98
+ console.log(`%c๐Ÿšซ Reason: %c${reason}`, 'font-weight: bold;', 'color: #F59E0B; font-weight: bold;');
99
+ if (details.size && details.limit) {
100
+ console.log(`%c๐Ÿ“Š Size: %c${formatBytes(details.size)} (limit: ${formatBytes(details.limit)})`, 'font-weight: bold;', 'color: #EF4444;');
101
+ }
102
+ if (details.networkQuality) {
103
+ console.log(`%c๐ŸŒ Network: %c${details.networkQuality}`, 'font-weight: bold;', 'color: #6B7280;');
104
+ }
105
+ if (details.priority) {
106
+ console.log(`%cโšก Priority: %c${details.priority.toUpperCase()}`, 'font-weight: bold;', details.priority === 'high' ? LOG_STYLES.priority_high : LOG_STYLES.priority_normal);
107
+ }
108
+ console.log('%cโš ๏ธ Object NOT cached', 'color: #F59E0B; font-weight: bold;');
109
+ console.groupEnd();
110
+ break;
111
+
112
+ case 'SERVED':
113
+ console.groupCollapsed(
114
+ `%c๐Ÿ“ค SERVED FROM CACHE %c${shortUrl}`,
115
+ LOG_STYLES.served,
116
+ LOG_STYLES.url
117
+ );
118
+ console.log(`%cโฐ Time: %c${time}`, 'font-weight: bold;', 'color: #6B7280;');
119
+ console.log(`%c๐Ÿ“ URL: %c${url}`, 'font-weight: bold;', LOG_STYLES.url);
120
+ console.log(`%c๐Ÿ“ Reason: %c${reason}`, 'font-weight: bold;', LOG_STYLES.reason);
121
+ if (details.priority) {
122
+ console.log(`%cโšก Priority: %c${details.priority.toUpperCase()}`, 'font-weight: bold;', details.priority === 'high' ? LOG_STYLES.priority_high : LOG_STYLES.priority_normal);
123
+ }
124
+ if (details.usage) {
125
+ console.log(`%c๐Ÿ“ˆ Usage Stats:`, 'font-weight: bold;', details.usage);
126
+ }
127
+ console.log('%c๐Ÿ”„ Served from offline cache', 'color: #3B82F6; font-weight: bold;');
128
+ console.groupEnd();
129
+ break;
130
+
131
+ case 'ERROR':
132
+ console.groupCollapsed(
133
+ `%cโŒ CACHE MISS %c${shortUrl}`,
134
+ LOG_STYLES.error,
135
+ LOG_STYLES.url
136
+ );
137
+ console.log(`%cโฐ Time: %c${time}`, 'font-weight: bold;', 'color: #6B7280;');
138
+ console.log(`%c๐Ÿ“ URL: %c${url}`, 'font-weight: bold;', LOG_STYLES.url);
139
+ console.log(`%c๐Ÿšซ Reason: %c${reason}`, 'font-weight: bold;', 'color: #EF4444; font-weight: bold;');
140
+ if (details.priority) {
141
+ console.log(`%cโšก Priority: %c${details.priority.toUpperCase()}`, 'font-weight: bold;', details.priority === 'high' ? LOG_STYLES.priority_high : LOG_STYLES.priority_normal);
142
+ }
143
+ console.log('%cโŒ Resource not available offline', 'color: #EF4444; font-weight: bold;');
144
+ console.groupEnd();
145
+ break;
146
+
147
+ case 'INTERCEPT':
148
+ console.log(
149
+ `%c๐Ÿ” INTERCEPT %c${shortUrl} %c[${details.isAPI ? 'API' : 'PAGE'}]`,
150
+ LOG_STYLES.intercept,
151
+ LOG_STYLES.url,
152
+ details.isAPI ? LOG_STYLES.type_api : LOG_STYLES.type_page
153
+ );
154
+ break;
155
+ }
156
+ }
157
+
23
158
  /**
24
159
  * Receive config from SDK
25
160
  */
@@ -44,9 +179,27 @@ self.addEventListener("message", (event) => {
44
179
  });
45
180
 
46
181
  /**
47
- * Log cache events to IndexedDB
182
+ * Log cache events to IndexedDB and send to main thread
48
183
  */
49
184
  function logEvent(type, url, reason, metadata = {}) {
185
+ const eventData = {
186
+ type: `CACHE_${type.toUpperCase()}`,
187
+ url,
188
+ reason,
189
+ metadata,
190
+ timestamp: Date.now()
191
+ };
192
+
193
+ // Always send to main thread when debug or enableDetailedLogs is on
194
+ if (SDK_CONFIG.debug || SDK_CONFIG.enableDetailedLogs) {
195
+ self.clients.matchAll().then(clients => {
196
+ clients.forEach(client => {
197
+ client.postMessage(eventData);
198
+ });
199
+ });
200
+ }
201
+
202
+ // Store in IndexedDB only if enableDetailedLogs is on
50
203
  if (!SDK_CONFIG.enableDetailedLogs) return;
51
204
 
52
205
  const request = indexedDB.open("smart-offline-logs", 1);
@@ -72,19 +225,6 @@ function logEvent(type, url, reason, metadata = {}) {
72
225
  date: new Date().toISOString()
73
226
  });
74
227
  };
75
-
76
- // Also send to main thread
77
- self.clients.matchAll().then(clients => {
78
- clients.forEach(client => {
79
- client.postMessage({
80
- type: `CACHE_${type.toUpperCase()}`,
81
- url,
82
- reason,
83
- metadata,
84
- timestamp: Date.now()
85
- });
86
- });
87
- });
88
228
  }
89
229
 
90
230
  /**
@@ -250,9 +390,8 @@ self.addEventListener("fetch", (event) => {
250
390
 
251
391
  if (!isPage && !isAPI) return;
252
392
 
253
- if (SDK_CONFIG.debug) {
254
- console.log("[SW] Intercepted:", request.url);
255
- }
393
+ // Log interception event
394
+ printCacheLog('INTERCEPT', request.url, 'URL pattern matched', { isPage, isAPI });
256
395
 
257
396
  event.respondWith(
258
397
  fetch(request)
@@ -269,12 +408,11 @@ self.addEventListener("fetch", (event) => {
269
408
  limit: SDK_CONFIG.maxResourceSize
270
409
  });
271
410
 
272
- if (SDK_CONFIG.debug) {
273
- console.log(
274
- `[SmartOffline] Skipped caching (size ${size} > ${SDK_CONFIG.maxResourceSize}):`,
275
- request.url
276
- );
277
- }
411
+ printCacheLog('SKIPPED', request.url, 'Resource too large (exceeds maxResourceSize)', {
412
+ size,
413
+ limit: SDK_CONFIG.maxResourceSize
414
+ });
415
+
278
416
  return response;
279
417
  }
280
418
 
@@ -289,12 +427,11 @@ self.addEventListener("fetch", (event) => {
289
427
  priority: 'low'
290
428
  });
291
429
 
292
- if (SDK_CONFIG.debug) {
293
- console.log(
294
- `[SmartOffline] Skipped caching (slow network, not high priority):`,
295
- request.url
296
- );
297
- }
430
+ printCacheLog('SKIPPED', request.url, 'Slow network detected - skipping low priority resource', {
431
+ networkQuality: netQuality,
432
+ priority: 'low'
433
+ });
434
+
298
435
  return response;
299
436
  }
300
437
 
@@ -308,12 +445,13 @@ self.addEventListener("fetch", (event) => {
308
445
  });
309
446
  });
310
447
 
311
- if (SDK_CONFIG.debug) {
312
- console.log(
313
- `[SmartOffline] Cached ${isAPI ? "API" : "PAGE"}:`,
314
- request.url
315
- );
316
- }
448
+ // Rich console log for successful cache
449
+ printCacheLog('CACHED', request.url, 'Successfully fetched from network and cached', {
450
+ type: isAPI ? 'API' : 'PAGE',
451
+ size,
452
+ priority: highPriority ? 'high' : 'normal',
453
+ usage: usage ? { accessCount: usage.count, lastAccessed: new Date(usage.lastAccessed).toLocaleString() } : { accessCount: 1, lastAccessed: 'Now (first access)' }
454
+ });
317
455
 
318
456
  return response;
319
457
  })
@@ -331,16 +469,18 @@ self.addEventListener("fetch", (event) => {
331
469
  usage: usage ? { count: usage.count, lastAccessed: usage.lastAccessed } : null
332
470
  });
333
471
 
334
- if (SDK_CONFIG.debug) {
335
- console.log(
336
- `[SmartOffline] Served from cache (${highPriority ? "HIGH" : "NORMAL"} priority):`,
337
- request.url
338
- );
339
- }
472
+ printCacheLog('SERVED', request.url, 'Network unavailable - serving from cache', {
473
+ priority: highPriority ? 'high' : 'normal',
474
+ usage: usage ? { accessCount: usage.count, lastAccessed: new Date(usage.lastAccessed).toLocaleString() } : null
475
+ });
340
476
  } else {
341
477
  logEvent('error', request.url, 'cache_miss_offline', {
342
478
  priority: highPriority ? 'high' : 'normal'
343
479
  });
480
+
481
+ printCacheLog('ERROR', request.url, 'Network unavailable and resource not in cache', {
482
+ priority: highPriority ? 'high' : 'normal'
483
+ });
344
484
  }
345
485
 
346
486
  return cached;