Merge pull request #15619 from Budibase/plugin-typing
Improve typing around plugins.
This commit is contained in:
commit
0a8cf31dff
|
@ -1 +1 @@
|
|||
Subproject commit 45f5673d5e5ab3c22deb6663cea2e31a628aa133
|
||||
Subproject commit e3843dd4eaced68ae063355b77df200dbc789c98
|
|
@ -11,6 +11,7 @@ import {
|
|||
UploadPluginResponse,
|
||||
FetchPluginResponse,
|
||||
DeletePluginResponse,
|
||||
PluginMetadata,
|
||||
} from "@budibase/types"
|
||||
import env from "../../../environment"
|
||||
import { clientAppSocket } from "../../../websockets"
|
||||
|
@ -53,10 +54,11 @@ export async function create(
|
|||
const { source, url, headers, githubToken } = ctx.request.body
|
||||
|
||||
try {
|
||||
let metadata
|
||||
let directory
|
||||
let metadata: PluginMetadata
|
||||
let directory: string
|
||||
|
||||
// Generating random name as a backup and needed for url
|
||||
let name = "PLUGIN_" + Math.floor(100000 + Math.random() * 900000)
|
||||
const name = "PLUGIN_" + Math.floor(100000 + Math.random() * 900000)
|
||||
|
||||
switch (source) {
|
||||
case PluginSource.NPM: {
|
||||
|
@ -81,12 +83,14 @@ export async function create(
|
|||
directory = directoryUrl
|
||||
break
|
||||
}
|
||||
default:
|
||||
ctx.throw(400, "Invalid source")
|
||||
}
|
||||
|
||||
pluginCore.validate(metadata?.schema)
|
||||
pluginCore.validate(metadata.schema)
|
||||
|
||||
// Only allow components in cloud
|
||||
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
|
||||
if (!env.SELF_HOSTED && metadata.schema?.type !== PluginType.COMPONENT) {
|
||||
throw new Error(
|
||||
"Only component plugins are supported outside of self-host"
|
||||
)
|
||||
|
|
|
@ -7,7 +7,7 @@ import { default as queries } from "./app/queries"
|
|||
import { default as rows } from "./app/rows"
|
||||
import { default as links } from "./app/links"
|
||||
import { default as users } from "./users"
|
||||
import { default as plugins } from "./plugins"
|
||||
import * as plugins from "./plugins"
|
||||
import * as views from "./app/views"
|
||||
import * as permissions from "./app/permissions"
|
||||
import * as rowActions from "./app/rowActions"
|
||||
|
|
|
@ -1,5 +1,41 @@
|
|||
import * as plugins from "./plugins"
|
||||
import { KoaFile, Plugin, PluginSource, PluginType } from "@budibase/types"
|
||||
import {
|
||||
db as dbCore,
|
||||
objectStore,
|
||||
plugins as pluginCore,
|
||||
tenancy,
|
||||
} from "@budibase/backend-core"
|
||||
import { fileUpload } from "../../api/controllers/plugin/file"
|
||||
import env from "../../environment"
|
||||
import { clientAppSocket } from "../../websockets"
|
||||
import { sdk as pro } from "@budibase/pro"
|
||||
|
||||
export default {
|
||||
...plugins,
|
||||
export async function fetch(type?: PluginType): Promise<Plugin[]> {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
dbCore.getPluginParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
|
||||
plugins = await objectStore.enrichPluginURLs(plugins)
|
||||
if (type) {
|
||||
return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
|
||||
} else {
|
||||
return plugins
|
||||
}
|
||||
}
|
||||
|
||||
export async function processUploaded(plugin: KoaFile, source: PluginSource) {
|
||||
const { metadata, directory } = await fileUpload(plugin)
|
||||
pluginCore.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 pro.plugins.storePlugin(metadata, directory, source)
|
||||
clientAppSocket?.emit("plugin-update", { name: doc.name, hash: doc.hash })
|
||||
return doc
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import { KoaFile, Plugin, PluginSource, PluginType } from "@budibase/types"
|
||||
import {
|
||||
db as dbCore,
|
||||
objectStore,
|
||||
plugins as pluginCore,
|
||||
tenancy,
|
||||
} from "@budibase/backend-core"
|
||||
import { fileUpload } from "../../api/controllers/plugin/file"
|
||||
import env from "../../environment"
|
||||
import { clientAppSocket } from "../../websockets"
|
||||
import { sdk as pro } from "@budibase/pro"
|
||||
|
||||
export async function fetch(type?: PluginType): Promise<Plugin[]> {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
dbCore.getPluginParams(null, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
|
||||
plugins = await objectStore.enrichPluginURLs(plugins)
|
||||
if (type) {
|
||||
return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
|
||||
} else {
|
||||
return plugins
|
||||
}
|
||||
}
|
||||
|
||||
export async function processUploaded(plugin: KoaFile, source?: PluginSource) {
|
||||
const { metadata, directory } = await fileUpload(plugin)
|
||||
pluginCore.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 pro.plugins.storePlugin(metadata, directory, source)
|
||||
clientAppSocket?.emit("plugin-update", { name: doc.name, hash: doc.hash })
|
||||
return doc
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { Plugin } from "@budibase/types"
|
||||
import { Plugin, PluginUpload } from "@budibase/types"
|
||||
import { budibaseTempDir } from "../budibaseDir"
|
||||
import fs from "fs"
|
||||
import { join } from "path"
|
||||
|
@ -8,31 +8,31 @@ import stream from "stream"
|
|||
const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
||||
const AUTOMATION_PATH = join(budibaseTempDir(), "automation")
|
||||
|
||||
export const getPluginMetadata = async (path: string) => {
|
||||
let metadata: any = {}
|
||||
export const getPluginMetadata = async (
|
||||
path: string
|
||||
): Promise<PluginUpload> => {
|
||||
let pkg: any
|
||||
let schema: any
|
||||
try {
|
||||
const pkg = fs.readFileSync(join(path, "package.json"), "utf8")
|
||||
const schema = fs.readFileSync(join(path, "schema.json"), "utf8")
|
||||
|
||||
metadata.schema = JSON.parse(schema)
|
||||
metadata.package = JSON.parse(pkg)
|
||||
|
||||
if (
|
||||
!metadata.package.name ||
|
||||
!metadata.package.version ||
|
||||
!metadata.package.description
|
||||
) {
|
||||
throw new Error(
|
||||
"package.json is missing one of 'name', 'version' or 'description'."
|
||||
)
|
||||
pkg = JSON.parse(fs.readFileSync(join(path, "package.json"), "utf8"))
|
||||
schema = JSON.parse(fs.readFileSync(join(path, "schema.json"), "utf8"))
|
||||
if (!pkg.name) {
|
||||
throw new Error("package.json is missing 'name'.")
|
||||
}
|
||||
if (!pkg.version) {
|
||||
throw new Error("package.json is missing 'version'.")
|
||||
}
|
||||
if (!pkg.description) {
|
||||
throw new Error("package.json is missing 'description'.")
|
||||
}
|
||||
} catch (err: any) {
|
||||
throw new Error(
|
||||
`Unable to process schema.json/package.json in plugin. ${err.message}`
|
||||
`Unable to process schema.json/package.json in plugin. ${err.message}`,
|
||||
{ cause: err }
|
||||
)
|
||||
}
|
||||
|
||||
return { metadata, directory: path }
|
||||
return { metadata: { package: pkg, schema }, directory: path }
|
||||
}
|
||||
|
||||
async function getPluginImpl(path: string, plugin: Plugin) {
|
||||
|
|
|
@ -3,7 +3,8 @@ import env from "./environment"
|
|||
import chokidar from "chokidar"
|
||||
import fs from "fs"
|
||||
import { constants, tenancy } from "@budibase/backend-core"
|
||||
import pluginsSdk from "./sdk/plugins"
|
||||
import { processUploaded } from "./sdk/plugins"
|
||||
import { PluginSource } from "@budibase/types"
|
||||
|
||||
export function watch() {
|
||||
const watchPath = path.join(env.PLUGINS_DIR, "./**/*.tar.gz")
|
||||
|
@ -27,7 +28,7 @@ export function watch() {
|
|||
const split = path.split("/")
|
||||
const name = split[split.length - 1]
|
||||
console.log("Importing plugin:", path)
|
||||
await pluginsSdk.processUploaded({ name, path })
|
||||
await processUploaded({ name, path }, PluginSource.FILE)
|
||||
} catch (err: any) {
|
||||
const message = err?.message ? err?.message : err
|
||||
console.error("Failed to import plugin:", message)
|
||||
|
|
|
@ -24,10 +24,7 @@ export interface Plugin extends Document {
|
|||
source: PluginSource
|
||||
package: { [key: string]: any }
|
||||
hash: string
|
||||
schema: {
|
||||
type: PluginType
|
||||
[key: string]: any
|
||||
}
|
||||
schema: PluginSchema
|
||||
iconFileName?: string
|
||||
// Populated on read
|
||||
jsUrl?: string
|
||||
|
@ -36,3 +33,24 @@ export interface Plugin extends Document {
|
|||
}
|
||||
|
||||
export const PLUGIN_TYPE_ARR = Object.values(PluginType)
|
||||
|
||||
export interface PluginSchema {
|
||||
type: PluginType
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
interface Package {
|
||||
name: string
|
||||
version: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface PluginMetadata {
|
||||
schema: PluginSchema
|
||||
package: Package
|
||||
}
|
||||
|
||||
export interface PluginUpload {
|
||||
metadata: PluginMetadata
|
||||
directory: string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue