* Generate presigned URL for Azure Blob
(
key: string,
contentType: string,
metadata: Record<string, string>,
config: {
containerName?: string
accountName?: string
accountKey?: string
connectionString?: string
},
expirationSeconds: number
)
| 624 | * Generate presigned URL for Azure Blob |
| 625 | */ |
| 626 | async function generateBlobPresignedUrl( |
| 627 | key: string, |
| 628 | contentType: string, |
| 629 | metadata: Record<string, string>, |
| 630 | config: { |
| 631 | containerName?: string |
| 632 | accountName?: string |
| 633 | accountKey?: string |
| 634 | connectionString?: string |
| 635 | }, |
| 636 | expirationSeconds: number |
| 637 | ): Promise<PresignedUrlResponse> { |
| 638 | const { getBlobServiceClient } = await import('@/lib/uploads/providers/blob/client') |
| 639 | const { BlobSASPermissions, generateBlobSASQueryParameters, StorageSharedKeyCredential } = |
| 640 | await import('@azure/storage-blob') |
| 641 | |
| 642 | if (!config.containerName) { |
| 643 | throw new Error('Blob configuration missing container name') |
| 644 | } |
| 645 | |
| 646 | const blobServiceClient = await getBlobServiceClient() |
| 647 | const containerClient = blobServiceClient.getContainerClient(config.containerName) |
| 648 | const blobClient = containerClient.getBlockBlobClient(key) |
| 649 | |
| 650 | const startsOn = new Date() |
| 651 | const expiresOn = new Date(startsOn.getTime() + expirationSeconds * 1000) |
| 652 | |
| 653 | let sasToken: string |
| 654 | |
| 655 | if (config.accountName && config.accountKey) { |
| 656 | const sharedKeyCredential = new StorageSharedKeyCredential( |
| 657 | config.accountName, |
| 658 | config.accountKey |
| 659 | ) |
| 660 | sasToken = generateBlobSASQueryParameters( |
| 661 | { |
| 662 | containerName: config.containerName, |
| 663 | blobName: key, |
| 664 | permissions: BlobSASPermissions.parse('w'), // write permission for upload |
| 665 | startsOn, |
| 666 | expiresOn, |
| 667 | }, |
| 668 | sharedKeyCredential |
| 669 | ).toString() |
| 670 | } else { |
| 671 | throw new Error('Azure Blob SAS generation requires accountName and accountKey') |
| 672 | } |
| 673 | |
| 674 | return { |
| 675 | url: `${blobClient.url}?${sasToken}`, |
| 676 | key, |
| 677 | uploadHeaders: { |
| 678 | 'x-ms-blob-type': 'BlockBlob', |
| 679 | 'x-ms-blob-content-type': contentType, |
| 680 | ...Object.entries(metadata).reduce( |
| 681 | (acc, [k, v]) => { |
| 682 | acc[`x-ms-meta-${k}`] = encodeURIComponent(v) |
| 683 | return acc |
no test coverage detected