Merge branch 'master' of github.com:Budibase/budibase into fix/group-ui-issues
This commit is contained in:
commit
a5b1213fc5
|
@ -1 +1 @@
|
||||||
Subproject commit 45f5673d5e5ab3c22deb6663cea2e31a628aa133
|
Subproject commit e3843dd4eaced68ae063355b77df200dbc789c98
|
|
@ -11,6 +11,7 @@ import {
|
||||||
UploadPluginResponse,
|
UploadPluginResponse,
|
||||||
FetchPluginResponse,
|
FetchPluginResponse,
|
||||||
DeletePluginResponse,
|
DeletePluginResponse,
|
||||||
|
PluginMetadata,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { clientAppSocket } from "../../../websockets"
|
import { clientAppSocket } from "../../../websockets"
|
||||||
|
@ -53,10 +54,11 @@ export async function create(
|
||||||
const { source, url, headers, githubToken } = ctx.request.body
|
const { source, url, headers, githubToken } = ctx.request.body
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let metadata
|
let metadata: PluginMetadata
|
||||||
let directory
|
let directory: string
|
||||||
|
|
||||||
// Generating random name as a backup and needed for url
|
// 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) {
|
switch (source) {
|
||||||
case PluginSource.NPM: {
|
case PluginSource.NPM: {
|
||||||
|
@ -81,12 +83,14 @@ export async function create(
|
||||||
directory = directoryUrl
|
directory = directoryUrl
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
ctx.throw(400, "Invalid source")
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginCore.validate(metadata?.schema)
|
pluginCore.validate(metadata.schema)
|
||||||
|
|
||||||
// Only allow components in cloud
|
// 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(
|
throw new Error(
|
||||||
"Only component plugins are supported outside of self-host"
|
"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 rows } from "./app/rows"
|
||||||
import { default as links } from "./app/links"
|
import { default as links } from "./app/links"
|
||||||
import { default as users } from "./users"
|
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 views from "./app/views"
|
||||||
import * as permissions from "./app/permissions"
|
import * as permissions from "./app/permissions"
|
||||||
import * as rowActions from "./app/rowActions"
|
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 {
|
export async function fetch(type?: PluginType): Promise<Plugin[]> {
|
||||||
...plugins,
|
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 { budibaseTempDir } from "../budibaseDir"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
|
@ -8,31 +8,31 @@ import stream from "stream"
|
||||||
const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
||||||
const AUTOMATION_PATH = join(budibaseTempDir(), "automation")
|
const AUTOMATION_PATH = join(budibaseTempDir(), "automation")
|
||||||
|
|
||||||
export const getPluginMetadata = async (path: string) => {
|
export const getPluginMetadata = async (
|
||||||
let metadata: any = {}
|
path: string
|
||||||
|
): Promise<PluginUpload> => {
|
||||||
|
let pkg: any
|
||||||
|
let schema: any
|
||||||
try {
|
try {
|
||||||
const pkg = fs.readFileSync(join(path, "package.json"), "utf8")
|
pkg = JSON.parse(fs.readFileSync(join(path, "package.json"), "utf8"))
|
||||||
const schema = fs.readFileSync(join(path, "schema.json"), "utf8")
|
schema = JSON.parse(fs.readFileSync(join(path, "schema.json"), "utf8"))
|
||||||
|
if (!pkg.name) {
|
||||||
metadata.schema = JSON.parse(schema)
|
throw new Error("package.json is missing 'name'.")
|
||||||
metadata.package = JSON.parse(pkg)
|
}
|
||||||
|
if (!pkg.version) {
|
||||||
if (
|
throw new Error("package.json is missing 'version'.")
|
||||||
!metadata.package.name ||
|
}
|
||||||
!metadata.package.version ||
|
if (!pkg.description) {
|
||||||
!metadata.package.description
|
throw new Error("package.json is missing 'description'.")
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
"package.json is missing one of 'name', 'version' or 'description'."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(
|
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) {
|
async function getPluginImpl(path: string, plugin: Plugin) {
|
||||||
|
|
|
@ -3,7 +3,8 @@ import env from "./environment"
|
||||||
import chokidar from "chokidar"
|
import chokidar from "chokidar"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { constants, tenancy } from "@budibase/backend-core"
|
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() {
|
export function watch() {
|
||||||
const watchPath = path.join(env.PLUGINS_DIR, "./**/*.tar.gz")
|
const watchPath = path.join(env.PLUGINS_DIR, "./**/*.tar.gz")
|
||||||
|
@ -27,7 +28,7 @@ export function watch() {
|
||||||
const split = path.split("/")
|
const split = path.split("/")
|
||||||
const name = split[split.length - 1]
|
const name = split[split.length - 1]
|
||||||
console.log("Importing plugin:", path)
|
console.log("Importing plugin:", path)
|
||||||
await pluginsSdk.processUploaded({ name, path })
|
await processUploaded({ name, path }, PluginSource.FILE)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const message = err?.message ? err?.message : err
|
const message = err?.message ? err?.message : err
|
||||||
console.error("Failed to import plugin:", message)
|
console.error("Failed to import plugin:", message)
|
||||||
|
|
|
@ -24,10 +24,7 @@ export interface Plugin extends Document {
|
||||||
source: PluginSource
|
source: PluginSource
|
||||||
package: { [key: string]: any }
|
package: { [key: string]: any }
|
||||||
hash: string
|
hash: string
|
||||||
schema: {
|
schema: PluginSchema
|
||||||
type: PluginType
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
iconFileName?: string
|
iconFileName?: string
|
||||||
// Populated on read
|
// Populated on read
|
||||||
jsUrl?: string
|
jsUrl?: string
|
||||||
|
@ -36,3 +33,24 @@ export interface Plugin extends Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PLUGIN_TYPE_ARR = Object.values(PluginType)
|
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