@budibase/backend-core 3.2.34 → 3.2.35

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 CHANGED
@@ -17698,7 +17698,7 @@ var environment = {
17698
17698
  MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
17699
17699
  MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
17700
17700
  AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,
17701
- AWS_REGION: process.env.AWS_REGION,
17701
+ AWS_REGION: process.env.AWS_REGION || "eu-west-1",
17702
17702
  MINIO_URL: process.env.MINIO_URL,
17703
17703
  MINIO_ENABLED: process.env.MINIO_ENABLED || 1,
17704
17704
  INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
@@ -18619,7 +18619,9 @@ __export(objectStore_exports2, {
18619
18619
  });
18620
18620
 
18621
18621
  // src/objectStore/objectStore.ts
18622
- var import_aws_sdk = __toESM(require("aws-sdk"));
18622
+ var import_client_s3 = require("@aws-sdk/client-s3");
18623
+ var import_lib_storage = require("@aws-sdk/lib-storage");
18624
+ var import_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
18623
18625
  var import_stream2 = __toESM(require("stream"));
18624
18626
  var import_node_fetch2 = __toESM(require("node-fetch"));
18625
18627
  var import_tar_fs = __toESM(require("tar-fs"));
@@ -18738,42 +18740,42 @@ function sanitizeKey(input) {
18738
18740
  function sanitizeBucket(input) {
18739
18741
  return input.replace(new RegExp(APP_DEV_PREFIX2, "g"), APP_PREFIX2);
18740
18742
  }
18741
- function ObjectStore(bucket, opts = { presigning: false }) {
18743
+ function ObjectStore(opts = { presigning: false }) {
18742
18744
  const config = {
18743
- s3ForcePathStyle: true,
18744
- signatureVersion: "v4",
18745
- apiVersion: "2006-03-01",
18746
- accessKeyId: environment_default.MINIO_ACCESS_KEY,
18747
- secretAccessKey: environment_default.MINIO_SECRET_KEY,
18745
+ forcePathStyle: true,
18746
+ credentials: {
18747
+ accessKeyId: environment_default.MINIO_ACCESS_KEY,
18748
+ secretAccessKey: environment_default.MINIO_SECRET_KEY
18749
+ },
18748
18750
  region: environment_default.AWS_REGION
18749
18751
  };
18750
- if (bucket) {
18751
- config.params = {
18752
- Bucket: sanitizeBucket(bucket)
18753
- };
18754
- }
18755
18752
  if (!environment_default.MINIO_ENABLED && environment_default.AWS_SESSION_TOKEN) {
18756
- config.sessionToken = environment_default.AWS_SESSION_TOKEN;
18753
+ config.credentials = {
18754
+ accessKeyId: environment_default.MINIO_ACCESS_KEY,
18755
+ secretAccessKey: environment_default.MINIO_SECRET_KEY,
18756
+ sessionToken: environment_default.AWS_SESSION_TOKEN
18757
+ };
18757
18758
  }
18758
18759
  if (environment_default.MINIO_URL) {
18759
18760
  if (opts.presigning && environment_default.MINIO_ENABLED) {
18760
- config.endpoint = "minio-service";
18761
+ config.endpoint = "http://minio-service";
18761
18762
  } else {
18762
18763
  config.endpoint = environment_default.MINIO_URL;
18763
18764
  }
18764
18765
  }
18765
- return new import_aws_sdk.default.S3(config);
18766
+ return new import_client_s3.S3(config);
18766
18767
  }
18767
18768
  async function createBucketIfNotExists(client, bucketName) {
18768
18769
  bucketName = sanitizeBucket(bucketName);
18769
18770
  try {
18770
18771
  await client.headBucket({
18771
18772
  Bucket: bucketName
18772
- }).promise();
18773
+ });
18773
18774
  return { created: false, exists: true };
18774
18775
  } catch (err) {
18776
+ const statusCode = err.statusCode || err.$response?.statusCode;
18775
18777
  const promises = STATE.bucketCreationPromises;
18776
- const doesntExist = err.statusCode === 404, noAccess = err.statusCode === 403;
18778
+ const doesntExist = statusCode === 404, noAccess = statusCode === 403;
18777
18779
  if (promises[bucketName]) {
18778
18780
  await promises[bucketName];
18779
18781
  return { created: false, exists: true };
@@ -18781,7 +18783,7 @@ async function createBucketIfNotExists(client, bucketName) {
18781
18783
  if (doesntExist) {
18782
18784
  promises[bucketName] = client.createBucket({
18783
18785
  Bucket: bucketName
18784
- }).promise();
18786
+ });
18785
18787
  await promises[bucketName];
18786
18788
  delete promises[bucketName];
18787
18789
  return { created: true, exists: false };
@@ -18804,21 +18806,20 @@ async function upload({
18804
18806
  }) {
18805
18807
  const extension = filename.split(".").pop();
18806
18808
  const fileBytes = path3 ? (await import_promises.default.open(path3)).createReadStream() : body2;
18807
- const objectStore = ObjectStore(bucketName);
18809
+ const objectStore = ObjectStore();
18808
18810
  const bucketCreated = await createBucketIfNotExists(objectStore, bucketName);
18809
18811
  if (ttl && bucketCreated.created) {
18810
18812
  let ttlConfig = bucketTTLConfig(bucketName, ttl);
18811
- await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise();
18813
+ await objectStore.putBucketLifecycleConfiguration(ttlConfig);
18812
18814
  }
18813
18815
  let contentType = type;
18814
- if (!contentType) {
18815
- contentType = extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
18816
- }
18816
+ const finalContentType = contentType ? contentType : extension ? CONTENT_TYPE_MAP[extension.toLowerCase()] : CONTENT_TYPE_MAP.txt;
18817
18817
  const config = {
18818
18818
  // windows file paths need to be converted to forward slashes for s3
18819
+ Bucket: sanitizeBucket(bucketName),
18819
18820
  Key: sanitizeKey(filename),
18820
18821
  Body: fileBytes,
18821
- ContentType: contentType
18822
+ ContentType: finalContentType
18822
18823
  };
18823
18824
  if (metadata && typeof metadata === "object") {
18824
18825
  for (let key of Object.keys(metadata)) {
@@ -18828,7 +18829,11 @@ async function upload({
18828
18829
  }
18829
18830
  config.Metadata = metadata;
18830
18831
  }
18831
- return objectStore.upload(config).promise();
18832
+ const upload2 = new import_lib_storage.Upload({
18833
+ client: objectStore,
18834
+ params: config
18835
+ });
18836
+ return upload2.done();
18832
18837
  }
18833
18838
  async function streamUpload({
18834
18839
  bucket: bucketName,
@@ -18842,11 +18847,11 @@ async function streamUpload({
18842
18847
  throw new Error("Stream to upload is invalid/undefined");
18843
18848
  }
18844
18849
  const extension = filename.split(".").pop();
18845
- const objectStore = ObjectStore(bucketName);
18850
+ const objectStore = ObjectStore();
18846
18851
  const bucketCreated = await createBucketIfNotExists(objectStore, bucketName);
18847
18852
  if (ttl && bucketCreated.created) {
18848
18853
  let ttlConfig = bucketTTLConfig(bucketName, ttl);
18849
- await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise();
18854
+ await objectStore.putBucketLifecycleConfiguration(ttlConfig);
18850
18855
  }
18851
18856
  if (filename?.endsWith(".js")) {
18852
18857
  extra = {
@@ -18871,37 +18876,45 @@ async function streamUpload({
18871
18876
  ContentType: contentType,
18872
18877
  ...extra
18873
18878
  };
18874
- const details = await objectStore.upload(params2).promise();
18879
+ const upload2 = new import_lib_storage.Upload({
18880
+ client: objectStore,
18881
+ params: params2
18882
+ });
18883
+ const details = await upload2.done();
18875
18884
  const headDetails = await objectStore.headObject({
18876
18885
  Bucket: bucket,
18877
18886
  Key: objKey
18878
- }).promise();
18887
+ });
18879
18888
  return {
18880
18889
  ...details,
18881
18890
  ContentLength: headDetails.ContentLength
18882
18891
  };
18883
18892
  }
18884
18893
  async function retrieve(bucketName, filepath) {
18885
- const objectStore = ObjectStore(bucketName);
18894
+ const objectStore = ObjectStore();
18886
18895
  const params2 = {
18887
18896
  Bucket: sanitizeBucket(bucketName),
18888
18897
  Key: sanitizeKey(filepath)
18889
18898
  };
18890
- const response = await objectStore.getObject(params2).promise();
18899
+ const response = await objectStore.getObject(params2);
18900
+ if (!response.Body) {
18901
+ throw new Error("Unable to retrieve object");
18902
+ }
18903
+ const nodeResponse = response.Body;
18891
18904
  if (STRING_CONTENT_TYPES.includes(response.ContentType)) {
18892
- return response.Body.toString("utf8");
18905
+ return nodeResponse.toString();
18893
18906
  } else {
18894
- return response.Body;
18907
+ return nodeResponse;
18895
18908
  }
18896
18909
  }
18897
18910
  async function listAllObjects(bucketName, path3) {
18898
- const objectStore = ObjectStore(bucketName);
18911
+ const objectStore = ObjectStore();
18899
18912
  const list = (params2 = {}) => {
18900
18913
  return objectStore.listObjectsV2({
18901
18914
  ...params2,
18902
18915
  Bucket: sanitizeBucket(bucketName),
18903
18916
  Prefix: sanitizeKey(path3)
18904
- }).promise();
18917
+ });
18905
18918
  };
18906
18919
  let isTruncated = false, token, objects = [];
18907
18920
  do {
@@ -18918,14 +18931,15 @@ async function listAllObjects(bucketName, path3) {
18918
18931
  } while (isTruncated && token);
18919
18932
  return objects;
18920
18933
  }
18921
- function getPresignedUrl(bucketName, key, durationSeconds = 3600) {
18922
- const objectStore = ObjectStore(bucketName, { presigning: true });
18934
+ async function getPresignedUrl(bucketName, key, durationSeconds = 3600) {
18935
+ const objectStore = ObjectStore({ presigning: true });
18923
18936
  const params2 = {
18924
18937
  Bucket: sanitizeBucket(bucketName),
18925
- Key: sanitizeKey(key),
18926
- Expires: durationSeconds
18938
+ Key: sanitizeKey(key)
18927
18939
  };
18928
- const url = objectStore.getSignedUrl("getObject", params2);
18940
+ const url = await (0, import_s3_request_presigner.getSignedUrl)(objectStore, new import_client_s3.GetObjectCommand(params2), {
18941
+ expiresIn: durationSeconds
18942
+ });
18929
18943
  if (!environment_default.MINIO_ENABLED) {
18930
18944
  return url;
18931
18945
  } else {
@@ -18940,7 +18954,11 @@ async function retrieveToTmp(bucketName, filepath) {
18940
18954
  filepath = sanitizeKey(filepath);
18941
18955
  const data = await retrieve(bucketName, filepath);
18942
18956
  const outputPath = (0, import_path2.join)(budibaseTempDir(), (0, import_uuid2.v4)());
18943
- import_fs3.default.writeFileSync(outputPath, data);
18957
+ if (data instanceof import_stream2.default.Readable) {
18958
+ data.pipe(import_fs3.default.createWriteStream(outputPath));
18959
+ } else {
18960
+ import_fs3.default.writeFileSync(outputPath, data);
18961
+ }
18944
18962
  return outputPath;
18945
18963
  }
18946
18964
  async function retrieveDirectory(bucketName, path3) {
@@ -18977,16 +18995,16 @@ async function retrieveDirectory(bucketName, path3) {
18977
18995
  return writePath;
18978
18996
  }
18979
18997
  async function deleteFile(bucketName, filepath) {
18980
- const objectStore = ObjectStore(bucketName);
18998
+ const objectStore = ObjectStore();
18981
18999
  await createBucketIfNotExists(objectStore, bucketName);
18982
19000
  const params2 = {
18983
19001
  Bucket: bucketName,
18984
19002
  Key: sanitizeKey(filepath)
18985
19003
  };
18986
- return objectStore.deleteObject(params2).promise();
19004
+ return objectStore.deleteObject(params2);
18987
19005
  }
18988
19006
  async function deleteFiles(bucketName, filepaths) {
18989
- const objectStore = ObjectStore(bucketName);
19007
+ const objectStore = ObjectStore();
18990
19008
  await createBucketIfNotExists(objectStore, bucketName);
18991
19009
  const params2 = {
18992
19010
  Bucket: bucketName,
@@ -18994,17 +19012,17 @@ async function deleteFiles(bucketName, filepaths) {
18994
19012
  Objects: filepaths.map((path3) => ({ Key: sanitizeKey(path3) }))
18995
19013
  }
18996
19014
  };
18997
- return objectStore.deleteObjects(params2).promise();
19015
+ return objectStore.deleteObjects(params2);
18998
19016
  }
18999
19017
  async function deleteFolder(bucketName, folder) {
19000
19018
  bucketName = sanitizeBucket(bucketName);
19001
19019
  folder = sanitizeKey(folder);
19002
- const client = ObjectStore(bucketName);
19020
+ const client = ObjectStore();
19003
19021
  const listParams = {
19004
19022
  Bucket: bucketName,
19005
19023
  Prefix: folder
19006
19024
  };
19007
- const existingObjectsResponse = await client.listObjects(listParams).promise();
19025
+ const existingObjectsResponse = await client.listObjects(listParams);
19008
19026
  if (existingObjectsResponse.Contents?.length === 0) {
19009
19027
  return;
19010
19028
  }
@@ -19017,7 +19035,7 @@ async function deleteFolder(bucketName, folder) {
19017
19035
  existingObjectsResponse.Contents?.forEach((content) => {
19018
19036
  deleteParams.Delete.Objects.push({ Key: content.Key });
19019
19037
  });
19020
- const deleteResponse = await client.deleteObjects(deleteParams).promise();
19038
+ const deleteResponse = await client.deleteObjects(deleteParams);
19021
19039
  if (deleteResponse.Deleted?.length === 1e3) {
19022
19040
  return deleteFolder(bucketName, folder);
19023
19041
  }
@@ -19069,23 +19087,27 @@ async function downloadTarball(url, bucketName, path3) {
19069
19087
  async function getReadStream(bucketName, path3) {
19070
19088
  bucketName = sanitizeBucket(bucketName);
19071
19089
  path3 = sanitizeKey(path3);
19072
- const client = ObjectStore(bucketName);
19090
+ const client = ObjectStore();
19073
19091
  const params2 = {
19074
19092
  Bucket: bucketName,
19075
19093
  Key: path3
19076
19094
  };
19077
- return client.getObject(params2).createReadStream();
19095
+ const response = await client.getObject(params2);
19096
+ if (!response.Body || !(response.Body instanceof import_stream2.default.Readable)) {
19097
+ throw new Error("Unable to retrieve stream - invalid response");
19098
+ }
19099
+ return response.Body;
19078
19100
  }
19079
19101
  async function getObjectMetadata(bucket, path3) {
19080
19102
  bucket = sanitizeBucket(bucket);
19081
19103
  path3 = sanitizeKey(path3);
19082
- const client = ObjectStore(bucket);
19104
+ const client = ObjectStore();
19083
19105
  const params2 = {
19084
19106
  Bucket: bucket,
19085
19107
  Key: path3
19086
19108
  };
19087
19109
  try {
19088
- return await client.headObject(params2).promise();
19110
+ return await client.headObject(params2);
19089
19111
  } catch (err) {
19090
19112
  throw new Error("Unable to retrieve metadata from object");
19091
19113
  }
@@ -19143,7 +19165,7 @@ var import_querystring = __toESM(require("querystring"));
19143
19165
  function clientLibraryPath(appId) {
19144
19166
  return `${sanitizeKey(appId)}/budibase-client.js`;
19145
19167
  }
19146
- function clientLibraryCDNUrl(appId, version) {
19168
+ async function clientLibraryCDNUrl(appId, version) {
19147
19169
  let file = clientLibraryPath(appId);
19148
19170
  if (environment_default.CLOUDFRONT_CDN) {
19149
19171
  if (version) {
@@ -19151,7 +19173,7 @@ function clientLibraryCDNUrl(appId, version) {
19151
19173
  }
19152
19174
  return getUrl(file);
19153
19175
  } else {
19154
- return getPresignedUrl(environment_default.APPS_BUCKET_NAME, file);
19176
+ return await getPresignedUrl(environment_default.APPS_BUCKET_NAME, file);
19155
19177
  }
19156
19178
  }
19157
19179
  function clientLibraryUrl(appId, version) {
@@ -19169,16 +19191,16 @@ function clientLibraryUrl(appId, version) {
19169
19191
  }
19170
19192
  return `/api/assets/client?${import_querystring.default.encode(qsParams)}`;
19171
19193
  }
19172
- function getAppFileUrl(s3Key) {
19194
+ async function getAppFileUrl(s3Key) {
19173
19195
  if (environment_default.CLOUDFRONT_CDN) {
19174
19196
  return getPresignedUrl2(s3Key);
19175
19197
  } else {
19176
- return getPresignedUrl(environment_default.APPS_BUCKET_NAME, s3Key);
19198
+ return await getPresignedUrl(environment_default.APPS_BUCKET_NAME, s3Key);
19177
19199
  }
19178
19200
  }
19179
19201
 
19180
19202
  // src/objectStore/buckets/global.ts
19181
- var getGlobalFileUrl = (type, name, etag) => {
19203
+ var getGlobalFileUrl = async (type, name, etag) => {
19182
19204
  let file = getGlobalFileS3Key(type, name);
19183
19205
  if (environment_default.CLOUDFRONT_CDN) {
19184
19206
  if (etag) {
@@ -19186,7 +19208,7 @@ var getGlobalFileUrl = (type, name, etag) => {
19186
19208
  }
19187
19209
  return getPresignedUrl2(file);
19188
19210
  } else {
19189
- return getPresignedUrl(environment_default.GLOBAL_BUCKET_NAME, file);
19211
+ return await getPresignedUrl(environment_default.GLOBAL_BUCKET_NAME, file);
19190
19212
  }
19191
19213
  };
19192
19214
  var getGlobalFileS3Key = (type, name) => {
@@ -19199,32 +19221,34 @@ var getGlobalFileS3Key = (type, name) => {
19199
19221
  };
19200
19222
 
19201
19223
  // src/objectStore/buckets/plugins.ts
19202
- function enrichPluginURLs(plugins) {
19224
+ async function enrichPluginURLs(plugins) {
19203
19225
  if (!plugins || !plugins.length) {
19204
19226
  return [];
19205
19227
  }
19206
- return plugins.map((plugin) => {
19207
- const jsUrl = getPluginJSUrl(plugin);
19208
- const iconUrl = getPluginIconUrl(plugin);
19209
- return { ...plugin, jsUrl, iconUrl };
19210
- });
19228
+ return await Promise.all(
19229
+ plugins.map(async (plugin) => {
19230
+ const jsUrl = await getPluginJSUrl(plugin);
19231
+ const iconUrl = await getPluginIconUrl(plugin);
19232
+ return { ...plugin, jsUrl, iconUrl };
19233
+ })
19234
+ );
19211
19235
  }
19212
- function getPluginJSUrl(plugin) {
19236
+ async function getPluginJSUrl(plugin) {
19213
19237
  const s3Key = getPluginJSKey(plugin);
19214
19238
  return getPluginUrl(s3Key);
19215
19239
  }
19216
- function getPluginIconUrl(plugin) {
19240
+ async function getPluginIconUrl(plugin) {
19217
19241
  const s3Key = getPluginIconKey(plugin);
19218
19242
  if (!s3Key) {
19219
19243
  return;
19220
19244
  }
19221
19245
  return getPluginUrl(s3Key);
19222
19246
  }
19223
- function getPluginUrl(s3Key) {
19247
+ async function getPluginUrl(s3Key) {
19224
19248
  if (environment_default.CLOUDFRONT_CDN) {
19225
19249
  return getPresignedUrl2(s3Key);
19226
19250
  } else {
19227
- return getPresignedUrl(environment_default.PLUGIN_BUCKET_NAME, s3Key);
19251
+ return await getPresignedUrl(environment_default.PLUGIN_BUCKET_NAME, s3Key);
19228
19252
  }
19229
19253
  }
19230
19254
  function getPluginJSKey(plugin) {