@qrvey/object-storage 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @qrvey/object-storage
2
2
 
3
3
  ![install size](https://packagephobia.com/badge?p=%40qrvey%2Fobject-storage)
4
- ![coverage](https://img.shields.io/badge/unit_test_coverage-11%25-brightgreen)
4
+ ![coverage](https://img.shields.io/badge/unit_test_coverage-12%25-brightgreen)
5
5
 
6
6
  The `@qrvey/object-storage` package provides a unified interface for ...
7
7
 
package/dist/cjs/index.js CHANGED
@@ -3,6 +3,12 @@
3
3
  var storageBlob = require('@azure/storage-blob');
4
4
  var clientS3 = require('@aws-sdk/client-s3');
5
5
  var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
6
+ var stream = require('stream');
7
+ var libStorage = require('@aws-sdk/lib-storage');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var stream__default = /*#__PURE__*/_interopDefault(stream);
6
12
 
7
13
  var __defProp = Object.defineProperty;
8
14
  var __defProps = Object.defineProperties;
@@ -93,6 +99,10 @@ var BlobStorageService = class {
93
99
  process.env.AZURE_STORAGE_CONNECTION_STRING
94
100
  );
95
101
  }
102
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
103
+ createUploadWriteStream(key) {
104
+ throw new Error("Method not implemented.");
105
+ }
96
106
  getUploadUrl(key, expiresInMinutes) {
97
107
  throw new Error("Method not implemented.");
98
108
  }
@@ -397,8 +407,6 @@ function s3ObjectToObjectResponse(s3Object) {
397
407
  lastModified: s3Object.LastModified
398
408
  };
399
409
  }
400
-
401
- // src/services/storage/s3/s3Storage.service.ts
402
410
  var S3StorageService = class {
403
411
  constructor(bucketName) {
404
412
  this.s3Client = new clientS3.S3Client({
@@ -568,6 +576,29 @@ var S3StorageService = class {
568
576
  await this.s3Client.send(command);
569
577
  return { key };
570
578
  }
579
+ /**
580
+ * Creates a writable stream for uploading a file to the S3 bucket.
581
+ *
582
+ * @param {string} key - The key of the object to upload.
583
+ * @return {CreateUploadWriteStreamResponse} An object containing the key of the uploaded object, the writable stream, and a promise that resolves when the upload is complete.
584
+ */
585
+ createUploadWriteStream(key) {
586
+ const streamPassThrough = new stream__default.default.PassThrough();
587
+ const params = {
588
+ Bucket: this.bucketName,
589
+ Key: key,
590
+ Body: streamPassThrough
591
+ };
592
+ const upload = new libStorage.Upload({
593
+ client: this.s3Client,
594
+ params
595
+ });
596
+ return {
597
+ key,
598
+ stream: streamPassThrough,
599
+ promise: upload.done()
600
+ };
601
+ }
571
602
  /**
572
603
  * Deletes an object from the S3 bucket.
573
604
  * @param key - The key of the object to delete.
@@ -682,6 +713,18 @@ var ObjectStorageService = class _ObjectStorageService {
682
713
  bucketName
683
714
  ).then((instance) => instance.upload(key, body, metadata));
684
715
  }
716
+ /**
717
+ * Creates an upload write stream for the specified key in the object storage service.
718
+ *
719
+ * @param {string} key - The key of the object to create the upload write stream for.
720
+ * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.
721
+ * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.
722
+ */
723
+ static async createUploadWriteStream(key, bucketName) {
724
+ return _ObjectStorageService.getObjectStorageServiceInstance(
725
+ bucketName
726
+ ).then((instance) => instance.createUploadWriteStream(key));
727
+ }
685
728
  /**
686
729
  * Deletes an object from the object storage service.
687
730
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts","../../src/shared/utils/errorHandler.ts","../../src/services/storage/blob/blobHelpers.ts","../../src/services/storage/s3/s3Storage.service.ts","../../src/services/storage/s3/s3Helpers.ts","../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n ListResponseItem,\n GetUploadUrlResponse,\n} from '../../../types';\nimport {\n BlobServiceClient,\n BlobSASPermissions,\n BlobItem,\n ContainerClient,\n} from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nimport { ErrorHandler } from '../../../shared/utils/errorHandler';\nimport { BlobPropertiesResponseToObjectResponse } from './blobHelpers';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n getUploadUrl(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n key: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n expiresInMinutes: number,\n ): Promise<GetUploadUrlResponse> {\n throw new Error('Method not implemented.');\n }\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n getHeadObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .getProperties()\n .then((blobProperties) => {\n return resolve(\n BlobPropertiesResponseToObjectResponse(\n blobProperties,\n ),\n );\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves an object from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to retrieve.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the object data, including the body, metadata, content type, and content length, or rejects with an error if there was an issue.\n */\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves a signed URL for the blob with the specified name that expires after a certain period.\n *\n * @param {string} blobName - The name of the blob to generate the signed URL for.\n * @param {number} expiresInMinutes - The duration in minutes until the signed URL expires.\n * @return {Promise<string>} A Promise that resolves with the signed URL.\n */\n getDownloadUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Uploads a file to the blob storage service.\n *\n * @param {string} blobName - The name of the blob to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {{ [key: string]: string } | undefined} [metadata] - Optional metadata to associate with the blob.\n * @return {Promise<UploadResponse>} A promise that resolves to the response object containing the key of the uploaded blob, or rejects with an error if there was an issue.\n */\n upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n blockBlobClient\n .uploadStream(\n body as Readable,\n undefined,\n undefined,\n metadata,\n )\n .then(() => resolve({ key: blobName }))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Deletes a blob from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to be deleted.\n * @return {Promise<boolean>} A promise that resolves to true if the blob is successfully deleted, or rejects with an error if there was an issue.\n */\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .delete()\n .then(() => resolve(true))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Lists a chunk of blobs from the specified container client based on the provided options and continuation token.\n *\n * @param {ListRequestOptions} options - The options for listing the blobs.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of blobs to list in a single page.\n * @param {ContainerClient} containerClient - The container client to list the blobs from.\n * @return {Promise<{ items: BlobItem[]; continuationToken?: string }>} - A promise that resolves to an object containing the list of blob items and an optional continuation token.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n containerClient: ContainerClient,\n ): Promise<{ items: BlobItem[]; continuationToken?: string }> {\n const iterator = containerClient\n .listBlobsFlat({\n prefix: options.prefix,\n })\n .byPage({\n maxPageSize: limit,\n continuationToken: continuationToken,\n });\n\n const items: BlobItem[] = [];\n const response = (await iterator.next()).value;\n items.push(...response.segment.blobItems);\n return {\n items,\n continuationToken: response.continuationToken,\n };\n }\n\n /**\n * Retrieves a list of blob contents based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the blob contents.\n * @return {Promise<{ contents: BlobItem[]; nextContinuationToken?: string }>} A promise that resolves to the list of blob contents and the next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: BlobItem[]; nextContinuationToken?: string }> {\n let responseContents: BlobItem[] = [];\n let continuationToken: string | undefined = options.pagination;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n while (continueListing) {\n const response = await this.listChunk(\n options,\n continuationToken,\n limit - responseContents.length,\n containerClient,\n );\n continuationToken = response.continuationToken;\n responseContents = responseContents.concat(response.items);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists blobs in the Azure Blob Storage container with pagination.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to a paginated list of blob names.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? response.contents.map((blob) => {\n return {\n key: blob.name,\n lastModified: blob.properties.lastModified,\n size: blob.properties.contentLength!,\n eTag: blob.properties.etag,\n };\n })\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken?.length\n ? response.nextContinuationToken\n : null,\n count: items.length,\n };\n }\n\n /**\n * Lists all blobs in the Azure Blob Storage container.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to list of blob names.\n */\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination = response.pagination ?? undefined;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n}\n","import { CustomError } from '../../types/CustomError';\n\nconst errorMessages: { [key: string]: string } = {\n AccessDenied: 'Access denied',\n AccountProblem: 'There is a problem with your account',\n AllAccessDisabled: 'All access to this resource has been disabled',\n BucketAlreadyExists: 'The requested bucket name is not available',\n BucketNotEmpty: 'The bucket you tried to delete is not empty',\n EntityTooLarge: 'The entity you are trying to upload is too large',\n ExpiredToken: 'The provided token has expired',\n InternalError: 'An internal server error has occurred',\n InvalidAccessKeyId:\n 'The AWS access key ID you provided does not exist in our records',\n InvalidBucketName: 'The specified bucket name is not valid',\n InvalidObjectState:\n 'The operation is not valid for the current state of the object',\n InvalidToken: 'The provided token is invalid',\n NoSuchBucket: 'The specified bucket does not exist',\n NoSuchKey: 'The specified key does not exist',\n PreconditionFailed: 'The condition specified in the request is not met',\n RequestTimeout: 'The request timed out',\n ServiceUnavailable: 'The service is currently unavailable',\n SignatureDoesNotMatch:\n 'The request signature we calculated does not match the signature you provided',\n SlowDown: 'Please reduce your request rate',\n TemporaryRedirect: 'Temporary redirect',\n DEFAULT: 'An unknown error occurred',\n};\n\nexport class ErrorHandler {\n static handleError(\n errorCode: string,\n errorMessage?: string,\n errorObj?: Error,\n ): CustomError {\n const errorResponse: CustomError = {\n code: errorCode,\n message:\n errorMessage ||\n errorMessages[errorCode] ||\n errorMessages['DEFAULT'],\n timestamp: new Date().toISOString(),\n error: errorObj\n ? {\n name: errorObj.name,\n message: errorObj.message,\n stack: errorObj.stack || null,\n }\n : null,\n };\n\n // Return the structured object\n return errorResponse;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectResponse } from '../../../types';\nimport { BlobGetPropertiesResponse } from '@azure/storage-blob';\n\nexport function BlobPropertiesResponseToObjectResponse(\n blobProperties: BlobGetPropertiesResponse,\n): GetObjectResponse {\n return {\n lastModified: blobProperties.lastModified,\n contentLength: blobProperties.contentLength,\n contentType: blobProperties.contentType,\n eTag: blobProperties.etag,\n metadata: blobProperties.metadata,\n contentEncoding: blobProperties.contentEncoding,\n cacheControl: blobProperties.cacheControl,\n contentDisposition: blobProperties.contentDisposition,\n contentLanguage: blobProperties.contentLanguage,\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectAclCommandInput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n GetObjectResponse,\n GetUploadUrlResponse,\n ListRequestOptions,\n ListResponse,\n ListResponseItem,\n UploadResponse,\n} from '../../../types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport {\n listResponseContentsToListResponseItems,\n s3ObjectToObjectResponse,\n} from './s3Helpers';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client = new S3Client({\n region: process.env.AWS_REGION,\n });\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n }\n\n /**\n * Retrieves a chunk of objects from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the objects.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of objects to retrieve.\n * @return {Promise<ListObjectsV2CommandOutput>} - A promise that resolves to the response containing the list of objects and metadata.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n ): Promise<ListObjectsV2CommandOutput> {\n const command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken || options.pagination,\n Prefix: options.prefix,\n MaxKeys: limit,\n });\n\n return this.s3Client.send(command);\n }\n\n /**\n * Retrieves a list of contents from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the contents.\n * @return {Promise<{ contents: unknown[]; nextContinuationToken?: string }>} - A promise that resolves to an object containing the list of contents and an optional next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: unknown[]; nextContinuationToken?: string }> {\n let responseContents: any[] = [];\n let continuationToken: string | undefined = undefined;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n while (continueListing) {\n const listChunkLimit = limit - responseContents.length;\n const response = await this.listChunk(\n options,\n continuationToken,\n listChunkLimit,\n );\n continuationToken = response.NextContinuationToken;\n responseContents = responseContents.concat(response.Contents ?? []);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists objects in the S3 bucket with pagination.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to a paginated list of object keys.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? listResponseContentsToListResponseItems(response.contents)\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken ?? null,\n count: items.length,\n };\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to list of object keys.\n */\n\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination =\n response.pagination === null ? undefined : response.pagination;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getHeadObject(key: string): Promise<GetObjectResponse> {\n const command = new HeadObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getDownloadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Retrieves a signed URL for uploading an object to the S3 bucket.\n *\n * @param {string} key - The key of the object to be uploaded.\n * @param {number} [expiresInMinutes=60] - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n async getUploadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<GetUploadUrlResponse> {\n const expiresIn = expiresInMinutes * 60;\n\n const putObjectCommandParams: PutObjectAclCommandInput = {\n Bucket: process.env.UPLOAD_BUCKET_NAME,\n Key: key,\n ACL: 'private',\n };\n\n const command = new PutObjectCommand(putObjectCommandParams);\n\n const signedUrl = await getSignedUrl(this.s3Client, command, {\n expiresIn,\n });\n\n return {\n signedUrl,\n key: `https://${process.env.UPLOAD_BUCKET_NAME}.s3.${process.env.AWS_DEFAULT_REGION}.amazonaws.com/${key}`,\n };\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectCommandOutput } from '@aws-sdk/client-s3';\nimport { GetObjectResponse, ListResponseItem } from '../../../types';\nimport { Readable } from 'stream';\n\n/**\n * Converts an array of S3 response contents into an array of ListResponseItem objects.\n *\n * @param {any[]} responseContents - The array of S3 response contents.\n * @return {ListResponseItem[]} The array of ListResponseItem objects.\n */\nexport function listResponseContentsToListResponseItems(\n responseContents: any[],\n): ListResponseItem[] {\n return responseContents.map((responseContent) => {\n return {\n key: responseContent.Key,\n lastModified: new Date(responseContent.LastModified),\n size: responseContent.Size,\n eTag: responseContent.ETag,\n };\n });\n}\n\n/**\n * Converts an S3 object response to a standardized object response.\n *\n * @param {GetObjectCommandOutput} s3Object - The S3 object response to convert.\n * @return {GetObjectResponse} The converted object response.\n */\nexport function s3ObjectToObjectResponse(\n s3Object: GetObjectCommandOutput,\n): GetObjectResponse {\n return {\n body: s3Object.Body as Readable,\n metadata: s3Object.Metadata,\n contentType: s3Object.ContentType,\n contentLength: s3Object.ContentLength as number,\n contentEncoding: s3Object.ContentEncoding,\n cacheControl: s3Object.CacheControl,\n contentDisposition: s3Object.ContentDisposition,\n contentLanguage: s3Object.ContentLanguage,\n eTag: s3Object.ETag,\n lastModified: s3Object.LastModified,\n };\n}\n","import { IObjectStorage } from '../interfaces';\nimport { S3StorageService, BlobStorageService } from './storage';\n\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n if (isBlobStorageService) {\n return new BlobStorageService(bucketName);\n } else {\n return new S3StorageService(bucketName);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n GetUploadUrlResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n /**\n * Retrieves a list of objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of objects.\n */\n static async list(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list(options));\n }\n\n /**\n * Retrieves a list of all objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of all objects.\n */\n static async listAll(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.listAll(options));\n }\n\n /**\n * Retrieves an object from the object storage service.\n *\n * @param {string} key - The key of the object to retrieve.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the retrieved object.\n */\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n /**\n * Retrieves a signed URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the signed URL.\n * @param {number} expiresInMinutes - The number of minutes until the signed URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated signed URL.\n */\n static async getDownloadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getDownloadUrl(key, expiresInMinutes));\n }\n\n /**\n * Retrieves an upload URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the upload URL.\n * @param {number} expiresInMinutes - The number of minutes until the upload URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated upload URL.\n */\n static async getUploadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<GetUploadUrlResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getUploadUrl(key, expiresInMinutes));\n }\n\n /**\n * Uploads a file to the object storage service.\n *\n * @param {string} key - The key of the object to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {Object} [metadata] - Optional metadata to associate with the object.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<UploadResponse>} A promise that resolves to the response of the upload operation.\n */\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n /**\n * Deletes an object from the object storage service.\n *\n * @param {string} key - The key of the object to delete.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<boolean>} A promise that resolves to true if the object was successfully deleted, or false otherwise.\n */\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts","../../src/shared/utils/errorHandler.ts","../../src/services/storage/blob/blobHelpers.ts","../../src/services/storage/s3/s3Storage.service.ts","../../src/services/storage/s3/s3Helpers.ts","../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n ListResponseItem,\n GetUploadUrlResponse,\n CreateUploadWriteStreamResponse,\n} from '../../../types';\nimport {\n BlobServiceClient,\n BlobSASPermissions,\n BlobItem,\n ContainerClient,\n} from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nimport { ErrorHandler } from '../../../shared/utils/errorHandler';\nimport { BlobPropertiesResponseToObjectResponse } from './blobHelpers';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n createUploadWriteStream(key: string): CreateUploadWriteStreamResponse {\n throw new Error('Method not implemented.');\n }\n getUploadUrl(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n key: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n expiresInMinutes: number,\n ): Promise<GetUploadUrlResponse> {\n throw new Error('Method not implemented.');\n }\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n getHeadObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .getProperties()\n .then((blobProperties) => {\n return resolve(\n BlobPropertiesResponseToObjectResponse(\n blobProperties,\n ),\n );\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves an object from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to retrieve.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the object data, including the body, metadata, content type, and content length, or rejects with an error if there was an issue.\n */\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves a signed URL for the blob with the specified name that expires after a certain period.\n *\n * @param {string} blobName - The name of the blob to generate the signed URL for.\n * @param {number} expiresInMinutes - The duration in minutes until the signed URL expires.\n * @return {Promise<string>} A Promise that resolves with the signed URL.\n */\n getDownloadUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Uploads a file to the blob storage service.\n *\n * @param {string} blobName - The name of the blob to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {{ [key: string]: string } | undefined} [metadata] - Optional metadata to associate with the blob.\n * @return {Promise<UploadResponse>} A promise that resolves to the response object containing the key of the uploaded blob, or rejects with an error if there was an issue.\n */\n upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n blockBlobClient\n .uploadStream(\n body as Readable,\n undefined,\n undefined,\n metadata,\n )\n .then(() => resolve({ key: blobName }))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Deletes a blob from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to be deleted.\n * @return {Promise<boolean>} A promise that resolves to true if the blob is successfully deleted, or rejects with an error if there was an issue.\n */\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .delete()\n .then(() => resolve(true))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Lists a chunk of blobs from the specified container client based on the provided options and continuation token.\n *\n * @param {ListRequestOptions} options - The options for listing the blobs.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of blobs to list in a single page.\n * @param {ContainerClient} containerClient - The container client to list the blobs from.\n * @return {Promise<{ items: BlobItem[]; continuationToken?: string }>} - A promise that resolves to an object containing the list of blob items and an optional continuation token.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n containerClient: ContainerClient,\n ): Promise<{ items: BlobItem[]; continuationToken?: string }> {\n const iterator = containerClient\n .listBlobsFlat({\n prefix: options.prefix,\n })\n .byPage({\n maxPageSize: limit,\n continuationToken: continuationToken,\n });\n\n const items: BlobItem[] = [];\n const response = (await iterator.next()).value;\n items.push(...response.segment.blobItems);\n return {\n items,\n continuationToken: response.continuationToken,\n };\n }\n\n /**\n * Retrieves a list of blob contents based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the blob contents.\n * @return {Promise<{ contents: BlobItem[]; nextContinuationToken?: string }>} A promise that resolves to the list of blob contents and the next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: BlobItem[]; nextContinuationToken?: string }> {\n let responseContents: BlobItem[] = [];\n let continuationToken: string | undefined = options.pagination;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n while (continueListing) {\n const response = await this.listChunk(\n options,\n continuationToken,\n limit - responseContents.length,\n containerClient,\n );\n continuationToken = response.continuationToken;\n responseContents = responseContents.concat(response.items);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists blobs in the Azure Blob Storage container with pagination.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to a paginated list of blob names.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? response.contents.map((blob) => {\n return {\n key: blob.name,\n lastModified: blob.properties.lastModified,\n size: blob.properties.contentLength!,\n eTag: blob.properties.etag,\n };\n })\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken?.length\n ? response.nextContinuationToken\n : null,\n count: items.length,\n };\n }\n\n /**\n * Lists all blobs in the Azure Blob Storage container.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to list of blob names.\n */\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination = response.pagination ?? undefined;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n}\n","import { CustomError } from '../../types/CustomError';\n\nconst errorMessages: { [key: string]: string } = {\n AccessDenied: 'Access denied',\n AccountProblem: 'There is a problem with your account',\n AllAccessDisabled: 'All access to this resource has been disabled',\n BucketAlreadyExists: 'The requested bucket name is not available',\n BucketNotEmpty: 'The bucket you tried to delete is not empty',\n EntityTooLarge: 'The entity you are trying to upload is too large',\n ExpiredToken: 'The provided token has expired',\n InternalError: 'An internal server error has occurred',\n InvalidAccessKeyId:\n 'The AWS access key ID you provided does not exist in our records',\n InvalidBucketName: 'The specified bucket name is not valid',\n InvalidObjectState:\n 'The operation is not valid for the current state of the object',\n InvalidToken: 'The provided token is invalid',\n NoSuchBucket: 'The specified bucket does not exist',\n NoSuchKey: 'The specified key does not exist',\n PreconditionFailed: 'The condition specified in the request is not met',\n RequestTimeout: 'The request timed out',\n ServiceUnavailable: 'The service is currently unavailable',\n SignatureDoesNotMatch:\n 'The request signature we calculated does not match the signature you provided',\n SlowDown: 'Please reduce your request rate',\n TemporaryRedirect: 'Temporary redirect',\n DEFAULT: 'An unknown error occurred',\n};\n\nexport class ErrorHandler {\n static handleError(\n errorCode: string,\n errorMessage?: string,\n errorObj?: Error,\n ): CustomError {\n const errorResponse: CustomError = {\n code: errorCode,\n message:\n errorMessage ||\n errorMessages[errorCode] ||\n errorMessages['DEFAULT'],\n timestamp: new Date().toISOString(),\n error: errorObj\n ? {\n name: errorObj.name,\n message: errorObj.message,\n stack: errorObj.stack || null,\n }\n : null,\n };\n\n // Return the structured object\n return errorResponse;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectResponse } from '../../../types';\nimport { BlobGetPropertiesResponse } from '@azure/storage-blob';\n\nexport function BlobPropertiesResponseToObjectResponse(\n blobProperties: BlobGetPropertiesResponse,\n): GetObjectResponse {\n return {\n lastModified: blobProperties.lastModified,\n contentLength: blobProperties.contentLength,\n contentType: blobProperties.contentType,\n eTag: blobProperties.etag,\n metadata: blobProperties.metadata,\n contentEncoding: blobProperties.contentEncoding,\n cacheControl: blobProperties.cacheControl,\n contentDisposition: blobProperties.contentDisposition,\n contentLanguage: blobProperties.contentLanguage,\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectAclCommandInput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n CreateUploadWriteStreamResponse,\n FileContent,\n GetObjectResponse,\n GetUploadUrlResponse,\n ListRequestOptions,\n ListResponse,\n ListResponseItem,\n UploadResponse,\n} from '../../../types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport {\n listResponseContentsToListResponseItems,\n s3ObjectToObjectResponse,\n} from './s3Helpers';\nimport stream from 'stream';\nimport { Upload } from '@aws-sdk/lib-storage';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client = new S3Client({\n region: process.env.AWS_REGION,\n });\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n }\n\n /**\n * Retrieves a chunk of objects from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the objects.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of objects to retrieve.\n * @return {Promise<ListObjectsV2CommandOutput>} - A promise that resolves to the response containing the list of objects and metadata.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n ): Promise<ListObjectsV2CommandOutput> {\n const command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken || options.pagination,\n Prefix: options.prefix,\n MaxKeys: limit,\n });\n\n return this.s3Client.send(command);\n }\n\n /**\n * Retrieves a list of contents from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the contents.\n * @return {Promise<{ contents: unknown[]; nextContinuationToken?: string }>} - A promise that resolves to an object containing the list of contents and an optional next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: unknown[]; nextContinuationToken?: string }> {\n let responseContents: any[] = [];\n let continuationToken: string | undefined = undefined;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n while (continueListing) {\n const listChunkLimit = limit - responseContents.length;\n const response = await this.listChunk(\n options,\n continuationToken,\n listChunkLimit,\n );\n continuationToken = response.NextContinuationToken;\n responseContents = responseContents.concat(response.Contents ?? []);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists objects in the S3 bucket with pagination.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to a paginated list of object keys.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? listResponseContentsToListResponseItems(response.contents)\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken ?? null,\n count: items.length,\n };\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to list of object keys.\n */\n\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination =\n response.pagination === null ? undefined : response.pagination;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getHeadObject(key: string): Promise<GetObjectResponse> {\n const command = new HeadObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getDownloadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Retrieves a signed URL for uploading an object to the S3 bucket.\n *\n * @param {string} key - The key of the object to be uploaded.\n * @param {number} [expiresInMinutes=60] - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n async getUploadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<GetUploadUrlResponse> {\n const expiresIn = expiresInMinutes * 60;\n\n const putObjectCommandParams: PutObjectAclCommandInput = {\n Bucket: process.env.UPLOAD_BUCKET_NAME,\n Key: key,\n ACL: 'private',\n };\n\n const command = new PutObjectCommand(putObjectCommandParams);\n\n const signedUrl = await getSignedUrl(this.s3Client, command, {\n expiresIn,\n });\n\n return {\n signedUrl,\n key: `https://${process.env.UPLOAD_BUCKET_NAME}.s3.${process.env.AWS_DEFAULT_REGION}.amazonaws.com/${key}`,\n };\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Creates a writable stream for uploading a file to the S3 bucket.\n *\n * @param {string} key - The key of the object to upload.\n * @return {CreateUploadWriteStreamResponse} An object containing the key of the uploaded object, the writable stream, and a promise that resolves when the upload is complete.\n */\n createUploadWriteStream(key: string): CreateUploadWriteStreamResponse {\n const streamPassThrough = new stream.PassThrough();\n const params = {\n Bucket: this.bucketName,\n Key: key,\n Body: streamPassThrough,\n };\n\n const upload = new Upload({\n client: this.s3Client,\n params,\n });\n\n return {\n key,\n stream: streamPassThrough,\n promise: upload.done(),\n };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectCommandOutput } from '@aws-sdk/client-s3';\nimport { GetObjectResponse, ListResponseItem } from '../../../types';\nimport { Readable } from 'stream';\n\n/**\n * Converts an array of S3 response contents into an array of ListResponseItem objects.\n *\n * @param {any[]} responseContents - The array of S3 response contents.\n * @return {ListResponseItem[]} The array of ListResponseItem objects.\n */\nexport function listResponseContentsToListResponseItems(\n responseContents: any[],\n): ListResponseItem[] {\n return responseContents.map((responseContent) => {\n return {\n key: responseContent.Key,\n lastModified: new Date(responseContent.LastModified),\n size: responseContent.Size,\n eTag: responseContent.ETag,\n };\n });\n}\n\n/**\n * Converts an S3 object response to a standardized object response.\n *\n * @param {GetObjectCommandOutput} s3Object - The S3 object response to convert.\n * @return {GetObjectResponse} The converted object response.\n */\nexport function s3ObjectToObjectResponse(\n s3Object: GetObjectCommandOutput,\n): GetObjectResponse {\n return {\n body: s3Object.Body as Readable,\n metadata: s3Object.Metadata,\n contentType: s3Object.ContentType,\n contentLength: s3Object.ContentLength as number,\n contentEncoding: s3Object.ContentEncoding,\n cacheControl: s3Object.CacheControl,\n contentDisposition: s3Object.ContentDisposition,\n contentLanguage: s3Object.ContentLanguage,\n eTag: s3Object.ETag,\n lastModified: s3Object.LastModified,\n };\n}\n","import { IObjectStorage } from '../interfaces';\nimport { S3StorageService, BlobStorageService } from './storage';\n\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n if (isBlobStorageService) {\n return new BlobStorageService(bucketName);\n } else {\n return new S3StorageService(bucketName);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n GetUploadUrlResponse,\n CreateUploadWriteStreamResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n /**\n * Retrieves a list of objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of objects.\n */\n static async list(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list(options));\n }\n\n /**\n * Retrieves a list of all objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of all objects.\n */\n static async listAll(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.listAll(options));\n }\n\n /**\n * Retrieves an object from the object storage service.\n *\n * @param {string} key - The key of the object to retrieve.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the retrieved object.\n */\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n /**\n * Retrieves a signed URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the signed URL.\n * @param {number} expiresInMinutes - The number of minutes until the signed URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated signed URL.\n */\n static async getDownloadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getDownloadUrl(key, expiresInMinutes));\n }\n\n /**\n * Retrieves an upload URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the upload URL.\n * @param {number} expiresInMinutes - The number of minutes until the upload URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated upload URL.\n */\n static async getUploadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<GetUploadUrlResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getUploadUrl(key, expiresInMinutes));\n }\n\n /**\n * Uploads a file to the object storage service.\n *\n * @param {string} key - The key of the object to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {Object} [metadata] - Optional metadata to associate with the object.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<UploadResponse>} A promise that resolves to the response of the upload operation.\n */\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n /**\n * Creates an upload write stream for the specified key in the object storage service.\n *\n * @param {string} key - The key of the object to create the upload write stream for.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.\n */\n static async createUploadWriteStream(\n key: string,\n bucketName?: string,\n ): Promise<CreateUploadWriteStreamResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.createUploadWriteStream(key));\n }\n\n /**\n * Deletes an object from the object storage service.\n *\n * @param {string} key - The key of the object to delete.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<boolean>} A promise that resolves to true if the object was successfully deleted, or false otherwise.\n */\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { Readable } from 'stream';
1
+ import stream, { Readable } from 'stream';
2
2
 
3
3
  type UploadResponse = {
4
4
  key: string;
@@ -45,6 +45,12 @@ type GetUploadUrlResponse = {
45
45
  signedUrl: string;
46
46
  };
47
47
 
48
+ type CreateUploadWriteStreamResponse = {
49
+ key: string;
50
+ stream: stream.PassThrough;
51
+ promise: Promise<unknown>;
52
+ };
53
+
48
54
  interface IObjectStorage {
49
55
  list(options: ListRequestOptions): Promise<ListResponse>;
50
56
  listAll(options: ListRequestOptions): Promise<ListResponse>;
@@ -55,6 +61,7 @@ interface IObjectStorage {
55
61
  upload(key: string, body: FileContent, metadata?: {
56
62
  [key: string]: string;
57
63
  }): Promise<UploadResponse>;
64
+ createUploadWriteStream(key: string): CreateUploadWriteStreamResponse;
58
65
  delete(key: string): Promise<boolean>;
59
66
  }
60
67
 
@@ -116,6 +123,14 @@ declare class ObjectStorageService {
116
123
  static upload(key: string, body: FileContent, metadata?: {
117
124
  [key: string]: string;
118
125
  }, bucketName?: string): Promise<UploadResponse>;
126
+ /**
127
+ * Creates an upload write stream for the specified key in the object storage service.
128
+ *
129
+ * @param {string} key - The key of the object to create the upload write stream for.
130
+ * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.
131
+ * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.
132
+ */
133
+ static createUploadWriteStream(key: string, bucketName?: string): Promise<CreateUploadWriteStreamResponse>;
119
134
  /**
120
135
  * Deletes an object from the object storage service.
121
136
  *
@@ -1,6 +1,8 @@
1
1
  import { BlobServiceClient, BlobSASPermissions } from '@azure/storage-blob';
2
2
  import { S3Client, ListObjectsV2Command, HeadObjectCommand, GetObjectCommand, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
3
3
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
4
+ import stream from 'stream';
5
+ import { Upload } from '@aws-sdk/lib-storage';
4
6
 
5
7
  var __defProp = Object.defineProperty;
6
8
  var __defProps = Object.defineProperties;
@@ -91,6 +93,10 @@ var BlobStorageService = class {
91
93
  process.env.AZURE_STORAGE_CONNECTION_STRING
92
94
  );
93
95
  }
96
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
97
+ createUploadWriteStream(key) {
98
+ throw new Error("Method not implemented.");
99
+ }
94
100
  getUploadUrl(key, expiresInMinutes) {
95
101
  throw new Error("Method not implemented.");
96
102
  }
@@ -395,8 +401,6 @@ function s3ObjectToObjectResponse(s3Object) {
395
401
  lastModified: s3Object.LastModified
396
402
  };
397
403
  }
398
-
399
- // src/services/storage/s3/s3Storage.service.ts
400
404
  var S3StorageService = class {
401
405
  constructor(bucketName) {
402
406
  this.s3Client = new S3Client({
@@ -566,6 +570,29 @@ var S3StorageService = class {
566
570
  await this.s3Client.send(command);
567
571
  return { key };
568
572
  }
573
+ /**
574
+ * Creates a writable stream for uploading a file to the S3 bucket.
575
+ *
576
+ * @param {string} key - The key of the object to upload.
577
+ * @return {CreateUploadWriteStreamResponse} An object containing the key of the uploaded object, the writable stream, and a promise that resolves when the upload is complete.
578
+ */
579
+ createUploadWriteStream(key) {
580
+ const streamPassThrough = new stream.PassThrough();
581
+ const params = {
582
+ Bucket: this.bucketName,
583
+ Key: key,
584
+ Body: streamPassThrough
585
+ };
586
+ const upload = new Upload({
587
+ client: this.s3Client,
588
+ params
589
+ });
590
+ return {
591
+ key,
592
+ stream: streamPassThrough,
593
+ promise: upload.done()
594
+ };
595
+ }
569
596
  /**
570
597
  * Deletes an object from the S3 bucket.
571
598
  * @param key - The key of the object to delete.
@@ -680,6 +707,18 @@ var ObjectStorageService = class _ObjectStorageService {
680
707
  bucketName
681
708
  ).then((instance) => instance.upload(key, body, metadata));
682
709
  }
710
+ /**
711
+ * Creates an upload write stream for the specified key in the object storage service.
712
+ *
713
+ * @param {string} key - The key of the object to create the upload write stream for.
714
+ * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.
715
+ * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.
716
+ */
717
+ static async createUploadWriteStream(key, bucketName) {
718
+ return _ObjectStorageService.getObjectStorageServiceInstance(
719
+ bucketName
720
+ ).then((instance) => instance.createUploadWriteStream(key));
721
+ }
683
722
  /**
684
723
  * Deletes an object from the object storage service.
685
724
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts","../../src/shared/utils/errorHandler.ts","../../src/services/storage/blob/blobHelpers.ts","../../src/services/storage/s3/s3Storage.service.ts","../../src/services/storage/s3/s3Helpers.ts","../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n ListResponseItem,\n GetUploadUrlResponse,\n} from '../../../types';\nimport {\n BlobServiceClient,\n BlobSASPermissions,\n BlobItem,\n ContainerClient,\n} from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nimport { ErrorHandler } from '../../../shared/utils/errorHandler';\nimport { BlobPropertiesResponseToObjectResponse } from './blobHelpers';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n getUploadUrl(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n key: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n expiresInMinutes: number,\n ): Promise<GetUploadUrlResponse> {\n throw new Error('Method not implemented.');\n }\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n getHeadObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .getProperties()\n .then((blobProperties) => {\n return resolve(\n BlobPropertiesResponseToObjectResponse(\n blobProperties,\n ),\n );\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves an object from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to retrieve.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the object data, including the body, metadata, content type, and content length, or rejects with an error if there was an issue.\n */\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves a signed URL for the blob with the specified name that expires after a certain period.\n *\n * @param {string} blobName - The name of the blob to generate the signed URL for.\n * @param {number} expiresInMinutes - The duration in minutes until the signed URL expires.\n * @return {Promise<string>} A Promise that resolves with the signed URL.\n */\n getDownloadUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Uploads a file to the blob storage service.\n *\n * @param {string} blobName - The name of the blob to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {{ [key: string]: string } | undefined} [metadata] - Optional metadata to associate with the blob.\n * @return {Promise<UploadResponse>} A promise that resolves to the response object containing the key of the uploaded blob, or rejects with an error if there was an issue.\n */\n upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n blockBlobClient\n .uploadStream(\n body as Readable,\n undefined,\n undefined,\n metadata,\n )\n .then(() => resolve({ key: blobName }))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Deletes a blob from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to be deleted.\n * @return {Promise<boolean>} A promise that resolves to true if the blob is successfully deleted, or rejects with an error if there was an issue.\n */\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .delete()\n .then(() => resolve(true))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Lists a chunk of blobs from the specified container client based on the provided options and continuation token.\n *\n * @param {ListRequestOptions} options - The options for listing the blobs.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of blobs to list in a single page.\n * @param {ContainerClient} containerClient - The container client to list the blobs from.\n * @return {Promise<{ items: BlobItem[]; continuationToken?: string }>} - A promise that resolves to an object containing the list of blob items and an optional continuation token.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n containerClient: ContainerClient,\n ): Promise<{ items: BlobItem[]; continuationToken?: string }> {\n const iterator = containerClient\n .listBlobsFlat({\n prefix: options.prefix,\n })\n .byPage({\n maxPageSize: limit,\n continuationToken: continuationToken,\n });\n\n const items: BlobItem[] = [];\n const response = (await iterator.next()).value;\n items.push(...response.segment.blobItems);\n return {\n items,\n continuationToken: response.continuationToken,\n };\n }\n\n /**\n * Retrieves a list of blob contents based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the blob contents.\n * @return {Promise<{ contents: BlobItem[]; nextContinuationToken?: string }>} A promise that resolves to the list of blob contents and the next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: BlobItem[]; nextContinuationToken?: string }> {\n let responseContents: BlobItem[] = [];\n let continuationToken: string | undefined = options.pagination;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n while (continueListing) {\n const response = await this.listChunk(\n options,\n continuationToken,\n limit - responseContents.length,\n containerClient,\n );\n continuationToken = response.continuationToken;\n responseContents = responseContents.concat(response.items);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists blobs in the Azure Blob Storage container with pagination.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to a paginated list of blob names.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? response.contents.map((blob) => {\n return {\n key: blob.name,\n lastModified: blob.properties.lastModified,\n size: blob.properties.contentLength!,\n eTag: blob.properties.etag,\n };\n })\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken?.length\n ? response.nextContinuationToken\n : null,\n count: items.length,\n };\n }\n\n /**\n * Lists all blobs in the Azure Blob Storage container.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to list of blob names.\n */\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination = response.pagination ?? undefined;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n}\n","import { CustomError } from '../../types/CustomError';\n\nconst errorMessages: { [key: string]: string } = {\n AccessDenied: 'Access denied',\n AccountProblem: 'There is a problem with your account',\n AllAccessDisabled: 'All access to this resource has been disabled',\n BucketAlreadyExists: 'The requested bucket name is not available',\n BucketNotEmpty: 'The bucket you tried to delete is not empty',\n EntityTooLarge: 'The entity you are trying to upload is too large',\n ExpiredToken: 'The provided token has expired',\n InternalError: 'An internal server error has occurred',\n InvalidAccessKeyId:\n 'The AWS access key ID you provided does not exist in our records',\n InvalidBucketName: 'The specified bucket name is not valid',\n InvalidObjectState:\n 'The operation is not valid for the current state of the object',\n InvalidToken: 'The provided token is invalid',\n NoSuchBucket: 'The specified bucket does not exist',\n NoSuchKey: 'The specified key does not exist',\n PreconditionFailed: 'The condition specified in the request is not met',\n RequestTimeout: 'The request timed out',\n ServiceUnavailable: 'The service is currently unavailable',\n SignatureDoesNotMatch:\n 'The request signature we calculated does not match the signature you provided',\n SlowDown: 'Please reduce your request rate',\n TemporaryRedirect: 'Temporary redirect',\n DEFAULT: 'An unknown error occurred',\n};\n\nexport class ErrorHandler {\n static handleError(\n errorCode: string,\n errorMessage?: string,\n errorObj?: Error,\n ): CustomError {\n const errorResponse: CustomError = {\n code: errorCode,\n message:\n errorMessage ||\n errorMessages[errorCode] ||\n errorMessages['DEFAULT'],\n timestamp: new Date().toISOString(),\n error: errorObj\n ? {\n name: errorObj.name,\n message: errorObj.message,\n stack: errorObj.stack || null,\n }\n : null,\n };\n\n // Return the structured object\n return errorResponse;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectResponse } from '../../../types';\nimport { BlobGetPropertiesResponse } from '@azure/storage-blob';\n\nexport function BlobPropertiesResponseToObjectResponse(\n blobProperties: BlobGetPropertiesResponse,\n): GetObjectResponse {\n return {\n lastModified: blobProperties.lastModified,\n contentLength: blobProperties.contentLength,\n contentType: blobProperties.contentType,\n eTag: blobProperties.etag,\n metadata: blobProperties.metadata,\n contentEncoding: blobProperties.contentEncoding,\n cacheControl: blobProperties.cacheControl,\n contentDisposition: blobProperties.contentDisposition,\n contentLanguage: blobProperties.contentLanguage,\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectAclCommandInput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n GetObjectResponse,\n GetUploadUrlResponse,\n ListRequestOptions,\n ListResponse,\n ListResponseItem,\n UploadResponse,\n} from '../../../types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport {\n listResponseContentsToListResponseItems,\n s3ObjectToObjectResponse,\n} from './s3Helpers';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client = new S3Client({\n region: process.env.AWS_REGION,\n });\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n }\n\n /**\n * Retrieves a chunk of objects from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the objects.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of objects to retrieve.\n * @return {Promise<ListObjectsV2CommandOutput>} - A promise that resolves to the response containing the list of objects and metadata.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n ): Promise<ListObjectsV2CommandOutput> {\n const command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken || options.pagination,\n Prefix: options.prefix,\n MaxKeys: limit,\n });\n\n return this.s3Client.send(command);\n }\n\n /**\n * Retrieves a list of contents from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the contents.\n * @return {Promise<{ contents: unknown[]; nextContinuationToken?: string }>} - A promise that resolves to an object containing the list of contents and an optional next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: unknown[]; nextContinuationToken?: string }> {\n let responseContents: any[] = [];\n let continuationToken: string | undefined = undefined;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n while (continueListing) {\n const listChunkLimit = limit - responseContents.length;\n const response = await this.listChunk(\n options,\n continuationToken,\n listChunkLimit,\n );\n continuationToken = response.NextContinuationToken;\n responseContents = responseContents.concat(response.Contents ?? []);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists objects in the S3 bucket with pagination.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to a paginated list of object keys.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? listResponseContentsToListResponseItems(response.contents)\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken ?? null,\n count: items.length,\n };\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to list of object keys.\n */\n\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination =\n response.pagination === null ? undefined : response.pagination;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getHeadObject(key: string): Promise<GetObjectResponse> {\n const command = new HeadObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getDownloadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Retrieves a signed URL for uploading an object to the S3 bucket.\n *\n * @param {string} key - The key of the object to be uploaded.\n * @param {number} [expiresInMinutes=60] - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n async getUploadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<GetUploadUrlResponse> {\n const expiresIn = expiresInMinutes * 60;\n\n const putObjectCommandParams: PutObjectAclCommandInput = {\n Bucket: process.env.UPLOAD_BUCKET_NAME,\n Key: key,\n ACL: 'private',\n };\n\n const command = new PutObjectCommand(putObjectCommandParams);\n\n const signedUrl = await getSignedUrl(this.s3Client, command, {\n expiresIn,\n });\n\n return {\n signedUrl,\n key: `https://${process.env.UPLOAD_BUCKET_NAME}.s3.${process.env.AWS_DEFAULT_REGION}.amazonaws.com/${key}`,\n };\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectCommandOutput } from '@aws-sdk/client-s3';\nimport { GetObjectResponse, ListResponseItem } from '../../../types';\nimport { Readable } from 'stream';\n\n/**\n * Converts an array of S3 response contents into an array of ListResponseItem objects.\n *\n * @param {any[]} responseContents - The array of S3 response contents.\n * @return {ListResponseItem[]} The array of ListResponseItem objects.\n */\nexport function listResponseContentsToListResponseItems(\n responseContents: any[],\n): ListResponseItem[] {\n return responseContents.map((responseContent) => {\n return {\n key: responseContent.Key,\n lastModified: new Date(responseContent.LastModified),\n size: responseContent.Size,\n eTag: responseContent.ETag,\n };\n });\n}\n\n/**\n * Converts an S3 object response to a standardized object response.\n *\n * @param {GetObjectCommandOutput} s3Object - The S3 object response to convert.\n * @return {GetObjectResponse} The converted object response.\n */\nexport function s3ObjectToObjectResponse(\n s3Object: GetObjectCommandOutput,\n): GetObjectResponse {\n return {\n body: s3Object.Body as Readable,\n metadata: s3Object.Metadata,\n contentType: s3Object.ContentType,\n contentLength: s3Object.ContentLength as number,\n contentEncoding: s3Object.ContentEncoding,\n cacheControl: s3Object.CacheControl,\n contentDisposition: s3Object.ContentDisposition,\n contentLanguage: s3Object.ContentLanguage,\n eTag: s3Object.ETag,\n lastModified: s3Object.LastModified,\n };\n}\n","import { IObjectStorage } from '../interfaces';\nimport { S3StorageService, BlobStorageService } from './storage';\n\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n if (isBlobStorageService) {\n return new BlobStorageService(bucketName);\n } else {\n return new S3StorageService(bucketName);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n GetUploadUrlResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n /**\n * Retrieves a list of objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of objects.\n */\n static async list(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list(options));\n }\n\n /**\n * Retrieves a list of all objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of all objects.\n */\n static async listAll(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.listAll(options));\n }\n\n /**\n * Retrieves an object from the object storage service.\n *\n * @param {string} key - The key of the object to retrieve.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the retrieved object.\n */\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n /**\n * Retrieves a signed URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the signed URL.\n * @param {number} expiresInMinutes - The number of minutes until the signed URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated signed URL.\n */\n static async getDownloadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getDownloadUrl(key, expiresInMinutes));\n }\n\n /**\n * Retrieves an upload URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the upload URL.\n * @param {number} expiresInMinutes - The number of minutes until the upload URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated upload URL.\n */\n static async getUploadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<GetUploadUrlResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getUploadUrl(key, expiresInMinutes));\n }\n\n /**\n * Uploads a file to the object storage service.\n *\n * @param {string} key - The key of the object to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {Object} [metadata] - Optional metadata to associate with the object.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<UploadResponse>} A promise that resolves to the response of the upload operation.\n */\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n /**\n * Deletes an object from the object storage service.\n *\n * @param {string} key - The key of the object to delete.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<boolean>} A promise that resolves to true if the object was successfully deleted, or false otherwise.\n */\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/services/storage/blob/blobStorage.service.ts","../../src/shared/utils/errorHandler.ts","../../src/services/storage/blob/blobHelpers.ts","../../src/services/storage/s3/s3Storage.service.ts","../../src/services/storage/s3/s3Helpers.ts","../../src/services/objectStorageFactory.service.ts","../../src/services/objectStorage.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { IObjectStorage } from '../../../interfaces';\nimport {\n FileContent,\n ListResponse,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n ListResponseItem,\n GetUploadUrlResponse,\n CreateUploadWriteStreamResponse,\n} from '../../../types';\nimport {\n BlobServiceClient,\n BlobSASPermissions,\n BlobItem,\n ContainerClient,\n} from '@azure/storage-blob';\n\nimport { Readable } from 'stream';\nimport { ErrorHandler } from '../../../shared/utils/errorHandler';\nimport { BlobPropertiesResponseToObjectResponse } from './blobHelpers';\nexport class BlobStorageService implements IObjectStorage {\n private blobServiceClient: BlobServiceClient;\n private containerName: string;\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n constructor(containerName: string) {\n this.containerName = containerName;\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n process.env.AZURE_STORAGE_CONNECTION_STRING!,\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n createUploadWriteStream(key: string): CreateUploadWriteStreamResponse {\n throw new Error('Method not implemented.');\n }\n getUploadUrl(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n key: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\n expiresInMinutes: number,\n ): Promise<GetUploadUrlResponse> {\n throw new Error('Method not implemented.');\n }\n\n /**\n * Retrieves the properties of a blob from the container by its name.\n *\n * @param {string} blobName - The name of the blob.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the blob properties.\n */\n getHeadObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .getProperties()\n .then((blobProperties) => {\n return resolve(\n BlobPropertiesResponseToObjectResponse(\n blobProperties,\n ),\n );\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves an object from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to retrieve.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the object data, including the body, metadata, content type, and content length, or rejects with an error if there was an issue.\n */\n getObject(blobName: string): Promise<GetObjectResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .download(0)\n .then((downloadBlockBlobResponse) => {\n return resolve({\n body: downloadBlockBlobResponse.readableStreamBody as Readable,\n metadata: {},\n contentType: '',\n contentLength: 0,\n });\n })\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Retrieves a signed URL for the blob with the specified name that expires after a certain period.\n *\n * @param {string} blobName - The name of the blob to generate the signed URL for.\n * @param {number} expiresInMinutes - The duration in minutes until the signed URL expires.\n * @return {Promise<string>} A Promise that resolves with the signed URL.\n */\n getDownloadUrl(\n blobName: string,\n expiresInMinutes: number,\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n const startDate = new Date();\n const expiryDate = new Date(startDate);\n expiryDate.setMinutes(\n startDate.getMinutes() + expiresInMinutes,\n );\n\n blockBlobClient\n .generateSasUrl({\n permissions: BlobSASPermissions.parse('r'),\n startsOn: startDate,\n expiresOn: expiryDate,\n })\n .then((sasUrl) => resolve(sasUrl))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Uploads a file to the blob storage service.\n *\n * @param {string} blobName - The name of the blob to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {{ [key: string]: string } | undefined} [metadata] - Optional metadata to associate with the blob.\n * @return {Promise<UploadResponse>} A promise that resolves to the response object containing the key of the uploaded blob, or rejects with an error if there was an issue.\n */\n upload(\n blobName: string,\n body: FileContent,\n metadata?: { [key: string]: string } | undefined,\n ): Promise<UploadResponse> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n\n blockBlobClient\n .uploadStream(\n body as Readable,\n undefined,\n undefined,\n metadata,\n )\n .then(() => resolve({ key: blobName }))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Deletes a blob from the blob storage service.\n *\n * @param {string} blobName - The name of the blob to be deleted.\n * @return {Promise<boolean>} A promise that resolves to true if the blob is successfully deleted, or rejects with an error if there was an issue.\n */\n delete(blobName: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const containerClient =\n this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n const blockBlobClient =\n containerClient.getBlockBlobClient(blobName);\n blockBlobClient\n .delete()\n .then(() => resolve(true))\n .catch((error) =>\n reject(\n ErrorHandler.handleError(\n 'DEFAULT',\n '',\n error as Error,\n ),\n ),\n );\n } catch (error) {\n return reject(\n ErrorHandler.handleError('DEFAULT', '', error as Error),\n );\n }\n });\n }\n\n /**\n * Lists a chunk of blobs from the specified container client based on the provided options and continuation token.\n *\n * @param {ListRequestOptions} options - The options for listing the blobs.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of blobs to list in a single page.\n * @param {ContainerClient} containerClient - The container client to list the blobs from.\n * @return {Promise<{ items: BlobItem[]; continuationToken?: string }>} - A promise that resolves to an object containing the list of blob items and an optional continuation token.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n containerClient: ContainerClient,\n ): Promise<{ items: BlobItem[]; continuationToken?: string }> {\n const iterator = containerClient\n .listBlobsFlat({\n prefix: options.prefix,\n })\n .byPage({\n maxPageSize: limit,\n continuationToken: continuationToken,\n });\n\n const items: BlobItem[] = [];\n const response = (await iterator.next()).value;\n items.push(...response.segment.blobItems);\n return {\n items,\n continuationToken: response.continuationToken,\n };\n }\n\n /**\n * Retrieves a list of blob contents based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the blob contents.\n * @return {Promise<{ contents: BlobItem[]; nextContinuationToken?: string }>} A promise that resolves to the list of blob contents and the next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: BlobItem[]; nextContinuationToken?: string }> {\n let responseContents: BlobItem[] = [];\n let continuationToken: string | undefined = options.pagination;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n const containerClient = this.blobServiceClient.getContainerClient(\n this.containerName,\n );\n while (continueListing) {\n const response = await this.listChunk(\n options,\n continuationToken,\n limit - responseContents.length,\n containerClient,\n );\n continuationToken = response.continuationToken;\n responseContents = responseContents.concat(response.items);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists blobs in the Azure Blob Storage container with pagination.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to a paginated list of blob names.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? response.contents.map((blob) => {\n return {\n key: blob.name,\n lastModified: blob.properties.lastModified,\n size: blob.properties.contentLength!,\n eTag: blob.properties.etag,\n };\n })\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken?.length\n ? response.nextContinuationToken\n : null,\n count: items.length,\n };\n }\n\n /**\n * Lists all blobs in the Azure Blob Storage container.\n * @param options - The options for listing blobs.\n * @returns A promise that resolves to list of blob names.\n */\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination = response.pagination ?? undefined;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n}\n","import { CustomError } from '../../types/CustomError';\n\nconst errorMessages: { [key: string]: string } = {\n AccessDenied: 'Access denied',\n AccountProblem: 'There is a problem with your account',\n AllAccessDisabled: 'All access to this resource has been disabled',\n BucketAlreadyExists: 'The requested bucket name is not available',\n BucketNotEmpty: 'The bucket you tried to delete is not empty',\n EntityTooLarge: 'The entity you are trying to upload is too large',\n ExpiredToken: 'The provided token has expired',\n InternalError: 'An internal server error has occurred',\n InvalidAccessKeyId:\n 'The AWS access key ID you provided does not exist in our records',\n InvalidBucketName: 'The specified bucket name is not valid',\n InvalidObjectState:\n 'The operation is not valid for the current state of the object',\n InvalidToken: 'The provided token is invalid',\n NoSuchBucket: 'The specified bucket does not exist',\n NoSuchKey: 'The specified key does not exist',\n PreconditionFailed: 'The condition specified in the request is not met',\n RequestTimeout: 'The request timed out',\n ServiceUnavailable: 'The service is currently unavailable',\n SignatureDoesNotMatch:\n 'The request signature we calculated does not match the signature you provided',\n SlowDown: 'Please reduce your request rate',\n TemporaryRedirect: 'Temporary redirect',\n DEFAULT: 'An unknown error occurred',\n};\n\nexport class ErrorHandler {\n static handleError(\n errorCode: string,\n errorMessage?: string,\n errorObj?: Error,\n ): CustomError {\n const errorResponse: CustomError = {\n code: errorCode,\n message:\n errorMessage ||\n errorMessages[errorCode] ||\n errorMessages['DEFAULT'],\n timestamp: new Date().toISOString(),\n error: errorObj\n ? {\n name: errorObj.name,\n message: errorObj.message,\n stack: errorObj.stack || null,\n }\n : null,\n };\n\n // Return the structured object\n return errorResponse;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectResponse } from '../../../types';\nimport { BlobGetPropertiesResponse } from '@azure/storage-blob';\n\nexport function BlobPropertiesResponseToObjectResponse(\n blobProperties: BlobGetPropertiesResponse,\n): GetObjectResponse {\n return {\n lastModified: blobProperties.lastModified,\n contentLength: blobProperties.contentLength,\n contentType: blobProperties.contentType,\n eTag: blobProperties.etag,\n metadata: blobProperties.metadata,\n contentEncoding: blobProperties.contentEncoding,\n cacheControl: blobProperties.cacheControl,\n contentDisposition: blobProperties.contentDisposition,\n contentLanguage: blobProperties.contentLanguage,\n };\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n PutObjectAclCommandInput,\n PutObjectCommand,\n S3Client,\n} from '@aws-sdk/client-s3';\nimport { IObjectStorage } from '../../../interfaces';\nimport {\n CreateUploadWriteStreamResponse,\n FileContent,\n GetObjectResponse,\n GetUploadUrlResponse,\n ListRequestOptions,\n ListResponse,\n ListResponseItem,\n UploadResponse,\n} from '../../../types';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport {\n listResponseContentsToListResponseItems,\n s3ObjectToObjectResponse,\n} from './s3Helpers';\nimport stream from 'stream';\nimport { Upload } from '@aws-sdk/lib-storage';\n\nexport class S3StorageService implements IObjectStorage {\n private s3Client: S3Client = new S3Client({\n region: process.env.AWS_REGION,\n });\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.bucketName = bucketName;\n }\n\n /**\n * Retrieves a chunk of objects from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the objects.\n * @param {string | undefined} continuationToken - The continuation token for pagination.\n * @param {number} limit - The maximum number of objects to retrieve.\n * @return {Promise<ListObjectsV2CommandOutput>} - A promise that resolves to the response containing the list of objects and metadata.\n */\n private async listChunk(\n options: ListRequestOptions,\n continuationToken: string | undefined,\n limit: number,\n ): Promise<ListObjectsV2CommandOutput> {\n const command = new ListObjectsV2Command({\n Bucket: this.bucketName,\n ContinuationToken: continuationToken || options.pagination,\n Prefix: options.prefix,\n MaxKeys: limit,\n });\n\n return this.s3Client.send(command);\n }\n\n /**\n * Retrieves a list of contents from the S3 bucket based on the provided options.\n *\n * @param {ListRequestOptions} options - The options for listing the contents.\n * @return {Promise<{ contents: unknown[]; nextContinuationToken?: string }>} - A promise that resolves to an object containing the list of contents and an optional next continuation token.\n */\n private async listContents(\n options: ListRequestOptions,\n ): Promise<{ contents: unknown[]; nextContinuationToken?: string }> {\n let responseContents: any[] = [];\n let continuationToken: string | undefined = undefined;\n const limit = options.limit ?? 1000;\n let continueListing = true;\n while (continueListing) {\n const listChunkLimit = limit - responseContents.length;\n const response = await this.listChunk(\n options,\n continuationToken,\n listChunkLimit,\n );\n continuationToken = response.NextContinuationToken;\n responseContents = responseContents.concat(response.Contents ?? []);\n\n if (responseContents.length >= limit || !continuationToken) {\n continueListing = false;\n }\n }\n\n return {\n contents: responseContents,\n nextContinuationToken: continuationToken,\n };\n }\n\n /**\n * Lists objects in the S3 bucket with pagination.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to a paginated list of object keys.\n */\n async list(options: ListRequestOptions): Promise<ListResponse> {\n let items: ListResponseItem[] = [];\n const response = await this.listContents(options);\n\n items = response.contents.length\n ? listResponseContentsToListResponseItems(response.contents)\n : [];\n\n return {\n items,\n pagination: response.nextContinuationToken ?? null,\n count: items.length,\n };\n }\n\n /**\n * Lists all objects in the S3 bucket.\n * @param options - The options for listing objects.\n * @returns A promise that resolves to list of object keys.\n */\n\n async listAll(options: ListRequestOptions): Promise<ListResponse> {\n let allItems: ListResponseItem[] = [];\n let pagination: string | undefined = undefined;\n\n do {\n const response: ListResponse = await this.list({\n ...options,\n pagination,\n });\n\n if (response.items?.length)\n allItems = [...allItems, ...response.items];\n\n pagination =\n response.pagination === null ? undefined : response.pagination;\n } while (pagination);\n\n return { items: allItems, count: allItems.length };\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getHeadObject(key: string): Promise<GetObjectResponse> {\n const command = new HeadObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Retrieves an object from the S3 bucket.\n * @param key - The key of the object to retrieve.\n * @returns A promise that resolves to the content of the file.\n */\n async getObject(key: string): Promise<GetObjectResponse> {\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n const response = await this.s3Client.send(command);\n return s3ObjectToObjectResponse(response);\n }\n\n /**\n * Generates a signed URL for accessing an object in the S3 bucket.\n * @param key - The key of the object.\n * @param expiresInMinutes - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n getDownloadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<string> {\n const expiresIn = expiresInMinutes * 60;\n const command = new GetObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n return getSignedUrl(this.s3Client, command, { expiresIn });\n }\n\n /**\n * Retrieves a signed URL for uploading an object to the S3 bucket.\n *\n * @param {string} key - The key of the object to be uploaded.\n * @param {number} [expiresInMinutes=60] - The number of minutes the signed URL should be valid for. Defaults to 60 minutes.\n * @returns A promise that resolves to the signed URL.\n */\n async getUploadUrl(\n key: string,\n expiresInMinutes: number = 60,\n ): Promise<GetUploadUrlResponse> {\n const expiresIn = expiresInMinutes * 60;\n\n const putObjectCommandParams: PutObjectAclCommandInput = {\n Bucket: process.env.UPLOAD_BUCKET_NAME,\n Key: key,\n ACL: 'private',\n };\n\n const command = new PutObjectCommand(putObjectCommandParams);\n\n const signedUrl = await getSignedUrl(this.s3Client, command, {\n expiresIn,\n });\n\n return {\n signedUrl,\n key: `https://${process.env.UPLOAD_BUCKET_NAME}.s3.${process.env.AWS_DEFAULT_REGION}.amazonaws.com/${key}`,\n };\n }\n\n /**\n * Uploads an object to the S3 bucket.\n * @param key - The key of the object to upload.\n * @param body - The content of the object to upload.\n * @param metadata - Optional metadata to associate with the object.\n * @returns A promise that resolves to the response containing the key of the uploaded object.\n */\n async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n ): Promise<UploadResponse> {\n const command = new PutObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n Body: body,\n Metadata: metadata,\n });\n await this.s3Client.send(command);\n return { key };\n }\n\n /**\n * Creates a writable stream for uploading a file to the S3 bucket.\n *\n * @param {string} key - The key of the object to upload.\n * @return {CreateUploadWriteStreamResponse} An object containing the key of the uploaded object, the writable stream, and a promise that resolves when the upload is complete.\n */\n createUploadWriteStream(key: string): CreateUploadWriteStreamResponse {\n const streamPassThrough = new stream.PassThrough();\n const params = {\n Bucket: this.bucketName,\n Key: key,\n Body: streamPassThrough,\n };\n\n const upload = new Upload({\n client: this.s3Client,\n params,\n });\n\n return {\n key,\n stream: streamPassThrough,\n promise: upload.done(),\n };\n }\n\n /**\n * Deletes an object from the S3 bucket.\n * @param key - The key of the object to delete.\n * @returns A promise that resolves to true if the object was deleted successfully.\n */\n async delete(key: string): Promise<boolean> {\n const command = new DeleteObjectCommand({\n Bucket: this.bucketName,\n Key: key,\n });\n await this.s3Client.send(command);\n return true;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { GetObjectCommandOutput } from '@aws-sdk/client-s3';\nimport { GetObjectResponse, ListResponseItem } from '../../../types';\nimport { Readable } from 'stream';\n\n/**\n * Converts an array of S3 response contents into an array of ListResponseItem objects.\n *\n * @param {any[]} responseContents - The array of S3 response contents.\n * @return {ListResponseItem[]} The array of ListResponseItem objects.\n */\nexport function listResponseContentsToListResponseItems(\n responseContents: any[],\n): ListResponseItem[] {\n return responseContents.map((responseContent) => {\n return {\n key: responseContent.Key,\n lastModified: new Date(responseContent.LastModified),\n size: responseContent.Size,\n eTag: responseContent.ETag,\n };\n });\n}\n\n/**\n * Converts an S3 object response to a standardized object response.\n *\n * @param {GetObjectCommandOutput} s3Object - The S3 object response to convert.\n * @return {GetObjectResponse} The converted object response.\n */\nexport function s3ObjectToObjectResponse(\n s3Object: GetObjectCommandOutput,\n): GetObjectResponse {\n return {\n body: s3Object.Body as Readable,\n metadata: s3Object.Metadata,\n contentType: s3Object.ContentType,\n contentLength: s3Object.ContentLength as number,\n contentEncoding: s3Object.ContentEncoding,\n cacheControl: s3Object.CacheControl,\n contentDisposition: s3Object.ContentDisposition,\n contentLanguage: s3Object.ContentLanguage,\n eTag: s3Object.ETag,\n lastModified: s3Object.LastModified,\n };\n}\n","import { IObjectStorage } from '../interfaces';\nimport { S3StorageService, BlobStorageService } from './storage';\n\nexport class ObjectStorageFactory {\n static async instance(bucketName: string): Promise<IObjectStorage> {\n const isBlobStorageService =\n process.env.OBJECT_STORAGE_SERVICE?.toLowerCase() ===\n 'azure_blob_storage';\n\n if (isBlobStorageService) {\n return new BlobStorageService(bucketName);\n } else {\n return new S3StorageService(bucketName);\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IObjectStorage } from '../interfaces';\nimport {\n ListResponse,\n FileContent,\n UploadResponse,\n GetObjectResponse,\n ListRequestOptions,\n GetUploadUrlResponse,\n CreateUploadWriteStreamResponse,\n} from '../types';\nimport { ObjectStorageFactory } from '../services/objectStorageFactory.service';\n\nexport default class ObjectStorageService {\n static bucketName: string;\n\n constructor(bucketName: string) {\n ObjectStorageService.bucketName = bucketName;\n }\n\n static async getObjectStorageServiceInstance(\n bucketName: string = ObjectStorageService.bucketName,\n ): Promise<IObjectStorage> {\n if (!bucketName)\n throw new Error('Bucket name not provided or not valid value');\n return ObjectStorageFactory.instance(bucketName);\n }\n\n /**\n * Retrieves a list of objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of objects.\n */\n static async list(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.list(options));\n }\n\n /**\n * Retrieves a list of all objects from the object storage service.\n *\n * @param {ListRequestOptions} options - The options to apply to the list operation.\n * @param {string} [bucketName] - The name of the bucket to list objects from. If not provided, the default bucket name will be used.\n * @return {Promise<ListResponse>} A promise that resolves to the list of all objects.\n */\n static async listAll(\n options: ListRequestOptions,\n bucketName?: string,\n ): Promise<ListResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.listAll(options));\n }\n\n /**\n * Retrieves an object from the object storage service.\n *\n * @param {string} key - The key of the object to retrieve.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<GetObjectResponse>} A promise that resolves to the retrieved object.\n */\n static async getObject(\n key: string,\n bucketName?: string,\n ): Promise<GetObjectResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getObject(key));\n }\n\n /**\n * Retrieves a signed URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the signed URL.\n * @param {number} expiresInMinutes - The number of minutes until the signed URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated signed URL.\n */\n static async getDownloadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<string> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getDownloadUrl(key, expiresInMinutes));\n }\n\n /**\n * Retrieves an upload URL for the specified object in the object storage service.\n *\n * @param {string} key - The key of the object for which to generate the upload URL.\n * @param {number} expiresInMinutes - The number of minutes until the upload URL expires.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<string>} A promise that resolves to the generated upload URL.\n */\n static async getUploadUrl(\n key: string,\n expiresInMinutes: number,\n bucketName?: string,\n ): Promise<GetUploadUrlResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.getUploadUrl(key, expiresInMinutes));\n }\n\n /**\n * Uploads a file to the object storage service.\n *\n * @param {string} key - The key of the object to upload.\n * @param {FileContent} body - The content of the file to upload.\n * @param {Object} [metadata] - Optional metadata to associate with the object.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<UploadResponse>} A promise that resolves to the response of the upload operation.\n */\n static async upload(\n key: string,\n body: FileContent,\n metadata?: { [key: string]: string },\n bucketName?: string,\n ): Promise<UploadResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.upload(key, body, metadata));\n }\n\n /**\n * Creates an upload write stream for the specified key in the object storage service.\n *\n * @param {string} key - The key of the object to create the upload write stream for.\n * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.\n * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.\n */\n static async createUploadWriteStream(\n key: string,\n bucketName?: string,\n ): Promise<CreateUploadWriteStreamResponse> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.createUploadWriteStream(key));\n }\n\n /**\n * Deletes an object from the object storage service.\n *\n * @param {string} key - The key of the object to delete.\n * @param {string} [bucketName] - The name of the bucket where the object is stored. If not provided, the default bucket name will be used.\n * @return {Promise<boolean>} A promise that resolves to true if the object was successfully deleted, or false otherwise.\n */\n static async delete(key: string, bucketName?: string): Promise<boolean> {\n return ObjectStorageService.getObjectStorageServiceInstance(\n bucketName,\n ).then((instance) => instance.delete(key));\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { Readable } from 'stream';
1
+ import stream, { Readable } from 'stream';
2
2
 
3
3
  type UploadResponse = {
4
4
  key: string;
@@ -45,6 +45,12 @@ type GetUploadUrlResponse = {
45
45
  signedUrl: string;
46
46
  };
47
47
 
48
+ type CreateUploadWriteStreamResponse = {
49
+ key: string;
50
+ stream: stream.PassThrough;
51
+ promise: Promise<unknown>;
52
+ };
53
+
48
54
  interface IObjectStorage {
49
55
  list(options: ListRequestOptions): Promise<ListResponse>;
50
56
  listAll(options: ListRequestOptions): Promise<ListResponse>;
@@ -55,6 +61,7 @@ interface IObjectStorage {
55
61
  upload(key: string, body: FileContent, metadata?: {
56
62
  [key: string]: string;
57
63
  }): Promise<UploadResponse>;
64
+ createUploadWriteStream(key: string): CreateUploadWriteStreamResponse;
58
65
  delete(key: string): Promise<boolean>;
59
66
  }
60
67
 
@@ -116,6 +123,14 @@ declare class ObjectStorageService {
116
123
  static upload(key: string, body: FileContent, metadata?: {
117
124
  [key: string]: string;
118
125
  }, bucketName?: string): Promise<UploadResponse>;
126
+ /**
127
+ * Creates an upload write stream for the specified key in the object storage service.
128
+ *
129
+ * @param {string} key - The key of the object to create the upload write stream for.
130
+ * @param {string} [bucketName] - The name of the bucket where the object will be stored. If not provided, the default bucket name will be used.
131
+ * @return {Promise<CreateUploadWriteStreamResponse>} A promise that resolves to the response of the upload operation.
132
+ */
133
+ static createUploadWriteStream(key: string, bucketName?: string): Promise<CreateUploadWriteStreamResponse>;
119
134
  /**
120
135
  * Deletes an object from the object storage service.
121
136
  *
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@qrvey/object-storage",
3
3
  "types": "dist/types/index.d.ts",
4
4
  "main": "dist/cjs/index.js",
5
- "version": "0.0.3",
5
+ "version": "0.0.4",
6
6
  "license": "MIT",
7
7
  "exports": {
8
8
  ".": {
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@aws-sdk/client-s3": "3.596.0",
29
+ "@aws-sdk/lib-storage": "3.598.0",
29
30
  "@aws-sdk/s3-request-presigner": "3.596.0",
30
31
  "@azure/storage-blob": "12.23.0"
31
32
  },