Skip to content

Commit d103bf5

Browse files
Ondřej Bašemjancarik
Ondřej Baše
authored andcommitted
feat: 🎸 Add maxAge option to saved items (expiration)
1 parent 3e88b57 commit d103bf5

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

Diff for: packages/plugin-session-storage/src/__tests__/indexSpec.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ describe('Session Storage plugin', () => {
3838
if ('sessionStorage' in widget.$dependencies) {
3939
widget.$dependencies.sessionStorage = sessionStorage;
4040
}
41+
42+
jest.useFakeTimers();
4143
});
4244

4345
afterEach(() => {
4446
sessionStorage.clear();
47+
jest.useRealTimers();
4548
});
4649

4750
it('should create empty widget', async () => {
@@ -128,7 +131,7 @@ describe('Session Storage plugin', () => {
128131
expect(session.get('item5')).toStrictEqual(arr);
129132
});
130133

131-
it('should should have (not) an item', () => {
134+
it('should have (not) an item', () => {
132135
expect(session.get('item1')).toBeUndefined();
133136

134137
session.set('item1', 1);
@@ -186,4 +189,35 @@ describe('Session Storage plugin', () => {
186189
expect(returnValue).toBeFalsy();
187190
expect(console.error).toHaveBeenCalledTimes(1);
188191
});
192+
193+
it('should delete an item after maxAge', () => {
194+
const maxAge = 60;
195+
const value = 1;
196+
session.set('item1', value, { maxAge });
197+
198+
jest.advanceTimersByTime(maxAge * 1000);
199+
expect(session.get('item1')).toBe(value);
200+
201+
jest.advanceTimersByTime(1);
202+
expect(session.get('item1')).toBeUndefined();
203+
});
204+
205+
it.each([-1, 0])('should not not set an item when maxAge is %p', (maxAge) => {
206+
expect(session.get('item1')).toBeUndefined();
207+
208+
session.set('item1', 1, { maxAge });
209+
210+
expect(session.get('item1')).toBeUndefined();
211+
});
212+
213+
it.each([-1, 0])('should delete an item when maxAge is %p', (maxAge) => {
214+
const value = 1;
215+
session.set('item1', value);
216+
217+
expect(session.get('item1')).toBe(value);
218+
219+
session.set('item1', value, { maxAge });
220+
221+
expect(session.get('item1')).toBeUndefined();
222+
});
189223
});

Diff for: packages/plugin-session-storage/src/index.js

+41-8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ function sessionStorageAPI() {
5353
try {
5454
const item = JSON.parse(sessionStorage.getItem(keyPrefix + key));
5555

56+
if (shouldDeleteItem(item)) {
57+
widget.sessionStorage.delete(key);
58+
59+
return undefined;
60+
}
61+
5662
return item && typeof item === 'object' ? item.value : undefined;
5763
} catch (error) {
5864
throw new Error(
@@ -68,10 +74,13 @@ function sessionStorageAPI() {
6874
* @param {object} widget A widget object.
6975
* @param {string} key A key
7076
* @param {*} value A value
77+
* @param {object} [options] An options object.
78+
* @param {number} [options.maxAge] Number of seconds after which the
79+
* value should be removed.
7180
* @return {boolean} It's `true` when the operation was successful,
7281
* otherwise `false`.
7382
*/
74-
set(widget, key, value) {
83+
set(widget, key, value, options) {
7584
const {
7685
$dependencies: { sessionStorage },
7786
$in: {
@@ -83,14 +92,23 @@ function sessionStorageAPI() {
8392
return false;
8493
}
8594

95+
const item = {
96+
created: Date.now(),
97+
value,
98+
};
99+
100+
if (Number.isFinite(Number.parseInt(options?.maxAge))) {
101+
item.maxAge = Number.parseInt(options.maxAge);
102+
}
103+
104+
if (shouldDeleteItem(item)) {
105+
widget.sessionStorage.delete(key);
106+
107+
return true;
108+
}
109+
86110
try {
87-
sessionStorage.setItem(
88-
keyPrefix + key,
89-
JSON.stringify({
90-
created: Date.now(),
91-
value,
92-
}),
93-
);
111+
sessionStorage.setItem(keyPrefix + key, JSON.stringify(item));
94112
} catch (error) {
95113
console.error(error);
96114

@@ -123,3 +141,18 @@ function sessionStorageAPI() {
123141
function getNativeSessionStorage() {
124142
return typeof window === 'undefined' ? undefined : window.sessionStorage;
125143
}
144+
145+
function shouldDeleteItem(item) {
146+
if (!item || !('maxAge' in item) || !item.created) {
147+
return false;
148+
}
149+
150+
if (item.maxAge <= 0) {
151+
return true;
152+
}
153+
154+
const now = Date.now();
155+
const age = now - item.created;
156+
157+
return age > item.maxAge * 1000;
158+
}

0 commit comments

Comments
 (0)