Merge pull request #15100 from Budibase/chore/api-typing
API typing - app service A -> D
This commit is contained in:
commit
10cf58e9a1
|
@ -1,16 +1,22 @@
|
||||||
import { events, context } from "@budibase/backend-core"
|
import { events, context } from "@budibase/backend-core"
|
||||||
import { AnalyticsPingRequest, App, PingSource } from "@budibase/types"
|
import {
|
||||||
|
AnalyticsPingRequest,
|
||||||
|
App,
|
||||||
|
PingSource,
|
||||||
|
Ctx,
|
||||||
|
AnalyticsEnabledResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
import { DocumentType, isDevAppID } from "../../db/utils"
|
import { DocumentType, isDevAppID } from "../../db/utils"
|
||||||
|
|
||||||
export const isEnabled = async (ctx: any) => {
|
export const isEnabled = async (ctx: Ctx<void, AnalyticsEnabledResponse>) => {
|
||||||
const enabled = await events.analytics.enabled()
|
const enabled = await events.analytics.enabled()
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
enabled,
|
enabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ping = async (ctx: any) => {
|
export const ping = async (ctx: Ctx<AnalyticsPingRequest, void>) => {
|
||||||
const body = ctx.request.body as AnalyticsPingRequest
|
const body = ctx.request.body
|
||||||
|
|
||||||
switch (body.source) {
|
switch (body.source) {
|
||||||
case PingSource.APP: {
|
case PingSource.APP: {
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
||||||
import { BBContext, Document } from "@budibase/types"
|
import {
|
||||||
|
Document,
|
||||||
|
UserCtx,
|
||||||
|
ApiKeyDoc,
|
||||||
|
ApiKeyFetchResponse,
|
||||||
|
UpdateApiKeyRequest,
|
||||||
|
UpdateApiKeyResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
const KEYS_DOC = dbCore.StaticDatabases.GLOBAL.docs.apiKeys
|
const KEYS_DOC = dbCore.StaticDatabases.GLOBAL.docs.apiKeys
|
||||||
|
|
||||||
async function getBuilderMainDoc() {
|
async function getBuilderMainDoc() {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
try {
|
const doc = await db.tryGet<ApiKeyDoc>(KEYS_DOC)
|
||||||
return await db.get<any>(KEYS_DOC)
|
if (!doc) {
|
||||||
} catch (err) {
|
|
||||||
// doesn't exist yet, nothing to get
|
|
||||||
return {
|
return {
|
||||||
_id: KEYS_DOC,
|
_id: KEYS_DOC,
|
||||||
|
apiKeys: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return doc
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setBuilderMainDoc(doc: Document) {
|
async function setBuilderMainDoc(doc: Document) {
|
||||||
|
@ -22,7 +29,7 @@ async function setBuilderMainDoc(doc: Document) {
|
||||||
return db.put(doc)
|
return db.put(doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetch(ctx: BBContext) {
|
export async function fetch(ctx: UserCtx<void, ApiKeyFetchResponse>) {
|
||||||
try {
|
try {
|
||||||
const mainDoc = await getBuilderMainDoc()
|
const mainDoc = await getBuilderMainDoc()
|
||||||
ctx.body = mainDoc.apiKeys ? mainDoc.apiKeys : {}
|
ctx.body = mainDoc.apiKeys ? mainDoc.apiKeys : {}
|
||||||
|
@ -32,7 +39,9 @@ export async function fetch(ctx: BBContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(ctx: BBContext) {
|
export async function update(
|
||||||
|
ctx: UserCtx<UpdateApiKeyRequest, UpdateApiKeyResponse>
|
||||||
|
) {
|
||||||
const key = ctx.params.key
|
const key = ctx.params.key
|
||||||
const value = ctx.request.body.value
|
const value = ctx.request.body.value
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,15 @@ import {
|
||||||
BBReferenceFieldSubType,
|
BBReferenceFieldSubType,
|
||||||
Row,
|
Row,
|
||||||
BBRequest,
|
BBRequest,
|
||||||
|
SyncAppResponse,
|
||||||
|
CreateAppResponse,
|
||||||
|
FetchAppsResponse,
|
||||||
|
UpdateAppClientResponse,
|
||||||
|
RevertAppClientResponse,
|
||||||
|
DeleteAppResponse,
|
||||||
|
ImportToUpdateAppRequest,
|
||||||
|
ImportToUpdateAppResponse,
|
||||||
|
SetRevertableAppVersionRequest,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
|
@ -166,7 +175,7 @@ async function createInstance(appId: string, template: AppTemplate) {
|
||||||
return { _id: appId }
|
return { _id: appId }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addSampleData = async (ctx: UserCtx) => {
|
export const addSampleData = async (ctx: UserCtx<void, void>) => {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -182,7 +191,7 @@ export const addSampleData = async (ctx: UserCtx) => {
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetch(ctx: UserCtx<void, App[]>) {
|
export async function fetch(ctx: UserCtx<void, FetchAppsResponse>) {
|
||||||
ctx.body = await sdk.applications.fetch(
|
ctx.body = await sdk.applications.fetch(
|
||||||
ctx.query.status as AppStatus,
|
ctx.query.status as AppStatus,
|
||||||
ctx.user
|
ctx.user
|
||||||
|
@ -242,7 +251,9 @@ export async function fetchAppPackage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function performAppCreate(ctx: UserCtx<CreateAppRequest, App>) {
|
async function performAppCreate(
|
||||||
|
ctx: UserCtx<CreateAppRequest, CreateAppResponse>
|
||||||
|
) {
|
||||||
const apps = (await dbCore.getAllApps({ dev: true })) as App[]
|
const apps = (await dbCore.getAllApps({ dev: true })) as App[]
|
||||||
const { body } = ctx.request
|
const { body } = ctx.request
|
||||||
const { name, url, encryptionPassword, templateKey } = body
|
const { name, url, encryptionPassword, templateKey } = body
|
||||||
|
@ -510,7 +521,9 @@ async function appPostCreate(ctx: UserCtx<CreateAppRequest, App>, app: App) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create(ctx: UserCtx<CreateAppRequest, App>) {
|
export async function create(
|
||||||
|
ctx: UserCtx<CreateAppRequest, CreateAppResponse>
|
||||||
|
) {
|
||||||
const newApplication = await quotas.addApp(() => performAppCreate(ctx))
|
const newApplication = await quotas.addApp(() => performAppCreate(ctx))
|
||||||
await appPostCreate(ctx, newApplication)
|
await appPostCreate(ctx, newApplication)
|
||||||
await cache.bustCache(cache.CacheKey.CHECKLIST)
|
await cache.bustCache(cache.CacheKey.CHECKLIST)
|
||||||
|
@ -553,7 +566,9 @@ export async function update(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateClient(ctx: UserCtx) {
|
export async function updateClient(
|
||||||
|
ctx: UserCtx<void, UpdateAppClientResponse>
|
||||||
|
) {
|
||||||
// Get current app version
|
// Get current app version
|
||||||
const application = await sdk.applications.metadata.get()
|
const application = await sdk.applications.metadata.get()
|
||||||
const currentVersion = application.version
|
const currentVersion = application.version
|
||||||
|
@ -581,7 +596,9 @@ export async function updateClient(ctx: UserCtx) {
|
||||||
ctx.body = app
|
ctx.body = app
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function revertClient(ctx: UserCtx) {
|
export async function revertClient(
|
||||||
|
ctx: UserCtx<void, RevertAppClientResponse>
|
||||||
|
) {
|
||||||
// Check app can be reverted
|
// Check app can be reverted
|
||||||
const application = await sdk.applications.metadata.get()
|
const application = await sdk.applications.metadata.get()
|
||||||
if (!application.revertableVersion) {
|
if (!application.revertableVersion) {
|
||||||
|
@ -668,7 +685,7 @@ async function postDestroyApp(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: UserCtx) {
|
export async function destroy(ctx: UserCtx<void, DeleteAppResponse>) {
|
||||||
await preDestroyApp(ctx)
|
await preDestroyApp(ctx)
|
||||||
const result = await destroyApp(ctx)
|
const result = await destroyApp(ctx)
|
||||||
await postDestroyApp(ctx)
|
await postDestroyApp(ctx)
|
||||||
|
@ -676,7 +693,7 @@ export async function destroy(ctx: UserCtx) {
|
||||||
ctx.body = result
|
ctx.body = result
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function unpublish(ctx: UserCtx) {
|
export async function unpublish(ctx: UserCtx<void, void>) {
|
||||||
const prodAppId = dbCore.getProdAppID(ctx.params.appId)
|
const prodAppId = dbCore.getProdAppID(ctx.params.appId)
|
||||||
const dbExists = await dbCore.dbExists(prodAppId)
|
const dbExists = await dbCore.dbExists(prodAppId)
|
||||||
|
|
||||||
|
@ -692,7 +709,7 @@ export async function unpublish(ctx: UserCtx) {
|
||||||
builderSocket?.emitAppUnpublish(ctx)
|
builderSocket?.emitAppUnpublish(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sync(ctx: UserCtx) {
|
export async function sync(ctx: UserCtx<void, SyncAppResponse>) {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
try {
|
try {
|
||||||
ctx.body = await sdk.applications.syncApp(appId)
|
ctx.body = await sdk.applications.syncApp(appId)
|
||||||
|
@ -701,10 +718,12 @@ export async function sync(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function importToApp(ctx: UserCtx) {
|
export async function importToApp(
|
||||||
|
ctx: UserCtx<ImportToUpdateAppRequest, ImportToUpdateAppResponse>
|
||||||
|
) {
|
||||||
const { appId } = ctx.params
|
const { appId } = ctx.params
|
||||||
const appExport = ctx.request.files?.appExport
|
const appExport = ctx.request.files?.appExport
|
||||||
const password = ctx.request.body.encryptionPassword as string
|
const password = ctx.request.body.encryptionPassword
|
||||||
if (!appExport) {
|
if (!appExport) {
|
||||||
ctx.throw(400, "Must supply app export to import")
|
ctx.throw(400, "Must supply app export to import")
|
||||||
}
|
}
|
||||||
|
@ -811,7 +830,7 @@ export async function updateAppPackage(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setRevertableVersion(
|
export async function setRevertableVersion(
|
||||||
ctx: UserCtx<{ revertableVersion: string }, App>
|
ctx: UserCtx<SetRevertableAppVersionRequest, void>
|
||||||
) {
|
) {
|
||||||
if (!env.isDev()) {
|
if (!env.isDev()) {
|
||||||
ctx.status = 403
|
ctx.status = 403
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { outputProcessing } from "../../utilities/rowProcessor"
|
||||||
import { InternalTables } from "../../db/utils"
|
import { InternalTables } from "../../db/utils"
|
||||||
import { getFullUser } from "../../utilities/users"
|
import { getFullUser } from "../../utilities/users"
|
||||||
import { roles, context, db as dbCore } from "@budibase/backend-core"
|
import { roles, context, db as dbCore } from "@budibase/backend-core"
|
||||||
import { ContextUser, Row, UserCtx } from "@budibase/types"
|
import { AppSelfResponse, ContextUser, UserCtx } from "@budibase/types"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
import { processUser } from "../../utilities/global"
|
import { processUser } from "../../utilities/global"
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ const addSessionAttributesToUser = (ctx: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSelf(ctx: UserCtx) {
|
export async function fetchSelf(ctx: UserCtx<void, AppSelfResponse>) {
|
||||||
let userId = ctx.user.userId || ctx.user._id
|
let userId = ctx.user.userId || ctx.user._id
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if (!userId || !ctx.isAuthenticated) {
|
if (!userId || !ctx.isAuthenticated) {
|
||||||
|
@ -45,9 +45,9 @@ export async function fetchSelf(ctx: UserCtx) {
|
||||||
try {
|
try {
|
||||||
const userTable = await sdk.tables.getTable(InternalTables.USER_METADATA)
|
const userTable = await sdk.tables.getTable(InternalTables.USER_METADATA)
|
||||||
// specifically needs to make sure is enriched
|
// specifically needs to make sure is enriched
|
||||||
ctx.body = await outputProcessing(userTable, user as Row)
|
ctx.body = await outputProcessing(userTable, user)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
let response
|
let response: ContextUser | {}
|
||||||
// user didn't exist in app, don't pretend they do
|
// user didn't exist in app, don't pretend they do
|
||||||
if (user.roleId === PUBLIC_ROLE) {
|
if (user.roleId === PUBLIC_ROLE) {
|
||||||
response = {}
|
response = {}
|
||||||
|
|
|
@ -9,10 +9,25 @@ import {
|
||||||
App,
|
App,
|
||||||
Automation,
|
Automation,
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationResults,
|
|
||||||
UserCtx,
|
UserCtx,
|
||||||
DeleteAutomationResponse,
|
DeleteAutomationResponse,
|
||||||
FetchAutomationResponse,
|
FetchAutomationResponse,
|
||||||
|
GetAutomationTriggerDefinitionsResponse,
|
||||||
|
GetAutomationStepDefinitionsResponse,
|
||||||
|
GetAutomationActionDefinitionsResponse,
|
||||||
|
FindAutomationResponse,
|
||||||
|
UpdateAutomationRequest,
|
||||||
|
UpdateAutomationResponse,
|
||||||
|
CreateAutomationRequest,
|
||||||
|
CreateAutomationResponse,
|
||||||
|
SearchAutomationLogsRequest,
|
||||||
|
SearchAutomationLogsResponse,
|
||||||
|
ClearAutomationLogRequest,
|
||||||
|
ClearAutomationLogResponse,
|
||||||
|
TriggerAutomationRequest,
|
||||||
|
TriggerAutomationResponse,
|
||||||
|
TestAutomationRequest,
|
||||||
|
TestAutomationResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getActionDefinitions as actionDefs } from "../../automations/actions"
|
import { getActionDefinitions as actionDefs } from "../../automations/actions"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
|
@ -34,7 +49,7 @@ function getTriggerDefinitions() {
|
||||||
*************************/
|
*************************/
|
||||||
|
|
||||||
export async function create(
|
export async function create(
|
||||||
ctx: UserCtx<Automation, { message: string; automation: Automation }>
|
ctx: UserCtx<CreateAutomationRequest, CreateAutomationResponse>
|
||||||
) {
|
) {
|
||||||
let automation = ctx.request.body
|
let automation = ctx.request.body
|
||||||
automation.appId = ctx.appId
|
automation.appId = ctx.appId
|
||||||
|
@ -55,7 +70,9 @@ export async function create(
|
||||||
builderSocket?.emitAutomationUpdate(ctx, automation)
|
builderSocket?.emitAutomationUpdate(ctx, automation)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(ctx: UserCtx) {
|
export async function update(
|
||||||
|
ctx: UserCtx<UpdateAutomationRequest, UpdateAutomationResponse>
|
||||||
|
) {
|
||||||
let automation = ctx.request.body
|
let automation = ctx.request.body
|
||||||
automation.appId = ctx.appId
|
automation.appId = ctx.appId
|
||||||
|
|
||||||
|
@ -80,7 +97,7 @@ export async function fetch(ctx: UserCtx<void, FetchAutomationResponse>) {
|
||||||
ctx.body = { automations }
|
ctx.body = { automations }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function find(ctx: UserCtx) {
|
export async function find(ctx: UserCtx<void, FindAutomationResponse>) {
|
||||||
ctx.body = await sdk.automations.get(ctx.params.id)
|
ctx.body = await sdk.automations.get(ctx.params.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,11 +113,15 @@ export async function destroy(ctx: UserCtx<void, DeleteAutomationResponse>) {
|
||||||
builderSocket?.emitAutomationDeletion(ctx, automationId)
|
builderSocket?.emitAutomationDeletion(ctx, automationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logSearch(ctx: UserCtx) {
|
export async function logSearch(
|
||||||
|
ctx: UserCtx<SearchAutomationLogsRequest, SearchAutomationLogsResponse>
|
||||||
|
) {
|
||||||
ctx.body = await automations.logs.logSearch(ctx.request.body)
|
ctx.body = await automations.logs.logSearch(ctx.request.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clearLogError(ctx: UserCtx) {
|
export async function clearLogError(
|
||||||
|
ctx: UserCtx<ClearAutomationLogRequest, ClearAutomationLogResponse>
|
||||||
|
) {
|
||||||
const { automationId, appId } = ctx.request.body
|
const { automationId, appId } = ctx.request.body
|
||||||
await context.doInAppContext(appId, async () => {
|
await context.doInAppContext(appId, async () => {
|
||||||
const db = context.getProdAppDB()
|
const db = context.getProdAppDB()
|
||||||
|
@ -119,15 +140,21 @@ export async function clearLogError(ctx: UserCtx) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActionList(ctx: UserCtx) {
|
export async function getActionList(
|
||||||
|
ctx: UserCtx<void, GetAutomationActionDefinitionsResponse>
|
||||||
|
) {
|
||||||
ctx.body = await getActionDefinitions()
|
ctx.body = await getActionDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTriggerList(ctx: UserCtx) {
|
export async function getTriggerList(
|
||||||
|
ctx: UserCtx<void, GetAutomationTriggerDefinitionsResponse>
|
||||||
|
) {
|
||||||
ctx.body = getTriggerDefinitions()
|
ctx.body = getTriggerDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getDefinitionList(ctx: UserCtx) {
|
export async function getDefinitionList(
|
||||||
|
ctx: UserCtx<void, GetAutomationStepDefinitionsResponse>
|
||||||
|
) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
trigger: getTriggerDefinitions(),
|
trigger: getTriggerDefinitions(),
|
||||||
action: await getActionDefinitions(),
|
action: await getActionDefinitions(),
|
||||||
|
@ -140,14 +167,16 @@ export async function getDefinitionList(ctx: UserCtx) {
|
||||||
* *
|
* *
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
export async function trigger(ctx: UserCtx) {
|
export async function trigger(
|
||||||
|
ctx: UserCtx<TriggerAutomationRequest, TriggerAutomationResponse>
|
||||||
|
) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
let automation = await db.get<Automation>(ctx.params.id)
|
let automation = await db.get<Automation>(ctx.params.id)
|
||||||
|
|
||||||
let hasCollectStep = sdk.automations.utils.checkForCollectStep(automation)
|
let hasCollectStep = sdk.automations.utils.checkForCollectStep(automation)
|
||||||
if (hasCollectStep && (await features.isSyncAutomationsEnabled())) {
|
if (hasCollectStep && (await features.isSyncAutomationsEnabled())) {
|
||||||
try {
|
try {
|
||||||
const response: AutomationResults = await triggers.externalTrigger(
|
const response = await triggers.externalTrigger(
|
||||||
automation,
|
automation,
|
||||||
{
|
{
|
||||||
fields: ctx.request.body.fields,
|
fields: ctx.request.body.fields,
|
||||||
|
@ -158,6 +187,10 @@ export async function trigger(ctx: UserCtx) {
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!("steps" in response)) {
|
||||||
|
ctx.throw(400, "Unable to collect response")
|
||||||
|
}
|
||||||
|
|
||||||
let collectedValue = response.steps.find(
|
let collectedValue = response.steps.find(
|
||||||
step => step.stepId === AutomationActionStepId.COLLECT
|
step => step.stepId === AutomationActionStepId.COLLECT
|
||||||
)
|
)
|
||||||
|
@ -185,7 +218,7 @@ export async function trigger(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareTestInput(input: any) {
|
function prepareTestInput(input: TestAutomationRequest) {
|
||||||
// prepare the test parameters
|
// prepare the test parameters
|
||||||
if (input.id && input.row) {
|
if (input.id && input.row) {
|
||||||
input.row._id = input.id
|
input.row._id = input.id
|
||||||
|
@ -196,7 +229,9 @@ function prepareTestInput(input: any) {
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function test(ctx: UserCtx) {
|
export async function test(
|
||||||
|
ctx: UserCtx<TestAutomationRequest, TestAutomationResponse>
|
||||||
|
) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
let automation = await db.get<Automation>(ctx.params.id)
|
let automation = await db.get<Automation>(ctx.params.id)
|
||||||
await setTestFlag(automation._id!)
|
await setTestFlag(automation._id!)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
import { events, context, db } from "@budibase/backend-core"
|
import { events, context, db } from "@budibase/backend-core"
|
||||||
import { DocumentType } from "../../db/utils"
|
import { DocumentType } from "../../db/utils"
|
||||||
import { App, Ctx } from "@budibase/types"
|
import {
|
||||||
|
App,
|
||||||
|
Ctx,
|
||||||
|
ExportAppDumpRequest,
|
||||||
|
ExportAppDumpResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
interface ExportAppDumpRequest {
|
export async function exportAppDump(
|
||||||
excludeRows: boolean
|
ctx: Ctx<ExportAppDumpRequest, ExportAppDumpResponse>
|
||||||
encryptPassword?: string
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
export async function exportAppDump(ctx: Ctx<ExportAppDumpRequest>) {
|
|
||||||
const { appId } = ctx.query as any
|
const { appId } = ctx.query as any
|
||||||
const { excludeRows, encryptPassword } = ctx.request.body
|
const { excludeRows, encryptPassword } = ctx.request.body
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
import { DocumentType } from "../../db/utils"
|
import { DocumentType } from "../../db/utils"
|
||||||
import { App, Plugin, UserCtx } from "@budibase/types"
|
import {
|
||||||
|
App,
|
||||||
|
FetchComponentDefinitionResponse,
|
||||||
|
Plugin,
|
||||||
|
UserCtx,
|
||||||
|
} from "@budibase/types"
|
||||||
import { db as dbCore, context, tenancy } from "@budibase/backend-core"
|
import { db as dbCore, context, tenancy } from "@budibase/backend-core"
|
||||||
import { getComponentLibraryManifest } from "../../utilities/fileSystem"
|
import { getComponentLibraryManifest } from "../../utilities/fileSystem"
|
||||||
|
|
||||||
export async function fetchAppComponentDefinitions(ctx: UserCtx) {
|
export async function fetchAppComponentDefinitions(
|
||||||
|
ctx: UserCtx<void, FetchComponentDefinitionResponse>
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const app = await db.get<App>(DocumentType.APP_METADATA)
|
const app = await db.get<App>(DocumentType.APP_METADATA)
|
||||||
|
|
|
@ -23,13 +23,17 @@ import {
|
||||||
Table,
|
Table,
|
||||||
RowValue,
|
RowValue,
|
||||||
DynamicVariable,
|
DynamicVariable,
|
||||||
|
FetchDatasourcesResponse,
|
||||||
|
FindDatasourcesResponse,
|
||||||
|
DeleteDatasourceResponse,
|
||||||
|
FetchExternalSchemaResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
import { builderSocket } from "../../websockets"
|
import { builderSocket } from "../../websockets"
|
||||||
import { isEqual } from "lodash"
|
import { isEqual } from "lodash"
|
||||||
import { processTable } from "../../sdk/app/tables/getters"
|
import { processTable } from "../../sdk/app/tables/getters"
|
||||||
|
|
||||||
export async function fetch(ctx: UserCtx) {
|
export async function fetch(ctx: UserCtx<void, FetchDatasourcesResponse>) {
|
||||||
ctx.body = await sdk.datasources.fetch()
|
ctx.body = await sdk.datasources.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +264,7 @@ async function destroyInternalTablesBySourceId(datasourceId: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: UserCtx) {
|
export async function destroy(ctx: UserCtx<void, DeleteDatasourceResponse>) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const datasourceId = ctx.params.datasourceId
|
const datasourceId = ctx.params.datasourceId
|
||||||
|
|
||||||
|
@ -291,12 +295,14 @@ export async function destroy(ctx: UserCtx) {
|
||||||
builderSocket?.emitDatasourceDeletion(ctx, datasourceId)
|
builderSocket?.emitDatasourceDeletion(ctx, datasourceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function find(ctx: UserCtx) {
|
export async function find(ctx: UserCtx<void, FindDatasourcesResponse>) {
|
||||||
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
||||||
ctx.body = await sdk.datasources.removeSecretSingle(datasource)
|
ctx.body = await sdk.datasources.removeSecretSingle(datasource)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getExternalSchema(ctx: UserCtx) {
|
export async function getExternalSchema(
|
||||||
|
ctx: UserCtx<void, FetchExternalSchemaResponse>
|
||||||
|
) {
|
||||||
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
||||||
const enrichedDatasource = await sdk.datasources.getAndMergeDatasource(
|
const enrichedDatasource = await sdk.datasources.getAndMergeDatasource(
|
||||||
datasource
|
datasource
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { context, utils } from "@budibase/backend-core"
|
import { context, utils } from "@budibase/backend-core"
|
||||||
|
import { DeploymentStatus } from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to pass around information about the deployment that is occurring
|
* This is used to pass around information about the deployment that is occurring
|
||||||
|
@ -6,7 +7,7 @@ import { context, utils } from "@budibase/backend-core"
|
||||||
export default class Deployment {
|
export default class Deployment {
|
||||||
_id: string
|
_id: string
|
||||||
verification: any
|
verification: any
|
||||||
status?: string
|
status?: DeploymentStatus
|
||||||
err?: any
|
err?: any
|
||||||
appUrl?: string
|
appUrl?: string
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ export default class Deployment {
|
||||||
return this.verification
|
return this.verification
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus(status: string, err?: any) {
|
setStatus(status: DeploymentStatus, err?: any) {
|
||||||
this.status = status
|
this.status = status
|
||||||
if (err) {
|
if (err) {
|
||||||
this.err = err
|
this.err = err
|
||||||
|
|
|
@ -7,20 +7,26 @@ import {
|
||||||
enableCronTrigger,
|
enableCronTrigger,
|
||||||
} from "../../../automations/utils"
|
} from "../../../automations/utils"
|
||||||
import { backups } from "@budibase/pro"
|
import { backups } from "@budibase/pro"
|
||||||
import { App, AppBackupTrigger } from "@budibase/types"
|
import {
|
||||||
|
App,
|
||||||
|
AppBackupTrigger,
|
||||||
|
DeploymentDoc,
|
||||||
|
FetchDeploymentResponse,
|
||||||
|
PublishAppResponse,
|
||||||
|
UserCtx,
|
||||||
|
DeploymentStatus,
|
||||||
|
DeploymentProgressResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import { builderSocket } from "../../../websockets"
|
import { builderSocket } from "../../../websockets"
|
||||||
|
|
||||||
// the max time we can wait for an invalidation to complete before considering it failed
|
// the max time we can wait for an invalidation to complete before considering it failed
|
||||||
const MAX_PENDING_TIME_MS = 30 * 60000
|
const MAX_PENDING_TIME_MS = 30 * 60000
|
||||||
const DeploymentStatus = {
|
|
||||||
SUCCESS: "SUCCESS",
|
|
||||||
PENDING: "PENDING",
|
|
||||||
FAILURE: "FAILURE",
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks that deployments are in a good state, any pending will be updated
|
// checks that deployments are in a good state, any pending will be updated
|
||||||
async function checkAllDeployments(deployments: any) {
|
async function checkAllDeployments(
|
||||||
|
deployments: any
|
||||||
|
): Promise<{ updated: boolean; deployments: DeploymentDoc }> {
|
||||||
let updated = false
|
let updated = false
|
||||||
let deployment: any
|
let deployment: any
|
||||||
for (deployment of Object.values(deployments.history)) {
|
for (deployment of Object.values(deployments.history)) {
|
||||||
|
@ -96,7 +102,9 @@ async function initDeployedApp(prodAppId: any) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDeployments(ctx: any) {
|
export async function fetchDeployments(
|
||||||
|
ctx: UserCtx<void, FetchDeploymentResponse>
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const deploymentDoc = await db.get(DocumentType.DEPLOYMENTS)
|
const deploymentDoc = await db.get(DocumentType.DEPLOYMENTS)
|
||||||
|
@ -104,17 +112,24 @@ export async function fetchDeployments(ctx: any) {
|
||||||
if (updated) {
|
if (updated) {
|
||||||
await db.put(deployments)
|
await db.put(deployments)
|
||||||
}
|
}
|
||||||
ctx.body = Object.values(deployments.history).reverse()
|
ctx.body = deployments.history
|
||||||
|
? Object.values(deployments.history).reverse()
|
||||||
|
: []
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.body = []
|
ctx.body = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deploymentProgress(ctx: any) {
|
export async function deploymentProgress(
|
||||||
|
ctx: UserCtx<void, DeploymentProgressResponse>
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const deploymentDoc = await db.get<any>(DocumentType.DEPLOYMENTS)
|
const deploymentDoc = await db.get<DeploymentDoc>(DocumentType.DEPLOYMENTS)
|
||||||
ctx.body = deploymentDoc[ctx.params.deploymentId]
|
if (!deploymentDoc.history?.[ctx.params.deploymentId]) {
|
||||||
|
ctx.throw(404, "No deployment found")
|
||||||
|
}
|
||||||
|
ctx.body = deploymentDoc.history?.[ctx.params.deploymentId]
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(
|
ctx.throw(
|
||||||
500,
|
500,
|
||||||
|
@ -123,7 +138,9 @@ export async function deploymentProgress(ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const publishApp = async function (ctx: any) {
|
export const publishApp = async function (
|
||||||
|
ctx: UserCtx<void, PublishAppResponse>
|
||||||
|
) {
|
||||||
let deployment = new Deployment()
|
let deployment = new Deployment()
|
||||||
console.log("Deployment object created")
|
console.log("Deployment object created")
|
||||||
deployment.setStatus(DeploymentStatus.PENDING)
|
deployment.setStatus(DeploymentStatus.PENDING)
|
||||||
|
|
|
@ -11,7 +11,13 @@ import {
|
||||||
db as dbCore,
|
db as dbCore,
|
||||||
cache,
|
cache,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import { App } from "@budibase/types"
|
import {
|
||||||
|
App,
|
||||||
|
ClearDevLockResponse,
|
||||||
|
Ctx,
|
||||||
|
GetVersionResponse,
|
||||||
|
RevertAppResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
async function redirect(
|
async function redirect(
|
||||||
ctx: any,
|
ctx: any,
|
||||||
|
@ -69,7 +75,7 @@ export function buildRedirectDelete(path: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function clearLock(ctx: any) {
|
export async function clearLock(ctx: Ctx<void, ClearDevLockResponse>) {
|
||||||
const { appId } = ctx.params
|
const { appId } = ctx.params
|
||||||
try {
|
try {
|
||||||
await redisClearLock(appId, ctx.user)
|
await redisClearLock(appId, ctx.user)
|
||||||
|
@ -81,7 +87,7 @@ export async function clearLock(ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function revert(ctx: any) {
|
export async function revert(ctx: Ctx<void, RevertAppResponse>) {
|
||||||
const { appId } = ctx.params
|
const { appId } = ctx.params
|
||||||
const productionAppId = dbCore.getProdAppID(appId)
|
const productionAppId = dbCore.getProdAppID(appId)
|
||||||
|
|
||||||
|
@ -131,7 +137,7 @@ export async function revert(ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBudibaseVersion(ctx: any) {
|
export async function getBudibaseVersion(ctx: Ctx<void, GetVersionResponse>) {
|
||||||
const version = envCore.VERSION
|
const version = envCore.VERSION
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
version,
|
version,
|
||||||
|
|
|
@ -94,12 +94,16 @@ export async function trigger(ctx: BBContext) {
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (triggers.isAutomationResults(response)) {
|
||||||
let collectedValue = response.steps.find(
|
let collectedValue = response.steps.find(
|
||||||
(step: any) => step.stepId === AutomationActionStepId.COLLECT
|
(step: any) => step.stepId === AutomationActionStepId.COLLECT
|
||||||
)
|
)
|
||||||
|
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
ctx.body = collectedValue.outputs
|
ctx.body = collectedValue?.outputs
|
||||||
|
} else {
|
||||||
|
ctx.throw(400, "Automation did not have a collect block.")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await triggers.externalTrigger(target, {
|
await triggers.externalTrigger(target, {
|
||||||
body: ctx.request.body,
|
body: ctx.request.body,
|
||||||
|
|
|
@ -102,7 +102,9 @@ if (env.SELF_HOSTED) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActionDefinitions() {
|
export async function getActionDefinitions(): Promise<
|
||||||
|
Record<keyof typeof AutomationActionStepId, AutomationStepDefinition>
|
||||||
|
> {
|
||||||
if (await features.flags.isEnabled(FeatureFlag.AUTOMATION_BRANCHING)) {
|
if (await features.flags.isEnabled(FeatureFlag.AUTOMATION_BRANCHING)) {
|
||||||
BUILTIN_ACTION_DEFINITIONS["BRANCH"] = branch.definition
|
BUILTIN_ACTION_DEFINITIONS["BRANCH"] = branch.definition
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
AutomationStepDefinition,
|
AutomationStepDefinition,
|
||||||
AutomationStepType,
|
AutomationStepType,
|
||||||
AutomationIOType,
|
AutomationIOType,
|
||||||
AutomationResults,
|
|
||||||
Automation,
|
Automation,
|
||||||
AutomationCustomIOType,
|
AutomationCustomIOType,
|
||||||
TriggerAutomationStepInputs,
|
TriggerAutomationStepInputs,
|
||||||
|
@ -78,7 +77,7 @@ export async function run({
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
let automation = await db.get<Automation>(inputs.automation.automationId)
|
let automation = await db.get<Automation>(inputs.automation.automationId)
|
||||||
|
|
||||||
const response: AutomationResults = await triggers.externalTrigger(
|
const response = await triggers.externalTrigger(
|
||||||
automation,
|
automation,
|
||||||
{
|
{
|
||||||
fields: { ...fieldParams },
|
fields: { ...fieldParams },
|
||||||
|
@ -88,10 +87,14 @@ export async function run({
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (triggers.isAutomationResults(response)) {
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
value: response.steps,
|
value: response.steps,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error("Automation did not have a collect block")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as triggers from "../triggers"
|
||||||
import { loopAutomation } from "../../tests/utilities/structures"
|
import { loopAutomation } from "../../tests/utilities/structures"
|
||||||
import { context } from "@budibase/backend-core"
|
import { context } from "@budibase/backend-core"
|
||||||
import * as setup from "./utilities"
|
import * as setup from "./utilities"
|
||||||
import { Table, LoopStepType } from "@budibase/types"
|
import { Table, LoopStepType, AutomationResults } from "@budibase/types"
|
||||||
import * as loopUtils from "../loopUtils"
|
import * as loopUtils from "../loopUtils"
|
||||||
import { LoopInput } from "../../definitions/automations"
|
import { LoopInput } from "../../definitions/automations"
|
||||||
|
|
||||||
|
@ -20,15 +20,19 @@ describe("Attempt to run a basic loop automation", () => {
|
||||||
|
|
||||||
afterAll(setup.afterAll)
|
afterAll(setup.afterAll)
|
||||||
|
|
||||||
async function runLoop(loopOpts?: LoopInput) {
|
async function runLoop(loopOpts?: LoopInput): Promise<AutomationResults> {
|
||||||
const appId = config.getAppId()
|
const appId = config.getAppId()
|
||||||
return await context.doInAppContext(appId, async () => {
|
return await context.doInAppContext(appId, async () => {
|
||||||
const params = { fields: { appId } }
|
const params = { fields: { appId } }
|
||||||
return await triggers.externalTrigger(
|
const result = await triggers.externalTrigger(
|
||||||
loopAutomation(table._id!, loopOpts),
|
loopAutomation(table._id!, loopOpts),
|
||||||
params,
|
params,
|
||||||
{ getResponses: true }
|
{ getResponses: true }
|
||||||
)
|
)
|
||||||
|
if ("outputs" in result && !result.outputs.success) {
|
||||||
|
throw new Error("Unable to proceed - failed to return anything.")
|
||||||
|
}
|
||||||
|
return result as AutomationResults
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
AutomationStatus,
|
AutomationStatus,
|
||||||
AutomationRowEvent,
|
AutomationRowEvent,
|
||||||
UserBindings,
|
UserBindings,
|
||||||
|
AutomationResults,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { executeInThread } from "../threads/automation"
|
import { executeInThread } from "../threads/automation"
|
||||||
import { dataFilters, sdk } from "@budibase/shared-core"
|
import { dataFilters, sdk } from "@budibase/shared-core"
|
||||||
|
@ -32,6 +33,14 @@ const JOB_OPTS = {
|
||||||
import * as automationUtils from "../automations/automationUtils"
|
import * as automationUtils from "../automations/automationUtils"
|
||||||
import { doesTableExist } from "../sdk/app/tables/getters"
|
import { doesTableExist } from "../sdk/app/tables/getters"
|
||||||
|
|
||||||
|
type DidNotTriggerResponse = {
|
||||||
|
outputs: {
|
||||||
|
success: false
|
||||||
|
status: AutomationStatus.STOPPED
|
||||||
|
}
|
||||||
|
message: AutomationStoppedReason.TRIGGER_FILTER_NOT_MET
|
||||||
|
}
|
||||||
|
|
||||||
async function getAllAutomations() {
|
async function getAllAutomations() {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
let automations = await db.allDocs<Automation>(
|
let automations = await db.allDocs<Automation>(
|
||||||
|
@ -139,6 +148,14 @@ function rowPassesFilters(row: Row, filters: SearchFilters) {
|
||||||
return filteredRows.length > 0
|
return filteredRows.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isAutomationResults(
|
||||||
|
response: AutomationResults | DidNotTriggerResponse | AutomationJob
|
||||||
|
): response is AutomationResults {
|
||||||
|
return (
|
||||||
|
response !== null && "steps" in response && Array.isArray(response.steps)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export async function externalTrigger(
|
export async function externalTrigger(
|
||||||
automation: Automation,
|
automation: Automation,
|
||||||
params: {
|
params: {
|
||||||
|
@ -148,7 +165,7 @@ export async function externalTrigger(
|
||||||
user?: UserBindings
|
user?: UserBindings
|
||||||
},
|
},
|
||||||
{ getResponses }: { getResponses?: boolean } = {}
|
{ getResponses }: { getResponses?: boolean } = {}
|
||||||
): Promise<any> {
|
): Promise<AutomationResults | DidNotTriggerResponse | AutomationJob> {
|
||||||
if (automation.disabled) {
|
if (automation.disabled) {
|
||||||
throw new Error("Automation is disabled")
|
throw new Error("Automation is disabled")
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@ import { cloneDeep } from "lodash/fp"
|
||||||
import { quotas } from "@budibase/pro"
|
import { quotas } from "@budibase/pro"
|
||||||
import {
|
import {
|
||||||
Automation,
|
Automation,
|
||||||
|
AutomationActionStepId,
|
||||||
AutomationJob,
|
AutomationJob,
|
||||||
AutomationStepDefinition,
|
AutomationStepDefinition,
|
||||||
AutomationTriggerDefinition,
|
AutomationTriggerDefinition,
|
||||||
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { automationsEnabled } from "../features"
|
import { automationsEnabled } from "../features"
|
||||||
import { helpers, REBOOT_CRON } from "@budibase/shared-core"
|
import { helpers, REBOOT_CRON } from "@budibase/shared-core"
|
||||||
|
@ -120,19 +122,21 @@ export async function updateTestHistory(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeDeprecated(
|
export function removeDeprecated<
|
||||||
definitions: Record<
|
T extends
|
||||||
|
| Record<keyof typeof AutomationTriggerStepId, AutomationTriggerDefinition>
|
||||||
|
| Record<keyof typeof AutomationActionStepId, AutomationStepDefinition>
|
||||||
|
>(definitions: T): T {
|
||||||
|
const base: Record<
|
||||||
string,
|
string,
|
||||||
AutomationStepDefinition | AutomationTriggerDefinition
|
AutomationTriggerDefinition | AutomationStepDefinition
|
||||||
>
|
> = cloneDeep(definitions)
|
||||||
) {
|
|
||||||
const base = cloneDeep(definitions)
|
|
||||||
for (let key of Object.keys(base)) {
|
for (let key of Object.keys(base)) {
|
||||||
if (base[key].deprecated) {
|
if (base[key].deprecated) {
|
||||||
delete base[key]
|
delete base[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base
|
return base as T
|
||||||
}
|
}
|
||||||
|
|
||||||
// end the repetition and the job itself
|
// end the repetition and the job itself
|
||||||
|
|
|
@ -26,3 +26,6 @@ export interface AutomationContext extends AutomationResults {
|
||||||
company?: string
|
company?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AutomationResponse
|
||||||
|
extends Omit<AutomationContext, "stepsByName" | "stepsById"> {}
|
||||||
|
|
|
@ -113,7 +113,7 @@ export async function syncUsersToAllApps(userIds: string[]) {
|
||||||
export async function syncApp(
|
export async function syncApp(
|
||||||
appId: string,
|
appId: string,
|
||||||
opts?: { automationOnly?: boolean }
|
opts?: { automationOnly?: boolean }
|
||||||
) {
|
): Promise<{ message: string }> {
|
||||||
if (env.DISABLE_AUTO_PROD_APP_SYNC) {
|
if (env.DISABLE_AUTO_PROD_APP_SYNC) {
|
||||||
return {
|
return {
|
||||||
message:
|
message:
|
||||||
|
|
|
@ -621,7 +621,7 @@ export default class TestConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
async unpublish() {
|
async unpublish() {
|
||||||
const response = await this._req(appController.unpublish, {
|
const response = await this._req(appController.unpublish, undefined, {
|
||||||
appId: this.appId,
|
appId: this.appId,
|
||||||
})
|
})
|
||||||
this.prodAppId = undefined
|
this.prodAppId = undefined
|
||||||
|
|
|
@ -30,7 +30,11 @@ import {
|
||||||
UserBindings,
|
UserBindings,
|
||||||
isBasicSearchOperator,
|
isBasicSearchOperator,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { AutomationContext, TriggerOutput } from "../definitions/automations"
|
import {
|
||||||
|
AutomationContext,
|
||||||
|
AutomationResponse,
|
||||||
|
TriggerOutput,
|
||||||
|
} from "../definitions/automations"
|
||||||
import { WorkerCallback } from "./definitions"
|
import { WorkerCallback } from "./definitions"
|
||||||
import { context, logging, configs } from "@budibase/backend-core"
|
import { context, logging, configs } from "@budibase/backend-core"
|
||||||
import {
|
import {
|
||||||
|
@ -81,7 +85,7 @@ class Orchestrator {
|
||||||
private job: Job
|
private job: Job
|
||||||
private loopStepOutputs: LoopStep[]
|
private loopStepOutputs: LoopStep[]
|
||||||
private stopped: boolean
|
private stopped: boolean
|
||||||
private executionOutput: Omit<AutomationContext, "stepsByName" | "stepsById">
|
private executionOutput: AutomationResponse
|
||||||
private currentUser: UserBindings | undefined
|
private currentUser: UserBindings | undefined
|
||||||
|
|
||||||
constructor(job: AutomationJob) {
|
constructor(job: AutomationJob) {
|
||||||
|
@ -257,7 +261,7 @@ class Orchestrator {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(): Promise<any> {
|
async execute(): Promise<AutomationResponse | undefined> {
|
||||||
return tracer.trace(
|
return tracer.trace(
|
||||||
"Orchestrator.execute",
|
"Orchestrator.execute",
|
||||||
{ resource: "automation" },
|
{ resource: "automation" },
|
||||||
|
@ -723,7 +727,9 @@ export function execute(job: Job<AutomationData>, callback: WorkerCallback) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function executeInThread(job: Job<AutomationData>) {
|
export async function executeInThread(
|
||||||
|
job: Job<AutomationData>
|
||||||
|
): Promise<AutomationResponse> {
|
||||||
const appId = job.data.event.appId
|
const appId = job.data.event.appId
|
||||||
if (!appId) {
|
if (!appId) {
|
||||||
throw new Error("Unable to execute, event doesn't contain app ID.")
|
throw new Error("Unable to execute, event doesn't contain app ID.")
|
||||||
|
@ -735,7 +741,7 @@ export async function executeInThread(job: Job<AutomationData>) {
|
||||||
}, job.data.event.timeout || env.AUTOMATION_THREAD_TIMEOUT)
|
}, job.data.event.timeout || env.AUTOMATION_THREAD_TIMEOUT)
|
||||||
})
|
})
|
||||||
|
|
||||||
return await context.doInAppContext(appId, async () => {
|
return (await context.doInAppContext(appId, async () => {
|
||||||
await context.ensureSnippetContext()
|
await context.ensureSnippetContext()
|
||||||
const envVars = await sdkUtils.getEnvironmentVariables()
|
const envVars = await sdkUtils.getEnvironmentVariables()
|
||||||
// put into automation thread for whole context
|
// put into automation thread for whole context
|
||||||
|
@ -746,7 +752,7 @@ export async function executeInThread(job: Job<AutomationData>) {
|
||||||
timeoutPromise,
|
timeoutPromise,
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})) as AutomationResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeStalled = async (job: Job) => {
|
export const removeStalled = async (job: Job) => {
|
||||||
|
|
|
@ -3,6 +3,10 @@ export enum PingSource {
|
||||||
APP = "app",
|
APP = "app",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AnalyticsEnabledResponse {
|
||||||
|
enabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface AnalyticsPingRequest {
|
export interface AnalyticsPingRequest {
|
||||||
source: PingSource
|
source: PingSource
|
||||||
timezone: string
|
timezone: string
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export type ApiKeyFetchResponse = Record<string, string>
|
||||||
|
|
||||||
|
export interface UpdateApiKeyRequest {
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateApiKeyResponse {
|
||||||
|
_id: string
|
||||||
|
_rev: string
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationStepDefinition,
|
||||||
|
AutomationTriggerDefinition,
|
||||||
|
AutomationTriggerStepId,
|
||||||
|
} from "../../../documents"
|
||||||
|
|
||||||
|
export type GetAutomationTriggerDefinitionsResponse = Record<
|
||||||
|
keyof typeof AutomationTriggerStepId,
|
||||||
|
AutomationTriggerDefinition
|
||||||
|
>
|
||||||
|
|
||||||
|
export type GetAutomationActionDefinitionsResponse = Record<
|
||||||
|
keyof typeof AutomationActionStepId,
|
||||||
|
AutomationStepDefinition
|
||||||
|
>
|
||||||
|
|
||||||
|
export interface GetAutomationStepDefinitionsResponse {
|
||||||
|
trigger: GetAutomationTriggerDefinitionsResponse
|
||||||
|
action: GetAutomationActionDefinitionsResponse
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export type FetchComponentDefinitionResponse = Record<
|
||||||
|
string,
|
||||||
|
Record<string, any>
|
||||||
|
>
|
|
@ -42,3 +42,14 @@ export interface BuildSchemaFromSourceResponse {
|
||||||
datasource: Datasource
|
datasource: Datasource
|
||||||
errors: Record<string, string>
|
errors: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FetchDatasourcesResponse = Datasource[]
|
||||||
|
export type FindDatasourcesResponse = Datasource
|
||||||
|
|
||||||
|
export interface DeleteDatasourceResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchExternalSchemaResponse {
|
||||||
|
schema: string
|
||||||
|
}
|
||||||
|
|
|
@ -8,3 +8,5 @@ export * from "./permission"
|
||||||
export * from "./attachment"
|
export * from "./attachment"
|
||||||
export * from "./user"
|
export * from "./user"
|
||||||
export * from "./rowAction"
|
export * from "./rowAction"
|
||||||
|
export * from "./automation"
|
||||||
|
export * from "./component"
|
||||||
|
|
|
@ -7,3 +7,5 @@ export interface SetFlagRequest {
|
||||||
flag: string
|
flag: string
|
||||||
value: any
|
value: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AppSelfResponse = ContextUserMetadata | {}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import type { PlanType } from "../../sdk"
|
import type { PlanType } from "../../sdk"
|
||||||
import type { Layout, App, Screen } from "../../documents"
|
import type { Layout, App, Screen } from "../../documents"
|
||||||
|
import { ReadStream } from "fs"
|
||||||
|
|
||||||
|
export interface SyncAppResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateAppRequest {
|
export interface CreateAppRequest {
|
||||||
name: string
|
name: string
|
||||||
|
@ -12,6 +17,8 @@ export interface CreateAppRequest {
|
||||||
file?: { path: string }
|
file?: { path: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreateAppResponse extends App {}
|
||||||
|
|
||||||
export interface DuplicateAppRequest {
|
export interface DuplicateAppRequest {
|
||||||
name: string
|
name: string
|
||||||
url?: string
|
url?: string
|
||||||
|
@ -37,6 +44,8 @@ export interface FetchAppPackageResponse {
|
||||||
hasLock: boolean
|
hasLock: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FetchAppsResponse = App[]
|
||||||
|
|
||||||
export interface PublishResponse {
|
export interface PublishResponse {
|
||||||
_id: string
|
_id: string
|
||||||
status: string
|
status: string
|
||||||
|
@ -45,3 +54,27 @@ export interface PublishResponse {
|
||||||
|
|
||||||
export interface UpdateAppRequest extends Partial<App> {}
|
export interface UpdateAppRequest extends Partial<App> {}
|
||||||
export interface UpdateAppResponse extends App {}
|
export interface UpdateAppResponse extends App {}
|
||||||
|
export interface UpdateAppClientResponse extends App {}
|
||||||
|
export interface RevertAppClientResponse extends App {}
|
||||||
|
|
||||||
|
export interface DeleteAppResponse {
|
||||||
|
ok: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportToUpdateAppRequest {
|
||||||
|
encryptionPassword?: string
|
||||||
|
}
|
||||||
|
export interface ImportToUpdateAppResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SetRevertableAppVersionRequest {
|
||||||
|
revertableVersion: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExportAppDumpRequest {
|
||||||
|
excludeRows: boolean
|
||||||
|
encryptPassword?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExportAppDumpResponse = ReadStream
|
||||||
|
|
|
@ -1,8 +1,58 @@
|
||||||
import { DocumentDestroyResponse } from "@budibase/nano"
|
import { DocumentDestroyResponse } from "@budibase/nano"
|
||||||
import { Automation } from "../../documents"
|
import {
|
||||||
|
Automation,
|
||||||
|
AutomationLogPage,
|
||||||
|
AutomationStatus,
|
||||||
|
Row,
|
||||||
|
} from "../../documents"
|
||||||
|
|
||||||
export interface DeleteAutomationResponse extends DocumentDestroyResponse {}
|
export interface DeleteAutomationResponse extends DocumentDestroyResponse {}
|
||||||
|
|
||||||
export interface FetchAutomationResponse {
|
export interface FetchAutomationResponse {
|
||||||
automations: Automation[]
|
automations: Automation[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FindAutomationResponse extends Automation {}
|
||||||
|
|
||||||
|
export interface UpdateAutomationRequest extends Automation {}
|
||||||
|
export interface UpdateAutomationResponse {
|
||||||
|
message: string
|
||||||
|
automation: Automation
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateAutomationRequest extends Automation {}
|
||||||
|
export interface CreateAutomationResponse {
|
||||||
|
message: string
|
||||||
|
automation: Automation
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchAutomationLogsRequest {
|
||||||
|
startDate?: string
|
||||||
|
status?: AutomationStatus
|
||||||
|
automationId?: string
|
||||||
|
page?: string
|
||||||
|
}
|
||||||
|
export interface SearchAutomationLogsResponse extends AutomationLogPage {}
|
||||||
|
|
||||||
|
export interface ClearAutomationLogRequest {
|
||||||
|
automationId: string
|
||||||
|
appId: string
|
||||||
|
}
|
||||||
|
export interface ClearAutomationLogResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TriggerAutomationRequest {
|
||||||
|
fields: Record<string, any>
|
||||||
|
// time in seconds
|
||||||
|
timeout: number
|
||||||
|
}
|
||||||
|
export type TriggerAutomationResponse = Record<string, any> | undefined
|
||||||
|
|
||||||
|
export interface TestAutomationRequest {
|
||||||
|
id?: string
|
||||||
|
revision?: string
|
||||||
|
fields: Record<string, any>
|
||||||
|
row?: Row
|
||||||
|
}
|
||||||
|
export interface TestAutomationResponse {}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { DeploymentDoc, DeploymentStatus } from "../../documents"
|
||||||
|
|
||||||
|
export interface PublishAppResponse extends DeploymentDoc {}
|
||||||
|
|
||||||
|
export interface DeploymentProgressResponse {
|
||||||
|
_id: string
|
||||||
|
appId: string
|
||||||
|
status?: DeploymentStatus
|
||||||
|
updatedAt: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FetchDeploymentResponse = DeploymentProgressResponse[]
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface GetVersionResponse {
|
||||||
|
version: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClearDevLockResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RevertAppResponse {
|
||||||
|
message: string
|
||||||
|
}
|
|
@ -16,3 +16,6 @@ export * from "./layout"
|
||||||
export * from "./query"
|
export * from "./query"
|
||||||
export * from "./role"
|
export * from "./role"
|
||||||
export * from "./plugins"
|
export * from "./plugins"
|
||||||
|
export * from "./apikeys"
|
||||||
|
export * from "./deployment"
|
||||||
|
export * from "./dev"
|
||||||
|
|
|
@ -311,6 +311,7 @@ export type AutomationStep =
|
||||||
type EmptyInputs = {}
|
type EmptyInputs = {}
|
||||||
export type AutomationStepDefinition = Omit<AutomationStep, "id" | "inputs"> & {
|
export type AutomationStepDefinition = Omit<AutomationStep, "id" | "inputs"> & {
|
||||||
inputs: EmptyInputs
|
inputs: EmptyInputs
|
||||||
|
deprecated?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AutomationTriggerDefinition = Omit<
|
export type AutomationTriggerDefinition = Omit<
|
||||||
|
@ -318,6 +319,7 @@ export type AutomationTriggerDefinition = Omit<
|
||||||
"id" | "inputs"
|
"id" | "inputs"
|
||||||
> & {
|
> & {
|
||||||
inputs: EmptyInputs
|
inputs: EmptyInputs
|
||||||
|
deprecated?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AutomationTriggerInputs<T extends AutomationTriggerStepId> =
|
export type AutomationTriggerInputs<T extends AutomationTriggerStepId> =
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
export enum DeploymentStatus {
|
||||||
|
SUCCESS = "SUCCESS",
|
||||||
|
PENDING = "PENDING",
|
||||||
|
FAILURE = "FAILURE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeploymentDoc {
|
||||||
|
_id: string
|
||||||
|
verification: any
|
||||||
|
status?: DeploymentStatus
|
||||||
|
history?: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
_id: string
|
||||||
|
appId: string
|
||||||
|
status?: DeploymentStatus
|
||||||
|
updatedAt: number
|
||||||
|
}
|
||||||
|
>
|
||||||
|
err?: any
|
||||||
|
appUrl?: string
|
||||||
|
}
|
|
@ -18,3 +18,4 @@ export * from "./sqlite"
|
||||||
export * from "./snippet"
|
export * from "./snippet"
|
||||||
export * from "./rowAction"
|
export * from "./rowAction"
|
||||||
export * from "./theme"
|
export * from "./theme"
|
||||||
|
export * from "./deployment"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { Document } from "../../"
|
||||||
|
|
||||||
|
export interface ApiKeyDoc extends Document {
|
||||||
|
apiKeys: Record<string, string>
|
||||||
|
}
|
|
@ -7,3 +7,4 @@ export * from "./schedule"
|
||||||
export * from "./templates"
|
export * from "./templates"
|
||||||
export * from "./environmentVariables"
|
export * from "./environmentVariables"
|
||||||
export * from "./auditLogs"
|
export * from "./auditLogs"
|
||||||
|
export * from "./apikeys"
|
||||||
|
|
Loading…
Reference in New Issue