Initial work on websockets

This commit is contained in:
Andrew Kingston 2022-08-19 11:09:20 +01:00
parent 2d5d22c914
commit 2c87d6e340
15 changed files with 2129 additions and 33 deletions

View File

@ -77,9 +77,19 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} }
location /ws { location /vite/ {
proxy_pass http://{{ address }}:3000; proxy_pass http://{{ address }}:3000;
rewrite ^/ws(.*)$ /$1 break; rewrite ^/vite(.*)$ /$1 break;
}
location /socket/ {
proxy_pass http://{{ address }}:4001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
} }
location / { location / {

View File

@ -93,6 +93,7 @@
: [], : [],
isBudibaseEvent: true, isBudibaseEvent: true,
usedPlugins: $store.usedPlugins, usedPlugins: $store.usedPlugins,
location: window.location,
} }
// Refresh the preview when required // Refresh the preview when required

View File

@ -68,6 +68,7 @@ export default `
navigation, navigation,
hiddenComponentIds, hiddenComponentIds,
usedPlugins, usedPlugins,
location
} = parsed } = parsed
// Set some flags so the app knows we're in the builder // Set some flags so the app knows we're in the builder
@ -83,6 +84,7 @@ export default `
window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
window["##BUDIBASE_USED_PLUGINS##"] = usedPlugins window["##BUDIBASE_USED_PLUGINS##"] = usedPlugins
window["##BUDIBASE_LOCATION##"] = location
// Initialise app // Initialise app
try { try {

View File

@ -39,6 +39,7 @@
"sanitize-html": "^2.7.0", "sanitize-html": "^2.7.0",
"screenfull": "^6.0.1", "screenfull": "^6.0.1",
"shortid": "^2.2.15", "shortid": "^2.2.15",
"socket.io-client": "^4.5.1",
"svelte": "^3.49.0", "svelte": "^3.49.0",
"svelte-apexcharts": "^1.0.2", "svelte-apexcharts": "^1.0.2",
"svelte-flatpickr": "^3.1.0", "svelte-flatpickr": "^3.1.0",

View File

@ -91,8 +91,8 @@
<svelte:head> <svelte:head>
{#if $builderStore.usedPlugins?.length} {#if $builderStore.usedPlugins?.length}
{#each $builderStore.usedPlugins as plugin} {#each $builderStore.usedPlugins as plugin (plugin.hash)}
<script src={`/plugins/${plugin.jsUrl}`}></script> <script src={`/plugins/${plugin.jsUrl}?r=${plugin.hash || ""}`}></script>
{/each} {/each}
{/if} {/if}
</svelte:head> </svelte:head>

View File

@ -2,6 +2,7 @@ import ClientApp from "./components/ClientApp.svelte"
import { componentStore, builderStore, appStore, devToolsStore } from "./stores" import { componentStore, builderStore, appStore, devToolsStore } from "./stores"
import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js" import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js"
import { get } from "svelte/store" import { get } from "svelte/store"
import { initWebsocket } from "./websocket.js"
// Provide svelte and svelte/internal as globals for custom components // Provide svelte and svelte/internal as globals for custom components
import * as svelte from "svelte" import * as svelte from "svelte"
@ -28,6 +29,7 @@ const loadBudibase = () => {
navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"],
hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"],
usedPlugins: window["##BUDIBASE_USED_PLUGINS##"], usedPlugins: window["##BUDIBASE_USED_PLUGINS##"],
location: window["##BUDIBASE_LOCATION##"],
}) })
// Set app ID - this window flag is set by both the preview and the real // Set app ID - this window flag is set by both the preview and the real
@ -51,6 +53,9 @@ const loadBudibase = () => {
window.registerCustomComponent = window.registerCustomComponent =
componentStore.actions.registerCustomComponent componentStore.actions.registerCustomComponent
// Initialise websocket
initWebsocket()
// Create app if one hasn't been created yet // Create app if one hasn't been created yet
if (!app) { if (!app) {
app = new ClientApp({ app = new ClientApp({

View File

@ -19,6 +19,7 @@ const createBuilderStore = () => {
isDragging: false, isDragging: false,
navigation: null, navigation: null,
hiddenComponentIds: [], hiddenComponentIds: [],
usedPlugins: null,
// Legacy - allow the builder to specify a layout // Legacy - allow the builder to specify a layout
layout: null, layout: null,
@ -84,6 +85,20 @@ const createBuilderStore = () => {
highlightSetting: setting => { highlightSetting: setting => {
dispatchEvent("highlight-setting", { setting }) dispatchEvent("highlight-setting", { setting })
}, },
updateUsedPlugin: (name, hash) => {
// Check if we used this plugin
const used = get(store)?.usedPlugins?.find(x => x.name === name)
if (used) {
store.update(state => {
state.usedPlugins = state.usedPlugins.filter(x => x.name !== name)
state.usedPlugins.push({
...used,
hash,
})
return state
})
}
},
} }
return { return {
...store, ...store,

View File

@ -140,16 +140,20 @@ const createComponentStore = () => {
return customComponentManifest?.[type]?.Component return customComponentManifest?.[type]?.Component
} }
const registerCustomComponent = ({ Component, schema, version }) => { const registerCustomComponent = ({ Component, schema }) => {
if (!Component || !schema?.schema?.name) { if (!Component || !schema?.schema?.name) {
return return
} }
const component = `plugin/${schema.schema.name}/${version}` console.log(schema)
console.log("register", schema.schema.name)
const component = `plugin/${schema.schema.name}/${
schema.schema.version || "2.0.5"
}`
console.log(component)
store.update(state => { store.update(state => {
state.customComponentManifest[component] = { state.customComponentManifest[component] = {
Component, Component,
schema, schema,
version,
} }
return state return state
}) })

View File

@ -0,0 +1,24 @@
import { builderStore } from "./stores/index.js"
import { get } from "svelte/store"
import { io } from "socket.io-client"
export const initWebsocket = () => {
const { inBuilder, location } = get(builderStore)
console.log(location)
if (!inBuilder || !location) {
return
}
// Websocket
const tls = location.protocol === "https:"
const proto = tls ? "wss:" : "ws:"
const host = location.hostname
const port = location.port || (tls ? 433 : 80)
console.log(`${proto}//${host}:${port}`)
const socket = io(`${proto}//${host}:${port}`, {
path: "/socket/",
})
socket.on("plugin-update", data => {
builderStore.actions.updateUsedPlugin(data.name, data.hash)
})
}

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,7 @@
"redis": "4", "redis": "4",
"server-destroy": "1.0.1", "server-destroy": "1.0.1",
"snowflake-promise": "^4.5.0", "snowflake-promise": "^4.5.0",
"socket.io": "^4.5.1",
"svelte": "3.49.0", "svelte": "3.49.0",
"swagger-parser": "10.0.3", "swagger-parser": "10.0.3",
"tar": "^6.1.11", "tar": "^6.1.11",

View File

@ -4,6 +4,7 @@ import { getGlobalDB } from "@budibase/backend-core/tenancy"
import { generatePluginID, getPluginParams } from "../../db/utils" import { generatePluginID, getPluginParams } from "../../db/utils"
import { uploadDirectory } from "@budibase/backend-core/objectStore" import { uploadDirectory } from "@budibase/backend-core/objectStore"
import { PluginType, FileType } from "@budibase/types" import { PluginType, FileType } from "@budibase/types"
import { io } from "../../app"
export async function getPlugins(type?: PluginType) { export async function getPlugins(type?: PluginType) {
const db = getGlobalDB() const db = getGlobalDB()
@ -53,7 +54,8 @@ export async function processPlugin(plugin: FileType) {
const { metadata, directory } = await extractPluginTarball(plugin) const { metadata, directory } = await extractPluginTarball(plugin)
const version = metadata.package.version, const version = metadata.package.version,
name = metadata.package.name, name = metadata.package.name,
description = metadata.package.description description = metadata.package.description,
hash = metadata.schema.hash
// first open the tarball into tmp directory // first open the tarball into tmp directory
const bucketPath = `${name}/${version}/` const bucketPath = `${name}/${version}/`
@ -82,11 +84,13 @@ export async function processPlugin(plugin: FileType) {
_rev: rev, _rev: rev,
name, name,
version, version,
hash,
description, description,
...metadata, ...metadata,
jsUrl: `${bucketPath}${jsFileName}`, jsUrl: `${bucketPath}${jsFileName}`,
} }
const response = await db.put(doc) const response = await db.put(doc)
io.sockets.emit("plugin-update", { name, hash })
return { return {
...doc, ...doc,
_rev: response.rev, _rev: response.rev,

View File

@ -20,6 +20,7 @@ const { Thread } = require("./threads")
const chokidar = require("chokidar") const chokidar = require("chokidar")
const fs = require("fs") const fs = require("fs")
const path = require("path") const path = require("path")
const SocketIO = require("socket.io")
import redis from "./utilities/redis" import redis from "./utilities/redis"
import * as migrations from "./migrations" import * as migrations from "./migrations"
import { events, installation, tenancy } from "@budibase/backend-core" import { events, installation, tenancy } from "@budibase/backend-core"
@ -71,6 +72,15 @@ if (env.isProd()) {
const server = http.createServer(app.callback()) const server = http.createServer(app.callback())
destroyable(server) destroyable(server)
// Websocket
export const io = SocketIO(server, {
path: "/socket/",
cors: {
origin: ["https://hmr.lan.kingston.dev"],
methods: ["GET", "POST"],
},
})
let shuttingDown = false, let shuttingDown = false,
errCode = 0 errCode = 0
server.on("close", async () => { server.on("close", async () => {

View File

@ -0,0 +1,9 @@
const { Server } = require("socket.io")
const io = new Server(4000)
io.on("connection", socket => {
socket.on("foo", arg => {
console.log(arg)
})
})

File diff suppressed because it is too large Load Diff