From fd81543e44f461eb01af3753419d912066affc75 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 10 Feb 2025 17:03:57 +0000 Subject: [PATCH 01/11] Remove runStep from the codebase. --- .../tests/steps/executeQuery.spec.ts | 50 +++++++++---------- .../tests/steps/sendSmtpEmail.spec.ts | 23 +++++---- .../src/automations/tests/utilities/index.ts | 40 +-------------- 3 files changed, 39 insertions(+), 74 deletions(-) diff --git a/packages/server/src/automations/tests/steps/executeQuery.spec.ts b/packages/server/src/automations/tests/steps/executeQuery.spec.ts index 64dd808b85..ef0edb3335 100644 --- a/packages/server/src/automations/tests/steps/executeQuery.spec.ts +++ b/packages/server/src/automations/tests/steps/executeQuery.spec.ts @@ -6,6 +6,7 @@ import { } from "../../../integrations/tests/utils" import { Knex } from "knex" import { generator } from "@budibase/backend-core/tests" +import { createAutomationBuilder } from "../utilities/AutomationTestBuilder" const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB, DatabaseName.SQS], @@ -41,39 +42,34 @@ if (descriptions.length) { }) it("should be able to execute a query", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: { queryId: query._id }, - } - ) - expect(res.response).toEqual([{ a: "string", b: 1 }]) - expect(res.success).toEqual(true) + const { steps } = await createAutomationBuilder(config) + .onAppAction() + .executeQuery({ query: { queryId: query._id! } }) + .test({ fields: {} }) + + expect(steps[0].outputs.response).toEqual([{ a: "string", b: 1 }]) + expect(steps[0].outputs.success).toEqual(true) }) it("should handle a null query value", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: null, - } - ) - expect(res.response.message).toEqual("Invalid inputs") - expect(res.success).toEqual(false) + const { steps } = await createAutomationBuilder(config) + .onAppAction() + // @ts-expect-error - intentionally passing null + .executeQuery({ query: { queryId: null } }) + .test({ fields: {} }) + + expect(steps[0].outputs.response.message).toEqual("Invalid inputs") + expect(steps[0].outputs.success).toEqual(false) }) it("should handle an error executing a query", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: { queryId: "wrong_id" }, - } - ) - expect(res.response).toBeDefined() - expect(res.success).toEqual(false) + const { steps } = await createAutomationBuilder(config) + .onAppAction() + .executeQuery({ query: { queryId: "wrong_id" } }) + .test({ fields: {} }) + + expect(steps[0].outputs.response).toBeDefined() + expect(steps[0].outputs.success).toEqual(false) }) } ) diff --git a/packages/server/src/automations/tests/steps/sendSmtpEmail.spec.ts b/packages/server/src/automations/tests/steps/sendSmtpEmail.spec.ts index 6ab0f32b65..7452239dfa 100644 --- a/packages/server/src/automations/tests/steps/sendSmtpEmail.spec.ts +++ b/packages/server/src/automations/tests/steps/sendSmtpEmail.spec.ts @@ -19,7 +19,7 @@ function generateResponse(to: string, from: string) { } } -import * as setup from "../utilities" +import { createAutomationBuilder } from "../utilities/AutomationTestBuilder" describe("test the outgoing webhook action", () => { const config = new TestConfiguration() @@ -60,13 +60,14 @@ describe("test the outgoing webhook action", () => { ...invite, } let resp = generateResponse(inputs.to, inputs.from) - const res = await setup.runStep( - config, - setup.actions.SEND_EMAIL_SMTP.stepId, - inputs - ) - expect(res.response).toEqual(resp) - expect(res.success).toEqual(true) + + const { steps } = await createAutomationBuilder(config) + .onAppAction() + .sendSmtpEmail(inputs) + .test({ fields: {} }) + + expect(steps[0].outputs.response).toEqual(resp) + expect(steps[0].outputs.success).toEqual(true) expect(workerRequests.sendSmtpEmail).toHaveBeenCalledTimes(1) expect(workerRequests.sendSmtpEmail).toHaveBeenCalledWith({ to: "user1@example.com", @@ -75,7 +76,11 @@ describe("test the outgoing webhook action", () => { contents: "testing", cc: "cc", bcc: "bcc", - invite, + invite: { + ...invite, + startTime: invite.startTime.toISOString(), + endTime: invite.endTime.toISOString(), + }, automation: true, attachments: [ { url: "attachment1", filename: "attachment1.txt" }, diff --git a/packages/server/src/automations/tests/utilities/index.ts b/packages/server/src/automations/tests/utilities/index.ts index ffecab8680..1a1c48659e 100644 --- a/packages/server/src/automations/tests/utilities/index.ts +++ b/packages/server/src/automations/tests/utilities/index.ts @@ -1,13 +1,7 @@ import TestConfiguration from "../../../tests/utilities/TestConfiguration" -import { context } from "@budibase/backend-core" -import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions" -import emitter from "../../../events/index" +import { BUILTIN_ACTION_DEFINITIONS } from "../../actions" import env from "../../../environment" -import { - AutomationActionStepId, - AutomationData, - Datasource, -} from "@budibase/types" +import { AutomationData, Datasource } from "@budibase/types" import { Knex } from "knex" import { getQueue } from "../.." import { Job } from "bull" @@ -40,36 +34,6 @@ export async function runInProd(fn: any) { } } -export async function runStep( - config: TestConfiguration, - stepId: string, - inputs: any, - stepContext?: any -) { - async function run() { - let step = await getAction(stepId as AutomationActionStepId) - expect(step).toBeDefined() - if (!step) { - throw new Error("No step found") - } - return step({ - context: stepContext || {}, - inputs, - appId: config ? config.getAppId() : "", - // don't really need an API key, mocked out usage quota, not being tested here - apiKey, - emitter, - }) - } - if (config.appId) { - return context.doInContext(config?.appId, async () => { - return run() - }) - } else { - return run() - } -} - /** * Capture all automation runs that occur during the execution of a function. * This function will wait for all messages to be processed before returning. From 133a64edd62bd5a93e9f203a4eae0ae6ac6c1f70 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 11 Feb 2025 14:45:26 +0000 Subject: [PATCH 02/11] Fix tests. --- .../server/src/automations/tests/steps/executeQuery.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/src/automations/tests/steps/executeQuery.spec.ts b/packages/server/src/automations/tests/steps/executeQuery.spec.ts index ef0edb3335..dff3580b7e 100644 --- a/packages/server/src/automations/tests/steps/executeQuery.spec.ts +++ b/packages/server/src/automations/tests/steps/executeQuery.spec.ts @@ -58,7 +58,7 @@ if (descriptions.length) { .executeQuery({ query: { queryId: null } }) .test({ fields: {} }) - expect(steps[0].outputs.response.message).toEqual("Invalid inputs") + expect(steps[0].outputs.response).toStartWith("Error:") expect(steps[0].outputs.success).toEqual(false) }) @@ -68,7 +68,7 @@ if (descriptions.length) { .executeQuery({ query: { queryId: "wrong_id" } }) .test({ fields: {} }) - expect(steps[0].outputs.response).toBeDefined() + expect(steps[0].outputs.response).toStartWith("Error:") expect(steps[0].outputs.success).toEqual(false) }) } From 7f900e2eb924f44c8702e8fe0f5a53f10ba9ac58 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 11 Feb 2025 14:58:05 +0000 Subject: [PATCH 03/11] Update pro reference. --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 8cbaa80a9c..eb96d8b2f2 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 8cbaa80a9cc1152c6cd53722e64da7d824da6e16 +Subproject commit eb96d8b2f2029033b0f758078ed30c888e8fb249 From f0a1ea6f7e9f9b7908e9a6d497a0be2d3819e8ec Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 11 Feb 2025 22:20:35 +0000 Subject: [PATCH 04/11] Some work to fix plugins, attempting to type the server rendered file. --- .../src/api/controllers/static/index.ts | 22 ++++++++++--------- packages/types/src/ui/BudibaseApp.ts | 17 ++++++++++++++ packages/types/src/ui/index.ts | 1 + 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 packages/types/src/ui/BudibaseApp.ts diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 8b5c61e875..25692c0df2 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -25,6 +25,7 @@ import sdk from "../../../sdk" import * as pro from "@budibase/pro" import { App, + BudibaseAppProps, Ctx, DocumentType, Feature, @@ -191,9 +192,14 @@ export const serveApp = async function (ctx: UserCtx) { const themeVariables = getThemeVariables(appInfo?.theme) if (!env.isJest()) { - const plugins = objectStore.enrichPluginURLs(appInfo.usedPlugins) - - const { head, html, css } = AppComponent.render({ + const plugins = await objectStore.enrichPluginURLs(appInfo.usedPlugins) + /* + * Server rendering in svelte sadly does not support type checking, the .render function + * always will just expect "any" when typing - so it is pointless for us to type the + * BudibaseApp.svelte file as we can never detect if the types are correct. To get around this + * I've created a type which expects what the app will expect to receive. + */ + const appProps: BudibaseAppProps = { title: branding?.platformTitle || `${appInfo.name}`, showSkeletonLoader: appInfo.features?.skeletonLoader ?? false, hideDevTools, @@ -205,21 +211,17 @@ export const serveApp = async function (ctx: UserCtx) { metaDescription: branding?.metaDescription || "", metaTitle: branding?.metaTitle || `${appInfo.name} - built with Budibase`, - production: env.isProd(), - appId, clientLibPath: objectStore.clientLibraryUrl(appId!, appInfo.version), usedPlugins: plugins, favicon: branding.faviconUrl !== "" ? await objectStore.getGlobalFileUrl("settings", "faviconUrl") : "", - logo: - config?.logoUrl !== "" - ? await objectStore.getGlobalFileUrl("settings", "logoUrl") - : "", appMigrating: needMigrations, nonce: ctx.state.nonce, - }) + } + + const { head, html, css } = AppComponent.render(appProps) const appHbs = loadHandlebarsFile(appHbsPath) ctx.body = await processString(appHbs, { head, diff --git a/packages/types/src/ui/BudibaseApp.ts b/packages/types/src/ui/BudibaseApp.ts new file mode 100644 index 0000000000..e0c01106ae --- /dev/null +++ b/packages/types/src/ui/BudibaseApp.ts @@ -0,0 +1,17 @@ +import { Plugin } from "../" + +export interface BudibaseAppProps { + title: string + favicon: string + metaImage: string + metaTitle: string + metaDescription: string + clientLibPath: string | undefined + usedPlugins: Plugin[] + appMigrating: boolean + showSkeletonLoader: boolean + hideDevTools: boolean + sideNav: boolean + hideFooter: boolean + nonce: string | undefined +} diff --git a/packages/types/src/ui/index.ts b/packages/types/src/ui/index.ts index 9c4ba93058..0b219f54fb 100644 --- a/packages/types/src/ui/index.ts +++ b/packages/types/src/ui/index.ts @@ -4,3 +4,4 @@ export * from "./components" export * from "./dataFetch" export * from "./datasource" export * from "./common" +export * from "./BudibaseApp" From 270e1e15eef37d817883ac99439ed14f99a0ce5e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 11 Feb 2025 22:38:59 +0000 Subject: [PATCH 05/11] Updating BudibaseApp to use the new props type instead of parts being passed in individually. --- package.json | 1 + .../src/components/ClientAppSkeleton.svelte | 2 +- .../src/api/controllers/static/index.ts | 2 +- .../static/templates/BudibaseApp.svelte | 69 ++++++++----------- scripts/build.js | 12 +++- yarn.lock | 42 +++++++++-- 6 files changed, 78 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index c0b295728e..1475abadf9 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "eslint-plugin-jest": "28.9.0", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-svelte": "2.46.1", + "svelte-preprocess": "^6.0.3", "husky": "^8.0.3", "kill-port": "^1.6.1", "lerna": "7.4.2", diff --git a/packages/frontend-core/src/components/ClientAppSkeleton.svelte b/packages/frontend-core/src/components/ClientAppSkeleton.svelte index f867fccddb..0590ce7862 100644 --- a/packages/frontend-core/src/components/ClientAppSkeleton.svelte +++ b/packages/frontend-core/src/components/ClientAppSkeleton.svelte @@ -1,4 +1,4 @@ - @@ -28,27 +13,27 @@ /> - - + + - - + + - + - - - - + + + + - {title} - {#if favicon !== ""} - + {props.title} + {#if props.favicon !== ""} + {:else} {/if} @@ -105,11 +90,15 @@ - {#if showSkeletonLoader} - + {#if props.showSkeletonLoader} + {/if}
- {#if clientLibPath} + {#if props.clientLibPath}

There was an error loading your app

The Budibase client library could not be loaded. Try republishing your @@ -120,24 +109,24 @@

{/if}

- - {#if appMigrating} - {/if} - - {#if usedPlugins?.length} - {#each usedPlugins as plugin} + {#if props.usedPlugins?.length} + {#each props.usedPlugins as plugin} {/each} {/if} -