135 lines
3.9 KiB
TypeScript
135 lines
3.9 KiB
TypeScript
import { npmUpload, urlUpload, githubUpload, fileUpload } from "./uploaders"
|
|
import { getGlobalDB } from "@budibase/backend-core/tenancy"
|
|
import { validate } from "@budibase/backend-core/plugins"
|
|
import { PluginType, FileType, PluginSource } from "@budibase/types"
|
|
import env from "../../../environment"
|
|
import { ClientAppSocket } from "../../../websocket"
|
|
import { db as dbCore } from "@budibase/backend-core"
|
|
import { plugins } from "@budibase/pro"
|
|
|
|
export async function getPlugins(type?: PluginType) {
|
|
const db = getGlobalDB()
|
|
const response = await db.allDocs(
|
|
dbCore.getPluginParams(null, {
|
|
include_docs: true,
|
|
})
|
|
)
|
|
const plugins = response.rows.map((row: any) => row.doc)
|
|
if (type) {
|
|
return plugins.filter((plugin: any) => plugin.schema?.type === type)
|
|
} else {
|
|
return plugins
|
|
}
|
|
}
|
|
|
|
export async function upload(ctx: any) {
|
|
const plugins: FileType[] =
|
|
ctx.request.files.file.length > 1
|
|
? Array.from(ctx.request.files.file)
|
|
: [ctx.request.files.file]
|
|
try {
|
|
let docs = []
|
|
// can do single or multiple plugins
|
|
for (let plugin of plugins) {
|
|
const doc = await processUploadedPlugin(plugin, PluginSource.FILE)
|
|
docs.push(doc)
|
|
}
|
|
ctx.body = {
|
|
message: "Plugin(s) uploaded successfully",
|
|
plugins: docs,
|
|
}
|
|
} catch (err: any) {
|
|
const errMsg = err?.message ? err?.message : err
|
|
|
|
ctx.throw(400, `Failed to import plugin: ${errMsg}`)
|
|
}
|
|
}
|
|
|
|
export async function create(ctx: any) {
|
|
const { source, url, headers, githubToken } = ctx.request.body
|
|
|
|
try {
|
|
let metadata
|
|
let directory
|
|
// Generating random name as a backup and needed for url
|
|
let name = "PLUGIN_" + Math.floor(100000 + Math.random() * 900000)
|
|
|
|
switch (source) {
|
|
case PluginSource.NPM:
|
|
const { metadata: metadataNpm, directory: directoryNpm } =
|
|
await npmUpload(url, name)
|
|
metadata = metadataNpm
|
|
directory = directoryNpm
|
|
break
|
|
case PluginSource.GITHUB:
|
|
const { metadata: metadataGithub, directory: directoryGithub } =
|
|
await githubUpload(url, name, githubToken)
|
|
metadata = metadataGithub
|
|
directory = directoryGithub
|
|
break
|
|
case PluginSource.URL:
|
|
const headersObj = headers || {}
|
|
const { metadata: metadataUrl, directory: directoryUrl } =
|
|
await urlUpload(url, name, headersObj)
|
|
metadata = metadataUrl
|
|
directory = directoryUrl
|
|
break
|
|
}
|
|
|
|
validate(metadata?.schema)
|
|
|
|
// Only allow components in cloud
|
|
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
|
|
throw new Error(
|
|
"Only component plugins are supported outside of self-host"
|
|
)
|
|
}
|
|
|
|
const doc = await plugins.storePlugin(metadata, directory, source)
|
|
|
|
ClientAppSocket.emit("plugins-update", { name, hash: doc.hash })
|
|
ctx.body = {
|
|
message: "Plugin uploaded successfully",
|
|
plugins: [doc],
|
|
}
|
|
ctx.body = { plugin: doc }
|
|
} catch (err: any) {
|
|
const errMsg = err?.message ? err?.message : err
|
|
|
|
ctx.throw(400, `Failed to import plugin: ${errMsg}`)
|
|
}
|
|
}
|
|
|
|
export async function fetch(ctx: any) {
|
|
ctx.body = await getPlugins()
|
|
}
|
|
|
|
export async function destroy(ctx: any) {
|
|
const { pluginId } = ctx.params
|
|
|
|
try {
|
|
await plugins.deletePlugin(pluginId)
|
|
|
|
ctx.body = { message: `Plugin ${ctx.params.pluginId} deleted.` }
|
|
} catch (err: any) {
|
|
ctx.throw(400, err.message)
|
|
}
|
|
}
|
|
|
|
export async function processUploadedPlugin(
|
|
plugin: FileType,
|
|
source?: PluginSource
|
|
) {
|
|
const { metadata, directory } = await fileUpload(plugin)
|
|
validate(metadata?.schema)
|
|
|
|
// Only allow components in cloud
|
|
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
|
|
throw new Error("Only component plugins are supported outside of self-host")
|
|
}
|
|
|
|
const doc = await plugins.storePlugin(metadata, directory, source)
|
|
ClientAppSocket.emit("plugins-update", { name, hash: doc.hash })
|
|
return doc
|
|
}
|