@alepha/bucket-azure 0.11.2 → 0.11.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/dist/{index.d.ts → index.d.mts} +3 -1
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +5 -3
- package/dist/index.mjs.map +1 -0
- package/package.json +9 -9
- package/src/providers/AzureFileStorageProvider.ts +4 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -2,6 +2,7 @@ import { FileStorageProvider } from "@alepha/bucket";
|
|
|
2
2
|
import * as _alepha_core1 from "@alepha/core";
|
|
3
3
|
import { Alepha, FileLike, Static } from "@alepha/core";
|
|
4
4
|
import { DateTimeProvider } from "@alepha/datetime";
|
|
5
|
+
import { FileSystem } from "@alepha/file";
|
|
5
6
|
import * as _alepha_logger0 from "@alepha/logger";
|
|
6
7
|
import { BlobServiceClient, BlockBlobClient, ContainerClient, StoragePipelineOptions } from "@azure/storage-blob";
|
|
7
8
|
|
|
@@ -22,6 +23,7 @@ declare class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
22
23
|
};
|
|
23
24
|
protected readonly alepha: Alepha;
|
|
24
25
|
protected readonly time: DateTimeProvider;
|
|
26
|
+
protected readonly fileSystem: FileSystem;
|
|
25
27
|
protected readonly containers: Record<string, ContainerClient>;
|
|
26
28
|
protected readonly blobServiceClient: BlobServiceClient;
|
|
27
29
|
readonly options: StoragePipelineOptions;
|
|
@@ -47,4 +49,4 @@ declare class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
47
49
|
declare const AlephaBucketAzure: _alepha_core1.Service<_alepha_core1.Module<{}>>;
|
|
48
50
|
//#endregion
|
|
49
51
|
export { AlephaBucketAzure, AzureFileStorageProvider };
|
|
50
|
-
//# sourceMappingURL=index.d.
|
|
52
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;cA0BM,WAEJ,aAAA,CAFa;gCAEb,aAAA,CAAA;;;EAFI,UAAA,GAEJ,SAGsB,OAHtB,CAG8B,MAH9B,CAAA,OAG4C,SAH5C,CAAA,CAAA,CAAA,CAFa;;;;;AAKS,cAMX,wBAAA,YAAoC,mBANzB,CAAA;EAAO,mBAAA,GAAA,EAMO,eAAA,CACd,MAPO;EAAA,mBAAA,GAAA,EAAA;IAAA,4BAAA,EAAA,MAAA;EAMlB,CAAA;EAAyB,mBACd,MAAA,EAEG,MAFH;EAEG,mBAAA,IAAA,EACF,gBADE;EACF,mBAAA,UAAA,EACM,UADN;EACM,mBAAA,UAAA,EACE,MADF,CAAA,MAAA,EACiB,eADjB,CAAA;EACiB,mBAAA,iBAAA,EACR,iBADQ;EAAf,SAAA,OAAA,EAGN,sBAHM;EACO,WAAA,CAAA;EAEb,mBAAA,OAAA,EAAsB,aAAA,CASrB,cATD,CAAA,OAAA,CAAA;EAAsB,WASrB,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EA6BlB,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,IAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAEL,OAFK,CAAA,MAAA,CAAA;EAEL,QAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA6CwD,OA7CxD,CA6CgE,QA7ChE,CAAA;EA6CgE,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAyBV,OAzBU,CAAA,OAAA,CAAA;EAAR,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAgCF,OAhCE,CAAA,IAAA,CAAA;EAyBF,QAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAmBL,eAnBK;EAOA,UAAA,qBAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EA0BtD,OA1BsD,CA0B9C,eA1B8C,CAAA;EAYL,UAAA,QAAA,CAAA,CAAA,EAAA,MAAA;;;;;;;;;;cCjKzC,mBAAiB,aAAA,CAAA,QAW5B,aAAA,CAX4B"}
|
|
@@ -3,7 +3,7 @@ import { $env, $hook, $inject, $module, Alepha, t } from "@alepha/core";
|
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { Readable } from "node:stream";
|
|
5
5
|
import { DateTimeProvider } from "@alepha/datetime";
|
|
6
|
-
import {
|
|
6
|
+
import { FileSystem } from "@alepha/file";
|
|
7
7
|
import { $logger } from "@alepha/logger";
|
|
8
8
|
import { BlobServiceClient } from "@azure/storage-blob";
|
|
9
9
|
|
|
@@ -17,6 +17,7 @@ var AzureFileStorageProvider = class {
|
|
|
17
17
|
env = $env(envSchema);
|
|
18
18
|
alepha = $inject(Alepha);
|
|
19
19
|
time = $inject(DateTimeProvider);
|
|
20
|
+
fileSystem = $inject(FileSystem);
|
|
20
21
|
containers = {};
|
|
21
22
|
blobServiceClient;
|
|
22
23
|
options = {};
|
|
@@ -67,7 +68,8 @@ var AzureFileStorageProvider = class {
|
|
|
67
68
|
throw error;
|
|
68
69
|
});
|
|
69
70
|
if (!blob.readableStreamBody) throw new FileNotFoundError("File not found - empty stream body");
|
|
70
|
-
return createFile(
|
|
71
|
+
return this.fileSystem.createFile({
|
|
72
|
+
stream: blob.readableStreamBody,
|
|
71
73
|
...blob.metadata,
|
|
72
74
|
size: blob.contentLength
|
|
73
75
|
});
|
|
@@ -120,4 +122,4 @@ const AlephaBucketAzure = $module({
|
|
|
120
122
|
|
|
121
123
|
//#endregion
|
|
122
124
|
export { AlephaBucketAzure, AzureFileStorageProvider };
|
|
123
|
-
//# sourceMappingURL=index.
|
|
125
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Readable } from \"node:stream\";\nimport {\n $bucket,\n FileNotFoundError,\n type FileStorageProvider,\n} from \"@alepha/bucket\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type FileLike,\n type Static,\n t,\n} from \"@alepha/core\";\nimport { DateTimeProvider } from \"@alepha/datetime\";\nimport { FileSystem } from \"@alepha/file\";\nimport { $logger } from \"@alepha/logger\";\nimport {\n BlobServiceClient,\n type BlockBlobClient,\n type ContainerClient,\n type StoragePipelineOptions,\n} from \"@azure/storage-blob\";\n\nconst envSchema = t.object({\n AZ_STORAGE_CONNECTION_STRING: t.string(),\n});\n\ndeclare module \"@alepha/core\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Azure Blog Storage implementation of File Storage Provider.\n */\nexport class AzureFileStorageProvider implements FileStorageProvider {\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly time = $inject(DateTimeProvider);\n protected readonly fileSystem = $inject(FileSystem);\n protected readonly containers: Record<string, ContainerClient> = {};\n protected readonly blobServiceClient: BlobServiceClient;\n\n public readonly options: StoragePipelineOptions = {};\n\n constructor() {\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n this.env.AZ_STORAGE_CONNECTION_STRING,\n this.options,\n );\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n for (const bucket of this.alepha.descriptors($bucket)) {\n if (bucket.provider !== this) {\n continue;\n }\n\n const containerName = this.convertName(bucket.name);\n\n this.log.debug(`Prepare container '${containerName}' ...`);\n\n if (!this.containers[containerName]) {\n this.containers[containerName] =\n await this.createContainerClient(containerName);\n }\n\n this.log.info(`Container '${bucket.name}' OK`);\n }\n },\n });\n\n public convertName(name: string): string {\n // Azure Blob Storage does not allow uppercase letters in container names\n return name.replaceAll(\"/\", \"-\").toLowerCase();\n }\n\n public async upload(\n bucketName: string,\n file: FileLike,\n fileId?: string,\n ): Promise<string> {\n fileId ??= this.createId();\n\n this.log.trace(\n `Uploading file '${file.name}' to bucket '${bucketName}' with id '${fileId}'...`,\n );\n\n const block = this.getBlock(bucketName, fileId);\n\n const metadata = {\n name: file.name,\n type: file.type,\n };\n\n if (file.filepath) {\n await block.uploadFile(file.filepath, {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n });\n } else if (file.size > 0) {\n await block.uploadData(await file.arrayBuffer(), {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n });\n } else {\n await block.uploadStream(\n Readable.from(file.stream()),\n file.size || undefined,\n 5,\n {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n },\n );\n }\n\n return fileId;\n }\n\n public async download(bucketName: string, fileId: string): Promise<FileLike> {\n this.log.trace(\n `Downloading file '${fileId}' from bucket '${bucketName}'...`,\n );\n const block = this.getBlock(bucketName, fileId);\n\n const blob = await block.download().catch((error) => {\n if (error instanceof Error) {\n throw new FileNotFoundError(\"Error downloading file\", { cause: error });\n }\n\n throw error;\n });\n\n if (!blob.readableStreamBody) {\n throw new FileNotFoundError(\"File not found - empty stream body\");\n }\n\n return this.fileSystem.createFile({\n stream: blob.readableStreamBody,\n ...blob.metadata,\n size: blob.contentLength,\n });\n }\n\n public async exists(bucketName: string, fileId: string): Promise<boolean> {\n this.log.trace(\n `Checking existence of file '${fileId}' in bucket '${bucketName}'...`,\n );\n return await this.getBlock(bucketName, fileId).exists();\n }\n\n public async delete(bucketName: string, fileId: string): Promise<void> {\n this.log.trace(`Deleting file '${fileId}' from bucket '${bucketName}'...`);\n try {\n await this.getBlock(bucketName, fileId).delete();\n } catch (error) {\n if (error instanceof Error) {\n throw new FileNotFoundError(\"Error deleting file\", { cause: error });\n }\n throw error;\n }\n }\n\n public getBlock(container: string, fileId: string): BlockBlobClient {\n const containerName = this.convertName(container);\n\n if (!this.containers[containerName]) {\n throw new FileNotFoundError(\n `File '${fileId}' not found - container '${container}' does not exists`,\n );\n }\n\n return this.containers[containerName].getBlockBlobClient(fileId);\n }\n\n protected async createContainerClient(\n name: string,\n ): Promise<ContainerClient> {\n const container = this.blobServiceClient.getContainerClient(name);\n\n await this.time.deadline(\n (abortSignal) => container.createIfNotExists({ abortSignal }),\n [5, \"seconds\"],\n );\n\n return container;\n }\n\n protected createId(): string {\n return randomUUID();\n }\n}\n","import { AlephaBucket, FileStorageProvider } from \"@alepha/bucket\";\nimport { $module } from \"@alepha/core\";\nimport { AzureFileStorageProvider } from \"./providers/AzureFileStorageProvider.ts\";\n\nexport * from \"./providers/AzureFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.\n *\n * @see {@link AzureFileStorageProvider}\n * @module alepha.bucket.azure\n */\nexport const AlephaBucketAzure = $module({\n name: \"alepha.bucket.azure\",\n services: [AzureFileStorageProvider],\n register: (alepha) =>\n alepha\n .with({\n optional: true,\n provide: FileStorageProvider,\n use: AzureFileStorageProvider,\n })\n .with(AlephaBucket),\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"storage-blob"
|
|
11
11
|
],
|
|
12
12
|
"author": "Feunard",
|
|
13
|
-
"version": "0.11.
|
|
13
|
+
"version": "0.11.4",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=22.0.0"
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
"src"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@alepha/bucket": "0.11.
|
|
27
|
-
"@alepha/core": "0.11.
|
|
28
|
-
"@alepha/datetime": "0.11.
|
|
29
|
-
"@alepha/file": "0.11.
|
|
30
|
-
"@alepha/logger": "0.11.
|
|
26
|
+
"@alepha/bucket": "0.11.4",
|
|
27
|
+
"@alepha/core": "0.11.4",
|
|
28
|
+
"@alepha/datetime": "0.11.4",
|
|
29
|
+
"@alepha/file": "0.11.4",
|
|
30
|
+
"@alepha/logger": "0.11.4",
|
|
31
31
|
"@azure/storage-blob": "^12.29.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@biomejs/biome": "^2.3.
|
|
35
|
-
"tsdown": "^0.
|
|
34
|
+
"@biomejs/biome": "^2.3.3",
|
|
35
|
+
"tsdown": "^0.16.0",
|
|
36
36
|
"typescript": "^5.9.3",
|
|
37
|
-
"vitest": "^
|
|
37
|
+
"vitest": "^4.0.6"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"test": "vitest run",
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
t,
|
|
16
16
|
} from "@alepha/core";
|
|
17
17
|
import { DateTimeProvider } from "@alepha/datetime";
|
|
18
|
-
import {
|
|
18
|
+
import { FileSystem } from "@alepha/file";
|
|
19
19
|
import { $logger } from "@alepha/logger";
|
|
20
20
|
import {
|
|
21
21
|
BlobServiceClient,
|
|
@@ -40,6 +40,7 @@ export class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
40
40
|
protected readonly env = $env(envSchema);
|
|
41
41
|
protected readonly alepha = $inject(Alepha);
|
|
42
42
|
protected readonly time = $inject(DateTimeProvider);
|
|
43
|
+
protected readonly fileSystem = $inject(FileSystem);
|
|
43
44
|
protected readonly containers: Record<string, ContainerClient> = {};
|
|
44
45
|
protected readonly blobServiceClient: BlobServiceClient;
|
|
45
46
|
|
|
@@ -146,7 +147,8 @@ export class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
146
147
|
throw new FileNotFoundError("File not found - empty stream body");
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
return createFile(
|
|
150
|
+
return this.fileSystem.createFile({
|
|
151
|
+
stream: blob.readableStreamBody,
|
|
150
152
|
...blob.metadata,
|
|
151
153
|
size: blob.contentLength,
|
|
152
154
|
});
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;cA0BM,WAEJ,aAAA,CAFa;gCAEb,aAAA,CAAA;;;EAFI,UAAA,GAEJ,SAGsB,OAHtB,CAG8B,MAH9B,CAAA,OAG4C,SAH5C,CAAA,CAAA,CAAA,CAFa;;;;;AAKS,cAMX,wBAAA,YAAoC,mBANzB,CAAA;EAAO,mBAAA,GAAA,EAMO,eAAA,CACd,MAPO;EAAA,mBAAA,GAAA,EAAA;IAAA,4BAAA,EAAA,MAAA;EAMlB,CAAA;EAAyB,mBACd,MAAA,EAEG,MAFH;EAEG,mBAAA,IAAA,EACF,gBADE;EACF,mBAAA,UAAA,EACQ,MADR,CAAA,MAAA,EACuB,eADvB,CAAA;EACuB,mBAAA,iBAAA,EACR,iBADQ;EAAf,SAAA,OAAA,EAGN,sBAHM;EACO,WAAA,CAAA;EAEb,mBAAA,OAAA,EAAsB,aAAA,CASrB,cATD,CAAA,OAAA,CAAA;EAAsB,WASrB,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EA6BlB,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,IAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAEL,OAFK,CAAA,MAAA,CAAA;EAEL,QAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA6CwD,OA7CxD,CA6CgE,QA7ChE,CAAA;EA6CgE,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAwBV,OAxBU,CAAA,OAAA,CAAA;EAAR,MAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA+BF,OA/BE,CAAA,IAAA,CAAA;EAwBF,QAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAmBL,eAnBK;EAOA,UAAA,qBAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EA0BtD,OA1BsD,CA0B9C,eA1B8C,CAAA;EAYL,UAAA,QAAA,CAAA,CAAA,EAAA,MAAA;;;;;;;;;;cC/JzC,mBAAiB,aAAA,CAAA,QAW5B,aAAA,CAX4B"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Readable } from \"node:stream\";\nimport {\n $bucket,\n FileNotFoundError,\n type FileStorageProvider,\n} from \"@alepha/bucket\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type FileLike,\n type Static,\n t,\n} from \"@alepha/core\";\nimport { DateTimeProvider } from \"@alepha/datetime\";\nimport { createFile } from \"@alepha/file\";\nimport { $logger } from \"@alepha/logger\";\nimport {\n BlobServiceClient,\n type BlockBlobClient,\n type ContainerClient,\n type StoragePipelineOptions,\n} from \"@azure/storage-blob\";\n\nconst envSchema = t.object({\n AZ_STORAGE_CONNECTION_STRING: t.string(),\n});\n\ndeclare module \"@alepha/core\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Azure Blog Storage implementation of File Storage Provider.\n */\nexport class AzureFileStorageProvider implements FileStorageProvider {\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly time = $inject(DateTimeProvider);\n protected readonly containers: Record<string, ContainerClient> = {};\n protected readonly blobServiceClient: BlobServiceClient;\n\n public readonly options: StoragePipelineOptions = {};\n\n constructor() {\n this.blobServiceClient = BlobServiceClient.fromConnectionString(\n this.env.AZ_STORAGE_CONNECTION_STRING,\n this.options,\n );\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n for (const bucket of this.alepha.descriptors($bucket)) {\n if (bucket.provider !== this) {\n continue;\n }\n\n const containerName = this.convertName(bucket.name);\n\n this.log.debug(`Prepare container '${containerName}' ...`);\n\n if (!this.containers[containerName]) {\n this.containers[containerName] =\n await this.createContainerClient(containerName);\n }\n\n this.log.info(`Container '${bucket.name}' OK`);\n }\n },\n });\n\n public convertName(name: string): string {\n // Azure Blob Storage does not allow uppercase letters in container names\n return name.replaceAll(\"/\", \"-\").toLowerCase();\n }\n\n public async upload(\n bucketName: string,\n file: FileLike,\n fileId?: string,\n ): Promise<string> {\n fileId ??= this.createId();\n\n this.log.trace(\n `Uploading file '${file.name}' to bucket '${bucketName}' with id '${fileId}'...`,\n );\n\n const block = this.getBlock(bucketName, fileId);\n\n const metadata = {\n name: file.name,\n type: file.type,\n };\n\n if (file.filepath) {\n await block.uploadFile(file.filepath, {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n });\n } else if (file.size > 0) {\n await block.uploadData(await file.arrayBuffer(), {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n });\n } else {\n await block.uploadStream(\n Readable.from(file.stream()),\n file.size || undefined,\n 5,\n {\n metadata,\n blobHTTPHeaders: {\n blobContentType: file.type,\n },\n },\n );\n }\n\n return fileId;\n }\n\n public async download(bucketName: string, fileId: string): Promise<FileLike> {\n this.log.trace(\n `Downloading file '${fileId}' from bucket '${bucketName}'...`,\n );\n const block = this.getBlock(bucketName, fileId);\n\n const blob = await block.download().catch((error) => {\n if (error instanceof Error) {\n throw new FileNotFoundError(\"Error downloading file\", { cause: error });\n }\n\n throw error;\n });\n\n if (!blob.readableStreamBody) {\n throw new FileNotFoundError(\"File not found - empty stream body\");\n }\n\n return createFile(blob.readableStreamBody, {\n ...blob.metadata,\n size: blob.contentLength,\n });\n }\n\n public async exists(bucketName: string, fileId: string): Promise<boolean> {\n this.log.trace(\n `Checking existence of file '${fileId}' in bucket '${bucketName}'...`,\n );\n return await this.getBlock(bucketName, fileId).exists();\n }\n\n public async delete(bucketName: string, fileId: string): Promise<void> {\n this.log.trace(`Deleting file '${fileId}' from bucket '${bucketName}'...`);\n try {\n await this.getBlock(bucketName, fileId).delete();\n } catch (error) {\n if (error instanceof Error) {\n throw new FileNotFoundError(\"Error deleting file\", { cause: error });\n }\n throw error;\n }\n }\n\n public getBlock(container: string, fileId: string): BlockBlobClient {\n const containerName = this.convertName(container);\n\n if (!this.containers[containerName]) {\n throw new FileNotFoundError(\n `File '${fileId}' not found - container '${container}' does not exists`,\n );\n }\n\n return this.containers[containerName].getBlockBlobClient(fileId);\n }\n\n protected async createContainerClient(\n name: string,\n ): Promise<ContainerClient> {\n const container = this.blobServiceClient.getContainerClient(name);\n\n await this.time.deadline(\n (abortSignal) => container.createIfNotExists({ abortSignal }),\n [5, \"seconds\"],\n );\n\n return container;\n }\n\n protected createId(): string {\n return randomUUID();\n }\n}\n","import { AlephaBucket, FileStorageProvider } from \"@alepha/bucket\";\nimport { $module } from \"@alepha/core\";\nimport { AzureFileStorageProvider } from \"./providers/AzureFileStorageProvider.ts\";\n\nexport * from \"./providers/AzureFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.\n *\n * @see {@link AzureFileStorageProvider}\n * @module alepha.bucket.azure\n */\nexport const AlephaBucketAzure = $module({\n name: \"alepha.bucket.azure\",\n services: [AzureFileStorageProvider],\n register: (alepha) =>\n alepha\n .with({\n optional: true,\n provide: FileStorageProvider,\n use: AzureFileStorageProvider,\n })\n .with(AlephaBucket),\n});\n"],"mappings":"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"}
|