From a9a4cdbb5c844aa9ce98dbdc5f633f59c20dd8e8 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Thu, 14 Apr 2022 02:12:38 +0300 Subject: [PATCH] add basic frontend modules to access the api --- frontend/src/{ => components}/App.svelte | 0 frontend/src/gateway.js | 63 ++++++++++++++++++++++++ frontend/src/main.js | 2 +- frontend/src/request.js | 41 +++++++++++++++ frontend/src/storage.js | 52 +++++++++++++++++++ 5 files changed, 157 insertions(+), 1 deletion(-) rename frontend/src/{ => components}/App.svelte (100%) create mode 100644 frontend/src/gateway.js create mode 100644 frontend/src/request.js create mode 100644 frontend/src/storage.js diff --git a/frontend/src/App.svelte b/frontend/src/components/App.svelte similarity index 100% rename from frontend/src/App.svelte rename to frontend/src/components/App.svelte diff --git a/frontend/src/gateway.js b/frontend/src/gateway.js new file mode 100644 index 0000000..a247f41 --- /dev/null +++ b/frontend/src/gateway.js @@ -0,0 +1,63 @@ +import { getAuthToken, getItem } from "./storage"; + +export const GatewayPayloadType = { + Hello: 0, + Authenticate: 1, + Ready: 2, + Ping: 3, + + ChannelCreate: 110, + ChannelUpdate: 111, + ChannelDelete: 112, + + MessageCreate: 120, + MessageUpdate: 121, + MessageDelete: 122, +} + +export default { + ws: null, + authenticated: false, + heartbeatInterval: null, + user: null, + channels: null, + init() { + this.ws = new WebSocket(getItem("gatewayBase")); + this.ws.onmessage = (message) => { + const payload = JSON.parse(message); + + switch (payload.t) { + case GatewayPayloadType.Hello: { + this.send({ + t: GatewayPayloadType.Authenticate, + d: getAuthToken() + }); + + this.heartbeatInterval = setInterval(() => { + this.send({ + t: GatewayPayloadType.Ping, + d: 0 + }); + }, payload.d.pingInterval); + break; + } + case GatewayPayloadType.Ready: { + this.user = payload.d.user; + this.channels = payload.d.channels; + break; + } + } + }; + this.ws.onclose = () => { + this.authenticated = false; + this.user = null; + this.channels = null; + if (this.heartbeatInterval) { + clearInterval(this.heartbeatInterval); + } + }; + }, + send(data) { + return this.ws.send(JSON.stringify(data)); + } +}; diff --git a/frontend/src/main.js b/frontend/src/main.js index 4c473fa..2624668 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -1,4 +1,4 @@ -import App from './App.svelte'; +import App from './components/App.svelte'; const app = new App({ target: document.body diff --git a/frontend/src/request.js b/frontend/src/request.js new file mode 100644 index 0000000..4fe2853 --- /dev/null +++ b/frontend/src/request.js @@ -0,0 +1,41 @@ +import { getAuthToken } from "./storage"; + +export default async function(method, endpoint, auth=true, body=null) { + const options = { + method, + }; + + if (body) { + options.headers = { + ...options.headers || {}, + "Content-Type": "application/json" + }; + } + + if (auth) { + const token = getAuthToken(); + if (token) { + options.headers = { + ...options.headers || {}, + "Authorization": `Bearer ${token}` + }; + } + } + + try { + const res = await fetch(endpoint, options); + return { + success: true, + json: await res.json(), + ok: res.ok, + status: res.status + } + } catch (e) { + return { + success: false, + json: null, + ok: res.ok, + status: res.status + } + } +} diff --git a/frontend/src/storage.js b/frontend/src/storage.js new file mode 100644 index 0000000..4e53bf8 --- /dev/null +++ b/frontend/src/storage.js @@ -0,0 +1,52 @@ +const defaults = { + apiBase: `${window.location.origin}/api/v1`, + gatewayBase: `${location.protocol === "https:" ? "wss" : "ws"}://${location.host}/gateway` +}; + +const dummyProvider = { + _store: {}, + getItem(key) { + return this._store[key]; + }, + setItem(key, value) { + this._store[key] = value; + } +}; + +function getProvider() { + if (!window.localStorage || !window.localStorage.getItem || !window.localStorage.setItem) { + return dummyProvider; + } + return window.localStorage; +} + +export function getItem(key) { + return getProvider().getItem(key); +} + +export function setItem(key, value) { + return getProvider().setItem(key, value); +} + +export function getAuthToken() { + return getItem("token"); +} + +export function setAuthToken(value) { + return setItem("token", value); +} + +export function setItemIfNull(key, value) { + const provider = getProvider(); + if (!provider.getItem(key)) { + provider.setItem(key, value); + return true; + } + return false; +} + +export function initStorageDefaults() { + for (const [k, v] of Object.entries(defaults)) { + setItemIfNull(k, v); + } +}