@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,242 @@
|
|
|
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 { getSmartDefaults } from './defaults.js';
|
|
13
|
+
// Global storage instance for performance (like auth module)
|
|
14
|
+
let globalStorage = null;
|
|
15
|
+
/**
|
|
16
|
+
* Get storage instance - the only function you need to learn
|
|
17
|
+
* Strategy auto-detected from environment (S3/R2 env vars → Cloud, nothing → Local)
|
|
18
|
+
* @llm-rule WHEN: Need file storage in any part of your app - this is your main entry point
|
|
19
|
+
* @llm-rule AVOID: Creating StorageClass directly - always use this function
|
|
20
|
+
* @llm-rule NOTE: Typical flow - get() → storage.put() → storage.url() → file served
|
|
21
|
+
*/
|
|
22
|
+
function get(overrides = {}) {
|
|
23
|
+
// Lazy initialization - parse environment once (like auth)
|
|
24
|
+
if (!globalStorage) {
|
|
25
|
+
const defaults = getSmartDefaults();
|
|
26
|
+
const config = { ...defaults, ...overrides };
|
|
27
|
+
globalStorage = new StorageClass(config);
|
|
28
|
+
}
|
|
29
|
+
return globalStorage;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Clear storage instance and disconnect - essential for testing
|
|
33
|
+
* @llm-rule WHEN: Testing storage logic with different configurations or app shutdown
|
|
34
|
+
* @llm-rule AVOID: Using in production except for graceful shutdown
|
|
35
|
+
*/
|
|
36
|
+
async function clear() {
|
|
37
|
+
if (globalStorage) {
|
|
38
|
+
await globalStorage.disconnect();
|
|
39
|
+
globalStorage = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reset storage configuration (useful for testing)
|
|
44
|
+
* @llm-rule WHEN: Testing storage logic with different environment configurations
|
|
45
|
+
* @llm-rule AVOID: Using in production - only for tests and development
|
|
46
|
+
*/
|
|
47
|
+
function reset(newConfig = {}) {
|
|
48
|
+
// Clear existing instance
|
|
49
|
+
if (globalStorage) {
|
|
50
|
+
globalStorage.disconnect().catch(console.error);
|
|
51
|
+
globalStorage = null;
|
|
52
|
+
}
|
|
53
|
+
// Create new instance with config
|
|
54
|
+
const defaults = getSmartDefaults();
|
|
55
|
+
const config = { ...defaults, ...newConfig };
|
|
56
|
+
globalStorage = new StorageClass(config);
|
|
57
|
+
return globalStorage;
|
|
58
|
+
}
|
|
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
|
+
function getStrategy() {
|
|
65
|
+
const storage = get();
|
|
66
|
+
return storage.getStrategy();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get storage configuration summary for debugging
|
|
70
|
+
* @llm-rule WHEN: Health checks or debugging storage configuration
|
|
71
|
+
* @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
|
|
72
|
+
*/
|
|
73
|
+
function getConfig() {
|
|
74
|
+
const storage = get();
|
|
75
|
+
return storage.getConfig();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if cloud storage is available and configured
|
|
79
|
+
* @llm-rule WHEN: Conditional logic based on storage capabilities
|
|
80
|
+
* @llm-rule AVOID: Complex storage detection - just use storage normally, strategy handles it
|
|
81
|
+
*/
|
|
82
|
+
function hasCloudStorage() {
|
|
83
|
+
const strategy = getStrategy();
|
|
84
|
+
return strategy === 's3' || strategy === 'r2';
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if local storage is being used
|
|
88
|
+
* @llm-rule WHEN: Development vs production feature detection
|
|
89
|
+
* @llm-rule AVOID: Using for business logic - storage should be transparent
|
|
90
|
+
*/
|
|
91
|
+
function isLocal() {
|
|
92
|
+
return getStrategy() === 'local';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate storage configuration at startup
|
|
96
|
+
* @llm-rule WHEN: App startup to ensure storage is properly configured
|
|
97
|
+
* @llm-rule AVOID: Skipping validation - missing storage config causes runtime failures
|
|
98
|
+
*/
|
|
99
|
+
function validateConfig() {
|
|
100
|
+
try {
|
|
101
|
+
const strategy = getStrategy();
|
|
102
|
+
if (strategy === 'local' && process.env.NODE_ENV === 'production') {
|
|
103
|
+
console.warn('[VoilaJSX AppKit] Using local storage in production. ' +
|
|
104
|
+
'Files will only exist on single server instance. ' +
|
|
105
|
+
'Set AWS_S3_BUCKET or CLOUDFLARE_R2_BUCKET for distributed storage.');
|
|
106
|
+
}
|
|
107
|
+
if (process.env.NODE_ENV === 'production' && !hasCloudStorage()) {
|
|
108
|
+
console.warn('[VoilaJSX AppKit] No cloud storage configured in production. ' +
|
|
109
|
+
'Set AWS_S3_BUCKET or CLOUDFLARE_R2_BUCKET for scalable file storage.');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('[VoilaJSX AppKit] Storage configuration validation failed:', error.message);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get storage statistics for monitoring
|
|
118
|
+
* @llm-rule WHEN: Monitoring storage system health and usage
|
|
119
|
+
* @llm-rule AVOID: Using for business logic - this is for monitoring only
|
|
120
|
+
*/
|
|
121
|
+
function getStats() {
|
|
122
|
+
const config = getConfig();
|
|
123
|
+
return {
|
|
124
|
+
strategy: config.strategy,
|
|
125
|
+
connected: config.connected,
|
|
126
|
+
maxFileSize: `${Math.round(config.maxFileSize / 1048576)}MB`,
|
|
127
|
+
environment: process.env.NODE_ENV || 'development',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Graceful shutdown for storage system
|
|
132
|
+
* @llm-rule WHEN: App shutdown or process termination
|
|
133
|
+
* @llm-rule AVOID: Abrupt process exit - graceful shutdown prevents data corruption
|
|
134
|
+
*/
|
|
135
|
+
async function shutdown() {
|
|
136
|
+
console.log('🔄 [AppKit] Storage graceful shutdown...');
|
|
137
|
+
try {
|
|
138
|
+
await clear();
|
|
139
|
+
console.log('✅ [AppKit] Storage shutdown complete');
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error('❌ [AppKit] Storage shutdown error:', error.message);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Upload helper with common patterns
|
|
147
|
+
* @llm-rule WHEN: Quick file uploads with automatic naming and validation
|
|
148
|
+
* @llm-rule AVOID: Manual key generation - this handles common upload patterns
|
|
149
|
+
*/
|
|
150
|
+
async function upload(file, options) {
|
|
151
|
+
const storage = get();
|
|
152
|
+
// Generate key with folder structure
|
|
153
|
+
const timestamp = Date.now();
|
|
154
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
155
|
+
const folder = options?.folder ? `${options.folder}/` : '';
|
|
156
|
+
const filename = options?.filename || `file-${timestamp}-${random}`;
|
|
157
|
+
const key = `${folder}${filename}`;
|
|
158
|
+
// Upload file
|
|
159
|
+
const resultKey = await storage.put(key, file, {
|
|
160
|
+
contentType: options?.contentType,
|
|
161
|
+
});
|
|
162
|
+
// Get public URL
|
|
163
|
+
const url = storage.url(resultKey);
|
|
164
|
+
return { key: resultKey, url };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Download helper with error handling
|
|
168
|
+
* @llm-rule WHEN: Quick file downloads with automatic error handling
|
|
169
|
+
* @llm-rule AVOID: Manual error handling - this provides consistent download experience
|
|
170
|
+
*/
|
|
171
|
+
async function download(key) {
|
|
172
|
+
const storage = get();
|
|
173
|
+
try {
|
|
174
|
+
const data = await storage.get(key);
|
|
175
|
+
// Try to determine content type from extension
|
|
176
|
+
const ext = key.split('.').pop()?.toLowerCase();
|
|
177
|
+
const contentTypes = {
|
|
178
|
+
'jpg': 'image/jpeg',
|
|
179
|
+
'jpeg': 'image/jpeg',
|
|
180
|
+
'png': 'image/png',
|
|
181
|
+
'gif': 'image/gif',
|
|
182
|
+
'pdf': 'application/pdf',
|
|
183
|
+
'txt': 'text/plain',
|
|
184
|
+
'json': 'application/json',
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
data,
|
|
188
|
+
contentType: ext ? contentTypes[ext] : undefined,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
throw new Error(`Failed to download file: ${key}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Single storage export with minimal API (like auth module)
|
|
197
|
+
*/
|
|
198
|
+
export const storageClass = {
|
|
199
|
+
// Core method (like auth.get())
|
|
200
|
+
get,
|
|
201
|
+
// Utility methods
|
|
202
|
+
clear,
|
|
203
|
+
reset,
|
|
204
|
+
getStrategy,
|
|
205
|
+
getConfig,
|
|
206
|
+
hasCloudStorage,
|
|
207
|
+
isLocal,
|
|
208
|
+
getStats,
|
|
209
|
+
validateConfig,
|
|
210
|
+
shutdown,
|
|
211
|
+
// Helper methods
|
|
212
|
+
upload,
|
|
213
|
+
download,
|
|
214
|
+
};
|
|
215
|
+
export { StorageClass } from './storage.js';
|
|
216
|
+
// Default export
|
|
217
|
+
export default StorageClass;
|
|
218
|
+
// Auto-setup graceful shutdown handlers
|
|
219
|
+
if (typeof process !== 'undefined') {
|
|
220
|
+
// Handle graceful shutdown
|
|
221
|
+
const shutdownHandler = () => {
|
|
222
|
+
shutdown().finally(() => {
|
|
223
|
+
process.exit(0);
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
process.on('SIGTERM', shutdownHandler);
|
|
227
|
+
process.on('SIGINT', shutdownHandler);
|
|
228
|
+
// Handle uncaught errors
|
|
229
|
+
process.on('uncaughtException', (error) => {
|
|
230
|
+
console.error('[AppKit] Uncaught exception during storage operation:', error);
|
|
231
|
+
shutdown().finally(() => {
|
|
232
|
+
process.exit(1);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
process.on('unhandledRejection', (reason) => {
|
|
236
|
+
console.error('[AppKit] Unhandled rejection during storage operation:', reason);
|
|
237
|
+
shutdown().finally(() => {
|
|
238
|
+
process.exit(1);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core storage class with automatic strategy selection and ultra-simple API
|
|
3
|
+
* @module @bloomneo/appkit/storage
|
|
4
|
+
* @file src/storage/storage.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need file storage with automatic Local/S3/R2 selection
|
|
7
|
+
* @llm-rule AVOID: Using directly - always get instance via storageClass.get()
|
|
8
|
+
* @llm-rule NOTE: Auto-detects Local vs S3 vs R2 based on environment variables
|
|
9
|
+
*/
|
|
10
|
+
import type { StorageConfig } from './defaults.js';
|
|
11
|
+
export interface StorageStrategy {
|
|
12
|
+
put(key: string, data: Buffer | Uint8Array | string): Promise<string>;
|
|
13
|
+
get(key: string): Promise<Buffer>;
|
|
14
|
+
delete(key: string): Promise<boolean>;
|
|
15
|
+
list(prefix: string): Promise<StorageFile[]>;
|
|
16
|
+
url(key: string): string;
|
|
17
|
+
signedUrl?(key: string, expiresIn?: number): Promise<string>;
|
|
18
|
+
exists(key: string): Promise<boolean>;
|
|
19
|
+
disconnect(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface StorageFile {
|
|
22
|
+
key: string;
|
|
23
|
+
size: number;
|
|
24
|
+
lastModified: Date;
|
|
25
|
+
etag?: string;
|
|
26
|
+
contentType?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface PutOptions {
|
|
29
|
+
contentType?: string;
|
|
30
|
+
metadata?: Record<string, string>;
|
|
31
|
+
cacheControl?: string;
|
|
32
|
+
expires?: Date;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Storage class with automatic strategy selection and ultra-simple API
|
|
36
|
+
*/
|
|
37
|
+
export declare class StorageClass {
|
|
38
|
+
config: StorageConfig;
|
|
39
|
+
private strategy;
|
|
40
|
+
private connected;
|
|
41
|
+
constructor(config: StorageConfig);
|
|
42
|
+
/**
|
|
43
|
+
* Creates appropriate strategy based on configuration
|
|
44
|
+
* @llm-rule WHEN: Storage initialization - selects Local, S3, or R2 based on environment
|
|
45
|
+
* @llm-rule AVOID: Manual strategy creation - configuration handles strategy selection
|
|
46
|
+
*/
|
|
47
|
+
private createStrategy;
|
|
48
|
+
/**
|
|
49
|
+
* Connects to storage backend with automatic setup
|
|
50
|
+
* @llm-rule WHEN: Storage initialization or reconnection after failure
|
|
51
|
+
* @llm-rule AVOID: Manual connection management - this handles connection state
|
|
52
|
+
*/
|
|
53
|
+
connect(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Disconnects from storage backend gracefully
|
|
56
|
+
* @llm-rule WHEN: App shutdown or storage cleanup
|
|
57
|
+
* @llm-rule AVOID: Abrupt disconnection - graceful shutdown prevents data loss
|
|
58
|
+
*/
|
|
59
|
+
disconnect(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Stores file with automatic validation and type detection
|
|
62
|
+
* @llm-rule WHEN: Uploading files to storage backend
|
|
63
|
+
* @llm-rule AVOID: Manual file validation - this handles size, type, and path validation
|
|
64
|
+
* @llm-rule NOTE: Returns the key/path where file was stored
|
|
65
|
+
*/
|
|
66
|
+
put(key: string, data: Buffer | Uint8Array | string, options?: PutOptions): Promise<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Retrieves file with automatic error handling
|
|
69
|
+
* @llm-rule WHEN: Downloading files from storage backend
|
|
70
|
+
* @llm-rule AVOID: Manual error handling - this provides consistent error messages
|
|
71
|
+
*/
|
|
72
|
+
get(key: string): Promise<Buffer>;
|
|
73
|
+
/**
|
|
74
|
+
* Deletes file with confirmation
|
|
75
|
+
* @llm-rule WHEN: Removing files from storage backend
|
|
76
|
+
* @llm-rule AVOID: Silent failures - this confirms deletion success
|
|
77
|
+
*/
|
|
78
|
+
delete(key: string): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Lists files with prefix filtering and metadata
|
|
81
|
+
* @llm-rule WHEN: Browsing files or implementing file managers
|
|
82
|
+
* @llm-rule AVOID: Loading all files - use prefix filtering for performance
|
|
83
|
+
*/
|
|
84
|
+
list(prefix?: string, limit?: number): Promise<StorageFile[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Gets public URL for file access
|
|
87
|
+
* @llm-rule WHEN: Generating URLs for file access in web applications
|
|
88
|
+
* @llm-rule AVOID: Hardcoding URLs - this handles CDN and strategy-specific URLs
|
|
89
|
+
*/
|
|
90
|
+
url(key: string): string;
|
|
91
|
+
/**
|
|
92
|
+
* Generates signed URL for temporary access
|
|
93
|
+
* @llm-rule WHEN: Creating temporary download links or private file access
|
|
94
|
+
* @llm-rule AVOID: Permanent URLs for private files - use signed URLs with expiration
|
|
95
|
+
*/
|
|
96
|
+
signedUrl(key: string, expiresIn?: number): Promise<string>;
|
|
97
|
+
/**
|
|
98
|
+
* Checks if file exists without downloading
|
|
99
|
+
* @llm-rule WHEN: Validating file existence before operations
|
|
100
|
+
* @llm-rule AVOID: Downloading files just to check existence - this is more efficient
|
|
101
|
+
*/
|
|
102
|
+
exists(key: string): Promise<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* Copies file from one location to another
|
|
105
|
+
* @llm-rule WHEN: Duplicating files or moving between folders
|
|
106
|
+
* @llm-rule AVOID: Download and upload - this uses efficient copy operations when possible
|
|
107
|
+
*/
|
|
108
|
+
copy(sourceKey: string, destKey: string): Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Gets current storage strategy name for debugging
|
|
111
|
+
* @llm-rule WHEN: Debugging or health checks to see which strategy is active
|
|
112
|
+
* @llm-rule AVOID: Using for application logic - storage should be transparent
|
|
113
|
+
*/
|
|
114
|
+
getStrategy(): string;
|
|
115
|
+
/**
|
|
116
|
+
* Gets storage configuration summary for debugging
|
|
117
|
+
* @llm-rule WHEN: Health checks or debugging storage configuration
|
|
118
|
+
* @llm-rule AVOID: Exposing sensitive details - this only shows safe info
|
|
119
|
+
*/
|
|
120
|
+
getConfig(): {
|
|
121
|
+
strategy: string;
|
|
122
|
+
connected: boolean;
|
|
123
|
+
maxFileSize: number;
|
|
124
|
+
allowedTypes: string[];
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Ensures storage system is connected before operations
|
|
128
|
+
*/
|
|
129
|
+
private ensureConnected;
|
|
130
|
+
/**
|
|
131
|
+
* Validates storage key format and security
|
|
132
|
+
*/
|
|
133
|
+
private validateKey;
|
|
134
|
+
/**
|
|
135
|
+
* Normalizes input data to Buffer
|
|
136
|
+
*/
|
|
137
|
+
private normalizeData;
|
|
138
|
+
/**
|
|
139
|
+
* Validates file size against configured limits
|
|
140
|
+
*/
|
|
141
|
+
private validateFileSize;
|
|
142
|
+
/**
|
|
143
|
+
* Detects content type from file extension and buffer
|
|
144
|
+
*/
|
|
145
|
+
private detectContentType;
|
|
146
|
+
/**
|
|
147
|
+
* Validates file type against allowed types
|
|
148
|
+
*/
|
|
149
|
+
private validateFileType;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/storage/storage.ts"],"names":[],"mappings":"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"}
|