@akadenia/azure-storage
Version:
Microsoft Azure storage helper methods
274 lines (273 loc) • 13.7 kB
JavaScript
;
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;