Merge branch 'master' of github.com:budibase/budibase into budi-8882-ms-sql-export-schema-feature-creates-and-downloads
This commit is contained in:
commit
0e6b3c258a
|
@ -2,6 +2,8 @@ import {
|
|||
PermissionLevel,
|
||||
PermissionType,
|
||||
BuiltinPermissionID,
|
||||
Permission,
|
||||
BuiltinPermissions,
|
||||
} from "@budibase/types"
|
||||
import flatten from "lodash/flatten"
|
||||
import cloneDeep from "lodash/fp/cloneDeep"
|
||||
|
@ -12,7 +14,7 @@ export type RoleHierarchy = {
|
|||
permissionId: string
|
||||
}[]
|
||||
|
||||
export class Permission {
|
||||
export class PermissionImpl implements Permission {
|
||||
type: PermissionType
|
||||
level: PermissionLevel
|
||||
|
||||
|
@ -61,68 +63,62 @@ export function getAllowedLevels(userPermLevel: PermissionLevel): string[] {
|
|||
}
|
||||
}
|
||||
|
||||
export const BUILTIN_PERMISSIONS: {
|
||||
[key in keyof typeof BuiltinPermissionID]: {
|
||||
_id: (typeof BuiltinPermissionID)[key]
|
||||
name: string
|
||||
permissions: Permission[]
|
||||
}
|
||||
} = {
|
||||
export const BUILTIN_PERMISSIONS: BuiltinPermissions = {
|
||||
PUBLIC: {
|
||||
_id: BuiltinPermissionID.PUBLIC,
|
||||
name: "Public",
|
||||
permissions: [
|
||||
new Permission(PermissionType.WEBHOOK, PermissionLevel.EXECUTE),
|
||||
new PermissionImpl(PermissionType.WEBHOOK, PermissionLevel.EXECUTE),
|
||||
],
|
||||
},
|
||||
READ_ONLY: {
|
||||
_id: BuiltinPermissionID.READ_ONLY,
|
||||
name: "Read only",
|
||||
permissions: [
|
||||
new Permission(PermissionType.QUERY, PermissionLevel.READ),
|
||||
new Permission(PermissionType.TABLE, PermissionLevel.READ),
|
||||
new Permission(PermissionType.APP, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.QUERY, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.TABLE, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.APP, PermissionLevel.READ),
|
||||
],
|
||||
},
|
||||
WRITE: {
|
||||
_id: BuiltinPermissionID.WRITE,
|
||||
name: "Read/Write",
|
||||
permissions: [
|
||||
new Permission(PermissionType.QUERY, PermissionLevel.WRITE),
|
||||
new Permission(PermissionType.TABLE, PermissionLevel.WRITE),
|
||||
new Permission(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
|
||||
new Permission(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new Permission(PermissionType.APP, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.QUERY, PermissionLevel.WRITE),
|
||||
new PermissionImpl(PermissionType.TABLE, PermissionLevel.WRITE),
|
||||
new PermissionImpl(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
|
||||
new PermissionImpl(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.APP, PermissionLevel.READ),
|
||||
],
|
||||
},
|
||||
POWER: {
|
||||
_id: BuiltinPermissionID.POWER,
|
||||
name: "Power",
|
||||
permissions: [
|
||||
new Permission(PermissionType.TABLE, PermissionLevel.WRITE),
|
||||
new Permission(PermissionType.USER, PermissionLevel.READ),
|
||||
new Permission(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
|
||||
new Permission(PermissionType.WEBHOOK, PermissionLevel.READ),
|
||||
new Permission(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new Permission(PermissionType.APP, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.TABLE, PermissionLevel.WRITE),
|
||||
new PermissionImpl(PermissionType.USER, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.AUTOMATION, PermissionLevel.EXECUTE),
|
||||
new PermissionImpl(PermissionType.WEBHOOK, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.APP, PermissionLevel.READ),
|
||||
],
|
||||
},
|
||||
ADMIN: {
|
||||
_id: BuiltinPermissionID.ADMIN,
|
||||
name: "Admin",
|
||||
permissions: [
|
||||
new Permission(PermissionType.TABLE, PermissionLevel.ADMIN),
|
||||
new Permission(PermissionType.USER, PermissionLevel.ADMIN),
|
||||
new Permission(PermissionType.AUTOMATION, PermissionLevel.ADMIN),
|
||||
new Permission(PermissionType.WEBHOOK, PermissionLevel.READ),
|
||||
new Permission(PermissionType.QUERY, PermissionLevel.ADMIN),
|
||||
new Permission(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new Permission(PermissionType.APP, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.TABLE, PermissionLevel.ADMIN),
|
||||
new PermissionImpl(PermissionType.USER, PermissionLevel.ADMIN),
|
||||
new PermissionImpl(PermissionType.AUTOMATION, PermissionLevel.ADMIN),
|
||||
new PermissionImpl(PermissionType.WEBHOOK, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.QUERY, PermissionLevel.ADMIN),
|
||||
new PermissionImpl(PermissionType.LEGACY_VIEW, PermissionLevel.READ),
|
||||
new PermissionImpl(PermissionType.APP, PermissionLevel.READ),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export function getBuiltinPermissions() {
|
||||
export function getBuiltinPermissions(): BuiltinPermissions {
|
||||
return cloneDeep(BUILTIN_PERMISSIONS)
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ describe("getBuiltinPermissionByID", () => {
|
|||
_id: BuiltinPermissionID.PUBLIC,
|
||||
name: "Public",
|
||||
permissions: [
|
||||
new permissions.Permission(
|
||||
new permissions.PermissionImpl(
|
||||
permissions.PermissionType.WEBHOOK,
|
||||
permissions.PermissionLevel.EXECUTE
|
||||
),
|
||||
|
|
|
@ -52,9 +52,16 @@
|
|||
let modal
|
||||
|
||||
$: text = value?.label ?? "Choose an option"
|
||||
$: tables = $tablesStore.list.map(table =>
|
||||
format.table(table, $datasources.list)
|
||||
)
|
||||
$: tables = $tablesStore.list
|
||||
.map(table => format.table(table, $datasources.list))
|
||||
.sort((a, b) => {
|
||||
// sort tables alphabetically, grouped by datasource
|
||||
const dsComparison = a.datasourceName.localeCompare(b.datasourceName)
|
||||
if (dsComparison !== 0) {
|
||||
return dsComparison
|
||||
}
|
||||
return a.label.localeCompare(b.label)
|
||||
})
|
||||
$: viewsV1 = $viewsStore.list.map(view => ({
|
||||
...view,
|
||||
label: view.name,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Heading, Body, Layout, Button, Modal } from "@budibase/bbui"
|
||||
import { Heading, Body, Layout, Button, Modal, Icon } from "@budibase/bbui"
|
||||
import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte"
|
||||
import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte"
|
||||
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||
|
@ -12,11 +12,13 @@
|
|||
automationStore,
|
||||
selectedAutomation,
|
||||
} from "stores/builder"
|
||||
import { createLocalStorageStore } from "@budibase/frontend-core"
|
||||
import { fly } from "svelte/transition"
|
||||
|
||||
$: automationId = $selectedAutomation?.data?._id
|
||||
$: builderStore.selectResource(automationId)
|
||||
|
||||
// Keep URL and state in sync for selected screen ID
|
||||
const surveyDismissed = createLocalStorageStore("automation-survey", false)
|
||||
const stopSyncing = syncURLToState({
|
||||
urlParam: "automationId",
|
||||
stateKey: "selectedAutomationId",
|
||||
|
@ -29,9 +31,11 @@
|
|||
|
||||
let modal
|
||||
let webhookModal
|
||||
let mounted = false
|
||||
|
||||
onMount(() => {
|
||||
$automationStore.showTestPanel = false
|
||||
mounted = true
|
||||
})
|
||||
|
||||
onDestroy(stopSyncing)
|
||||
|
@ -79,6 +83,43 @@
|
|||
</Modal>
|
||||
</div>
|
||||
|
||||
{#if !$surveyDismissed && mounted}
|
||||
<div
|
||||
class="survey"
|
||||
in:fly={{ x: 600, duration: 260, delay: 1000 }}
|
||||
out:fly={{ x: 600, duration: 260 }}
|
||||
>
|
||||
<div class="survey__body">
|
||||
<div class="survey__title">We value your feedback!</div>
|
||||
<div class="survey__text">
|
||||
<a
|
||||
href="https://t.maze.co/310149185"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
on:click={() => surveyDismissed.set(true)}
|
||||
>
|
||||
Complete our survey on Automations</a
|
||||
>
|
||||
and receive a $20 thank-you gift.
|
||||
<a
|
||||
href="https://drive.google.com/file/d/12-qk_2F9g5PdbM6wuKoz2KkIyLI-feMX/view?usp=sharing"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Terms apply.
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<Icon
|
||||
name="Close"
|
||||
hoverable
|
||||
color="var(--spectrum-global-color-static-gray-300)"
|
||||
hoverColor="var(--spectrum-global-color-static-gray-100)"
|
||||
on:click={() => surveyDismissed.set(true)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.root {
|
||||
flex: 1 1 auto;
|
||||
|
@ -108,11 +149,9 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.setup {
|
||||
padding-top: 9px;
|
||||
border-left: var(--border-light);
|
||||
|
@ -125,4 +164,39 @@
|
|||
grid-column: 3;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Survey */
|
||||
.survey {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
right: 32px;
|
||||
background: var(--spectrum-semantic-positive-color-background);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: var(--spacing-l) var(--spacing-xl);
|
||||
border-radius: 4px;
|
||||
gap: var(--spacing-xl);
|
||||
}
|
||||
.survey * {
|
||||
color: var(--spectrum-global-color-static-gray-300);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.survey a {
|
||||
text-decoration: underline;
|
||||
transition: color 130ms ease-out;
|
||||
}
|
||||
.survey a:hover {
|
||||
color: var(--spectrum-global-color-static-gray-100);
|
||||
cursor: pointer;
|
||||
}
|
||||
.survey__body {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.survey__title {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { getDefinition, getDefinitions } from "../../integrations"
|
||||
import { SourceName, UserCtx } from "@budibase/types"
|
||||
import {
|
||||
SourceName,
|
||||
UserCtx,
|
||||
FetchIntegrationsResponse,
|
||||
FindIntegrationResponse,
|
||||
} from "@budibase/types"
|
||||
|
||||
const DISABLED_EXTERNAL_INTEGRATIONS = [
|
||||
SourceName.AIRTABLE,
|
||||
SourceName.BUDIBASE,
|
||||
]
|
||||
|
||||
export async function fetch(ctx: UserCtx) {
|
||||
export async function fetch(ctx: UserCtx<void, FetchIntegrationsResponse>) {
|
||||
const definitions = await getDefinitions()
|
||||
for (let disabledIntegration of DISABLED_EXTERNAL_INTEGRATIONS) {
|
||||
delete definitions[disabledIntegration]
|
||||
|
@ -14,10 +19,14 @@ export async function fetch(ctx: UserCtx) {
|
|||
ctx.body = definitions
|
||||
}
|
||||
|
||||
export async function find(ctx: UserCtx) {
|
||||
export async function find(ctx: UserCtx<void, FindIntegrationResponse>) {
|
||||
const sourceType = ctx.params?.type
|
||||
if (DISABLED_EXTERNAL_INTEGRATIONS.indexOf(sourceType) !== -1) {
|
||||
ctx.throw(400, `Invalid source type - ${sourceType} is not supported.`)
|
||||
}
|
||||
ctx.body = await getDefinition(ctx.params.type)
|
||||
const integration = await getDefinition(ctx.params.type)
|
||||
if (!integration) {
|
||||
ctx.throw(404, "Integration not found")
|
||||
}
|
||||
ctx.body = integration
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { EMPTY_LAYOUT } from "../../constants/layouts"
|
|||
import { generateLayoutID, getScreenParams } from "../../db/utils"
|
||||
import { events, context } from "@budibase/backend-core"
|
||||
import {
|
||||
BBContext,
|
||||
DeleteLayoutResponse,
|
||||
Layout,
|
||||
SaveLayoutRequest,
|
||||
SaveLayoutResponse,
|
||||
|
@ -32,7 +32,7 @@ export async function save(
|
|||
ctx.status = 200
|
||||
}
|
||||
|
||||
export async function destroy(ctx: BBContext) {
|
||||
export async function destroy(ctx: UserCtx<void, DeleteLayoutResponse>) {
|
||||
const db = context.getAppDB()
|
||||
const layoutId = ctx.params.layoutId,
|
||||
layoutRev = ctx.params.layoutRev
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
import { MetadataTypes } from "../../constants"
|
||||
import { generateMetadataID } from "../../db/utils"
|
||||
import { saveEntityMetadata, deleteEntityMetadata } from "../../utilities"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import { BBContext } from "@budibase/types"
|
||||
import {
|
||||
UserCtx,
|
||||
MetadataType,
|
||||
GetMetadataTypesResponse,
|
||||
SaveMetadataRequest,
|
||||
SaveMetadataResponse,
|
||||
DeleteMetadataResponse,
|
||||
FindMetadataResponse,
|
||||
} from "@budibase/types"
|
||||
|
||||
export async function getTypes(ctx: BBContext) {
|
||||
export async function getTypes(ctx: UserCtx<void, GetMetadataTypesResponse>) {
|
||||
ctx.body = {
|
||||
types: MetadataTypes,
|
||||
types: MetadataType,
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveMetadata(ctx: BBContext) {
|
||||
export async function saveMetadata(
|
||||
ctx: UserCtx<SaveMetadataRequest, SaveMetadataResponse>
|
||||
) {
|
||||
const { type, entityId } = ctx.params
|
||||
if (type === MetadataTypes.AUTOMATION_TEST_HISTORY) {
|
||||
if (type === MetadataType.AUTOMATION_TEST_HISTORY) {
|
||||
ctx.throw(400, "Cannot save automation history type")
|
||||
}
|
||||
ctx.body = await saveEntityMetadata(type, entityId, ctx.request.body)
|
||||
}
|
||||
|
||||
export async function deleteMetadata(ctx: BBContext) {
|
||||
export async function deleteMetadata(
|
||||
ctx: UserCtx<void, DeleteMetadataResponse>
|
||||
) {
|
||||
const { type, entityId } = ctx.params
|
||||
await deleteEntityMetadata(type, entityId)
|
||||
ctx.body = {
|
||||
|
@ -26,17 +37,9 @@ export async function deleteMetadata(ctx: BBContext) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function getMetadata(ctx: BBContext) {
|
||||
export async function getMetadata(ctx: UserCtx<void, FindMetadataResponse>) {
|
||||
const { type, entityId } = ctx.params
|
||||
const db = context.getAppDB()
|
||||
const id = generateMetadataID(type, entityId)
|
||||
try {
|
||||
ctx.body = await db.get(id)
|
||||
} catch (err: any) {
|
||||
if (err.status === 404) {
|
||||
ctx.body = {}
|
||||
} else {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
ctx.body = (await db.tryGet(id)) || {}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,33 @@
|
|||
import { context } from "@budibase/backend-core"
|
||||
import { migrate as migrationImpl, MIGRATIONS } from "../../migrations"
|
||||
import { Ctx } from "@budibase/types"
|
||||
import {
|
||||
Ctx,
|
||||
FetchOldMigrationResponse,
|
||||
GetOldMigrationStatus,
|
||||
RunOldMigrationRequest,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
getAppMigrationVersion,
|
||||
getLatestEnabledMigrationId,
|
||||
} from "../../appMigrations"
|
||||
|
||||
export async function migrate(ctx: Ctx) {
|
||||
export async function migrate(ctx: Ctx<RunOldMigrationRequest, void>) {
|
||||
const options = ctx.request.body
|
||||
// don't await as can take a while, just return
|
||||
migrationImpl(options)
|
||||
ctx.status = 200
|
||||
}
|
||||
|
||||
export async function fetchDefinitions(ctx: Ctx) {
|
||||
export async function fetchDefinitions(
|
||||
ctx: Ctx<void, FetchOldMigrationResponse>
|
||||
) {
|
||||
ctx.body = MIGRATIONS
|
||||
ctx.status = 200
|
||||
}
|
||||
|
||||
export async function getMigrationStatus(ctx: Ctx) {
|
||||
export async function getMigrationStatus(
|
||||
ctx: Ctx<void, GetOldMigrationStatus>
|
||||
) {
|
||||
const appId = context.getAppId()
|
||||
|
||||
if (!appId) {
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
import { Ctx } from "@budibase/types"
|
||||
import { Ctx, LogOpsRequest, ErrorOpsRequest } from "@budibase/types"
|
||||
import { logging } from "@budibase/backend-core"
|
||||
|
||||
interface LogRequest {
|
||||
message: string
|
||||
data?: any
|
||||
}
|
||||
|
||||
interface ErrorRequest {
|
||||
message: string
|
||||
}
|
||||
|
||||
export async function log(ctx: Ctx<LogRequest>) {
|
||||
export async function log(ctx: Ctx<LogOpsRequest, void>) {
|
||||
const body = ctx.request.body
|
||||
console.trace(body.message, body.data)
|
||||
console.debug(body.message, body.data)
|
||||
|
@ -20,13 +11,13 @@ export async function log(ctx: Ctx<LogRequest>) {
|
|||
ctx.status = 204
|
||||
}
|
||||
|
||||
export async function alert(ctx: Ctx<ErrorRequest>) {
|
||||
export async function alert(ctx: Ctx<ErrorOpsRequest, void>) {
|
||||
const body = ctx.request.body
|
||||
logging.logAlert(body.message, new Error(body.message))
|
||||
ctx.status = 204
|
||||
}
|
||||
|
||||
export async function error(ctx: Ctx<ErrorRequest>) {
|
||||
export async function error(ctx: Ctx<ErrorOpsRequest, void>) {
|
||||
const body = ctx.request.body
|
||||
throw new Error(body.message)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import {
|
|||
RemovePermissionRequest,
|
||||
RemovePermissionResponse,
|
||||
FetchResourcePermissionInfoResponse,
|
||||
FetchBuiltinPermissionsRequest,
|
||||
FetchPermissionLevelsRequest,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
CURRENTLY_SUPPORTED_LEVELS,
|
||||
|
@ -19,11 +21,13 @@ import { PermissionUpdateType } from "../../sdk/app/permissions"
|
|||
|
||||
const SUPPORTED_LEVELS = CURRENTLY_SUPPORTED_LEVELS
|
||||
|
||||
export function fetchBuiltin(ctx: UserCtx) {
|
||||
export function fetchBuiltin(
|
||||
ctx: UserCtx<void, FetchBuiltinPermissionsRequest>
|
||||
) {
|
||||
ctx.body = Object.values(permissions.getBuiltinPermissions())
|
||||
}
|
||||
|
||||
export function fetchLevels(ctx: UserCtx) {
|
||||
export function fetchLevels(ctx: UserCtx<void, FetchPermissionLevelsRequest>) {
|
||||
// for now only provide the read/write perms externally
|
||||
ctx.body = SUPPORTED_LEVELS
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ import {
|
|||
getPluginMetadata,
|
||||
extractTarball,
|
||||
} from "../../../utilities/fileSystem"
|
||||
import { KoaFile } from "@budibase/types"
|
||||
|
||||
export async function fileUpload(file: { name: string; path: string }) {
|
||||
export async function fileUpload(file: KoaFile) {
|
||||
if (!file.name || !file.path) {
|
||||
throw new Error("File is not valid - cannot upload.")
|
||||
}
|
||||
if (!file.name.endsWith(".tar.gz")) {
|
||||
throw new Error("Plugin must be compressed into a gzipped tarball.")
|
||||
}
|
||||
|
|
|
@ -2,26 +2,37 @@ import { npmUpload, urlUpload, githubUpload } from "./uploaders"
|
|||
import { plugins as pluginCore } from "@budibase/backend-core"
|
||||
import {
|
||||
PluginType,
|
||||
FileType,
|
||||
PluginSource,
|
||||
Ctx,
|
||||
CreatePluginRequest,
|
||||
CreatePluginResponse,
|
||||
UserCtx,
|
||||
UploadPluginRequest,
|
||||
Plugin,
|
||||
UploadPluginResponse,
|
||||
FetchPluginResponse,
|
||||
DeletePluginResponse,
|
||||
} from "@budibase/types"
|
||||
import env from "../../../environment"
|
||||
import { clientAppSocket } from "../../../websockets"
|
||||
import sdk from "../../../sdk"
|
||||
import { sdk as pro } from "@budibase/pro"
|
||||
|
||||
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]
|
||||
export async function upload(
|
||||
ctx: UserCtx<UploadPluginRequest, UploadPluginResponse>
|
||||
) {
|
||||
const files = ctx.request.files
|
||||
const plugins =
|
||||
files && Array.isArray(files.file) && files.file.length > 1
|
||||
? Array.from(files.file)
|
||||
: [files?.file]
|
||||
|
||||
try {
|
||||
let docs = []
|
||||
let docs: Plugin[] = []
|
||||
// can do single or multiple plugins
|
||||
for (let plugin of plugins) {
|
||||
if (!plugin || Array.isArray(plugin)) {
|
||||
continue
|
||||
}
|
||||
const doc = await sdk.plugins.processUploaded(plugin, PluginSource.FILE)
|
||||
docs.push(doc)
|
||||
}
|
||||
|
@ -37,7 +48,7 @@ export async function upload(ctx: any) {
|
|||
}
|
||||
|
||||
export async function create(
|
||||
ctx: Ctx<CreatePluginRequest, CreatePluginResponse>
|
||||
ctx: UserCtx<CreatePluginRequest, CreatePluginResponse>
|
||||
) {
|
||||
const { source, url, headers, githubToken } = ctx.request.body
|
||||
|
||||
|
@ -91,11 +102,11 @@ export async function create(
|
|||
}
|
||||
}
|
||||
|
||||
export async function fetch(ctx: any) {
|
||||
export async function fetch(ctx: UserCtx<void, FetchPluginResponse>) {
|
||||
ctx.body = await sdk.plugins.fetch()
|
||||
}
|
||||
|
||||
export async function destroy(ctx: any) {
|
||||
export async function destroy(ctx: UserCtx<void, DeletePluginResponse>) {
|
||||
const { pluginId } = ctx.params
|
||||
|
||||
try {
|
||||
|
|
|
@ -4,26 +4,38 @@ import { save as saveDatasource } from "../datasource"
|
|||
import { RestImporter } from "./import"
|
||||
import { invalidateCachedVariable } from "../../../threads/utils"
|
||||
import env from "../../../environment"
|
||||
import { events, context, utils, constants } from "@budibase/backend-core"
|
||||
import { constants, context, events, utils } from "@budibase/backend-core"
|
||||
import sdk from "../../../sdk"
|
||||
import { QueryEvent, QueryEventParameters } from "../../../threads/definitions"
|
||||
import {
|
||||
ConfigType,
|
||||
Query,
|
||||
UserCtx,
|
||||
SessionCookie,
|
||||
JsonFieldSubType,
|
||||
QueryResponse,
|
||||
QuerySchema,
|
||||
FieldType,
|
||||
CreateDatasourceRequest,
|
||||
Datasource,
|
||||
ExecuteQueryRequest,
|
||||
ExecuteQueryResponse,
|
||||
ExecuteV2QueryResponse,
|
||||
ExecuteV1QueryResponse,
|
||||
FetchQueriesResponse,
|
||||
FieldType,
|
||||
FindQueryResponse,
|
||||
ImportRestQueryRequest,
|
||||
ImportRestQueryResponse,
|
||||
JsonFieldSubType,
|
||||
PreviewQueryRequest,
|
||||
PreviewQueryResponse,
|
||||
Query,
|
||||
QueryResponse,
|
||||
QuerySchema,
|
||||
SaveQueryRequest,
|
||||
SaveQueryResponse,
|
||||
SessionCookie,
|
||||
SourceName,
|
||||
UserCtx,
|
||||
DeleteQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import { ValidQueryNameRegex, utils as JsonUtils } from "@budibase/shared-core"
|
||||
import { utils as JsonUtils, ValidQueryNameRegex } from "@budibase/shared-core"
|
||||
import { findHBSBlocks } from "@budibase/string-templates"
|
||||
import { ObjectId } from "mongodb"
|
||||
import { merge } from "lodash"
|
||||
|
||||
const Runner = new Thread(ThreadType.QUERY, {
|
||||
timeoutMs: env.QUERY_THREAD_TIMEOUT,
|
||||
|
@ -43,11 +55,13 @@ function validateQueryInputs(parameters: QueryEventParameters) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function fetch(ctx: UserCtx) {
|
||||
export async function fetch(ctx: UserCtx<void, FetchQueriesResponse>) {
|
||||
ctx.body = await sdk.queries.fetch()
|
||||
}
|
||||
|
||||
const _import = async (ctx: UserCtx) => {
|
||||
const _import = async (
|
||||
ctx: UserCtx<ImportRestQueryRequest, ImportRestQueryResponse>
|
||||
) => {
|
||||
const body = ctx.request.body
|
||||
const data = body.data
|
||||
|
||||
|
@ -58,9 +72,9 @@ const _import = async (ctx: UserCtx) => {
|
|||
if (!body.datasourceId) {
|
||||
// construct new datasource
|
||||
const info: any = await importer.getInfo()
|
||||
let datasource = {
|
||||
let datasource: Datasource = {
|
||||
type: "datasource",
|
||||
source: "REST",
|
||||
source: SourceName.REST,
|
||||
config: {
|
||||
url: info.url,
|
||||
defaultHeaders: [],
|
||||
|
@ -69,8 +83,14 @@ const _import = async (ctx: UserCtx) => {
|
|||
name: info.name,
|
||||
}
|
||||
// save the datasource
|
||||
const datasourceCtx = { ...ctx }
|
||||
datasourceCtx.request.body.datasource = datasource
|
||||
const datasourceCtx: UserCtx<CreateDatasourceRequest> = merge(ctx, {
|
||||
request: {
|
||||
body: {
|
||||
datasource,
|
||||
tablesFilter: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
await saveDatasource(datasourceCtx)
|
||||
datasourceId = datasourceCtx.body.datasource._id
|
||||
} else {
|
||||
|
@ -88,7 +108,7 @@ const _import = async (ctx: UserCtx) => {
|
|||
}
|
||||
export { _import as import }
|
||||
|
||||
export async function save(ctx: UserCtx<Query, Query>) {
|
||||
export async function save(ctx: UserCtx<SaveQueryRequest, SaveQueryResponse>) {
|
||||
const db = context.getAppDB()
|
||||
const query: Query = ctx.request.body
|
||||
|
||||
|
@ -119,10 +139,9 @@ export async function save(ctx: UserCtx<Query, Query>) {
|
|||
query._rev = response.rev
|
||||
|
||||
ctx.body = query
|
||||
ctx.message = `Query ${query.name} saved successfully.`
|
||||
}
|
||||
|
||||
export async function find(ctx: UserCtx) {
|
||||
export async function find(ctx: UserCtx<void, FindQueryResponse>) {
|
||||
const queryId = ctx.params.queryId
|
||||
ctx.body = await sdk.queries.find(queryId)
|
||||
}
|
||||
|
@ -335,7 +354,7 @@ export async function preview(
|
|||
async function execute(
|
||||
ctx: UserCtx<
|
||||
ExecuteQueryRequest,
|
||||
ExecuteQueryResponse | Record<string, any>[]
|
||||
ExecuteV2QueryResponse | ExecuteV1QueryResponse
|
||||
>,
|
||||
opts: any = { rowsOnly: false, isAutomation: false }
|
||||
) {
|
||||
|
@ -390,19 +409,21 @@ async function execute(
|
|||
}
|
||||
|
||||
export async function executeV1(
|
||||
ctx: UserCtx<ExecuteQueryRequest, Record<string, any>[]>
|
||||
ctx: UserCtx<ExecuteQueryRequest, ExecuteV1QueryResponse>
|
||||
) {
|
||||
return execute(ctx, { rowsOnly: true, isAutomation: false })
|
||||
}
|
||||
|
||||
export async function executeV2(
|
||||
ctx: UserCtx<
|
||||
ExecuteQueryRequest,
|
||||
ExecuteQueryResponse | Record<string, any>[]
|
||||
>,
|
||||
{ isAutomation }: { isAutomation?: boolean } = {}
|
||||
ctx: UserCtx<ExecuteQueryRequest, ExecuteV2QueryResponse>
|
||||
) {
|
||||
return execute(ctx, { rowsOnly: false, isAutomation })
|
||||
return execute(ctx, { rowsOnly: false })
|
||||
}
|
||||
|
||||
export async function executeV2AsAutomation(
|
||||
ctx: UserCtx<ExecuteQueryRequest, ExecuteV2QueryResponse>
|
||||
) {
|
||||
return execute(ctx, { rowsOnly: false, isAutomation: true })
|
||||
}
|
||||
|
||||
const removeDynamicVariables = async (queryId: string) => {
|
||||
|
@ -426,14 +447,14 @@ const removeDynamicVariables = async (queryId: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
export async function destroy(ctx: UserCtx) {
|
||||
export async function destroy(ctx: UserCtx<void, DeleteQueryResponse>) {
|
||||
const db = context.getAppDB()
|
||||
const queryId = ctx.params.queryId as string
|
||||
await removeDynamicVariables(queryId)
|
||||
const query = await db.get<Query>(queryId)
|
||||
const datasource = await sdk.datasources.get(query.datasourceId)
|
||||
await db.remove(ctx.params.queryId, ctx.params.revId)
|
||||
ctx.message = `Query deleted.`
|
||||
ctx.body = { message: `Query deleted.` }
|
||||
ctx.status = 200
|
||||
await events.query.deleted(datasource, query)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { getUserMetadataParams, InternalTables } from "../../db/utils"
|
|||
import {
|
||||
AccessibleRolesResponse,
|
||||
Database,
|
||||
DestroyRoleResponse,
|
||||
DeleteRoleResponse,
|
||||
FetchRolesResponse,
|
||||
FindRoleResponse,
|
||||
Role,
|
||||
|
@ -199,7 +199,7 @@ export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
|||
builderSocket?.emitRoleUpdate(ctx, role)
|
||||
}
|
||||
|
||||
export async function destroy(ctx: UserCtx<void, DestroyRoleResponse>) {
|
||||
export async function destroy(ctx: UserCtx<void, DeleteRoleResponse>) {
|
||||
const db = context.getAppDB()
|
||||
let roleId = ctx.params.roleId as string
|
||||
if (roles.isBuiltin(roleId)) {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import { getRoutingInfo } from "../../utilities/routing"
|
||||
import { roles } from "@budibase/backend-core"
|
||||
import { UserCtx } from "@budibase/types"
|
||||
import {
|
||||
FetchClientScreenRoutingResponse,
|
||||
FetchScreenRoutingResponse,
|
||||
ScreenRoutingJson,
|
||||
UserCtx,
|
||||
} from "@budibase/types"
|
||||
|
||||
const URL_SEPARATOR = "/"
|
||||
|
||||
class Routing {
|
||||
json: any
|
||||
json: ScreenRoutingJson
|
||||
|
||||
constructor() {
|
||||
this.json = {}
|
||||
}
|
||||
|
@ -43,7 +49,7 @@ class Routing {
|
|||
* @returns The routing structure, this is the full structure designed for use in the builder,
|
||||
* if the client routing is required then the updateRoutingStructureForUserRole should be used.
|
||||
*/
|
||||
async function getRoutingStructure() {
|
||||
async function getRoutingStructure(): Promise<{ routes: ScreenRoutingJson }> {
|
||||
const screenRoutes = await getRoutingInfo()
|
||||
const routing = new Routing()
|
||||
|
||||
|
@ -56,11 +62,13 @@ async function getRoutingStructure() {
|
|||
return { routes: routing.json }
|
||||
}
|
||||
|
||||
export async function fetch(ctx: UserCtx) {
|
||||
export async function fetch(ctx: UserCtx<void, FetchScreenRoutingResponse>) {
|
||||
ctx.body = await getRoutingStructure()
|
||||
}
|
||||
|
||||
export async function clientFetch(ctx: UserCtx) {
|
||||
export async function clientFetch(
|
||||
ctx: UserCtx<void, FetchClientScreenRoutingResponse>
|
||||
) {
|
||||
const routing = await getRoutingStructure()
|
||||
let roleId = ctx.user?.role?._id
|
||||
const roleIds = roleId ? await roles.getUserRoleIdHierarchy(roleId) : []
|
||||
|
|
|
@ -11,11 +11,14 @@ import {
|
|||
DeleteRow,
|
||||
DeleteRowRequest,
|
||||
DeleteRows,
|
||||
DownloadAttachmentResponse,
|
||||
EventType,
|
||||
ExportRowsRequest,
|
||||
ExportRowsResponse,
|
||||
FetchEnrichedRowResponse,
|
||||
FetchRowsResponse,
|
||||
FieldType,
|
||||
GetRowResponse,
|
||||
FindRowResponse,
|
||||
isRelationshipField,
|
||||
PatchRowRequest,
|
||||
PatchRowResponse,
|
||||
|
@ -23,12 +26,15 @@ import {
|
|||
Row,
|
||||
RowAttachment,
|
||||
RowSearchParams,
|
||||
SaveRowRequest,
|
||||
SaveRowResponse,
|
||||
SearchFilters,
|
||||
SearchRowRequest,
|
||||
SearchRowResponse,
|
||||
Table,
|
||||
UserCtx,
|
||||
ValidateResponse,
|
||||
ValidateRowRequest,
|
||||
ValidateRowResponse,
|
||||
} from "@budibase/types"
|
||||
import * as utils from "./utils"
|
||||
import { gridSocket } from "../../../websockets"
|
||||
|
@ -83,7 +89,7 @@ export async function patch(
|
|||
}
|
||||
}
|
||||
|
||||
export const save = async (ctx: UserCtx<Row, Row>) => {
|
||||
export const save = async (ctx: UserCtx<SaveRowRequest, SaveRowResponse>) => {
|
||||
const { tableId, viewId } = utils.getSourceId(ctx)
|
||||
const sourceId = viewId || tableId
|
||||
|
||||
|
@ -131,12 +137,12 @@ export async function fetchLegacyView(ctx: any) {
|
|||
})
|
||||
}
|
||||
|
||||
export async function fetch(ctx: any) {
|
||||
export async function fetch(ctx: UserCtx<void, FetchRowsResponse>) {
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
ctx.body = await sdk.rows.fetch(tableId)
|
||||
}
|
||||
|
||||
export async function find(ctx: UserCtx<void, GetRowResponse>) {
|
||||
export async function find(ctx: UserCtx<void, FindRowResponse>) {
|
||||
const { tableId, viewId } = utils.getSourceId(ctx)
|
||||
const sourceId = viewId || tableId
|
||||
const rowId = ctx.params.rowId
|
||||
|
@ -314,7 +320,9 @@ function replaceTableNamesInFilters(
|
|||
})
|
||||
}
|
||||
|
||||
export async function validate(ctx: Ctx<Row, ValidateResponse>) {
|
||||
export async function validate(
|
||||
ctx: Ctx<ValidateRowRequest, ValidateRowResponse>
|
||||
) {
|
||||
const source = await utils.getSource(ctx)
|
||||
const table = await utils.getTableFromSource(source)
|
||||
// external tables are hard to validate currently
|
||||
|
@ -328,7 +336,9 @@ export async function validate(ctx: Ctx<Row, ValidateResponse>) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function fetchEnrichedRow(ctx: UserCtx<void, Row>) {
|
||||
export async function fetchEnrichedRow(
|
||||
ctx: UserCtx<void, FetchEnrichedRowResponse>
|
||||
) {
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
ctx.body = await pickApi(tableId).fetchEnrichedRow(ctx)
|
||||
}
|
||||
|
@ -366,7 +376,9 @@ export const exportRows = async (
|
|||
ctx.body = apiFileReturn(content)
|
||||
}
|
||||
|
||||
export async function downloadAttachment(ctx: UserCtx) {
|
||||
export async function downloadAttachment(
|
||||
ctx: UserCtx<void, DownloadAttachmentResponse>
|
||||
) {
|
||||
const { columnName } = ctx.params
|
||||
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
|
|
|
@ -56,7 +56,7 @@ router
|
|||
"/api/v2/queries/:queryId",
|
||||
paramResource("queryId"),
|
||||
authorized(PermissionType.QUERY, PermissionLevel.WRITE),
|
||||
queryController.executeV2 as any
|
||||
queryController.executeV2
|
||||
)
|
||||
|
||||
export default router
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const { testAutomation } = require("./utilities/TestFunctions")
|
||||
const setup = require("./utilities")
|
||||
const { MetadataTypes } = require("../../../constants")
|
||||
import { testAutomation } from "./utilities/TestFunctions"
|
||||
import * as setup from "./utilities"
|
||||
import { MetadataType, Automation } from "@budibase/types"
|
||||
|
||||
describe("/metadata", () => {
|
||||
let request = setup.getRequest()
|
||||
let config = setup.getConfig()
|
||||
let automation
|
||||
let automation: Automation
|
||||
|
||||
afterAll(setup.afterAll)
|
||||
|
||||
|
@ -15,8 +15,8 @@ describe("/metadata", () => {
|
|||
})
|
||||
|
||||
async function createMetadata(
|
||||
data,
|
||||
type = MetadataTypes.AUTOMATION_TEST_INPUT
|
||||
data: Record<string, string>,
|
||||
type = MetadataType.AUTOMATION_TEST_INPUT
|
||||
) {
|
||||
const res = await request
|
||||
.post(`/api/metadata/${type}/${automation._id}`)
|
||||
|
@ -27,7 +27,7 @@ describe("/metadata", () => {
|
|||
expect(res.body._rev).toBeDefined()
|
||||
}
|
||||
|
||||
async function getMetadata(type) {
|
||||
async function getMetadata(type: MetadataType) {
|
||||
const res = await request
|
||||
.get(`/api/metadata/${type}/${automation._id}`)
|
||||
.set(config.defaultHeaders())
|
||||
|
@ -39,14 +39,14 @@ describe("/metadata", () => {
|
|||
describe("save", () => {
|
||||
it("should be able to save some metadata", async () => {
|
||||
await createMetadata({ test: "a" })
|
||||
const testInput = await getMetadata(MetadataTypes.AUTOMATION_TEST_INPUT)
|
||||
const testInput = await getMetadata(MetadataType.AUTOMATION_TEST_INPUT)
|
||||
expect(testInput.test).toBe("a")
|
||||
})
|
||||
|
||||
it("should save history metadata on automation run", async () => {
|
||||
// this should have created some history
|
||||
await testAutomation(config, automation)
|
||||
const metadata = await getMetadata(MetadataTypes.AUTOMATION_TEST_HISTORY)
|
||||
await testAutomation(config, automation, {})
|
||||
const metadata = await getMetadata(MetadataType.AUTOMATION_TEST_HISTORY)
|
||||
expect(metadata).toBeDefined()
|
||||
expect(metadata.history.length).toBe(1)
|
||||
expect(typeof metadata.history[0].occurredAt).toBe("number")
|
||||
|
@ -57,13 +57,13 @@ describe("/metadata", () => {
|
|||
it("should be able to delete some test inputs", async () => {
|
||||
const res = await request
|
||||
.delete(
|
||||
`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`
|
||||
`/api/metadata/${MetadataType.AUTOMATION_TEST_INPUT}/${automation._id}`
|
||||
)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body.message).toBeDefined()
|
||||
const metadata = await getMetadata(MetadataTypes.AUTOMATION_TEST_INPUT)
|
||||
const metadata = await getMetadata(MetadataType.AUTOMATION_TEST_INPUT)
|
||||
expect(metadata.test).toBeUndefined()
|
||||
})
|
||||
})
|
|
@ -94,7 +94,7 @@ export async function run({
|
|||
})
|
||||
|
||||
try {
|
||||
await queryController.executeV2(ctx, { isAutomation: true })
|
||||
await queryController.executeV2AsAutomation(ctx)
|
||||
const { data, ...rest } = ctx.body
|
||||
|
||||
return {
|
||||
|
|
|
@ -2,7 +2,6 @@ import { Thread, ThreadType } from "../threads"
|
|||
import { definitions } from "./triggerInfo"
|
||||
import { automationQueue } from "./bullboard"
|
||||
import { updateEntityMetadata } from "../utilities"
|
||||
import { MetadataTypes } from "../constants"
|
||||
import { context, db as dbCore, utils } from "@budibase/backend-core"
|
||||
import { getAutomationMetadataParams } from "../db/utils"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
@ -14,6 +13,7 @@ import {
|
|||
AutomationStepDefinition,
|
||||
AutomationTriggerDefinition,
|
||||
AutomationTriggerStepId,
|
||||
MetadataType,
|
||||
} from "@budibase/types"
|
||||
import { automationsEnabled } from "../features"
|
||||
import { helpers, REBOOT_CRON } from "@budibase/shared-core"
|
||||
|
@ -107,7 +107,7 @@ export async function updateTestHistory(
|
|||
history: any
|
||||
) {
|
||||
return updateEntityMetadata(
|
||||
MetadataTypes.AUTOMATION_TEST_HISTORY,
|
||||
MetadataType.AUTOMATION_TEST_HISTORY,
|
||||
automation._id,
|
||||
(metadata: any) => {
|
||||
if (metadata && Array.isArray(metadata.history)) {
|
||||
|
|
|
@ -124,11 +124,6 @@ export enum BaseQueryVerbs {
|
|||
DELETE = "delete",
|
||||
}
|
||||
|
||||
export enum MetadataTypes {
|
||||
AUTOMATION_TEST_INPUT = "automationTestInput",
|
||||
AUTOMATION_TEST_HISTORY = "automationTestHistory",
|
||||
}
|
||||
|
||||
export enum InvalidColumns {
|
||||
ID = "_id",
|
||||
REV = "_rev",
|
||||
|
|
|
@ -3,10 +3,10 @@ import {
|
|||
RequiredKeys,
|
||||
Webhook,
|
||||
WebhookActionType,
|
||||
MetadataType,
|
||||
} from "@budibase/types"
|
||||
import { generateAutomationID, getAutomationParams } from "../../../db/utils"
|
||||
import { deleteEntityMetadata } from "../../../utilities"
|
||||
import { MetadataTypes } from "../../../constants"
|
||||
import {
|
||||
context,
|
||||
events,
|
||||
|
@ -161,7 +161,7 @@ export async function update(automation: Automation) {
|
|||
if (oldAutoTrigger && oldAutoTrigger.id !== newAutoTrigger?.id) {
|
||||
await events.automation.triggerUpdated(automation)
|
||||
await deleteEntityMetadata(
|
||||
MetadataTypes.AUTOMATION_TEST_INPUT,
|
||||
MetadataType.AUTOMATION_TEST_INPUT,
|
||||
automation._id!
|
||||
)
|
||||
}
|
||||
|
@ -183,11 +183,8 @@ export async function remove(automationId: string, rev: string) {
|
|||
})
|
||||
|
||||
// delete metadata first
|
||||
await deleteEntityMetadata(MetadataTypes.AUTOMATION_TEST_INPUT, automationId)
|
||||
await deleteEntityMetadata(
|
||||
MetadataTypes.AUTOMATION_TEST_HISTORY,
|
||||
automationId
|
||||
)
|
||||
await deleteEntityMetadata(MetadataType.AUTOMATION_TEST_INPUT, automationId)
|
||||
await deleteEntityMetadata(MetadataType.AUTOMATION_TEST_HISTORY, automationId)
|
||||
|
||||
const result = await db.remove(automationId, rev)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { FileType, Plugin, PluginSource, PluginType } from "@budibase/types"
|
||||
import { KoaFile, Plugin, PluginSource, PluginType } from "@budibase/types"
|
||||
import {
|
||||
db as dbCore,
|
||||
objectStore,
|
||||
|
@ -10,7 +10,7 @@ import env from "../../environment"
|
|||
import { clientAppSocket } from "../../websockets"
|
||||
import { sdk as pro } from "@budibase/pro"
|
||||
|
||||
export async function fetch(type?: PluginType) {
|
||||
export async function fetch(type?: PluginType): Promise<Plugin[]> {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
dbCore.getPluginParams(null, {
|
||||
|
@ -26,7 +26,7 @@ export async function fetch(type?: PluginType) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function processUploaded(plugin: FileType, source?: PluginSource) {
|
||||
export async function processUploaded(plugin: KoaFile, source?: PluginSource) {
|
||||
const { metadata, directory } = await fileUpload(plugin)
|
||||
pluginCore.validate(metadata?.schema)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
Query,
|
||||
ExecuteQueryRequest,
|
||||
ExecuteQueryResponse,
|
||||
ExecuteV2QueryResponse,
|
||||
PreviewQueryRequest,
|
||||
PreviewQueryResponse,
|
||||
} from "@budibase/types"
|
||||
|
@ -17,8 +17,8 @@ export class QueryAPI extends TestAPI {
|
|||
queryId: string,
|
||||
body?: ExecuteQueryRequest,
|
||||
expectations?: Expectations
|
||||
): Promise<ExecuteQueryResponse> => {
|
||||
return await this._post<ExecuteQueryResponse>(
|
||||
): Promise<ExecuteV2QueryResponse> => {
|
||||
return await this._post<ExecuteV2QueryResponse>(
|
||||
`/api/v2/queries/${queryId}`,
|
||||
{
|
||||
body,
|
||||
|
|
|
@ -2,7 +2,7 @@ import {
|
|||
PatchRowRequest,
|
||||
SaveRowRequest,
|
||||
Row,
|
||||
ValidateResponse,
|
||||
ValidateRowResponse,
|
||||
ExportRowsRequest,
|
||||
BulkImportRequest,
|
||||
BulkImportResponse,
|
||||
|
@ -51,8 +51,8 @@ export class RowAPI extends TestAPI {
|
|||
sourceId: string,
|
||||
row: SaveRowRequest,
|
||||
expectations?: Expectations
|
||||
): Promise<ValidateResponse> => {
|
||||
return await this._post<ValidateResponse>(
|
||||
): Promise<ValidateRowResponse> => {
|
||||
return await this._post<ValidateRowResponse>(
|
||||
`/api/${sourceId}/rows/validate`,
|
||||
{
|
||||
body: row,
|
||||
|
|
|
@ -88,7 +88,7 @@ export async function saveEntityMetadata(
|
|||
type: string,
|
||||
entityId: string,
|
||||
metadata: Document
|
||||
) {
|
||||
): Promise<Document> {
|
||||
return updateEntityMetadata(type, entityId, () => {
|
||||
return metadata
|
||||
})
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
import { createRoutingView } from "../../db/views/staticViews"
|
||||
import { ViewName, getQueryIndex, UNICODE_MAX } from "../../db/utils"
|
||||
import { context } from "@budibase/backend-core"
|
||||
import { ScreenRouting, Document } from "@budibase/types"
|
||||
import { ScreenRoutesViewOutput } from "@budibase/types"
|
||||
|
||||
interface ScreenRoutesView extends Document {
|
||||
id: string
|
||||
routing: ScreenRouting
|
||||
}
|
||||
|
||||
export async function getRoutingInfo(): Promise<ScreenRoutesView[]> {
|
||||
export async function getRoutingInfo(): Promise<ScreenRoutesViewOutput[]> {
|
||||
const db = context.getAppDB()
|
||||
try {
|
||||
const allRouting = await db.query<ScreenRoutesView>(
|
||||
const allRouting = await db.query<ScreenRoutesViewOutput>(
|
||||
getQueryIndex(ViewName.ROUTING),
|
||||
{
|
||||
startkey: "",
|
||||
endkey: UNICODE_MAX,
|
||||
}
|
||||
)
|
||||
return allRouting.rows.map(row => row.value as ScreenRoutesView)
|
||||
return allRouting.rows.map(row => row.value)
|
||||
} catch (err: any) {
|
||||
// check if the view doesn't exist, it should for all new instances
|
||||
/* istanbul ignore next */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
export * from "./backup"
|
||||
export * from "./datasource"
|
||||
export * from "./row"
|
||||
export * from "./view"
|
||||
export * from "./rows"
|
||||
export * from "./table"
|
||||
|
@ -10,3 +9,7 @@ export * from "./user"
|
|||
export * from "./rowAction"
|
||||
export * from "./automation"
|
||||
export * from "./component"
|
||||
export * from "./integration"
|
||||
export * from "./metadata"
|
||||
export * from "./query"
|
||||
export * from "./screen"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import { Integration, SourceName } from "../../../sdk"
|
||||
|
||||
export type FetchIntegrationsResponse = Record<
|
||||
SourceName,
|
||||
Integration | undefined
|
||||
>
|
||||
|
||||
export type FindIntegrationResponse = Integration
|
|
@ -0,0 +1,14 @@
|
|||
import { MetadataType, Document } from "../../../documents"
|
||||
|
||||
export interface GetMetadataTypesResponse {
|
||||
types: typeof MetadataType
|
||||
}
|
||||
|
||||
export interface SaveMetadataRequest extends Document {}
|
||||
export interface SaveMetadataResponse extends Document {}
|
||||
|
||||
export interface DeleteMetadataResponse {
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface FindMetadataResponse extends Document {}
|
|
@ -1,4 +1,8 @@
|
|||
import { PermissionLevel } from "../../../sdk"
|
||||
import { BuiltinPermission, PermissionLevel } from "../../../sdk"
|
||||
|
||||
export type FetchBuiltinPermissionsRequest = BuiltinPermission[]
|
||||
|
||||
export type FetchPermissionLevelsRequest = string[]
|
||||
|
||||
export interface FetchResourcePermissionInfoResponse {
|
||||
[key: string]: Record<string, string>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import {
|
||||
Datasource,
|
||||
Query,
|
||||
QueryPreview,
|
||||
QuerySchema,
|
||||
} from "../../../documents"
|
||||
|
||||
export type FetchQueriesResponse = Query[]
|
||||
|
||||
export interface SaveQueryRequest extends Query {}
|
||||
export interface SaveQueryResponse extends Query {}
|
||||
|
||||
export interface ImportRestQueryRequest {
|
||||
datasourceId: string
|
||||
data: string
|
||||
datasource: Datasource
|
||||
}
|
||||
export interface ImportRestQueryResponse {
|
||||
errorQueries: Query[]
|
||||
queries: Query[]
|
||||
datasourceId: string
|
||||
}
|
||||
|
||||
export interface FindQueryResponse extends Query {}
|
||||
|
||||
export interface PreviewQueryRequest extends QueryPreview {}
|
||||
|
||||
export interface PreviewQueryResponse {
|
||||
rows: any[]
|
||||
nestedSchemaFields: { [key: string]: { [key: string]: string | QuerySchema } }
|
||||
schema: { [key: string]: string | QuerySchema }
|
||||
info: any
|
||||
extra: any
|
||||
}
|
||||
|
||||
export interface ExecuteQueryRequest {
|
||||
parameters?: Record<string, string>
|
||||
pagination?: any
|
||||
}
|
||||
export type ExecuteV1QueryResponse = Record<string, any>[]
|
||||
export interface ExecuteV2QueryResponse {
|
||||
data: Record<string, any>[]
|
||||
}
|
||||
|
||||
export interface DeleteQueryResponse {
|
||||
message: string
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import { Row } from "../../../documents/app/row"
|
||||
|
||||
export interface GetRowResponse extends Row {}
|
||||
|
||||
export interface DeleteRows {
|
||||
rows: (Row | string)[]
|
||||
}
|
||||
|
||||
export interface DeleteRow {
|
||||
_id: string
|
||||
}
|
||||
|
||||
export type DeleteRowRequest = DeleteRows | DeleteRow
|
||||
|
||||
export interface ValidateResponse {
|
||||
valid: boolean
|
||||
errors: Record<string, any>
|
||||
}
|
|
@ -1,11 +1,17 @@
|
|||
import { SearchFilters } from "../../../../sdk"
|
||||
import { Row } from "../../../../documents"
|
||||
import { SortOrder } from "../../../../api/web/pagination"
|
||||
import { SortOrder } from "../../pagination"
|
||||
import { ReadStream } from "fs"
|
||||
import stream from "node:stream"
|
||||
|
||||
export * from "./search"
|
||||
|
||||
export interface FetchEnrichedRowResponse extends Row {}
|
||||
|
||||
export type FetchRowsResponse = Row[]
|
||||
|
||||
export interface SaveRowRequest extends Row {}
|
||||
export interface SaveRowResponse extends Row {}
|
||||
|
||||
export interface PatchRowRequest extends Row {
|
||||
_id: string
|
||||
|
@ -26,3 +32,23 @@ export interface ExportRowsRequest {
|
|||
}
|
||||
|
||||
export type ExportRowsResponse = ReadStream
|
||||
|
||||
export type DownloadAttachmentResponse = stream.PassThrough | stream.Readable
|
||||
|
||||
export interface FindRowResponse extends Row {}
|
||||
|
||||
export interface DeleteRows {
|
||||
rows: (Row | string)[]
|
||||
}
|
||||
|
||||
export interface DeleteRow {
|
||||
_id: string
|
||||
}
|
||||
|
||||
export type DeleteRowRequest = DeleteRows | DeleteRow
|
||||
|
||||
export interface ValidateRowRequest extends Row {}
|
||||
export interface ValidateRowResponse {
|
||||
valid: boolean
|
||||
errors: Record<string, any>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import { ScreenRoutingJson } from "../../../documents"
|
||||
|
||||
export interface FetchScreenRoutingResponse {
|
||||
routes: ScreenRoutingJson
|
||||
}
|
||||
|
||||
export interface FetchClientScreenRoutingResponse
|
||||
extends FetchScreenRoutingResponse {}
|
|
@ -4,3 +4,4 @@ export * from "./events"
|
|||
export * from "./configs"
|
||||
export * from "./scim"
|
||||
export * from "./license"
|
||||
export * from "./oldMigration"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { Migration, MigrationOptions } from "../../../sdk"
|
||||
|
||||
export interface RunOldMigrationRequest extends MigrationOptions {}
|
||||
|
||||
export type FetchOldMigrationResponse = Migration[]
|
||||
|
||||
export interface GetOldMigrationStatus {
|
||||
migrated: boolean
|
||||
}
|
|
@ -13,7 +13,6 @@ export * from "./searchFilter"
|
|||
export * from "./cookies"
|
||||
export * from "./automation"
|
||||
export * from "./layout"
|
||||
export * from "./query"
|
||||
export * from "./role"
|
||||
export * from "./plugins"
|
||||
export * from "./apikeys"
|
||||
|
|
|
@ -3,3 +3,7 @@ import { Layout } from "../../documents"
|
|||
export interface SaveLayoutRequest extends Layout {}
|
||||
|
||||
export interface SaveLayoutResponse extends Layout {}
|
||||
|
||||
export interface DeleteLayoutResponse {
|
||||
message: string
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { PluginSource } from "../../documents"
|
||||
import { PluginSource, Plugin } from "../../documents"
|
||||
|
||||
export interface UploadPluginRequest {}
|
||||
export interface UploadPluginResponse {
|
||||
message: string
|
||||
plugins: Plugin[]
|
||||
}
|
||||
|
||||
export interface CreatePluginRequest {
|
||||
source: PluginSource
|
||||
|
@ -10,3 +16,9 @@ export interface CreatePluginRequest {
|
|||
export interface CreatePluginResponse {
|
||||
plugin: any
|
||||
}
|
||||
|
||||
export type FetchPluginResponse = Plugin[]
|
||||
|
||||
export interface DeletePluginResponse {
|
||||
message: string
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import { QueryPreview, QuerySchema } from "../../documents"
|
||||
|
||||
export interface PreviewQueryRequest extends QueryPreview {}
|
||||
|
||||
export interface PreviewQueryResponse {
|
||||
rows: any[]
|
||||
nestedSchemaFields: { [key: string]: { [key: string]: string | QuerySchema } }
|
||||
schema: { [key: string]: string | QuerySchema }
|
||||
info: any
|
||||
extra: any
|
||||
}
|
||||
|
||||
export interface ExecuteQueryRequest {
|
||||
parameters?: Record<string, string>
|
||||
pagination?: any
|
||||
}
|
||||
|
||||
export interface ExecuteQueryResponse {
|
||||
data: Record<string, any>[]
|
||||
}
|
|
@ -18,7 +18,7 @@ export interface FindRoleResponse extends Role {}
|
|||
|
||||
export type FetchRolesResponse = Role[]
|
||||
|
||||
export interface DestroyRoleResponse {
|
||||
export interface DeleteRoleResponse {
|
||||
message: string
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export * from "./environment"
|
||||
export * from "./status"
|
||||
export * from "./ops"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
export interface LogOpsRequest {
|
||||
message: string
|
||||
data?: any
|
||||
}
|
||||
|
||||
export interface ErrorOpsRequest {
|
||||
message: string
|
||||
}
|
|
@ -19,3 +19,4 @@ export * from "./snippet"
|
|||
export * from "./rowAction"
|
||||
export * from "./theme"
|
||||
export * from "./deployment"
|
||||
export * from "./metadata"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export enum MetadataType {
|
||||
AUTOMATION_TEST_INPUT = "automationTestInput",
|
||||
AUTOMATION_TEST_HISTORY = "automationTestHistory",
|
||||
}
|
|
@ -24,3 +24,20 @@ export interface Screen extends Document {
|
|||
name?: string
|
||||
pluginAdded?: boolean
|
||||
}
|
||||
|
||||
export interface ScreenRoutesViewOutput extends Document {
|
||||
id: string
|
||||
routing: ScreenRouting
|
||||
}
|
||||
|
||||
export type ScreenRoutingJson = Record<
|
||||
string,
|
||||
{
|
||||
subpaths: Record<
|
||||
string,
|
||||
{
|
||||
screens: Record<string, string>
|
||||
}
|
||||
>
|
||||
}
|
||||
>
|
||||
|
|
|
@ -12,9 +12,9 @@ export enum PluginSource {
|
|||
URL = "URL",
|
||||
FILE = "File Upload",
|
||||
}
|
||||
export interface FileType {
|
||||
path: string
|
||||
name: string
|
||||
export interface KoaFile {
|
||||
path: string | null
|
||||
name: string | null
|
||||
}
|
||||
|
||||
export interface Plugin extends Document {
|
||||
|
|
|
@ -36,3 +36,22 @@ export enum PermissionSource {
|
|||
INHERITED = "INHERITED",
|
||||
BASE = "BASE",
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
type: PermissionType
|
||||
level: PermissionLevel
|
||||
}
|
||||
|
||||
export interface BuiltinPermission {
|
||||
_id: BuiltinPermissionID
|
||||
name: string
|
||||
permissions: Permission[]
|
||||
}
|
||||
|
||||
export type BuiltinPermissions = {
|
||||
[key in keyof typeof BuiltinPermissionID]: {
|
||||
_id: (typeof BuiltinPermissionID)[key]
|
||||
name: string
|
||||
permissions: Permission[]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue