forked from marcj/angular2-localstorage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWebStorage.ts
116 lines (99 loc) · 4.08 KB
/
WebStorage.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import {LocalStorageEmitter} from "./LocalStorageEmitter";
interface IWebStorage {
getItem: (key: string) => string;
setItem: (key: string, value: string) => void;
}
export interface WebStorageOptions {
storageKey?: string,
serialize?: (deserialized: any) => string;
deserialize?: (serialized: string) => any;
}
export function LocalStorage(storageKeyOrOptions: string|WebStorageOptions = {}) {
if ("string" === typeof storageKeyOrOptions) {
return WebStorage(localStorage, {storageKey: storageKeyOrOptions as string});
}
else {
return WebStorage(localStorage, storageKeyOrOptions);
}
}
export function SessionStorage(storageKeyOrOptions: string|WebStorageOptions = {}) {
if ("string" === typeof storageKeyOrOptions) {
return WebStorage(sessionStorage, {storageKey: storageKeyOrOptions as string});
}
else {
return WebStorage(sessionStorage, storageKeyOrOptions);
}
}
function WebStorage(webStorage: IWebStorage, options: WebStorageOptions) {
return (target: Object, decoratedPropertyName?: string): void => {
if (!webStorage) {
return;
}
if (!options.storageKey) {
options.storageKey = "" + "/" + decoratedPropertyName;
}
if (!options.serialize) {
options.serialize = JSON.stringify;
}
if (!options.deserialize) {
options.deserialize = JSON.parse;
}
Object.defineProperty(target, "_" + decoratedPropertyName + "_mapped", {
enumerable: false,
configurable: true,
writable: true,
value: false
});
let instances: any = [];
let values = {};
let storageValue = webStorage.getItem(options.storageKey) || null;
let storageValueJSON = storageValue;
if ("string" === typeof storageValue) {
try {
storageValue = options.deserialize(storageValue);
} catch (e) {
storageValue = null;
storageValueJSON = "null";
}
}
let oldJSONValues = {};
Object.defineProperty(target, decoratedPropertyName, {
get: function () {
if (false === this["_" + decoratedPropertyName + "_mapped"]) {
this["_" + decoratedPropertyName + "_mapped"] = instances.length;
// first registration triggers a setting to localStorage value
values[instances.length] = storageValue;
oldJSONValues[instances.length] = storageValueJSON;
instances.push(this);
}
return values[this["_" + decoratedPropertyName + "_mapped"]];
},
set: function (newValue) {
if (false === this["_" + decoratedPropertyName + "_mapped"]) {
this["_" + decoratedPropertyName + "_mapped"] = instances.length;
// first registration triggers a setting to localStorage value
values[instances.length] = storageValue;
oldJSONValues[instances.length] = storageValueJSON;
instances.push(this);
// first "set" call is ignored if we have already a value from the localStorage
if (storageValue) {
return;
}
}
values[this["_" + decoratedPropertyName + "_mapped"]] = newValue;
},
enumerable: true,
configurable: true
});
LocalStorageEmitter.subscribe(() => {
for (let instance of instances) {
let currentValue = options.serialize(instance[decoratedPropertyName]);
let oldJSONValue = oldJSONValues[instance["_" + decoratedPropertyName + "_mapped"]];
if (currentValue !== oldJSONValue) {
oldJSONValues[instance["_" + decoratedPropertyName + "_mapped"]] = currentValue;
webStorage.setItem(options.storageKey, currentValue);
}
}
});
};
}