@soham20/smart-offline-sdk 0.1.0 → 0.1.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,3 +1,7 @@
1
+ <<<<<<< HEAD
2
+ # Hackvision2026
3
+
4
+ =======
1
5
  # Hackvision2026 SDK (JavaScript)
2
6
 
3
7
  This repository contains the JavaScript SDK for Hackvision2026.
@@ -12,3 +16,4 @@ client.echo('hello').then(console.log);
12
16
  ```
13
17
 
14
18
  See `examples/` for a runnable example.
19
+ >>>>>>> 061641ebd342b507a49884dd32b30125a6525011
package/demo/index.html CHANGED
@@ -12,14 +12,14 @@
12
12
 
13
13
  SmartOffline.init({
14
14
  pages: ["/demo/index.html","/demo/api/profile.json"],
15
- apis: ["https://jsonplaceholder.typicode.com/posts"],
15
+ apis: ["https://jsonplaceholder.typicode.com/posts/2"],
16
16
  debug: true
17
17
  });
18
18
 
19
- fetch("https://jsonplaceholder.typicode.com/posts")
19
+ fetch("https://jsonplaceholder.typicode.com/posts/2")
20
20
  .then(res => res.json())
21
21
  .then(data => {
22
- document.body.innerHTML += `<pre>${data}</pre>`;
22
+ document.body.innerHTML += `<pre>${JSON.stringify(data, null, 2)}</pre>`;
23
23
  })
24
24
  .catch(err => {
25
25
  document.body.innerHTML += "<p>API failed</p>";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soham20/smart-offline-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Smart offline-first JavaScript SDK with intelligent caching for web applications",
5
5
  "main": "src/sdk/index.js",
6
6
  "scripts": {
@@ -22,11 +22,81 @@ self.addEventListener("message", (event) => {
22
22
  }
23
23
  });
24
24
 
25
+ /**
26
+ * -------- Usage Tracking (IndexedDB) --------
27
+ * Tracks frequency + recency per URL
28
+ */
29
+ function trackUsage(url) {
30
+ const request = indexedDB.open("smart-offline-usage", 1);
31
+
32
+ request.onupgradeneeded = () => {
33
+ const db = request.result;
34
+ if (!db.objectStoreNames.contains("usage")) {
35
+ db.createObjectStore("usage", { keyPath: "url" });
36
+ }
37
+ };
38
+
39
+ request.onsuccess = () => {
40
+ const db = request.result;
41
+ const tx = db.transaction("usage", "readwrite");
42
+ const store = tx.objectStore("usage");
43
+
44
+ const getReq = store.get(url);
45
+ getReq.onsuccess = () => {
46
+ const data = getReq.result || {
47
+ url,
48
+ count: 0,
49
+ lastAccessed: 0,
50
+ };
51
+
52
+ data.count += 1;
53
+ data.lastAccessed = Date.now();
54
+ store.put(data);
55
+ };
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Read usage info
61
+ */
62
+ function getUsage(url) {
63
+ return new Promise((resolve) => {
64
+ const request = indexedDB.open("smart-offline-usage", 1);
65
+
66
+ request.onsuccess = () => {
67
+ const db = request.result;
68
+ const tx = db.transaction("usage", "readonly");
69
+ const store = tx.objectStore("usage");
70
+
71
+ const getReq = store.get(url);
72
+ getReq.onsuccess = () => resolve(getReq.result);
73
+ getReq.onerror = () => resolve(null);
74
+ };
75
+
76
+ request.onerror = () => resolve(null);
77
+ });
78
+ }
79
+
80
+ /**
81
+ * Decide priority based on real usage
82
+ */
83
+ function isHighPriority(usage) {
84
+ if (!usage) return false;
85
+
86
+ const FREQUENT_THRESHOLD = 3;
87
+ const RECENT_THRESHOLD = 24 * 60 * 60 * 1000; // 24h
88
+
89
+ const frequent = usage.count >= FREQUENT_THRESHOLD;
90
+ const recent = Date.now() - usage.lastAccessed <= RECENT_THRESHOLD;
91
+
92
+ return frequent || recent;
93
+ }
94
+
25
95
  /**
26
96
  * Install event
27
97
  */
28
98
  self.addEventListener("install", (event) => {
29
- self.skipWaiting(); // 🔥 REQUIRED
99
+ self.skipWaiting();
30
100
  event.waitUntil(caches.open(CACHE_NAME));
31
101
  });
32
102
 
@@ -36,69 +106,80 @@ self.addEventListener("install", (event) => {
36
106
  self.addEventListener("activate", (event) => {
37
107
  event.waitUntil(
38
108
  Promise.all([
39
- self.clients.claim(), // 🔥 REQUIRED
109
+ self.clients.claim(),
40
110
  caches.keys().then((cacheNames) =>
41
111
  Promise.all(
42
112
  cacheNames.map((name) => {
43
113
  if (name !== CACHE_NAME) {
44
114
  return caches.delete(name);
45
115
  }
46
- }),
47
- ),
116
+ })
117
+ )
48
118
  ),
49
- ]),
119
+ ])
50
120
  );
51
121
  });
52
122
 
53
-
54
123
  /**
55
- * Fetch event SMART logic
124
+ * Fetch event SMART + PRIORITY logic
56
125
  */
57
126
  self.addEventListener("fetch", (event) => {
58
127
  const request = event.request;
59
128
 
60
129
  if (request.method !== "GET") return;
61
130
 
62
- console.log("[SW] Intercepted:", request.url);
63
-
64
131
  const isPage = SDK_CONFIG.pages.some((p) =>
65
132
  request.url.includes(p)
66
133
  );
67
-
68
134
  const isAPI = SDK_CONFIG.apis.some((a) =>
69
135
  request.url.includes(a)
70
136
  );
71
137
 
72
138
  if (!isPage && !isAPI) return;
73
139
 
140
+ if (SDK_CONFIG.debug) {
141
+ console.log("[SW] Intercepted:", request.url);
142
+ }
143
+
74
144
  event.respondWith(
75
145
  fetch(request)
76
146
  .then((response) => {
77
- const clone = response.clone();
78
- const cacheKey = request.url;
147
+ // Network success
148
+ trackUsage(request.url);
79
149
 
150
+ const clone = response.clone();
80
151
  caches.open(CACHE_NAME).then((cache) => {
81
- cache.put(cacheKey, clone);
152
+ cache.put(request.url, clone);
82
153
  });
83
154
 
84
155
  if (SDK_CONFIG.debug) {
85
156
  console.log(
86
157
  `[SmartOffline] Cached ${isAPI ? "API" : "PAGE"}:`,
87
- cacheKey
158
+ request.url
88
159
  );
89
160
  }
90
161
 
91
162
  return response;
92
163
  })
93
164
  .catch(() => {
94
- if (SDK_CONFIG.debug) {
95
- console.log(
96
- `[SmartOffline] Served from cache ${isAPI ? "API" : "PAGE"}:`,
97
- request.url
98
- );
99
- }
100
- return caches.match(request.url);
101
- }),
165
+ // Offline / network failure
166
+ trackUsage(request.url);
167
+
168
+ return getUsage(request.url).then((usage) => {
169
+ const highPriority = isHighPriority(usage);
170
+
171
+ if (SDK_CONFIG.debug) {
172
+ console.log(
173
+ `[SmartOffline] ${
174
+ highPriority ? "HIGH" : "NORMAL"
175
+ } priority:`,
176
+ request.url
177
+ );
178
+ }
179
+
180
+ // v1 behavior: both return cache, but priority is decided & logged
181
+ return caches.match(request.url);
182
+ });
183
+ })
102
184
  );
103
185
  });
104
-
@@ -0,0 +1,37 @@
1
+ const DB_NAME = "smart-offline-usage";
2
+ const STORE_NAME = "usage";
3
+ const DB_VERSION = 1;
4
+
5
+ function openDB() {
6
+ return new Promise((resolve, reject) => {
7
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
8
+
9
+ request.onupgradeneeded = () => {
10
+ const db = request.result;
11
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
12
+ db.createObjectStore(STORE_NAME, { keyPath: "url" });
13
+ }
14
+ };
15
+
16
+ request.onsuccess = () => resolve(request.result);
17
+ request.onerror = () => reject(request.error);
18
+ });
19
+ }
20
+
21
+ export async function trackUsage(url) {
22
+ const db = await openDB();
23
+ const tx = db.transaction(STORE_NAME, "readwrite");
24
+ const store = tx.objectStore(STORE_NAME);
25
+
26
+ const existing = await new Promise(resolve => {
27
+ const req = store.get(url);
28
+ req.onsuccess = () => resolve(req.result);
29
+ req.onerror = () => resolve(null);
30
+ });
31
+
32
+ const data = existing || { url, count: 0, lastAccessed: 0 };
33
+ data.count += 1;
34
+ data.lastAccessed = Date.now();
35
+
36
+ store.put(data);
37
+ }