mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 22:49:45 +01:00
feat: add sse support
This commit is contained in:
@@ -11,6 +11,8 @@ import Content from "../collections/content";
|
|||||||
import Conflicts from "./sync/conflicts";
|
import Conflicts from "./sync/conflicts";
|
||||||
import EventManager from "../utils/event-manager";
|
import EventManager from "../utils/event-manager";
|
||||||
import Session from "./session";
|
import Session from "./session";
|
||||||
|
import { EventSourcePolyfill } from "event-source-polyfill";
|
||||||
|
import { HOST } from "../utils/constants";
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
constructor(context) {
|
constructor(context) {
|
||||||
@@ -28,6 +30,7 @@ class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
this.ev = new EventManager();
|
||||||
this.session = new Session(this.context);
|
this.session = new Session(this.context);
|
||||||
this._validate();
|
this._validate();
|
||||||
|
|
||||||
@@ -38,7 +41,6 @@ class Database {
|
|||||||
this.vault = new Vault(this);
|
this.vault = new Vault(this);
|
||||||
this.conflicts = new Conflicts(this);
|
this.conflicts = new Conflicts(this);
|
||||||
this.lookup = new Lookup(this);
|
this.lookup = new Lookup(this);
|
||||||
this.ev = new EventManager();
|
|
||||||
|
|
||||||
// collections
|
// collections
|
||||||
/** @type {Notes} */
|
/** @type {Notes} */
|
||||||
@@ -56,10 +58,37 @@ class Database {
|
|||||||
/** @type {Content} */
|
/** @type {Content} */
|
||||||
this.text = await Content.new(this, "text", false);
|
this.text = await Content.new(this, "text", false);
|
||||||
|
|
||||||
if (this._syncInterval) clearInterval(this._syncInterval);
|
this.ev.subscribeMulti(
|
||||||
this._syncInterval = setInterval(async () => {
|
["user:loggedIn", "user:loggedOut", "user:tokenRefreshed", "user:synced"],
|
||||||
this.ev.publish("sync");
|
this._onUserStateChanged.bind(this)
|
||||||
}, 60 * 1000 * 3);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onUserStateChanged(user) {
|
||||||
|
if (this.evtSource) {
|
||||||
|
this.evtSource.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
this.evtSource = new EventSourcePolyfill(`${HOST}/events`, {
|
||||||
|
headers: { Authorization: `Bearer ${user.accessToken}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
this.evtSource.onmessage = async (event) => {
|
||||||
|
const { type, data } = JSON.parse(event.data);
|
||||||
|
switch (type) {
|
||||||
|
case "upgrade":
|
||||||
|
await this.user.set({
|
||||||
|
notesnook: { ...user.notesnook, subscription: data },
|
||||||
|
});
|
||||||
|
this.ev.publish("user:upgraded");
|
||||||
|
break;
|
||||||
|
case "sync":
|
||||||
|
this.ev.publish("db:sync");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sync() {
|
sync() {
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ export default class User {
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
user = await authRequest.call(this, "users", undefined, true, true);
|
user = await authRequest.call(this, "users", undefined, true, true);
|
||||||
await this.set(user);
|
await this.set(user);
|
||||||
|
|
||||||
|
// propogate event
|
||||||
|
this._db.ev.publish("user:synced", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
@@ -43,6 +46,9 @@ export default class User {
|
|||||||
const key = await this._context.deriveKey(password, response.payload.salt);
|
const key = await this._context.deriveKey(password, response.payload.salt);
|
||||||
let user = userFromResponse(response, key);
|
let user = userFromResponse(response, key);
|
||||||
await this._context.write("user", user);
|
await this._context.write("user", user);
|
||||||
|
|
||||||
|
// propogate event
|
||||||
|
this._db.ev.publish("user:loggedIn", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
async token() {
|
async token() {
|
||||||
@@ -67,10 +73,17 @@ export default class User {
|
|||||||
expiry: Date.now() + response.expiry * 100,
|
expiry: Date.now() + response.expiry * 100,
|
||||||
};
|
};
|
||||||
await this._context.write("user", user);
|
await this._context.write("user", user);
|
||||||
|
|
||||||
|
// propogate event
|
||||||
|
this._db.ev.publish("user:tokenRefreshed", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
this._db.ev.publish("clear");
|
this._db.ev.publish("clear");
|
||||||
|
|
||||||
|
// propogate event
|
||||||
|
this._db.ev.publish("user:loggedOut", null);
|
||||||
|
|
||||||
return this._context.clear();
|
return this._context.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +97,9 @@ export default class User {
|
|||||||
const key = await this._context.deriveKey(password, response.payload.salt);
|
const key = await this._context.deriveKey(password, response.payload.salt);
|
||||||
let user = userFromResponse(response, key);
|
let user = userFromResponse(response, key);
|
||||||
await this._context.write("user", user);
|
await this._context.write("user", user);
|
||||||
|
|
||||||
|
// propogate event
|
||||||
|
this._db.ev.publish("user:loggedIn", user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"fuzzysearch": "^1.0.3",
|
"fuzzysearch": "^1.0.3",
|
||||||
"no-internet": "^1.5.2",
|
"no-internet": "^1.5.2",
|
||||||
"qclone": "^1.0.4",
|
"qclone": "^1.0.4",
|
||||||
|
"event-source-polyfill": "^1.0.16",
|
||||||
"transfun": "^1.0.2"
|
"transfun": "^1.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,12 @@ class EventManager {
|
|||||||
this._registry = {};
|
this._registry = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscribeMulti(names, handler) {
|
||||||
|
names.forEach((name) => {
|
||||||
|
this.subscribe(name, handler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
subscribe(name, handler) {
|
subscribe(name, handler) {
|
||||||
if (!name || !handler) throw new Error("name and handler are required.");
|
if (!name || !handler) throw new Error("name and handler are required.");
|
||||||
if (!this._registry[name]) this._registry[name] = [];
|
if (!this._registry[name]) this._registry[name] = [];
|
||||||
|
|||||||
@@ -2327,6 +2327,11 @@ esutils@^2.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||||
|
|
||||||
|
event-source-polyfill@^1.0.16:
|
||||||
|
version "1.0.17"
|
||||||
|
resolved "https://registry.yarnpkg.com/event-source-polyfill/-/event-source-polyfill-1.0.17.tgz#850a5103c8fbc5c2c0640ca8e545224e3be9614d"
|
||||||
|
integrity sha512-eLZQQpKZahOH5sFaqfrbLNXJKz+JawiDQVrl6lZmQHHSamIn5PlNV3HXAY9+ZRaQC5YTIBRDd8jeTxjuEveJnQ==
|
||||||
|
|
||||||
exec-sh@^0.3.2:
|
exec-sh@^0.3.2:
|
||||||
version "0.3.4"
|
version "0.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
|
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
|
||||||
|
|||||||
Reference in New Issue
Block a user