@budibase/backend-core 2.24.2 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +268 -207
- package/dist/index.js.map +3 -3
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +4 -4
- package/dist/plugins.js.map +2 -2
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/context/mainContext.d.ts +1 -1
- package/dist/src/context/mainContext.js +2 -2
- package/dist/src/context/mainContext.js.map +1 -1
- package/dist/src/db/couch/DatabaseImpl.d.ts +2 -2
- package/dist/src/db/couch/DatabaseImpl.js +17 -6
- package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/objectStore/objectStore.d.ts +7 -2
- package/dist/src/objectStore/objectStore.js +26 -12
- package/dist/src/objectStore/objectStore.js.map +1 -1
- package/dist/src/objectStore/utils.d.ts +3 -0
- package/dist/src/objectStore/utils.js +80 -2
- package/dist/src/objectStore/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/context/mainContext.ts +2 -2
- package/src/db/couch/DatabaseImpl.ts +41 -9
- package/src/objectStore/objectStore.ts +37 -13
- package/src/objectStore/utils.ts +54 -2
|
@@ -13,13 +13,14 @@ import { bucketTTLConfig, budibaseTempDir } from "./utils"
|
|
|
13
13
|
import { v4 } from "uuid"
|
|
14
14
|
import { APP_PREFIX, APP_DEV_PREFIX } from "../db"
|
|
15
15
|
import fsp from "fs/promises"
|
|
16
|
+
import { HeadObjectOutput } from "aws-sdk/clients/s3"
|
|
16
17
|
|
|
17
18
|
const streamPipeline = promisify(stream.pipeline)
|
|
18
19
|
// use this as a temporary store of buckets that are being created
|
|
19
20
|
const STATE = {
|
|
20
21
|
bucketCreationPromises: {},
|
|
21
22
|
}
|
|
22
|
-
const
|
|
23
|
+
export const SIGNED_FILE_PREFIX = "/files/signed"
|
|
23
24
|
|
|
24
25
|
type ListParams = {
|
|
25
26
|
ContinuationToken?: string
|
|
@@ -40,8 +41,13 @@ type UploadParams = BaseUploadParams & {
|
|
|
40
41
|
path?: string | PathLike
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
type
|
|
44
|
-
|
|
44
|
+
export type StreamTypes =
|
|
45
|
+
| ReadStream
|
|
46
|
+
| NodeJS.ReadableStream
|
|
47
|
+
| ReadableStream<Uint8Array>
|
|
48
|
+
|
|
49
|
+
export type StreamUploadParams = BaseUploadParams & {
|
|
50
|
+
stream?: StreamTypes
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
const CONTENT_TYPE_MAP: any = {
|
|
@@ -174,11 +180,9 @@ export async function upload({
|
|
|
174
180
|
const objectStore = ObjectStore(bucketName)
|
|
175
181
|
const bucketCreated = await createBucketIfNotExists(objectStore, bucketName)
|
|
176
182
|
|
|
177
|
-
if (ttl &&
|
|
183
|
+
if (ttl && bucketCreated.created) {
|
|
178
184
|
let ttlConfig = bucketTTLConfig(bucketName, ttl)
|
|
179
|
-
|
|
180
|
-
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
|
|
181
|
-
}
|
|
185
|
+
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
let contentType = type
|
|
@@ -222,11 +226,9 @@ export async function streamUpload({
|
|
|
222
226
|
const objectStore = ObjectStore(bucketName)
|
|
223
227
|
const bucketCreated = await createBucketIfNotExists(objectStore, bucketName)
|
|
224
228
|
|
|
225
|
-
if (ttl &&
|
|
229
|
+
if (ttl && bucketCreated.created) {
|
|
226
230
|
let ttlConfig = bucketTTLConfig(bucketName, ttl)
|
|
227
|
-
|
|
228
|
-
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
|
|
229
|
-
}
|
|
231
|
+
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
|
|
230
232
|
}
|
|
231
233
|
|
|
232
234
|
// Set content type for certain known extensions
|
|
@@ -333,7 +335,7 @@ export function getPresignedUrl(
|
|
|
333
335
|
const signedUrl = new URL(url)
|
|
334
336
|
const path = signedUrl.pathname
|
|
335
337
|
const query = signedUrl.search
|
|
336
|
-
return `${
|
|
338
|
+
return `${SIGNED_FILE_PREFIX}${path}${query}`
|
|
337
339
|
}
|
|
338
340
|
}
|
|
339
341
|
|
|
@@ -521,6 +523,26 @@ export async function getReadStream(
|
|
|
521
523
|
return client.getObject(params).createReadStream()
|
|
522
524
|
}
|
|
523
525
|
|
|
526
|
+
export async function getObjectMetadata(
|
|
527
|
+
bucket: string,
|
|
528
|
+
path: string
|
|
529
|
+
): Promise<HeadObjectOutput> {
|
|
530
|
+
bucket = sanitizeBucket(bucket)
|
|
531
|
+
path = sanitizeKey(path)
|
|
532
|
+
|
|
533
|
+
const client = ObjectStore(bucket)
|
|
534
|
+
const params = {
|
|
535
|
+
Bucket: bucket,
|
|
536
|
+
Key: path,
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
try {
|
|
540
|
+
return await client.headObject(params).promise()
|
|
541
|
+
} catch (err: any) {
|
|
542
|
+
throw new Error("Unable to retrieve metadata from object")
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
524
546
|
/*
|
|
525
547
|
Given a signed url like '/files/signed/tmp-files-attachments/app_123456/myfile.txt' extract
|
|
526
548
|
the bucket and the path from it
|
|
@@ -530,7 +552,9 @@ export function extractBucketAndPath(
|
|
|
530
552
|
): { bucket: string; path: string } | null {
|
|
531
553
|
const baseUrl = url.split("?")[0]
|
|
532
554
|
|
|
533
|
-
const regex = new RegExp(
|
|
555
|
+
const regex = new RegExp(
|
|
556
|
+
`^${SIGNED_FILE_PREFIX}/(?<bucket>[^/]+)/(?<path>.+)$`
|
|
557
|
+
)
|
|
534
558
|
const match = baseUrl.match(regex)
|
|
535
559
|
|
|
536
560
|
if (match && match.groups) {
|
package/src/objectStore/utils.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { join } from "path"
|
|
1
|
+
import path, { join } from "path"
|
|
2
2
|
import { tmpdir } from "os"
|
|
3
3
|
import fs from "fs"
|
|
4
4
|
import env from "../environment"
|
|
5
5
|
import { PutBucketLifecycleConfigurationRequest } from "aws-sdk/clients/s3"
|
|
6
|
-
|
|
6
|
+
import * as objectStore from "./objectStore"
|
|
7
|
+
import {
|
|
8
|
+
AutomationAttachment,
|
|
9
|
+
AutomationAttachmentContent,
|
|
10
|
+
BucketedContent,
|
|
11
|
+
} from "@budibase/types"
|
|
7
12
|
/****************************************************
|
|
8
13
|
* NOTE: When adding a new bucket - name *
|
|
9
14
|
* sure that S3 usages (like budibase-infra) *
|
|
@@ -55,3 +60,50 @@ export const bucketTTLConfig = (
|
|
|
55
60
|
|
|
56
61
|
return params
|
|
57
62
|
}
|
|
63
|
+
|
|
64
|
+
async function processUrlAttachment(
|
|
65
|
+
attachment: AutomationAttachment
|
|
66
|
+
): Promise<AutomationAttachmentContent> {
|
|
67
|
+
const response = await fetch(attachment.url)
|
|
68
|
+
if (!response.ok || !response.body) {
|
|
69
|
+
throw new Error(`Unexpected response ${response.statusText}`)
|
|
70
|
+
}
|
|
71
|
+
const fallbackFilename = path.basename(new URL(attachment.url).pathname)
|
|
72
|
+
return {
|
|
73
|
+
filename: attachment.filename || fallbackFilename,
|
|
74
|
+
content: response.body,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function processObjectStoreAttachment(
|
|
79
|
+
attachment: AutomationAttachment
|
|
80
|
+
): Promise<BucketedContent> {
|
|
81
|
+
const result = objectStore.extractBucketAndPath(attachment.url)
|
|
82
|
+
|
|
83
|
+
if (result === null) {
|
|
84
|
+
throw new Error("Invalid signed URL")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const { bucket, path: objectPath } = result
|
|
88
|
+
const readStream = await objectStore.getReadStream(bucket, objectPath)
|
|
89
|
+
const fallbackFilename = path.basename(objectPath)
|
|
90
|
+
return {
|
|
91
|
+
bucket,
|
|
92
|
+
path: objectPath,
|
|
93
|
+
filename: attachment.filename || fallbackFilename,
|
|
94
|
+
content: readStream,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function processAutomationAttachment(
|
|
99
|
+
attachment: AutomationAttachment
|
|
100
|
+
): Promise<AutomationAttachmentContent | BucketedContent> {
|
|
101
|
+
const isFullyFormedUrl =
|
|
102
|
+
attachment.url?.startsWith("http://") ||
|
|
103
|
+
attachment.url?.startsWith("https://")
|
|
104
|
+
if (isFullyFormedUrl) {
|
|
105
|
+
return await processUrlAttachment(attachment)
|
|
106
|
+
} else {
|
|
107
|
+
return await processObjectStoreAttachment(attachment)
|
|
108
|
+
}
|
|
109
|
+
}
|