universe-code 0.0.60 → 0.0.62
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/dist/angular/index.d.ts +7 -0
- package/dist/angular/index.js +1 -0
- package/dist/angular/services/idbService.ts +16 -42
- package/dist/core/index.js +1 -0
- package/dist/core/{time.ts → time.js} +2 -2
- package/dist/index.js +10 -0
- package/dist/indexdb/{db.ts → db.js} +6 -16
- package/dist/indexdb/{index.ts → index.js} +2 -2
- package/dist/indexdb/store.js +55 -0
- package/dist/react/{index.ts → index.js} +3 -3
- package/dist/react/indexdb/hooks/{idbHook.ts → idbHook.js} +1 -1
- package/dist/react/indexdb/store/{config.ts → config.js} +2 -8
- package/dist/react/indexdb/store/idbStore.js +39 -0
- package/package.json +9 -12
- package/dist/angular/index.ts +0 -9
- package/dist/core/index.ts +0 -1
- package/dist/index.ts +0 -6
- package/dist/indexdb/store.ts +0 -78
- package/dist/react/indexdb/store/idbStore.ts +0 -39
- /package/dist/socket/{index.ts → index.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IdbService } from './services/idbService.ts';
|
|
@@ -1,92 +1,66 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
2
|
import { DBManager, DB } from 'universe-code/indexdb';
|
|
3
3
|
|
|
4
|
-
@Injectable({
|
|
5
|
-
|
|
6
|
-
})
|
|
7
|
-
export class idbService {
|
|
8
|
-
private manager = new DBManager('exchange', 1);
|
|
9
|
-
private db!: IDBDatabase;
|
|
10
|
-
private store: {
|
|
11
|
-
get: (key: string) => Promise<any>;
|
|
12
|
-
getWithExpiry: (
|
|
13
|
-
key: string,
|
|
14
|
-
ttl: number,
|
|
15
|
-
api: () => Promise<any>
|
|
16
|
-
) => Promise<any>;
|
|
17
|
-
put: (data: any) => Promise<any>;
|
|
18
|
-
remove: (key: string) => Promise<any>;
|
|
19
|
-
clear: () => Promise<any>;
|
|
20
|
-
} | null = null;
|
|
4
|
+
@Injectable({ providedIn: 'root' })
|
|
5
|
+
export class IdbService {
|
|
21
6
|
|
|
7
|
+
private manager = new DBManager('exchange', 1);
|
|
8
|
+
private db: IDBDatabase | null = null;
|
|
9
|
+
private store: any = null;
|
|
22
10
|
private readonly storeName = 'exchangeStore';
|
|
23
11
|
|
|
24
|
-
/**
|
|
25
|
-
* Initialize DB + Store only once (Singleton)
|
|
26
|
-
*/
|
|
27
12
|
private async getStore() {
|
|
28
13
|
if (!this.store) {
|
|
29
14
|
if (!this.db) {
|
|
30
|
-
this.db = await this.manager.connect([
|
|
31
|
-
{ name: this.storeName }
|
|
32
|
-
]);
|
|
15
|
+
this.db = await this.manager.connect([{ name: this.storeName }]);
|
|
33
16
|
}
|
|
34
17
|
|
|
35
18
|
this.store = {
|
|
36
19
|
get: (key: string) =>
|
|
37
|
-
DB.get(this.db
|
|
20
|
+
DB.get(this.db!, this.storeName, key),
|
|
38
21
|
|
|
39
22
|
getWithExpiry: (
|
|
40
23
|
key: string,
|
|
41
24
|
ttl: number,
|
|
42
25
|
api: () => Promise<any>
|
|
43
26
|
) =>
|
|
44
|
-
DB.getWithExpiry(this.db
|
|
27
|
+
DB.getWithExpiry(this.db!, this.storeName, key, ttl, api),
|
|
45
28
|
|
|
46
29
|
put: (data: any) =>
|
|
47
|
-
DB.put(this.db
|
|
30
|
+
DB.put(this.db!, this.storeName, data),
|
|
48
31
|
|
|
49
32
|
remove: (key: string) =>
|
|
50
|
-
DB.remove(this.db
|
|
33
|
+
DB.remove(this.db!, this.storeName, key),
|
|
51
34
|
|
|
52
35
|
clear: () =>
|
|
53
|
-
DB.clear(this.db
|
|
36
|
+
DB.clear(this.db!, this.storeName)
|
|
54
37
|
};
|
|
55
38
|
}
|
|
56
39
|
|
|
57
40
|
return this.store;
|
|
58
41
|
}
|
|
59
42
|
|
|
60
|
-
/* =======================
|
|
61
|
-
PUBLIC METHODS
|
|
62
|
-
======================= */
|
|
63
|
-
|
|
64
43
|
async fetchWithCache(
|
|
65
44
|
key: string,
|
|
66
45
|
ttl: number,
|
|
67
46
|
apiFn: () => Promise<any>
|
|
68
47
|
) {
|
|
69
|
-
|
|
70
|
-
return store.getWithExpiry(key, ttl, apiFn);
|
|
48
|
+
return (await this.getStore()).getWithExpiry(key, ttl, apiFn);
|
|
71
49
|
}
|
|
72
50
|
|
|
73
51
|
async get(key: string) {
|
|
74
|
-
|
|
75
|
-
return store.get(key);
|
|
52
|
+
return (await this.getStore()).get(key);
|
|
76
53
|
}
|
|
77
54
|
|
|
78
55
|
async set(data: any) {
|
|
79
|
-
|
|
80
|
-
return store.put(data);
|
|
56
|
+
return (await this.getStore()).put(data);
|
|
81
57
|
}
|
|
82
58
|
|
|
83
59
|
async remove(key: string) {
|
|
84
|
-
|
|
85
|
-
return store.remove(key);
|
|
60
|
+
return (await this.getStore()).remove(key);
|
|
86
61
|
}
|
|
87
62
|
|
|
88
63
|
async clear() {
|
|
89
|
-
|
|
90
|
-
return store.clear();
|
|
64
|
+
return (await this.getStore()).clear();
|
|
91
65
|
}
|
|
92
66
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './time.js';
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* @param {number} minutes
|
|
4
4
|
* @returns {number} milliseconds
|
|
5
5
|
*/
|
|
6
|
-
export const minutesToMs = (minutes
|
|
6
|
+
export const minutesToMs = (minutes) => minutes * 60 * 1000;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Converts hours to milliseconds
|
|
10
10
|
* @param {number} hours
|
|
11
11
|
* @returns {number} milliseconds
|
|
12
12
|
*/
|
|
13
|
-
export const hoursToMs = (hours
|
|
13
|
+
export const hoursToMs = (hours) => hours * 60 * 60 * 1000;
|
package/dist/index.js
ADDED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
export class DBManager {
|
|
2
|
-
dbName
|
|
3
|
-
version: any;
|
|
4
|
-
db: any;
|
|
5
|
-
|
|
6
|
-
constructor(dbName: any, version: any = 1) {
|
|
2
|
+
constructor(dbName, version = 1) {
|
|
7
3
|
this.dbName = dbName;
|
|
8
4
|
this.version = version;
|
|
9
5
|
this.db = null;
|
|
10
6
|
}
|
|
11
7
|
|
|
12
|
-
async connect(stores
|
|
8
|
+
async connect(stores = []) {
|
|
13
9
|
if (this.db) return this.db;
|
|
14
10
|
|
|
15
11
|
return new Promise((resolve, reject) => {
|
|
16
|
-
const request
|
|
12
|
+
const request = indexedDB.open(this.dbName, this.version);
|
|
17
13
|
|
|
18
|
-
request.onupgradeneeded = (e
|
|
14
|
+
request.onupgradeneeded = (e) => {
|
|
19
15
|
const db = e.target.result;
|
|
20
|
-
|
|
21
|
-
stores.forEach((store: any) => {
|
|
22
|
-
const name = store.name;
|
|
23
|
-
const keyPath = store.keyPath || "id";
|
|
24
|
-
const autoIncrement = store.autoIncrement || false;
|
|
25
|
-
|
|
16
|
+
stores.forEach(({ name, keyPath = "id", autoIncrement = false }) => {
|
|
26
17
|
if (!db.objectStoreNames.contains(name)) {
|
|
27
18
|
db.createObjectStore(name, { keyPath, autoIncrement });
|
|
28
19
|
}
|
|
@@ -33,8 +24,7 @@ export class DBManager {
|
|
|
33
24
|
this.db = request.result;
|
|
34
25
|
resolve(this.db);
|
|
35
26
|
};
|
|
36
|
-
|
|
37
27
|
request.onerror = () => reject(request.error);
|
|
38
28
|
});
|
|
39
29
|
}
|
|
40
|
-
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic Transaction Wrapper
|
|
3
|
+
*/
|
|
4
|
+
const perform = (db, storeName, mode, action) => {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const tx = db.transaction(storeName, mode);
|
|
7
|
+
const store = tx.objectStore(storeName);
|
|
8
|
+
const request = action(store);
|
|
9
|
+
|
|
10
|
+
request.onsuccess = () => resolve(request.result);
|
|
11
|
+
request.onerror = () => reject(request.error);
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const DB = {
|
|
16
|
+
get: (db, store, key) => perform(db, store, "readonly", s => s.get(key)),
|
|
17
|
+
|
|
18
|
+
put: (db, store, data) => perform(db, store, "readwrite", s => s.put(data)),
|
|
19
|
+
|
|
20
|
+
remove: (db, store, key) => perform(db, store, "readwrite", s => s.delete(key)),
|
|
21
|
+
|
|
22
|
+
clear: (db, store) => perform(db, store, "readwrite", s => s.clear()),
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* PRO FEATURE: getWithExpiry
|
|
26
|
+
* Automatically refreshes data from an API if the local version is too old.
|
|
27
|
+
*/
|
|
28
|
+
async getWithExpiry(db, storeName, key, ttl, apiCall) {
|
|
29
|
+
try {
|
|
30
|
+
const cached = await this.get(db, storeName, key);
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
|
|
33
|
+
// If valid data exists and is NOT expired, return it
|
|
34
|
+
if (cached && cached.timestamp && (now - cached.timestamp < ttl)) {
|
|
35
|
+
return cached.data;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Otherwise, call API
|
|
39
|
+
const freshData = await apiCall();
|
|
40
|
+
|
|
41
|
+
// Save to IndexedDB with new timestamp
|
|
42
|
+
await this.put(db, storeName, {
|
|
43
|
+
id: key,
|
|
44
|
+
data: freshData,
|
|
45
|
+
timestamp: now
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return freshData;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.warn("API/DB Error, returning fallback if available:", error);
|
|
51
|
+
const fallback = await this.get(db, storeName, key);
|
|
52
|
+
return fallback ? fallback.data : null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getIdbStore } from './indexdb/store/idbStore.
|
|
2
|
-
import { useIdbStore } from './indexdb/hooks/idbHook.
|
|
3
|
-
import { configureIdb } from "./indexdb/store/config.
|
|
1
|
+
import { getIdbStore } from './indexdb/store/idbStore.js';
|
|
2
|
+
import { useIdbStore } from './indexdb/hooks/idbHook.js';
|
|
3
|
+
import { configureIdb } from "./indexdb/store/config.js";
|
|
4
4
|
|
|
5
5
|
// Export everything as a unified object or individual pieces
|
|
6
6
|
export { configureIdb, getIdbStore, useIdbStore };
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
let config
|
|
1
|
+
let config = null;
|
|
2
2
|
|
|
3
|
-
export const configureIdb = (options
|
|
3
|
+
export const configureIdb = (options) => {
|
|
4
4
|
if (config) {
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
if (!options) {
|
|
9
|
-
throw new Error("configureIdb requires options");
|
|
10
|
-
}
|
|
11
|
-
|
|
12
7
|
config = options;
|
|
13
8
|
};
|
|
14
9
|
|
|
@@ -18,6 +13,5 @@ export const getConfig = () => {
|
|
|
18
13
|
"IndexedDB not configured. Call configureIdb() before using the store."
|
|
19
14
|
);
|
|
20
15
|
}
|
|
21
|
-
|
|
22
16
|
return config;
|
|
23
17
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DBManager, DB } from "universe-code";
|
|
2
|
+
import { getConfig } from "./config.js";
|
|
3
|
+
|
|
4
|
+
let db = null;
|
|
5
|
+
let store = null;
|
|
6
|
+
let manager = null;
|
|
7
|
+
|
|
8
|
+
// ✅ index db connection
|
|
9
|
+
const connectDB = async () => {
|
|
10
|
+
const { dbName, dbVersion, storeName } = getConfig(); // ✅ FIXED
|
|
11
|
+
|
|
12
|
+
if (!manager) {
|
|
13
|
+
manager = new DBManager(dbName, dbVersion);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!db) {
|
|
17
|
+
db = await manager.connect([{ name: storeName }]); // ✅ FIXED
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return db;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getIdbStore = async () => {
|
|
24
|
+
if (!store) {
|
|
25
|
+
const { storeName } = getConfig(); // ✅ FIXED
|
|
26
|
+
const database = await connectDB();
|
|
27
|
+
|
|
28
|
+
store = {
|
|
29
|
+
get: (key) => DB.get(database, storeName, key),
|
|
30
|
+
getWithExpiry: (key, ttl, api) =>
|
|
31
|
+
DB.getWithExpiry(database, storeName, key, ttl, api),
|
|
32
|
+
put: (data) => DB.put(database, storeName, data),
|
|
33
|
+
remove: (key) => DB.remove(database, storeName, key),
|
|
34
|
+
clear: () => DB.clear(database, storeName),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return store;
|
|
39
|
+
};
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universe-code",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.62",
|
|
4
4
|
"description": "Universal utility functions for all JS frameworks",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./dist/index.
|
|
8
|
-
"module": "./dist/index.
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import": "./dist/indexdb/index.
|
|
12
|
+
"import": "./dist/indexdb/index.js",
|
|
13
13
|
"types": "./dist/index.d.ts"
|
|
14
14
|
},
|
|
15
15
|
"./react": {
|
|
16
|
-
"import": "./dist/react/index.
|
|
16
|
+
"import": "./dist/react/index.js",
|
|
17
17
|
"types": "./dist/index.d.ts"
|
|
18
18
|
},
|
|
19
19
|
"./angular": {
|
|
20
|
-
"import": "./dist/angular/index.
|
|
20
|
+
"import": "./dist/angular/index.js",
|
|
21
21
|
"types": "./dist/index.d.ts"
|
|
22
22
|
},
|
|
23
23
|
"./indexdb": {
|
|
24
|
-
"import": "./dist/indexdb/index.
|
|
24
|
+
"import": "./dist/indexdb/index.js",
|
|
25
25
|
"types": "./dist/index.d.ts"
|
|
26
26
|
},
|
|
27
27
|
"./socket": {
|
|
28
|
-
"import": "./dist/socket/index.
|
|
28
|
+
"import": "./dist/socket/index.js",
|
|
29
29
|
"types": "./dist/index.d.ts"
|
|
30
30
|
},
|
|
31
31
|
"./core": {
|
|
32
|
-
"import": "./dist/core/index.
|
|
32
|
+
"import": "./dist/core/index.js",
|
|
33
33
|
"types": "./dist/index.d.ts"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
@@ -50,8 +50,5 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@angular/core": "^21.0.6",
|
|
52
52
|
"react": "^19.2.3"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@types/react": "^19.2.7"
|
|
56
53
|
}
|
|
57
54
|
}
|
package/dist/angular/index.ts
DELETED
package/dist/core/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './time.ts';
|
package/dist/index.ts
DELETED
package/dist/indexdb/store.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic Transaction Wrapper
|
|
3
|
-
*/
|
|
4
|
-
const perform = (
|
|
5
|
-
db: any,
|
|
6
|
-
storeName: any,
|
|
7
|
-
mode: any,
|
|
8
|
-
action: any
|
|
9
|
-
): Promise<any> => {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
const tx: any = db.transaction(storeName, mode);
|
|
12
|
-
const store: any = tx.objectStore(storeName);
|
|
13
|
-
const request: any = action(store);
|
|
14
|
-
|
|
15
|
-
request.onsuccess = () => resolve(request.result);
|
|
16
|
-
request.onerror = () => reject(request.error);
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const DB: any = {
|
|
21
|
-
get: (db: any, store: any, key: any) =>
|
|
22
|
-
perform(db, store, "readonly", (s: any) => s.get(key)),
|
|
23
|
-
|
|
24
|
-
put: (db: any, store: any, data: any) =>
|
|
25
|
-
perform(db, store, "readwrite", (s: any) => s.put(data)),
|
|
26
|
-
|
|
27
|
-
remove: (db: any, store: any, key: any) =>
|
|
28
|
-
perform(db, store, "readwrite", (s: any) => s.delete(key)),
|
|
29
|
-
|
|
30
|
-
clear: (db: any, store: any) =>
|
|
31
|
-
perform(db, store, "readwrite", (s: any) => s.clear()),
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* PRO FEATURE: getWithExpiry
|
|
35
|
-
* Automatically refreshes data from an API if the local version is too old.
|
|
36
|
-
*/
|
|
37
|
-
async getWithExpiry(
|
|
38
|
-
db: any,
|
|
39
|
-
storeName: any,
|
|
40
|
-
key: any,
|
|
41
|
-
ttl: any,
|
|
42
|
-
apiCall: any
|
|
43
|
-
): Promise<any> {
|
|
44
|
-
try {
|
|
45
|
-
const cached: any = await this.get(db, storeName, key);
|
|
46
|
-
const now: any = Date.now();
|
|
47
|
-
|
|
48
|
-
// If valid data exists and is NOT expired, return it
|
|
49
|
-
if (
|
|
50
|
-
cached &&
|
|
51
|
-
cached.timestamp &&
|
|
52
|
-
now - cached.timestamp < ttl
|
|
53
|
-
) {
|
|
54
|
-
return cached.data;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Otherwise, call API
|
|
58
|
-
const freshData: any = await apiCall();
|
|
59
|
-
|
|
60
|
-
// Save to IndexedDB with new timestamp
|
|
61
|
-
await this.put(db, storeName, {
|
|
62
|
-
id: key,
|
|
63
|
-
data: freshData,
|
|
64
|
-
timestamp: now,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return freshData;
|
|
68
|
-
} catch (error: any) {
|
|
69
|
-
console.warn(
|
|
70
|
-
"API/DB Error, returning fallback if available:",
|
|
71
|
-
error
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const fallback: any = await this.get(db, storeName, key);
|
|
75
|
-
return fallback ? fallback.data : null;
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { DBManager, DB } from "universe-code";
|
|
2
|
-
import { getConfig } from "./config.ts";
|
|
3
|
-
|
|
4
|
-
let db: any = null;
|
|
5
|
-
let store: any = null;
|
|
6
|
-
let manager: any = null;
|
|
7
|
-
|
|
8
|
-
// ✅ index db connection
|
|
9
|
-
const connectDB = async (): Promise<any> => {
|
|
10
|
-
const { dbName, dbVersion, storeName }: any = getConfig();
|
|
11
|
-
|
|
12
|
-
if (!manager) {
|
|
13
|
-
manager = new DBManager(dbName, dbVersion);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (!db) {
|
|
17
|
-
db = await manager.connect([{ name: storeName }]);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return db;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const getIdbStore = async (): Promise<any> => {
|
|
24
|
-
if (!store) {
|
|
25
|
-
const { storeName }: any = getConfig();
|
|
26
|
-
const database: any = await connectDB();
|
|
27
|
-
|
|
28
|
-
store = {
|
|
29
|
-
get: (key: any) => DB.get(database, storeName, key),
|
|
30
|
-
getWithExpiry: (key: any, ttl: any, api: any) =>
|
|
31
|
-
DB.getWithExpiry(database, storeName, key, ttl, api),
|
|
32
|
-
put: (data: any) => DB.put(database, storeName, data),
|
|
33
|
-
remove: (key: any) => DB.remove(database, storeName, key),
|
|
34
|
-
clear: () => DB.clear(database, storeName),
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return store;
|
|
39
|
-
};
|
|
File without changes
|