@zcomponent/core 1.27.2 → 1.28.0-beta.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/lib/cache.d.ts +12 -0
- package/lib/cache.js +139 -0
- package/lib/contexts/textalertcontext.d.ts +4 -0
- package/lib/contexts/textalertcontext.js +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +1 -1
package/lib/cache.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CacheOptions {
|
|
2
|
+
key: string;
|
|
3
|
+
expireMS?: number;
|
|
4
|
+
revalidateMS?: number;
|
|
5
|
+
expireError?: number;
|
|
6
|
+
cacheError?: boolean;
|
|
7
|
+
lifetime?: 'pageload' | 'session' | 'persistent';
|
|
8
|
+
}
|
|
9
|
+
export interface CachePerformer<T> extends CacheOptions {
|
|
10
|
+
perform: () => Promise<T>;
|
|
11
|
+
}
|
|
12
|
+
export declare function cache<T>(opts: CachePerformer<T>): Promise<T>;
|
package/lib/cache.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const dbPromise = new Promise((resolve, reject) => {
|
|
2
|
+
const db = indexedDB.open('zee-cache-db');
|
|
3
|
+
db.onupgradeneeded = event => {
|
|
4
|
+
if (!event || !event.target)
|
|
5
|
+
return;
|
|
6
|
+
const db = event.target.result;
|
|
7
|
+
db.createObjectStore('zee-cache', { keyPath: 'key' });
|
|
8
|
+
};
|
|
9
|
+
db.onsuccess = event => {
|
|
10
|
+
if (!event || !event.target)
|
|
11
|
+
return;
|
|
12
|
+
const idb = event.target.result;
|
|
13
|
+
resolve(idb);
|
|
14
|
+
clearExpired();
|
|
15
|
+
};
|
|
16
|
+
db.onerror = event => {
|
|
17
|
+
reject(event);
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
const pageLoadByKey = new Map();
|
|
21
|
+
const inflight = new Map();
|
|
22
|
+
function isError(result) {
|
|
23
|
+
return typeof result['err'] === 'string';
|
|
24
|
+
}
|
|
25
|
+
export async function cache(opts) {
|
|
26
|
+
const lifetime = opts.lifetime ?? 'pageload';
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
let entry;
|
|
29
|
+
if (lifetime === 'pageload') {
|
|
30
|
+
entry = pageLoadByKey.get(opts.key);
|
|
31
|
+
if (entry && entry.expireTime && entry.expireTime < now) {
|
|
32
|
+
pageLoadByKey.delete(opts.key);
|
|
33
|
+
entry = undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (lifetime === 'persistent' || window.sessionStorage.getItem(opts.key) === '1') {
|
|
38
|
+
entry = await getItemFromDB(opts.key);
|
|
39
|
+
if (entry && entry.expireTime && entry.expireTime < now) {
|
|
40
|
+
// Will be deleted next open
|
|
41
|
+
entry = undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const revalidate = entry && opts.revalidateMS && entry.startTime && now - entry.startTime > opts.revalidateMS;
|
|
46
|
+
const revalidateEntry = revalidate ? entry : undefined;
|
|
47
|
+
if (!entry) {
|
|
48
|
+
entry = await inflight.get(opts.key);
|
|
49
|
+
}
|
|
50
|
+
if (!entry || revalidate) {
|
|
51
|
+
const promise = (async () => {
|
|
52
|
+
let ret;
|
|
53
|
+
try {
|
|
54
|
+
const res = await opts.perform();
|
|
55
|
+
ret = {
|
|
56
|
+
key: opts.key,
|
|
57
|
+
expireTime: opts.expireMS ? Date.now() + opts.expireMS : undefined,
|
|
58
|
+
startTime: now,
|
|
59
|
+
result: { val: res },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (!opts.cacheError)
|
|
64
|
+
throw err;
|
|
65
|
+
ret = {
|
|
66
|
+
key: opts.key,
|
|
67
|
+
expireTime: opts.expireError ? Date.now() + opts.expireError : undefined,
|
|
68
|
+
startTime: now,
|
|
69
|
+
result: { err: err instanceof Error ? err.message : typeof err === 'string' ? err : 'Unknown error' },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (lifetime === 'pageload') {
|
|
73
|
+
pageLoadByKey.set(opts.key, ret);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
await addItemToDB(ret);
|
|
77
|
+
if (lifetime === 'session')
|
|
78
|
+
window.sessionStorage.setItem(opts.key, '1');
|
|
79
|
+
}
|
|
80
|
+
return ret;
|
|
81
|
+
})();
|
|
82
|
+
inflight.set(opts.key, promise);
|
|
83
|
+
promise
|
|
84
|
+
.then(() => {
|
|
85
|
+
inflight.delete(opts.key);
|
|
86
|
+
})
|
|
87
|
+
.catch(() => {
|
|
88
|
+
inflight.delete(opts.key);
|
|
89
|
+
});
|
|
90
|
+
if (!revalidate)
|
|
91
|
+
entry = await promise;
|
|
92
|
+
else
|
|
93
|
+
entry = revalidateEntry;
|
|
94
|
+
}
|
|
95
|
+
if (!entry)
|
|
96
|
+
throw new Error('No value');
|
|
97
|
+
if (isError(entry.result))
|
|
98
|
+
throw new Error(entry.result.err);
|
|
99
|
+
return entry.result.val;
|
|
100
|
+
}
|
|
101
|
+
function handleRequest(r) {
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
r.onsuccess = () => {
|
|
104
|
+
resolve(r.result);
|
|
105
|
+
};
|
|
106
|
+
r.onerror = event => {
|
|
107
|
+
reject(event);
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function clearExpired() {
|
|
112
|
+
const db = await dbPromise;
|
|
113
|
+
const os = db.transaction('zee-cache', 'readonly').objectStore('zee-cache');
|
|
114
|
+
const objects = (await handleRequest(os.getAll()));
|
|
115
|
+
const toDelete = new Set();
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
for (const obj of objects) {
|
|
118
|
+
if (obj.expireTime && obj.expireTime < now) {
|
|
119
|
+
toDelete.add(obj.key);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (toDelete.size > 0) {
|
|
123
|
+
const os = db.transaction('zee-cache', 'readwrite').objectStore('zee-cache');
|
|
124
|
+
for (const key of toDelete) {
|
|
125
|
+
os.delete(key);
|
|
126
|
+
}
|
|
127
|
+
os.transaction.commit();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function addItemToDB(e) {
|
|
131
|
+
const db = await dbPromise;
|
|
132
|
+
const os = db.transaction('zee-cache', 'readwrite').objectStore('zee-cache');
|
|
133
|
+
await handleRequest(os.put(e));
|
|
134
|
+
}
|
|
135
|
+
async function getItemFromDB(key) {
|
|
136
|
+
const db = await dbPromise;
|
|
137
|
+
const os = db.transaction('zee-cache', 'readonly').objectStore('zee-cache');
|
|
138
|
+
return await handleRequest(os.get(key));
|
|
139
|
+
}
|
|
@@ -39,7 +39,7 @@ export class TextAlertContext extends Context {
|
|
|
39
39
|
const timeout = options?.timeout ?? 3000;
|
|
40
40
|
setTimeout(() => {
|
|
41
41
|
entry.classList.add('zcomponent-textalert-shown');
|
|
42
|
-
}, 30);
|
|
42
|
+
}, options?.delay ?? 30);
|
|
43
43
|
if (timeout >= 0) {
|
|
44
44
|
setTimeout(() => {
|
|
45
45
|
entry.classList.remove('zcomponent-textalert-shown');
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * from './observable';
|
|
|
16
16
|
export * from './contexts/environmentcontext';
|
|
17
17
|
export * from './contexts/audiocontextcontext';
|
|
18
18
|
export * from './animation';
|
|
19
|
+
export { cache } from './cache';
|
|
19
20
|
const link = document.createElement('link');
|
|
20
21
|
link.setAttribute('rel', 'stylesheet');
|
|
21
22
|
link.setAttribute('href', new URL('../css/zcomponent.css', import.meta.url).toString());
|