@alepha/bucket-azure 0.13.0 → 0.13.2
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 +82 -82
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/providers/AzureFileStorageProvider.ts +1 -1
- package/dist/chunk-MC1wKe0N.js +0 -27
- package/dist/index.cjs +0 -126
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1998
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import "node:fs";
|
|
|
11
11
|
|
|
12
12
|
//#region ../alepha/src/core/constants/KIND.d.ts
|
|
13
13
|
/**
|
|
14
|
-
* Used for identifying
|
|
14
|
+
* Used for identifying primitives.
|
|
15
15
|
*
|
|
16
16
|
* @internal
|
|
17
17
|
*/
|
|
@@ -64,34 +64,50 @@ interface ServiceSubstitution<T extends object = any> {
|
|
|
64
64
|
*/
|
|
65
65
|
type ServiceEntry<T extends object = any> = Service<T> | ServiceSubstitution<T>;
|
|
66
66
|
//#endregion
|
|
67
|
-
//#region ../alepha/src/core/helpers/
|
|
68
|
-
interface
|
|
67
|
+
//#region ../alepha/src/core/helpers/primitive.d.ts
|
|
68
|
+
interface PrimitiveArgs<T extends object = {}> {
|
|
69
69
|
options: T;
|
|
70
70
|
alepha: Alepha;
|
|
71
71
|
service: InstantiableClass<Service>;
|
|
72
72
|
module?: Service;
|
|
73
73
|
}
|
|
74
|
-
interface
|
|
74
|
+
interface PrimitiveConfig {
|
|
75
75
|
propertyKey: string;
|
|
76
76
|
service: InstantiableClass<Service>;
|
|
77
77
|
module?: Service;
|
|
78
78
|
}
|
|
79
|
-
declare abstract class
|
|
79
|
+
declare abstract class Primitive<T extends object = {}> {
|
|
80
80
|
protected readonly alepha: Alepha;
|
|
81
81
|
readonly options: T;
|
|
82
|
-
readonly config:
|
|
83
|
-
constructor(args:
|
|
82
|
+
readonly config: PrimitiveConfig;
|
|
83
|
+
constructor(args: PrimitiveArgs<T>);
|
|
84
84
|
/**
|
|
85
|
-
* Called automatically by Alepha after the
|
|
85
|
+
* Called automatically by Alepha after the primitive is created.
|
|
86
86
|
*/
|
|
87
87
|
protected onInit(): void;
|
|
88
88
|
}
|
|
89
|
-
type
|
|
89
|
+
type PrimitiveFactoryLike<T extends object = any> = {
|
|
90
90
|
(options: T): any;
|
|
91
91
|
[KIND]: any;
|
|
92
92
|
};
|
|
93
93
|
//#endregion
|
|
94
|
-
//#region ../alepha/src/core/
|
|
94
|
+
//#region ../alepha/src/core/interfaces/Async.d.ts
|
|
95
|
+
/**
|
|
96
|
+
* Represents a value that can be either a value or a promise of value.
|
|
97
|
+
*/
|
|
98
|
+
type Async<T> = T | Promise<T>;
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region ../alepha/src/core/interfaces/LoggerInterface.d.ts
|
|
101
|
+
type LogLevel = "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "SILENT";
|
|
102
|
+
interface LoggerInterface {
|
|
103
|
+
trace(message: string, data?: unknown): void;
|
|
104
|
+
debug(message: string, data?: unknown): void;
|
|
105
|
+
info(message: string, data?: unknown): void;
|
|
106
|
+
warn(message: string, data?: unknown): void;
|
|
107
|
+
error(message: string, data?: unknown): void;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region ../alepha/src/core/primitives/$inject.d.ts
|
|
95
111
|
interface InjectOptions<T extends object = any> {
|
|
96
112
|
/**
|
|
97
113
|
* - 'transient' → Always a new instance on every inject. Zero caching.
|
|
@@ -116,8 +132,8 @@ interface InjectOptions<T extends object = any> {
|
|
|
116
132
|
parent?: Service | null;
|
|
117
133
|
}
|
|
118
134
|
//#endregion
|
|
119
|
-
//#region ../alepha/src/core/
|
|
120
|
-
interface
|
|
135
|
+
//#region ../alepha/src/core/primitives/$module.d.ts
|
|
136
|
+
interface ModulePrimitiveOptions {
|
|
121
137
|
/**
|
|
122
138
|
* Name of the module.
|
|
123
139
|
*
|
|
@@ -132,9 +148,9 @@ interface ModuleDescriptorOptions {
|
|
|
132
148
|
*/
|
|
133
149
|
services?: Array<Service>;
|
|
134
150
|
/**
|
|
135
|
-
* List of $
|
|
151
|
+
* List of $primitives to register in the module.
|
|
136
152
|
*/
|
|
137
|
-
|
|
153
|
+
primitives?: Array<PrimitiveFactoryLike>;
|
|
138
154
|
/**
|
|
139
155
|
* By default, module will register ALL services.
|
|
140
156
|
* You can override this behavior by providing a register function.
|
|
@@ -148,7 +164,7 @@ interface ModuleDescriptorOptions {
|
|
|
148
164
|
* Base class for all modules.
|
|
149
165
|
*/
|
|
150
166
|
declare abstract class Module {
|
|
151
|
-
abstract readonly options:
|
|
167
|
+
abstract readonly options: ModulePrimitiveOptions;
|
|
152
168
|
abstract register(alepha: Alepha): void;
|
|
153
169
|
static NAME_REGEX: RegExp;
|
|
154
170
|
/**
|
|
@@ -163,22 +179,6 @@ declare abstract class Module {
|
|
|
163
179
|
static of(ctor: Service): Service<Module> | undefined;
|
|
164
180
|
}
|
|
165
181
|
//#endregion
|
|
166
|
-
//#region ../alepha/src/core/interfaces/Async.d.ts
|
|
167
|
-
/**
|
|
168
|
-
* Represents a value that can be either a value or a promise of value.
|
|
169
|
-
*/
|
|
170
|
-
type Async<T> = T | Promise<T>;
|
|
171
|
-
//#endregion
|
|
172
|
-
//#region ../alepha/src/core/interfaces/LoggerInterface.d.ts
|
|
173
|
-
type LogLevel = "ERROR" | "WARN" | "INFO" | "DEBUG" | "TRACE" | "SILENT";
|
|
174
|
-
interface LoggerInterface {
|
|
175
|
-
trace(message: string, data?: unknown): void;
|
|
176
|
-
debug(message: string, data?: unknown): void;
|
|
177
|
-
info(message: string, data?: unknown): void;
|
|
178
|
-
warn(message: string, data?: unknown): void;
|
|
179
|
-
error(message: string, data?: unknown): void;
|
|
180
|
-
}
|
|
181
|
-
//#endregion
|
|
182
182
|
//#region ../alepha/src/core/providers/AlsProvider.d.ts
|
|
183
183
|
type AsyncLocalStorageData = any;
|
|
184
184
|
declare class AlsProvider {
|
|
@@ -440,7 +440,7 @@ declare class EventManager {
|
|
|
440
440
|
}): Promise<void>;
|
|
441
441
|
}
|
|
442
442
|
//#endregion
|
|
443
|
-
//#region ../alepha/src/core/
|
|
443
|
+
//#region ../alepha/src/core/primitives/$atom.d.ts
|
|
444
444
|
type AtomOptions<T extends TAtomObject, N extends string> = {
|
|
445
445
|
name: N;
|
|
446
446
|
schema: T;
|
|
@@ -569,7 +569,7 @@ type OnlyArray<T extends object> = { [K in keyof T]: NonNullable<T[K]> extends A
|
|
|
569
569
|
* // You can access the environment variables using alepha.env
|
|
570
570
|
* console.log(alepha.env.MY_VAR); // "value"
|
|
571
571
|
*
|
|
572
|
-
* // But you should use $env()
|
|
572
|
+
* // But you should use $env() primitive to get typed values from the environment.
|
|
573
573
|
* class App {
|
|
574
574
|
* env = $env(
|
|
575
575
|
* t.object({
|
|
@@ -582,7 +582,7 @@ type OnlyArray<T extends object> = { [K in keyof T]: NonNullable<T[K]> extends A
|
|
|
582
582
|
* ### Modules
|
|
583
583
|
*
|
|
584
584
|
* Modules are a way to group services together.
|
|
585
|
-
* You can register a module using the `$module`
|
|
585
|
+
* You can register a module using the `$module` primitive.
|
|
586
586
|
*
|
|
587
587
|
* ```ts
|
|
588
588
|
* import { $module } from "alepha";
|
|
@@ -600,7 +600,7 @@ type OnlyArray<T extends object> = { [K in keyof T]: NonNullable<T[K]> extends A
|
|
|
600
600
|
* ### Hooks
|
|
601
601
|
*
|
|
602
602
|
* Hooks are a way to run async functions from all registered providers/services.
|
|
603
|
-
* You can register a hook using the `$hook`
|
|
603
|
+
* You can register a hook using the `$hook` primitive.
|
|
604
604
|
*
|
|
605
605
|
* ```ts
|
|
606
606
|
* import { $hook } from "alepha";
|
|
@@ -697,9 +697,9 @@ declare class Alepha {
|
|
|
697
697
|
use: Service;
|
|
698
698
|
}>;
|
|
699
699
|
/**
|
|
700
|
-
* Registry of
|
|
700
|
+
* Registry of primitives.
|
|
701
701
|
*/
|
|
702
|
-
protected
|
|
702
|
+
protected primitiveRegistry: Map<Service<Primitive<{}>>, Primitive<{}>[]>;
|
|
703
703
|
/**
|
|
704
704
|
* List of all services + how they are provided.
|
|
705
705
|
*/
|
|
@@ -719,7 +719,7 @@ declare class Alepha {
|
|
|
719
719
|
/**
|
|
720
720
|
* State manager to store arbitrary values.
|
|
721
721
|
*/
|
|
722
|
-
get
|
|
722
|
+
get store(): StateManager<State>;
|
|
723
723
|
/**
|
|
724
724
|
* Codec manager for encoding and decoding data with different formats.
|
|
725
725
|
*
|
|
@@ -792,7 +792,7 @@ declare class Alepha {
|
|
|
792
792
|
* Starts the App.
|
|
793
793
|
*
|
|
794
794
|
* - Lock any further changes to the container.
|
|
795
|
-
* - Run "configure" hook for all services.
|
|
795
|
+
* - Run "configure" hook for all services. Primitives will be processed.
|
|
796
796
|
* - Run "start" hook for all services. Providers will connect/listen/...
|
|
797
797
|
* - Run "ready" hook for all services. This is the point where the App is ready to serve requests.
|
|
798
798
|
*
|
|
@@ -897,13 +897,13 @@ declare class Alepha {
|
|
|
897
897
|
}>;
|
|
898
898
|
services<T extends object>(base: Service<T>): Array<T>;
|
|
899
899
|
/**
|
|
900
|
-
* Get all
|
|
900
|
+
* Get all primitives of the specified type.
|
|
901
901
|
*/
|
|
902
|
-
|
|
903
|
-
[KIND]: InstantiableClass<
|
|
904
|
-
} | string): Array<
|
|
902
|
+
primitives<TPrimitive extends Primitive>(factory: {
|
|
903
|
+
[KIND]: InstantiableClass<TPrimitive>;
|
|
904
|
+
} | string): Array<TPrimitive>;
|
|
905
905
|
protected new<T extends object>(service: Service<T>, args?: any[]): T;
|
|
906
|
-
protected
|
|
906
|
+
protected processPrimitive(value: Primitive, propertyKey?: string): void;
|
|
907
907
|
}
|
|
908
908
|
interface Hook<T extends keyof Hooks = any> {
|
|
909
909
|
caller?: Service;
|
|
@@ -1030,34 +1030,6 @@ interface Hooks {
|
|
|
1030
1030
|
};
|
|
1031
1031
|
}
|
|
1032
1032
|
//#endregion
|
|
1033
|
-
//#region ../alepha/src/core/descriptors/$hook.d.ts
|
|
1034
|
-
interface HookOptions<T extends keyof Hooks> {
|
|
1035
|
-
/**
|
|
1036
|
-
* The name of the hook. "configure", "start", "ready", "stop", ...
|
|
1037
|
-
*/
|
|
1038
|
-
on: T;
|
|
1039
|
-
/**
|
|
1040
|
-
* The handler to run when the hook is triggered.
|
|
1041
|
-
*/
|
|
1042
|
-
handler: (args: Hooks[T]) => Async<any>;
|
|
1043
|
-
/**
|
|
1044
|
-
* Force the hook to run first or last on the list of hooks.
|
|
1045
|
-
*/
|
|
1046
|
-
priority?: "first" | "last";
|
|
1047
|
-
/**
|
|
1048
|
-
* Empty placeholder, not implemented yet. :-)
|
|
1049
|
-
*/
|
|
1050
|
-
before?: object | Array<object>;
|
|
1051
|
-
/**
|
|
1052
|
-
* Empty placeholder, not implemented yet. :-)
|
|
1053
|
-
*/
|
|
1054
|
-
after?: object | Array<object>;
|
|
1055
|
-
}
|
|
1056
|
-
declare class HookDescriptor<T extends keyof Hooks> extends Descriptor<HookOptions<T>> {
|
|
1057
|
-
called: number;
|
|
1058
|
-
protected onInit(): void;
|
|
1059
|
-
}
|
|
1060
|
-
//#endregion
|
|
1061
1033
|
//#region ../alepha/src/core/schemas/pageSchema.d.ts
|
|
1062
1034
|
declare const pageMetadataSchema: TObject$1<{
|
|
1063
1035
|
number: TInteger;
|
|
@@ -1090,6 +1062,34 @@ declare module "alepha" {
|
|
|
1090
1062
|
}
|
|
1091
1063
|
}
|
|
1092
1064
|
//#endregion
|
|
1065
|
+
//#region ../alepha/src/core/primitives/$hook.d.ts
|
|
1066
|
+
interface HookOptions<T extends keyof Hooks> {
|
|
1067
|
+
/**
|
|
1068
|
+
* The name of the hook. "configure", "start", "ready", "stop", ...
|
|
1069
|
+
*/
|
|
1070
|
+
on: T;
|
|
1071
|
+
/**
|
|
1072
|
+
* The handler to run when the hook is triggered.
|
|
1073
|
+
*/
|
|
1074
|
+
handler: (args: Hooks[T]) => Async<any>;
|
|
1075
|
+
/**
|
|
1076
|
+
* Force the hook to run first or last on the list of hooks.
|
|
1077
|
+
*/
|
|
1078
|
+
priority?: "first" | "last";
|
|
1079
|
+
/**
|
|
1080
|
+
* Empty placeholder, not implemented yet. :-)
|
|
1081
|
+
*/
|
|
1082
|
+
before?: object | Array<object>;
|
|
1083
|
+
/**
|
|
1084
|
+
* Empty placeholder, not implemented yet. :-)
|
|
1085
|
+
*/
|
|
1086
|
+
after?: object | Array<object>;
|
|
1087
|
+
}
|
|
1088
|
+
declare class HookPrimitive<T extends keyof Hooks> extends Primitive<HookOptions<T>> {
|
|
1089
|
+
called: number;
|
|
1090
|
+
protected onInit(): void;
|
|
1091
|
+
}
|
|
1092
|
+
//#endregion
|
|
1093
1093
|
//#region ../alepha/src/logger/schemas/logEntrySchema.d.ts
|
|
1094
1094
|
declare const logEntrySchema: TObject$1<{
|
|
1095
1095
|
level: TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
|
|
@@ -1114,8 +1114,8 @@ declare class DateTimeProvider {
|
|
|
1114
1114
|
protected readonly timeouts: Timeout[];
|
|
1115
1115
|
protected readonly intervals: Interval[];
|
|
1116
1116
|
constructor();
|
|
1117
|
-
protected readonly onStart:
|
|
1118
|
-
protected readonly onStop:
|
|
1117
|
+
protected readonly onStart: HookPrimitive<"start">;
|
|
1118
|
+
protected readonly onStop: HookPrimitive<"stop">;
|
|
1119
1119
|
setLocale(locale: string): void;
|
|
1120
1120
|
isDateTime(value: unknown): value is DateTime;
|
|
1121
1121
|
/**
|
|
@@ -1733,8 +1733,8 @@ declare class MemoryFileStorageProvider implements FileStorageProvider {
|
|
|
1733
1733
|
protected createId(): string;
|
|
1734
1734
|
}
|
|
1735
1735
|
//#endregion
|
|
1736
|
-
//#region ../alepha/src/bucket/
|
|
1737
|
-
interface
|
|
1736
|
+
//#region ../alepha/src/bucket/primitives/$bucket.d.ts
|
|
1737
|
+
interface BucketPrimitiveOptions extends BucketFileOptions {
|
|
1738
1738
|
/**
|
|
1739
1739
|
* File storage provider configuration for the bucket.
|
|
1740
1740
|
*
|
|
@@ -1866,7 +1866,7 @@ interface BucketFileOptions {
|
|
|
1866
1866
|
*/
|
|
1867
1867
|
maxSize?: number;
|
|
1868
1868
|
}
|
|
1869
|
-
declare class
|
|
1869
|
+
declare class BucketPrimitive extends Primitive<BucketPrimitiveOptions> {
|
|
1870
1870
|
readonly provider: FileStorageProvider | MemoryFileStorageProvider;
|
|
1871
1871
|
private readonly fileSystem;
|
|
1872
1872
|
get name(): string;
|
|
@@ -1929,7 +1929,7 @@ declare module "alepha" {
|
|
|
1929
1929
|
"bucket:file:uploaded": {
|
|
1930
1930
|
id: string;
|
|
1931
1931
|
file: FileLike;
|
|
1932
|
-
bucket:
|
|
1932
|
+
bucket: BucketPrimitive;
|
|
1933
1933
|
options: BucketFileOptions;
|
|
1934
1934
|
};
|
|
1935
1935
|
/**
|
|
@@ -1937,14 +1937,14 @@ declare module "alepha" {
|
|
|
1937
1937
|
*/
|
|
1938
1938
|
"bucket:file:deleted": {
|
|
1939
1939
|
id: string;
|
|
1940
|
-
bucket:
|
|
1940
|
+
bucket: BucketPrimitive;
|
|
1941
1941
|
};
|
|
1942
1942
|
}
|
|
1943
1943
|
}
|
|
1944
1944
|
/**
|
|
1945
|
-
* Provides file storage capabilities through declarative bucket
|
|
1945
|
+
* Provides file storage capabilities through declarative bucket primitives with support for multiple storage backends.
|
|
1946
1946
|
*
|
|
1947
|
-
* The bucket module enables unified file operations across different storage systems using the `$bucket`
|
|
1947
|
+
* The bucket module enables unified file operations across different storage systems using the `$bucket` primitive
|
|
1948
1948
|
* on class properties. It abstracts storage provider differences, offering consistent APIs for local filesystem,
|
|
1949
1949
|
* cloud storage, or in-memory storage for testing environments.
|
|
1950
1950
|
*
|
|
@@ -1975,7 +1975,7 @@ declare class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
1975
1975
|
protected readonly blobServiceClient: BlobServiceClient;
|
|
1976
1976
|
readonly options: StoragePipelineOptions;
|
|
1977
1977
|
constructor();
|
|
1978
|
-
protected readonly onStart:
|
|
1978
|
+
protected readonly onStart: HookPrimitive<"start">;
|
|
1979
1979
|
convertName(name: string): string;
|
|
1980
1980
|
upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
|
|
1981
1981
|
download(bucketName: string, fileId: string): Promise<FileLike>;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ var AzureFileStorageProvider = class {
|
|
|
27
27
|
onStart = $hook({
|
|
28
28
|
on: "start",
|
|
29
29
|
handler: async () => {
|
|
30
|
-
for (const bucket of this.alepha.
|
|
30
|
+
for (const bucket of this.alepha.primitives($bucket)) {
|
|
31
31
|
if (bucket.provider !== this) continue;
|
|
32
32
|
const containerName = this.convertName(bucket.name);
|
|
33
33
|
this.log.debug(`Prepare container '${containerName}' ...`);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 BlobServiceClient,\n type BlockBlobClient,\n type ContainerClient,\n type StoragePipelineOptions,\n} from \"@azure/storage-blob\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type FileLike,\n type Static,\n t,\n} from \"alepha\";\nimport {\n $bucket,\n FileNotFoundError,\n type FileStorageProvider,\n} from \"alepha/bucket\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { FileSystemProvider } from \"alepha/file\";\nimport { $logger } from \"alepha/logger\";\n\nconst envSchema = t.object({\n AZ_STORAGE_CONNECTION_STRING: t.string(),\n});\n\ndeclare module \"alepha\" {\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(FileSystemProvider);\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.
|
|
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 BlobServiceClient,\n type BlockBlobClient,\n type ContainerClient,\n type StoragePipelineOptions,\n} from \"@azure/storage-blob\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type FileLike,\n type Static,\n t,\n} from \"alepha\";\nimport {\n $bucket,\n FileNotFoundError,\n type FileStorageProvider,\n} from \"alepha/bucket\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { FileSystemProvider } from \"alepha/file\";\nimport { $logger } from \"alepha/logger\";\n\nconst envSchema = t.object({\n AZ_STORAGE_CONNECTION_STRING: t.string(),\n});\n\ndeclare module \"alepha\" {\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(FileSystemProvider);\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.primitives($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 { $module } from \"alepha\";\nimport { AlephaBucket, FileStorageProvider } from \"alepha/bucket\";\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": "Nicolas Foures",
|
|
13
|
-
"version": "0.13.
|
|
13
|
+
"version": "0.13.2",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=22.0.0"
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"@azure/storage-blob": "^12.29.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"alepha": "0.13.
|
|
29
|
+
"alepha": "0.13.2",
|
|
30
30
|
"tsdown": "^0.16.7",
|
|
31
31
|
"vitest": "^4.0.14"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"alepha": "0.13.
|
|
34
|
+
"alepha": "0.13.2"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"lint": "alepha lint",
|
|
@@ -56,7 +56,7 @@ export class AzureFileStorageProvider implements FileStorageProvider {
|
|
|
56
56
|
protected readonly onStart = $hook({
|
|
57
57
|
on: "start",
|
|
58
58
|
handler: async () => {
|
|
59
|
-
for (const bucket of this.alepha.
|
|
59
|
+
for (const bucket of this.alepha.primitives($bucket)) {
|
|
60
60
|
if (bucket.provider !== this) {
|
|
61
61
|
continue;
|
|
62
62
|
}
|
package/dist/chunk-MC1wKe0N.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
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") {
|
|
10
|
-
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: ((k) => from[k]).bind(null, key),
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
-
value: mod,
|
|
24
|
-
enumerable: true
|
|
25
|
-
}) : target, mod));
|
|
26
|
-
|
|
27
|
-
//#endregion
|
package/dist/index.cjs
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
let alepha = require("alepha");
|
|
2
|
-
let alepha_bucket = require("alepha/bucket");
|
|
3
|
-
let node_crypto = require("node:crypto");
|
|
4
|
-
let node_stream = require("node:stream");
|
|
5
|
-
let __azure_storage_blob = require("@azure/storage-blob");
|
|
6
|
-
let alepha_datetime = require("alepha/datetime");
|
|
7
|
-
let alepha_file = require("alepha/file");
|
|
8
|
-
let alepha_logger = require("alepha/logger");
|
|
9
|
-
|
|
10
|
-
//#region src/providers/AzureFileStorageProvider.ts
|
|
11
|
-
const envSchema = alepha.t.object({ AZ_STORAGE_CONNECTION_STRING: alepha.t.string() });
|
|
12
|
-
/**
|
|
13
|
-
* Azure Blog Storage implementation of File Storage Provider.
|
|
14
|
-
*/
|
|
15
|
-
var AzureFileStorageProvider = class {
|
|
16
|
-
log = (0, alepha_logger.$logger)();
|
|
17
|
-
env = (0, alepha.$env)(envSchema);
|
|
18
|
-
alepha = (0, alepha.$inject)(alepha.Alepha);
|
|
19
|
-
time = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
|
|
20
|
-
fileSystem = (0, alepha.$inject)(alepha_file.FileSystemProvider);
|
|
21
|
-
containers = {};
|
|
22
|
-
blobServiceClient;
|
|
23
|
-
options = {};
|
|
24
|
-
constructor() {
|
|
25
|
-
this.blobServiceClient = __azure_storage_blob.BlobServiceClient.fromConnectionString(this.env.AZ_STORAGE_CONNECTION_STRING, this.options);
|
|
26
|
-
}
|
|
27
|
-
onStart = (0, alepha.$hook)({
|
|
28
|
-
on: "start",
|
|
29
|
-
handler: async () => {
|
|
30
|
-
for (const bucket of this.alepha.descriptors(alepha_bucket.$bucket)) {
|
|
31
|
-
if (bucket.provider !== this) continue;
|
|
32
|
-
const containerName = this.convertName(bucket.name);
|
|
33
|
-
this.log.debug(`Prepare container '${containerName}' ...`);
|
|
34
|
-
if (!this.containers[containerName]) this.containers[containerName] = await this.createContainerClient(containerName);
|
|
35
|
-
this.log.info(`Container '${bucket.name}' OK`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
convertName(name) {
|
|
40
|
-
return name.replaceAll("/", "-").toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
async upload(bucketName, file, fileId) {
|
|
43
|
-
fileId ??= this.createId();
|
|
44
|
-
this.log.trace(`Uploading file '${file.name}' to bucket '${bucketName}' with id '${fileId}'...`);
|
|
45
|
-
const block = this.getBlock(bucketName, fileId);
|
|
46
|
-
const metadata = {
|
|
47
|
-
name: file.name,
|
|
48
|
-
type: file.type
|
|
49
|
-
};
|
|
50
|
-
if (file.filepath) await block.uploadFile(file.filepath, {
|
|
51
|
-
metadata,
|
|
52
|
-
blobHTTPHeaders: { blobContentType: file.type }
|
|
53
|
-
});
|
|
54
|
-
else if (file.size > 0) await block.uploadData(await file.arrayBuffer(), {
|
|
55
|
-
metadata,
|
|
56
|
-
blobHTTPHeaders: { blobContentType: file.type }
|
|
57
|
-
});
|
|
58
|
-
else await block.uploadStream(node_stream.Readable.from(file.stream()), file.size || void 0, 5, {
|
|
59
|
-
metadata,
|
|
60
|
-
blobHTTPHeaders: { blobContentType: file.type }
|
|
61
|
-
});
|
|
62
|
-
return fileId;
|
|
63
|
-
}
|
|
64
|
-
async download(bucketName, fileId) {
|
|
65
|
-
this.log.trace(`Downloading file '${fileId}' from bucket '${bucketName}'...`);
|
|
66
|
-
const blob = await this.getBlock(bucketName, fileId).download().catch((error) => {
|
|
67
|
-
if (error instanceof Error) throw new alepha_bucket.FileNotFoundError("Error downloading file", { cause: error });
|
|
68
|
-
throw error;
|
|
69
|
-
});
|
|
70
|
-
if (!blob.readableStreamBody) throw new alepha_bucket.FileNotFoundError("File not found - empty stream body");
|
|
71
|
-
return this.fileSystem.createFile({
|
|
72
|
-
stream: blob.readableStreamBody,
|
|
73
|
-
...blob.metadata,
|
|
74
|
-
size: blob.contentLength
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
async exists(bucketName, fileId) {
|
|
78
|
-
this.log.trace(`Checking existence of file '${fileId}' in bucket '${bucketName}'...`);
|
|
79
|
-
return await this.getBlock(bucketName, fileId).exists();
|
|
80
|
-
}
|
|
81
|
-
async delete(bucketName, fileId) {
|
|
82
|
-
this.log.trace(`Deleting file '${fileId}' from bucket '${bucketName}'...`);
|
|
83
|
-
try {
|
|
84
|
-
await this.getBlock(bucketName, fileId).delete();
|
|
85
|
-
} catch (error) {
|
|
86
|
-
if (error instanceof Error) throw new alepha_bucket.FileNotFoundError("Error deleting file", { cause: error });
|
|
87
|
-
throw error;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
getBlock(container, fileId) {
|
|
91
|
-
const containerName = this.convertName(container);
|
|
92
|
-
if (!this.containers[containerName]) throw new alepha_bucket.FileNotFoundError(`File '${fileId}' not found - container '${container}' does not exists`);
|
|
93
|
-
return this.containers[containerName].getBlockBlobClient(fileId);
|
|
94
|
-
}
|
|
95
|
-
async createContainerClient(name) {
|
|
96
|
-
const container = this.blobServiceClient.getContainerClient(name);
|
|
97
|
-
await this.time.deadline((abortSignal) => container.createIfNotExists({ abortSignal }), [5, "seconds"]);
|
|
98
|
-
return container;
|
|
99
|
-
}
|
|
100
|
-
createId() {
|
|
101
|
-
return (0, node_crypto.randomUUID)();
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
//#endregion
|
|
106
|
-
//#region src/index.ts
|
|
107
|
-
/**
|
|
108
|
-
* Plugin for Alepha Bucket that provides Azure Blob Storage capabilities.
|
|
109
|
-
*
|
|
110
|
-
* @see {@link AzureFileStorageProvider}
|
|
111
|
-
* @module alepha.bucket.azure
|
|
112
|
-
*/
|
|
113
|
-
const AlephaBucketAzure = (0, alepha.$module)({
|
|
114
|
-
name: "alepha.bucket.azure",
|
|
115
|
-
services: [AzureFileStorageProvider],
|
|
116
|
-
register: (alepha$1) => alepha$1.with({
|
|
117
|
-
optional: true,
|
|
118
|
-
provide: alepha_bucket.FileStorageProvider,
|
|
119
|
-
use: AzureFileStorageProvider
|
|
120
|
-
}).with(alepha_bucket.AlephaBucket)
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
//#endregion
|
|
124
|
-
exports.AlephaBucketAzure = AlephaBucketAzure;
|
|
125
|
-
exports.AzureFileStorageProvider = AzureFileStorageProvider;
|
|
126
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["t","Alepha","DateTimeProvider","FileSystemProvider","BlobServiceClient","$bucket","Readable","FileNotFoundError","alepha","FileStorageProvider","AlephaBucket"],"sources":["../src/providers/AzureFileStorageProvider.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Readable } from \"node:stream\";\nimport {\n BlobServiceClient,\n type BlockBlobClient,\n type ContainerClient,\n type StoragePipelineOptions,\n} from \"@azure/storage-blob\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type FileLike,\n type Static,\n t,\n} from \"alepha\";\nimport {\n $bucket,\n FileNotFoundError,\n type FileStorageProvider,\n} from \"alepha/bucket\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { FileSystemProvider } from \"alepha/file\";\nimport { $logger } from \"alepha/logger\";\n\nconst envSchema = t.object({\n AZ_STORAGE_CONNECTION_STRING: t.string(),\n});\n\ndeclare module \"alepha\" {\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(FileSystemProvider);\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 { $module } from \"alepha\";\nimport { AlephaBucket, FileStorageProvider } from \"alepha/bucket\";\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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"}
|