Skip to content

Commit e781aa1

Browse files
committed
Added BrowserStorage
1 parent 7c78a70 commit e781aa1

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

src/storage/BrowserStorage.ts

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { IStorage } from './IStorage';
2+
import { IStorageItem } from './IStorageItem';
3+
4+
interface IndexEntry {
5+
name: string;
6+
timestamp: number;
7+
}
8+
9+
export class BrowserStorage implements IStorage {
10+
private prefix: string;
11+
private maxItems: number;
12+
private timestamp: number;
13+
private index: IndexEntry[];
14+
15+
static isAvailable(): boolean {
16+
try {
17+
let storage = window.localStorage,
18+
x = '__storage_test__';
19+
storage.setItem(x, x);
20+
storage.removeItem(x);
21+
return true;
22+
} catch (e) {
23+
return false;
24+
}
25+
}
26+
27+
constructor(prefix: string = 'com.exceptionless.', maxItems: number = 20, fs?: any) {
28+
this.prefix = prefix;
29+
this.maxItems = maxItems;
30+
31+
this.index = this.createIndex();
32+
this.timestamp = this.index.length > 0
33+
? this.index[this.index.length - 1].timestamp
34+
: 0;
35+
}
36+
37+
save(path: string, value: any): boolean {
38+
if (!path || !value) {
39+
return false;
40+
}
41+
42+
this.remove(path);
43+
let entry = { name: path, timestamp: ++this.timestamp };
44+
this.index.push(entry);
45+
let fullPath = this.getFullPath(entry);
46+
let json = JSON.stringify(value);
47+
window.localStorage.setItem(fullPath, json);
48+
49+
return true;
50+
}
51+
52+
get(path: string): any {
53+
try {
54+
let entry = this.findEntry(path);
55+
if (!entry) {
56+
return null;
57+
}
58+
59+
let fullPath = this.getFullPath(entry);
60+
let json = window.localStorage.getItem(fullPath);
61+
return JSON.parse(json, parseDate);
62+
} catch (e) {
63+
return null;
64+
}
65+
}
66+
67+
getList(searchPattern?: string, limit?: number): IStorageItem[] {
68+
let entries = this.index;
69+
70+
if (searchPattern) {
71+
let regex = new RegExp(searchPattern);
72+
entries = entries.filter(entry => regex.test(entry.name));
73+
}
74+
75+
if (entries.length > this.maxItems) {
76+
entries = entries.slice(entries.length - this.maxItems);
77+
}
78+
79+
if (entries.length > limit) {
80+
entries = entries.slice(0, limit);
81+
}
82+
83+
let items = entries.map(e => this.loadEntry(e));
84+
return items;
85+
}
86+
87+
remove(path: string): void {
88+
try {
89+
let entry = this.findEntry(path);
90+
if (!entry) {
91+
return null;
92+
}
93+
94+
let fullPath = this.getFullPath(entry);
95+
window.localStorage.removeItem(fullPath);
96+
this.removeEntry(entry);
97+
} catch (e) { }
98+
}
99+
100+
private loadEntry(entry: IndexEntry) {
101+
let fullPath = this.getFullPath(entry);
102+
let created = Date.now();
103+
let json = window.localStorage.getItem(fullPath);
104+
let value = JSON.parse(json, parseDate);
105+
return {
106+
created: created,
107+
path: entry.name,
108+
value
109+
};
110+
}
111+
112+
private findEntry(path: string) {
113+
for (let i = this.index.length - 1; i >= 0; i--) {
114+
if (this.index[i].name === path) {
115+
return this.index[i];
116+
}
117+
}
118+
return null;
119+
}
120+
121+
private removeEntry(entry: IndexEntry) {
122+
let i = this.index.indexOf(entry);
123+
if (i > -1) {
124+
this.index.splice(i, 1);
125+
}
126+
}
127+
128+
private getFullPath(entry: IndexEntry) {
129+
let filename = this.prefix + entry.name + '__' + entry.timestamp;
130+
return filename;
131+
}
132+
133+
private createIndex() {
134+
let regex = new RegExp('^' + regExEscape(this.prefix));
135+
let files = Object.keys(window.localStorage)
136+
.filter(f => regex.test(f))
137+
.map(f => f.substr(this.prefix.length));
138+
return files
139+
.map(file => {
140+
let parts = file.split('__');
141+
return {
142+
name: parts[0],
143+
timestamp: parseInt(parts[1], 10)
144+
};
145+
}).sort((a, b) => a.timestamp - b.timestamp);
146+
}
147+
}
148+
149+
function regExEscape(value) {
150+
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
151+
}
152+
153+
function parseDate(key, value) {
154+
let dateRegx = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/g;
155+
if (typeof value === 'string') {
156+
let a = dateRegx.exec(value);
157+
if (a) {
158+
return new Date(value);
159+
}
160+
}
161+
return value;
162+
};

0 commit comments

Comments
 (0)