@alepha/bucket-azure 0.7.5 → 0.7.7

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.cjs CHANGED
@@ -1,137 +1,141 @@
1
- 'use strict';
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
2
22
 
3
- var bucket = require('@alepha/bucket');
4
- var node_crypto = require('node:crypto');
5
- var core = require('@alepha/core');
6
- var datetime = require('@alepha/datetime');
7
- var file = require('@alepha/file');
8
- var storageBlob = require('@azure/storage-blob');
23
+ //#endregion
24
+ const __alepha_bucket = __toESM(require("@alepha/bucket"));
25
+ const node_crypto = __toESM(require("node:crypto"));
26
+ const __alepha_core = __toESM(require("@alepha/core"));
27
+ const __alepha_datetime = __toESM(require("@alepha/datetime"));
28
+ const __alepha_file = __toESM(require("@alepha/file"));
29
+ const __azure_storage_blob = __toESM(require("@azure/storage-blob"));
9
30
 
10
- const envSchema = core.t.object({
11
- AZ_STORAGE_CONNECTION_STRING: core.t.string({
12
- size: "long",
13
- default: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
14
- })
15
- });
16
- class AzureFileStorageProvider {
17
- log = core.$logger();
18
- env = core.$env(envSchema);
19
- bucketProvider = core.$inject(bucket.BucketDescriptorProvider);
20
- dateTimeProvider = core.$inject(datetime.DateTimeProvider);
21
- containers = {};
22
- blobServiceClient;
23
- options = {};
24
- constructor() {
25
- this.blobServiceClient = storageBlob.BlobServiceClient.fromConnectionString(
26
- this.env.AZ_STORAGE_CONNECTION_STRING,
27
- this.storagePipelineOptions()
28
- );
29
- }
30
- storagePipelineOptions() {
31
- return {};
32
- }
33
- async createContainer(containerName) {
34
- if (this.containers[containerName]) {
35
- return this.containers[containerName];
36
- }
37
- const container = await this.createContainerClient(containerName);
38
- this.containers[containerName] = container;
39
- return container;
40
- }
41
- async upload(bucketName, file2, fileId) {
42
- fileId ??= this.createId();
43
- const block = this.getBlock(bucketName, fileId);
44
- const metadata = {
45
- name: file2.name,
46
- type: file2.type
47
- };
48
- if (file2.filepath) {
49
- await block.uploadFile(file2.filepath, {
50
- metadata,
51
- blobHTTPHeaders: {
52
- blobContentType: file2.type
53
- }
54
- });
55
- } else if (file2.size > 0) {
56
- await block.uploadData(await file2.arrayBuffer(), {
57
- metadata,
58
- blobHTTPHeaders: {
59
- blobContentType: file2.type
60
- }
61
- });
62
- } else {
63
- throw new Error("Raw stream upload is not supported yet");
64
- }
65
- return fileId;
66
- }
67
- async download(bucketName, fileId) {
68
- const block = this.getBlock(bucketName, fileId);
69
- const blob = await block.download().catch((error) => {
70
- if (error instanceof Error) {
71
- throw new bucket.FileNotFoundError("Error downloading file", { cause: error });
72
- }
73
- throw error;
74
- });
75
- if (!blob.readableStreamBody) {
76
- throw new bucket.FileNotFoundError("File not found - empty stream body");
77
- }
78
- return file.file(blob.readableStreamBody, blob.metadata);
79
- }
80
- async exists(bucketName, fileId) {
81
- return await this.getBlock(bucketName, fileId).exists();
82
- }
83
- async delete(bucketName, fileId) {
84
- try {
85
- await this.getBlock(bucketName, fileId).delete();
86
- } catch (error) {
87
- if (error instanceof Error) {
88
- throw new bucket.FileNotFoundError("Error deleting file", { cause: error });
89
- }
90
- throw error;
91
- }
92
- }
93
- getBlock(container, fileId) {
94
- if (!this.containers[container]) {
95
- throw new bucket.FileNotFoundError(
96
- `File '${fileId}' not found - container '${container}' does not exists`
97
- );
98
- }
99
- return this.containers[container].getBlockBlobClient(fileId);
100
- }
101
- onStart = core.$hook({
102
- name: "start",
103
- handler: async () => {
104
- for (const bucket of this.bucketProvider.getBuckets()) {
105
- const containerName = bucket.name.replaceAll("/", "-").toLowerCase();
106
- this.log.debug(`Prepare container ${containerName}...`);
107
- if (!this.containers[containerName]) {
108
- this.containers[containerName] = await this.createContainerClient(containerName);
109
- }
110
- this.log.info(`Container ${bucket} OK`);
111
- }
112
- }
113
- });
114
- async createContainerClient(name) {
115
- const container = this.blobServiceClient.getContainerClient(name);
116
- await this.dateTimeProvider.deadline(
117
- (abortSignal) => container.createIfNotExists({ abortSignal }),
118
- [5, "seconds"]
119
- );
120
- return container;
121
- }
122
- createId() {
123
- return node_crypto.randomUUID();
124
- }
125
- }
31
+ //#region src/providers/AzureFileStorageProvider.ts
32
+ const envSchema = __alepha_core.t.object({ AZ_STORAGE_CONNECTION_STRING: __alepha_core.t.string({
33
+ size: "long",
34
+ default: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
35
+ }) });
36
+ var AzureFileStorageProvider = class {
37
+ log = (0, __alepha_core.$logger)();
38
+ env = (0, __alepha_core.$env)(envSchema);
39
+ bucketProvider = (0, __alepha_core.$inject)(__alepha_bucket.BucketDescriptorProvider);
40
+ dateTimeProvider = (0, __alepha_core.$inject)(__alepha_datetime.DateTimeProvider);
41
+ containers = {};
42
+ blobServiceClient;
43
+ options = {};
44
+ constructor() {
45
+ this.blobServiceClient = __azure_storage_blob.BlobServiceClient.fromConnectionString(this.env.AZ_STORAGE_CONNECTION_STRING, this.storagePipelineOptions());
46
+ }
47
+ storagePipelineOptions() {
48
+ return {};
49
+ }
50
+ async createContainer(containerName) {
51
+ if (this.containers[containerName]) return this.containers[containerName];
52
+ const container = await this.createContainerClient(containerName);
53
+ this.containers[containerName] = container;
54
+ return container;
55
+ }
56
+ async upload(bucketName, file$1, fileId) {
57
+ fileId ??= this.createId();
58
+ const block = this.getBlock(bucketName, fileId);
59
+ const metadata = {
60
+ name: file$1.name,
61
+ type: file$1.type
62
+ };
63
+ if (file$1.filepath) await block.uploadFile(file$1.filepath, {
64
+ metadata,
65
+ blobHTTPHeaders: { blobContentType: file$1.type }
66
+ });
67
+ else if (file$1.size > 0) await block.uploadData(await file$1.arrayBuffer(), {
68
+ metadata,
69
+ blobHTTPHeaders: { blobContentType: file$1.type }
70
+ });
71
+ else throw new Error("Raw stream upload is not supported yet");
72
+ return fileId;
73
+ }
74
+ async download(bucketName, fileId) {
75
+ const block = this.getBlock(bucketName, fileId);
76
+ const blob = await block.download().catch((error) => {
77
+ if (error instanceof Error) throw new __alepha_bucket.FileNotFoundError("Error downloading file", { cause: error });
78
+ throw error;
79
+ });
80
+ if (!blob.readableStreamBody) throw new __alepha_bucket.FileNotFoundError("File not found - empty stream body");
81
+ return (0, __alepha_file.file)(blob.readableStreamBody, blob.metadata);
82
+ }
83
+ async exists(bucketName, fileId) {
84
+ return await this.getBlock(bucketName, fileId).exists();
85
+ }
86
+ async delete(bucketName, fileId) {
87
+ try {
88
+ await this.getBlock(bucketName, fileId).delete();
89
+ } catch (error) {
90
+ if (error instanceof Error) throw new __alepha_bucket.FileNotFoundError("Error deleting file", { cause: error });
91
+ throw error;
92
+ }
93
+ }
94
+ getBlock(container, fileId) {
95
+ if (!this.containers[container]) throw new __alepha_bucket.FileNotFoundError(`File '${fileId}' not found - container '${container}' does not exists`);
96
+ return this.containers[container].getBlockBlobClient(fileId);
97
+ }
98
+ onStart = (0, __alepha_core.$hook)({
99
+ name: "start",
100
+ handler: async () => {
101
+ for (const bucket of this.bucketProvider.getBuckets()) {
102
+ const containerName = bucket.name.replaceAll("/", "-").toLowerCase();
103
+ this.log.debug(`Prepare container ${containerName}...`);
104
+ if (!this.containers[containerName]) this.containers[containerName] = await this.createContainerClient(containerName);
105
+ this.log.info(`Container ${bucket} OK`);
106
+ }
107
+ }
108
+ });
109
+ async createContainerClient(name) {
110
+ const container = this.blobServiceClient.getContainerClient(name);
111
+ await this.dateTimeProvider.deadline((abortSignal) => container.createIfNotExists({ abortSignal }), [5, "seconds"]);
112
+ return container;
113
+ }
114
+ createId() {
115
+ return (0, node_crypto.randomUUID)();
116
+ }
117
+ };
126
118
 
127
- class AlephaBucketAzure {
128
- name = "alepha.bucket.azure";
129
- $services = (alepha) => alepha.with({
130
- provide: bucket.FileStorageProvider,
131
- use: AzureFileStorageProvider,
132
- optional: true
133
- }).with(bucket.AlephaBucket);
134
- }
119
+ //#endregion
120
+ //#region src/index.ts
121
+ /**
122
+ * Alepha Bucket Azure Module
123
+ *
124
+ * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.
125
+ *
126
+ * @see {@link AzureFileStorageProvider}
127
+ * @module alepha.bucket.azure
128
+ */
129
+ var AlephaBucketAzure = class {
130
+ name = "alepha.bucket.azure";
131
+ $services = (alepha) => alepha.with({
132
+ provide: __alepha_bucket.FileStorageProvider,
133
+ use: AzureFileStorageProvider,
134
+ optional: true
135
+ }).with(__alepha_bucket.AlephaBucket);
136
+ };
135
137
 
138
+ //#endregion
136
139
  exports.AlephaBucketAzure = AlephaBucketAzure;
137
140
  exports.AzureFileStorageProvider = AzureFileStorageProvider;
141
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["BucketDescriptorProvider","DateTimeProvider","containerName: string","bucketName: string","file: FileLike","fileId?: string","file","fileId: string","FileNotFoundError","container: string","name: string","alepha: Alepha","FileStorageProvider","AlephaBucket"],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n\tBucketDescriptorProvider,\n\tFileNotFoundError,\n\ttype FileStorageProvider,\n} from \"@alepha/bucket\";\nimport type { Static } from \"@alepha/core\";\nimport { $env, $hook, $inject, $logger, type FileLike, t } from \"@alepha/core\";\nimport { DateTimeProvider } from \"@alepha/datetime\";\nimport { file } from \"@alepha/file\";\nimport {\n\tBlobServiceClient,\n\ttype BlockBlobClient,\n\ttype ContainerClient,\n\ttype StoragePipelineOptions,\n} from \"@azure/storage-blob\";\n\nconst envSchema = t.object({\n\tAZ_STORAGE_CONNECTION_STRING: t.string({\n\t\tsize: \"long\",\n\t\tdefault:\n\t\t\t\"DefaultEndpointsProtocol=http;\" +\n\t\t\t\"AccountName=devstoreaccount1;\" +\n\t\t\t\"AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;\" +\n\t\t\t\"BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;\",\n\t}),\n});\n\ndeclare module \"@alepha/core\" {\n\tinterface Env extends Partial<Static<typeof envSchema>> {}\n}\n\nexport class AzureFileStorageProvider implements FileStorageProvider {\n\tprotected readonly log = $logger();\n\tprotected readonly env = $env(envSchema);\n\tprotected readonly bucketProvider = $inject(BucketDescriptorProvider);\n\tprotected readonly dateTimeProvider = $inject(DateTimeProvider);\n\tprotected readonly containers: Record<string, ContainerClient> = {};\n\tprotected readonly blobServiceClient: BlobServiceClient;\n\tprotected readonly options: StoragePipelineOptions = {};\n\n\tconstructor() {\n\t\tthis.blobServiceClient = BlobServiceClient.fromConnectionString(\n\t\t\tthis.env.AZ_STORAGE_CONNECTION_STRING,\n\t\t\tthis.storagePipelineOptions(),\n\t\t);\n\t}\n\n\tpublic storagePipelineOptions(): StoragePipelineOptions {\n\t\treturn {};\n\t}\n\n\tpublic async createContainer(\n\t\tcontainerName: string,\n\t): Promise<ContainerClient> {\n\t\tif (this.containers[containerName]) {\n\t\t\treturn this.containers[containerName];\n\t\t}\n\t\tconst container = await this.createContainerClient(containerName);\n\t\tthis.containers[containerName] = container;\n\t\treturn container;\n\t}\n\n\tpublic async upload(\n\t\tbucketName: string,\n\t\tfile: FileLike,\n\t\tfileId?: string,\n\t): Promise<string> {\n\t\tfileId ??= this.createId();\n\t\tconst block = this.getBlock(bucketName, fileId);\n\n\t\tconst metadata = {\n\t\t\tname: file.name,\n\t\t\ttype: file.type,\n\t\t};\n\n\t\tif (file.filepath) {\n\t\t\tawait block.uploadFile(file.filepath, {\n\t\t\t\tmetadata,\n\t\t\t\tblobHTTPHeaders: {\n\t\t\t\t\tblobContentType: file.type,\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (file.size > 0) {\n\t\t\tawait block.uploadData(await file.arrayBuffer(), {\n\t\t\t\tmetadata,\n\t\t\t\tblobHTTPHeaders: {\n\t\t\t\t\tblobContentType: file.type,\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new Error(\"Raw stream upload is not supported yet\");\n\t\t}\n\n\t\treturn fileId;\n\t}\n\n\tpublic async download(bucketName: string, fileId: string): Promise<FileLike> {\n\t\tconst block = this.getBlock(bucketName, fileId);\n\n\t\tconst blob = await block.download().catch((error) => {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow new FileNotFoundError(\"Error downloading file\", { cause: error });\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t});\n\n\t\tif (!blob.readableStreamBody) {\n\t\t\tthrow new FileNotFoundError(\"File not found - empty stream body\");\n\t\t}\n\n\t\treturn file(blob.readableStreamBody, blob.metadata);\n\t}\n\n\tpublic async exists(bucketName: string, fileId: string): Promise<boolean> {\n\t\treturn await this.getBlock(bucketName, fileId).exists();\n\t}\n\n\tpublic async delete(bucketName: string, fileId: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.getBlock(bucketName, fileId).delete();\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow new FileNotFoundError(\"Error deleting file\", { cause: error });\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getBlock(container: string, fileId: string): BlockBlobClient {\n\t\tif (!this.containers[container]) {\n\t\t\tthrow new FileNotFoundError(\n\t\t\t\t`File '${fileId}' not found - container '${container}' does not exists`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.containers[container].getBlockBlobClient(fileId);\n\t}\n\n\tpublic readonly onStart = $hook({\n\t\tname: \"start\",\n\t\thandler: async () => {\n\t\t\tfor (const bucket of this.bucketProvider.getBuckets()) {\n\t\t\t\tconst containerName = bucket.name.replaceAll(\"/\", \"-\").toLowerCase();\n\t\t\t\tthis.log.debug(`Prepare container ${containerName}...`);\n\n\t\t\t\tif (!this.containers[containerName]) {\n\t\t\t\t\tthis.containers[containerName] =\n\t\t\t\t\t\tawait this.createContainerClient(containerName);\n\t\t\t\t}\n\n\t\t\t\tthis.log.info(`Container ${bucket} OK`);\n\t\t\t}\n\t\t},\n\t});\n\n\tprotected async createContainerClient(\n\t\tname: string,\n\t): Promise<ContainerClient> {\n\t\tconst container = this.blobServiceClient.getContainerClient(name);\n\n\t\tawait this.dateTimeProvider.deadline(\n\t\t\t(abortSignal) => container.createIfNotExists({ abortSignal }),\n\t\t\t[5, \"seconds\"],\n\t\t);\n\n\t\treturn container;\n\t}\n\n\tprotected createId(): string {\n\t\treturn randomUUID();\n\t}\n}\n","import { AlephaBucket, FileStorageProvider } from \"@alepha/bucket\";\nimport type { Alepha, Module } from \"@alepha/core\";\nimport { AzureFileStorageProvider } from \"./providers/AzureFileStorageProvider.ts\";\n\nexport * from \"./providers/AzureFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Alepha Bucket Azure Module\n *\n * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.\n *\n * @see {@link AzureFileStorageProvider}\n * @module alepha.bucket.azure\n */\nexport class AlephaBucketAzure implements Module {\n\tpublic readonly name = \"alepha.bucket.azure\";\n\tpublic readonly $services = (alepha: Alepha) =>\n\t\talepha\n\t\t\t.with({\n\t\t\t\tprovide: FileStorageProvider,\n\t\t\t\tuse: AzureFileStorageProvider,\n\t\t\t\toptional: true,\n\t\t\t})\n\t\t\t.with(AlephaBucket);\n}\n"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import * as _alepha_core1 from "@alepha/core";
2
+ import { Alepha, FileLike, Module, Static } from "@alepha/core";
3
+ import * as _sinclair_typebox0 from "@sinclair/typebox";
4
+ import { BucketDescriptorProvider, FileStorageProvider } from "@alepha/bucket";
5
+ import { DateTimeProvider } from "@alepha/datetime";
6
+ import { BlobServiceClient, BlockBlobClient, ContainerClient, StoragePipelineOptions } from "@azure/storage-blob";
7
+
8
+ //#region src/providers/AzureFileStorageProvider.d.ts
9
+ declare const envSchema: _alepha_core1.TObject<{
10
+ AZ_STORAGE_CONNECTION_STRING: _sinclair_typebox0.TString;
11
+ }>;
12
+ declare module "@alepha/core" {
13
+ interface Env extends Partial<Static<typeof envSchema>> {}
14
+ }
15
+ declare class AzureFileStorageProvider implements FileStorageProvider {
16
+ protected readonly log: _alepha_core1.Logger;
17
+ protected readonly env: {
18
+ AZ_STORAGE_CONNECTION_STRING: string;
19
+ };
20
+ protected readonly bucketProvider: BucketDescriptorProvider;
21
+ protected readonly dateTimeProvider: DateTimeProvider;
22
+ protected readonly containers: Record<string, ContainerClient>;
23
+ protected readonly blobServiceClient: BlobServiceClient;
24
+ protected readonly options: StoragePipelineOptions;
25
+ constructor();
26
+ storagePipelineOptions(): StoragePipelineOptions;
27
+ createContainer(containerName: string): Promise<ContainerClient>;
28
+ upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
29
+ download(bucketName: string, fileId: string): Promise<FileLike>;
30
+ exists(bucketName: string, fileId: string): Promise<boolean>;
31
+ delete(bucketName: string, fileId: string): Promise<void>;
32
+ getBlock(container: string, fileId: string): BlockBlobClient;
33
+ readonly onStart: _alepha_core1.HookDescriptor<"start">;
34
+ protected createContainerClient(name: string): Promise<ContainerClient>;
35
+ protected createId(): string;
36
+ }
37
+ //#endregion
38
+ //#region src/index.d.ts
39
+ /**
40
+ * Alepha Bucket Azure Module
41
+ *
42
+ * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.
43
+ *
44
+ * @see {@link AzureFileStorageProvider}
45
+ * @module alepha.bucket.azure
46
+ */
47
+ declare class AlephaBucketAzure implements Module {
48
+ readonly name = "alepha.bucket.azure";
49
+ readonly $services: (alepha: Alepha) => Alepha;
50
+ }
51
+ //#endregion
52
+ export { AlephaBucketAzure, AzureFileStorageProvider };
53
+ //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,99 +1,41 @@
1
- import * as _alepha_core from '@alepha/core';
2
- import { Static, FileLike, Module, Alepha } from '@alepha/core';
3
- import { FileStorageProvider, BucketDescriptorProvider } from '@alepha/bucket';
4
- import { DateTimeProvider } from '@alepha/datetime';
5
- import { ContainerClient, BlobServiceClient, StoragePipelineOptions, BlockBlobClient } from '@azure/storage-blob';
1
+ import { BucketDescriptorProvider, FileStorageProvider } from "@alepha/bucket";
2
+ import * as _alepha_core1 from "@alepha/core";
3
+ import { Alepha, FileLike, Module, Static } from "@alepha/core";
4
+ import { DateTimeProvider } from "@alepha/datetime";
5
+ import { BlobServiceClient, BlockBlobClient, ContainerClient, StoragePipelineOptions } from "@azure/storage-blob";
6
+ import * as _sinclair_typebox0 from "@sinclair/typebox";
6
7
 
7
- /** Symbol key applied to readonly types */
8
- declare const ReadonlyKind: unique symbol;
9
- /** Symbol key applied to optional types */
10
- declare const OptionalKind: unique symbol;
11
- /** Symbol key applied to types */
12
- declare const Hint: unique symbol;
13
- /** Symbol key applied to types */
14
- declare const Kind: unique symbol;
15
-
16
- type StringFormatOption = 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex' | ({} & string);
17
- type StringContentEncodingOption = '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' | ({} & string);
18
- interface StringOptions extends SchemaOptions {
19
- /** The maximum string length */
20
- maxLength?: number;
21
- /** The minimum string length */
22
- minLength?: number;
23
- /** A regular expression pattern this string should match */
24
- pattern?: string;
25
- /** A format this string should match */
26
- format?: StringFormatOption;
27
- /** The content encoding for this string */
28
- contentEncoding?: StringContentEncodingOption;
29
- /** The content media type for this string */
30
- contentMediaType?: string;
31
- }
32
- interface TString extends TSchema, StringOptions {
33
- [Kind]: 'String';
34
- static: string;
35
- type: 'string';
36
- }
37
-
38
- interface SchemaOptions {
39
- $schema?: string;
40
- /** Id for this schema */
41
- $id?: string;
42
- /** Title of this schema */
43
- title?: string;
44
- /** Description of this schema */
45
- description?: string;
46
- /** Default value for this schema */
47
- default?: any;
48
- /** Example values matching this schema */
49
- examples?: any;
50
- /** Optional annotation for readOnly */
51
- readOnly?: boolean;
52
- /** Optional annotation for writeOnly */
53
- writeOnly?: boolean;
54
- [prop: string]: any;
55
- }
56
- interface TKind {
57
- [Kind]: string;
58
- }
59
- interface TSchema extends TKind, SchemaOptions {
60
- [ReadonlyKind]?: string;
61
- [OptionalKind]?: string;
62
- [Hint]?: string;
63
- params: unknown[];
64
- static: unknown;
65
- }
66
-
67
- declare const envSchema: _alepha_core.TObject<{
68
- AZ_STORAGE_CONNECTION_STRING: TString;
8
+ //#region src/providers/AzureFileStorageProvider.d.ts
9
+ declare const envSchema: _alepha_core1.TObject<{
10
+ AZ_STORAGE_CONNECTION_STRING: _sinclair_typebox0.TString;
69
11
  }>;
70
12
  declare module "@alepha/core" {
71
- interface Env extends Partial<Static<typeof envSchema>> {
72
- }
13
+ interface Env extends Partial<Static<typeof envSchema>> {}
73
14
  }
74
15
  declare class AzureFileStorageProvider implements FileStorageProvider {
75
- protected readonly log: _alepha_core.Logger;
76
- protected readonly env: {
77
- AZ_STORAGE_CONNECTION_STRING: string;
78
- };
79
- protected readonly bucketProvider: BucketDescriptorProvider;
80
- protected readonly dateTimeProvider: DateTimeProvider;
81
- protected readonly containers: Record<string, ContainerClient>;
82
- protected readonly blobServiceClient: BlobServiceClient;
83
- protected readonly options: StoragePipelineOptions;
84
- constructor();
85
- storagePipelineOptions(): StoragePipelineOptions;
86
- createContainer(containerName: string): Promise<ContainerClient>;
87
- upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
88
- download(bucketName: string, fileId: string): Promise<FileLike>;
89
- exists(bucketName: string, fileId: string): Promise<boolean>;
90
- delete(bucketName: string, fileId: string): Promise<void>;
91
- getBlock(container: string, fileId: string): BlockBlobClient;
92
- readonly onStart: _alepha_core.HookDescriptor<"start">;
93
- protected createContainerClient(name: string): Promise<ContainerClient>;
94
- protected createId(): string;
95
- }
96
-
16
+ protected readonly log: _alepha_core1.Logger;
17
+ protected readonly env: {
18
+ AZ_STORAGE_CONNECTION_STRING: string;
19
+ };
20
+ protected readonly bucketProvider: BucketDescriptorProvider;
21
+ protected readonly dateTimeProvider: DateTimeProvider;
22
+ protected readonly containers: Record<string, ContainerClient>;
23
+ protected readonly blobServiceClient: BlobServiceClient;
24
+ protected readonly options: StoragePipelineOptions;
25
+ constructor();
26
+ storagePipelineOptions(): StoragePipelineOptions;
27
+ createContainer(containerName: string): Promise<ContainerClient>;
28
+ upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
29
+ download(bucketName: string, fileId: string): Promise<FileLike>;
30
+ exists(bucketName: string, fileId: string): Promise<boolean>;
31
+ delete(bucketName: string, fileId: string): Promise<void>;
32
+ getBlock(container: string, fileId: string): BlockBlobClient;
33
+ readonly onStart: _alepha_core1.HookDescriptor<"start">;
34
+ protected createContainerClient(name: string): Promise<ContainerClient>;
35
+ protected createId(): string;
36
+ }
37
+ //#endregion
38
+ //#region src/index.d.ts
97
39
  /**
98
40
  * Alepha Bucket Azure Module
99
41
  *
@@ -103,8 +45,9 @@ declare class AzureFileStorageProvider implements FileStorageProvider {
103
45
  * @module alepha.bucket.azure
104
46
  */
105
47
  declare class AlephaBucketAzure implements Module {
106
- readonly name = "alepha.bucket.azure";
107
- readonly $services: (alepha: Alepha) => Alepha;
48
+ readonly name = "alepha.bucket.azure";
49
+ readonly $services: (alepha: Alepha) => Alepha;
108
50
  }
109
-
51
+ //#endregion
110
52
  export { AlephaBucketAzure, AzureFileStorageProvider };
53
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,134 +1,117 @@
1
- import { BucketDescriptorProvider, FileNotFoundError, FileStorageProvider, AlephaBucket } from '@alepha/bucket';
2
- import { randomUUID } from 'node:crypto';
3
- import { t, $logger, $env, $inject, $hook } from '@alepha/core';
4
- import { DateTimeProvider } from '@alepha/datetime';
5
- import { file } from '@alepha/file';
6
- import { BlobServiceClient } from '@azure/storage-blob';
1
+ import { AlephaBucket, BucketDescriptorProvider, FileNotFoundError, FileStorageProvider } from "@alepha/bucket";
2
+ import { randomUUID } from "node:crypto";
3
+ import { $env, $hook, $inject, $logger, t } from "@alepha/core";
4
+ import { DateTimeProvider } from "@alepha/datetime";
5
+ import { file } from "@alepha/file";
6
+ import { BlobServiceClient } from "@azure/storage-blob";
7
7
 
8
- const envSchema = t.object({
9
- AZ_STORAGE_CONNECTION_STRING: t.string({
10
- size: "long",
11
- default: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
12
- })
13
- });
14
- class AzureFileStorageProvider {
15
- log = $logger();
16
- env = $env(envSchema);
17
- bucketProvider = $inject(BucketDescriptorProvider);
18
- dateTimeProvider = $inject(DateTimeProvider);
19
- containers = {};
20
- blobServiceClient;
21
- options = {};
22
- constructor() {
23
- this.blobServiceClient = BlobServiceClient.fromConnectionString(
24
- this.env.AZ_STORAGE_CONNECTION_STRING,
25
- this.storagePipelineOptions()
26
- );
27
- }
28
- storagePipelineOptions() {
29
- return {};
30
- }
31
- async createContainer(containerName) {
32
- if (this.containers[containerName]) {
33
- return this.containers[containerName];
34
- }
35
- const container = await this.createContainerClient(containerName);
36
- this.containers[containerName] = container;
37
- return container;
38
- }
39
- async upload(bucketName, file2, fileId) {
40
- fileId ??= this.createId();
41
- const block = this.getBlock(bucketName, fileId);
42
- const metadata = {
43
- name: file2.name,
44
- type: file2.type
45
- };
46
- if (file2.filepath) {
47
- await block.uploadFile(file2.filepath, {
48
- metadata,
49
- blobHTTPHeaders: {
50
- blobContentType: file2.type
51
- }
52
- });
53
- } else if (file2.size > 0) {
54
- await block.uploadData(await file2.arrayBuffer(), {
55
- metadata,
56
- blobHTTPHeaders: {
57
- blobContentType: file2.type
58
- }
59
- });
60
- } else {
61
- throw new Error("Raw stream upload is not supported yet");
62
- }
63
- return fileId;
64
- }
65
- async download(bucketName, fileId) {
66
- const block = this.getBlock(bucketName, fileId);
67
- const blob = await block.download().catch((error) => {
68
- if (error instanceof Error) {
69
- throw new FileNotFoundError("Error downloading file", { cause: error });
70
- }
71
- throw error;
72
- });
73
- if (!blob.readableStreamBody) {
74
- throw new FileNotFoundError("File not found - empty stream body");
75
- }
76
- return file(blob.readableStreamBody, blob.metadata);
77
- }
78
- async exists(bucketName, fileId) {
79
- return await this.getBlock(bucketName, fileId).exists();
80
- }
81
- async delete(bucketName, fileId) {
82
- try {
83
- await this.getBlock(bucketName, fileId).delete();
84
- } catch (error) {
85
- if (error instanceof Error) {
86
- throw new FileNotFoundError("Error deleting file", { cause: error });
87
- }
88
- throw error;
89
- }
90
- }
91
- getBlock(container, fileId) {
92
- if (!this.containers[container]) {
93
- throw new FileNotFoundError(
94
- `File '${fileId}' not found - container '${container}' does not exists`
95
- );
96
- }
97
- return this.containers[container].getBlockBlobClient(fileId);
98
- }
99
- onStart = $hook({
100
- name: "start",
101
- handler: async () => {
102
- for (const bucket of this.bucketProvider.getBuckets()) {
103
- const containerName = bucket.name.replaceAll("/", "-").toLowerCase();
104
- this.log.debug(`Prepare container ${containerName}...`);
105
- if (!this.containers[containerName]) {
106
- this.containers[containerName] = await this.createContainerClient(containerName);
107
- }
108
- this.log.info(`Container ${bucket} OK`);
109
- }
110
- }
111
- });
112
- async createContainerClient(name) {
113
- const container = this.blobServiceClient.getContainerClient(name);
114
- await this.dateTimeProvider.deadline(
115
- (abortSignal) => container.createIfNotExists({ abortSignal }),
116
- [5, "seconds"]
117
- );
118
- return container;
119
- }
120
- createId() {
121
- return randomUUID();
122
- }
123
- }
8
+ //#region src/providers/AzureFileStorageProvider.ts
9
+ const envSchema = t.object({ AZ_STORAGE_CONNECTION_STRING: t.string({
10
+ size: "long",
11
+ default: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
12
+ }) });
13
+ var AzureFileStorageProvider = class {
14
+ log = $logger();
15
+ env = $env(envSchema);
16
+ bucketProvider = $inject(BucketDescriptorProvider);
17
+ dateTimeProvider = $inject(DateTimeProvider);
18
+ containers = {};
19
+ blobServiceClient;
20
+ options = {};
21
+ constructor() {
22
+ this.blobServiceClient = BlobServiceClient.fromConnectionString(this.env.AZ_STORAGE_CONNECTION_STRING, this.storagePipelineOptions());
23
+ }
24
+ storagePipelineOptions() {
25
+ return {};
26
+ }
27
+ async createContainer(containerName) {
28
+ if (this.containers[containerName]) return this.containers[containerName];
29
+ const container = await this.createContainerClient(containerName);
30
+ this.containers[containerName] = container;
31
+ return container;
32
+ }
33
+ async upload(bucketName, file$1, fileId) {
34
+ fileId ??= this.createId();
35
+ const block = this.getBlock(bucketName, fileId);
36
+ const metadata = {
37
+ name: file$1.name,
38
+ type: file$1.type
39
+ };
40
+ if (file$1.filepath) await block.uploadFile(file$1.filepath, {
41
+ metadata,
42
+ blobHTTPHeaders: { blobContentType: file$1.type }
43
+ });
44
+ else if (file$1.size > 0) await block.uploadData(await file$1.arrayBuffer(), {
45
+ metadata,
46
+ blobHTTPHeaders: { blobContentType: file$1.type }
47
+ });
48
+ else throw new Error("Raw stream upload is not supported yet");
49
+ return fileId;
50
+ }
51
+ async download(bucketName, fileId) {
52
+ const block = this.getBlock(bucketName, fileId);
53
+ const blob = await block.download().catch((error) => {
54
+ if (error instanceof Error) throw new FileNotFoundError("Error downloading file", { cause: error });
55
+ throw error;
56
+ });
57
+ if (!blob.readableStreamBody) throw new FileNotFoundError("File not found - empty stream body");
58
+ return file(blob.readableStreamBody, blob.metadata);
59
+ }
60
+ async exists(bucketName, fileId) {
61
+ return await this.getBlock(bucketName, fileId).exists();
62
+ }
63
+ async delete(bucketName, fileId) {
64
+ try {
65
+ await this.getBlock(bucketName, fileId).delete();
66
+ } catch (error) {
67
+ if (error instanceof Error) throw new FileNotFoundError("Error deleting file", { cause: error });
68
+ throw error;
69
+ }
70
+ }
71
+ getBlock(container, fileId) {
72
+ if (!this.containers[container]) throw new FileNotFoundError(`File '${fileId}' not found - container '${container}' does not exists`);
73
+ return this.containers[container].getBlockBlobClient(fileId);
74
+ }
75
+ onStart = $hook({
76
+ name: "start",
77
+ handler: async () => {
78
+ for (const bucket of this.bucketProvider.getBuckets()) {
79
+ const containerName = bucket.name.replaceAll("/", "-").toLowerCase();
80
+ this.log.debug(`Prepare container ${containerName}...`);
81
+ if (!this.containers[containerName]) this.containers[containerName] = await this.createContainerClient(containerName);
82
+ this.log.info(`Container ${bucket} OK`);
83
+ }
84
+ }
85
+ });
86
+ async createContainerClient(name) {
87
+ const container = this.blobServiceClient.getContainerClient(name);
88
+ await this.dateTimeProvider.deadline((abortSignal) => container.createIfNotExists({ abortSignal }), [5, "seconds"]);
89
+ return container;
90
+ }
91
+ createId() {
92
+ return randomUUID();
93
+ }
94
+ };
124
95
 
125
- class AlephaBucketAzure {
126
- name = "alepha.bucket.azure";
127
- $services = (alepha) => alepha.with({
128
- provide: FileStorageProvider,
129
- use: AzureFileStorageProvider,
130
- optional: true
131
- }).with(AlephaBucket);
132
- }
96
+ //#endregion
97
+ //#region src/index.ts
98
+ /**
99
+ * Alepha Bucket Azure Module
100
+ *
101
+ * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.
102
+ *
103
+ * @see {@link AzureFileStorageProvider}
104
+ * @module alepha.bucket.azure
105
+ */
106
+ var AlephaBucketAzure = class {
107
+ name = "alepha.bucket.azure";
108
+ $services = (alepha) => alepha.with({
109
+ provide: FileStorageProvider,
110
+ use: AzureFileStorageProvider,
111
+ optional: true
112
+ }).with(AlephaBucket);
113
+ };
133
114
 
115
+ //#endregion
134
116
  export { AlephaBucketAzure, AzureFileStorageProvider };
117
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["containerName: string","bucketName: string","file: FileLike","fileId?: string","file","fileId: string","container: string","name: string","alepha: Alepha"],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n\tBucketDescriptorProvider,\n\tFileNotFoundError,\n\ttype FileStorageProvider,\n} from \"@alepha/bucket\";\nimport type { Static } from \"@alepha/core\";\nimport { $env, $hook, $inject, $logger, type FileLike, t } from \"@alepha/core\";\nimport { DateTimeProvider } from \"@alepha/datetime\";\nimport { file } from \"@alepha/file\";\nimport {\n\tBlobServiceClient,\n\ttype BlockBlobClient,\n\ttype ContainerClient,\n\ttype StoragePipelineOptions,\n} from \"@azure/storage-blob\";\n\nconst envSchema = t.object({\n\tAZ_STORAGE_CONNECTION_STRING: t.string({\n\t\tsize: \"long\",\n\t\tdefault:\n\t\t\t\"DefaultEndpointsProtocol=http;\" +\n\t\t\t\"AccountName=devstoreaccount1;\" +\n\t\t\t\"AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;\" +\n\t\t\t\"BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;\",\n\t}),\n});\n\ndeclare module \"@alepha/core\" {\n\tinterface Env extends Partial<Static<typeof envSchema>> {}\n}\n\nexport class AzureFileStorageProvider implements FileStorageProvider {\n\tprotected readonly log = $logger();\n\tprotected readonly env = $env(envSchema);\n\tprotected readonly bucketProvider = $inject(BucketDescriptorProvider);\n\tprotected readonly dateTimeProvider = $inject(DateTimeProvider);\n\tprotected readonly containers: Record<string, ContainerClient> = {};\n\tprotected readonly blobServiceClient: BlobServiceClient;\n\tprotected readonly options: StoragePipelineOptions = {};\n\n\tconstructor() {\n\t\tthis.blobServiceClient = BlobServiceClient.fromConnectionString(\n\t\t\tthis.env.AZ_STORAGE_CONNECTION_STRING,\n\t\t\tthis.storagePipelineOptions(),\n\t\t);\n\t}\n\n\tpublic storagePipelineOptions(): StoragePipelineOptions {\n\t\treturn {};\n\t}\n\n\tpublic async createContainer(\n\t\tcontainerName: string,\n\t): Promise<ContainerClient> {\n\t\tif (this.containers[containerName]) {\n\t\t\treturn this.containers[containerName];\n\t\t}\n\t\tconst container = await this.createContainerClient(containerName);\n\t\tthis.containers[containerName] = container;\n\t\treturn container;\n\t}\n\n\tpublic async upload(\n\t\tbucketName: string,\n\t\tfile: FileLike,\n\t\tfileId?: string,\n\t): Promise<string> {\n\t\tfileId ??= this.createId();\n\t\tconst block = this.getBlock(bucketName, fileId);\n\n\t\tconst metadata = {\n\t\t\tname: file.name,\n\t\t\ttype: file.type,\n\t\t};\n\n\t\tif (file.filepath) {\n\t\t\tawait block.uploadFile(file.filepath, {\n\t\t\t\tmetadata,\n\t\t\t\tblobHTTPHeaders: {\n\t\t\t\t\tblobContentType: file.type,\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (file.size > 0) {\n\t\t\tawait block.uploadData(await file.arrayBuffer(), {\n\t\t\t\tmetadata,\n\t\t\t\tblobHTTPHeaders: {\n\t\t\t\t\tblobContentType: file.type,\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new Error(\"Raw stream upload is not supported yet\");\n\t\t}\n\n\t\treturn fileId;\n\t}\n\n\tpublic async download(bucketName: string, fileId: string): Promise<FileLike> {\n\t\tconst block = this.getBlock(bucketName, fileId);\n\n\t\tconst blob = await block.download().catch((error) => {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow new FileNotFoundError(\"Error downloading file\", { cause: error });\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t});\n\n\t\tif (!blob.readableStreamBody) {\n\t\t\tthrow new FileNotFoundError(\"File not found - empty stream body\");\n\t\t}\n\n\t\treturn file(blob.readableStreamBody, blob.metadata);\n\t}\n\n\tpublic async exists(bucketName: string, fileId: string): Promise<boolean> {\n\t\treturn await this.getBlock(bucketName, fileId).exists();\n\t}\n\n\tpublic async delete(bucketName: string, fileId: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.getBlock(bucketName, fileId).delete();\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow new FileNotFoundError(\"Error deleting file\", { cause: error });\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getBlock(container: string, fileId: string): BlockBlobClient {\n\t\tif (!this.containers[container]) {\n\t\t\tthrow new FileNotFoundError(\n\t\t\t\t`File '${fileId}' not found - container '${container}' does not exists`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.containers[container].getBlockBlobClient(fileId);\n\t}\n\n\tpublic readonly onStart = $hook({\n\t\tname: \"start\",\n\t\thandler: async () => {\n\t\t\tfor (const bucket of this.bucketProvider.getBuckets()) {\n\t\t\t\tconst containerName = bucket.name.replaceAll(\"/\", \"-\").toLowerCase();\n\t\t\t\tthis.log.debug(`Prepare container ${containerName}...`);\n\n\t\t\t\tif (!this.containers[containerName]) {\n\t\t\t\t\tthis.containers[containerName] =\n\t\t\t\t\t\tawait this.createContainerClient(containerName);\n\t\t\t\t}\n\n\t\t\t\tthis.log.info(`Container ${bucket} OK`);\n\t\t\t}\n\t\t},\n\t});\n\n\tprotected async createContainerClient(\n\t\tname: string,\n\t): Promise<ContainerClient> {\n\t\tconst container = this.blobServiceClient.getContainerClient(name);\n\n\t\tawait this.dateTimeProvider.deadline(\n\t\t\t(abortSignal) => container.createIfNotExists({ abortSignal }),\n\t\t\t[5, \"seconds\"],\n\t\t);\n\n\t\treturn container;\n\t}\n\n\tprotected createId(): string {\n\t\treturn randomUUID();\n\t}\n}\n","import { AlephaBucket, FileStorageProvider } from \"@alepha/bucket\";\nimport type { Alepha, Module } from \"@alepha/core\";\nimport { AzureFileStorageProvider } from \"./providers/AzureFileStorageProvider.ts\";\n\nexport * from \"./providers/AzureFileStorageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Alepha Bucket Azure Module\n *\n * Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.\n *\n * @see {@link AzureFileStorageProvider}\n * @module alepha.bucket.azure\n */\nexport class AlephaBucketAzure implements Module {\n\tpublic readonly name = \"alepha.bucket.azure\";\n\tpublic readonly $services = (alepha: Alepha) =>\n\t\talepha\n\t\t\t.with({\n\t\t\t\tprovide: FileStorageProvider,\n\t\t\t\tuse: AzureFileStorageProvider,\n\t\t\t\toptional: true,\n\t\t\t})\n\t\t\t.with(AlephaBucket);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -10,8 +10,11 @@
10
10
  "storage-blob"
11
11
  ],
12
12
  "author": "Feunard",
13
- "version": "0.7.5",
13
+ "version": "0.7.7",
14
14
  "type": "module",
15
+ "engines": {
16
+ "node": ">=22.0.0"
17
+ },
15
18
  "license": "MIT",
16
19
  "main": "./dist/index.js",
17
20
  "types": "./dist/index.d.ts",
@@ -20,19 +23,19 @@
20
23
  "src"
21
24
  ],
22
25
  "dependencies": {
23
- "@alepha/bucket": "0.7.5",
24
- "@alepha/core": "0.7.5",
25
- "@alepha/datetime": "0.7.5",
26
- "@alepha/file": "0.7.5",
26
+ "@alepha/bucket": "0.7.7",
27
+ "@alepha/core": "0.7.7",
28
+ "@alepha/datetime": "0.7.7",
29
+ "@alepha/file": "0.7.7",
27
30
  "@azure/storage-blob": "^12.27.0"
28
31
  },
29
32
  "devDependencies": {
30
- "pkgroll": "^2.13.1",
33
+ "tsdown": "^0.12.9",
31
34
  "vitest": "^3.2.4"
32
35
  },
33
36
  "scripts": {
34
37
  "test": "vitest run",
35
- "build": "pkgroll --clean-dist"
38
+ "build": "tsdown -c ../../tsdown.config.ts"
36
39
  },
37
40
  "repository": {
38
41
  "type": "git",