@budibase/backend-core 2.23.11 → 2.23.12
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 +91 -14
- 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 +2 -0
- package/dist/plugins.js.map +2 -2
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/environment.d.ts +1 -0
- package/dist/src/environment.js +2 -1
- package/dist/src/environment.js.map +1 -1
- package/dist/src/objectStore/objectStore.d.ts +24 -6
- package/dist/src/objectStore/objectStore.js +61 -14
- package/dist/src/objectStore/objectStore.js.map +1 -1
- package/dist/src/objectStore/utils.d.ts +3 -0
- package/dist/src/objectStore/utils.js +21 -1
- package/dist/src/objectStore/utils.js.map +1 -1
- package/dist/tests/core/utilities/index.d.ts +4 -0
- package/dist/tests/core/utilities/index.js +3 -1
- package/dist/tests/core/utilities/index.js.map +1 -1
- package/dist/tests/core/utilities/minio.d.ts +2 -0
- package/dist/tests/core/utilities/minio.js +53 -0
- package/dist/tests/core/utilities/minio.js.map +1 -0
- package/package.json +4 -4
- package/src/environment.ts +2 -0
- package/src/objectStore/objectStore.ts +97 -24
- package/src/objectStore/utils.ts +26 -0
- package/tests/core/utilities/index.ts +3 -0
- package/tests/core/utilities/minio.ts +34 -0
package/dist/index.js
CHANGED
|
@@ -54482,6 +54482,7 @@ var AutomationIOType = /* @__PURE__ */ ((AutomationIOType2) => {
|
|
|
54482
54482
|
AutomationIOType2["ARRAY"] = "array";
|
|
54483
54483
|
AutomationIOType2["JSON"] = "json";
|
|
54484
54484
|
AutomationIOType2["DATE"] = "date";
|
|
54485
|
+
AutomationIOType2["ATTACHMENT"] = "attachment";
|
|
54485
54486
|
return AutomationIOType2;
|
|
54486
54487
|
})(AutomationIOType || {});
|
|
54487
54488
|
var AutomationCustomIOType = /* @__PURE__ */ ((AutomationCustomIOType2) => {
|
|
@@ -54502,6 +54503,7 @@ var AutomationCustomIOType = /* @__PURE__ */ ((AutomationCustomIOType2) => {
|
|
|
54502
54503
|
AutomationCustomIOType2["WEBHOOK_URL"] = "webhookUrl";
|
|
54503
54504
|
AutomationCustomIOType2["AUTOMATION"] = "automation";
|
|
54504
54505
|
AutomationCustomIOType2["AUTOMATION_FIELDS"] = "automationFields";
|
|
54506
|
+
AutomationCustomIOType2["MULTI_ATTACHMENTS"] = "multi_attachments";
|
|
54505
54507
|
return AutomationCustomIOType2;
|
|
54506
54508
|
})(AutomationCustomIOType || {});
|
|
54507
54509
|
var AutomationTriggerStepId = /* @__PURE__ */ ((AutomationTriggerStepId2) => {
|
|
@@ -55611,7 +55613,8 @@ var DefaultBucketName = {
|
|
|
55611
55613
|
APPS: "prod-budi-app-assets",
|
|
55612
55614
|
TEMPLATES: "templates",
|
|
55613
55615
|
GLOBAL: "global",
|
|
55614
|
-
PLUGINS: "plugins"
|
|
55616
|
+
PLUGINS: "plugins",
|
|
55617
|
+
TEMP: "tmp-file-attachments"
|
|
55615
55618
|
};
|
|
55616
55619
|
var selfHosted = !!parseInt(process.env.SELF_HOSTED || "");
|
|
55617
55620
|
function getAPIEncryptionKey() {
|
|
@@ -55702,6 +55705,7 @@ var environment = {
|
|
|
55702
55705
|
TEMPLATES_BUCKET_NAME: process.env.TEMPLATES_BUCKET_NAME || DefaultBucketName.TEMPLATES,
|
|
55703
55706
|
GLOBAL_BUCKET_NAME: process.env.GLOBAL_BUCKET_NAME || DefaultBucketName.GLOBAL,
|
|
55704
55707
|
PLUGIN_BUCKET_NAME: process.env.PLUGIN_BUCKET_NAME || DefaultBucketName.PLUGINS,
|
|
55708
|
+
TEMP_BUCKET_NAME: process.env.TEMP_BUCKET_NAME || DefaultBucketName.TEMP,
|
|
55705
55709
|
USE_COUCH: process.env.USE_COUCH || true,
|
|
55706
55710
|
MOCK_REDIS: process.env.MOCK_REDIS,
|
|
55707
55711
|
DEFAULT_LICENSE: process.env.DEFAULT_LICENSE,
|
|
@@ -56848,16 +56852,19 @@ var objectStore_exports2 = {};
|
|
|
56848
56852
|
__export(objectStore_exports2, {
|
|
56849
56853
|
ObjectStore: () => ObjectStore,
|
|
56850
56854
|
ObjectStoreBuckets: () => ObjectStoreBuckets,
|
|
56855
|
+
bucketTTLConfig: () => bucketTTLConfig,
|
|
56851
56856
|
budibaseTempDir: () => budibaseTempDir,
|
|
56852
56857
|
clientLibraryCDNUrl: () => clientLibraryCDNUrl,
|
|
56853
56858
|
clientLibraryPath: () => clientLibraryPath,
|
|
56854
56859
|
clientLibraryUrl: () => clientLibraryUrl,
|
|
56860
|
+
createBucketIfNotExists: () => createBucketIfNotExists,
|
|
56855
56861
|
deleteFile: () => deleteFile,
|
|
56856
56862
|
deleteFiles: () => deleteFiles,
|
|
56857
56863
|
deleteFolder: () => deleteFolder,
|
|
56858
56864
|
downloadTarball: () => downloadTarball,
|
|
56859
56865
|
downloadTarballDirect: () => downloadTarballDirect,
|
|
56860
56866
|
enrichPluginURLs: () => enrichPluginURLs,
|
|
56867
|
+
extractBucketAndPath: () => extractBucketAndPath,
|
|
56861
56868
|
getAppFileUrl: () => getAppFileUrl,
|
|
56862
56869
|
getGlobalFileS3Key: () => getGlobalFileS3Key,
|
|
56863
56870
|
getGlobalFileUrl: () => getGlobalFileUrl,
|
|
@@ -56867,7 +56874,6 @@ __export(objectStore_exports2, {
|
|
|
56867
56874
|
getPresignedUrl: () => getPresignedUrl,
|
|
56868
56875
|
getReadStream: () => getReadStream,
|
|
56869
56876
|
listAllObjects: () => listAllObjects,
|
|
56870
|
-
makeSureBucketExists: () => makeSureBucketExists,
|
|
56871
56877
|
retrieve: () => retrieve,
|
|
56872
56878
|
retrieveDirectory: () => retrieveDirectory,
|
|
56873
56879
|
retrieveToTmp: () => retrieveToTmp,
|
|
@@ -56897,7 +56903,8 @@ var ObjectStoreBuckets = {
|
|
|
56897
56903
|
APPS: environment_default.APPS_BUCKET_NAME,
|
|
56898
56904
|
TEMPLATES: environment_default.TEMPLATES_BUCKET_NAME,
|
|
56899
56905
|
GLOBAL: environment_default.GLOBAL_BUCKET_NAME,
|
|
56900
|
-
PLUGINS: environment_default.PLUGIN_BUCKET_NAME
|
|
56906
|
+
PLUGINS: environment_default.PLUGIN_BUCKET_NAME,
|
|
56907
|
+
TEMP: environment_default.TEMP_BUCKET_NAME
|
|
56901
56908
|
};
|
|
56902
56909
|
var bbTmp = (0, import_path.join)((0, import_os.tmpdir)(), ".budibase");
|
|
56903
56910
|
try {
|
|
@@ -56910,6 +56917,24 @@ try {
|
|
|
56910
56917
|
function budibaseTempDir() {
|
|
56911
56918
|
return bbTmp;
|
|
56912
56919
|
}
|
|
56920
|
+
var bucketTTLConfig = (bucketName, days) => {
|
|
56921
|
+
const lifecycleRule = {
|
|
56922
|
+
ID: `${bucketName}-ExpireAfter${days}days`,
|
|
56923
|
+
Prefix: "",
|
|
56924
|
+
Status: "Enabled",
|
|
56925
|
+
Expiration: {
|
|
56926
|
+
Days: days
|
|
56927
|
+
}
|
|
56928
|
+
};
|
|
56929
|
+
const lifecycleConfiguration = {
|
|
56930
|
+
Rules: [lifecycleRule]
|
|
56931
|
+
};
|
|
56932
|
+
const params2 = {
|
|
56933
|
+
Bucket: bucketName,
|
|
56934
|
+
LifecycleConfiguration: lifecycleConfiguration
|
|
56935
|
+
};
|
|
56936
|
+
return params2;
|
|
56937
|
+
};
|
|
56913
56938
|
|
|
56914
56939
|
// src/objectStore/objectStore.ts
|
|
56915
56940
|
var import_uuid2 = require("uuid");
|
|
@@ -58216,18 +58241,22 @@ function isDocumentConflictError(error) {
|
|
|
58216
58241
|
}
|
|
58217
58242
|
|
|
58218
58243
|
// src/objectStore/objectStore.ts
|
|
58244
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
58219
58245
|
var sanitize = require("sanitize-s3-objectkey");
|
|
58220
58246
|
var streamPipeline = (0, import_util.promisify)(import_stream.default.pipeline);
|
|
58221
58247
|
var STATE = {
|
|
58222
58248
|
bucketCreationPromises: {}
|
|
58223
58249
|
};
|
|
58250
|
+
var signedFilePrefix = "/files/signed";
|
|
58224
58251
|
var CONTENT_TYPE_MAP = {
|
|
58225
58252
|
txt: "text/plain",
|
|
58226
58253
|
html: "text/html",
|
|
58227
58254
|
css: "text/css",
|
|
58228
58255
|
js: "application/javascript",
|
|
58229
58256
|
json: "application/json",
|
|
58230
|
-
gz: "application/gzip"
|
|
58257
|
+
gz: "application/gzip",
|
|
58258
|
+
svg: "image/svg+xml",
|
|
58259
|
+
form: "multipart/form-data"
|
|
58231
58260
|
};
|
|
58232
58261
|
var STRING_CONTENT_TYPES = [
|
|
58233
58262
|
CONTENT_TYPE_MAP.html,
|
|
@@ -58264,17 +58293,19 @@ function ObjectStore(bucket, opts = { presigning: false }) {
|
|
|
58264
58293
|
}
|
|
58265
58294
|
return new import_aws_sdk.default.S3(config);
|
|
58266
58295
|
}
|
|
58267
|
-
async function
|
|
58296
|
+
async function createBucketIfNotExists(client, bucketName) {
|
|
58268
58297
|
bucketName = sanitizeBucket(bucketName);
|
|
58269
58298
|
try {
|
|
58270
58299
|
await client.headBucket({
|
|
58271
58300
|
Bucket: bucketName
|
|
58272
58301
|
}).promise();
|
|
58302
|
+
return { created: false, exists: true };
|
|
58273
58303
|
} catch (err) {
|
|
58274
58304
|
const promises = STATE.bucketCreationPromises;
|
|
58275
58305
|
const doesntExist = err.statusCode === 404, noAccess = err.statusCode === 403;
|
|
58276
58306
|
if (promises[bucketName]) {
|
|
58277
58307
|
await promises[bucketName];
|
|
58308
|
+
return { created: false, exists: true };
|
|
58278
58309
|
} else if (doesntExist || noAccess) {
|
|
58279
58310
|
if (doesntExist) {
|
|
58280
58311
|
promises[bucketName] = client.createBucket({
|
|
@@ -58282,6 +58313,9 @@ async function makeSureBucketExists(client, bucketName) {
|
|
|
58282
58313
|
}).promise();
|
|
58283
58314
|
await promises[bucketName];
|
|
58284
58315
|
delete promises[bucketName];
|
|
58316
|
+
return { created: true, exists: false };
|
|
58317
|
+
} else {
|
|
58318
|
+
throw new Error("Access denied to object store bucket." + err);
|
|
58285
58319
|
}
|
|
58286
58320
|
} else {
|
|
58287
58321
|
throw new Error("Unable to write to object store bucket.");
|
|
@@ -58293,12 +58327,20 @@ async function upload({
|
|
|
58293
58327
|
filename,
|
|
58294
58328
|
path: path2,
|
|
58295
58329
|
type,
|
|
58296
|
-
metadata
|
|
58330
|
+
metadata,
|
|
58331
|
+
body: body2,
|
|
58332
|
+
ttl
|
|
58297
58333
|
}) {
|
|
58298
58334
|
const extension = filename.split(".").pop();
|
|
58299
|
-
const fileBytes =
|
|
58335
|
+
const fileBytes = path2 ? (await import_promises.default.open(path2)).createReadStream() : body2;
|
|
58300
58336
|
const objectStore = ObjectStore(bucketName);
|
|
58301
|
-
await
|
|
58337
|
+
const bucketCreated = await createBucketIfNotExists(objectStore, bucketName);
|
|
58338
|
+
if (ttl && (bucketCreated.created || bucketCreated.exists)) {
|
|
58339
|
+
let ttlConfig = bucketTTLConfig(bucketName, ttl);
|
|
58340
|
+
if (objectStore.putBucketLifecycleConfiguration) {
|
|
58341
|
+
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise();
|
|
58342
|
+
}
|
|
58343
|
+
}
|
|
58302
58344
|
let contentType = type;
|
|
58303
58345
|
if (!contentType) {
|
|
58304
58346
|
contentType = extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
|
|
@@ -58319,9 +58361,23 @@ async function upload({
|
|
|
58319
58361
|
}
|
|
58320
58362
|
return objectStore.upload(config).promise();
|
|
58321
58363
|
}
|
|
58322
|
-
async function streamUpload(
|
|
58364
|
+
async function streamUpload({
|
|
58365
|
+
bucket: bucketName,
|
|
58366
|
+
stream: stream2,
|
|
58367
|
+
filename,
|
|
58368
|
+
type,
|
|
58369
|
+
extra,
|
|
58370
|
+
ttl
|
|
58371
|
+
}) {
|
|
58372
|
+
const extension = filename.split(".").pop();
|
|
58323
58373
|
const objectStore = ObjectStore(bucketName);
|
|
58324
|
-
await
|
|
58374
|
+
const bucketCreated = await createBucketIfNotExists(objectStore, bucketName);
|
|
58375
|
+
if (ttl && (bucketCreated.created || bucketCreated.exists)) {
|
|
58376
|
+
let ttlConfig = bucketTTLConfig(bucketName, ttl);
|
|
58377
|
+
if (objectStore.putBucketLifecycleConfiguration) {
|
|
58378
|
+
await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise();
|
|
58379
|
+
}
|
|
58380
|
+
}
|
|
58325
58381
|
if (filename?.endsWith(".js")) {
|
|
58326
58382
|
extra = {
|
|
58327
58383
|
...extra,
|
|
@@ -58333,10 +58389,15 @@ async function streamUpload(bucketName, filename, stream2, extra = {}) {
|
|
|
58333
58389
|
ContentType: "image"
|
|
58334
58390
|
};
|
|
58335
58391
|
}
|
|
58392
|
+
let contentType = type;
|
|
58393
|
+
if (!contentType) {
|
|
58394
|
+
contentType = extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
|
|
58395
|
+
}
|
|
58336
58396
|
const params2 = {
|
|
58337
58397
|
Bucket: sanitizeBucket(bucketName),
|
|
58338
58398
|
Key: sanitizeKey(filename),
|
|
58339
58399
|
Body: stream2,
|
|
58400
|
+
ContentType: contentType,
|
|
58340
58401
|
...extra
|
|
58341
58402
|
};
|
|
58342
58403
|
return objectStore.upload(params2).promise();
|
|
@@ -58392,7 +58453,7 @@ function getPresignedUrl(bucketName, key, durationSeconds = 3600) {
|
|
|
58392
58453
|
const signedUrl = new URL(url);
|
|
58393
58454
|
const path2 = signedUrl.pathname;
|
|
58394
58455
|
const query = signedUrl.search;
|
|
58395
|
-
return
|
|
58456
|
+
return `${signedFilePrefix}${path2}${query}`;
|
|
58396
58457
|
}
|
|
58397
58458
|
}
|
|
58398
58459
|
async function retrieveToTmp(bucketName, filepath) {
|
|
@@ -58438,7 +58499,7 @@ async function retrieveDirectory(bucketName, path2) {
|
|
|
58438
58499
|
}
|
|
58439
58500
|
async function deleteFile(bucketName, filepath) {
|
|
58440
58501
|
const objectStore = ObjectStore(bucketName);
|
|
58441
|
-
await
|
|
58502
|
+
await createBucketIfNotExists(objectStore, bucketName);
|
|
58442
58503
|
const params2 = {
|
|
58443
58504
|
Bucket: bucketName,
|
|
58444
58505
|
Key: sanitizeKey(filepath)
|
|
@@ -58447,7 +58508,7 @@ async function deleteFile(bucketName, filepath) {
|
|
|
58447
58508
|
}
|
|
58448
58509
|
async function deleteFiles(bucketName, filepaths) {
|
|
58449
58510
|
const objectStore = ObjectStore(bucketName);
|
|
58450
|
-
await
|
|
58511
|
+
await createBucketIfNotExists(objectStore, bucketName);
|
|
58451
58512
|
const params2 = {
|
|
58452
58513
|
Bucket: bucketName,
|
|
58453
58514
|
Delete: {
|
|
@@ -58492,7 +58553,13 @@ async function uploadDirectory(bucketName, localPath, bucketPath) {
|
|
|
58492
58553
|
if (file.isDirectory()) {
|
|
58493
58554
|
uploads.push(uploadDirectory(bucketName, local, path2));
|
|
58494
58555
|
} else {
|
|
58495
|
-
uploads.push(
|
|
58556
|
+
uploads.push(
|
|
58557
|
+
streamUpload({
|
|
58558
|
+
bucket: bucketName,
|
|
58559
|
+
filename: path2,
|
|
58560
|
+
stream: import_fs3.default.createReadStream(local)
|
|
58561
|
+
})
|
|
58562
|
+
);
|
|
58496
58563
|
}
|
|
58497
58564
|
}
|
|
58498
58565
|
await Promise.all(uploads);
|
|
@@ -58530,6 +58597,16 @@ async function getReadStream(bucketName, path2) {
|
|
|
58530
58597
|
};
|
|
58531
58598
|
return client.getObject(params2).createReadStream();
|
|
58532
58599
|
}
|
|
58600
|
+
function extractBucketAndPath(url) {
|
|
58601
|
+
const baseUrl = url.split("?")[0];
|
|
58602
|
+
const regex = new RegExp(`^${signedFilePrefix}/(?<bucket>[^/]+)/(?<path>.+)$`);
|
|
58603
|
+
const match = baseUrl.match(regex);
|
|
58604
|
+
if (match && match.groups) {
|
|
58605
|
+
const { bucket, path: path2 } = match.groups;
|
|
58606
|
+
return { bucket, path: path2 };
|
|
58607
|
+
}
|
|
58608
|
+
return null;
|
|
58609
|
+
}
|
|
58533
58610
|
|
|
58534
58611
|
// src/objectStore/cloudfront.ts
|
|
58535
58612
|
var cfsign = __toESM(require("aws-cloudfront-sign"));
|