alepha 0.20.3 → 0.20.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/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/jobs/index.d.ts +14 -14
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/keys/index.d.ts +4 -4
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/parameters/index.d.ts +8 -3
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +20 -4
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/users/index.browser.js +6 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +5037 -139
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +58 -10
- package/dist/api/users/index.js.map +1 -1
- package/dist/bucket/index.d.ts +77 -107
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +148 -4
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +7 -1
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +26 -0
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +11 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js +11 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cli/config/index.d.ts +7 -5
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +2 -3
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +420 -13
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +22 -511
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +4 -8
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js +13 -15
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +10 -13
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +18 -15
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +10 -13
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +16 -13
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/core/index.browser.js +27 -3
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -3
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -3
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/datetime/index.d.ts +69 -10
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +135 -13
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/smtp/index.js +10636 -2
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +8085 -4
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +33554 -3
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +30 -2
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +35 -12
- package/dist/lock/core/index.js.map +1 -1
- package/dist/mcp/index.d.ts +238 -31
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +198 -71
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +1 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +4 -3
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +4877 -9
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +4 -3
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +608 -1
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/react/core/index.d.ts +102 -1
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +65 -1
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +6 -0
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +7 -7
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +7 -1
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +6 -0
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/router/index.browser.js +20 -2
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +36 -4
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +20 -2
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/chunk-6Ep1yQYe.js +16 -0
- package/dist/react/testing/index.d.ts +411 -1
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +12293 -13
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +195 -1
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js +61 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +84 -3
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +390 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js +390 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.d.ts +325 -2
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1361 -2
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +1054 -1
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1223 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/core/index.browser.js +10 -3
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +28 -5
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +514 -1
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +4374 -4
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +3 -4
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/websocket/index.browser.js +11 -5
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +3 -1
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +21 -6
- package/dist/websocket/index.js.map +1 -1
- package/package.json +671 -263
- package/src/api/parameters/services/ParameterProvider.ts +21 -4
- package/src/api/users/__tests__/SessionService.spec.ts +99 -0
- package/src/api/users/__tests__/UserJobs.spec.ts +67 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +15 -0
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/jobs/UserJobs.ts +44 -17
- package/src/api/users/providers/RealmProvider.ts +4 -0
- package/src/api/users/services/SessionService.ts +27 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +74 -0
- package/src/bucket/index.ts +19 -2
- package/src/bucket/primitives/$bucket.ts +9 -1
- package/src/bucket/providers/CloudflareR2Provider.ts +2 -137
- package/src/bucket/providers/NodeS3BucketProvider.ts +218 -0
- package/src/cache/core/index.ts +29 -0
- package/src/cache/core/primitives/$cache.ts +14 -1
- package/src/cli/config/defineConfig.ts +13 -15
- package/src/cli/core/__tests__/init.spec.ts +6 -7
- package/src/cli/core/services/ProjectScaffolder.ts +18 -14
- package/src/cli/core/tasks/BuildCloudflareTask.ts +5 -0
- package/src/cli/core/templates/agentMd.ts +2 -10
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +3 -3
- package/src/cli/devtools/index.ts +12 -26
- package/src/cli/platform/index.ts +15 -24
- package/src/cli/vendor/atoms/vendorOptions.ts +1 -1
- package/src/cli/vendor/index.ts +14 -23
- package/src/core/Alepha.ts +11 -1
- package/src/core/helpers/ref.ts +18 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/providers/SchemaValidator.ts +9 -1
- package/src/core/providers/TypeProvider.ts +1 -2
- package/src/datetime/REFACTORING.md +118 -0
- package/src/datetime/providers/DateTimeProvider.ts +203 -24
- package/src/lock/core/index.ts +31 -0
- package/src/lock/core/primitives/$lock.ts +14 -1
- package/src/mcp/__tests__/jsonrpc.spec.ts +1 -1
- package/src/mcp/helpers/jsonrpc.ts +26 -1
- package/src/mcp/index.ts +10 -5
- package/src/mcp/interfaces/McpTypes.ts +83 -6
- package/src/mcp/primitives/$prompt.ts +18 -1
- package/src/mcp/primitives/$resource.ts +18 -1
- package/src/mcp/primitives/$tool.ts +83 -7
- package/src/mcp/providers/McpServerProvider.ts +74 -16
- package/src/mcp/transports/StreamableHttpMcpTransport.ts +226 -0
- package/src/orm/REFACTORING.md +330 -0
- package/src/orm/core/primitives/$transactional.ts +11 -0
- package/src/orm/core/schemas/updateSchema.ts +1 -1
- package/src/orm/core/services/PgRelationManager.ts +4 -2
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +86 -0
- package/src/react/core/hooks/useQuery.ts +153 -0
- package/src/react/core/index.ts +1 -0
- package/src/react/form/services/FormModel.ts +15 -6
- package/src/react/form/services/parseField.ts +8 -0
- package/src/react/i18n/providers/I18nProvider.ts +8 -2
- package/src/react/router/__tests__/$page.spec.tsx +0 -16
- package/src/react/router/__tests__/ssr.spec.tsx +339 -0
- package/src/react/router/primitives/$page.ts +28 -4
- package/src/react/router/providers/ReactPageProvider.ts +27 -9
- package/src/react/ui/atoms/uiThemeListAtom.ts +36 -0
- package/src/react/ui/index.ts +6 -0
- package/src/react/ui/services/SchemaControl.ts +209 -0
- package/src/security/primitives/$issuer.ts +6 -3
- package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +75 -0
- package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +306 -0
- package/src/server/core/errors/ValidationError.ts +13 -1
- package/src/server/core/primitives/$action.ts +16 -5
- package/src/server/core/providers/ServerRouterProvider.ts +26 -4
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +5 -7
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +10 -4
- package/src/websocket/services/WebSocketClient.ts +11 -5
- package/src/mcp/transports/SseMcpTransport.ts +0 -182
package/dist/bucket/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { Alepha, AlephaError, FileLike, KIND, Primitive, Service, Static } from
|
|
|
3
3
|
import { FileDetector, FileSystemProvider } from "alepha/system";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as _$alepha_logger0 from "alepha/logger";
|
|
6
|
+
import { S3mini } from "s3mini";
|
|
7
|
+
import { R2Bucket } from "@cloudflare/workers-types";
|
|
6
8
|
|
|
7
9
|
//#region ../../src/bucket/providers/FileStorageProvider.d.ts
|
|
8
10
|
declare abstract class FileStorageProvider {
|
|
@@ -245,7 +247,7 @@ interface BucketFileOptions {
|
|
|
245
247
|
maxSize?: number;
|
|
246
248
|
}
|
|
247
249
|
declare class BucketPrimitive extends Primitive<BucketPrimitiveOptions> {
|
|
248
|
-
readonly provider:
|
|
250
|
+
readonly provider: FileStorageProvider | MemoryFileStorageProvider;
|
|
249
251
|
protected readonly fileSystem: FileSystemProvider;
|
|
250
252
|
get name(): string;
|
|
251
253
|
/**
|
|
@@ -264,7 +266,7 @@ declare class BucketPrimitive extends Primitive<BucketPrimitiveOptions> {
|
|
|
264
266
|
* Downloads a file from the bucket.
|
|
265
267
|
*/
|
|
266
268
|
download(fileId: string): Promise<FileLike>;
|
|
267
|
-
protected $provider():
|
|
269
|
+
protected $provider(): FileStorageProvider | MemoryFileStorageProvider;
|
|
268
270
|
}
|
|
269
271
|
interface BucketFileOptions {
|
|
270
272
|
/**
|
|
@@ -289,110 +291,6 @@ declare class FileNotFoundError extends AlephaError {
|
|
|
289
291
|
}
|
|
290
292
|
//#endregion
|
|
291
293
|
//#region ../../src/bucket/providers/CloudflareR2Provider.d.ts
|
|
292
|
-
/**
|
|
293
|
-
* R2Bucket interface matching Cloudflare's R2 API.
|
|
294
|
-
*/
|
|
295
|
-
interface R2Bucket {
|
|
296
|
-
put(key: string, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob | null, options?: R2PutOptions): Promise<R2Object | null>;
|
|
297
|
-
get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | null>;
|
|
298
|
-
head(key: string): Promise<R2Object | null>;
|
|
299
|
-
delete(keys: string | string[]): Promise<void>;
|
|
300
|
-
list(options?: R2ListOptions): Promise<R2Objects>;
|
|
301
|
-
createMultipartUpload(key: string, options?: R2MultipartOptions): Promise<R2MultipartUpload>;
|
|
302
|
-
}
|
|
303
|
-
interface R2Object {
|
|
304
|
-
key: string;
|
|
305
|
-
version: string;
|
|
306
|
-
size: number;
|
|
307
|
-
etag: string;
|
|
308
|
-
httpEtag: string;
|
|
309
|
-
checksums: R2Checksums;
|
|
310
|
-
uploaded: Date;
|
|
311
|
-
httpMetadata?: R2HTTPMetadata;
|
|
312
|
-
customMetadata?: Record<string, string>;
|
|
313
|
-
range?: R2Range;
|
|
314
|
-
storageClass: string;
|
|
315
|
-
}
|
|
316
|
-
interface R2ObjectBody extends R2Object {
|
|
317
|
-
body: ReadableStream;
|
|
318
|
-
bodyUsed: boolean;
|
|
319
|
-
arrayBuffer(): Promise<ArrayBuffer>;
|
|
320
|
-
text(): Promise<string>;
|
|
321
|
-
json<T>(): Promise<T>;
|
|
322
|
-
blob(): Promise<Blob>;
|
|
323
|
-
}
|
|
324
|
-
interface R2PutOptions {
|
|
325
|
-
onlyIf?: R2Conditional;
|
|
326
|
-
httpMetadata?: R2HTTPMetadata;
|
|
327
|
-
customMetadata?: Record<string, string>;
|
|
328
|
-
md5?: ArrayBuffer | string;
|
|
329
|
-
sha1?: ArrayBuffer | string;
|
|
330
|
-
sha256?: ArrayBuffer | string;
|
|
331
|
-
sha384?: ArrayBuffer | string;
|
|
332
|
-
sha512?: ArrayBuffer | string;
|
|
333
|
-
storageClass?: string;
|
|
334
|
-
}
|
|
335
|
-
interface R2GetOptions {
|
|
336
|
-
onlyIf?: R2Conditional;
|
|
337
|
-
range?: R2Range;
|
|
338
|
-
}
|
|
339
|
-
interface R2ListOptions {
|
|
340
|
-
limit?: number;
|
|
341
|
-
prefix?: string;
|
|
342
|
-
cursor?: string;
|
|
343
|
-
delimiter?: string;
|
|
344
|
-
startAfter?: string;
|
|
345
|
-
include?: ("httpMetadata" | "customMetadata")[];
|
|
346
|
-
}
|
|
347
|
-
interface R2Objects {
|
|
348
|
-
objects: R2Object[];
|
|
349
|
-
truncated: boolean;
|
|
350
|
-
cursor?: string;
|
|
351
|
-
delimitedPrefixes: string[];
|
|
352
|
-
}
|
|
353
|
-
interface R2Checksums {
|
|
354
|
-
md5?: ArrayBuffer;
|
|
355
|
-
sha1?: ArrayBuffer;
|
|
356
|
-
sha256?: ArrayBuffer;
|
|
357
|
-
sha384?: ArrayBuffer;
|
|
358
|
-
sha512?: ArrayBuffer;
|
|
359
|
-
}
|
|
360
|
-
interface R2HTTPMetadata {
|
|
361
|
-
contentType?: string;
|
|
362
|
-
contentLanguage?: string;
|
|
363
|
-
contentDisposition?: string;
|
|
364
|
-
contentEncoding?: string;
|
|
365
|
-
cacheControl?: string;
|
|
366
|
-
cacheExpiry?: Date;
|
|
367
|
-
}
|
|
368
|
-
interface R2Conditional {
|
|
369
|
-
etagMatches?: string;
|
|
370
|
-
etagDoesNotMatch?: string;
|
|
371
|
-
uploadedBefore?: Date;
|
|
372
|
-
uploadedAfter?: Date;
|
|
373
|
-
secondsGranularity?: boolean;
|
|
374
|
-
}
|
|
375
|
-
interface R2Range {
|
|
376
|
-
offset?: number;
|
|
377
|
-
length?: number;
|
|
378
|
-
suffix?: number;
|
|
379
|
-
}
|
|
380
|
-
interface R2MultipartOptions {
|
|
381
|
-
httpMetadata?: R2HTTPMetadata;
|
|
382
|
-
customMetadata?: Record<string, string>;
|
|
383
|
-
storageClass?: string;
|
|
384
|
-
}
|
|
385
|
-
interface R2MultipartUpload {
|
|
386
|
-
key: string;
|
|
387
|
-
uploadId: string;
|
|
388
|
-
uploadPart(partNumber: number, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob): Promise<R2UploadedPart>;
|
|
389
|
-
abort(): Promise<void>;
|
|
390
|
-
complete(uploadedParts: R2UploadedPart[]): Promise<R2Object>;
|
|
391
|
-
}
|
|
392
|
-
interface R2UploadedPart {
|
|
393
|
-
partNumber: number;
|
|
394
|
-
etag: string;
|
|
395
|
-
}
|
|
396
294
|
/**
|
|
397
295
|
* Cloudflare R2 storage provider.
|
|
398
296
|
*
|
|
@@ -501,6 +399,70 @@ declare class LocalFileStorageProvider implements FileStorageProvider {
|
|
|
501
399
|
protected isErrorNoEntry(error: unknown): boolean;
|
|
502
400
|
}
|
|
503
401
|
//#endregion
|
|
402
|
+
//#region ../../src/bucket/providers/NodeS3BucketProvider.d.ts
|
|
403
|
+
declare const envSchema: _$alepha.TObject<{
|
|
404
|
+
/**
|
|
405
|
+
* S3 endpoint URL. The bucket name is appended (path-style) per request.
|
|
406
|
+
*
|
|
407
|
+
* Examples:
|
|
408
|
+
* - AWS S3: `https://s3.us-east-1.amazonaws.com`
|
|
409
|
+
* - Cloudflare R2: `https://<account-id>.r2.cloudflarestorage.com`
|
|
410
|
+
* - MinIO: `http://localhost:9000`
|
|
411
|
+
* - DigitalOcean Spaces: `https://<region>.digitaloceanspaces.com`
|
|
412
|
+
*/
|
|
413
|
+
S3_ENDPOINT: _$alepha.TString;
|
|
414
|
+
/**
|
|
415
|
+
* AWS region or "auto" for R2.
|
|
416
|
+
*
|
|
417
|
+
* @default "auto"
|
|
418
|
+
*/
|
|
419
|
+
S3_REGION: _$alepha.TOptional<_$alepha.TString>;
|
|
420
|
+
/**
|
|
421
|
+
* Access key ID for S3 authentication.
|
|
422
|
+
*/
|
|
423
|
+
S3_ACCESS_KEY_ID: _$alepha.TString;
|
|
424
|
+
/**
|
|
425
|
+
* Secret access key for S3 authentication.
|
|
426
|
+
*/
|
|
427
|
+
S3_SECRET_ACCESS_KEY: _$alepha.TString;
|
|
428
|
+
}>;
|
|
429
|
+
declare module "alepha" {
|
|
430
|
+
interface Env extends Partial<Static<typeof envSchema>> {}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* S3-compatible file storage provider for Node.js.
|
|
434
|
+
*
|
|
435
|
+
* Backed by `s3mini` (zero-dep, ~20 KB). Works with AWS S3, Cloudflare R2,
|
|
436
|
+
* MinIO, DigitalOcean Spaces, Backblaze B2, and any other S3-compatible service.
|
|
437
|
+
*
|
|
438
|
+
* Uses path-style addressing (`<endpoint>/<bucket>`).
|
|
439
|
+
*/
|
|
440
|
+
declare class NodeS3BucketProvider implements FileStorageProvider {
|
|
441
|
+
protected readonly log: _$alepha_logger0.Logger;
|
|
442
|
+
protected readonly env: {
|
|
443
|
+
S3_REGION?: string | undefined;
|
|
444
|
+
S3_ENDPOINT: string;
|
|
445
|
+
S3_ACCESS_KEY_ID: string;
|
|
446
|
+
S3_SECRET_ACCESS_KEY: string;
|
|
447
|
+
};
|
|
448
|
+
protected readonly alepha: Alepha;
|
|
449
|
+
protected readonly fileSystem: FileSystemProvider;
|
|
450
|
+
protected readonly fileDetector: FileDetector;
|
|
451
|
+
protected readonly clients: Map<string, S3mini>;
|
|
452
|
+
/**
|
|
453
|
+
* Convert bucket name to S3-compatible format.
|
|
454
|
+
* S3 bucket names must be lowercase, 3-63 characters, no underscores.
|
|
455
|
+
*/
|
|
456
|
+
convertName(name: string): string;
|
|
457
|
+
protected getClient(bucketName: string): S3mini;
|
|
458
|
+
protected readonly onStart: _$alepha.HookPrimitive<"start">;
|
|
459
|
+
protected createId(mimeType: string): string;
|
|
460
|
+
upload(bucketName: string, file: FileLike, fileId?: string): Promise<string>;
|
|
461
|
+
download(bucketName: string, fileId: string): Promise<FileLike>;
|
|
462
|
+
exists(bucketName: string, fileId: string): Promise<boolean>;
|
|
463
|
+
delete(bucketName: string, fileId: string): Promise<void>;
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
504
466
|
//#region ../../src/bucket/index.d.ts
|
|
505
467
|
declare module "alepha" {
|
|
506
468
|
interface Hooks {
|
|
@@ -521,6 +483,14 @@ declare module "alepha" {
|
|
|
521
483
|
id: string;
|
|
522
484
|
bucket: BucketPrimitive;
|
|
523
485
|
};
|
|
486
|
+
/**
|
|
487
|
+
* Triggered when a file is downloaded from a bucket.
|
|
488
|
+
*/
|
|
489
|
+
"bucket:file:downloaded": {
|
|
490
|
+
id: string;
|
|
491
|
+
file: FileLike;
|
|
492
|
+
bucket: BucketPrimitive;
|
|
493
|
+
};
|
|
524
494
|
}
|
|
525
495
|
}
|
|
526
496
|
/**
|
|
@@ -539,5 +509,5 @@ declare module "alepha" {
|
|
|
539
509
|
*/
|
|
540
510
|
declare const AlephaBucket: _$alepha.Service<_$alepha.Module>;
|
|
541
511
|
//#endregion
|
|
542
|
-
export { $bucket, AlephaBucket, BucketFileOptions, BucketPrimitive, BucketPrimitiveOptions, CloudflareR2Provider, FileNotFoundError, FileStorageProvider, LocalFileStorageProvider, LocalFileStorageProviderOptions, MemoryFileStorageProvider,
|
|
512
|
+
export { $bucket, AlephaBucket, BucketFileOptions, BucketPrimitive, BucketPrimitiveOptions, CloudflareR2Provider, FileNotFoundError, FileStorageProvider, LocalFileStorageProvider, LocalFileStorageProviderOptions, MemoryFileStorageProvider, NodeS3BucketProvider, localFileStorageOptions };
|
|
543
513
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/bucket/providers/FileStorageProvider.ts","../../src/bucket/providers/MemoryFileStorageProvider.ts","../../src/bucket/primitives/$bucket.ts","../../src/bucket/errors/FileNotFoundError.ts","../../src/bucket/providers/CloudflareR2Provider.ts","../../src/bucket/providers/LocalFileStorageProvider.ts","../../src/bucket/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/bucket/providers/FileStorageProvider.ts","../../src/bucket/providers/MemoryFileStorageProvider.ts","../../src/bucket/primitives/$bucket.ts","../../src/bucket/errors/FileNotFoundError.ts","../../src/bucket/providers/CloudflareR2Provider.ts","../../src/bucket/providers/LocalFileStorageProvider.ts","../../src/bucket/providers/NodeS3BucketProvider.ts","../../src/bucket/index.ts"],"mappings":"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"}
|
package/dist/bucket/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { mkdir, stat, unlink } from "node:fs/promises";
|
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { $logger } from "alepha/logger";
|
|
9
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
10
|
+
import { S3mini } from "s3mini";
|
|
9
11
|
//#region ../../src/bucket/errors/InvalidFileError.ts
|
|
10
12
|
var InvalidFileError = class extends AlephaError {
|
|
11
13
|
status = 400;
|
|
@@ -164,7 +166,13 @@ var BucketPrimitive = class extends Primitive {
|
|
|
164
166
|
* Downloads a file from the bucket.
|
|
165
167
|
*/
|
|
166
168
|
async download(fileId) {
|
|
167
|
-
|
|
169
|
+
const file = await this.provider.download(this.name, fileId);
|
|
170
|
+
await this.alepha.events.emit("bucket:file:downloaded", {
|
|
171
|
+
id: fileId,
|
|
172
|
+
bucket: this,
|
|
173
|
+
file
|
|
174
|
+
});
|
|
175
|
+
return file;
|
|
168
176
|
}
|
|
169
177
|
$provider() {
|
|
170
178
|
if (!this.options.provider) return this.alepha.inject(FileStorageProvider);
|
|
@@ -265,6 +273,137 @@ var LocalFileStorageProvider = class {
|
|
|
265
273
|
}
|
|
266
274
|
};
|
|
267
275
|
//#endregion
|
|
276
|
+
//#region ../../src/bucket/providers/NodeS3BucketProvider.ts
|
|
277
|
+
const envSchema = t.object({
|
|
278
|
+
/**
|
|
279
|
+
* S3 endpoint URL. The bucket name is appended (path-style) per request.
|
|
280
|
+
*
|
|
281
|
+
* Examples:
|
|
282
|
+
* - AWS S3: `https://s3.us-east-1.amazonaws.com`
|
|
283
|
+
* - Cloudflare R2: `https://<account-id>.r2.cloudflarestorage.com`
|
|
284
|
+
* - MinIO: `http://localhost:9000`
|
|
285
|
+
* - DigitalOcean Spaces: `https://<region>.digitaloceanspaces.com`
|
|
286
|
+
*/
|
|
287
|
+
S3_ENDPOINT: t.string(),
|
|
288
|
+
/**
|
|
289
|
+
* AWS region or "auto" for R2.
|
|
290
|
+
*
|
|
291
|
+
* @default "auto"
|
|
292
|
+
*/
|
|
293
|
+
S3_REGION: t.optional(t.string()),
|
|
294
|
+
/**
|
|
295
|
+
* Access key ID for S3 authentication.
|
|
296
|
+
*/
|
|
297
|
+
S3_ACCESS_KEY_ID: t.string(),
|
|
298
|
+
/**
|
|
299
|
+
* Secret access key for S3 authentication.
|
|
300
|
+
*/
|
|
301
|
+
S3_SECRET_ACCESS_KEY: t.string()
|
|
302
|
+
});
|
|
303
|
+
/**
|
|
304
|
+
* S3-compatible file storage provider for Node.js.
|
|
305
|
+
*
|
|
306
|
+
* Backed by `s3mini` (zero-dep, ~20 KB). Works with AWS S3, Cloudflare R2,
|
|
307
|
+
* MinIO, DigitalOcean Spaces, Backblaze B2, and any other S3-compatible service.
|
|
308
|
+
*
|
|
309
|
+
* Uses path-style addressing (`<endpoint>/<bucket>`).
|
|
310
|
+
*/
|
|
311
|
+
var NodeS3BucketProvider = class {
|
|
312
|
+
log = $logger();
|
|
313
|
+
env = $env(envSchema);
|
|
314
|
+
alepha = $inject(Alepha);
|
|
315
|
+
fileSystem = $inject(FileSystemProvider);
|
|
316
|
+
fileDetector = $inject(FileDetector);
|
|
317
|
+
clients = /* @__PURE__ */ new Map();
|
|
318
|
+
/**
|
|
319
|
+
* Convert bucket name to S3-compatible format.
|
|
320
|
+
* S3 bucket names must be lowercase, 3-63 characters, no underscores.
|
|
321
|
+
*/
|
|
322
|
+
convertName(name) {
|
|
323
|
+
return name.replaceAll("/", "-").replaceAll("_", "-").toLowerCase();
|
|
324
|
+
}
|
|
325
|
+
getClient(bucketName) {
|
|
326
|
+
const name = this.convertName(bucketName);
|
|
327
|
+
let client = this.clients.get(name);
|
|
328
|
+
if (!client) {
|
|
329
|
+
const endpoint = this.env.S3_ENDPOINT.replace(/\/+$/, "");
|
|
330
|
+
client = new S3mini({
|
|
331
|
+
accessKeyId: this.env.S3_ACCESS_KEY_ID,
|
|
332
|
+
secretAccessKey: this.env.S3_SECRET_ACCESS_KEY,
|
|
333
|
+
region: this.env.S3_REGION || "auto",
|
|
334
|
+
endpoint: `${endpoint}/${name}`
|
|
335
|
+
});
|
|
336
|
+
this.clients.set(name, client);
|
|
337
|
+
}
|
|
338
|
+
return client;
|
|
339
|
+
}
|
|
340
|
+
onStart = $hook({
|
|
341
|
+
on: "start",
|
|
342
|
+
handler: async () => {
|
|
343
|
+
for (const bucket of this.alepha.primitives($bucket)) {
|
|
344
|
+
if (bucket.provider !== this) continue;
|
|
345
|
+
const name = this.convertName(bucket.name);
|
|
346
|
+
const client = this.getClient(bucket.name);
|
|
347
|
+
this.log.debug(`Preparing S3 bucket '${name}'...`);
|
|
348
|
+
if (!await client.bucketExists()) {
|
|
349
|
+
this.log.debug(`Creating S3 bucket '${name}'...`);
|
|
350
|
+
if (!await client.createBucket()) throw new AlephaError(`Failed to create S3 bucket '${name}'`);
|
|
351
|
+
}
|
|
352
|
+
this.log.info(`S3 bucket '${bucket.name}' OK`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
createId(mimeType) {
|
|
357
|
+
const ext = this.fileDetector.getExtensionFromMimeType(mimeType);
|
|
358
|
+
return `${crypto.randomUUID()}.${ext}`;
|
|
359
|
+
}
|
|
360
|
+
async upload(bucketName, file, fileId) {
|
|
361
|
+
fileId ??= this.createId(file.type);
|
|
362
|
+
this.log.trace(`Uploading file '${file.name}' to bucket '${bucketName}' with id '${fileId}'...`);
|
|
363
|
+
const client = this.getClient(bucketName);
|
|
364
|
+
try {
|
|
365
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
366
|
+
await client.putObject(fileId, buffer, file.type || "application/octet-stream", void 0, { "x-amz-meta-name": encodeURIComponent(file.name) }, file.size);
|
|
367
|
+
this.log.trace(`File uploaded successfully: ${fileId}`);
|
|
368
|
+
return fileId;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
this.log.error(`Failed to upload file: ${error}`);
|
|
371
|
+
if (error instanceof Error) throw new AlephaError(`Upload failed: ${error.message}`, { cause: error });
|
|
372
|
+
throw error;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async download(bucketName, fileId) {
|
|
376
|
+
this.log.trace(`Downloading file '${fileId}' from bucket '${bucketName}'...`);
|
|
377
|
+
const response = await this.getClient(bucketName).getObjectResponse(fileId);
|
|
378
|
+
if (!response) throw new FileNotFoundError(`File '${fileId}' not found in bucket '${bucketName}'`);
|
|
379
|
+
const buffer = Buffer$1.from(await response.arrayBuffer());
|
|
380
|
+
const mimeType = response.headers.get("content-type") || this.fileDetector.getContentType(fileId);
|
|
381
|
+
const metaName = response.headers.get("x-amz-meta-name");
|
|
382
|
+
const name = metaName ? decodeURIComponent(metaName) : fileId;
|
|
383
|
+
return this.fileSystem.createFile({
|
|
384
|
+
buffer,
|
|
385
|
+
name,
|
|
386
|
+
type: mimeType,
|
|
387
|
+
size: buffer.length
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
async exists(bucketName, fileId) {
|
|
391
|
+
this.log.trace(`Checking existence of file '${fileId}' in bucket '${bucketName}'...`);
|
|
392
|
+
return await this.getClient(bucketName).objectExists(fileId) === true;
|
|
393
|
+
}
|
|
394
|
+
async delete(bucketName, fileId) {
|
|
395
|
+
this.log.trace(`Deleting file '${fileId}' from bucket '${bucketName}'...`);
|
|
396
|
+
const client = this.getClient(bucketName);
|
|
397
|
+
try {
|
|
398
|
+
await client.deleteObject(fileId);
|
|
399
|
+
} catch (error) {
|
|
400
|
+
this.log.error(`Failed to delete file: ${error}`);
|
|
401
|
+
if (error instanceof Error) throw new FileNotFoundError("Error deleting file", { cause: error });
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
//#endregion
|
|
268
407
|
//#region ../../src/bucket/providers/CloudflareR2Provider.ts
|
|
269
408
|
/**
|
|
270
409
|
* Cloudflare R2 storage provider.
|
|
@@ -431,16 +570,21 @@ const AlephaBucket = $module({
|
|
|
431
570
|
name: "alepha.bucket",
|
|
432
571
|
primitives: [$bucket],
|
|
433
572
|
services: [FileStorageProvider],
|
|
434
|
-
variants: [
|
|
573
|
+
variants: [
|
|
574
|
+
MemoryFileStorageProvider,
|
|
575
|
+
LocalFileStorageProvider,
|
|
576
|
+
NodeS3BucketProvider
|
|
577
|
+
],
|
|
435
578
|
register: (alepha) => {
|
|
579
|
+
const useS3 = !!alepha.env.S3_ENDPOINT;
|
|
436
580
|
alepha.with({
|
|
437
581
|
optional: true,
|
|
438
582
|
provide: FileStorageProvider,
|
|
439
|
-
use: alepha.isTest() || alepha.isServerless() ? MemoryFileStorageProvider : LocalFileStorageProvider
|
|
583
|
+
use: alepha.isTest() || alepha.isServerless() ? MemoryFileStorageProvider : useS3 ? NodeS3BucketProvider : LocalFileStorageProvider
|
|
440
584
|
});
|
|
441
585
|
}
|
|
442
586
|
});
|
|
443
587
|
//#endregion
|
|
444
|
-
export { $bucket, AlephaBucket, BucketPrimitive, CloudflareR2Provider, FileNotFoundError, FileStorageProvider, LocalFileStorageProvider, MemoryFileStorageProvider, localFileStorageOptions };
|
|
588
|
+
export { $bucket, AlephaBucket, BucketPrimitive, CloudflareR2Provider, FileNotFoundError, FileStorageProvider, LocalFileStorageProvider, MemoryFileStorageProvider, NodeS3BucketProvider, localFileStorageOptions };
|
|
445
589
|
|
|
446
590
|
//# sourceMappingURL=index.js.map
|