/
local.ts
83 lines (68 loc) · 2.21 KB
/
local.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
import { PreoccupyAction } from './../actions/base';
import { AbstractTransport, TransportEvents } from './abstract';
import { EventEmitter } from './EventEmitter';
import { Message } from './Message';
export class LocalTransport extends EventEmitter implements AbstractTransport {
private connected: boolean = false;
private publishedMessages: Message[] = [];
private storage: Storage = localStorage;
constructor(private preifx: string = 'prefix', private stackSize: number = 10) {
super();
}
public handshake() {
if (this.connected) {
this.trigger(TransportEvents.connect);
} else {
this.connect();
}
}
public disconnect() {
this.cleanUp();
window.removeEventListener('storage', this);
this.off();
this.connected = false;
}
public publish(action: PreoccupyAction): void {
const message = new Message('action', action);
this.publishedMessages.push(message);
this.storage.setItem(`${this.preifx}|${message.type}|${message.hash}`, message.serialize());
if (this.publishedMessages.length > this.stackSize) {
const messageToDelete = this.publishedMessages.shift();
if (messageToDelete) {
this.storage.removeItem(`${this.preifx}|${messageToDelete.type}|${messageToDelete.hash}`);
}
}
}
public handleEvent(event: Event) {
switch (event.type) {
case 'storage':
this.onStorageMessage(event as StorageEvent);
break;
default:
break;
}
}
private connect() {
window.addEventListener('storage', this);
this.connected = true;
this.trigger(TransportEvents.connect);
}
private cleanUp() {
Object.keys(localStorage).forEach(key => {
if (key.startsWith(this.preifx)) {
localStorage.removeItem(key);
}
});
}
private onStorageMessage({ key, newValue }: StorageEvent) {
if (key && newValue && key.startsWith(this.preifx)) {
const message = Message.parse(key + '|' + newValue);
if (this.isExternalMessage(message)) {
this.trigger(TransportEvents.action, message);
}
}
}
private isExternalMessage(message: Message): boolean {
return !this.publishedMessages.find(ownMessage => ownMessage.hash === message.hash);
}
}