UNPKG

@akadenia/azure-storage

Version:
274 lines (273 loc) 13.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlobStorage = exports.BlobPermissions = void 0; const storage_blob_1 = require("@azure/storage-blob"); const logger_1 = require("@azure/logger"); (0, logger_1.setLogLevel)("error"); var BlobPermissions; (function (BlobPermissions) { BlobPermissions["READ"] = "r"; BlobPermissions["WRITE"] = "w"; BlobPermissions["CREATE"] = "c"; BlobPermissions["DELETE"] = "d"; BlobPermissions["ADD"] = "a"; })(BlobPermissions || (exports.BlobPermissions = BlobPermissions = {})); /** * @class BlobStorage - A class that contains azure blob storage helpers */ class BlobStorage { constructor(connectionStringOrSASUrl) { if (!connectionStringOrSASUrl) { throw new Error("Connection string or SAS URL is required"); } this.connectionStringOrSASUrl = connectionStringOrSASUrl; } isEmulatorConnection() { return (this.connectionStringOrSASUrl.includes("UseDevelopmentStorage=true") || this.connectionStringOrSASUrl.includes("devstoreaccount1")); } isSASUrl() { return this.connectionStringOrSASUrl.includes("?sv=") && this.connectionStringOrSASUrl.includes("sig="); } /** * @returns {BlobServiceClient} - A BlobServiceClient object */ getBlobServiceUrl() { if (this.isSASUrl()) { return new storage_blob_1.BlobServiceClient(this.connectionStringOrSASUrl); } return storage_blob_1.BlobServiceClient.fromConnectionString(this.connectionStringOrSASUrl); } /** * Creates a container in Azure Blob Storage if it does not already exist. * * @param containerName - The name of the container to create. * @param sasUrl - Optional. The SAS URL for accessing the Blob service. If not provided, the default Blob service URL will be used. * @returns A promise that resolves to a boolean indicating whether the container was successfully created or already exists. */ createContainer(containerName) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const result = yield container.createIfNotExists(); return result.succeeded; }); } /** * Deletes a container in Azure Blob Storage if it exists. * * @param containerName - The name of the container to delete. * @returns A promise that resolves to a boolean indicating whether the container was successfully deleted. */ deleteContainer(containerName) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const result = yield container.deleteIfExists(); return result.succeeded; }); } /** * @param {string} containerName - The name of the container to check * @param {string} blobNamePrefix - The prefix of the blob name * @returns {Promise<Array<BlobItem>>} - An array of BlobItem objects */ listBlobs(containerName, blobNamePrefix) { return __awaiter(this, void 0, void 0, function* () { var _a, e_1, _b, _c; const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const result = []; try { for (var _d = true, _e = __asyncValues(container.listBlobsFlat({ prefix: blobNamePrefix })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const blob = _c; result.push(blob); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_1) throw e_1.error; } } return result; }); } /** * @param {string} containerName - The name of the container to download from * @param {string} blobName - The name of the blob to download * @returns {Promise<Buffer>} - A Buffer object */ downloadBlob(containerName, blobName) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlobClient(blobName); return yield blob.downloadToBuffer(); }); } /** * @param {string} containerName - The name of the container to check * @param {string} blobName - The name of the blob to check * @returns {Promise<boolean>} - A boolean indicating whether or not the blob exists */ blobExists(containerName, blobName) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlockBlobClient(blobName); return yield blob.exists(); }); } /** * @param {string} containerName - The name of the container to upload to * @param {string} blobName - The name of the blob to upload * @param {HttpRequestBody} body - The body of the blob * @param {string} contentLength - The content length * @param {string} contentType - The content type of the blob * @returns {Promise<boolean>} - A boolean indicating whether or not the blob was successfully uploaded */ upload(containerName, blobName, body, contentLength, contentType) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlockBlobClient(blobName); const response = yield blob.upload(body, contentLength, { blobHTTPHeaders: { blobContentType: contentType }, }); return response.errorCode === undefined; }); } /** * @param {string} containerName - The name of the container to upload to * @param {string} blobName - The name of the blob to upload * @param data - Buffer | Blob | ArrayBuffer | ArrayBufferView * @param {BlobHTTPHeaders} [blobHTTPHeaders] - The blob HTTP headers to set while uploading the blob * @param bufferSize - Size of every buffer allocated, also the block size in the uploaded block blob. Default value is 8MB * @returns {Promise<boolean>} - A boolean indicating whether or not the blob was successfully uploaded */ uploadData(containerName, blobName, data, blobHTTPHeaders) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlockBlobClient(blobName); const response = yield blob.uploadData(data, { blobHTTPHeaders, }); return response.errorCode === undefined; }); } /** * @param {string} containerName - The name of the container to upload to * @param {string} blobName - The name of the blob to upload * @param stream - Node.js Readable stream * @param {BlobHTTPHeaders} [blobHTTPHeaders] - The blob HTTP headers to set while uploading the blob * @param bufferSize - Size of every buffer allocated, also the block size in the uploaded block blob. Default value is 8MB * @returns {Promise<boolean>} - A boolean indicating whether or not the blob was successfully uploaded */ uploadStream(containerName, blobName, stream, blobHTTPHeaders) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlockBlobClient(blobName); const response = yield blob.uploadStream(stream, undefined, undefined, { blobHTTPHeaders, }); return response.errorCode === undefined; }); } /** * * Generates a Shared Access Signature (SAS) URL for a blob or container * * @param {string} containerName - The name of the blob container * @param {string} [blobName] - Optional. The name of the specific blob. If not provided, the SAS token will be generated for the container level * @param {SASOptions} [sasOptions={}] - Optional. The options used for generating the SAS token * @returns {SASUrlComponents} - Object containing: * - fullUrlWithSAS: The complete URL with SAS token * - fullUrl: The complete URL without SAS token * - containerName: The name of the blob container * - blobName: The name of the specific blob (if provided) * - sasQueryString: The SAS token query parameters */ generateSASUrl(containerName, blobName, sasOptions = {}) { var _a, _b; const blobService = this.getBlobServiceUrl(); const { startsOn = new Date(new Date().valueOf() - 300 * 1000), expiresOn = new Date(new Date().valueOf() + 3600 * 1000), permissions = [BlobPermissions.READ], } = sasOptions; const options = { containerName, blobName, startsOn, expiresOn, permissions: storage_blob_1.BlobSASPermissions.parse(permissions.join("")), }; const parts = this.connectionStringOrSASUrl.split(";"); const accountName = (_a = parts.find((p) => p.startsWith("AccountName="))) === null || _a === void 0 ? void 0 : _a.split("=")[1]; const accountKey = (_b = parts.find((p) => p.startsWith("AccountKey="))) === null || _b === void 0 ? void 0 : _b.split("=")[1]; if (!(accountName && accountKey)) { throw new Error("Could not extract account name and account key from connection string"); } const sharedKeyCredential = new storage_blob_1.StorageSharedKeyCredential(accountName, accountKey); const sasQueryString = (0, storage_blob_1.generateBlobSASQueryParameters)(options, sharedKeyCredential).toString(); // Create base URL object const baseUrl = new URL(blobService.url); const fullUrl = new URL(`?${sasQueryString}`, baseUrl); // Create full URL with container and blob const fullUrlWithSAS = new URL(blobService.url); fullUrlWithSAS.pathname = blobName ? `${containerName}/${blobName}` : containerName; fullUrlWithSAS.search = `?${sasQueryString}`; return { sasQueryString, fullUrl: fullUrl.toString(), fullUrlWithSAS: fullUrlWithSAS.toString(), containerName, blobName, }; } /** * Deletes a blob from the specified container. * * @param {string} containerName - The name of the container containing the blob * @param {string} blobName - The name of the blob to delete * @returns {Promise<boolean>} - A boolean indicating whether the blob was successfully deleted */ deleteBlob(containerName, blobName) { return __awaiter(this, void 0, void 0, function* () { const blobService = this.getBlobServiceUrl(); const container = blobService.getContainerClient(containerName); const blob = container.getBlockBlobClient(blobName); try { const response = yield blob.delete(); return response.errorCode === undefined; } catch (error) { if (error.statusCode === 404) { if (!this.isSASUrl()) { return true; } throw error; } throw error; } }); } } exports.BlobStorage = BlobStorage;