@bloomneo/appkit 1.2.9
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/LICENSE +21 -0
- package/README.md +902 -0
- package/bin/appkit.js +71 -0
- package/bin/commands/generate.js +1050 -0
- package/bin/templates/backend/README.md.template +39 -0
- package/bin/templates/backend/api.http.template +0 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
- package/bin/templates/backend/package.json.template +34 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
- package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
- package/bin/templates/backend/src/api/server.ts.template +188 -0
- package/bin/templates/backend/tsconfig.api.json.template +24 -0
- package/bin/templates/backend/tsconfig.json.template +40 -0
- package/bin/templates/feature/feature.http.template +63 -0
- package/bin/templates/feature/feature.route.ts.template +36 -0
- package/bin/templates/feature/feature.service.ts.template +81 -0
- package/bin/templates/feature/feature.types.ts.template +23 -0
- package/bin/templates/feature-db/feature.http.template +63 -0
- package/bin/templates/feature-db/feature.model.ts.template +74 -0
- package/bin/templates/feature-db/feature.route.ts.template +58 -0
- package/bin/templates/feature-db/feature.service.ts.template +231 -0
- package/bin/templates/feature-db/feature.types.ts.template +25 -0
- package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
- package/bin/templates/feature-db/seeding/README.md.template +57 -0
- package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
- package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
- package/bin/templates/feature-user/user.http.template +157 -0
- package/bin/templates/feature-user/user.model.ts.template +244 -0
- package/bin/templates/feature-user/user.route.ts.template +379 -0
- package/bin/templates/feature-user/user.seed.js.template +182 -0
- package/bin/templates/feature-user/user.service.ts.template +426 -0
- package/bin/templates/feature-user/user.types.ts.template +127 -0
- package/dist/auth/auth.d.ts +182 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +477 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/defaults.d.ts +104 -0
- package/dist/auth/defaults.d.ts.map +1 -0
- package/dist/auth/defaults.js +374 -0
- package/dist/auth/defaults.js.map +1 -0
- package/dist/auth/index.d.ts +70 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +94 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/cache.d.ts +118 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +249 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/defaults.d.ts +63 -0
- package/dist/cache/defaults.d.ts.map +1 -0
- package/dist/cache/defaults.js +193 -0
- package/dist/cache/defaults.js.map +1 -0
- package/dist/cache/index.d.ts +101 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +203 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/strategies/memory.d.ts +138 -0
- package/dist/cache/strategies/memory.d.ts.map +1 -0
- package/dist/cache/strategies/memory.js +348 -0
- package/dist/cache/strategies/memory.js.map +1 -0
- package/dist/cache/strategies/redis.d.ts +105 -0
- package/dist/cache/strategies/redis.d.ts.map +1 -0
- package/dist/cache/strategies/redis.js +318 -0
- package/dist/cache/strategies/redis.js.map +1 -0
- package/dist/config/config.d.ts +62 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +107 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +44 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +217 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +163 -0
- package/dist/config/index.js.map +1 -0
- package/dist/database/adapters/mongoose.d.ts +106 -0
- package/dist/database/adapters/mongoose.d.ts.map +1 -0
- package/dist/database/adapters/mongoose.js +480 -0
- package/dist/database/adapters/mongoose.js.map +1 -0
- package/dist/database/adapters/prisma.d.ts +106 -0
- package/dist/database/adapters/prisma.d.ts.map +1 -0
- package/dist/database/adapters/prisma.js +494 -0
- package/dist/database/adapters/prisma.js.map +1 -0
- package/dist/database/defaults.d.ts +87 -0
- package/dist/database/defaults.d.ts.map +1 -0
- package/dist/database/defaults.js +271 -0
- package/dist/database/defaults.js.map +1 -0
- package/dist/database/index.d.ts +137 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +490 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/defaults.d.ts +100 -0
- package/dist/email/defaults.d.ts.map +1 -0
- package/dist/email/defaults.js +400 -0
- package/dist/email/defaults.js.map +1 -0
- package/dist/email/email.d.ts +139 -0
- package/dist/email/email.d.ts.map +1 -0
- package/dist/email/email.js +316 -0
- package/dist/email/email.js.map +1 -0
- package/dist/email/index.d.ts +176 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +251 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/strategies/console.d.ts +90 -0
- package/dist/email/strategies/console.d.ts.map +1 -0
- package/dist/email/strategies/console.js +268 -0
- package/dist/email/strategies/console.js.map +1 -0
- package/dist/email/strategies/resend.d.ts +84 -0
- package/dist/email/strategies/resend.d.ts.map +1 -0
- package/dist/email/strategies/resend.js +266 -0
- package/dist/email/strategies/resend.js.map +1 -0
- package/dist/email/strategies/smtp.d.ts +77 -0
- package/dist/email/strategies/smtp.d.ts.map +1 -0
- package/dist/email/strategies/smtp.js +286 -0
- package/dist/email/strategies/smtp.js.map +1 -0
- package/dist/error/defaults.d.ts +40 -0
- package/dist/error/defaults.d.ts.map +1 -0
- package/dist/error/defaults.js +75 -0
- package/dist/error/defaults.js.map +1 -0
- package/dist/error/error.d.ts +140 -0
- package/dist/error/error.d.ts.map +1 -0
- package/dist/error/error.js +200 -0
- package/dist/error/error.js.map +1 -0
- package/dist/error/index.d.ts +145 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +145 -0
- package/dist/error/index.js.map +1 -0
- package/dist/event/defaults.d.ts +111 -0
- package/dist/event/defaults.d.ts.map +1 -0
- package/dist/event/defaults.js +378 -0
- package/dist/event/defaults.js.map +1 -0
- package/dist/event/event.d.ts +171 -0
- package/dist/event/event.d.ts.map +1 -0
- package/dist/event/event.js +391 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/index.d.ts +173 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/index.js +302 -0
- package/dist/event/index.js.map +1 -0
- package/dist/event/strategies/memory.d.ts +122 -0
- package/dist/event/strategies/memory.d.ts.map +1 -0
- package/dist/event/strategies/memory.js +331 -0
- package/dist/event/strategies/memory.js.map +1 -0
- package/dist/event/strategies/redis.d.ts +115 -0
- package/dist/event/strategies/redis.d.ts.map +1 -0
- package/dist/event/strategies/redis.js +434 -0
- package/dist/event/strategies/redis.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/defaults.d.ts +67 -0
- package/dist/logger/defaults.d.ts.map +1 -0
- package/dist/logger/defaults.js +213 -0
- package/dist/logger/defaults.js.map +1 -0
- package/dist/logger/index.d.ts +84 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +101 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/logger.d.ts +165 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +843 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logger/transports/console.d.ts +102 -0
- package/dist/logger/transports/console.d.ts.map +1 -0
- package/dist/logger/transports/console.js +276 -0
- package/dist/logger/transports/console.js.map +1 -0
- package/dist/logger/transports/database.d.ts +153 -0
- package/dist/logger/transports/database.d.ts.map +1 -0
- package/dist/logger/transports/database.js +539 -0
- package/dist/logger/transports/database.js.map +1 -0
- package/dist/logger/transports/file.d.ts +146 -0
- package/dist/logger/transports/file.d.ts.map +1 -0
- package/dist/logger/transports/file.js +464 -0
- package/dist/logger/transports/file.js.map +1 -0
- package/dist/logger/transports/http.d.ts +128 -0
- package/dist/logger/transports/http.d.ts.map +1 -0
- package/dist/logger/transports/http.js +401 -0
- package/dist/logger/transports/http.js.map +1 -0
- package/dist/logger/transports/webhook.d.ts +152 -0
- package/dist/logger/transports/webhook.d.ts.map +1 -0
- package/dist/logger/transports/webhook.js +485 -0
- package/dist/logger/transports/webhook.js.map +1 -0
- package/dist/queue/defaults.d.ts +66 -0
- package/dist/queue/defaults.d.ts.map +1 -0
- package/dist/queue/defaults.js +205 -0
- package/dist/queue/defaults.js.map +1 -0
- package/dist/queue/index.d.ts +124 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +116 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/queue.d.ts +156 -0
- package/dist/queue/queue.d.ts.map +1 -0
- package/dist/queue/queue.js +387 -0
- package/dist/queue/queue.js.map +1 -0
- package/dist/queue/transports/database.d.ts +165 -0
- package/dist/queue/transports/database.d.ts.map +1 -0
- package/dist/queue/transports/database.js +595 -0
- package/dist/queue/transports/database.js.map +1 -0
- package/dist/queue/transports/memory.d.ts +143 -0
- package/dist/queue/transports/memory.d.ts.map +1 -0
- package/dist/queue/transports/memory.js +415 -0
- package/dist/queue/transports/memory.js.map +1 -0
- package/dist/queue/transports/redis.d.ts +203 -0
- package/dist/queue/transports/redis.d.ts.map +1 -0
- package/dist/queue/transports/redis.js +744 -0
- package/dist/queue/transports/redis.js.map +1 -0
- package/dist/security/defaults.d.ts +64 -0
- package/dist/security/defaults.d.ts.map +1 -0
- package/dist/security/defaults.js +159 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/index.d.ts +110 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +160 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security.d.ts +138 -0
- package/dist/security/security.d.ts.map +1 -0
- package/dist/security/security.js +419 -0
- package/dist/security/security.js.map +1 -0
- package/dist/storage/defaults.d.ts +79 -0
- package/dist/storage/defaults.d.ts.map +1 -0
- package/dist/storage/defaults.js +358 -0
- package/dist/storage/defaults.js.map +1 -0
- package/dist/storage/index.d.ts +153 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +242 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/storage.d.ts +151 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +439 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/strategies/local.d.ts +117 -0
- package/dist/storage/strategies/local.d.ts.map +1 -0
- package/dist/storage/strategies/local.js +368 -0
- package/dist/storage/strategies/local.js.map +1 -0
- package/dist/storage/strategies/r2.d.ts +130 -0
- package/dist/storage/strategies/r2.d.ts.map +1 -0
- package/dist/storage/strategies/r2.js +470 -0
- package/dist/storage/strategies/r2.js.map +1 -0
- package/dist/storage/strategies/s3.d.ts +121 -0
- package/dist/storage/strategies/s3.d.ts.map +1 -0
- package/dist/storage/strategies/s3.js +461 -0
- package/dist/storage/strategies/s3.js.map +1 -0
- package/dist/util/defaults.d.ts +77 -0
- package/dist/util/defaults.d.ts.map +1 -0
- package/dist/util/defaults.js +193 -0
- package/dist/util/defaults.js.map +1 -0
- package/dist/util/index.d.ts +97 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +165 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/util.d.ts +145 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +481 -0
- package/dist/util/util.js.map +1 -0
- package/package.json +234 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/storage/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,WAAW,EAAE;QACX,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAsDhD;AAiRD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;CACrB,CAUA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C1G"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart defaults and environment validation for file storage with auto-strategy detection
|
|
3
|
+
* @module @bloomneo/appkit/storage
|
|
4
|
+
* @file src/storage/defaults.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: App startup - need to configure storage system and connection strategy
|
|
7
|
+
* @llm-rule AVOID: Calling multiple times - expensive environment parsing, use lazy loading in get()
|
|
8
|
+
* @llm-rule NOTE: Called once at startup, cached globally for performance
|
|
9
|
+
* @llm-rule NOTE: Auto-detects Local vs S3 vs R2 based on environment variables
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Gets smart defaults using environment variables with auto-strategy detection
|
|
13
|
+
* @llm-rule WHEN: App startup to get production-ready storage configuration
|
|
14
|
+
* @llm-rule AVOID: Calling repeatedly - expensive validation, cache the result
|
|
15
|
+
* @llm-rule NOTE: Auto-detects strategy: S3/R2 env vars → Cloud, nothing → Local
|
|
16
|
+
*/
|
|
17
|
+
export function getSmartDefaults() {
|
|
18
|
+
validateEnvironment();
|
|
19
|
+
const nodeEnv = process.env.NODE_ENV || 'development';
|
|
20
|
+
const isDevelopment = nodeEnv === 'development';
|
|
21
|
+
const isProduction = nodeEnv === 'production';
|
|
22
|
+
const isTest = nodeEnv === 'test';
|
|
23
|
+
// Auto-detect strategy from environment
|
|
24
|
+
const strategy = detectStorageStrategy();
|
|
25
|
+
return {
|
|
26
|
+
// Strategy selection with smart detection
|
|
27
|
+
strategy,
|
|
28
|
+
// Local configuration (only used when strategy is 'local')
|
|
29
|
+
local: {
|
|
30
|
+
dir: process.env.VOILA_STORAGE_DIR || './uploads',
|
|
31
|
+
baseUrl: process.env.VOILA_STORAGE_BASE_URL || '/uploads',
|
|
32
|
+
maxFileSize: parseInt(process.env.VOILA_STORAGE_MAX_SIZE || '52428800'), // 50MB default
|
|
33
|
+
allowedTypes: parseAllowedTypes(),
|
|
34
|
+
createDirs: process.env.VOILA_STORAGE_CREATE_DIRS !== 'false',
|
|
35
|
+
},
|
|
36
|
+
// S3 configuration (only used when strategy is 's3')
|
|
37
|
+
s3: {
|
|
38
|
+
bucket: process.env.AWS_S3_BUCKET || process.env.S3_BUCKET || '',
|
|
39
|
+
region: process.env.AWS_REGION || process.env.S3_REGION || 'us-east-1',
|
|
40
|
+
endpoint: process.env.S3_ENDPOINT,
|
|
41
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID || process.env.S3_ACCESS_KEY_ID || '',
|
|
42
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || process.env.S3_SECRET_ACCESS_KEY || '',
|
|
43
|
+
forcePathStyle: process.env.S3_FORCE_PATH_STYLE === 'true',
|
|
44
|
+
signedUrlExpiry: parseInt(process.env.VOILA_STORAGE_SIGNED_EXPIRY || '3600'), // 1 hour
|
|
45
|
+
cdnUrl: process.env.VOILA_STORAGE_CDN_URL,
|
|
46
|
+
},
|
|
47
|
+
// R2 configuration (only used when strategy is 'r2')
|
|
48
|
+
r2: {
|
|
49
|
+
bucket: process.env.CLOUDFLARE_R2_BUCKET || '',
|
|
50
|
+
accountId: process.env.CLOUDFLARE_ACCOUNT_ID || '',
|
|
51
|
+
accessKeyId: process.env.CLOUDFLARE_R2_ACCESS_KEY_ID || '',
|
|
52
|
+
secretAccessKey: process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY || '',
|
|
53
|
+
cdnUrl: process.env.CLOUDFLARE_R2_CDN_URL,
|
|
54
|
+
signedUrlExpiry: parseInt(process.env.VOILA_STORAGE_SIGNED_EXPIRY || '3600'), // 1 hour
|
|
55
|
+
},
|
|
56
|
+
// Environment information
|
|
57
|
+
environment: {
|
|
58
|
+
isDevelopment,
|
|
59
|
+
isProduction,
|
|
60
|
+
isTest,
|
|
61
|
+
nodeEnv,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Auto-detect storage strategy from environment variables
|
|
67
|
+
* @llm-rule WHEN: Determining which storage strategy to use automatically
|
|
68
|
+
* @llm-rule AVOID: Manual strategy selection - environment detection handles most cases
|
|
69
|
+
* @llm-rule NOTE: Priority: R2 → S3 → Local (R2 has zero egress fees)
|
|
70
|
+
*/
|
|
71
|
+
function detectStorageStrategy() {
|
|
72
|
+
// Explicit override wins (for testing/debugging)
|
|
73
|
+
const explicit = process.env.VOILA_STORAGE_STRATEGY?.toLowerCase();
|
|
74
|
+
if (explicit && ['local', 's3', 'r2'].includes(explicit)) {
|
|
75
|
+
return explicit;
|
|
76
|
+
}
|
|
77
|
+
// Auto-detection logic - prioritize R2 for cost savings
|
|
78
|
+
if (process.env.CLOUDFLARE_R2_BUCKET) {
|
|
79
|
+
return 'r2'; // Cloudflare R2 - zero egress fees
|
|
80
|
+
}
|
|
81
|
+
if (process.env.AWS_S3_BUCKET || process.env.S3_BUCKET || process.env.S3_ENDPOINT) {
|
|
82
|
+
return 's3'; // S3-compatible services
|
|
83
|
+
}
|
|
84
|
+
// Default to local for development/single server
|
|
85
|
+
if (process.env.NODE_ENV === 'production') {
|
|
86
|
+
console.warn('[VoilaJSX AppKit] No cloud storage configured in production. ' +
|
|
87
|
+
'Using local filesystem which may not scale. ' +
|
|
88
|
+
'Set AWS_S3_BUCKET or CLOUDFLARE_R2_BUCKET for cloud storage.');
|
|
89
|
+
}
|
|
90
|
+
return 'local'; // Default to local filesystem
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Parse allowed file types from environment with safe defaults
|
|
94
|
+
* @llm-rule WHEN: Setting up file type restrictions for security
|
|
95
|
+
* @llm-rule AVOID: Allowing all file types in production - security risk
|
|
96
|
+
*/
|
|
97
|
+
function parseAllowedTypes() {
|
|
98
|
+
const envTypes = process.env.VOILA_STORAGE_ALLOWED_TYPES;
|
|
99
|
+
if (!envTypes) {
|
|
100
|
+
// Safe defaults - common web file types
|
|
101
|
+
return [
|
|
102
|
+
'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
|
|
103
|
+
'text/plain', 'text/csv', 'application/json',
|
|
104
|
+
'application/pdf', 'application/zip',
|
|
105
|
+
'video/mp4', 'video/webm', 'audio/mpeg', 'audio/wav'
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
if (envTypes === '*') {
|
|
109
|
+
if (process.env.NODE_ENV === 'production') {
|
|
110
|
+
console.warn('[VoilaJSX AppKit] SECURITY WARNING: All file types allowed in production. ' +
|
|
111
|
+
'Set VOILA_STORAGE_ALLOWED_TYPES to specific types for security.');
|
|
112
|
+
}
|
|
113
|
+
return ['*']; // Allow all types (use with caution)
|
|
114
|
+
}
|
|
115
|
+
return envTypes.split(',').map(type => type.trim()).filter(Boolean);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Validates environment variables for storage configuration
|
|
119
|
+
* @llm-rule WHEN: App startup to ensure proper storage environment configuration
|
|
120
|
+
* @llm-rule AVOID: Skipping validation - improper config causes runtime failures
|
|
121
|
+
* @llm-rule NOTE: Validates cloud credentials, bucket names, and numeric values
|
|
122
|
+
*/
|
|
123
|
+
function validateEnvironment() {
|
|
124
|
+
// Validate storage strategy if explicitly set
|
|
125
|
+
const strategy = process.env.VOILA_STORAGE_STRATEGY;
|
|
126
|
+
if (strategy && !['local', 's3', 'r2'].includes(strategy.toLowerCase())) {
|
|
127
|
+
throw new Error(`Invalid VOILA_STORAGE_STRATEGY: "${strategy}". Must be "local", "s3", or "r2"`);
|
|
128
|
+
}
|
|
129
|
+
// Validate numeric values
|
|
130
|
+
validateNumericEnv('VOILA_STORAGE_MAX_SIZE', 1048576, 1073741824); // 1MB to 1GB
|
|
131
|
+
validateNumericEnv('VOILA_STORAGE_SIGNED_EXPIRY', 60, 604800); // 1 minute to 7 days
|
|
132
|
+
// Validate S3 configuration if S3 strategy detected
|
|
133
|
+
if (shouldValidateS3()) {
|
|
134
|
+
validateS3Config();
|
|
135
|
+
}
|
|
136
|
+
// Validate R2 configuration if R2 strategy detected
|
|
137
|
+
if (shouldValidateR2()) {
|
|
138
|
+
validateR2Config();
|
|
139
|
+
}
|
|
140
|
+
// Validate local configuration if local strategy
|
|
141
|
+
if (shouldValidateLocal()) {
|
|
142
|
+
validateLocalConfig();
|
|
143
|
+
}
|
|
144
|
+
// Production-specific validations
|
|
145
|
+
const nodeEnv = process.env.NODE_ENV;
|
|
146
|
+
if (nodeEnv === 'production') {
|
|
147
|
+
validateProductionConfig();
|
|
148
|
+
}
|
|
149
|
+
// Validate NODE_ENV
|
|
150
|
+
if (nodeEnv && !['development', 'production', 'test', 'staging'].includes(nodeEnv)) {
|
|
151
|
+
console.warn(`[VoilaJSX AppKit] Unusual NODE_ENV: "${nodeEnv}". ` +
|
|
152
|
+
`Expected: development, production, test, or staging`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check if S3 validation is needed
|
|
157
|
+
*/
|
|
158
|
+
function shouldValidateS3() {
|
|
159
|
+
return !!(process.env.AWS_S3_BUCKET || process.env.S3_BUCKET || process.env.S3_ENDPOINT);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if R2 validation is needed
|
|
163
|
+
*/
|
|
164
|
+
function shouldValidateR2() {
|
|
165
|
+
return !!process.env.CLOUDFLARE_R2_BUCKET;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if local validation is needed
|
|
169
|
+
*/
|
|
170
|
+
function shouldValidateLocal() {
|
|
171
|
+
const strategy = detectStorageStrategy();
|
|
172
|
+
return strategy === 'local';
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Validates S3 configuration
|
|
176
|
+
*/
|
|
177
|
+
function validateS3Config() {
|
|
178
|
+
const bucket = process.env.AWS_S3_BUCKET || process.env.S3_BUCKET;
|
|
179
|
+
if (!bucket) {
|
|
180
|
+
throw new Error('S3 bucket name required. Set AWS_S3_BUCKET or S3_BUCKET environment variable');
|
|
181
|
+
}
|
|
182
|
+
if (!isValidBucketName(bucket)) {
|
|
183
|
+
throw new Error(`Invalid S3 bucket name: "${bucket}". Must be 3-63 characters, lowercase, no dots`);
|
|
184
|
+
}
|
|
185
|
+
const accessKey = process.env.AWS_ACCESS_KEY_ID || process.env.S3_ACCESS_KEY_ID;
|
|
186
|
+
const secretKey = process.env.AWS_SECRET_ACCESS_KEY || process.env.S3_SECRET_ACCESS_KEY;
|
|
187
|
+
if (!accessKey || !secretKey) {
|
|
188
|
+
throw new Error('S3 credentials required. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables');
|
|
189
|
+
}
|
|
190
|
+
const endpoint = process.env.S3_ENDPOINT;
|
|
191
|
+
if (endpoint && !isValidUrl(endpoint)) {
|
|
192
|
+
throw new Error(`Invalid S3 endpoint: "${endpoint}". Must be a valid URL`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Validates R2 configuration
|
|
197
|
+
*/
|
|
198
|
+
function validateR2Config() {
|
|
199
|
+
const bucket = process.env.CLOUDFLARE_R2_BUCKET;
|
|
200
|
+
if (!bucket) {
|
|
201
|
+
throw new Error('R2 bucket name required. Set CLOUDFLARE_R2_BUCKET environment variable');
|
|
202
|
+
}
|
|
203
|
+
if (!isValidBucketName(bucket)) {
|
|
204
|
+
throw new Error(`Invalid R2 bucket name: "${bucket}". Must be 3-63 characters, lowercase`);
|
|
205
|
+
}
|
|
206
|
+
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
207
|
+
const accessKey = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID;
|
|
208
|
+
const secretKey = process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY;
|
|
209
|
+
if (!accountId || !accessKey || !secretKey) {
|
|
210
|
+
throw new Error('R2 credentials required. Set CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_R2_ACCESS_KEY_ID, and CLOUDFLARE_R2_SECRET_ACCESS_KEY environment variables');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Validates local configuration
|
|
215
|
+
*/
|
|
216
|
+
function validateLocalConfig() {
|
|
217
|
+
const dir = process.env.VOILA_STORAGE_DIR;
|
|
218
|
+
if (dir && (dir.includes('..') || dir.startsWith('/') && process.env.NODE_ENV === 'production')) {
|
|
219
|
+
console.warn(`[VoilaJSX AppKit] Potentially unsafe storage directory: "${dir}". ` +
|
|
220
|
+
`Consider using a relative path for security.`);
|
|
221
|
+
}
|
|
222
|
+
const baseUrl = process.env.VOILA_STORAGE_BASE_URL;
|
|
223
|
+
if (baseUrl && !baseUrl.startsWith('/') && !isValidUrl(baseUrl)) {
|
|
224
|
+
throw new Error(`Invalid VOILA_STORAGE_BASE_URL: "${baseUrl}". Must be a path or valid URL`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Validates production storage configuration
|
|
229
|
+
* @llm-rule WHEN: Running in production environment
|
|
230
|
+
* @llm-rule AVOID: Local storage in multi-server production - files won't sync across servers
|
|
231
|
+
*/
|
|
232
|
+
function validateProductionConfig() {
|
|
233
|
+
const strategy = detectStorageStrategy();
|
|
234
|
+
if (strategy === 'local') {
|
|
235
|
+
console.warn('[VoilaJSX AppKit] Using local storage in production. ' +
|
|
236
|
+
'Files will only exist on single server instance. ' +
|
|
237
|
+
'Set AWS_S3_BUCKET or CLOUDFLARE_R2_BUCKET for distributed storage.');
|
|
238
|
+
}
|
|
239
|
+
// Warn about missing CDN in production
|
|
240
|
+
const cdnUrl = process.env.VOILA_STORAGE_CDN_URL || process.env.CLOUDFLARE_R2_CDN_URL;
|
|
241
|
+
if (!cdnUrl && strategy !== 'local') {
|
|
242
|
+
console.warn('[VoilaJSX AppKit] No CDN URL configured in production. ' +
|
|
243
|
+
'Set VOILA_STORAGE_CDN_URL for better performance.');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Validates bucket name format (S3/R2 compatible)
|
|
248
|
+
*/
|
|
249
|
+
function isValidBucketName(name) {
|
|
250
|
+
if (name.length < 3 || name.length > 63)
|
|
251
|
+
return false;
|
|
252
|
+
if (name !== name.toLowerCase())
|
|
253
|
+
return false;
|
|
254
|
+
if (name.includes('..') || name.includes('.-') || name.includes('-.'))
|
|
255
|
+
return false;
|
|
256
|
+
if (name.startsWith('-') || name.endsWith('-'))
|
|
257
|
+
return false;
|
|
258
|
+
if (name.startsWith('.') || name.endsWith('.'))
|
|
259
|
+
return false;
|
|
260
|
+
return /^[a-z0-9.-]+$/.test(name);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Validates URL format
|
|
264
|
+
*/
|
|
265
|
+
function isValidUrl(url) {
|
|
266
|
+
try {
|
|
267
|
+
new URL(url);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Validates numeric environment variable within acceptable range
|
|
276
|
+
*/
|
|
277
|
+
function validateNumericEnv(name, min, max) {
|
|
278
|
+
const value = process.env[name];
|
|
279
|
+
if (!value)
|
|
280
|
+
return;
|
|
281
|
+
const num = parseInt(value);
|
|
282
|
+
if (isNaN(num) || num < min || num > max) {
|
|
283
|
+
throw new Error(`Invalid ${name}: "${value}". Must be a number between ${min} and ${max}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Gets storage configuration summary for debugging and health checks
|
|
288
|
+
* @llm-rule WHEN: Debugging storage configuration or building health check endpoints
|
|
289
|
+
* @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
|
|
290
|
+
*/
|
|
291
|
+
export function getConfigSummary() {
|
|
292
|
+
const config = getSmartDefaults();
|
|
293
|
+
return {
|
|
294
|
+
strategy: config.strategy,
|
|
295
|
+
local: config.strategy === 'local',
|
|
296
|
+
s3: config.strategy === 's3',
|
|
297
|
+
r2: config.strategy === 'r2',
|
|
298
|
+
environment: config.environment.nodeEnv,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Checks if cloud storage is available and properly configured
|
|
303
|
+
* @llm-rule WHEN: Conditional logic based on storage capabilities
|
|
304
|
+
* @llm-rule AVOID: Complex storage detection - just use storage normally, strategy handles it
|
|
305
|
+
*/
|
|
306
|
+
export function hasCloudStorage() {
|
|
307
|
+
const strategy = detectStorageStrategy();
|
|
308
|
+
return strategy === 's3' || strategy === 'r2';
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Gets recommended configuration for different deployment types
|
|
312
|
+
* @llm-rule WHEN: Setting up storage for specific deployment scenarios
|
|
313
|
+
* @llm-rule AVOID: Default config for specialized deployments - needs specific tuning
|
|
314
|
+
*/
|
|
315
|
+
export function getDeploymentConfig(type) {
|
|
316
|
+
switch (type) {
|
|
317
|
+
case 'development':
|
|
318
|
+
return {
|
|
319
|
+
strategy: 'local',
|
|
320
|
+
local: {
|
|
321
|
+
dir: './uploads',
|
|
322
|
+
baseUrl: '/uploads',
|
|
323
|
+
maxFileSize: 10485760, // 10MB
|
|
324
|
+
allowedTypes: ['*'], // Allow all for development
|
|
325
|
+
createDirs: true,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
case 'staging':
|
|
329
|
+
return {
|
|
330
|
+
strategy: hasCloudStorage() ? detectStorageStrategy() : 'local',
|
|
331
|
+
local: {
|
|
332
|
+
dir: './uploads-staging',
|
|
333
|
+
baseUrl: '/uploads',
|
|
334
|
+
maxFileSize: 26214400, // 25MB
|
|
335
|
+
allowedTypes: parseAllowedTypes(),
|
|
336
|
+
createDirs: true,
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
case 'production':
|
|
340
|
+
const strategy = detectStorageStrategy();
|
|
341
|
+
if (strategy === 'local') {
|
|
342
|
+
console.warn('[VoilaJSX AppKit] Local storage not recommended for production');
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
strategy,
|
|
346
|
+
local: {
|
|
347
|
+
dir: './uploads-prod',
|
|
348
|
+
baseUrl: '/uploads',
|
|
349
|
+
maxFileSize: 52428800, // 50MB
|
|
350
|
+
allowedTypes: parseAllowedTypes(),
|
|
351
|
+
createDirs: false, // Don't auto-create in production
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
default:
|
|
355
|
+
throw new Error(`Unknown deployment type: ${type}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/storage/defaults.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultra-simple file storage that just works with automatic Local/S3/R2 strategy
|
|
3
|
+
* @module @bloomneo/appkit/storage
|
|
4
|
+
* @file src/storage/index.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need file storage with zero configuration
|
|
7
|
+
* @llm-rule AVOID: Complex storage setups - this auto-detects Local/S3/R2 from environment
|
|
8
|
+
* @llm-rule NOTE: Uses storageClass.get() pattern like auth - get() → storage.put() → distributed
|
|
9
|
+
* @llm-rule NOTE: Common pattern - storageClass.get() → storage.put() → storage.url() → served
|
|
10
|
+
*/
|
|
11
|
+
import { StorageClass } from './storage.js';
|
|
12
|
+
import { type StorageConfig } from './defaults.js';
|
|
13
|
+
export interface Storage {
|
|
14
|
+
put(key: string, data: Buffer | Uint8Array | string, options?: PutOptions): Promise<string>;
|
|
15
|
+
get(key: string): Promise<Buffer>;
|
|
16
|
+
delete(key: string): Promise<boolean>;
|
|
17
|
+
list(prefix?: string, limit?: number): Promise<StorageFile[]>;
|
|
18
|
+
url(key: string): string;
|
|
19
|
+
signedUrl(key: string, expiresIn?: number): Promise<string>;
|
|
20
|
+
exists(key: string): Promise<boolean>;
|
|
21
|
+
copy(sourceKey: string, destKey: string): Promise<string>;
|
|
22
|
+
disconnect(): Promise<void>;
|
|
23
|
+
getStrategy(): string;
|
|
24
|
+
getConfig(): any;
|
|
25
|
+
}
|
|
26
|
+
export interface StorageFile {
|
|
27
|
+
key: string;
|
|
28
|
+
size: number;
|
|
29
|
+
lastModified: Date;
|
|
30
|
+
etag?: string;
|
|
31
|
+
contentType?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PutOptions {
|
|
34
|
+
contentType?: string;
|
|
35
|
+
metadata?: Record<string, string>;
|
|
36
|
+
cacheControl?: string;
|
|
37
|
+
expires?: Date;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get storage instance - the only function you need to learn
|
|
41
|
+
* Strategy auto-detected from environment (S3/R2 env vars → Cloud, nothing → Local)
|
|
42
|
+
* @llm-rule WHEN: Need file storage in any part of your app - this is your main entry point
|
|
43
|
+
* @llm-rule AVOID: Creating StorageClass directly - always use this function
|
|
44
|
+
* @llm-rule NOTE: Typical flow - get() → storage.put() → storage.url() → file served
|
|
45
|
+
*/
|
|
46
|
+
declare function get(overrides?: Partial<StorageConfig>): Storage;
|
|
47
|
+
/**
|
|
48
|
+
* Clear storage instance and disconnect - essential for testing
|
|
49
|
+
* @llm-rule WHEN: Testing storage logic with different configurations or app shutdown
|
|
50
|
+
* @llm-rule AVOID: Using in production except for graceful shutdown
|
|
51
|
+
*/
|
|
52
|
+
declare function clear(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Reset storage configuration (useful for testing)
|
|
55
|
+
* @llm-rule WHEN: Testing storage logic with different environment configurations
|
|
56
|
+
* @llm-rule AVOID: Using in production - only for tests and development
|
|
57
|
+
*/
|
|
58
|
+
declare function reset(newConfig?: Partial<StorageConfig>): Storage;
|
|
59
|
+
/**
|
|
60
|
+
* Get active storage strategy for debugging
|
|
61
|
+
* @llm-rule WHEN: Debugging or health checks to see which strategy is active (Local vs S3 vs R2)
|
|
62
|
+
* @llm-rule AVOID: Using for application logic - storage should be transparent
|
|
63
|
+
*/
|
|
64
|
+
declare function getStrategy(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Get storage configuration summary for debugging
|
|
67
|
+
* @llm-rule WHEN: Health checks or debugging storage configuration
|
|
68
|
+
* @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
|
|
69
|
+
*/
|
|
70
|
+
declare function getConfig(): {
|
|
71
|
+
strategy: string;
|
|
72
|
+
connected: boolean;
|
|
73
|
+
maxFileSize: number;
|
|
74
|
+
allowedTypes: string[];
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Check if cloud storage is available and configured
|
|
78
|
+
* @llm-rule WHEN: Conditional logic based on storage capabilities
|
|
79
|
+
* @llm-rule AVOID: Complex storage detection - just use storage normally, strategy handles it
|
|
80
|
+
*/
|
|
81
|
+
declare function hasCloudStorage(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Check if local storage is being used
|
|
84
|
+
* @llm-rule WHEN: Development vs production feature detection
|
|
85
|
+
* @llm-rule AVOID: Using for business logic - storage should be transparent
|
|
86
|
+
*/
|
|
87
|
+
declare function isLocal(): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Validate storage configuration at startup
|
|
90
|
+
* @llm-rule WHEN: App startup to ensure storage is properly configured
|
|
91
|
+
* @llm-rule AVOID: Skipping validation - missing storage config causes runtime failures
|
|
92
|
+
*/
|
|
93
|
+
declare function validateConfig(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Get storage statistics for monitoring
|
|
96
|
+
* @llm-rule WHEN: Monitoring storage system health and usage
|
|
97
|
+
* @llm-rule AVOID: Using for business logic - this is for monitoring only
|
|
98
|
+
*/
|
|
99
|
+
declare function getStats(): {
|
|
100
|
+
strategy: string;
|
|
101
|
+
connected: boolean;
|
|
102
|
+
maxFileSize: string;
|
|
103
|
+
environment: string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Graceful shutdown for storage system
|
|
107
|
+
* @llm-rule WHEN: App shutdown or process termination
|
|
108
|
+
* @llm-rule AVOID: Abrupt process exit - graceful shutdown prevents data corruption
|
|
109
|
+
*/
|
|
110
|
+
declare function shutdown(): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Upload helper with common patterns
|
|
113
|
+
* @llm-rule WHEN: Quick file uploads with automatic naming and validation
|
|
114
|
+
* @llm-rule AVOID: Manual key generation - this handles common upload patterns
|
|
115
|
+
*/
|
|
116
|
+
declare function upload(file: Buffer | Uint8Array | string, options?: {
|
|
117
|
+
folder?: string;
|
|
118
|
+
filename?: string;
|
|
119
|
+
contentType?: string;
|
|
120
|
+
}): Promise<{
|
|
121
|
+
key: string;
|
|
122
|
+
url: string;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* Download helper with error handling
|
|
126
|
+
* @llm-rule WHEN: Quick file downloads with automatic error handling
|
|
127
|
+
* @llm-rule AVOID: Manual error handling - this provides consistent download experience
|
|
128
|
+
*/
|
|
129
|
+
declare function download(key: string): Promise<{
|
|
130
|
+
data: Buffer;
|
|
131
|
+
contentType?: string;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Single storage export with minimal API (like auth module)
|
|
135
|
+
*/
|
|
136
|
+
export declare const storageClass: {
|
|
137
|
+
readonly get: typeof get;
|
|
138
|
+
readonly clear: typeof clear;
|
|
139
|
+
readonly reset: typeof reset;
|
|
140
|
+
readonly getStrategy: typeof getStrategy;
|
|
141
|
+
readonly getConfig: typeof getConfig;
|
|
142
|
+
readonly hasCloudStorage: typeof hasCloudStorage;
|
|
143
|
+
readonly isLocal: typeof isLocal;
|
|
144
|
+
readonly getStats: typeof getStats;
|
|
145
|
+
readonly validateConfig: typeof validateConfig;
|
|
146
|
+
readonly shutdown: typeof shutdown;
|
|
147
|
+
readonly upload: typeof upload;
|
|
148
|
+
readonly download: typeof download;
|
|
149
|
+
};
|
|
150
|
+
export type { StorageConfig } from './defaults.js';
|
|
151
|
+
export { StorageClass } from './storage.js';
|
|
152
|
+
export default StorageClass;
|
|
153
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}
|