From c797b908f135b788189bd0cc3b7a322be55b85a8 Mon Sep 17 00:00:00 2001 From: Michael Drury Date: Wed, 8 Jan 2025 10:41:57 +0000 Subject: [PATCH 001/210] Revert "Revert "Update AWS SDK to V3"" --- .../__mocks__/@aws-sdk/client-s3.ts | 28 + .../@aws-sdk/s3-request-presigner.ts | 4 + packages/backend-core/__mocks__/aws-sdk.ts | 19 - packages/backend-core/package.json | 6 +- packages/backend-core/src/environment.ts | 2 +- .../src/objectStore/buckets/app.ts | 8 +- .../src/objectStore/buckets/global.ts | 8 +- .../src/objectStore/buckets/plugins.ts | 22 +- .../src/objectStore/buckets/tests/app.spec.ts | 24 +- .../objectStore/buckets/tests/global.spec.ts | 26 +- .../objectStore/buckets/tests/plugins.spec.ts | 28 +- .../src/objectStore/objectStore.ts | 198 +-- .../backend-core/src/objectStore/utils.ts | 9 +- packages/cli/src/backups/objectStore.ts | 25 +- packages/server/package.json | 5 +- .../server/src/api/controllers/application.ts | 2 +- .../src/api/controllers/static/index.ts | 26 +- .../src/api/routes/tests/static.spec.ts | 19 +- .../src/automations/tests/createRow.spec.ts | 18 +- packages/server/src/integrations/dynamodb.ts | 38 +- packages/server/src/integrations/s3.ts | 57 +- .../src/integrations/tests/aws-sdk.mock.ts | 76 -- .../src/integrations/tests/dynamodb.spec.ts | 24 +- .../server/src/integrations/tests/s3.spec.ts | 49 +- .../server/src/integrations/utils/utils.ts | 2 +- packages/server/src/sdk/plugins/plugins.ts | 2 +- .../server/src/utilities/fileSystem/app.ts | 2 +- .../server/src/utilities/fileSystem/plugin.ts | 7 +- .../src/utilities/rowProcessor/index.ts | 14 +- .../src/api/controllers/global/configs.ts | 46 +- yarn.lock | 1107 ++++++++++++++++- 31 files changed, 1537 insertions(+), 364 deletions(-) create mode 100644 packages/backend-core/__mocks__/@aws-sdk/client-s3.ts create mode 100644 packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts delete mode 100644 packages/backend-core/__mocks__/aws-sdk.ts delete mode 100644 packages/server/src/integrations/tests/aws-sdk.mock.ts diff --git a/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts new file mode 100644 index 0000000000..8f002f41a8 --- /dev/null +++ b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts @@ -0,0 +1,28 @@ +export class S3 { + headBucket() { + return jest.fn().mockReturnThis() + } + deleteObject() { + return jest.fn().mockReturnThis() + } + deleteObjects() { + return jest.fn().mockReturnThis() + } + createBucket() { + return jest.fn().mockReturnThis() + } + getObject() { + return jest.fn().mockReturnThis() + } + listObject() { + return jest.fn().mockReturnThis() + } + promise() { + return jest.fn().mockReturnThis() + } + catch() { + return jest.fn() + } +} + +export const GetObjectCommand = jest.fn(inputs => ({ inputs })) diff --git a/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts new file mode 100644 index 0000000000..3ed2c10595 --- /dev/null +++ b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts @@ -0,0 +1,4 @@ +export const getSignedUrl = jest.fn((_, cmd) => { + const { inputs } = cmd + return `http://s3.example.com/${inputs?.Bucket}/${inputs?.Key}` +}) diff --git a/packages/backend-core/__mocks__/aws-sdk.ts b/packages/backend-core/__mocks__/aws-sdk.ts deleted file mode 100644 index e3be511d08..0000000000 --- a/packages/backend-core/__mocks__/aws-sdk.ts +++ /dev/null @@ -1,19 +0,0 @@ -const mockS3 = { - headBucket: jest.fn().mockReturnThis(), - deleteObject: jest.fn().mockReturnThis(), - deleteObjects: jest.fn().mockReturnThis(), - createBucket: jest.fn().mockReturnThis(), - getObject: jest.fn().mockReturnThis(), - listObject: jest.fn().mockReturnThis(), - getSignedUrl: jest.fn((operation: string, params: any) => { - return `http://s3.example.com/${params.Bucket}/${params.Key}` - }), - promise: jest.fn().mockReturnThis(), - catch: jest.fn(), -} - -const AWS = { - S3: jest.fn(() => mockS3), -} - -export default AWS diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 3e1b5f324b..b380fca017 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -30,6 +30,9 @@ "test:watch": "jest --watchAll" }, "dependencies": { + "@aws-sdk/client-s3": "3.709.0", + "@aws-sdk/lib-storage": "3.709.0", + "@aws-sdk/s3-request-presigner": "3.709.0", "@budibase/nano": "10.1.5", "@budibase/pouchdb-replication-stream": "1.2.11", "@budibase/shared-core": "*", @@ -71,11 +74,13 @@ "devDependencies": { "@jest/types": "^29.6.3", "@shopify/jest-koa-mocks": "5.1.1", + "@smithy/types": "4.0.0", "@swc/core": "1.3.71", "@swc/jest": "0.2.27", "@types/chance": "1.1.3", "@types/cookies": "0.7.8", "@types/jest": "29.5.5", + "@types/koa": "2.13.4", "@types/lodash": "4.14.200", "@types/node-fetch": "2.6.4", "@types/pouchdb": "6.4.2", @@ -83,7 +88,6 @@ "@types/semver": "7.3.7", "@types/tar-fs": "2.0.1", "@types/uuid": "8.3.4", - "@types/koa": "2.13.4", "chance": "1.1.8", "ioredis-mock": "8.9.0", "jest": "29.7.0", diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts index 954fdd4135..9a46758062 100644 --- a/packages/backend-core/src/environment.ts +++ b/packages/backend-core/src/environment.ts @@ -154,7 +154,7 @@ const environment = { MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN, - AWS_REGION: process.env.AWS_REGION, + AWS_REGION: process.env.AWS_REGION || "eu-west-1", MINIO_URL: process.env.MINIO_URL, MINIO_ENABLED: process.env.MINIO_ENABLED || 1, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, diff --git a/packages/backend-core/src/objectStore/buckets/app.ts b/packages/backend-core/src/objectStore/buckets/app.ts index 43bc965c65..dbf49ca994 100644 --- a/packages/backend-core/src/objectStore/buckets/app.ts +++ b/packages/backend-core/src/objectStore/buckets/app.ts @@ -13,7 +13,7 @@ export function clientLibraryPath(appId: string) { * due to issues with the domain we were unable to continue doing this - keeping * incase we are able to switch back to CDN path again in future. */ -export function clientLibraryCDNUrl(appId: string, version: string) { +export async function clientLibraryCDNUrl(appId: string, version: string) { let file = clientLibraryPath(appId) if (env.CLOUDFRONT_CDN) { // append app version to bust the cache @@ -24,7 +24,7 @@ export function clientLibraryCDNUrl(appId: string, version: string) { // file is public return cloudfront.getUrl(file) } else { - return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file) + return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file) } } @@ -44,10 +44,10 @@ export function clientLibraryUrl(appId: string, version: string) { return `/api/assets/client?${qs.encode(qsParams)}` } -export function getAppFileUrl(s3Key: string) { +export async function getAppFileUrl(s3Key: string) { if (env.CLOUDFRONT_CDN) { return cloudfront.getPresignedUrl(s3Key) } else { - return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key) + return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key) } } diff --git a/packages/backend-core/src/objectStore/buckets/global.ts b/packages/backend-core/src/objectStore/buckets/global.ts index 69e201bb98..29c3347b05 100644 --- a/packages/backend-core/src/objectStore/buckets/global.ts +++ b/packages/backend-core/src/objectStore/buckets/global.ts @@ -5,7 +5,11 @@ import * as cloudfront from "../cloudfront" // URLs -export const getGlobalFileUrl = (type: string, name: string, etag?: string) => { +export const getGlobalFileUrl = async ( + type: string, + name: string, + etag?: string +) => { let file = getGlobalFileS3Key(type, name) if (env.CLOUDFRONT_CDN) { if (etag) { @@ -13,7 +17,7 @@ export const getGlobalFileUrl = (type: string, name: string, etag?: string) => { } return cloudfront.getPresignedUrl(file) } else { - return objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file) + return await objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file) } } diff --git a/packages/backend-core/src/objectStore/buckets/plugins.ts b/packages/backend-core/src/objectStore/buckets/plugins.ts index 02be9345ab..131f180f48 100644 --- a/packages/backend-core/src/objectStore/buckets/plugins.ts +++ b/packages/backend-core/src/objectStore/buckets/plugins.ts @@ -6,23 +6,25 @@ import { Plugin } from "@budibase/types" // URLS -export function enrichPluginURLs(plugins?: Plugin[]): Plugin[] { +export async function enrichPluginURLs(plugins?: Plugin[]): Promise { if (!plugins || !plugins.length) { return [] } - return plugins.map(plugin => { - const jsUrl = getPluginJSUrl(plugin) - const iconUrl = getPluginIconUrl(plugin) - return { ...plugin, jsUrl, iconUrl } - }) + return await Promise.all( + plugins.map(async plugin => { + const jsUrl = await getPluginJSUrl(plugin) + const iconUrl = await getPluginIconUrl(plugin) + return { ...plugin, jsUrl, iconUrl } + }) + ) } -function getPluginJSUrl(plugin: Plugin) { +async function getPluginJSUrl(plugin: Plugin) { const s3Key = getPluginJSKey(plugin) return getPluginUrl(s3Key) } -function getPluginIconUrl(plugin: Plugin): string | undefined { +async function getPluginIconUrl(plugin: Plugin) { const s3Key = getPluginIconKey(plugin) if (!s3Key) { return @@ -30,11 +32,11 @@ function getPluginIconUrl(plugin: Plugin): string | undefined { return getPluginUrl(s3Key) } -function getPluginUrl(s3Key: string) { +async function getPluginUrl(s3Key: string) { if (env.CLOUDFRONT_CDN) { return cloudfront.getPresignedUrl(s3Key) } else { - return objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key) + return await objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key) } } diff --git a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts index 4a132ce54d..e36b36d39d 100644 --- a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts +++ b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts @@ -93,25 +93,25 @@ describe("app", () => { testEnv.multiTenant() }) - it("gets url with embedded minio", () => { + it("gets url with embedded minio", async () => { testEnv.withMinio() - const url = getAppFileUrl() + const url = await getAppFileUrl() expect(url).toBe( "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg" ) }) - it("gets url with custom S3", () => { + it("gets url with custom S3", async () => { testEnv.withS3() - const url = getAppFileUrl() + const url = await getAppFileUrl() expect(url).toBe( "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg" ) }) - it("gets url with cloudfront + s3", () => { + it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - const url = getAppFileUrl() + const url = await getAppFileUrl() // omit rest of signed params expect( url.includes("http://cf.example.com/app_123/attachments/image.jpeg?") @@ -126,8 +126,8 @@ describe("app", () => { it("gets url with embedded minio", async () => { testEnv.withMinio() - await testEnv.withTenant(() => { - const url = getAppFileUrl() + await testEnv.withTenant(async () => { + const url = await getAppFileUrl() expect(url).toBe( "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg" ) @@ -136,8 +136,8 @@ describe("app", () => { it("gets url with custom S3", async () => { testEnv.withS3() - await testEnv.withTenant(() => { - const url = getAppFileUrl() + await testEnv.withTenant(async () => { + const url = await getAppFileUrl() expect(url).toBe( "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg" ) @@ -146,8 +146,8 @@ describe("app", () => { it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - await testEnv.withTenant(() => { - const url = getAppFileUrl() + await testEnv.withTenant(async () => { + const url = await getAppFileUrl() // omit rest of signed params expect( url.includes( diff --git a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts index 148a4c80bf..c98d98e016 100644 --- a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts +++ b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts @@ -3,7 +3,7 @@ import { testEnv } from "../../../../tests/extra" describe("global", () => { describe("getGlobalFileUrl", () => { - function getGlobalFileUrl() { + async function getGlobalFileUrl() { return global.getGlobalFileUrl("settings", "logoUrl", "etag") } @@ -12,21 +12,21 @@ describe("global", () => { testEnv.singleTenant() }) - it("gets url with embedded minio", () => { + it("gets url with embedded minio", async () => { testEnv.withMinio() - const url = getGlobalFileUrl() + const url = await getGlobalFileUrl() expect(url).toBe("/files/signed/global/settings/logoUrl") }) - it("gets url with custom S3", () => { + it("gets url with custom S3", async () => { testEnv.withS3() - const url = getGlobalFileUrl() + const url = await getGlobalFileUrl() expect(url).toBe("http://s3.example.com/global/settings/logoUrl") }) - it("gets url with cloudfront + s3", () => { + it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - const url = getGlobalFileUrl() + const url = await getGlobalFileUrl() // omit rest of signed params expect( url.includes("http://cf.example.com/settings/logoUrl?etag=etag&") @@ -41,16 +41,16 @@ describe("global", () => { it("gets url with embedded minio", async () => { testEnv.withMinio() - await testEnv.withTenant(tenantId => { - const url = getGlobalFileUrl() + await testEnv.withTenant(async tenantId => { + const url = await getGlobalFileUrl() expect(url).toBe(`/files/signed/global/${tenantId}/settings/logoUrl`) }) }) it("gets url with custom S3", async () => { testEnv.withS3() - await testEnv.withTenant(tenantId => { - const url = getGlobalFileUrl() + await testEnv.withTenant(async tenantId => { + const url = await getGlobalFileUrl() expect(url).toBe( `http://s3.example.com/global/${tenantId}/settings/logoUrl` ) @@ -59,8 +59,8 @@ describe("global", () => { it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - await testEnv.withTenant(tenantId => { - const url = getGlobalFileUrl() + await testEnv.withTenant(async tenantId => { + const url = await getGlobalFileUrl() // omit rest of signed params expect( url.includes( diff --git a/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts index fc2822314e..0906ea91c2 100644 --- a/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts +++ b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts @@ -6,8 +6,8 @@ describe("plugins", () => { describe("enrichPluginURLs", () => { const plugin = structures.plugins.plugin() - function getEnrichedPluginUrls() { - const enriched = plugins.enrichPluginURLs([plugin])[0] + async function getEnrichedPluginUrls() { + const enriched = (await plugins.enrichPluginURLs([plugin]))[0] return { jsUrl: enriched.jsUrl!, iconUrl: enriched.iconUrl!, @@ -19,9 +19,9 @@ describe("plugins", () => { testEnv.singleTenant() }) - it("gets url with embedded minio", () => { + it("gets url with embedded minio", async () => { testEnv.withMinio() - const urls = getEnrichedPluginUrls() + const urls = await getEnrichedPluginUrls() expect(urls.jsUrl).toBe( `/files/signed/plugins/${plugin.name}/plugin.min.js` ) @@ -30,9 +30,9 @@ describe("plugins", () => { ) }) - it("gets url with custom S3", () => { + it("gets url with custom S3", async () => { testEnv.withS3() - const urls = getEnrichedPluginUrls() + const urls = await getEnrichedPluginUrls() expect(urls.jsUrl).toBe( `http://s3.example.com/plugins/${plugin.name}/plugin.min.js` ) @@ -41,9 +41,9 @@ describe("plugins", () => { ) }) - it("gets url with cloudfront + s3", () => { + it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - const urls = getEnrichedPluginUrls() + const urls = await getEnrichedPluginUrls() // omit rest of signed params expect( urls.jsUrl.includes( @@ -65,8 +65,8 @@ describe("plugins", () => { it("gets url with embedded minio", async () => { testEnv.withMinio() - await testEnv.withTenant(tenantId => { - const urls = getEnrichedPluginUrls() + await testEnv.withTenant(async tenantId => { + const urls = await getEnrichedPluginUrls() expect(urls.jsUrl).toBe( `/files/signed/plugins/${tenantId}/${plugin.name}/plugin.min.js` ) @@ -78,8 +78,8 @@ describe("plugins", () => { it("gets url with custom S3", async () => { testEnv.withS3() - await testEnv.withTenant(tenantId => { - const urls = getEnrichedPluginUrls() + await testEnv.withTenant(async tenantId => { + const urls = await getEnrichedPluginUrls() expect(urls.jsUrl).toBe( `http://s3.example.com/plugins/${tenantId}/${plugin.name}/plugin.min.js` ) @@ -91,8 +91,8 @@ describe("plugins", () => { it("gets url with cloudfront + s3", async () => { testEnv.withCloudfront() - await testEnv.withTenant(tenantId => { - const urls = getEnrichedPluginUrls() + await testEnv.withTenant(async tenantId => { + const urls = await getEnrichedPluginUrls() // omit rest of signed params expect( urls.jsUrl.includes( diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index 79875b5e99..4f07abe7e2 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -1,6 +1,15 @@ const sanitize = require("sanitize-s3-objectkey") -import AWS from "aws-sdk" +import { + HeadObjectCommandOutput, + PutObjectCommandInput, + S3, + S3ClientConfig, + GetObjectCommand, + _Object as S3Object, +} from "@aws-sdk/client-s3" +import { Upload } from "@aws-sdk/lib-storage" +import { getSignedUrl } from "@aws-sdk/s3-request-presigner" import stream, { Readable } from "stream" import fetch from "node-fetch" import tar from "tar-fs" @@ -13,8 +22,8 @@ import { bucketTTLConfig, budibaseTempDir } from "./utils" import { v4 } from "uuid" import { APP_PREFIX, APP_DEV_PREFIX } from "../db" import fsp from "fs/promises" -import { HeadObjectOutput } from "aws-sdk/clients/s3" import { ReadableStream } from "stream/web" +import { NodeJsRuntimeStreamingBlobPayloadOutputTypes } from "@smithy/types" const streamPipeline = promisify(stream.pipeline) // use this as a temporary store of buckets that are being created @@ -84,26 +93,24 @@ export function sanitizeBucket(input: string) { * @constructor */ export function ObjectStore( - bucket: string, opts: { presigning: boolean } = { presigning: false } ) { - const config: AWS.S3.ClientConfiguration = { - s3ForcePathStyle: true, - signatureVersion: "v4", - apiVersion: "2006-03-01", - accessKeyId: env.MINIO_ACCESS_KEY, - secretAccessKey: env.MINIO_SECRET_KEY, + const config: S3ClientConfig = { + forcePathStyle: true, + credentials: { + accessKeyId: env.MINIO_ACCESS_KEY!, + secretAccessKey: env.MINIO_SECRET_KEY!, + }, region: env.AWS_REGION, } - if (bucket) { - config.params = { - Bucket: sanitizeBucket(bucket), - } - } // for AWS Credentials using temporary session token if (!env.MINIO_ENABLED && env.AWS_SESSION_TOKEN) { - config.sessionToken = env.AWS_SESSION_TOKEN + config.credentials = { + accessKeyId: env.MINIO_ACCESS_KEY!, + secretAccessKey: env.MINIO_SECRET_KEY!, + sessionToken: env.AWS_SESSION_TOKEN, + } } // custom S3 is in use i.e. minio @@ -113,13 +120,13 @@ export function ObjectStore( // Normally a signed url will need to be generated with a specified host in mind. // To support dynamic hosts, e.g. some unknown self-hosted installation url, // use a predefined host. The host 'minio-service' is also forwarded to minio requests via nginx - config.endpoint = "minio-service" + config.endpoint = "http://minio-service" } else { config.endpoint = env.MINIO_URL } } - return new AWS.S3(config) + return new S3(config) } /** @@ -132,26 +139,25 @@ export async function createBucketIfNotExists( ): Promise<{ created: boolean; exists: boolean }> { bucketName = sanitizeBucket(bucketName) try { - await client - .headBucket({ - Bucket: bucketName, - }) - .promise() + await client.headBucket({ + Bucket: bucketName, + }) return { created: false, exists: true } } catch (err: any) { - const promises: any = STATE.bucketCreationPromises - const doesntExist = err.statusCode === 404, - noAccess = err.statusCode === 403 + const statusCode = err.statusCode || err.$response?.statusCode + const promises: Record | undefined> = + STATE.bucketCreationPromises + const doesntExist = statusCode === 404, + noAccess = statusCode === 403 if (promises[bucketName]) { await promises[bucketName] return { created: false, exists: true } } else if (doesntExist || noAccess) { if (doesntExist) { - promises[bucketName] = client - .createBucket({ - Bucket: bucketName, - }) - .promise() + promises[bucketName] = client.createBucket({ + Bucket: bucketName, + }) + await promises[bucketName] delete promises[bucketName] return { created: true, exists: false } @@ -180,25 +186,26 @@ export async function upload({ const fileBytes = path ? (await fsp.open(path)).createReadStream() : body - const objectStore = ObjectStore(bucketName) + const objectStore = ObjectStore() const bucketCreated = await createBucketIfNotExists(objectStore, bucketName) if (ttl && bucketCreated.created) { let ttlConfig = bucketTTLConfig(bucketName, ttl) - await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise() + await objectStore.putBucketLifecycleConfiguration(ttlConfig) } let contentType = type - if (!contentType) { - contentType = extension - ? CONTENT_TYPE_MAP[extension.toLowerCase()] - : CONTENT_TYPE_MAP.txt - } - const config: any = { + const finalContentType = contentType + ? contentType + : extension + ? CONTENT_TYPE_MAP[extension.toLowerCase()] + : CONTENT_TYPE_MAP.txt + const config: PutObjectCommandInput = { // windows file paths need to be converted to forward slashes for s3 + Bucket: sanitizeBucket(bucketName), Key: sanitizeKey(filename), - Body: fileBytes, - ContentType: contentType, + Body: fileBytes as stream.Readable | Buffer, + ContentType: finalContentType, } if (metadata && typeof metadata === "object") { // remove any nullish keys from the metadata object, as these may be considered invalid @@ -207,10 +214,15 @@ export async function upload({ delete metadata[key] } } - config.Metadata = metadata + config.Metadata = metadata as Record } - return objectStore.upload(config).promise() + const upload = new Upload({ + client: objectStore, + params: config, + }) + + return upload.done() } /** @@ -229,12 +241,12 @@ export async function streamUpload({ throw new Error("Stream to upload is invalid/undefined") } const extension = filename.split(".").pop() - const objectStore = ObjectStore(bucketName) + const objectStore = ObjectStore() const bucketCreated = await createBucketIfNotExists(objectStore, bucketName) if (ttl && bucketCreated.created) { let ttlConfig = bucketTTLConfig(bucketName, ttl) - await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise() + await objectStore.putBucketLifecycleConfiguration(ttlConfig) } // Set content type for certain known extensions @@ -267,13 +279,15 @@ export async function streamUpload({ ...extra, } - const details = await objectStore.upload(params).promise() - const headDetails = await objectStore - .headObject({ - Bucket: bucket, - Key: objKey, - }) - .promise() + const upload = new Upload({ + client: objectStore, + params, + }) + const details = await upload.done() + const headDetails = await objectStore.headObject({ + Bucket: bucket, + Key: objKey, + }) return { ...details, ContentLength: headDetails.ContentLength, @@ -284,35 +298,44 @@ export async function streamUpload({ * retrieves the contents of a file from the object store, if it is a known content type it * will be converted, otherwise it will be returned as a buffer stream. */ -export async function retrieve(bucketName: string, filepath: string) { - const objectStore = ObjectStore(bucketName) +export async function retrieve( + bucketName: string, + filepath: string +): Promise { + const objectStore = ObjectStore() const params = { Bucket: sanitizeBucket(bucketName), Key: sanitizeKey(filepath), } - const response: any = await objectStore.getObject(params).promise() + const response = await objectStore.getObject(params) + if (!response.Body) { + throw new Error("Unable to retrieve object") + } + const nodeResponse = + response.Body as NodeJsRuntimeStreamingBlobPayloadOutputTypes // currently these are all strings if (STRING_CONTENT_TYPES.includes(response.ContentType)) { - return response.Body.toString("utf8") + return nodeResponse.toString() } else { - return response.Body + return nodeResponse } } -export async function listAllObjects(bucketName: string, path: string) { - const objectStore = ObjectStore(bucketName) +export async function listAllObjects( + bucketName: string, + path: string +): Promise { + const objectStore = ObjectStore() const list = (params: ListParams = {}) => { - return objectStore - .listObjectsV2({ - ...params, - Bucket: sanitizeBucket(bucketName), - Prefix: sanitizeKey(path), - }) - .promise() + return objectStore.listObjectsV2({ + ...params, + Bucket: sanitizeBucket(bucketName), + Prefix: sanitizeKey(path), + }) } let isTruncated = false, token, - objects: AWS.S3.Types.Object[] = [] + objects: Object[] = [] do { let params: ListParams = {} if (token) { @@ -331,18 +354,19 @@ export async function listAllObjects(bucketName: string, path: string) { /** * Generate a presigned url with a default TTL of 1 hour */ -export function getPresignedUrl( +export async function getPresignedUrl( bucketName: string, key: string, durationSeconds = 3600 ) { - const objectStore = ObjectStore(bucketName, { presigning: true }) + const objectStore = ObjectStore({ presigning: true }) const params = { Bucket: sanitizeBucket(bucketName), Key: sanitizeKey(key), - Expires: durationSeconds, } - const url = objectStore.getSignedUrl("getObject", params) + const url = await getSignedUrl(objectStore, new GetObjectCommand(params), { + expiresIn: durationSeconds, + }) if (!env.MINIO_ENABLED) { // return the full URL to the client @@ -366,7 +390,11 @@ export async function retrieveToTmp(bucketName: string, filepath: string) { filepath = sanitizeKey(filepath) const data = await retrieve(bucketName, filepath) const outputPath = join(budibaseTempDir(), v4()) - fs.writeFileSync(outputPath, data) + if (data instanceof stream.Readable) { + data.pipe(fs.createWriteStream(outputPath)) + } else { + fs.writeFileSync(outputPath, data) + } return outputPath } @@ -408,17 +436,17 @@ export async function retrieveDirectory(bucketName: string, path: string) { * Delete a single file. */ export async function deleteFile(bucketName: string, filepath: string) { - const objectStore = ObjectStore(bucketName) + const objectStore = ObjectStore() await createBucketIfNotExists(objectStore, bucketName) const params = { Bucket: bucketName, Key: sanitizeKey(filepath), } - return objectStore.deleteObject(params).promise() + return objectStore.deleteObject(params) } export async function deleteFiles(bucketName: string, filepaths: string[]) { - const objectStore = ObjectStore(bucketName) + const objectStore = ObjectStore() await createBucketIfNotExists(objectStore, bucketName) const params = { Bucket: bucketName, @@ -426,7 +454,7 @@ export async function deleteFiles(bucketName: string, filepaths: string[]) { Objects: filepaths.map((path: any) => ({ Key: sanitizeKey(path) })), }, } - return objectStore.deleteObjects(params).promise() + return objectStore.deleteObjects(params) } /** @@ -438,13 +466,13 @@ export async function deleteFolder( ): Promise { bucketName = sanitizeBucket(bucketName) folder = sanitizeKey(folder) - const client = ObjectStore(bucketName) + const client = ObjectStore() const listParams = { Bucket: bucketName, Prefix: folder, } - const existingObjectsResponse = await client.listObjects(listParams).promise() + const existingObjectsResponse = await client.listObjects(listParams) if (existingObjectsResponse.Contents?.length === 0) { return } @@ -459,7 +487,7 @@ export async function deleteFolder( deleteParams.Delete.Objects.push({ Key: content.Key }) }) - const deleteResponse = await client.deleteObjects(deleteParams).promise() + const deleteResponse = await client.deleteObjects(deleteParams) // can only empty 1000 items at once if (deleteResponse.Deleted?.length === 1000) { return deleteFolder(bucketName, folder) @@ -534,29 +562,33 @@ export async function getReadStream( ): Promise { bucketName = sanitizeBucket(bucketName) path = sanitizeKey(path) - const client = ObjectStore(bucketName) + const client = ObjectStore() const params = { Bucket: bucketName, Key: path, } - return client.getObject(params).createReadStream() + const response = await client.getObject(params) + if (!response.Body || !(response.Body instanceof stream.Readable)) { + throw new Error("Unable to retrieve stream - invalid response") + } + return response.Body } export async function getObjectMetadata( bucket: string, path: string -): Promise { +): Promise { bucket = sanitizeBucket(bucket) path = sanitizeKey(path) - const client = ObjectStore(bucket) + const client = ObjectStore() const params = { Bucket: bucket, Key: path, } try { - return await client.headObject(params).promise() + return await client.headObject(params) } catch (err: any) { throw new Error("Unable to retrieve metadata from object") } diff --git a/packages/backend-core/src/objectStore/utils.ts b/packages/backend-core/src/objectStore/utils.ts index 30c2fefbf1..2a9dd26e02 100644 --- a/packages/backend-core/src/objectStore/utils.ts +++ b/packages/backend-core/src/objectStore/utils.ts @@ -2,7 +2,10 @@ import path, { join } from "path" import { tmpdir } from "os" import fs from "fs" import env from "../environment" -import { PutBucketLifecycleConfigurationRequest } from "aws-sdk/clients/s3" +import { + LifecycleRule, + PutBucketLifecycleConfigurationCommandInput, +} from "@aws-sdk/client-s3" import * as objectStore from "./objectStore" import { AutomationAttachment, @@ -43,8 +46,8 @@ export function budibaseTempDir() { export const bucketTTLConfig = ( bucketName: string, days: number -): PutBucketLifecycleConfigurationRequest => { - const lifecycleRule = { +): PutBucketLifecycleConfigurationCommandInput => { + const lifecycleRule: LifecycleRule = { ID: `${bucketName}-ExpireAfter${days}days`, Prefix: "", Status: "Enabled", diff --git a/packages/cli/src/backups/objectStore.ts b/packages/cli/src/backups/objectStore.ts index 2a24199603..34e231b87b 100644 --- a/packages/cli/src/backups/objectStore.ts +++ b/packages/cli/src/backups/objectStore.ts @@ -3,6 +3,7 @@ import fs from "fs" import { join } from "path" import { TEMP_DIR, MINIO_DIR } from "./utils" import { progressBar } from "../utils" +import * as stream from "node:stream" const { ObjectStoreBuckets, @@ -20,15 +21,21 @@ export async function exportObjects() { let fullList: any[] = [] let errorCount = 0 for (let bucket of bucketList) { - const client = ObjectStore(bucket) + const client = ObjectStore() try { - await client.headBucket().promise() + await client.headBucket({ + Bucket: bucket, + }) } catch (err) { errorCount++ continue } - const list = (await client.listObjectsV2().promise()) as { Contents: any[] } - fullList = fullList.concat(list.Contents.map(el => ({ ...el, bucket }))) + const list = await client.listObjectsV2({ + Bucket: bucket, + }) + fullList = fullList.concat( + list.Contents?.map(el => ({ ...el, bucket })) || [] + ) } if (errorCount === bucketList.length) { throw new Error("Unable to access MinIO/S3 - check environment config.") @@ -43,7 +50,13 @@ export async function exportObjects() { const dirs = possiblePath.slice(0, possiblePath.length - 1) fs.mkdirSync(join(path, object.bucket, ...dirs), { recursive: true }) } - fs.writeFileSync(join(path, object.bucket, ...possiblePath), data) + if (data instanceof stream.Readable) { + data.pipe( + fs.createWriteStream(join(path, object.bucket, ...possiblePath)) + ) + } else { + fs.writeFileSync(join(path, object.bucket, ...possiblePath), data) + } bar.update(++count) } bar.stop() @@ -60,7 +73,7 @@ export async function importObjects() { const bar = progressBar(total) let count = 0 for (let bucket of buckets) { - const client = ObjectStore(bucket) + const client = ObjectStore() await createBucketIfNotExists(client, bucket) const files = await uploadDirectory(bucket, join(path, bucket), "/") count += files.length diff --git a/packages/server/package.json b/packages/server/package.json index 8cd49a0fe8..fd448629e8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -50,6 +50,10 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", + "@aws-sdk/client-dynamodb": "3.709.0", + "@aws-sdk/client-s3": "3.709.0", + "@aws-sdk/lib-dynamodb": "3.709.0", + "@aws-sdk/s3-request-presigner": "3.709.0", "@azure/msal-node": "^2.5.1", "@budibase/backend-core": "*", "@budibase/client": "*", @@ -70,7 +74,6 @@ "airtable": "0.12.2", "arangojs": "7.2.0", "archiver": "7.0.1", - "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", "bcryptjs": "2.4.3", "bson": "^6.9.0", diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 4169087a63..7ffd075ec0 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -230,7 +230,7 @@ export async function fetchAppPackage( const license = await licensing.cache.getCachedLicense() // Enrich plugin URLs - application.usedPlugins = objectStore.enrichPluginURLs( + application.usedPlugins = await objectStore.enrichPluginURLs( application.usedPlugins ) diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 0dd5e77c50..8b5c61e875 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -18,7 +18,8 @@ import { objectStore, utils, } from "@budibase/backend-core" -import AWS from "aws-sdk" +import { getSignedUrl } from "@aws-sdk/s3-request-presigner" +import { PutObjectCommand, S3 } from "@aws-sdk/client-s3" import fs from "fs" import sdk from "../../../sdk" import * as pro from "@budibase/pro" @@ -128,9 +129,9 @@ export const uploadFile = async function ( return { size: file.size, name: file.name, - url: objectStore.getAppFileUrl(s3Key), + url: await objectStore.getAppFileUrl(s3Key), extension, - key: response.Key, + key: response.Key!, } }) ) @@ -210,11 +211,11 @@ export const serveApp = async function (ctx: UserCtx) { usedPlugins: plugins, favicon: branding.faviconUrl !== "" - ? objectStore.getGlobalFileUrl("settings", "faviconUrl") + ? await objectStore.getGlobalFileUrl("settings", "faviconUrl") : "", logo: config?.logoUrl !== "" - ? objectStore.getGlobalFileUrl("settings", "logoUrl") + ? await objectStore.getGlobalFileUrl("settings", "logoUrl") : "", appMigrating: needMigrations, nonce: ctx.state.nonce, @@ -243,7 +244,7 @@ export const serveApp = async function (ctx: UserCtx) { metaDescription: branding?.metaDescription || "", favicon: branding.faviconUrl !== "" - ? objectStore.getGlobalFileUrl("settings", "faviconUrl") + ? await objectStore.getGlobalFileUrl("settings", "faviconUrl") : "", }) @@ -334,16 +335,17 @@ export const getSignedUploadURL = async function ( ctx.throw(400, "bucket and key values are required") } try { - const s3 = new AWS.S3({ + const s3 = new S3({ region: awsRegion, endpoint: datasource?.config?.endpoint || undefined, - accessKeyId: datasource?.config?.accessKeyId as string, - secretAccessKey: datasource?.config?.secretAccessKey as string, - apiVersion: "2006-03-01", - signatureVersion: "v4", + + credentials: { + accessKeyId: datasource?.config?.accessKeyId as string, + secretAccessKey: datasource?.config?.secretAccessKey as string, + }, }) const params = { Bucket: bucket, Key: key } - signedUrl = s3.getSignedUrl("putObject", params) + signedUrl = await getSignedUrl(s3, new PutObjectCommand(params)) if (datasource?.config?.endpoint) { publicUrl = `${datasource.config.endpoint}/${bucket}/${key}` } else { diff --git a/packages/server/src/api/routes/tests/static.spec.ts b/packages/server/src/api/routes/tests/static.spec.ts index c2808603e9..872085c382 100644 --- a/packages/server/src/api/routes/tests/static.spec.ts +++ b/packages/server/src/api/routes/tests/static.spec.ts @@ -1,12 +1,10 @@ // Directly mock the AWS SDK -jest.mock("aws-sdk", () => ({ - S3: jest.fn(() => ({ - getSignedUrl: jest.fn( - (operation, params) => `http://example.com/${params.Bucket}/${params.Key}` - ), - upload: jest.fn(() => ({ Contents: {} })), - })), +jest.mock("@aws-sdk/s3-request-presigner", () => ({ + getSignedUrl: jest.fn(() => { + return `http://example.com` + }), })) +jest.mock("@aws-sdk/client-s3") import { Datasource, SourceName } from "@budibase/types" import { setEnv } from "../../../environment" @@ -77,7 +75,10 @@ describe("/static", () => { type: "datasource", name: "Test", source: SourceName.S3, - config: {}, + config: { + accessKeyId: "bb", + secretAccessKey: "bb", + }, }, }) }) @@ -91,7 +92,7 @@ describe("/static", () => { .set(config.defaultHeaders()) .expect("Content-Type", /json/) .expect(200) - expect(res.body.signedUrl).toEqual("http://example.com/foo/bar") + expect(res.body.signedUrl).toEqual("http://example.com") expect(res.body.publicUrl).toEqual( `https://${bucket}.s3.eu-west-1.amazonaws.com/${key}` ) diff --git a/packages/server/src/automations/tests/createRow.spec.ts b/packages/server/src/automations/tests/createRow.spec.ts index bd78de2217..42b69324e2 100644 --- a/packages/server/src/automations/tests/createRow.spec.ts +++ b/packages/server/src/automations/tests/createRow.spec.ts @@ -154,11 +154,12 @@ describe("test the create row action", () => { expect(result.steps[1].outputs.row.file_attachment[0]).toHaveProperty("key") let s3Key = result.steps[1].outputs.row.file_attachment[0].key - const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS) + const client = objectStore.ObjectStore() - const objectData = await client - .headObject({ Bucket: objectStore.ObjectStoreBuckets.APPS, Key: s3Key }) - .promise() + const objectData = await client.headObject({ + Bucket: objectStore.ObjectStoreBuckets.APPS, + Key: s3Key, + }) expect(objectData).toBeDefined() expect(objectData.ContentLength).toBeGreaterThan(0) @@ -229,11 +230,12 @@ describe("test the create row action", () => { ) let s3Key = result.steps[1].outputs.row.single_file_attachment.key - const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS) + const client = objectStore.ObjectStore() - const objectData = await client - .headObject({ Bucket: objectStore.ObjectStoreBuckets.APPS, Key: s3Key }) - .promise() + const objectData = await client.headObject({ + Bucket: objectStore.ObjectStoreBuckets.APPS, + Key: s3Key, + }) expect(objectData).toBeDefined() expect(objectData.ContentLength).toBeGreaterThan(0) diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts index 424a3dfce0..96941ebb0e 100644 --- a/packages/server/src/integrations/dynamodb.ts +++ b/packages/server/src/integrations/dynamodb.ts @@ -7,9 +7,15 @@ import { ConnectionInfo, } from "@budibase/types" -import AWS from "aws-sdk" +import { + DynamoDBDocument, + PutCommandInput, + GetCommandInput, + UpdateCommandInput, + DeleteCommandInput, +} from "@aws-sdk/lib-dynamodb" +import { DynamoDB } from "@aws-sdk/client-dynamodb" import { AWS_REGION } from "../constants" -import { DocumentClient } from "aws-sdk/clients/dynamodb" interface DynamoDBConfig { region: string @@ -151,7 +157,7 @@ class DynamoDBIntegration implements IntegrationBase { region: config.region || AWS_REGION, endpoint: config.endpoint || undefined, } - this.client = new AWS.DynamoDB.DocumentClient(this.config) + this.client = DynamoDBDocument.from(new DynamoDB(this.config)) } async testConnection() { @@ -159,8 +165,8 @@ class DynamoDBIntegration implements IntegrationBase { connected: false, } try { - const scanRes = await new AWS.DynamoDB(this.config).listTables().promise() - response.connected = !!scanRes.$response + const scanRes = await new DynamoDB(this.config).listTables() + response.connected = !!scanRes.$metadata } catch (e: any) { response.error = e.message as string } @@ -169,13 +175,13 @@ class DynamoDBIntegration implements IntegrationBase { async create(query: { table: string - json: Omit + json: Omit }) { const params = { TableName: query.table, ...query.json, } - return this.client.put(params).promise() + return this.client.put(params) } async read(query: { table: string; json: object; index: null | string }) { @@ -184,7 +190,7 @@ class DynamoDBIntegration implements IntegrationBase { IndexName: query.index ? query.index : undefined, ...query.json, } - const response = await this.client.query(params).promise() + const response = await this.client.query(params) if (response.Items) { return response.Items } @@ -197,7 +203,7 @@ class DynamoDBIntegration implements IntegrationBase { IndexName: query.index ? query.index : undefined, ...query.json, } - const response = await this.client.scan(params).promise() + const response = await this.client.scan(params) if (response.Items) { return response.Items } @@ -208,40 +214,40 @@ class DynamoDBIntegration implements IntegrationBase { const params = { TableName: query.table, } - return new AWS.DynamoDB(this.config).describeTable(params).promise() + return new DynamoDB(this.config).describeTable(params) } async get(query: { table: string - json: Omit + json: Omit }) { const params = { TableName: query.table, ...query.json, } - return this.client.get(params).promise() + return this.client.get(params) } async update(query: { table: string - json: Omit + json: Omit }) { const params = { TableName: query.table, ...query.json, } - return this.client.update(params).promise() + return this.client.update(params) } async delete(query: { table: string - json: Omit + json: Omit }) { const params = { TableName: query.table, ...query.json, } - return this.client.delete(params).promise() + return this.client.delete(params) } } diff --git a/packages/server/src/integrations/s3.ts b/packages/server/src/integrations/s3.ts index 0b7d774048..488c22835a 100644 --- a/packages/server/src/integrations/s3.ts +++ b/packages/server/src/integrations/s3.ts @@ -7,8 +7,9 @@ import { ConnectionInfo, } from "@budibase/types" -import AWS from "aws-sdk" +import { S3 } from "@aws-sdk/client-s3" import csv from "csvtojson" +import stream from "stream" interface S3Config { region: string @@ -167,7 +168,7 @@ class S3Integration implements IntegrationBase { delete this.config.endpoint } - this.client = new AWS.S3(this.config) + this.client = new S3(this.config) } async testConnection() { @@ -175,7 +176,7 @@ class S3Integration implements IntegrationBase { connected: false, } try { - await this.client.listBuckets().promise() + await this.client.listBuckets() response.connected = true } catch (e: any) { response.error = e.message as string @@ -209,7 +210,7 @@ class S3Integration implements IntegrationBase { LocationConstraint: query.location, } } - return await this.client.createBucket(params).promise() + return await this.client.createBucket(params) } async read(query: { @@ -220,37 +221,39 @@ class S3Integration implements IntegrationBase { maxKeys: number prefix: string }) { - const response = await this.client - .listObjects({ - Bucket: query.bucket, - Delimiter: query.delimiter, - Marker: query.marker, - MaxKeys: query.maxKeys, - Prefix: query.prefix, - }) - .promise() + const response = await this.client.listObjects({ + Bucket: query.bucket, + Delimiter: query.delimiter, + Marker: query.marker, + MaxKeys: query.maxKeys, + Prefix: query.prefix, + }) return response.Contents } async readCsv(query: { bucket: string; key: string }) { - const stream = this.client - .getObject({ - Bucket: query.bucket, - Key: query.key, - }) - .createReadStream() + const response = await this.client.getObject({ + Bucket: query.bucket, + Key: query.key, + }) + + const fileStream = response.Body?.transformToWebStream() + + if (!fileStream || !(fileStream instanceof stream.Readable)) { + throw new Error("Unable to retrieve CSV - invalid stream") + } let csvError = false return new Promise((resolve, reject) => { - stream.on("error", (err: Error) => { + fileStream.on("error", (err: Error) => { reject(err) }) const response = csv() - .fromStream(stream) + .fromStream(fileStream) .on("error", () => { csvError = true }) - stream.on("finish", () => { + fileStream.on("finish", () => { resolve(response) }) }).catch(err => { @@ -263,12 +266,10 @@ class S3Integration implements IntegrationBase { } async delete(query: { bucket: string; delete: string }) { - return await this.client - .deleteObjects({ - Bucket: query.bucket, - Delete: JSON.parse(query.delete), - }) - .promise() + return await this.client.deleteObjects({ + Bucket: query.bucket, + Delete: JSON.parse(query.delete), + }) } } diff --git a/packages/server/src/integrations/tests/aws-sdk.mock.ts b/packages/server/src/integrations/tests/aws-sdk.mock.ts deleted file mode 100644 index 0422adfd3c..0000000000 --- a/packages/server/src/integrations/tests/aws-sdk.mock.ts +++ /dev/null @@ -1,76 +0,0 @@ -const response = (body: any, extra?: any) => () => ({ - promise: () => body, - ...extra, -}) - -class DocumentClient { - put = jest.fn(response({})) - query = jest.fn( - response({ - Items: [], - }) - ) - scan = jest.fn( - response({ - Items: [ - { - Name: "test", - }, - ], - }) - ) - get = jest.fn(response({})) - update = jest.fn(response({})) - delete = jest.fn(response({})) -} - -class S3 { - listObjects = jest.fn( - response({ - Contents: [], - }) - ) - createBucket = jest.fn( - response({ - Contents: {}, - }) - ) - deleteObjects = jest.fn( - response({ - Contents: {}, - }) - ) - getSignedUrl = jest.fn((operation, params) => { - return `http://example.com/${params.Bucket}/${params.Key}` - }) - headBucket = jest.fn( - response({ - Contents: {}, - }) - ) - upload = jest.fn( - response({ - Contents: {}, - }) - ) - getObject = jest.fn( - response( - { - Body: "", - }, - { - createReadStream: jest.fn().mockReturnValue("stream"), - } - ) - ) -} - -module.exports = { - DynamoDB: { - DocumentClient, - }, - S3, - config: { - update: jest.fn(), - }, -} diff --git a/packages/server/src/integrations/tests/dynamodb.spec.ts b/packages/server/src/integrations/tests/dynamodb.spec.ts index c992bc8bfd..75fb84ae60 100644 --- a/packages/server/src/integrations/tests/dynamodb.spec.ts +++ b/packages/server/src/integrations/tests/dynamodb.spec.ts @@ -1,4 +1,20 @@ -jest.mock("aws-sdk", () => require("./aws-sdk.mock")) +jest.mock("@aws-sdk/lib-dynamodb", () => ({ + DynamoDBDocument: { + from: jest.fn(() => ({ + update: jest.fn(), + put: jest.fn(), + query: jest.fn(() => ({ + Items: [], + })), + scan: jest.fn(() => ({ + Items: [], + })), + delete: jest.fn(), + get: jest.fn(), + })), + }, +})) +jest.mock("@aws-sdk/client-dynamodb") import { default as DynamoDBIntegration } from "../dynamodb" class TestConfiguration { @@ -57,11 +73,7 @@ describe("DynamoDB Integration", () => { TableName: tableName, IndexName: indexName, }) - expect(response).toEqual([ - { - Name: "test", - }, - ]) + expect(response).toEqual([]) }) it("calls the get method with the correct params", async () => { diff --git a/packages/server/src/integrations/tests/s3.spec.ts b/packages/server/src/integrations/tests/s3.spec.ts index abe8fb9cf1..678f15bf17 100644 --- a/packages/server/src/integrations/tests/s3.spec.ts +++ b/packages/server/src/integrations/tests/s3.spec.ts @@ -1,5 +1,52 @@ -jest.mock("aws-sdk", () => require("./aws-sdk.mock")) import { default as S3Integration } from "../s3" +jest.mock("@aws-sdk/client-s3", () => { + class S3Mock { + response(body: any, extra?: any) { + return () => ({ + promise: () => body, + ...extra, + }) + } + + listObjects = jest.fn( + this.response({ + Contents: [], + }) + ) + createBucket = jest.fn( + this.response({ + Contents: {}, + }) + ) + deleteObjects = jest.fn( + this.response({ + Contents: {}, + }) + ) + headBucket = jest.fn( + this.response({ + Contents: {}, + }) + ) + upload = jest.fn( + this.response({ + Contents: {}, + }) + ) + getObject = jest.fn( + this.response( + { + Body: "", + }, + { + createReadStream: jest.fn().mockReturnValue("stream"), + } + ) + ) + } + + return { S3: S3Mock } +}) class TestConfiguration { integration: any diff --git a/packages/server/src/integrations/utils/utils.ts b/packages/server/src/integrations/utils/utils.ts index 315a8010e8..db9148ae90 100644 --- a/packages/server/src/integrations/utils/utils.ts +++ b/packages/server/src/integrations/utils/utils.ts @@ -430,7 +430,7 @@ export async function handleFileResponse( size = details.ContentLength } } - presignedUrl = objectStore.getPresignedUrl(bucket, key) + presignedUrl = await objectStore.getPresignedUrl(bucket, key) return { data: { size, diff --git a/packages/server/src/sdk/plugins/plugins.ts b/packages/server/src/sdk/plugins/plugins.ts index 63f2f22cd9..bff24dcef7 100644 --- a/packages/server/src/sdk/plugins/plugins.ts +++ b/packages/server/src/sdk/plugins/plugins.ts @@ -18,7 +18,7 @@ export async function fetch(type?: PluginType): Promise { }) ) let plugins = response.rows.map((row: any) => row.doc) as Plugin[] - plugins = objectStore.enrichPluginURLs(plugins) + plugins = await objectStore.enrichPluginURLs(plugins) if (type) { return plugins.filter((plugin: Plugin) => plugin.schema?.type === type) } else { diff --git a/packages/server/src/utilities/fileSystem/app.ts b/packages/server/src/utilities/fileSystem/app.ts index 9bd88ba0b1..642017d2da 100644 --- a/packages/server/src/utilities/fileSystem/app.ts +++ b/packages/server/src/utilities/fileSystem/app.ts @@ -78,7 +78,7 @@ export const getComponentLibraryManifest = async (library: string) => { resp = await objectStore.retrieve(ObjectStoreBuckets.APPS, path) } if (typeof resp !== "string") { - resp = resp.toString("utf8") + resp = resp.toString() } return JSON.parse(resp) } diff --git a/packages/server/src/utilities/fileSystem/plugin.ts b/packages/server/src/utilities/fileSystem/plugin.ts index 3e1e9bef4d..2949daef61 100644 --- a/packages/server/src/utilities/fileSystem/plugin.ts +++ b/packages/server/src/utilities/fileSystem/plugin.ts @@ -3,6 +3,7 @@ import { budibaseTempDir } from "../budibaseDir" import fs from "fs" import { join } from "path" import { objectStore } from "@budibase/backend-core" +import stream from "stream" const DATASOURCE_PATH = join(budibaseTempDir(), "datasource") const AUTOMATION_PATH = join(budibaseTempDir(), "automation") @@ -58,7 +59,11 @@ async function getPluginImpl(path: string, plugin: Plugin) { pluginKey ) - fs.writeFileSync(filename, pluginJs) + if (pluginJs instanceof stream.Readable) { + pluginJs.pipe(fs.createWriteStream(filename)) + } else { + fs.writeFileSync(filename, pluginJs) + } fs.writeFileSync(metadataName, hash) return require(filename) diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 14b524fd95..7c01c54f13 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -359,9 +359,9 @@ export async function coreOutputProcessing( if (row[property] == null) { continue } - const process = (attachment: RowAttachment) => { + const process = async (attachment: RowAttachment) => { if (!attachment.url && attachment.key) { - attachment.url = objectStore.getAppFileUrl(attachment.key) + attachment.url = await objectStore.getAppFileUrl(attachment.key) } return attachment } @@ -369,11 +369,13 @@ export async function coreOutputProcessing( row[property] = JSON.parse(row[property]) } if (Array.isArray(row[property])) { - row[property].forEach((attachment: RowAttachment) => { - process(attachment) - }) + await Promise.all( + row[property].map((attachment: RowAttachment) => + process(attachment) + ) + ) } else { - process(row[property]) + await process(row[property]) } } } else if ( diff --git a/packages/worker/src/api/controllers/global/configs.ts b/packages/worker/src/api/controllers/global/configs.ts index a10fce35f6..4ee8dcbb24 100644 --- a/packages/worker/src/api/controllers/global/configs.ts +++ b/packages/worker/src/api/controllers/global/configs.ts @@ -322,27 +322,27 @@ export async function save( } } -function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) { +async function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) { if (!oidcLogos) { return } - oidcLogos.config = Object.keys(oidcLogos.config || {}).reduce( - (acc: any, key: string) => { - if (!key.endsWith("Etag")) { - const etag = oidcLogos.config[`${key}Etag`] - const objectStoreUrl = objectStore.getGlobalFileUrl( - oidcLogos.type, - key, - etag - ) - acc[key] = objectStoreUrl - } else { - acc[key] = oidcLogos.config[key] - } - return acc - }, - {} - ) + const newConfig: Record = {} + const keys = Object.keys(oidcLogos.config || {}) + + for (const key of keys) { + if (!key.endsWith("Etag")) { + const etag = oidcLogos.config[`${key}Etag`] + const objectStoreUrl = await objectStore.getGlobalFileUrl( + oidcLogos.type, + key, + etag + ) + newConfig[key] = objectStoreUrl + } else { + newConfig[key] = oidcLogos.config[key] + } + } + oidcLogos.config = newConfig } export async function find(ctx: UserCtx) { @@ -370,7 +370,7 @@ export async function find(ctx: UserCtx) { async function handleConfigType(type: ConfigType, config: Config) { if (type === ConfigType.OIDC_LOGOS) { - enrichOIDCLogos(config) + await enrichOIDCLogos(config) } else if (type === ConfigType.AI) { await handleAIConfig(config) } @@ -396,7 +396,7 @@ export async function publicOidc(ctx: Ctx) { const oidcCustomLogos = await configs.getOIDCLogosDoc() if (oidcCustomLogos) { - enrichOIDCLogos(oidcCustomLogos) + await enrichOIDCLogos(oidcCustomLogos) } if (!oidcConfig) { @@ -427,7 +427,7 @@ export async function publicSettings( // enrich the logo url - empty url means deleted if (config.logoUrl && config.logoUrl !== "") { - config.logoUrl = objectStore.getGlobalFileUrl( + config.logoUrl = await objectStore.getGlobalFileUrl( "settings", "logoUrl", config.logoUrlEtag @@ -437,7 +437,7 @@ export async function publicSettings( // enrich the favicon url - empty url means deleted const faviconUrl = branding.faviconUrl && branding.faviconUrl !== "" - ? objectStore.getGlobalFileUrl( + ? await objectStore.getGlobalFileUrl( "settings", "faviconUrl", branding.faviconUrlEtag @@ -522,7 +522,7 @@ export async function upload(ctx: UserCtx) { ctx.body = { message: "File has been uploaded and url stored to config.", - url: objectStore.getGlobalFileUrl(type, name, etag), + url: await objectStore.getGlobalFileUrl(type, name, etag), } } diff --git a/yarn.lock b/yarn.lock index c54385478e..a9517925a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -150,6 +150,121 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" +"@aws-sdk/client-dynamodb@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-dynamodb/-/client-dynamodb-3.709.0.tgz#589cfab9d27f7d0d2056f72e4674315ccd98b6bc" + integrity sha512-p/GVuEgfPccFUm5lxr7EPi5gQAsUO4SDdKcIV+v/dNwtH2SXEgnFN0o1TEIJtuVY3BsQyXyR1aMjeQ81O832kw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.709.0" + "@aws-sdk/client-sts" "3.709.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/credential-provider-node" "3.709.0" + "@aws-sdk/middleware-endpoint-discovery" "3.709.0" + "@aws-sdk/middleware-host-header" "3.709.0" + "@aws-sdk/middleware-logger" "3.709.0" + "@aws-sdk/middleware-recursion-detection" "3.709.0" + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/region-config-resolver" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@aws-sdk/util-user-agent-browser" "3.709.0" + "@aws-sdk/util-user-agent-node" "3.709.0" + "@smithy/config-resolver" "^3.0.13" + "@smithy/core" "^2.5.5" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/hash-node" "^3.0.11" + "@smithy/invalid-dependency" "^3.0.11" + "@smithy/middleware-content-length" "^3.0.13" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-retry" "^3.0.30" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.30" + "@smithy/util-defaults-mode-node" "^3.0.30" + "@smithy/util-endpoints" "^2.1.7" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.2.0" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-s3@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.709.0.tgz#ae27e18c5ced29f0d24857e4a28fb6947cdba3a4" + integrity sha512-IvC7coELoQ4YenTdULArVdL5yk6jNRVUALX1aqv9JlPdrXxb3Om6YrM9e7AlSTLxrULTsAe1ubm8i/DmcSY/Ng== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.709.0" + "@aws-sdk/client-sts" "3.709.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/credential-provider-node" "3.709.0" + "@aws-sdk/middleware-bucket-endpoint" "3.709.0" + "@aws-sdk/middleware-expect-continue" "3.709.0" + "@aws-sdk/middleware-flexible-checksums" "3.709.0" + "@aws-sdk/middleware-host-header" "3.709.0" + "@aws-sdk/middleware-location-constraint" "3.709.0" + "@aws-sdk/middleware-logger" "3.709.0" + "@aws-sdk/middleware-recursion-detection" "3.709.0" + "@aws-sdk/middleware-sdk-s3" "3.709.0" + "@aws-sdk/middleware-ssec" "3.709.0" + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/region-config-resolver" "3.709.0" + "@aws-sdk/signature-v4-multi-region" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@aws-sdk/util-user-agent-browser" "3.709.0" + "@aws-sdk/util-user-agent-node" "3.709.0" + "@aws-sdk/xml-builder" "3.709.0" + "@smithy/config-resolver" "^3.0.13" + "@smithy/core" "^2.5.5" + "@smithy/eventstream-serde-browser" "^3.0.14" + "@smithy/eventstream-serde-config-resolver" "^3.0.11" + "@smithy/eventstream-serde-node" "^3.0.13" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/hash-blob-browser" "^3.1.10" + "@smithy/hash-node" "^3.0.11" + "@smithy/hash-stream-node" "^3.1.10" + "@smithy/invalid-dependency" "^3.0.11" + "@smithy/md5-js" "^3.0.11" + "@smithy/middleware-content-length" "^3.0.13" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-retry" "^3.0.30" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.30" + "@smithy/util-defaults-mode-node" "^3.0.30" + "@smithy/util-endpoints" "^2.1.7" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + "@smithy/util-stream" "^3.3.2" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.2.0" + tslib "^2.6.2" + "@aws-sdk/client-s3@^3.388.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.693.0.tgz#188b621498ffaeb7b1ea5794f61e3e8d9a4bcac2" @@ -259,6 +374,51 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/client-sso-oidc@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.709.0.tgz#959e4df4070f1d059d8d0cd5b9028d9a46ac7ecf" + integrity sha512-1w6egz17QQy661lNCRmZZlqIANEbD6g2VFAQIJbVwSiu7brg+GUns+mT1eLLLHAMQc1sL0Ds8/ybSK2SrgGgIA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/credential-provider-node" "3.709.0" + "@aws-sdk/middleware-host-header" "3.709.0" + "@aws-sdk/middleware-logger" "3.709.0" + "@aws-sdk/middleware-recursion-detection" "3.709.0" + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/region-config-resolver" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@aws-sdk/util-user-agent-browser" "3.709.0" + "@aws-sdk/util-user-agent-node" "3.709.0" + "@smithy/config-resolver" "^3.0.13" + "@smithy/core" "^2.5.5" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/hash-node" "^3.0.11" + "@smithy/invalid-dependency" "^3.0.11" + "@smithy/middleware-content-length" "^3.0.13" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-retry" "^3.0.30" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.30" + "@smithy/util-defaults-mode-node" "^3.0.30" + "@smithy/util-endpoints" "^2.1.7" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/client-sso@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.693.0.tgz#9cd5e07e57013b8c7980512810d775d7b6f67e36" @@ -303,6 +463,50 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/client-sso@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.709.0.tgz#b5b29161e07af6f82afd7a6e750c09b0158d19e3" + integrity sha512-Qxeo8cN0jNy6Wnbqq4wucffAGJM6sJjofoTgNtPA6cC7sPYx7aYC6OAAAo6NaMRY+WywOKdS9Wgjx2QYRxKx7w== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/middleware-host-header" "3.709.0" + "@aws-sdk/middleware-logger" "3.709.0" + "@aws-sdk/middleware-recursion-detection" "3.709.0" + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/region-config-resolver" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@aws-sdk/util-user-agent-browser" "3.709.0" + "@aws-sdk/util-user-agent-node" "3.709.0" + "@smithy/config-resolver" "^3.0.13" + "@smithy/core" "^2.5.5" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/hash-node" "^3.0.11" + "@smithy/invalid-dependency" "^3.0.11" + "@smithy/middleware-content-length" "^3.0.13" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-retry" "^3.0.30" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.30" + "@smithy/util-defaults-mode-node" "^3.0.30" + "@smithy/util-endpoints" "^2.1.7" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/client-sts@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.693.0.tgz#9e2c418f4850269635632bee4d1a31057c04bcc5" @@ -349,6 +553,52 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/client-sts@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.709.0.tgz#b9ad3c9c6419d0d149b28cdd6c115cc40c4e7906" + integrity sha512-cBAvlPg6yslXNL385UUGFPw+XY+lA9BzioNdIFkMo3fEUlTShogTtiWz4LsyLHoN6LhKojssP9DSmmWKWjCZIw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.709.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/credential-provider-node" "3.709.0" + "@aws-sdk/middleware-host-header" "3.709.0" + "@aws-sdk/middleware-logger" "3.709.0" + "@aws-sdk/middleware-recursion-detection" "3.709.0" + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/region-config-resolver" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@aws-sdk/util-user-agent-browser" "3.709.0" + "@aws-sdk/util-user-agent-node" "3.709.0" + "@smithy/config-resolver" "^3.0.13" + "@smithy/core" "^2.5.5" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/hash-node" "^3.0.11" + "@smithy/invalid-dependency" "^3.0.11" + "@smithy/middleware-content-length" "^3.0.13" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-retry" "^3.0.30" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.30" + "@smithy/util-defaults-mode-node" "^3.0.30" + "@smithy/util-endpoints" "^2.1.7" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/core@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.693.0.tgz#437969dd740895a59863d737bad14646bc2e1725" @@ -366,6 +616,23 @@ fast-xml-parser "4.4.1" tslib "^2.6.2" +"@aws-sdk/core@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.709.0.tgz#d2b3d5b90f6614e3afc109ebdcaaedbb54c2d68b" + integrity sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/core" "^2.5.5" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/property-provider" "^3.1.11" + "@smithy/protocol-http" "^4.1.8" + "@smithy/signature-v4" "^4.2.4" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/util-middleware" "^3.0.11" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + "@aws-sdk/credential-provider-env@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.693.0.tgz#f97feed9809fe2800216943470015fdaaba47c4f" @@ -377,6 +644,17 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-env@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.709.0.tgz#a7f75375d8a413f9ab2bc42f743b943da6d3362d" + integrity sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/property-provider" "^3.1.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-http@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.693.0.tgz#5caad0ac47eded1edeb63f907280580ccfaadba3" @@ -393,6 +671,22 @@ "@smithy/util-stream" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-http@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.709.0.tgz#a378cbcc4cf373cc277944f1e84e9952f3884f5d" + integrity sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/property-provider" "^3.1.11" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/util-stream" "^3.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-ini@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.693.0.tgz#b4557ac1092657660a15c9bd55e17c27f79ec621" @@ -411,6 +705,24 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-ini@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.709.0.tgz#b01c68d98ce4cc48f79405234e32a9de2f943ea1" + integrity sha512-qCF8IIGcPoUp+Ib3ANhbF5gElxFd+kIrtv2/1tKdvhudMANstQbMiWV0LTH47ZZR6c3as4iSrm09NZnpEoD/pA== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/credential-provider-env" "3.709.0" + "@aws-sdk/credential-provider-http" "3.709.0" + "@aws-sdk/credential-provider-process" "3.709.0" + "@aws-sdk/credential-provider-sso" "3.709.0" + "@aws-sdk/credential-provider-web-identity" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/credential-provider-imds" "^3.2.8" + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-node@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.693.0.tgz#c5ceac64a69304d5b4db3fd68473480cafddb4a9" @@ -429,6 +741,24 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-node@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.709.0.tgz#270a31aae394e6c8fe7d3fdd0b92e7c3a863b933" + integrity sha512-4HRX9KYWPSjO5O/Vg03YAsebKpvTjTvpK1n7zHYBmlLMBLxUrVsL1nNKKC5p2/7OW3RL8XR1ki3QkoV7kGRxUQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.709.0" + "@aws-sdk/credential-provider-http" "3.709.0" + "@aws-sdk/credential-provider-ini" "3.709.0" + "@aws-sdk/credential-provider-process" "3.709.0" + "@aws-sdk/credential-provider-sso" "3.709.0" + "@aws-sdk/credential-provider-web-identity" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/credential-provider-imds" "^3.2.8" + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-process@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.693.0.tgz#e84e945f1a148f06ff697608d5309e73347e5aa9" @@ -441,6 +771,18 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-process@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.709.0.tgz#2521f810590f0874c54cc842d3d56f455a728325" + integrity sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-sso@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.693.0.tgz#72767389f533d9d17a14af63daaafcc8368ab43a" @@ -455,6 +797,20 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-sso@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.709.0.tgz#f0cb855eed86748ff0c9afa06b3a234fb04b3206" + integrity sha512-rYdTDOxazS2GdGScelsRK5CAkktRLCCdRjlwXaxrcW57j749hEqxcF5uTv9RD6WBwInfedcSywErNZB+hylQlg== + dependencies: + "@aws-sdk/client-sso" "3.709.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/token-providers" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-web-identity@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.693.0.tgz#b6133b5ef9d3582e36e02e9c66766714ff672a11" @@ -466,6 +822,50 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-web-identity@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.709.0.tgz#c2b03541cb57ae4c7d6abdca98f99a6a56833ea6" + integrity sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/property-provider" "^3.1.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + +"@aws-sdk/endpoint-cache@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/endpoint-cache/-/endpoint-cache-3.693.0.tgz#4b3f0bbc16dc2907e1b977e3d8ddfc7ba008fd12" + integrity sha512-/zK0ZZncBf5FbTfo8rJMcQIXXk4Ibhe5zEMiwFNivVPR2uNC0+oqfwXz7vjxwY0t6BPE3Bs4h9uFEz4xuGCY6w== + dependencies: + mnemonist "0.38.3" + tslib "^2.6.2" + +"@aws-sdk/lib-dynamodb@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.709.0.tgz#fd90b76bce67af1a3079524710f7bc19647829ad" + integrity sha512-piIyvQ1DhoUEosKmjGnMxLClUb9tv5rPPZfgh9J4MmSygsYbE9HvC3tstje0xUudVZjsmzZpNyibl/n0LA0gdQ== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/util-dynamodb" "3.709.0" + "@smithy/core" "^2.5.5" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + +"@aws-sdk/lib-storage@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.709.0.tgz#2b12e558880418c3348cbd8f1e4e7f8db424b7b7" + integrity sha512-TnP+QSsWdiaQYS5HuB3n9H947z49m6qSEv5fth4L9xinBldLepLyyF+cua3/GlagkWqpxcATISgR9pE1PB0mhQ== + dependencies: + "@smithy/abort-controller" "^3.1.9" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/smithy-client" "^3.5.0" + buffer "5.6.0" + events "3.3.0" + stream-browserify "3.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-bucket-endpoint@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.693.0.tgz#e4823a40935d34f5e58a4fbc830d8ff92e44fc99" @@ -479,6 +879,31 @@ "@smithy/util-config-provider" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-bucket-endpoint@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.709.0.tgz#a69bdebfebb7b5b174d3a396f2361f5025d168f4" + integrity sha512-03+tJOd7KIZOiqWH7Z8BOfQIWkKJgjcpKOJKZ6FR2KjWGUOE1G+bo11wF4UuHQ0RmpKnApt+pQghZmSnE7WEeg== + dependencies: + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-arn-parser" "3.693.0" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-endpoint-discovery@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.709.0.tgz#d5866603f2515f0da2c84ead99cd25b806d8ee5b" + integrity sha512-6CSHoAy3sVBJdeGiBpoRqVHpqLPqv5QuDxKsEMHoGdbGATmffyn2whTFfo5hfRYsN9WPz/XxUX2iynqQCnlrzw== + dependencies: + "@aws-sdk/endpoint-cache" "3.693.0" + "@aws-sdk/types" "3.709.0" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-expect-continue@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.693.0.tgz#d8696cee9ebea1d973d8daf872fd913b41d62cf0" @@ -489,6 +914,16 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-expect-continue@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.709.0.tgz#a7fec776da9de32e15088badfc09d69118f5d5ab" + integrity sha512-Tbl/DFvE4rHl8lMb9IzetwK4tf5R3VeHZkvEXQalsWoK0tbEQ8kXWi7wAYO4qbE7bFVvaxKX+irjJjTxf3BrCQ== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-flexible-checksums@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.693.0.tgz#80f07802d98ff33a6899a09c59cf51aab426aaac" @@ -508,6 +943,25 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-flexible-checksums@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.709.0.tgz#f0fb543c2db724cb43bae215ff0aea942d06a967" + integrity sha512-wbYm9tkyCaqMeU82yjaXw7V5BxCSlSLNupENW63LC7Fvyo/aQzj6LjSMHcBpR2QwjBEhXCtF47L7aQ8SPTNhdw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-stream" "^3.3.2" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-host-header@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.693.0.tgz#69322909c0792df1e6be7c7fb5e2b6f76090a55c" @@ -518,6 +972,16 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-host-header@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.709.0.tgz#f44f5c62f9bd7e5a443603fed68143d2d9725219" + integrity sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-location-constraint@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.693.0.tgz#1856eaaad64d41d1f8fa53ced58a6c7cf5eccc6e" @@ -527,6 +991,15 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-location-constraint@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.709.0.tgz#4437d3d3cfbbdfca60664b1f237d600b94fd06a5" + integrity sha512-5YQWPXfZq7OE0jB2G0PP8K10GBod/YPJXb+1CfJS6FbQaglRoIm8KZmVEvJNnptSKyGtE62veeCcCQcfAUfFig== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-logger@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.693.0.tgz#fc10294e6963f8e5d58ba1ededd891e999f544a9" @@ -536,6 +1009,15 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-logger@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.709.0.tgz#b9a0b016b7ae09cb502cc4faf45964d4b5745824" + integrity sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-recursion-detection@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.693.0.tgz#88a8157293775e7116707da26501da4b5e042f51" @@ -546,6 +1028,16 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-recursion-detection@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.709.0.tgz#d7dc253d4858d496caeb12dd6cddd87b250fb98b" + integrity sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-sdk-s3@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.693.0.tgz#e0850854d5079f372786b2ccfe85729caa7a49d8" @@ -566,6 +1058,26 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-sdk-s3@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.709.0.tgz#b6f22c77e64760869eb06255af58376f879742b2" + integrity sha512-FwtOG9t9xsLoLOQZ6qAdsWOjx9dsO6t28IjIDV1l6Ixiu2oC0Yks7goONjJUH0IDE4pDDDGzmuq0sn1XtHhheA== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-arn-parser" "3.693.0" + "@smithy/core" "^2.5.5" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/protocol-http" "^4.1.8" + "@smithy/signature-v4" "^4.2.4" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-stream" "^3.3.2" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-ssec@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.693.0.tgz#2ff779147d188090b3a6cda3ed12ca4085220a73" @@ -575,6 +1087,15 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-ssec@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.709.0.tgz#bbf5253cdce45ed2759a108fd924fff4b8e049d5" + integrity sha512-2muiLe7YkmlwZp2SKz+goZrDThGfRq3o0FcJF3Puc0XGmcEPEDjih537mCoTrGgcXNFlBc7YChd84r3t72ySaQ== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/middleware-user-agent@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.693.0.tgz#4b55cfab3fc7e671b08e1ea63a98e45a1e13e6a5" @@ -588,6 +1109,19 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/middleware-user-agent@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.709.0.tgz#2a467f14b3f4a9270bcdfde32e3d4e38701aaafe" + integrity sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw== + dependencies: + "@aws-sdk/core" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-endpoints" "3.709.0" + "@smithy/core" "^2.5.5" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/node-http-handler@^3.374.0": version "3.374.0" resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.374.0.tgz#8cd58b4d9814713e26034c12eabc119c113a5bc4" @@ -608,6 +1142,32 @@ "@smithy/util-middleware" "^3.0.9" tslib "^2.6.2" +"@aws-sdk/region-config-resolver@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.709.0.tgz#64547b333842e5804e1793e4d6d29578c0b34a68" + integrity sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/types" "^3.7.2" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.11" + tslib "^2.6.2" + +"@aws-sdk/s3-request-presigner@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.709.0.tgz#d3c9d881158bdece69863be318d49e9d7d2c512f" + integrity sha512-WYmXU2ur/z6xBX9TcGwSWlSiS8rxrRl2f1HJXZzgSu9FWZ7fJssoQGvrk/w64wjNq1tEzKbd1iWXw9s9qexT3g== + dependencies: + "@aws-sdk/signature-v4-multi-region" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@aws-sdk/util-format-url" "3.709.0" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/protocol-http" "^4.1.8" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/signature-v4-multi-region@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.693.0.tgz#85bd90bb78be1a98d5a5ca41033cb0703146c2c4" @@ -620,6 +1180,18 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/signature-v4-multi-region@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.709.0.tgz#0c6f9d3e2978158163b63a4085356616237223c9" + integrity sha512-m0vhJEy6SLbjL11K9cHzX/ZhCIj//1GkTbYk2d4tTQFSuPyJEkjmoeHk9dYm2mJy0wH48j29OJadI1JUsR5bOw== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/protocol-http" "^4.1.8" + "@smithy/signature-v4" "^4.2.4" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/token-providers@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.693.0.tgz#5ce7d6aa7a3437d4abdc0dca1be47f5158d15c85" @@ -631,6 +1203,17 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/token-providers@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.709.0.tgz#56305ab187660a711fd172c329dc953ca754fa80" + integrity sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/types@3.692.0", "@aws-sdk/types@^3.222.0": version "3.692.0" resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.692.0.tgz#c8f6c75b6ad659865b72759796d4d92c1b72069b" @@ -639,6 +1222,14 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/types@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.709.0.tgz#f8d7ab07e253d3ed0e3b360e09fc67c7430a73b9" + integrity sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/util-arn-parser@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.693.0.tgz#8dae27eb822ab4f88be28bb3c0fc11f1f13d3948" @@ -646,6 +1237,13 @@ dependencies: tslib "^2.6.2" +"@aws-sdk/util-dynamodb@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-dynamodb/-/util-dynamodb-3.709.0.tgz#12ced0849ff8f1ac8a1921f97fdb57813f22ec14" + integrity sha512-rGr9+Po6Ma2BHV2hIhfXdn8hWxLtmgFzFRqqtxOlRRIDN55wkb2AYXz/ydzf4kgb+PzT8sQxtn6hf7pDkl+yAg== + dependencies: + tslib "^2.6.2" + "@aws-sdk/util-endpoints@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.693.0.tgz#99f56f83fc25bdc3321f5871d6354abd56768891" @@ -656,6 +1254,26 @@ "@smithy/util-endpoints" "^2.1.5" tslib "^2.6.2" +"@aws-sdk/util-endpoints@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.709.0.tgz#32dfe339d78b699ada68392bbb3bec25441bae5c" + integrity sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/types" "^3.7.2" + "@smithy/util-endpoints" "^2.1.7" + tslib "^2.6.2" + +"@aws-sdk/util-format-url@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.709.0.tgz#6ac420c297cae442f6d4065214eefc0d977e1a10" + integrity sha512-HGR11hx1KeFfoub/TACf+Yyal37lR85791Di2QPaElQThaqztLlppxale3EohKboOFf7Q/zvslJyM0fmgrlpQw== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/querystring-builder" "^3.0.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz#1160f6d055cf074ca198eb8ecf89b6311537ad6c" @@ -673,6 +1291,16 @@ bowser "^2.11.0" tslib "^2.6.2" +"@aws-sdk/util-user-agent-browser@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.709.0.tgz#ad6e867bdd348923ec10ddd6c37740ce0986cd8f" + integrity sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg== + dependencies: + "@aws-sdk/types" "3.709.0" + "@smithy/types" "^3.7.2" + bowser "^2.11.0" + tslib "^2.6.2" + "@aws-sdk/util-user-agent-node@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.693.0.tgz#b26c806faa2001d4fa1d515b146eeff411513dd9" @@ -684,6 +1312,17 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/util-user-agent-node@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.709.0.tgz#7ff5a508bcad49963a550acadcced43d7af9960d" + integrity sha512-trBfzSCVWy7ILgqhEXgiuM7hfRCw4F4a8IK90tjk9YL0jgoJ6eJuOp7+DfCtHJaygoBxD3cdMFkOu+lluFmGBA== + dependencies: + "@aws-sdk/middleware-user-agent" "3.709.0" + "@aws-sdk/types" "3.709.0" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@aws-sdk/xml-builder@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.693.0.tgz#709a46a3335b71144d9f7917a7cb3033b5a04e82" @@ -692,6 +1331,14 @@ "@smithy/types" "^3.7.0" tslib "^2.6.2" +"@aws-sdk/xml-builder@3.709.0": + version "3.709.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.709.0.tgz#5841faa1e78afcea064557a1a56709978b325758" + integrity sha512-2GPCwlNxeHspoK/Mc8nbk9cBOkSpp3j2SJUQmFnyQK6V/pR6II2oPRyZkMomug1Rc10hqlBHByMecq4zhV2uUw== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -4224,6 +4871,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/abort-controller@^3.1.9": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.9.tgz#47d323f754136a489e972d7fd465d534d72fcbff" + integrity sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/chunked-blob-reader-native@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.1.tgz#39045ed278ee1b6f4c12715c7565678557274c29" @@ -4250,6 +4905,17 @@ "@smithy/util-middleware" "^3.0.10" tslib "^2.6.2" +"@smithy/config-resolver@^3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.13.tgz#653643a77a33d0f5907a5e7582353886b07ba752" + integrity sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg== + dependencies: + "@smithy/node-config-provider" "^3.1.12" + "@smithy/types" "^3.7.2" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.11" + tslib "^2.6.2" + "@smithy/core@^2.5.2", "@smithy/core@^2.5.3": version "2.5.3" resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.3.tgz#1d5723f676b0d6ec08c515272f0ac03aa59fac72" @@ -4264,6 +4930,20 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/core@^2.5.5": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.5.tgz#c75b15caee9e58c800db3e6b99e9e373532d394a" + integrity sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw== + dependencies: + "@smithy/middleware-serde" "^3.0.11" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-stream" "^3.3.2" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/credential-provider-imds@^3.2.6", "@smithy/credential-provider-imds@^3.2.7": version "3.2.7" resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.7.tgz#6eedf87ba0238723ec46d8ce0f18e276685a702d" @@ -4275,6 +4955,27 @@ "@smithy/url-parser" "^3.0.10" tslib "^2.6.2" +"@smithy/credential-provider-imds@^3.2.8": + version "3.2.8" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz#27ed2747074c86a7d627a98e56f324a65cba88de" + integrity sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw== + dependencies: + "@smithy/node-config-provider" "^3.1.12" + "@smithy/property-provider" "^3.1.11" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.1.10": + version "3.1.10" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.10.tgz#0c1a3457e7a23b71cd71525ceb668f8569a84dad" + integrity sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.7.2" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + "@smithy/eventstream-codec@^3.1.9": version "3.1.9" resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.9.tgz#4271354e75e57d30771fca307da403896c657430" @@ -4294,6 +4995,23 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/eventstream-serde-browser@^3.0.14": + version "3.0.14" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.14.tgz#0c3584c7cde2e210aacdfbbd2b57c1d7e2ca3b95" + integrity sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.13" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.11.tgz#5edceba836debea165ea93145231036f6286d67c" + integrity sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/eventstream-serde-config-resolver@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.10.tgz#5c0b2ae0bb8e11cfa77851098e46f7350047ec8d" @@ -4311,6 +5029,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/eventstream-serde-node@^3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.13.tgz#5aebd7b553becee277e411a2b69f6af8c9d7b3a6" + integrity sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.13" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/eventstream-serde-universal@^3.0.12": version "3.0.12" resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.12.tgz#803d7beb29a3de4a64e91af97331a4654741c35f" @@ -4320,6 +5047,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/eventstream-serde-universal@^3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.13.tgz#609c922ea14a0a3eed23a28ac110344c935704eb" + integrity sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw== + dependencies: + "@smithy/eventstream-codec" "^3.1.10" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/fetch-http-handler@^4.1.0", "@smithy/fetch-http-handler@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.1.tgz#cead80762af4cdea11e7eeb627ea1c4835265dfa" @@ -4331,6 +5067,27 @@ "@smithy/util-base64" "^3.0.0" tslib "^2.6.2" +"@smithy/fetch-http-handler@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz#f034ff16416b37d92908a1381ef5fddbf4ef1879" + integrity sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA== + dependencies: + "@smithy/protocol-http" "^4.1.8" + "@smithy/querystring-builder" "^3.0.11" + "@smithy/types" "^3.7.2" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.10": + version "3.1.10" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.10.tgz#985e308189c2687a15004152b97506882ffb2b13" + integrity sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA== + dependencies: + "@smithy/chunked-blob-reader" "^4.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.1" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/hash-blob-browser@^3.1.8": version "3.1.9" resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.9.tgz#1f2c3ef6afbb0ce3e58a0129753850bb9267aae8" @@ -4341,6 +5098,16 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/hash-node@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.11.tgz#99e09ead3fc99c8cd7ca0f254ea0e35714f2a0d3" + integrity sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA== + dependencies: + "@smithy/types" "^3.7.2" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/hash-node@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.10.tgz#93c857b4bff3a48884886440fd9772924887e592" @@ -4351,6 +5118,15 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/hash-stream-node@^3.1.10": + version "3.1.10" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.10.tgz#94716b4556f4ccf2807e605f47bb5b018ed7dfb0" + integrity sha512-olomK/jZQ93OMayW1zfTHwcbwBdhcZOHsyWyiZ9h9IXvc1mCD/VuvzbLb3Gy/qNJwI4MANPLctTp2BucV2oU/Q== + dependencies: + "@smithy/types" "^3.7.2" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/hash-stream-node@^3.1.8": version "3.1.9" resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.9.tgz#97eb416811b7e7b9d036f0271588151b619759e9" @@ -4360,6 +5136,14 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/invalid-dependency@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz#8144d7b0af9d34ab5f672e1f674f97f8740bb9ae" + integrity sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/invalid-dependency@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.10.tgz#8616dee555916c24dec3e33b1e046c525efbfee3" @@ -4382,6 +5166,15 @@ dependencies: tslib "^2.6.2" +"@smithy/md5-js@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.11.tgz#27e4dab616348ff94aed24dc75e4017c582df40f" + integrity sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ== + dependencies: + "@smithy/types" "^3.7.2" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/md5-js@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.10.tgz#52ab927cf03cd1d24fed82d8ba936faf5632436e" @@ -4400,6 +5193,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/middleware-content-length@^3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz#6e08fe52739ac8fb3996088e0f8837e4b2ea187f" + integrity sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw== + dependencies: + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/middleware-endpoint@^3.2.2", "@smithy/middleware-endpoint@^3.2.3": version "3.2.3" resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.3.tgz#7dd3df0052fc55891522631a7751e613b6efd68a" @@ -4414,6 +5216,20 @@ "@smithy/util-middleware" "^3.0.10" tslib "^2.6.2" +"@smithy/middleware-endpoint@^3.2.5": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz#bdcfdf1f342cf933b0b8a709996f9a8fbb8148f4" + integrity sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg== + dependencies: + "@smithy/core" "^2.5.5" + "@smithy/middleware-serde" "^3.0.11" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + "@smithy/url-parser" "^3.0.11" + "@smithy/util-middleware" "^3.0.11" + tslib "^2.6.2" + "@smithy/middleware-retry@^3.0.26": version "3.0.27" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.27.tgz#2e4dda420178835cd2d416479505d313b601ba21" @@ -4429,6 +5245,21 @@ tslib "^2.6.2" uuid "^9.0.1" +"@smithy/middleware-retry@^3.0.30": + version "3.0.30" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz#2580322d0d28ad782b5b8c07c150b14efdc3b2f9" + integrity sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ== + dependencies: + "@smithy/node-config-provider" "^3.1.12" + "@smithy/protocol-http" "^4.1.8" + "@smithy/service-error-classification" "^3.0.11" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-retry" "^3.0.11" + tslib "^2.6.2" + uuid "^9.0.1" + "@smithy/middleware-serde@^3.0.10", "@smithy/middleware-serde@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.10.tgz#5f6c0b57b10089a21d355bd95e9b7d40378454d7" @@ -4437,6 +5268,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/middleware-serde@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz#c7d54e0add4f83e05c6878a011fc664e21022f12" + integrity sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/middleware-stack@^3.0.10", "@smithy/middleware-stack@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.10.tgz#73e2fde5d151440844161773a17ee13375502baf" @@ -4445,6 +5284,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/middleware-stack@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz#453af2096924e4064d9da4e053cfdf65d9a36acc" + integrity sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/node-config-provider@^3.1.10", "@smithy/node-config-provider@^3.1.11": version "3.1.11" resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.11.tgz#95feba85a5cb3de3fe9adfff1060b35fd556d023" @@ -4455,6 +5302,16 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/node-config-provider@^3.1.12": + version "3.1.12" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz#1b1d674fc83f943dc7b3017e37f16f374e878a6c" + integrity sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ== + dependencies: + "@smithy/property-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/node-http-handler@^1.0.2": version "1.1.0" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-1.1.0.tgz#887cee930b520e08043c9f41e463f8d8f5dae127" @@ -4477,6 +5334,17 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/node-http-handler@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz#b34685863b74dabdaf7860aa81b42d0d5437c7e0" + integrity sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA== + dependencies: + "@smithy/abort-controller" "^3.1.9" + "@smithy/protocol-http" "^4.1.8" + "@smithy/querystring-builder" "^3.0.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/property-provider@^3.1.10", "@smithy/property-provider@^3.1.9": version "3.1.10" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.10.tgz#ae00447c1060c194c3e1b9475f7c8548a70f8486" @@ -4485,6 +5353,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/property-provider@^3.1.11": + version "3.1.11" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.11.tgz#161cf1c2a2ada361e417382c57f5ba6fbca8acad" + integrity sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/protocol-http@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.2.0.tgz#a554e4dabb14508f0bc2cdef9c3710e2b294be04" @@ -4501,6 +5377,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/protocol-http@^4.1.8": + version "4.1.8" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.8.tgz#0461758671335f65e8ff3fc0885ab7ed253819c9" + integrity sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/querystring-builder@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-1.1.0.tgz#de6306104640ade34e59be33949db6cc64aa9d7f" @@ -4519,6 +5403,15 @@ "@smithy/util-uri-escape" "^3.0.0" tslib "^2.6.2" +"@smithy/querystring-builder@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz#2ed04adbe725671824c5613d0d6f9376d791a909" + integrity sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg== + dependencies: + "@smithy/types" "^3.7.2" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + "@smithy/querystring-parser@^3.0.10": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.10.tgz#62db744a1ed2cf90f4c08d2c73d365e033b4a11c" @@ -4527,6 +5420,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/querystring-parser@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz#9d3177ea19ce8462f18d9712b395239e1ca1f969" + integrity sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/service-error-classification@^3.0.10": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.10.tgz#941c549daf0e9abb84d3def1d9e1e3f0f74f5ba6" @@ -4534,6 +5435,13 @@ dependencies: "@smithy/types" "^3.7.1" +"@smithy/service-error-classification@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz#d3d7fc0aacd2e60d022507367e55c7939e5bcb8a" + integrity sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog== + dependencies: + "@smithy/types" "^3.7.2" + "@smithy/shared-ini-file-loader@^3.1.10", "@smithy/shared-ini-file-loader@^3.1.11": version "3.1.11" resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.11.tgz#0b4f98c4a66480956fbbefc4627c5dc09d891aea" @@ -4542,6 +5450,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/shared-ini-file-loader@^3.1.12": + version "3.1.12" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz#d98b1b663eb18935ce2cbc79024631d34f54042a" + integrity sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/signature-v4@^4.2.2": version "4.2.3" resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.3.tgz#abbca5e5fe9158422b3125b2956791a325a27f22" @@ -4556,6 +5472,20 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/signature-v4@^4.2.4": + version "4.2.4" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.4.tgz#3501d3d09fd82768867bfc00a7be4bad62f62f4d" + integrity sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.11" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/smithy-client@^3.4.3", "@smithy/smithy-client@^3.4.4": version "3.4.4" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.4.4.tgz#460870dc97d945fa2f390890359cf09d01131e0f" @@ -4569,6 +5499,26 @@ "@smithy/util-stream" "^3.3.1" tslib "^2.6.2" +"@smithy/smithy-client@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.5.0.tgz#65cff262801b009998c1196764ee69929ee06f8a" + integrity sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg== + dependencies: + "@smithy/core" "^2.5.5" + "@smithy/middleware-endpoint" "^3.2.5" + "@smithy/middleware-stack" "^3.0.11" + "@smithy/protocol-http" "^4.1.8" + "@smithy/types" "^3.7.2" + "@smithy/util-stream" "^3.3.2" + tslib "^2.6.2" + +"@smithy/types@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.0.0.tgz#7458c1c4dde3c6cf23221370acf5acd03215de6e" + integrity sha512-aNwIGSOgDOhtTRY/rrn2aeuQeKw/IFrQ998yK5l6Ah853WeWIEmFPs/EO4OpfADEdcK+igWnZytm/oUgkLgUYg== + dependencies: + tslib "^2.6.2" + "@smithy/types@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e" @@ -4583,6 +5533,13 @@ dependencies: tslib "^2.6.2" +"@smithy/types@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10" + integrity sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg== + dependencies: + tslib "^2.6.2" + "@smithy/url-parser@^3.0.10", "@smithy/url-parser@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.10.tgz#f389985a79766cff4a99af14979f01a17ce318da" @@ -4592,6 +5549,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/url-parser@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.11.tgz#e5f5ffabfb6230159167cf4cc970705fca6b8b2d" + integrity sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw== + dependencies: + "@smithy/querystring-parser" "^3.0.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/util-base64@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" @@ -4649,6 +5615,17 @@ bowser "^2.11.0" tslib "^2.6.2" +"@smithy/util-defaults-mode-browser@^3.0.30": + version "3.0.30" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz#6c0d95af3f15bef8f1fe3f6217cc4f5ba8df5554" + integrity sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg== + dependencies: + "@smithy/property-provider" "^3.1.11" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + bowser "^2.11.0" + tslib "^2.6.2" + "@smithy/util-defaults-mode-node@^3.0.26": version "3.0.27" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.27.tgz#a7248c9d9cb620827ab57ef9d1867bfe8aef42d0" @@ -4662,6 +5639,19 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/util-defaults-mode-node@^3.0.30": + version "3.0.30" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz#33cdb02f90944b9ff221e2f8e0904a63ac1e335f" + integrity sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow== + dependencies: + "@smithy/config-resolver" "^3.0.13" + "@smithy/credential-provider-imds" "^3.2.8" + "@smithy/node-config-provider" "^3.1.12" + "@smithy/property-provider" "^3.1.11" + "@smithy/smithy-client" "^3.5.0" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/util-endpoints@^2.1.5": version "2.1.6" resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.6.tgz#720cbd1a616ad7c099b77780f0cb0f1f9fc5d2df" @@ -4671,6 +5661,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/util-endpoints@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz#a088ebfab946a7219dd4763bfced82709894b82d" + integrity sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw== + dependencies: + "@smithy/node-config-provider" "^3.1.12" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/util-hex-encoding@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" @@ -4686,6 +5685,14 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/util-middleware@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.11.tgz#2ab5c17266b42c225e62befcffb048afa682b5bf" + integrity sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow== + dependencies: + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/util-retry@^3.0.10", "@smithy/util-retry@^3.0.9": version "3.0.10" resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.10.tgz#fc13e1b30e87af0cbecadf29ca83b171e2040440" @@ -4695,6 +5702,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/util-retry@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.11.tgz#d267e5ccb290165cee69732547fea17b695a7425" + integrity sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ== + dependencies: + "@smithy/service-error-classification" "^3.0.11" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@smithy/util-stream@^3.3.0", "@smithy/util-stream@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.1.tgz#a2636f435637ef90d64df2bb8e71cd63236be112" @@ -4709,6 +5725,20 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/util-stream@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.2.tgz#daeea26397e8541cf2499ce65bf0b8d528cba421" + integrity sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg== + dependencies: + "@smithy/fetch-http-handler" "^4.1.2" + "@smithy/node-http-handler" "^3.3.2" + "@smithy/types" "^3.7.2" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/util-uri-escape@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz#a8c5edaf19c0efdb9b51661e840549cf600a1808" @@ -4748,6 +5778,15 @@ "@smithy/types" "^3.7.1" tslib "^2.6.2" +"@smithy/util-waiter@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.2.0.tgz#1e52f870e77d2e5572025f7606053e6ff00df93d" + integrity sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg== + dependencies: + "@smithy/abort-controller" "^3.1.9" + "@smithy/types" "^3.7.2" + tslib "^2.6.2" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -6057,6 +7096,11 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== +"@types/uuid@^9.0.1": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" + integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== + "@types/webidl-conversions@*": version "7.0.0" resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz#2b8e60e33906459219aa587e9d1a612ae994cfe7" @@ -7465,6 +8509,14 @@ buffer@4.9.2: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffer@6.0.3, buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -10180,7 +11232,7 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== -events@^3.0.0, events@^3.3.0: +events@3.3.0, events@^3.0.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -11936,7 +12988,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -14760,6 +15812,13 @@ mlly@^1.1.0, mlly@^1.7.1: pkg-types "^1.1.1" ufo "^1.5.3" +mnemonist@0.38.3: + version "0.38.3" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.3.tgz#35ec79c1c1f4357cfda2fe264659c2775ccd7d9d" + integrity sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw== + dependencies: + obliterator "^1.6.1" + modify-values@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -15552,6 +16611,11 @@ object.values@^1.1.7: define-properties "^1.2.0" es-abstract "^1.22.1" +obliterator@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-1.6.1.tgz#dea03e8ab821f6c4d96a299e17aef6a3af994ef3" + integrity sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig== + omggif@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" @@ -18597,6 +19661,14 @@ stoppable@^1.1.0: resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + stream-events@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" @@ -18644,7 +19716,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18736,7 +19817,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18750,6 +19831,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -20497,7 +21585,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20515,6 +21603,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 4024159452846dac574510a88bc23e96bc1734ba Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 8 Jan 2025 15:11:39 +0000 Subject: [PATCH 002/210] Some type fixes and converting test case to TS. --- .../backend-core/src/objectStore/objectStore.ts | 16 +++++++++------- .../{component.spec.js => component.spec.ts} | 4 ++-- packages/server/src/environment.ts | 3 +++ packages/server/src/utilities/fileSystem/app.ts | 4 ++-- 4 files changed, 16 insertions(+), 11 deletions(-) rename packages/server/src/api/routes/tests/{component.spec.js => component.spec.ts} (88%) diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index 4f07abe7e2..0e2bb9d391 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -23,7 +23,7 @@ import { v4 } from "uuid" import { APP_PREFIX, APP_DEV_PREFIX } from "../db" import fsp from "fs/promises" import { ReadableStream } from "stream/web" -import { NodeJsRuntimeStreamingBlobPayloadOutputTypes } from "@smithy/types" +import { NodeJsClient } from "@smithy/types" const streamPipeline = promisify(stream.pipeline) // use this as a temporary store of buckets that are being created @@ -126,7 +126,7 @@ export function ObjectStore( } } - return new S3(config) + return new S3(config) as NodeJsClient } /** @@ -311,13 +311,15 @@ export async function retrieve( if (!response.Body) { throw new Error("Unable to retrieve object") } - const nodeResponse = - response.Body as NodeJsRuntimeStreamingBlobPayloadOutputTypes - // currently these are all strings if (STRING_CONTENT_TYPES.includes(response.ContentType)) { - return nodeResponse.toString() + return response.Body.transformToString() } else { - return nodeResponse + // this typecast is required - for some reason the AWS SDK V3 defines its own "ReadableStream" + // found in the @aws-sdk/types package which is meant to be the Node type, but due to the SDK + // supporting both the browser and Nodejs it is a polyfill which causes a type class with Node. + const readableStream = + response.Body.transformToWebStream() as ReadableStream + return stream.Readable.fromWeb(readableStream) } } diff --git a/packages/server/src/api/routes/tests/component.spec.js b/packages/server/src/api/routes/tests/component.spec.ts similarity index 88% rename from packages/server/src/api/routes/tests/component.spec.js rename to packages/server/src/api/routes/tests/component.spec.ts index c621afae0a..a7ca2d353a 100644 --- a/packages/server/src/api/routes/tests/component.spec.js +++ b/packages/server/src/api/routes/tests/component.spec.ts @@ -1,5 +1,5 @@ -const { checkBuilderEndpoint } = require("./utilities/TestFunctions") -const setup = require("./utilities") +import { checkBuilderEndpoint } from "./utilities/TestFunctions" +import * as setup from "./utilities" describe("/component", () => { let request = setup.getRequest() diff --git a/packages/server/src/environment.ts b/packages/server/src/environment.ts index 45d675ec3f..4e97176748 100644 --- a/packages/server/src/environment.ts +++ b/packages/server/src/environment.ts @@ -29,6 +29,7 @@ const DEFAULTS = { PLUGINS_DIR: "/plugins", FORKED_PROCESS_NAME: "main", JS_RUNNER_MEMORY_LIMIT: 64, + USE_LOCAL_COMPONENT_LIBS: coreEnv.isDev() || coreEnv.isTest(), } const QUERY_THREAD_TIMEOUT = @@ -114,6 +115,8 @@ const environment = { DEFAULTS.JS_RUNNER_MEMORY_LIMIT, LOG_JS_ERRORS: process.env.LOG_JS_ERRORS, DISABLE_USER_SYNC: process.env.DISABLE_USER_SYNC, + USE_LOCAL_COMPONENT_LIBS: + process.env.USE_LOCAL_COMPONENT_LIBS || DEFAULTS.USE_LOCAL_COMPONENT_LIBS, // old CLIENT_ID: process.env.CLIENT_ID, _set(key: string, value: any) { diff --git a/packages/server/src/utilities/fileSystem/app.ts b/packages/server/src/utilities/fileSystem/app.ts index 642017d2da..be7c9977c3 100644 --- a/packages/server/src/utilities/fileSystem/app.ts +++ b/packages/server/src/utilities/fileSystem/app.ts @@ -36,11 +36,11 @@ export const getComponentLibraryManifest = async (library: string) => { const appId = context.getAppId() const filename = "manifest.json" - if (env.isDev() || env.isTest()) { + if (env.USE_LOCAL_COMPONENT_LIBS) { const db = context.getAppDB() const app = await db.get(DocumentType.APP_METADATA) - if (shouldServeLocally(app.version) || env.isTest()) { + if (shouldServeLocally(app.version) || env.USE_LOCAL_COMPONENT_LIBS) { const paths = [ join(TOP_LEVEL_PATH, "packages/client", filename), join(process.cwd(), "client", filename), From 929a0f332142c0552882be03cc88160c3dd686af Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 8 Jan 2025 17:18:39 +0000 Subject: [PATCH 003/210] Updating worker to use same system for setting env vars in tests as server/backend-core. --- .../routes/system/tests/environment.spec.ts | 3 +- packages/worker/src/environment.ts | 27 ++++++++++++++++++ .../worker/src/tests/TestConfiguration.ts | 28 ------------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/worker/src/api/routes/system/tests/environment.spec.ts b/packages/worker/src/api/routes/system/tests/environment.spec.ts index 58f523648d..b94124f112 100644 --- a/packages/worker/src/api/routes/system/tests/environment.spec.ts +++ b/packages/worker/src/api/routes/system/tests/environment.spec.ts @@ -1,4 +1,5 @@ import { TestConfiguration } from "../../../../tests" +import { withEnv } from "../../../../environment" jest.unmock("node-fetch") @@ -32,7 +33,7 @@ describe("/api/system/environment", () => { }) it("returns the expected environment for self hosters", async () => { - await config.withEnv({ SELF_HOSTED: true }, async () => { + await withEnv({ SELF_HOSTED: true }, async () => { const env = await config.api.environment.getEnvironment() expect(env.body).toEqual({ cloud: false, diff --git a/packages/worker/src/environment.ts b/packages/worker/src/environment.ts index 3a9efd70ce..e84efdd575 100644 --- a/packages/worker/src/environment.ts +++ b/packages/worker/src/environment.ts @@ -1,6 +1,7 @@ import { env as coreEnv } from "@budibase/backend-core" import { ServiceType } from "@budibase/types" import { join } from "path" +import cloneDeep from "lodash/cloneDeep" coreEnv._set("SERVICE_TYPE", ServiceType.WORKER) @@ -92,6 +93,32 @@ if (!environment.APPS_URL) { : "http://app-service:4002" } +export function setEnv(newEnvVars: Partial): () => void { + const oldEnv = cloneDeep(environment) + + let key: keyof typeof newEnvVars + for (key in newEnvVars) { + environment._set(key, newEnvVars[key]) + } + + return () => { + for (const [key, value] of Object.entries(oldEnv)) { + environment._set(key, value) + } + } +} + +export function withEnv(envVars: Partial, f: () => T) { + const cleanup = setEnv(envVars) + const result = f() + if (result instanceof Promise) { + return result.finally(cleanup) + } else { + cleanup() + return result + } +} + // clean up any environment variable edge cases for (let [key, value] of Object.entries(environment)) { // handle the edge case of "0" to disable an environment variable diff --git a/packages/worker/src/tests/TestConfiguration.ts b/packages/worker/src/tests/TestConfiguration.ts index 440d6dc776..f544a478c4 100644 --- a/packages/worker/src/tests/TestConfiguration.ts +++ b/packages/worker/src/tests/TestConfiguration.ts @@ -247,34 +247,6 @@ class TestConfiguration { return { message: "Admin user only endpoint.", status: 403 } } - async withEnv(newEnvVars: Partial, f: () => Promise) { - let cleanup = this.setEnv(newEnvVars) - try { - await f() - } finally { - cleanup() - } - } - - /* - * Sets the environment variables to the given values and returns a function - * that can be called to reset the environment variables to their original values. - */ - setEnv(newEnvVars: Partial): () => void { - const oldEnv = cloneDeep(env) - - let key: keyof typeof newEnvVars - for (key in newEnvVars) { - env._set(key, newEnvVars[key]) - } - - return () => { - for (const [key, value] of Object.entries(oldEnv)) { - env._set(key, value) - } - } - } - // USERS async createDefaultUser() { From 6b29a47f5fffe288dfc7c041431e2ea5635edeeb Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 8 Jan 2025 18:08:24 +0000 Subject: [PATCH 004/210] Adding test case for fetching the component/client libraries. --- .../server/src/api/controllers/application.ts | 11 +++-- .../src/api/routes/tests/component.spec.ts | 44 ++++++++++++++++--- .../server/src/utilities/fileSystem/app.ts | 4 +- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 7ffd075ec0..316e307cf8 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -6,8 +6,8 @@ import { } from "../../db/views/staticViews" import { backupClientLibrary, - createApp, - deleteApp, + uploadAppFiles, + deleteAppFiles, revertClientLibrary, updateClientLibrary, } from "../../utilities/fileSystem" @@ -377,9 +377,8 @@ async function performAppCreate( const response = await db.put(newApplication, { force: true }) newApplication._rev = response.rev - /* istanbul ignore next */ - if (!env.isTest()) { - await createApp(appId) + if (!env.USE_LOCAL_COMPONENT_LIBS) { + await uploadAppFiles(appId) } const latestMigrationId = appMigrations.getLatestEnabledMigrationId() @@ -665,7 +664,7 @@ async function destroyApp(ctx: UserCtx) { await events.app.deleted(app) if (!env.isTest()) { - await deleteApp(appId) + await deleteAppFiles(appId) } await removeAppFromUserRoles(ctx, appId) diff --git a/packages/server/src/api/routes/tests/component.spec.ts b/packages/server/src/api/routes/tests/component.spec.ts index a7ca2d353a..9aab44f7cb 100644 --- a/packages/server/src/api/routes/tests/component.spec.ts +++ b/packages/server/src/api/routes/tests/component.spec.ts @@ -1,4 +1,5 @@ import { checkBuilderEndpoint } from "./utilities/TestFunctions" +import * as env from "../../../environment" import * as setup from "./utilities" describe("/component", () => { @@ -12,13 +13,42 @@ describe("/component", () => { }) describe("fetch definitions", () => { - it("should be able to fetch definitions", async () => { - const res = await request - .get(`/api/${config.getAppId()}/components/definitions`) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(200) - expect(res.body["@budibase/standard-components/container"]).toBeDefined() + it("should be able to fetch definitions locally", async () => { + await env.withEnv( + { + USE_LOCAL_COMPONENT_LIBS: "1", + }, + async () => { + const res = await request + .get(`/api/${config.getAppId()}/components/definitions`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect( + res.body["@budibase/standard-components/container"] + ).toBeDefined() + } + ) + }) + + it("should be able to fetch definitions from object store", async () => { + await env.withEnv( + { + USE_LOCAL_COMPONENT_LIBS: "0", + }, + async () => { + // init again to make an app with a real component lib + await config.init() + const res = await request + .get(`/api/${config.getAppId()}/components/definitions`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect( + res.body["@budibase/standard-components/container"] + ).toBeDefined() + } + ) }) it("should apply authorization to endpoint", async () => { diff --git a/packages/server/src/utilities/fileSystem/app.ts b/packages/server/src/utilities/fileSystem/app.ts index be7c9977c3..890fff5f06 100644 --- a/packages/server/src/utilities/fileSystem/app.ts +++ b/packages/server/src/utilities/fileSystem/app.ts @@ -16,7 +16,7 @@ export const NODE_MODULES_PATH = join(TOP_LEVEL_PATH, "node_modules") * @param appId The ID of the app which is being created. * @return once promise completes app resources should be ready in object store. */ -export const createApp = async (appId: string) => { +export const uploadAppFiles = async (appId: string) => { await updateClientLibrary(appId) } @@ -25,7 +25,7 @@ export const createApp = async (appId: string) => { * @param appId The ID of the app which is being deleted. * @return once promise completes the app resources will be removed from object store. */ -export const deleteApp = async (appId: string) => { +export const deleteAppFiles = async (appId: string) => { await objectStore.deleteFolder(ObjectStoreBuckets.APPS, `${appId}/`) } From 2f50a429bb1968e37c19257f51fcecaa2c707a1f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 8 Jan 2025 18:12:56 +0000 Subject: [PATCH 005/210] Linting. --- packages/worker/src/tests/TestConfiguration.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/worker/src/tests/TestConfiguration.ts b/packages/worker/src/tests/TestConfiguration.ts index f544a478c4..b4d5061db7 100644 --- a/packages/worker/src/tests/TestConfiguration.ts +++ b/packages/worker/src/tests/TestConfiguration.ts @@ -35,7 +35,6 @@ import { } from "@budibase/types" import API from "./api" import jwt, { Secret } from "jsonwebtoken" -import cloneDeep from "lodash/fp/cloneDeep" class TestConfiguration { server: any From 977e0bfefe17769b0c291abc50ace63ca57c1bad Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 9 Jan 2025 14:55:40 +0000 Subject: [PATCH 006/210] Adding client build to server test for component testing. --- .github/workflows/budibase_ci.yml | 3 +++ package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index e81925876b..e294e50e8d 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -202,6 +202,9 @@ jobs: - run: yarn --frozen-lockfile + - name: Build client library - necessary for component tests + run: yarn build:client + - name: Set up PostgreSQL 16 if: matrix.datasource == 'postgres' run: | diff --git a/package.json b/package.json index 771d3cefd5..c0b295728e 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "lint:fix:eslint": "eslint --fix --max-warnings=0 packages", "lint:fix:prettier": "prettier --write \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\"", "lint:fix": "yarn run lint:fix:eslint && yarn run lint:fix:prettier", + "build:client": "lerna run --stream build --scope @budibase/client", "build:specs": "lerna run --stream specs", "build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild", "build:docker:airgap:single": "SINGLE_IMAGE=1 node hosting/scripts/airgapped/airgappedDockerBuild", From e765cbafa1368b8ff5f48eebc1daebb0ccd3a313 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 9 Jan 2025 17:27:20 +0000 Subject: [PATCH 007/210] Comment fix. --- packages/backend-core/src/objectStore/objectStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index 0e2bb9d391..bdbab63767 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -316,7 +316,7 @@ export async function retrieve( } else { // this typecast is required - for some reason the AWS SDK V3 defines its own "ReadableStream" // found in the @aws-sdk/types package which is meant to be the Node type, but due to the SDK - // supporting both the browser and Nodejs it is a polyfill which causes a type class with Node. + // supporting both the browser and Nodejs it is a polyfill which causes a type clash with Node. const readableStream = response.Body.transformToWebStream() as ReadableStream return stream.Readable.fromWeb(readableStream) From f27f4d601ab39cd189efe37981f55bb3c66e84ab Mon Sep 17 00:00:00 2001 From: joecks Date: Thu, 30 Jan 2025 20:55:23 +0100 Subject: [PATCH 008/210] Fixes 503 errors on /api/global/auth/default/oidc/configs/ using https Similar to the http solution in the default config this fixes the same issue when https is used. Related to https://github.com/Budibase/budibase/issues/5969 https://github.com/Budibase/budibase/discussions/5807 --- hosting/letsencrypt/nginx-ssl.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hosting/letsencrypt/nginx-ssl.conf b/hosting/letsencrypt/nginx-ssl.conf index b3f51e5cc5..710ce2d22d 100644 --- a/hosting/letsencrypt/nginx-ssl.conf +++ b/hosting/letsencrypt/nginx-ssl.conf @@ -41,6 +41,11 @@ server { } location ~ ^/api/(system|admin|global)/ { + # Enable buffering for potentially large OIDC configs + proxy_buffering on; + proxy_buffer_size 16k; + proxy_buffers 4 32k; + proxy_pass http://127.0.0.1:4002; } From 73d3ce2038c4086b99e4494b6d6caf6de7faa6ad Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 11:01:09 +0000 Subject: [PATCH 009/210] Initial work on support dragging new components on to grid screens and typing improvements for client --- .../new/_components/NewComponentPanel.svelte | 12 +- packages/builder/src/stores/builder/app.ts | 6 +- .../builder/src/stores/builder/components.ts | 82 +------- .../builder/src/stores/builder/navigation.ts | 4 +- .../builder/src/stores/builder/preview.ts | 17 +- packages/client/package.json | 2 +- .../client/src/components/ClientApp.svelte | 2 + .../preview/GridNewComponentDNDHandler.svelte | 166 +++++++++++++++ packages/client/src/index.d.ts | 5 - packages/client/src/index.js | 138 ------------- packages/client/src/index.ts | 195 +++++++++++++++++- packages/client/src/stores/dnd.js | 11 +- packages/client/src/stores/index.js | 2 +- packages/client/src/stores/screens.js | 4 + packages/client/vite.config.mjs | 10 +- packages/types/src/ui/components/index.ts | 10 + 16 files changed, 430 insertions(+), 236 deletions(-) create mode 100644 packages/client/src/components/preview/GridNewComponentDNDHandler.svelte delete mode 100644 packages/client/src/index.d.ts delete mode 100644 packages/client/src/index.js diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index aa0b26f6b7..784642787b 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -13,6 +13,11 @@ import { fly } from "svelte/transition" import { findComponentPath } from "@/helpers/components" + // Smallest possible 1x1 transparent GIF + const ghost = new Image(1, 1) + ghost.src = + "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + let searchString let searchRef let selectedIndex @@ -217,7 +222,8 @@ } }) - const onDragStart = component => { + const onDragStart = (e, component) => { + e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } @@ -250,7 +256,7 @@ {#each category.children as component}
onDragStart(component.component)} + on:dragstart={e => onDragStart(e, component.component)} on:dragend={onDragEnd} class="component" class:selected={selectedIndex === orderMap[component.component]} @@ -308,7 +314,7 @@ } .component:hover { background: var(--spectrum-global-color-gray-300); - cursor: pointer; + cursor: grab; } .component :global(.spectrum-Body) { line-height: 1.2 !important; diff --git a/packages/builder/src/stores/builder/app.ts b/packages/builder/src/stores/builder/app.ts index 3c8ed4afc1..abebb5d9f1 100644 --- a/packages/builder/src/stores/builder/app.ts +++ b/packages/builder/src/stores/builder/app.ts @@ -39,7 +39,7 @@ interface AppMetaState { appInstance: { _id: string } | null initialised: boolean hasAppPackage: boolean - usedPlugins: Plugin[] | null + usedPlugins: Plugin[] automations: AutomationSettings routes: { [key: string]: any } version?: string @@ -76,7 +76,7 @@ export const INITIAL_APP_META_STATE: AppMetaState = { appInstance: null, initialised: false, hasAppPackage: false, - usedPlugins: null, + usedPlugins: [], automations: {}, routes: {}, } @@ -109,7 +109,7 @@ export class AppMetaStore extends BudiStore { appInstance: app.instance, revertableVersion: app.revertableVersion, upgradableVersion: app.upgradableVersion, - usedPlugins: app.usedPlugins || null, + usedPlugins: app.usedPlugins || [], icon: app.icon, features: { ...INITIAL_APP_META_STATE.features, diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index a8f52e2660..ad221cc67d 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -139,10 +139,6 @@ export class ComponentStore extends BudiStore { /** * Retrieve the component definition object - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {object} */ getDefinition(componentType: string) { if (!componentType) { @@ -151,10 +147,6 @@ export class ComponentStore extends BudiStore { return get(this.store).components[componentType] } - /** - * - * @returns {object} - */ getDefaultDatasource() { // Ignore users table const validTables = get(tables).list.filter(x => x._id !== "ta_users") @@ -188,8 +180,6 @@ export class ComponentStore extends BudiStore { /** * Takes an enriched component instance and applies any required migration * logic - * @param {object} enrichedComponent - * @returns {object} migrated Component */ migrateSettings(enrichedComponent: Component) { const componentPrefix = "@budibase/standard-components" @@ -230,22 +220,15 @@ export class ComponentStore extends BudiStore { for (let setting of filterableTypes || []) { const isLegacy = Array.isArray(enrichedComponent[setting.key]) if (isLegacy) { - const processedSetting = utils.processSearchFilters( + enrichedComponent[setting.key] = utils.processSearchFilters( enrichedComponent[setting.key] ) - enrichedComponent[setting.key] = processedSetting migrated = true } } return migrated } - /** - * - * @param {object} component - * @param {object} opts - * @returns - */ enrichEmptySettings( component: Component, opts: { screen?: Screen; parent?: Component; useDefaultValues?: boolean } @@ -427,17 +410,10 @@ export class ComponentStore extends BudiStore { } } - /** - * - * @param {string} componentName - * @param {object} presetProps - * @param {object} parent - * @returns - */ createInstance( componentType: string, - presetProps: any, - parent: any + presetProps?: Record, + parent?: Component ): Component | null { const screen = get(selectedScreen) if (!screen) { @@ -463,7 +439,7 @@ export class ComponentStore extends BudiStore { _id: Helpers.uuid(), _component: definition.component, _styles: { - normal: {}, + normal: { ...presetProps?._styles?.normal }, hover: {}, active: {}, }, @@ -512,19 +488,11 @@ export class ComponentStore extends BudiStore { } } - /** - * - * @param {string} componentName - * @param {object} presetProps - * @param {object} parent - * @param {number} index - * @returns - */ async create( componentType: string, - presetProps: any, - parent: Component, - index: number + presetProps?: Record, + parent?: Component, + index?: number ) { const state = get(this.store) const componentInstance = this.createInstance( @@ -611,13 +579,6 @@ export class ComponentStore extends BudiStore { return componentInstance } - /** - * - * @param {function} patchFn - * @param {string} componentId - * @param {string} screenId - * @returns - */ async patch( patchFn: (component: Component, screen: Screen) => any, componentId?: string, @@ -652,11 +613,6 @@ export class ComponentStore extends BudiStore { await screenStore.patch(patchScreen, screenId) } - /** - * - * @param {object} component - * @returns - */ async delete(component: Component) { if (!component) { return @@ -737,13 +693,6 @@ export class ComponentStore extends BudiStore { }) } - /** - * - * @param {object} targetComponent - * @param {string} mode - * @param {object} targetScreen - * @returns - */ async paste( targetComponent: Component, mode: string, @@ -1101,6 +1050,7 @@ export class ComponentStore extends BudiStore { async updateStyles(styles: Record, id: string) { const patchFn = (component: Component) => { + delete component._placeholder component._styles.normal = { ...component._styles.normal, ...styles, @@ -1231,7 +1181,7 @@ export class ComponentStore extends BudiStore { } // Create new parent instance - const newParentDefinition = this.createInstance(parentType, null, parent) + const newParentDefinition = this.createInstance(parentType) if (!newParentDefinition) { return } @@ -1267,10 +1217,6 @@ export class ComponentStore extends BudiStore { /** * Check if the components settings have been cached - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {boolean} */ isCached(componentType: string) { const settings = get(this.store).settingsCache @@ -1279,11 +1225,6 @@ export class ComponentStore extends BudiStore { /** * Cache component settings - * @param {string} componentType - * @param {object} definition - * @example - * '@budibase/standard-components/container' - * @returns {array} the settings */ cacheSettings(componentType: string, definition: ComponentDefinition | null) { let settings: ComponentSetting[] = [] @@ -1313,12 +1254,7 @@ export class ComponentStore extends BudiStore { /** * Retrieve an array of the component settings. * These settings are cached because they cannot change at run time. - * * Searches a component's definition for a setting matching a certain predicate. - * @param {string} componentType - * @example - * '@budibase/standard-components/container' - * @returns {Array} */ getComponentSettings(componentType: string) { if (!componentType) { diff --git a/packages/builder/src/stores/builder/navigation.ts b/packages/builder/src/stores/builder/navigation.ts index 1574efee2a..1ef019a11c 100644 --- a/packages/builder/src/stores/builder/navigation.ts +++ b/packages/builder/src/stores/builder/navigation.ts @@ -4,15 +4,13 @@ import { appStore } from "@/stores/builder" import { BudiStore } from "../BudiStore" import { AppNavigation, AppNavigationLink, UIObject } from "@budibase/types" -interface BuilderNavigationStore extends AppNavigation {} - export const INITIAL_NAVIGATION_STATE = { navigation: "Top", links: [], textAlign: "Left", } -export class NavigationStore extends BudiStore { +export class NavigationStore extends BudiStore { constructor() { super(INITIAL_NAVIGATION_STATE) } diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 87b2b9355e..9aeaf99346 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -1,5 +1,7 @@ import { get } from "svelte/store" import { BudiStore } from "../BudiStore" +import { componentStore } from "./components" +import { selectedScreen } from "./screens" type PreviewDevice = "desktop" | "tablet" | "mobile" type PreviewEventHandler = (name: string, payload?: any) => void @@ -54,10 +56,21 @@ export class PreviewStore extends BudiStore { })) } - startDrag(component: any) { + async startDrag(componentType: string) { + let componentId + const gridScreen = get(selectedScreen)?.props?.layout === "grid" + if (gridScreen) { + const component = await componentStore.create(componentType, { + _placeholder: true, + _styles: { normal: { opacity: 0 } }, + }) + componentId = component?._id + } this.sendEvent("dragging-new-component", { dragging: true, - component, + componentType, + componentId, + gridScreen, }) } diff --git a/packages/client/package.json b/packages/client/package.json index 2ae049f6d0..72be403698 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -5,7 +5,7 @@ "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", "type": "module", - "svelte": "src/index.js", + "svelte": "src/index.ts", "exports": { ".": { "import": "./dist/budibase-client.js", diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 2840d82f47..7144105fd8 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -44,6 +44,7 @@ import MaintenanceScreen from "components/MaintenanceScreen.svelte" import SnippetsProvider from "./context/SnippetsProvider.svelte" import EmbedProvider from "./context/EmbedProvider.svelte" + import GridNewComponentDNDHandler from "components/preview/GridNewComponentDNDHandler.svelte" // Provide contexts setContext("sdk", SDK) @@ -266,6 +267,7 @@ {#if $builderStore.inBuilder} + {/if} diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte new file mode 100644 index 0000000000..8a3da6f419 --- /dev/null +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -0,0 +1,166 @@ + diff --git a/packages/client/src/index.d.ts b/packages/client/src/index.d.ts deleted file mode 100644 index 7e13670b33..0000000000 --- a/packages/client/src/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -interface Window { - "##BUDIBASE_APP_ID##": string - "##BUDIBASE_IN_BUILDER##": string - MIGRATING_APP: boolean -} diff --git a/packages/client/src/index.js b/packages/client/src/index.js deleted file mode 100644 index 8a48aa08e5..0000000000 --- a/packages/client/src/index.js +++ /dev/null @@ -1,138 +0,0 @@ -import ClientApp from "./components/ClientApp.svelte" -import UpdatingApp from "./components/UpdatingApp.svelte" -import { - builderStore, - appStore, - blockStore, - componentStore, - environmentStore, - dndStore, - eventStore, - hoverStore, - stateStore, -} from "./stores" -import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" -import { get } from "svelte/store" -import { initWebsocket } from "./websocket.js" - -// Provide svelte and svelte/internal as globals for custom components -import * as svelte from "svelte" -import * as internal from "svelte/internal" - -window.svelte_internal = internal -window.svelte = svelte - -// Initialise spectrum icons -loadSpectrumIcons() - -let app - -const loadBudibase = async () => { - // Update builder store with any builder flags - builderStore.set({ - ...get(builderStore), - inBuilder: !!window["##BUDIBASE_IN_BUILDER##"], - layout: window["##BUDIBASE_PREVIEW_LAYOUT##"], - screen: window["##BUDIBASE_PREVIEW_SCREEN##"], - selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"], - previewId: window["##BUDIBASE_PREVIEW_ID##"], - theme: window["##BUDIBASE_PREVIEW_THEME##"], - customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], - previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], - navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], - hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], - usedPlugins: window["##BUDIBASE_USED_PLUGINS##"], - location: window["##BUDIBASE_LOCATION##"], - snippets: window["##BUDIBASE_SNIPPETS##"], - componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"], - }) - - // Set app ID - this window flag is set by both the preview and the real - // server rendered app HTML - appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) - - // Set the flag used to determine if the app is being loaded via an iframe - appStore.actions.setAppEmbedded( - window["##BUDIBASE_APP_EMBEDDED##"] === "true" - ) - - if (window.MIGRATING_APP) { - new UpdatingApp({ - target: window.document.body, - }) - return - } - - // Fetch environment info - if (!get(environmentStore)?.loaded) { - await environmentStore.actions.fetchEnvironment() - } - - // Register handler for runtime events from the builder - window.handleBuilderRuntimeEvent = (type, data) => { - if (!window["##BUDIBASE_IN_BUILDER##"]) { - return - } - if (type === "event-completed") { - eventStore.actions.resolveEvent(data) - } else if (type === "eject-block") { - const block = blockStore.actions.getBlock(data) - block?.eject() - } else if (type === "dragging-new-component") { - const { dragging, component } = data - if (dragging) { - const definition = - componentStore.actions.getComponentDefinition(component) - dndStore.actions.startDraggingNewComponent({ component, definition }) - } else { - dndStore.actions.reset() - } - } else if (type === "request-context") { - const { selectedComponentInstance, screenslotInstance } = - get(componentStore) - const instance = selectedComponentInstance || screenslotInstance - const context = instance?.getDataContext() - let stringifiedContext = null - try { - stringifiedContext = JSON.stringify(context) - } catch (error) { - // Ignore - invalid context - } - eventStore.actions.dispatchEvent("provide-context", { - context: stringifiedContext, - }) - } else if (type === "hover-component") { - hoverStore.actions.hoverComponent(data, false) - } else if (type === "builder-meta") { - builderStore.actions.setMetadata(data) - } else if (type === "builder-state") { - const [[key, value]] = Object.entries(data) - stateStore.actions.setValue(key, value) - } - } - - // Register any custom components - if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) { - window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => { - componentStore.actions.registerCustomComponent(component) - }) - } - - // Make a callback available for custom component bundles to register - // themselves at runtime - window.registerCustomComponent = - componentStore.actions.registerCustomComponent - - // Initialise websocket - initWebsocket() - - // Create app if one hasn't been created yet - if (!app) { - app = new ClientApp({ - target: window.document.body, - }) - } -} - -// Attach to window so the HTML template can call this when it loads -window.loadBudibase = loadBudibase diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 08330a60fa..e7d454e2f1 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,6 +1,83 @@ +import ClientApp from "./components/ClientApp.svelte" +import UpdatingApp from "./components/UpdatingApp.svelte" +import { + builderStore, + appStore, + blockStore, + componentStore, + environmentStore, + dndStore, + eventStore, + hoverStore, + stateStore, +} from "@/stores" +import { get } from "svelte/store" +import { initWebsocket } from "@/websocket" import { APIClient } from "@budibase/frontend-core" -import type { ActionTypes } from "./constants" +import type { ActionTypes } from "@/constants" import { Readable } from "svelte/store" +import { + Screen, + Layout, + Theme, + AppCustomTheme, + PreviewDevice, + AppNavigation, + Plugin, + Snippet, + UIComponentError, + CustomComponent, +} from "@budibase/types" + +// Provide svelte and svelte/internal as globals for custom components +import * as svelte from "svelte" +// @ts-ignore +import * as internal from "svelte/internal" +window.svelte_internal = internal +window.svelte = svelte + +// Initialise spectrum icons +// eslint-disable-next-line local-rules/no-budibase-imports +import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" +loadSpectrumIcons() + +// Extend global window scope +declare global { + interface Window { + // Data from builder + "##BUDIBASE_APP_ID##"?: string + "##BUDIBASE_IN_BUILDER##"?: true + "##BUDIBASE_PREVIEW_LAYOUT##"?: Layout + "##BUDIBASE_PREVIEW_SCREEN##"?: Screen + "##BUDIBASE_SELECTED_COMPONENT_ID##"?: string + "##BUDIBASE_PREVIEW_ID##"?: number + "##BUDIBASE_PREVIEW_THEME##"?: Theme + "##BUDIBASE_PREVIEW_CUSTOM_THEME##"?: AppCustomTheme + "##BUDIBASE_PREVIEW_DEVICE##"?: PreviewDevice + "##BUDIBASE_APP_EMBEDDED##"?: string // This is a bool wrapped in a string + "##BUDIBASE_PREVIEW_NAVIGATION##"?: AppNavigation + "##BUDIBASE_HIDDEN_COMPONENT_IDS##"?: string[] + "##BUDIBASE_USED_PLUGINS##"?: Plugin[] + "##BUDIBASE_LOCATION##"?: { + protocol: string + hostname: string + port: string + } + "##BUDIBASE_SNIPPETS##"?: Snippet[] + "##BUDIBASE_COMPONENT_ERRORS##"?: Record[] + "##BUDIBASE_CUSTOM_COMPONENTS##"?: CustomComponent[] + + // Other flags + MIGRATING_APP: boolean + + // Client additions + handleBuilderRuntimeEvent: (type: string, data: any) => void + registerCustomComponent: typeof componentStore.actions.registerCustomComponent + loadBudibase: typeof loadBudibase + svelte: typeof svelte + svelte_internal: typeof internal + } +} export interface SDK { API: APIClient @@ -29,3 +106,119 @@ export type Component = Readable<{ }> export type Context = Readable<{}> + +let app: ClientApp + +const loadBudibase = async () => { + // Update builder store with any builder flags + builderStore.set({ + ...get(builderStore), + inBuilder: !!window["##BUDIBASE_IN_BUILDER##"], + layout: window["##BUDIBASE_PREVIEW_LAYOUT##"], + screen: window["##BUDIBASE_PREVIEW_SCREEN##"], + selectedComponentId: window["##BUDIBASE_SELECTED_COMPONENT_ID##"], + previewId: window["##BUDIBASE_PREVIEW_ID##"], + theme: window["##BUDIBASE_PREVIEW_THEME##"], + customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], + previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], + navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], + hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], + usedPlugins: window["##BUDIBASE_USED_PLUGINS##"], + location: window["##BUDIBASE_LOCATION##"], + snippets: window["##BUDIBASE_SNIPPETS##"], + componentErrors: window["##BUDIBASE_COMPONENT_ERRORS##"], + }) + + // Set app ID - this window flag is set by both the preview and the real + // server rendered app HTML + appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) + + // Set the flag used to determine if the app is being loaded via an iframe + appStore.actions.setAppEmbedded( + window["##BUDIBASE_APP_EMBEDDED##"] === "true" + ) + + if (window.MIGRATING_APP) { + new UpdatingApp({ + target: window.document.body, + }) + return + } + + // Fetch environment info + if (!get(environmentStore)?.loaded) { + await environmentStore.actions.fetchEnvironment() + } + + // Register handler for runtime events from the builder + window.handleBuilderRuntimeEvent = (type, data) => { + if (!window["##BUDIBASE_IN_BUILDER##"]) { + return + } + if (type === "event-completed") { + eventStore.actions.resolveEvent(data) + } else if (type === "eject-block") { + const block = blockStore.actions.getBlock(data) + block?.eject() + } else if (type === "dragging-new-component") { + const { dragging, component, componentId } = data + if (dragging) { + const definition = + componentStore.actions.getComponentDefinition(component) + dndStore.actions.startDraggingNewComponent({ + component, + definition, + componentId, + }) + } else { + dndStore.actions.reset() + } + } else if (type === "request-context") { + const { selectedComponentInstance, screenslotInstance } = + get(componentStore) + const instance = selectedComponentInstance || screenslotInstance + const context = instance?.getDataContext() + let stringifiedContext = null + try { + stringifiedContext = JSON.stringify(context) + } catch (error) { + // Ignore - invalid context + } + eventStore.actions.dispatchEvent("provide-context", { + context: stringifiedContext, + }) + } else if (type === "hover-component") { + hoverStore.actions.hoverComponent(data, false) + } else if (type === "builder-meta") { + builderStore.actions.setMetadata(data) + } else if (type === "builder-state") { + const [[key, value]] = Object.entries(data) + stateStore.actions.setValue(key, value) + } + } + + // Register any custom components + if (window["##BUDIBASE_CUSTOM_COMPONENTS##"]) { + window["##BUDIBASE_CUSTOM_COMPONENTS##"].forEach(component => { + componentStore.actions.registerCustomComponent(component) + }) + } + + // Make a callback available for custom component bundles to register + // themselves at runtime + window.registerCustomComponent = + componentStore.actions.registerCustomComponent + + // Initialise websocket + initWebsocket() + + // Create app if one hasn't been created yet + if (!app) { + app = new ClientApp({ + target: window.document.body, + }) + } +} + +// Attach to window so the HTML template can call this when it loads +window.loadBudibase = loadBudibase diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 43d4eeeed8..5cfb12c7d2 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -21,7 +21,11 @@ const createDndStore = () => { }) } - const startDraggingNewComponent = ({ component, definition }) => { + const startDraggingNewComponent = ({ + component, + definition, + componentId, + }) => { if (!component) { return } @@ -38,6 +42,7 @@ const createDndStore = () => { bounds: { height, width }, index: null, newComponentType: component, + newComponentId: componentId, }, }) } @@ -82,6 +87,10 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) +export const dndNewComponentId = derivedMemo( + dndStore, + x => x.source?.newComponentId +) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index f2b80ed732..268b0cc4bf 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -2,7 +2,7 @@ export { authStore } from "./auth" export { appStore } from "./app" export { notificationStore } from "./notification" export { routeStore } from "./routes" -export { screenStore } from "./screens" +export { screenStore, isGridScreen } from "./screens" export { builderStore } from "./builder" export { dataSourceStore } from "./dataSource" export { confirmationStore } from "./confirmation" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index a7277ca2b5..f85675e389 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -198,3 +198,7 @@ const createScreenStore = () => { } export const screenStore = createScreenStore() + +export const isGridScreen = derived(screenStore, $screenStore => { + return $screenStore.activeScreen?.props?.layout === "grid" +}) diff --git a/packages/client/vite.config.mjs b/packages/client/vite.config.mjs index 7c163181ae..9ef87d8ec8 100644 --- a/packages/client/vite.config.mjs +++ b/packages/client/vite.config.mjs @@ -20,7 +20,7 @@ export default defineConfig(({ mode }) => { }, build: { lib: { - entry: "src/index.js", + entry: "src/index.ts", formats: ["iife"], outDir: "dist", name: "budibase_client", @@ -67,10 +67,6 @@ export default defineConfig(({ mode }) => { find: "constants", replacement: path.resolve("./src/constants"), }, - { - find: "@/constants", - replacement: path.resolve("./src/constants"), - }, { find: "sdk", replacement: path.resolve("./src/sdk"), @@ -87,6 +83,10 @@ export default defineConfig(({ mode }) => { find: "@budibase/bbui", replacement: path.resolve("../bbui/src"), }, + { + find: "@", + replacement: path.resolve(__dirname, "src"), + }, ], }, } diff --git a/packages/types/src/ui/components/index.ts b/packages/types/src/ui/components/index.ts index 283ceb47da..85c7b1af84 100644 --- a/packages/types/src/ui/components/index.ts +++ b/packages/types/src/ui/components/index.ts @@ -2,6 +2,16 @@ export * from "./sidepanel" export * from "./codeEditor" export * from "./errors" +export interface CustomComponent { + Component: any + schema: { + type: "component" + metadata: Record + schema: ComponentDefinition + } + version: string +} + export interface ComponentDefinition { component: string name: string From 5b5a0d2ba80218758985d695655a6513408fd6dd Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 14:55:05 +0000 Subject: [PATCH 010/210] Add working DND placeholder support for grid screens --- .../new/_components/NewComponentPanel.svelte | 3 +- .../[screenId]/_components/AppPreview.svelte | 4 +- .../builder/src/stores/builder/preview.ts | 17 +--- .../src/components/preview/DNDHandler.svelte | 23 ++++-- .../preview/DNDPlaceholderOverlay.svelte | 33 ++++++-- .../components/preview/GridDNDHandler.svelte | 78 +++++++++++++++++-- packages/client/src/index.ts | 5 +- packages/client/src/stores/builder.js | 3 +- packages/client/src/stores/dnd.js | 68 +++++++++++++--- packages/client/src/stores/index.js | 1 + packages/client/src/stores/screens.js | 3 +- 11 files changed, 185 insertions(+), 53 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index 784642787b..c76b03be36 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -223,11 +223,13 @@ }) const onDragStart = (e, component) => { + console.log("DRAG START") e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } const onDragEnd = () => { + console.log("DRAG END") previewStore.stopDrag() } @@ -314,7 +316,6 @@ } .component:hover { background: var(--spectrum-global-color-gray-300); - cursor: grab; } .component :global(.spectrum-Body) { line-height: 1.2 !important; diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 3951c0e902..39e0835fa8 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -199,8 +199,8 @@ } else if (type === "reload-plugin") { await componentStore.refreshDefinitions() } else if (type === "drop-new-component") { - const { component, parent, index } = data - await componentStore.create(component, null, parent, index) + const { component, parent, index, props } = data + await componentStore.create(component, props, parent, index) } else if (type === "add-parent-component") { const { componentId, parentType } = data await componentStore.addParent(componentId, parentType) diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 9aeaf99346..a382eeefb0 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -1,7 +1,5 @@ import { get } from "svelte/store" import { BudiStore } from "../BudiStore" -import { componentStore } from "./components" -import { selectedScreen } from "./screens" type PreviewDevice = "desktop" | "tablet" | "mobile" type PreviewEventHandler = (name: string, payload?: any) => void @@ -56,21 +54,10 @@ export class PreviewStore extends BudiStore { })) } - async startDrag(componentType: string) { - let componentId - const gridScreen = get(selectedScreen)?.props?.layout === "grid" - if (gridScreen) { - const component = await componentStore.create(componentType, { - _placeholder: true, - _styles: { normal: { opacity: 0 } }, - }) - componentId = component?._id - } + async startDrag(component: string) { this.sendEvent("dragging-new-component", { dragging: true, - componentType, - componentId, - gridScreen, + component, }) } diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index bdd538748b..11bed5a1b7 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -8,12 +8,14 @@ dndStore, dndParent, dndIsDragging, + isGridScreen, + dndInitialised, } from "stores" import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" - import { findComponentById } from "utils/components.js" - import { DNDPlaceholderID } from "constants" - import { isGridEvent } from "utils/grid" + import { findComponentById } from "@/utils/components.js" + import { isGridEvent } from "@/utils/grid" + import { DNDPlaceholderID } from "@/constants" const ThrottleRate = 130 @@ -219,9 +221,9 @@ processEvent(e.clientX, e.clientY) } - // Callback when on top of a component. + // Callback when on top of a component const onDragOver = e => { - if (!source || !target) { + if (!source || !target || $isGridScreen) { return } handleEvent(e) @@ -233,6 +235,14 @@ return } + // Mark as initialised if this is our first valid drag enter event + if (!$dndInitialised) { + dndStore.actions.markInitialised() + } + if ($isGridScreen) { + return + } + // Find the next valid component to consider dropping over, ignoring nested // block components const component = e.target?.closest?.( @@ -262,7 +272,8 @@ builderStore.actions.dropNewComponent( source.newComponentType, drop.parent, - drop.index + drop.index, + $dndStore.meta.newComponentProps ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 61cecc885b..50b76c6208 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,38 +1,56 @@ -{#if left != null && top != null && width && height} +{#if left != null && top != null && width && height && $dndInitialised}
diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index f173dfd960..3d50bfded9 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -1,15 +1,22 @@ diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index e7d454e2f1..7d6b100dc6 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -36,6 +36,8 @@ import * as internal from "svelte/internal" window.svelte_internal = internal window.svelte = svelte +console.log("NEW CLIENT") + // Initialise spectrum icons // eslint-disable-next-line local-rules/no-budibase-imports import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" @@ -161,14 +163,13 @@ const loadBudibase = async () => { const block = blockStore.actions.getBlock(data) block?.eject() } else if (type === "dragging-new-component") { - const { dragging, component, componentId } = data + const { dragging, component } = data if (dragging) { const definition = componentStore.actions.getComponentDefinition(component) dndStore.actions.startDraggingNewComponent({ component, definition, - componentId, }) } else { dndStore.actions.reset() diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 1ae7d3a670..7effd718a0 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -77,11 +77,12 @@ const createBuilderStore = () => { mode, }) }, - dropNewComponent: (component, parent, index) => { + dropNewComponent: (component, parent, index, props) => { eventStore.actions.dispatchEvent("drop-new-component", { component, parent, index, + props, }) }, setEditMode: enabled => { diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 5cfb12c7d2..74987ea7d9 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -1,5 +1,7 @@ -import { writable } from "svelte/store" +import { writable, get } from "svelte/store" import { derivedMemo } from "@budibase/frontend-core" +import { screenStore } from "@/stores" +import { ScreenslotID } from "@/constants" const createDndStore = () => { const initialState = { @@ -11,6 +13,12 @@ const createDndStore = () => { // Info about where the component would be dropped drop: null, + + // Metadata about the event + meta: { + initialised: false, + newComponentProps: null, + }, } const store = writable(initialState) @@ -21,35 +29,53 @@ const createDndStore = () => { }) } - const startDraggingNewComponent = ({ - component, - definition, - componentId, - }) => { + const startDraggingNewComponent = ({ component, definition }) => { + console.log("start", component, definition) if (!component) { return } + let target, drop + const screen = get(screenStore)?.activeScreen + const isGridScreen = screen?.props?.layout === "grid" + if (isGridScreen) { + const id = screen?.props?._id + drop = { + parent: id, + index: screen?.props?._children?.length, + } + target = { + id, + parent: ScreenslotID, + node: null, + empty: false, + acceptsChildren: true, + } + } + // Get size of new component so we can show a properly sized placeholder const width = definition?.size?.width || 128 const height = definition?.size?.height || 64 store.set({ ...initialState, + isGridScreen, source: { id: null, parent: null, bounds: { height, width }, index: null, newComponentType: component, - newComponentId: componentId, }, + target, + drop, }) } const updateTarget = ({ id, parent, node, empty, acceptsChildren }) => { store.update(state => { state.target = { id, parent, node, empty, acceptsChildren } + console.log("TARGET", state.target) return state }) } @@ -57,6 +83,7 @@ const createDndStore = () => { const updateDrop = ({ parent, index }) => { store.update(state => { state.drop = { parent, index } + console.log("DROP", state.drop) return state }) } @@ -65,6 +92,26 @@ const createDndStore = () => { store.set(initialState) } + const markInitialised = () => { + store.update(state => ({ + ...state, + meta: { + ...state.meta, + initialised: true, + }, + })) + } + + const updateNewComponentProps = newComponentProps => { + store.update(state => ({ + ...state, + meta: { + ...state.meta, + newComponentProps, + }, + })) + } + return { subscribe: store.subscribe, actions: { @@ -73,6 +120,8 @@ const createDndStore = () => { updateTarget, updateDrop, reset, + markInitialised, + updateNewComponentProps, }, } } @@ -87,10 +136,7 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndNewComponentId = derivedMemo( - dndStore, - x => x.source?.newComponentId -) +export const dndInitialised = derivedMemo(dndStore, x => x.meta.initialised) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 268b0cc4bf..b1f0f8955a 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,6 +25,7 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, + dndInitialised, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index f85675e389..6193dcca94 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -7,7 +7,7 @@ import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" -import { DNDPlaceholderID, ScreenslotID, ScreenslotType } from "constants" +import { DNDPlaceholderID, ScreenslotID, ScreenslotType } from "@/constants" const createScreenStore = () => { const store = derived( @@ -99,7 +99,6 @@ const createScreenStore = () => { normal: { width: `${$dndBounds?.width || 400}px`, height: `${$dndBounds?.height || 200}px`, - opacity: 0, "--default-width": $dndBounds?.width || 400, "--default-height": $dndBounds?.height || 200, }, From b9c2b07f3e7d696a7956e0b1c9e492bd00be8cfe Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:16:22 +0000 Subject: [PATCH 011/210] Finally actually fix devilish issue of flashing placeholder overlay --- .../src/components/preview/DNDHandler.svelte | 27 ++++++-------- .../preview/DNDPlaceholderOverlay.svelte | 36 ++++++++++++++++--- .../components/preview/GridDNDHandler.svelte | 21 ++++++----- .../preview/SelectionIndicator.svelte | 4 +-- packages/client/src/stores/dnd.js | 18 +++------- packages/client/src/stores/index.js | 2 +- packages/client/src/stores/screens.js | 1 + 7 files changed, 62 insertions(+), 47 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 11bed5a1b7..f62f21e94c 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -9,7 +9,6 @@ dndParent, dndIsDragging, isGridScreen, - dndInitialised, } from "stores" import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" @@ -230,16 +229,8 @@ } // Callback when entering a potential drop target - const onDragEnter = e => { - if (!source) { - return - } - - // Mark as initialised if this is our first valid drag enter event - if (!$dndInitialised) { - dndStore.actions.markInitialised() - } - if ($isGridScreen) { + const onDragEnter = async e => { + if (!source || $isGridScreen) { return } @@ -345,12 +336,14 @@ }) - +{#if !$isGridScreen} + +{/if} {#if $dndIsDragging} diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 50b76c6208..5593fa010d 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,14 +1,38 @@ -{#if left != null && top != null && width && height && $dndInitialised} +{#if left != null && top != null && width && height && !waitingForGrid}
{/if} @@ -65,4 +90,7 @@ border-radius: 4px; border: 2px solid var(--spectrum-global-color-static-green-500); } + .overlay.animate { + transition: all 130ms ease-out; + } diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 3d50bfded9..4f810d226f 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -42,23 +42,26 @@ // Set ephemeral styles $: instance = componentStore.actions.getComponentInstance(id) - $: $instance?.setEphemeralStyles($styles) + $: applyStyles($instance, $styles) - // Keep DND store up to date with grid styles if dragging a new component - // on to a grid screen - $: { - if ($dndIsNewComponent) { + // Reset when not dragging new components + $: !$dndIsDragging && stopDragging() + + const applyStyles = async (instance, styles) => { + instance?.setEphemeralStyles(styles) + + // If dragging a new component on to a grid screen, tick to allow the + // real component to render in the new position before updating the DND + // store, preventing the green DND overlay from being out of position + if ($dndIsNewComponent && styles) { dndStore.actions.updateNewComponentProps({ _styles: { - normal: $styles, + normal: styles, }, }) } } - // Reset when not dragging new components - $: !$dndIsDragging && stopDragging() - // Sugar for a combination of both min and max const minMax = (value, min, max) => Math.min(max, Math.max(min, value)) diff --git a/packages/client/src/components/preview/SelectionIndicator.svelte b/packages/client/src/components/preview/SelectionIndicator.svelte index a271389cbd..5c34fe6f42 100644 --- a/packages/client/src/components/preview/SelectionIndicator.svelte +++ b/packages/client/src/components/preview/SelectionIndicator.svelte @@ -1,5 +1,5 @@ { // Metadata about the event meta: { - initialised: false, newComponentProps: null, }, } @@ -30,7 +29,6 @@ const createDndStore = () => { } const startDraggingNewComponent = ({ component, definition }) => { - console.log("start", component, definition) if (!component) { return } @@ -92,16 +90,6 @@ const createDndStore = () => { store.set(initialState) } - const markInitialised = () => { - store.update(state => ({ - ...state, - meta: { - ...state.meta, - initialised: true, - }, - })) - } - const updateNewComponentProps = newComponentProps => { store.update(state => ({ ...state, @@ -120,7 +108,6 @@ const createDndStore = () => { updateTarget, updateDrop, reset, - markInitialised, updateNewComponentProps, }, } @@ -136,8 +123,11 @@ export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndInitialised = derivedMemo(dndStore, x => x.meta.initialised) export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null ) +export const dndNewComponentProps = derivedMemo( + dndStore, + x => x.meta?.newComponentProps +) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index b1f0f8955a..7d8257f6d0 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,7 +25,7 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, - dndInitialised, + dndNewComponentProps, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 6193dcca94..99b943fbd2 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -99,6 +99,7 @@ const createScreenStore = () => { normal: { width: `${$dndBounds?.width || 400}px`, height: `${$dndBounds?.height || 200}px`, + opacity: 0, "--default-width": $dndBounds?.width || 400, "--default-height": $dndBounds?.height || 200, }, From e71e8ff6b68fcc61762ebdcaa053bd447ba53de0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:20:31 +0000 Subject: [PATCH 012/210] Tidy up --- .../components/preview/GridDNDHandler.svelte | 2 -- packages/client/src/index.ts | 2 -- packages/client/src/stores/dnd.js | 21 +++++++------------ packages/client/src/stores/index.js | 1 - 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 4f810d226f..6ada5b4b4b 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -124,7 +124,6 @@ } const startDraggingPlaceholder = () => { - console.log("START PLACEHOLDER") const mode = GridDragModes.Move const id = DNDPlaceholderID @@ -160,7 +159,6 @@ } // Add event handler to clear all drag state when dragging ends - console.log("add up listener") document.addEventListener("mouseup", stopDragging) } diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 7d6b100dc6..20f582106b 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -36,8 +36,6 @@ import * as internal from "svelte/internal" window.svelte_internal = internal window.svelte = svelte -console.log("NEW CLIENT") - // Initialise spectrum icons // eslint-disable-next-line local-rules/no-budibase-imports import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 16f1441950..38c1e8aab8 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -1,6 +1,6 @@ import { writable, get } from "svelte/store" import { derivedMemo } from "@budibase/frontend-core" -import { screenStore } from "@/stores" +import { screenStore, isGridScreen } from "@/stores" import { ScreenslotID } from "@/constants" const createDndStore = () => { @@ -33,15 +33,11 @@ const createDndStore = () => { return } + // On grid screens, we already know exactly where to insert the component let target, drop const screen = get(screenStore)?.activeScreen - const isGridScreen = screen?.props?.layout === "grid" - if (isGridScreen) { + if (get(isGridScreen)) { const id = screen?.props?._id - drop = { - parent: id, - index: screen?.props?._children?.length, - } target = { id, parent: ScreenslotID, @@ -49,6 +45,10 @@ const createDndStore = () => { empty: false, acceptsChildren: true, } + drop = { + parent: id, + index: screen?.props?._children?.length, + } } // Get size of new component so we can show a properly sized placeholder @@ -57,7 +57,6 @@ const createDndStore = () => { store.set({ ...initialState, - isGridScreen, source: { id: null, parent: null, @@ -73,7 +72,6 @@ const createDndStore = () => { const updateTarget = ({ id, parent, node, empty, acceptsChildren }) => { store.update(state => { state.target = { id, parent, node, empty, acceptsChildren } - console.log("TARGET", state.target) return state }) } @@ -81,7 +79,6 @@ const createDndStore = () => { const updateDrop = ({ parent, index }) => { store.update(state => { state.drop = { parent, index } - console.log("DROP", state.drop) return state }) } @@ -127,7 +124,3 @@ export const dndIsNewComponent = derivedMemo( dndStore, x => x.source?.newComponentType != null ) -export const dndNewComponentProps = derivedMemo( - dndStore, - x => x.meta?.newComponentProps -) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 7d8257f6d0..268b0cc4bf 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -25,7 +25,6 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, - dndNewComponentProps, } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" From 0471e113e37103831910f3faeaf66363de132148 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 5 Feb 2025 16:31:38 +0000 Subject: [PATCH 013/210] More tidy up --- .../new/_components/NewComponentPanel.svelte | 2 -- .../components/preview/GridDNDHandler.svelte | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index c76b03be36..f80b681782 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -223,13 +223,11 @@ }) const onDragStart = (e, component) => { - console.log("DRAG START") e.dataTransfer.setDragImage(ghost, 0, 0) previewStore.startDrag(component) } const onDragEnd = () => { - console.log("DRAG END") previewStore.stopDrag() } diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 6ada5b4b4b..569a9879a6 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -123,12 +123,10 @@ processEvent(e.clientX, e.clientY) } + // Callback when dragging a new component over the preview iframe in a valid + // position for the first time const startDraggingPlaceholder = () => { - const mode = GridDragModes.Move - const id = DNDPlaceholderID - - // Find grid parent and read from DOM - const domComponent = document.getElementsByClassName(id)[0] + const domComponent = document.getElementsByClassName(DNDPlaceholderID)[0] const domGrid = domComponent?.closest(".grid") if (!domGrid) { return @@ -139,15 +137,14 @@ // Show as active domComponent.classList.add("dragging") domGrid.classList.add("highlight") - builderStore.actions.selectComponent(id) // Update state dragInfo = { domComponent, domGrid, - id, + id: DNDPlaceholderID, gridId: domGrid.parentNode.dataset.id, - mode, + mode: GridDragModes.Move, grid: { startX: bounds.left + bounds.width / 2, startY: bounds.top + bounds.height / 2, @@ -157,9 +154,6 @@ colEnd: parseInt(styles["grid-column-end"]), }, } - - // Add event handler to clear all drag state when dragging ends - document.addEventListener("mouseup", stopDragging) } // Callback when initially starting a drag on a draggable component @@ -266,6 +260,5 @@ onDestroy(() => { document.removeEventListener("dragstart", onDragStart, false) document.removeEventListener("dragover", onDragOver, false) - document.removeEventListener("mouseup", stopDragging, false) }) From 0ad0ded2e2febf94370fdda88643833cda4d60ba Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:13:20 +0000 Subject: [PATCH 014/210] Use new technique for DND selection indicators --- .../client/src/components/ClientApp.svelte | 4 +- .../client/src/components/Component.svelte | 2 +- .../src/components/preview/DNDHandler.svelte | 21 +- .../preview/DNDPlaceholderOverlay.svelte | 186 ++++++++++-------- .../preview/DNDSelectionIndicators.svelte | 27 +++ .../components/preview/GridDNDHandler.svelte | 6 +- .../src/components/preview/Indicator.svelte | 10 +- .../components/preview/IndicatorSet.svelte | 31 +-- packages/client/src/stores/dnd.js | 22 ++- packages/client/src/stores/index.js | 9 +- packages/client/src/stores/screens.js | 18 +- 11 files changed, 188 insertions(+), 148 deletions(-) create mode 100644 packages/client/src/components/preview/DNDSelectionIndicators.svelte diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 7144105fd8..144b5a8dec 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -44,7 +44,7 @@ import MaintenanceScreen from "components/MaintenanceScreen.svelte" import SnippetsProvider from "./context/SnippetsProvider.svelte" import EmbedProvider from "./context/EmbedProvider.svelte" - import GridNewComponentDNDHandler from "components/preview/GridNewComponentDNDHandler.svelte" + import DNDSelectionIndicators from "./preview/DNDSelectionIndicators.svelte" // Provide contexts setContext("sdk", SDK) @@ -267,7 +267,7 @@ {#if $builderStore.inBuilder} - + {/if}
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 3e22ffada1..67f8fdc63c 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -120,7 +120,7 @@ $: children = instance._children || [] $: id = instance._id $: name = isRoot ? "Screen" : instance._instanceName - $: icon = definition?.icon + $: icon = instance._icon || definition?.icon // Determine if the component is selected or is part of the critical path // leading to the selected component diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index f62f21e94c..82db06a623 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -7,10 +7,10 @@ screenStore, dndStore, dndParent, + dndSource, dndIsDragging, isGridScreen, } from "stores" - import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" import { findComponentById } from "@/utils/components.js" import { isGridEvent } from "@/utils/grid" @@ -92,6 +92,8 @@ bounds: component.children[0].getBoundingClientRect(), parent: parentId, index, + name: component.dataset.name, + icon: component.dataset.icon, }) builderStore.actions.selectComponent(id) @@ -258,10 +260,10 @@ } // Check if we're adding a new component rather than moving one - if (source.newComponentType) { + if (source.isNew) { dropping = true builderStore.actions.dropNewComponent( - source.newComponentType, + source.type, drop.parent, drop.index, $dndStore.meta.newComponentProps @@ -335,16 +337,3 @@ document.removeEventListener("drop", onDrop, false) }) - -{#if !$isGridScreen} - -{/if} - -{#if $dndIsDragging} - -{/if} diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 5593fa010d..f06454acce 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,96 +1,108 @@ - + + + + + + + -{#if left != null && top != null && width && height && !waitingForGrid} -
-{/if} + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte new file mode 100644 index 0000000000..9949f07ace --- /dev/null +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -0,0 +1,27 @@ + + +{#if !$isGridScreen} + +{/if} + +{#if $dndIsDragging} + +{/if} diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 569a9879a6..58ba92ab07 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -4,8 +4,8 @@ builderStore, componentStore, dndIsDragging, - dndIsNewComponent, dndStore, + dndSource, isGridScreen, } from "stores" import { Utils, memo } from "@budibase/frontend-core" @@ -53,7 +53,7 @@ // If dragging a new component on to a grid screen, tick to allow the // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position - if ($dndIsNewComponent && styles) { + if ($dndSource?.isNew && styles) { dndStore.actions.updateNewComponentProps({ _styles: { normal: styles, @@ -222,7 +222,7 @@ const onDragOver = e => { if (!dragInfo) { // Check if we're dragging a new component - if ($dndIsDragging && $dndIsNewComponent && $isGridScreen) { + if ($dndIsDragging && $dndSource?.isNew && $isGridScreen) { startDraggingPlaceholder() } return diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index dce7945b29..94940285ff 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -14,6 +14,8 @@ export let line = false export let alignRight = false export let showResizeAnchors = false + export let background = null + export let animate = false const AnchorSides = [ "right", @@ -33,10 +35,12 @@ class="indicator" class:flipped class:line - style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex};" + style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex}; --bg: {background || + 'none'};" class:withText={!!text} class:vCompact={height < 40} class:hCompact={width < 40} + class:animate > {#if text || icon}
{ mutationObserver.observe(element, { attributes: true, - attributeFilter: ["style"], }) observingMutations = true } @@ -108,17 +111,19 @@ } // Check if we're inside a grid - if (allowResizeAnchors) { - nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - } + nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - // Get text to display - nextState.text = elements[0].dataset.name - if (nextState.prefix) { - nextState.text = `${nextState.prefix} ${nextState.text}` + // Get text and icon to display + if (!text) { + nextState.text = elements[0].dataset.name + if (nextState.prefix) { + nextState.text = `${nextState.prefix} ${nextState.text}` + } } - if (elements[0].dataset.icon) { - nextState.icon = elements[0].dataset.icon + if (!icon) { + if (elements[0].dataset.icon) { + nextState.icon = elements[0].dataset.icon + } } nextState.error = elements[0].classList.contains("error") @@ -205,5 +210,7 @@ color={state.error ? errorColor : state.color} componentId={state.componentId} zIndex={state.zIndex} + {background} + {animate} /> {/each} diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 38c1e8aab8..f6b8fec48c 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -21,10 +21,17 @@ const createDndStore = () => { } const store = writable(initialState) - const startDraggingExistingComponent = ({ id, parent, bounds, index }) => { + const startDraggingExistingComponent = ({ + id, + parent, + bounds, + index, + name, + icon, + }) => { store.set({ ...initialState, - source: { id, parent, bounds, index }, + source: { id, parent, bounds, index, name, icon, isNew: false }, }) } @@ -62,7 +69,10 @@ const createDndStore = () => { parent: null, bounds: { height, width }, index: null, - newComponentType: component, + type: component, + isNew: true, + name: `New ${definition.name}`, + icon: definition.icon, }, target, drop, @@ -118,9 +128,5 @@ export const dndStore = createDndStore() // or components which depend on DND state unless values actually change. export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) -export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) +export const dndSource = derivedMemo(dndStore, x => x.source) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndIsNewComponent = derivedMemo( - dndStore, - x => x.source?.newComponentType != null -) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 268b0cc4bf..522fadc643 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -18,14 +18,7 @@ export { environmentStore } from "./environment" export { eventStore } from "./events" export { orgStore } from "./org" export { roleStore } from "./roles" -export { - dndStore, - dndIndex, - dndParent, - dndBounds, - dndIsNewComponent, - dndIsDragging, -} from "./dnd" +export { dndStore, dndIndex, dndParent, dndIsDragging, dndSource } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" export { hoverStore } from "./hover" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 99b943fbd2..df0dc0e365 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -3,7 +3,7 @@ import { routeStore } from "./routes" import { builderStore } from "./builder" import { appStore } from "./app" import { orgStore } from "./org" -import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" +import { dndIndex, dndParent, dndSource } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" @@ -18,8 +18,7 @@ const createScreenStore = () => { orgStore, dndParent, dndIndex, - dndIsNewComponent, - dndBounds, + dndSource, ], ([ $appStore, @@ -28,8 +27,7 @@ const createScreenStore = () => { $orgStore, $dndParent, $dndIndex, - $dndIsNewComponent, - $dndBounds, + $dndSource, ]) => { let activeLayout, activeScreen let screens @@ -85,7 +83,7 @@ const createScreenStore = () => { // Remove selected component from tree if we are moving an existing // component - if (!$dndIsNewComponent && selectedParent) { + if (!$dndSource.isNew && selectedParent) { selectedParent._children = selectedParent._children?.filter( x => x._id !== selectedComponentId ) @@ -97,11 +95,11 @@ const createScreenStore = () => { _id: DNDPlaceholderID, _styles: { normal: { - width: `${$dndBounds?.width || 400}px`, - height: `${$dndBounds?.height || 200}px`, + width: `${$dndSource?.bounds?.width || 400}px`, + height: `${$dndSource?.bounds?.height || 200}px`, opacity: 0, - "--default-width": $dndBounds?.width || 400, - "--default-height": $dndBounds?.height || 200, + "--default-width": $dndSource?.bounds?.width || 400, + "--default-height": $dndSource?.bounds?.height || 200, }, }, static: true, From 89d6231dad6a0f13999471237704e7cd9a09d2c2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:47:09 +0000 Subject: [PATCH 015/210] Type IndicatorSet --- .../preview/DNDSelectionIndicators.svelte | 20 ++-- .../components/preview/IndicatorSet.svelte | 107 +++++++++++------- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index 9949f07ace..cb81e83a6b 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,19 +1,19 @@ -{#if !$isGridScreen} - -{/if} - {#if $dndIsDragging} + {#if !$isGridScreen} + + {/if} + + - +{#if !$dndIsDragging && componentId} + +{/if}} diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 94940285ff..b14807e535 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -1,20 +1,20 @@ - - +{#if !$dndIsDragging && $builderStore.selectedComponentId} + +{/if} From a541603267ceb664f1fb3a36343af98f01a326ef Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 09:57:04 +0000 Subject: [PATCH 017/210] Type hover and selection indicators --- .../src/components/preview/HoverIndicator.svelte | 16 ++++++++++------ .../components/preview/SelectionIndicator.svelte | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 4930fc35eb..d8846bdb42 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -1,4 +1,4 @@ - diff --git a/packages/client/src/components/context/RowSelectionProvider.svelte b/packages/client/src/components/context/RowSelectionProvider.svelte index 2c87a5fa00..da731e6f05 100644 --- a/packages/client/src/components/context/RowSelectionProvider.svelte +++ b/packages/client/src/components/context/RowSelectionProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/SnippetsProvider.svelte b/packages/client/src/components/context/SnippetsProvider.svelte index 53fa1e8b7f..104147ecf7 100644 --- a/packages/client/src/components/context/SnippetsProvider.svelte +++ b/packages/client/src/components/context/SnippetsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/StateBindingsProvider.svelte b/packages/client/src/components/context/StateBindingsProvider.svelte index a1166594a8..4ef99228c1 100644 --- a/packages/client/src/components/context/StateBindingsProvider.svelte +++ b/packages/client/src/components/context/StateBindingsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/context/UserBindingsProvider.svelte b/packages/client/src/components/context/UserBindingsProvider.svelte index 98769cf76a..4cfb804998 100644 --- a/packages/client/src/components/context/UserBindingsProvider.svelte +++ b/packages/client/src/components/context/UserBindingsProvider.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte b/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte index 3b4c426851..6e020c06f4 100644 --- a/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte +++ b/packages/client/src/components/devtools/DevToolsComponentContextTab.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/overlay/ConfirmationDisplay.svelte b/packages/client/src/components/overlay/ConfirmationDisplay.svelte index b96af502df..823c1c1ab2 100644 --- a/packages/client/src/components/overlay/ConfirmationDisplay.svelte +++ b/packages/client/src/components/overlay/ConfirmationDisplay.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/overlay/NotificationDisplay.svelte b/packages/client/src/components/overlay/NotificationDisplay.svelte index 46b3a2a6a1..28f4b33433 100644 --- a/packages/client/src/components/overlay/NotificationDisplay.svelte +++ b/packages/client/src/components/overlay/NotificationDisplay.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/overlay/PeekScreenDisplay.svelte b/packages/client/src/components/overlay/PeekScreenDisplay.svelte index 6e0fa81b43..17a92797d5 100644 --- a/packages/client/src/components/overlay/PeekScreenDisplay.svelte +++ b/packages/client/src/components/overlay/PeekScreenDisplay.svelte @@ -5,7 +5,7 @@ notificationStore, routeStore, stateStore, - } from "stores" + } from "@/stores" import { Modal, ModalContent, ActionButton } from "@budibase/bbui" import { onDestroy } from "svelte" diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 82db06a623..263be016fc 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -10,7 +10,7 @@ dndSource, dndIsDragging, isGridScreen, - } from "stores" + } from "@/stores" import { Utils } from "@budibase/frontend-core" import { findComponentById } from "@/utils/components.js" import { isGridEvent } from "@/utils/grid" @@ -266,7 +266,7 @@ source.type, drop.parent, drop.index, - $dndStore.meta.newComponentProps + $dndStore.source?.props ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index cb81e83a6b..42f2e464cc 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 58ba92ab07..e2414e9d78 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -7,7 +7,7 @@ dndStore, dndSource, isGridScreen, - } from "stores" + } from "@/stores" import { Utils, memo } from "@budibase/frontend-core" import { DNDPlaceholderID, GridRowHeight } from "@/constants" import { @@ -54,7 +54,7 @@ // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position if ($dndSource?.isNew && styles) { - dndStore.actions.updateNewComponentProps({ + dndStore.actions.updateSourceProps({ _styles: { normal: styles, }, diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte index 8a3da6f419..4a444b59e9 100644 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte index 4a444b59e9..a705561294 100644 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte @@ -2,8 +2,8 @@ import { onDestroy, getContext } from "svelte" import { builderStore, componentStore, screenStore } from "@/stores" import { Utils, memo } from "@budibase/frontend-core" - import { GridRowHeight } from "constants" - import { GridParams, getGridVar, Devices } from "utils/grid" + import { GridRowHeight } from "@/constants" + import { GridParams, getGridVar, Devices } from "@/utils/grid" const context = getContext("context") diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index d8846bdb42..981e82bc2e 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -1,7 +1,7 @@ {#if $dndIsDragging} - {#if !$isGridScreen} + {#if !$isGridScreen && $dndParent} @@ -24,7 +24,7 @@ interface DNDTarget { parent: string empty: boolean acceptsChildren: boolean - node?: Node + element?: HTMLElement } interface DNDDrop { diff --git a/packages/client/src/utils/grid.ts b/packages/client/src/utils/grid.ts index 6294c70f55..c0e4bd5bfa 100644 --- a/packages/client/src/utils/grid.ts +++ b/packages/client/src/utils/grid.ts @@ -68,15 +68,18 @@ export const getGridVar = (device: string, param: string) => `--grid-${device}-${param}` // Determines whether a JS event originated from immediately within a grid -export const isGridEvent = (e: Event & { target: HTMLElement }): boolean => { +export const isGridEvent = (e: Event): boolean => { + if (!(e.target instanceof HTMLElement)) { + return false + } + const componentParent = e.target.closest?.(".component")?.parentNode as + | HTMLElement + | undefined + const gridDOMCandidate = componentParent?.closest(".component") + ?.childNodes[0] as HTMLElement | undefined return ( e.target.dataset?.indicator === "true" || - // @ts-expect-error: api is not properly typed - e.target - .closest?.(".component") - // @ts-expect-error - ?.parentNode.closest(".component") - ?.childNodes[0]?.classList?.contains("grid") + !!gridDOMCandidate?.classList?.contains("grid") ) } From 732b2575d1b499f61d638e8ea39427aaebeec9d3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 14:21:39 +0000 Subject: [PATCH 021/210] Type grid DND handler --- .../components/preview/GridDNDHandler.svelte | 124 ++++++++++++------ .../src/components/preview/Indicator.svelte | 6 +- packages/client/src/index.ts | 2 +- packages/client/src/utils/grid.ts | 39 +++--- packages/frontend-core/src/utils/memo.d.ts | 2 +- 5 files changed, 110 insertions(+), 63 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index e2414e9d78..24d61bad2b 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -1,4 +1,4 @@ - {#if $dndIsDragging} @@ -14,14 +19,16 @@ /> {/if} - + {#if !waitingForGrid} + + {/if} {/if} From 61940705b94394005c9a634c93e5f891edce3be8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:01:45 +0000 Subject: [PATCH 023/210] Increase DND performance via minimzing component updates --- .../new/_components/NewComponentPanel.svelte | 3 +- .../src/components/preview/DNDHandler.svelte | 7 +- .../preview/DNDPlaceholderOverlay.svelte | 108 ------------------ .../preview/DNDSelectionIndicators.svelte | 10 +- .../components/preview/GridDNDHandler.svelte | 2 +- .../components/preview/IndicatorSet.svelte | 1 + packages/client/src/stores/dnd.ts | 17 +-- 7 files changed, 24 insertions(+), 124 deletions(-) delete mode 100644 packages/client/src/components/preview/DNDPlaceholderOverlay.svelte diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte index f80b681782..d13d72b89f 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/new/_components/NewComponentPanel.svelte @@ -261,8 +261,7 @@ class="component" class:selected={selectedIndex === orderMap[component.component]} on:click={() => addComponent(component.component)} - on:mouseover={() => (selectedIndex = null)} - on:focus + on:mouseenter={() => (selectedIndex = null)} > {component.name} diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index a0f9bfe2aa..15177a90c4 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -25,6 +25,7 @@ $: source = $dndStore.source $: target = $dndStore.target $: drop = $dndStore.drop + $: gridScreen = $isGridScreen // Local flag for whether we are awaiting an async drop event let dropping = false @@ -235,7 +236,7 @@ // Callback when on top of a component const onDragOver = (e: DragEvent) => { - if (!source || !target || $isGridScreen) { + if (!source || !target || gridScreen) { return } handleEvent(e) @@ -243,7 +244,7 @@ // Callback when entering a potential drop target const onDragEnter = async (e: DragEvent) => { - if (!source || $isGridScreen || !(e.target instanceof HTMLElement)) { + if (!source || gridScreen || !(e.target instanceof HTMLElement)) { return } @@ -278,7 +279,7 @@ source.type, drop.parent, drop.index, - $dndStore.source?.props + $dndStore.meta?.props ) dropping = false stopDragging() diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte deleted file mode 100644 index adff10baf8..0000000000 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte index d07082d439..cd7eb8302d 100644 --- a/packages/client/src/components/preview/DNDSelectionIndicators.svelte +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -1,12 +1,18 @@ {#if $dndIsDragging} diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 24d61bad2b..aa5187dec1 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -85,7 +85,7 @@ // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position if ($dndSource?.isNew && styles) { - dndStore.actions.updateSourceProps({ + dndStore.actions.updateNewComponentProps({ _styles: { normal: styles, }, diff --git a/packages/client/src/components/preview/IndicatorSet.svelte b/packages/client/src/components/preview/IndicatorSet.svelte index 4fc45e7b8a..83535f92cb 100644 --- a/packages/client/src/components/preview/IndicatorSet.svelte +++ b/packages/client/src/components/preview/IndicatorSet.svelte @@ -93,6 +93,7 @@ const observeMutations = (node: Node) => { mutationObserver.observe(node, { attributes: true, + attributeFilter: ["style"], }) observingMutations = true } diff --git a/packages/client/src/stores/dnd.ts b/packages/client/src/stores/dnd.ts index 6160d654da..c04ca9547e 100644 --- a/packages/client/src/stores/dnd.ts +++ b/packages/client/src/stores/dnd.ts @@ -16,7 +16,6 @@ interface DNDSource { icon?: string type: string isNew: boolean - props?: Record } interface DNDTarget { @@ -32,10 +31,15 @@ interface DNDDrop { index: number } +interface DNDMeta { + props?: Record +} + interface DNDState { source?: DNDSource target?: DNDTarget drop?: DNDDrop + meta?: DNDMeta } const createDndStore = () => { @@ -106,15 +110,12 @@ const createDndStore = () => { store.set({}) } - const updateSourceProps = (props: Record) => { + const updateNewComponentProps = (props: Record) => { store.update(state => { - if (!state.source) { - return state - } return { ...state, - source: { - ...state.source, + meta: { + ...state.meta, props, }, } @@ -129,7 +130,7 @@ const createDndStore = () => { updateTarget, updateDrop, reset, - updateSourceProps, + updateNewComponentProps, }, } } From b4fed6a02ffecb6b9a23cae7b30493902257b713 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:06:45 +0000 Subject: [PATCH 024/210] Cleanup --- .../preview/GridNewComponentDNDHandler.svelte | 166 ------------------ 1 file changed, 166 deletions(-) delete mode 100644 packages/client/src/components/preview/GridNewComponentDNDHandler.svelte diff --git a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte b/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte deleted file mode 100644 index a705561294..0000000000 --- a/packages/client/src/components/preview/GridNewComponentDNDHandler.svelte +++ /dev/null @@ -1,166 +0,0 @@ - From 585c9a8f6227dd1e9f5fbe47822fd5fba2571534 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 6 Feb 2025 16:36:39 +0000 Subject: [PATCH 025/210] Support scrolling while dragging components --- .../src/components/preview/GridDNDHandler.svelte | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index aa5187dec1..e5297e9208 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -53,6 +53,7 @@ ghost.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + let scrollElement: HTMLElement let dragInfo: GridDragInfo | undefined let styles = memo | undefined>() @@ -75,6 +76,8 @@ // Reset when not dragging new components $: !$dndIsDragging && stopDragging() + const scrollOffset = () => scrollElement?.scrollTop || 0 + const applyStyles = async ( instance: any, styles: Record | undefined @@ -113,7 +116,7 @@ } const diffX = mouseX - startX let deltaX = Math.round(diffX / colSize) - const diffY = mouseY - startY + const diffY = mouseY - startY + scrollOffset() let deltaY = Math.round(diffY / GridRowHeight) if (mode === GridDragMode.Move) { deltaX = minMax(deltaX, 1 - colStart, cols + 1 - colEnd) @@ -186,7 +189,7 @@ mode: GridDragMode.Move, grid: { startX: bounds.left + bounds.width / 2, - startY: bounds.top + bounds.height / 2, + startY: bounds.top + bounds.height / 2 + scrollOffset(), rowStart: parseInt(styles.gridRowStart), rowEnd: parseInt(styles.gridRowEnd), colStart: parseInt(styles.gridColumnStart), @@ -249,7 +252,7 @@ side, grid: { startX: e.clientX, - startY: e.clientY, + startY: e.clientY + scrollOffset(), rowStart: parseInt(styles.gridRowStart), rowEnd: parseInt(styles.gridRowEnd), colStart: parseInt(styles.gridColumnStart), @@ -295,12 +298,17 @@ } onMount(() => { + scrollElement = document.getElementsByClassName( + "screen-wrapper" + )[0] as HTMLElement document.addEventListener("dragstart", onDragStart, false) document.addEventListener("dragover", onDragOver, false) + document.addEventListener("scroll", processEvent) }) onDestroy(() => { document.removeEventListener("dragstart", onDragStart, false) document.removeEventListener("dragover", onDragOver, false) + document.removeEventListener("scroll", processEvent) }) From 83e23ef5789831d2ff4e68a3413f0d70b89dce62 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 7 Feb 2025 16:17:13 +0000 Subject: [PATCH 026/210] Restore format setting, fix conditional UI missing nested flag and component bindings, restrict format setting to own context only --- .../settings/controls/PropertyControl.svelte | 8 ++++++-- .../Component/ComponentSettingsPanel.svelte | 1 + .../Component/ComponentSettingsSection.svelte | 1 + .../Component/ConditionalUIDrawer.svelte | 5 +++++ .../Component/ConditionalUISection.svelte | 7 ++++++- packages/client/manifest.json | 10 +++++++++- .../src/components/app/GridBlock.svelte | 19 +++++++++++-------- packages/types/src/ui/components/index.ts | 2 ++ 8 files changed, 41 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte index 2b63cdd748..c4eb3f04e6 100644 --- a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte +++ b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte @@ -23,11 +23,12 @@ export let info = null export let disableBindings = false export let wide + export let isolated = false let highlightType $: highlightedProp = $builderStore.highlightedSetting - $: allBindings = getAllBindings(bindings, componentBindings, nested) + $: allBindings = getAllBindings(bindings, componentBindings, nested, isolated) $: safeValue = getSafeValue(value, defaultValue, allBindings) $: replaceBindings = val => readableToRuntimeBinding(allBindings, val) @@ -36,7 +37,10 @@ highlightedProp?.key === key ? `highlighted-${highlightedProp?.type}` : "" } - const getAllBindings = (bindings, componentBindings, nested) => { + const getAllBindings = (bindings, componentBindings, nested, isolated) => { + if (isolated) { + bindings = [] + } if (!nested) { return bindings } diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte index de6993c661..020f86357b 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsPanel.svelte @@ -147,6 +147,7 @@ {componentInstance} {componentDefinition} {bindings} + {componentBindings} /> {/if} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte index 0b147e867c..6940c8b6fc 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte @@ -151,6 +151,7 @@ propertyFocus={$builderStore.propertyFocus === setting.key} info={setting.info} disableBindings={setting.disableBindings} + isolated={setting.isolated} props={{ // Generic settings placeholder: setting.placeholder || null, diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte index 863333e91d..4b39022880 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte @@ -19,6 +19,7 @@ export let conditions = [] export let bindings = [] + export let componentBindings = [] const flipDurationMs = 150 const actionOptions = [ @@ -55,6 +56,7 @@ ] let dragDisabled = true + $: settings = componentStore .getComponentSettings($selectedComponent?._component) ?.concat({ @@ -213,7 +215,10 @@ options: definition.options, placeholder: definition.placeholder, }} + nested={definition.nested} + isolated={definition.isolated} {bindings} + {componentBindings} /> {:else} +
+
+ p.slice(1)).join("/")}` + : "Add test values"} + /> +
+
+
+ + diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte index 3a6e7a702c..1591331f45 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Screen/GeneralPanel.svelte @@ -15,9 +15,11 @@ import ButtonActionEditor from "@/components/design/settings/controls/ButtonActionEditor/ButtonActionEditor.svelte" import { getBindableProperties } from "@/dataBinding" import BarButtonList from "@/components/design/settings/controls/BarButtonList.svelte" + import URLVariableTestInput from "@/components/design/settings/controls/URLVariableTestInput.svelte" $: bindings = getBindableProperties($selectedScreen, null) $: screenSettings = getScreenSettings($selectedScreen) + let urlTestValue = "" let errors = {} @@ -93,6 +95,14 @@ ], }, }, + { + key: "urlTest", + control: URLVariableTestInput, + props: { + baseRoute: screen.routing?.route, + testValue: urlTestValue, + }, + }, ] return settings diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 87b2b9355e..84d6447bb7 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -86,6 +86,10 @@ export class PreviewStore extends BudiStore { this.sendEvent("builder-state", data) } + updateUrl(data: Record) { + this.sendEvent("builder-test-url", data) + } + requestComponentContext() { this.sendEvent("request-context") } diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 2840d82f47..8169328b5f 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -29,6 +29,7 @@ import UserBindingsProvider from "components/context/UserBindingsProvider.svelte" import DeviceBindingsProvider from "components/context/DeviceBindingsProvider.svelte" import StateBindingsProvider from "components/context/StateBindingsProvider.svelte" + import TestUrlBindingsProvider from "components/context/TestUrlBindingsProvider.svelte" import RowSelectionProvider from "components/context/RowSelectionProvider.svelte" import QueryParamsProvider from "components/context/QueryParamsProvider.svelte" import SettingsBar from "components/preview/SettingsBar.svelte" @@ -168,107 +169,109 @@ - - - - {#key $builderStore.selectedComponentId} - {#if $builderStore.inBuilder} - - {/if} - {/key} - - -
- -
- {#if showDevTools} - + + + + + {#key $builderStore.selectedComponentId} + {#if $builderStore.inBuilder} + {/if} + {/key} -
- {#if permissionError} -
- - - {@html ErrorSVG} - - You don't have permission to use this app - - - Ask your administrator to grant you access - - -
- {:else if !$screenStore.activeLayout} -
- - - {@html ErrorSVG} - - Something went wrong rendering your app - - - Get in touch with support if this issue - persists - - -
- {:else if embedNoScreens} -
- - - {@html ErrorSVG} - - This Budibase app is not publicly accessible - - -
- {:else} - - {#key $screenStore.activeLayout._id} - - {/key} - - - - - - + +
+ +
+ {#if showDevTools} + {/if} - {#if showDevTools} - +
+ {#if permissionError} +
+ + + {@html ErrorSVG} + + You don't have permission to use this app + + + Ask your administrator to grant you access + + +
+ {:else if !$screenStore.activeLayout} +
+ + + {@html ErrorSVG} + + Something went wrong rendering your app + + + Get in touch with support if this issue + persists + + +
+ {:else if embedNoScreens} +
+ + + {@html ErrorSVG} + + This Budibase app is not publicly accessible + + +
+ {:else} + + {#key $screenStore.activeLayout._id} + + {/key} + + + + + + + {/if} + + {#if showDevTools} + + {/if} +
+ + {#if !$builderStore.inBuilder && $featuresStore.logoEnabled} + {/if}
- {#if !$builderStore.inBuilder && $featuresStore.logoEnabled} - + + {#if $appStore.isDevApp} + + {/if} + {#if $builderStore.inBuilder || $devToolsStore.allowSelection} + + {/if} + {#if $builderStore.inBuilder} + + {/if}
- - - {#if $appStore.isDevApp} - - {/if} - {#if $builderStore.inBuilder || $devToolsStore.allowSelection} - - {/if} - {#if $builderStore.inBuilder} - - - {/if} -
-
+ +
diff --git a/packages/client/src/components/context/TestUrlBindingsProvider.svelte b/packages/client/src/components/context/TestUrlBindingsProvider.svelte new file mode 100644 index 0000000000..7f8c0f04da --- /dev/null +++ b/packages/client/src/components/context/TestUrlBindingsProvider.svelte @@ -0,0 +1,8 @@ + + + + + diff --git a/packages/client/src/index.js b/packages/client/src/index.js index 8a48aa08e5..b76186af8e 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -10,6 +10,7 @@ import { eventStore, hoverStore, stateStore, + routeStore, } from "./stores" import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" import { get } from "svelte/store" @@ -108,6 +109,9 @@ const loadBudibase = async () => { } else if (type === "builder-state") { const [[key, value]] = Object.entries(data) stateStore.actions.setValue(key, value) + } else if (type === "builder-test-url") { + const { route, testValue } = data + routeStore.actions.setTestUrlParams(route, testValue) } } diff --git a/packages/client/src/stores/routes.ts b/packages/client/src/stores/routes.ts index 3f200a9c88..f9e2cca27e 100644 --- a/packages/client/src/stores/routes.ts +++ b/packages/client/src/stores/routes.ts @@ -119,7 +119,19 @@ const createRouteStore = () => { const base = window.location.href.split("#")[0] return `${base}#${relativeURL}` } + const setTestUrlParams = (route: string, testValue: string) => { + const routeSegments = route.split("/").slice(2) + const testSegments = testValue.split("/") + const params: Record = {} + routeSegments.forEach((segment, index) => { + if (segment.startsWith(":") && index < testSegments.length) { + params[segment.slice(1)] = testSegments[index] + } + }) + + store.update(state => ({ ...state, testUrlParams: params })) + } return { subscribe: store.subscribe, actions: { @@ -130,6 +142,7 @@ const createRouteStore = () => { setQueryParams, setActiveRoute, setRouterLoaded, + setTestUrlParams, }, } } From cb9a1f4e2136fe78fd9ba116cd4b08a992af72da Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Tue, 11 Feb 2025 12:25:44 +0000 Subject: [PATCH 041/210] Bump version to 3.4.6 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 4e4efe7d00..c893e4b402 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.4.5", + "version": "3.4.6", "npmClient": "yarn", "concurrency": 20, "command": { From dc202f63a90f72b5f9fd8cc7d0d31db6a977cc9e Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 11 Feb 2025 13:27:12 +0000 Subject: [PATCH 042/210] tweaks --- .../controls/URLVariableTestInput.svelte | 55 ++++++++++++------- packages/client/src/stores/routes.ts | 3 +- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/URLVariableTestInput.svelte b/packages/builder/src/components/design/settings/controls/URLVariableTestInput.svelte index 67a372141b..d1a20dbb44 100644 --- a/packages/builder/src/components/design/settings/controls/URLVariableTestInput.svelte +++ b/packages/builder/src/components/design/settings/controls/URLVariableTestInput.svelte @@ -1,13 +1,28 @@
-
URL Variable Testing
-
Pattern: {baseRoute}
+
+ URL Variable Testing + +
+ +
+
+
@@ -35,9 +60,7 @@ p.slice(1)).join("/")}` - : "Add test values"} + placeholder={`${placeholder}`} />
@@ -49,18 +72,13 @@ margin-top: var(--spacing-xl); } - .label { - font-size: var(--spectrum-global-dimension-font-size-75); - font-weight: 500; + .info { + display: flex; + align-items: center; + gap: var(--spacing-s); margin-bottom: var(--spacing-s); } - .url-pattern { - font-size: var(--spectrum-global-dimension-font-size-75); - color: var(--spectrum-global-color-gray-700); - margin-bottom: var(--spacing-xs); - } - .url-test-container { display: flex; width: 100%; @@ -86,9 +104,4 @@ border-top-left-radius: 0; border-bottom-left-radius: 0; } - - /* Override input styles to make them look connected */ - .url-test-container :global(.spectrum-Textfield:focus-within) { - z-index: 1; - } diff --git a/packages/client/src/stores/routes.ts b/packages/client/src/stores/routes.ts index f9e2cca27e..50df18fa11 100644 --- a/packages/client/src/stores/routes.ts +++ b/packages/client/src/stores/routes.ts @@ -122,14 +122,13 @@ const createRouteStore = () => { const setTestUrlParams = (route: string, testValue: string) => { const routeSegments = route.split("/").slice(2) const testSegments = testValue.split("/") - const params: Record = {} + const params: Record = {} routeSegments.forEach((segment, index) => { if (segment.startsWith(":") && index < testSegments.length) { params[segment.slice(1)] = testSegments[index] } }) - store.update(state => ({ ...state, testUrlParams: params })) } return { From 133a64edd62bd5a93e9f203a4eae0ae6ac6c1f70 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 11 Feb 2025 14:45:26 +0000 Subject: [PATCH 043/210] 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 044/210] 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 917548bf84c42bc6017aae7352695955fe02b96f Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 11 Feb 2025 16:14:24 +0000 Subject: [PATCH 045/210] Simplify and add new contextAccess manifest key to solve incompatibility with table format and condition settings --- .../ButtonConfiguration/ButtonSetting.svelte | 1 - .../controls/EditComponentPopover.svelte | 8 +++- .../FieldConfiguration/FieldSetting.svelte | 1 - .../settings/controls/PropertyControl.svelte | 48 +++++++++++++++---- .../Component/ComponentSettingsSection.svelte | 2 +- packages/client/manifest.json | 15 ++++-- .../src/components/app/GridBlock.svelte | 20 ++++++-- .../src/components/grid/stores/conditions.ts | 2 +- packages/types/src/ui/stores/grid/columns.ts | 10 +++- .../types/src/ui/stores/grid/condition.ts | 2 +- 10 files changed, 82 insertions(+), 27 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte index 726f3cdbea..85b3455172 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonConfiguration/ButtonSetting.svelte @@ -43,7 +43,6 @@ import { Icon, Popover, Layout } from "@budibase/bbui" - import { componentStore } from "@/stores/builder" + import { componentStore, selectedScreen } from "@/stores/builder" import { cloneDeep } from "lodash/fp" import { createEventDispatcher, getContext } from "svelte" import ComponentSettingsSection from "@/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte" + import { getComponentBindableProperties } from "@/dataBinding" export let anchor export let componentInstance - export let componentBindings export let bindings export let parseSettings @@ -28,6 +28,10 @@ } $: componentDef = componentStore.getDefinition(componentInstance._component) $: parsedComponentDef = processComponentDefinitionSettings(componentDef) + $: componentBindings = getComponentBindableProperties( + $selectedScreen, + $componentStore.selectedComponentId + ) const open = () => { isOpen = true diff --git a/packages/builder/src/components/design/settings/controls/FieldConfiguration/FieldSetting.svelte b/packages/builder/src/components/design/settings/controls/FieldConfiguration/FieldSetting.svelte index d39af94ce1..d54fdfccbd 100644 --- a/packages/builder/src/components/design/settings/controls/FieldConfiguration/FieldSetting.svelte +++ b/packages/builder/src/components/design/settings/controls/FieldConfiguration/FieldSetting.svelte @@ -45,7 +45,6 @@ readableToRuntimeBinding(allBindings, val) - $: if (value) { highlightType = highlightedProp?.key === key ? `highlighted-${highlightedProp?.type}` : "" } - const getAllBindings = (bindings, componentBindings, nested, isolated) => { - if (isolated) { - bindings = [] + const getAllBindings = ( + bindings, + componentBindings, + nested, + contextAccess + ) => { + // contextAccess is a bit of an escape hatch to get around how we render + // certain settings types by using a pseudo component definition, leading + // to problems with the nested flag + if (contextAccess != null) { + // Optionally include global bindings + let allBindings = contextAccess.global ? bindings : [] + + // Optionally include or exclude self (component) bindings. + // If this is a nested setting then we will already have our own context + // bindings mixed in, so if we don't want self context we need to filter + // them out. + if (contextAccess.self) { + return [...allBindings, ...componentBindings] + } else { + return allBindings.filter(binding => { + return !componentBindings.some(componentBinding => { + return componentBinding.runtimeBinding === binding.runtimeBinding + }) + }) + } } - if (!nested) { + + // Otherwise just honour the normal nested flag + if (nested) { + return [...bindings, ...componentBindings] + } else { return bindings } - return [...(componentBindings || []), ...(bindings || [])] } // Handle a value change of any type diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte index 6940c8b6fc..1d31554df9 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte @@ -151,7 +151,7 @@ propertyFocus={$builderStore.propertyFocus === setting.key} info={setting.info} disableBindings={setting.disableBindings} - isolated={setting.isolated} + contextAccess={setting.contextAccess} props={{ // Generic settings placeholder: setting.placeholder || null, diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 711f2000aa..c240e17176 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -3088,13 +3088,21 @@ { "type": "tableConditions", "label": "Conditions", - "key": "conditions" + "key": "conditions", + "contextAccess": { + "global": true, + "self": false + } }, { "type": "text", "label": "Format", "key": "format", - "info": "Changing format will display values as text" + "info": "Changing format will display values as text", + "contextAccess": { + "global": false, + "self": true + } } ] }, @@ -7692,8 +7700,7 @@ "type": "columns/grid", "key": "columns", "resetOn": "table", - "nested": true, - "isolated": true + "nested": true } ] }, diff --git a/packages/client/src/components/app/GridBlock.svelte b/packages/client/src/components/app/GridBlock.svelte index 1ff273548a..c750ad4001 100644 --- a/packages/client/src/components/app/GridBlock.svelte +++ b/packages/client/src/components/app/GridBlock.svelte @@ -47,8 +47,8 @@ $: currentTheme = $context?.device?.theme $: darkMode = !currentTheme?.includes("light") $: parsedColumns = getParsedColumns(columns) - $: schemaOverrides = getSchemaOverrides(parsedColumns) $: enrichedButtons = enrichButtons(buttons) + $: schemaOverrides = getSchemaOverrides(parsedColumns, $context) $: selectedRows = deriveSelectedRows(gridContext) $: styles = patchStyles($component.styles, minHeight) $: data = { selectedRows: $selectedRows } @@ -97,18 +97,19 @@ })) } - const getSchemaOverrides = columns => { + const getSchemaOverrides = (columns, context) => { let overrides = {} columns.forEach((column, idx) => { overrides[column.field] = { displayName: column.label, order: idx, - conditions: column.conditions, visible: !!column.active, + conditions: enrichConditions(column.conditions, context), format: createFormatter(column), - // Small hack to ensure we react to all changes when inside the builder - rand: Math.random(), + // Small hack to ensure we react to all changes, as our + // memoization cannot compare differences in functions + rand: column.conditions?.length ? Math.random() : null, } if (column.width) { overrides[column.field].width = column.width @@ -117,6 +118,15 @@ return overrides } + const enrichConditions = (conditions, context) => { + return conditions?.map(condition => { + return { + ...condition, + referenceValue: processStringSync(condition.referenceValue, context), + } + }) + } + const createFormatter = column => { if (typeof column.format !== "string" || !column.format.trim().length) { return null diff --git a/packages/frontend-core/src/components/grid/stores/conditions.ts b/packages/frontend-core/src/components/grid/stores/conditions.ts index cf47456b44..214b89fb42 100644 --- a/packages/frontend-core/src/components/grid/stores/conditions.ts +++ b/packages/frontend-core/src/components/grid/stores/conditions.ts @@ -31,7 +31,7 @@ export const deriveStores = (context: StoreContext): ConditionDerivedStore => { // Derive and memoize the cell conditions present in our columns so that we // only recompute condition metadata when absolutely necessary const conditions = derivedMemo(columns, $columns => { - let newConditions = [] + let newConditions: UICondition[] = [] for (let column of $columns) { for (let condition of column.conditions || []) { newConditions.push({ diff --git a/packages/types/src/ui/stores/grid/columns.ts b/packages/types/src/ui/stores/grid/columns.ts index c6ea801713..0132128f9e 100644 --- a/packages/types/src/ui/stores/grid/columns.ts +++ b/packages/types/src/ui/stores/grid/columns.ts @@ -1,9 +1,15 @@ -import { CalculationType, FieldSchema, FieldType, UIRow } from "@budibase/types" +import { + CalculationType, + FieldSchema, + FieldType, + UICondition, + UIRow, +} from "@budibase/types" export type UIColumn = FieldSchema & { label: string readonly: boolean - conditions: any + conditions?: UICondition[] format?: (row: UIRow) => any related?: { field: string diff --git a/packages/types/src/ui/stores/grid/condition.ts b/packages/types/src/ui/stores/grid/condition.ts index dfd9ee867c..95b9977e4b 100644 --- a/packages/types/src/ui/stores/grid/condition.ts +++ b/packages/types/src/ui/stores/grid/condition.ts @@ -3,7 +3,7 @@ import { FieldType, SearchFilter } from "@budibase/types" export interface UICondition { column: string type: FieldType - referenceValue: string + referenceValue: any operator: SearchFilter["operator"] metadataKey: string metadataValue: string From 27f368ebd714b971a50271f1d14b64a06025f258 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 11 Feb 2025 16:23:00 +0000 Subject: [PATCH 046/210] Ensure conditional UI drawer accurately reflects real bindings --- .../_components/Component/ConditionalUIDrawer.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte index 4b39022880..a33d60a644 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ConditionalUIDrawer.svelte @@ -216,7 +216,7 @@ placeholder: definition.placeholder, }} nested={definition.nested} - isolated={definition.isolated} + contextAccess={definition.contextAccess} {bindings} {componentBindings} /> From 33f286d528780db41bf29db076c4de390fc337f1 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Tue, 11 Feb 2025 17:09:34 +0000 Subject: [PATCH 047/210] correctly types gen-collection-info.ts --- packages/string-templates/package.json | 1 + .../scripts/gen-collection-info.ts | 49 ++++++++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index acd0ea4fa8..a80c2ec15c 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -33,6 +33,7 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-typescript": "8.3.0", + "@types/doctrine": "^0.0.9", "doctrine": "^3.0.0", "jest": "29.7.0", "marked": "^4.0.10", diff --git a/packages/string-templates/scripts/gen-collection-info.ts b/packages/string-templates/scripts/gen-collection-info.ts index 8b3825bf5c..ff26228ea9 100644 --- a/packages/string-templates/scripts/gen-collection-info.ts +++ b/packages/string-templates/scripts/gen-collection-info.ts @@ -7,18 +7,30 @@ import { marked } from "marked" import { join, dirname } from "path" const helpers = require("@budibase/handlebars-helpers") -const doctrine = require("doctrine") +import doctrine, { Annotation } from "doctrine" -type HelperInfo = { +type BudibaseAnnotation = Annotation & { + example?: string acceptsInline?: boolean acceptsBlock?: boolean +} + +type Helper = { + args: string[] + numArgs: number example?: string description: string - tags?: any[] + requiresBlock?: boolean +} + +type Manifest = { + [category: string]: { + [helper: string]: Helper + } } const FILENAME = join(__dirname, "..", "src", "manifest.json") -const outputJSON: any = {} +const outputJSON: Manifest = {} const ADDED_HELPERS = { date: { date: { @@ -38,11 +50,11 @@ const ADDED_HELPERS = { }, } -function fixSpecialCases(name: string, obj: any) { +function fixSpecialCases(name: string, obj: Helper) { const args = obj.args if (name === "ifNth") { - args[0] = "a" - args[1] = "b" + obj.args = ["a", "b", "options"] + obj.numArgs = 3 } if (name === "eachIndex") { obj.description = "Iterates the array, listing an item and the index of it." @@ -66,10 +78,10 @@ function lookForward(lines: string[], funcLines: string[], idx: number) { return true } -function getCommentInfo(file: string, func: string): HelperInfo { +function getCommentInfo(file: string, func: string): BudibaseAnnotation { const lines = file.split("\n") const funcLines = func.split("\n") - let comment = null + let comment: string | null = null for (let idx = 0; idx < lines.length; ++idx) { // from here work back until we have the comment if (lookForward(lines, funcLines, idx)) { @@ -91,15 +103,9 @@ function getCommentInfo(file: string, func: string): HelperInfo { } } if (comment == null) { - return { description: "" } + return { description: "", tags: [] } } - const docs: { - acceptsInline?: boolean - acceptsBlock?: boolean - example: string - description: string - tags: any[] - } = doctrine.parse(comment, { unwrap: true }) + const docs: BudibaseAnnotation = doctrine.parse(comment, { unwrap: true }) // some hacky fixes docs.description = docs.description.replace(/\n/g, " ") docs.description = docs.description.replace(/[ ]{2,}/g, " ") @@ -135,7 +141,7 @@ function run() { )}/lib/${collection}.js`, "utf8" ) - const collectionInfo: any = {} + const collectionInfo: { [name: string]: Helper } = {} // collect information about helper let hbsHelperInfo = helpers[collection]() for (let entry of Object.entries(hbsHelperInfo)) { @@ -154,11 +160,8 @@ function run() { const jsDocInfo = getCommentInfo(collectionFile, fnc) let args = jsDocInfo.tags .filter(tag => tag.title === "param") - .map( - tag => - tag.description && - tag.description.replace(/`/g, "").split(" ")[0].trim() - ) + .filter(tag => tag.description) + .map(tag => tag.description!.replace(/`/g, "").split(" ")[0].trim()) collectionInfo[name] = fixSpecialCases(name, { args, numArgs: args.length, From 6f3d097410551cb163459d77ae880a604189ffe3 Mon Sep 17 00:00:00 2001 From: mikesealey Date: Tue, 11 Feb 2025 17:21:05 +0000 Subject: [PATCH 048/210] adds yarn lock --- yarn.lock | 228 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 175 insertions(+), 53 deletions(-) diff --git a/yarn.lock b/yarn.lock index ea7084e53a..71dbfa2c63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -810,7 +810,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@4.2.1", "@azure/identity@^4.2.1": +"@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2130,28 +2130,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.47" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.47.tgz#150d7b16b14932d03c84bdb0e6d570d490c28a5c" - integrity sha512-UeTIq7yzMUK6w/akUsRafoD/Kif6PXv4d7K1arn8GTMjwFm9QYu2hg1YkQ+duNdwyZ/GEPlEAV5SYK+NDgtpdA== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "*" - "@budibase/shared-core" "*" - "@budibase/string-templates" "*" - "@budibase/types" "*" - "@koa/router" "13.1.0" - bull "4.10.1" - dd-trace "5.26.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - "@budibase/vm-browserify@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@budibase/vm-browserify/-/vm-browserify-1.1.4.tgz#eecb001bd9521cb7647e26fb4d2d29d0a4dce262" @@ -5417,6 +5395,11 @@ "@types/node" "*" "@types/ssh2" "*" +"@types/doctrine@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" + integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA== + "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -7049,7 +7032,23 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -10667,7 +10666,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11282,10 +11281,22 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@15.13.0, globals@^11.1.0, globals@^13.19.0, globals@^14.0.0: - version "15.13.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-15.13.0.tgz#bbec719d69aafef188ecd67954aae76a696010fc" - integrity sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g== +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== globalthis@^1.0.1, globalthis@^1.0.4: version "1.0.4" @@ -11695,7 +11706,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -11807,6 +11823,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -12151,6 +12172,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12590,11 +12616,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13474,7 +13495,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -14879,7 +14907,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15072,13 +15100,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16102,7 +16144,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -17087,6 +17137,13 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -17120,6 +17177,11 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -17951,6 +18013,11 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== +sax@>=0.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -18023,13 +18090,28 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: +"semver@2 || 3 || 4 || 5", semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -18658,7 +18740,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18750,7 +18841,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18764,6 +18855,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -19477,7 +19575,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -19487,6 +19585,14 @@ tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0 universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -19954,14 +20060,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20511,7 +20609,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20529,6 +20627,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -20656,7 +20763,14 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.1.x: + version "0.1.14" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" + integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== + dependencies: + sax ">=0.1.1" + +xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -20664,6 +20778,14 @@ xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From f0a1ea6f7e9f9b7908e9a6d497a0be2d3819e8ec Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 11 Feb 2025 22:20:35 +0000 Subject: [PATCH 049/210] 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 050/210] 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} - diff --git a/packages/server/svelte.config.js b/packages/server/svelte.config.js deleted file mode 100644 index 77aeada229..0000000000 --- a/packages/server/svelte.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const { vitePreprocess } = require("@sveltejs/vite-plugin-svelte") - -module.exports = { - preprocess: vitePreprocess(), -} diff --git a/yarn.lock b/yarn.lock index b2ca6a0568..7fb2e6175f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13739,11 +13739,6 @@ jake@^10.8.5: filelist "^1.0.1" minimatch "^3.0.4" -jest-chain-transform@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/jest-chain-transform/-/jest-chain-transform-0.0.8.tgz#cbb4d3aef8d02678b1852968a9b0c861f75eef5a" - integrity sha512-AELTTzYJ34WrmQKAbxUGT+xqnAHu0/XJZhahYNGvBVUhnAayjm1QmT45DQjwEbQPQp7gn6CXzu6rZA03riwBuw== - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" From 6ccd8d66d508a20bed939b8ed56ef230eade83d1 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 12 Feb 2025 17:06:01 +0000 Subject: [PATCH 099/210] Linting. --- packages/server/scripts/svelteTransformer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/scripts/svelteTransformer.js b/packages/server/scripts/svelteTransformer.js index ecc8bbbe5d..6b67971581 100644 --- a/packages/server/scripts/svelteTransformer.js +++ b/packages/server/scripts/svelteTransformer.js @@ -8,4 +8,4 @@ module.exports = { return { code: code } }, -} \ No newline at end of file +} From f70b5cb1293ecf6b835a1a36a28d2df76b4a4d21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 19:53:48 +0000 Subject: [PATCH 100/210] Bump koa from 2.13.4 to 2.15.4 Bumps [koa](https://github.com/koajs/koa) from 2.13.4 to 2.15.4. - [Release notes](https://github.com/koajs/koa/releases) - [Changelog](https://github.com/koajs/koa/blob/2.15.4/History.md) - [Commits](https://github.com/koajs/koa/compare/2.13.4...2.15.4) --- updated-dependencies: - dependency-name: koa dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- packages/server/package.json | 2 +- packages/worker/package.json | 2 +- yarn.lock | 74 ++++++++++++------------------------ 3 files changed, 26 insertions(+), 52 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index fd448629e8..9a70ecba9c 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -99,7 +99,7 @@ "jsonschema": "1.4.0", "jsonwebtoken": "9.0.2", "knex": "2.4.2", - "koa": "2.13.4", + "koa": "2.15.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", "koa-send": "5.0.1", diff --git a/packages/worker/package.json b/packages/worker/package.json index ff21d88ac0..c5e32d11a0 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -58,7 +58,7 @@ "joi": "17.6.0", "jsonwebtoken": "9.0.2", "knex": "2.4.2", - "koa": "2.13.4", + "koa": "2.15.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", "koa-passport": "4.1.4", diff --git a/yarn.lock b/yarn.lock index 3191513b07..23bb5fe1d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2777,7 +2777,7 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": +"@budibase/pro@*", "@budibase/pro@npm:@budibase/pro@latest": version "3.4.6" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.4.6.tgz#62b6ee13a015b98d4768dc7821f468f8177da3e9" integrity sha512-MC3P5SMokmqbjejZMlNM6z7NB9o5H6hZ++yVvbyThniBPYfuDc2ssa1HNwwcuNE3uRLhcxcKe8CY/0SbFgn51g== @@ -9390,7 +9390,7 @@ cookiejar@^2.1.4: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== -cookies@0.8.0, cookies@~0.8.0: +cookies@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== @@ -9398,6 +9398,14 @@ cookies@0.8.0, cookies@~0.8.0: depd "~2.0.0" keygrip "~1.1.0" +cookies@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.9.1.tgz#3ffed6f60bb4fb5f146feeedba50acc418af67e3" + integrity sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + copyfiles@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" @@ -9789,10 +9797,10 @@ dd-trace@5.26.0: shell-quote "^1.8.1" tlhunter-sorted-set "^0.1.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: - version "4.3.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" - integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== dependencies: ms "^2.1.3" @@ -9810,10 +9818,10 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.5: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: ms "^2.1.3" @@ -14701,45 +14709,16 @@ koa2-ratelimit@1.1.1: resolved "https://registry.yarnpkg.com/koa2-ratelimit/-/koa2-ratelimit-1.1.1.tgz#9c1d8257770e4a0a08063ba2ddcaf690fd457d23" integrity sha512-IpxGMdZqEhMykW0yYKGVB4vDEacPvSBH4hNpDL38ABj3W2KHNLujAljGEDg7eEjXvrRbXRSWXzANhV3c9v7nyg== -koa@2.13.4: - version "2.13.4" - resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e" - integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g== +koa@2.15.4, koa@^2.13.1, koa@^2.13.4: + version "2.15.4" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.15.4.tgz#7000b3d8354558671adb1ba1b1c09bedb5f8da75" + integrity sha512-7fNBIdrU2PEgLljXoPWoyY4r1e+ToWCmzS/wwMPbUNs7X+5MMET1ObhJBlUkF5uZG9B6QhM2zS1TsH6adegkiQ== dependencies: accepts "^1.3.5" cache-content-type "^1.0.0" content-disposition "~0.5.2" content-type "^1.0.4" - cookies "~0.8.0" - debug "^4.3.2" - delegates "^1.0.0" - depd "^2.0.0" - destroy "^1.0.4" - encodeurl "^1.0.2" - escape-html "^1.0.3" - fresh "~0.5.2" - http-assert "^1.3.0" - http-errors "^1.6.3" - is-generator-function "^1.0.7" - koa-compose "^4.1.0" - koa-convert "^2.0.0" - on-finished "^2.3.0" - only "~0.0.2" - parseurl "^1.3.2" - statuses "^1.5.0" - type-is "^1.6.16" - vary "^1.1.2" - -koa@^2.13.1, koa@^2.13.4: - version "2.14.1" - resolved "https://registry.yarnpkg.com/koa/-/koa-2.14.1.tgz#defb9589297d8eb1859936e777f3feecfc26925c" - integrity sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw== - dependencies: - accepts "^1.3.5" - cache-content-type "^1.0.0" - content-disposition "~0.5.2" - content-type "^1.0.4" - cookies "~0.8.0" + cookies "~0.9.0" debug "^4.3.2" delegates "^1.0.0" depd "^2.0.0" @@ -20451,11 +20430,6 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== -timekeeper@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" - integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== - tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -20683,7 +20657,7 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: +tsconfig-paths@^4.1.2: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== From 4685a4591646c10bc624818bbfddd941f276988c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 13 Feb 2025 09:06:44 +0000 Subject: [PATCH 101/210] Add default icon for icon settings --- packages/builder/src/stores/builder/components.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index d1acb4cfbd..440d0c1993 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -299,6 +299,8 @@ export class ComponentStore extends BudiStore { component[setting.key] = fieldOptions[0] component.label = fieldOptions[0] } + } else if (setting.type === "icon") { + component[setting.key] = "ri-star-fill" } else if (useDefaultValues && setting.defaultValue !== undefined) { // Use default value where required component[setting.key] = setting.defaultValue From b6185c3925a155901c07a37607674cd375454d30 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 13 Feb 2025 09:18:18 +0000 Subject: [PATCH 102/210] Attempt to auto-fill data provider type settings when adding components --- .../builder/src/stores/builder/components.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/stores/builder/components.ts b/packages/builder/src/stores/builder/components.ts index 440d0c1993..b3e897fa3c 100644 --- a/packages/builder/src/stores/builder/components.ts +++ b/packages/builder/src/stores/builder/components.ts @@ -11,6 +11,7 @@ import { findComponentParent, findAllMatchingComponents, makeComponentUnique, + findComponentType, } from "@/helpers/components" import { getComponentFieldOptions } from "@/helpers/formFields" import { selectedScreen } from "./screens" @@ -263,14 +264,25 @@ export class ComponentStore extends BudiStore { type: "table", } } else if (setting.type === "dataProvider") { - // Pick closest data provider where required + let providerId + + // Pick closest parent data provider if one exists const path = findComponentPath(screen.props, treeId) const providers = path.filter((component: Component) => component._component?.endsWith("/dataprovider") ) - if (providers.length) { - const id = providers[providers.length - 1]?._id - component[setting.key] = `{{ literal ${safe(id)} }}` + providerId = providers[providers.length - 1]?._id + + // If none in our direct path, select the first one the screen + if (!providerId) { + providerId = findComponentType( + screen.props, + "@budibase/standard-components/dataprovider" + )?._id + } + + if (providerId) { + component[setting.key] = `{{ literal ${safe(providerId)} }}` } } else if (setting.type.startsWith("field/")) { // Autofill form field names From ea597c90fc709e81aa9591815361d492ad83a698 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 13 Feb 2025 10:46:40 +0100 Subject: [PATCH 103/210] Initial ts conversion --- .../builder/src/stores/builder/preview.ts | 2 +- packages/client/src/components/Block.svelte | 2 +- .../src/components/app/forms/S3Upload.svelte | 2 +- .../src/stores/{builder.js => builder.ts} | 24 +++++++++++++++++-- 4 files changed, 25 insertions(+), 5 deletions(-) rename packages/client/src/stores/{builder.js => builder.ts} (87%) diff --git a/packages/builder/src/stores/builder/preview.ts b/packages/builder/src/stores/builder/preview.ts index 87b2b9355e..a0b72559aa 100644 --- a/packages/builder/src/stores/builder/preview.ts +++ b/packages/builder/src/stores/builder/preview.ts @@ -1,7 +1,7 @@ import { get } from "svelte/store" import { BudiStore } from "../BudiStore" +import { PreviewDevice } from "@budibase/types" -type PreviewDevice = "desktop" | "tablet" | "mobile" type PreviewEventHandler = (name: string, payload?: any) => void type ComponentContext = Record diff --git a/packages/client/src/components/Block.svelte b/packages/client/src/components/Block.svelte index 48c11f152a..24e010f3d9 100644 --- a/packages/client/src/components/Block.svelte +++ b/packages/client/src/components/Block.svelte @@ -1,6 +1,6 @@

import { onMount } from "svelte" - import { - Input, - Icon, - Body, - AbsTooltip, - TooltipPosition, - } from "@budibase/bbui" + import { Input, Label } from "@budibase/bbui" import { previewStore, selectedScreen } from "@/stores/builder" import type { ComponentContext } from "@budibase/types" @@ -14,6 +8,8 @@ let testValue: string | undefined + $: routeParams = baseRoute.match(/:[a-zA-Z]+/g) || [] + $: hasUrlParams = routeParams.length > 0 $: placeholder = getPlaceholder(baseRoute) $: baseInput = createBaseInput(baseRoute) $: updateTestValueFromContext($previewStore.selectedComponentContext) @@ -73,28 +69,21 @@ }) -

-
- URL Variable Testing - -
- +{#if hasUrlParams} +
+
+ +
+
+
+ +
+
+
- -
-
-
- -
-
-
-
+{/if}