Integrationsfiles
Azure Blob Storage files
Store files in an Azure Blob Storage container with @mayurajs/filestorage-azure-blob: Shared Key, Entra ID or SAS, preconditions and errors.
- Package
- @mayurajs/filestorage-azure-blob
- Install
- npm install mayura @mayurajs/filestorage-azure-blob
- Vendor
- Microsoft Azure ↗
Azure Blob Storage is Microsoft Azure's object store.
@mayurajs/filestorage-azure-blob plugs a container into mayura/files, so you get the same
createFileStore API, limits, per-tenant views and file tools as with the built-in S3 backend. It talks to the Blob
REST API (service version 2024-11-04) with fetch, signing with Web Crypto: no Azure SDK, no other dependencies, and
it runs on every runtime Mayura runs on.
Install
npm install mayura @mayurajs/filestorage-azure-blobCredentials
Give exactly one of three credentials, all from the storage account in the Azure portal:
- Account key (
accountKey): under Security + networking > Access keys. Requests are signed with Shared Key. The key grants everything in the account. - Microsoft Entra ID token (
token): a function returning an access token forhttps://storage.azure.com/, for example from@azure/identity. Give the identity the Storage Blob Data Contributor role on the container. - Shared access signature (
sas): under Shared access tokens, or generated by your code. The store reads, creates, writes, deletes and lists, so the SAS needs those permissions (sp=rcwdl) on the container.
The package reads nothing from the environment, neither AZURE_STORAGE_CONNECTION_STRING nor AZURE_STORAGE_KEY:
pass the credential yourself, for example from AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY (or
AZURE_STORAGE_SAS_TOKEN) and AZURE_STORAGE_CONTAINER.
Use it
import { createFileStore } from 'mayura/files';
import { azureBlobFiles } from '@mayurajs/filestorage-azure-blob';
const files = createFileStore(azureBlobFiles({
account: process.env.AZURE_STORAGE_ACCOUNT ?? 'acmestorage',
container: process.env.AZURE_STORAGE_CONTAINER ?? 'reports',
accountKey: process.env.AZURE_STORAGE_KEY ?? '',
}), { maxFileBytes: 10 * 1024 * 1024 });
const written = await files.put('q3/sales.csv', new TextEncoder().encode('order,total\n'), {
contentType: 'text/csv',
metadata: { 'run-id': 'run-42' },
ifNoneMatch: '*',
});
const file = await files.get('q3/sales.csv', { ifMatch: written.etag });
console.log(file?.metadata); // { 'run-id': 'run-42' }With a SAS, pass sas: 'sv=...&sp=rcwdl&sig=...' (the query string, without a leading ?) instead of accountKey.
See Files for every store method, the store's own options and the file tools.
Options
| Option | Default | Meaning |
|---|---|---|
account |
required | The storage account name: 3 to 24 lowercase letters and digits. |
container |
required | The container name. |
accountKey |
one of three | The base64 account key, for Shared Key signing. |
token |
one of three | A function returning a Microsoft Entra ID access token for https://storage.azure.com/, called for each request. |
sas |
one of three | A shared access signature: the query string Azure gave, without a leading ?, containing sig. |
endpoint |
https://<account>.blob.core.windows.net |
Another endpoint: an https origin, or an http one on this machine for Azurite, optionally with the account as its path (http://127.0.0.1:10000/devstoreaccount1). |
maxListResponseBytes |
16 MiB | The largest list response read. |
fetch |
globalThis.fetch |
For tests and proxies. |
Versions and preconditions
A file's etag is Azure's ETag, quoted. The store's conditionalWrites and conditionalDelete are both true, and
they are Azure's own conditional headers:
ifNoneMatch: '*'sendsIf-None-Match: *; Azure's answer that the blob already exists becomesCONFLICT.ifMatchon a write, a read or a delete sendsIf-Match; a stale etag (HTTP 412) or a missing blob becomesCONFLICT.
Writes, metadata and limits
- Files are block blobs, each written in one request. A delete also removes the blob's snapshots.
- The media type is the blob's
Content-Type. Metadata names must be C# identifiers on Azure, so each key is stored under a name Azure accepts (run-idasm_run_id) and read back as written. Listings return each file's size, etag, media type and time, but not its metadata. - Files are as large as the store's
maxFileBytes, up to 5 GiB. Each file is held in memory while it is written or read. - Ranges are read with
x-ms-range; a range that starts at or past the end returns no bytes and the file's size.
Errors
Failures reach you as a FileStoreError (code STORAGE_UNAVAILABLE) with a reason, mapped from Azure's answers.
Nothing Azure wrote reaches the message.
| Error | When |
|---|---|
CONFLICT |
A precondition failed: the blob exists for a create-only write, has another version, or is missing for ifMatch. |
reason: 'authentication' |
The token source threw or returned no usable token (nothing is sent), or Azure answered 401 or 403, for example a wrong key or signature. |
reason: 'rate_limited' |
HTTP 429. |
reason: 'timeout' |
HTTP 408, or the call took longer than the store's timeoutMs. |
reason: 'unavailable' |
HTTP 5xx, or Azure could not be reached. |
reason: 'rejected' |
Azure refused the request for another reason. |
reason: 'invalid_response' |
The reply was not what the Blob API promises. |
LIMIT_EXCEEDED |
A file or range is larger than the limit for the call. |
Configuration mistakes, such as two credentials at once, an account key that is not base64 or an http endpoint on
another host, fail with INVALID_CONFIG when you call azureBlobFiles().
How it is tested
- Unit tests run the package against a fake that records every request: Shared Key signatures, block blob headers, metadata names, conditional headers, Entra ID and SAS authentication, error mapping without the service's text, and that nothing is read from the environment.
- In CI, the file store conformance suite runs against Azurite, Microsoft's
Azure Storage emulator, which checks Shared Key signatures: all 13 cases pass, and a request signed with another key is
refused with
authentication. - It has not been run against a real Azure account yet.
Related
- Files: stores, views, preconditions and file tools.
- Artifacts: keep agent artifacts in this container.
- Google Cloud Storage files: the same store on Google Cloud.
- Files SDK files: other providers through Files SDK.