@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.
Files changed (262) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +902 -0
  3. package/bin/appkit.js +71 -0
  4. package/bin/commands/generate.js +1050 -0
  5. package/bin/templates/backend/README.md.template +39 -0
  6. package/bin/templates/backend/api.http.template +0 -0
  7. package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
  8. package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
  9. package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
  10. package/bin/templates/backend/package.json.template +34 -0
  11. package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
  12. package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
  13. package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
  14. package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
  15. package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
  16. package/bin/templates/backend/src/api/server.ts.template +188 -0
  17. package/bin/templates/backend/tsconfig.api.json.template +24 -0
  18. package/bin/templates/backend/tsconfig.json.template +40 -0
  19. package/bin/templates/feature/feature.http.template +63 -0
  20. package/bin/templates/feature/feature.route.ts.template +36 -0
  21. package/bin/templates/feature/feature.service.ts.template +81 -0
  22. package/bin/templates/feature/feature.types.ts.template +23 -0
  23. package/bin/templates/feature-db/feature.http.template +63 -0
  24. package/bin/templates/feature-db/feature.model.ts.template +74 -0
  25. package/bin/templates/feature-db/feature.route.ts.template +58 -0
  26. package/bin/templates/feature-db/feature.service.ts.template +231 -0
  27. package/bin/templates/feature-db/feature.types.ts.template +25 -0
  28. package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
  29. package/bin/templates/feature-db/seeding/README.md.template +57 -0
  30. package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
  31. package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
  32. package/bin/templates/feature-user/user.http.template +157 -0
  33. package/bin/templates/feature-user/user.model.ts.template +244 -0
  34. package/bin/templates/feature-user/user.route.ts.template +379 -0
  35. package/bin/templates/feature-user/user.seed.js.template +182 -0
  36. package/bin/templates/feature-user/user.service.ts.template +426 -0
  37. package/bin/templates/feature-user/user.types.ts.template +127 -0
  38. package/dist/auth/auth.d.ts +182 -0
  39. package/dist/auth/auth.d.ts.map +1 -0
  40. package/dist/auth/auth.js +477 -0
  41. package/dist/auth/auth.js.map +1 -0
  42. package/dist/auth/defaults.d.ts +104 -0
  43. package/dist/auth/defaults.d.ts.map +1 -0
  44. package/dist/auth/defaults.js +374 -0
  45. package/dist/auth/defaults.js.map +1 -0
  46. package/dist/auth/index.d.ts +70 -0
  47. package/dist/auth/index.d.ts.map +1 -0
  48. package/dist/auth/index.js +94 -0
  49. package/dist/auth/index.js.map +1 -0
  50. package/dist/cache/cache.d.ts +118 -0
  51. package/dist/cache/cache.d.ts.map +1 -0
  52. package/dist/cache/cache.js +249 -0
  53. package/dist/cache/cache.js.map +1 -0
  54. package/dist/cache/defaults.d.ts +63 -0
  55. package/dist/cache/defaults.d.ts.map +1 -0
  56. package/dist/cache/defaults.js +193 -0
  57. package/dist/cache/defaults.js.map +1 -0
  58. package/dist/cache/index.d.ts +101 -0
  59. package/dist/cache/index.d.ts.map +1 -0
  60. package/dist/cache/index.js +203 -0
  61. package/dist/cache/index.js.map +1 -0
  62. package/dist/cache/strategies/memory.d.ts +138 -0
  63. package/dist/cache/strategies/memory.d.ts.map +1 -0
  64. package/dist/cache/strategies/memory.js +348 -0
  65. package/dist/cache/strategies/memory.js.map +1 -0
  66. package/dist/cache/strategies/redis.d.ts +105 -0
  67. package/dist/cache/strategies/redis.d.ts.map +1 -0
  68. package/dist/cache/strategies/redis.js +318 -0
  69. package/dist/cache/strategies/redis.js.map +1 -0
  70. package/dist/config/config.d.ts +62 -0
  71. package/dist/config/config.d.ts.map +1 -0
  72. package/dist/config/config.js +107 -0
  73. package/dist/config/config.js.map +1 -0
  74. package/dist/config/defaults.d.ts +44 -0
  75. package/dist/config/defaults.d.ts.map +1 -0
  76. package/dist/config/defaults.js +217 -0
  77. package/dist/config/defaults.js.map +1 -0
  78. package/dist/config/index.d.ts +105 -0
  79. package/dist/config/index.d.ts.map +1 -0
  80. package/dist/config/index.js +163 -0
  81. package/dist/config/index.js.map +1 -0
  82. package/dist/database/adapters/mongoose.d.ts +106 -0
  83. package/dist/database/adapters/mongoose.d.ts.map +1 -0
  84. package/dist/database/adapters/mongoose.js +480 -0
  85. package/dist/database/adapters/mongoose.js.map +1 -0
  86. package/dist/database/adapters/prisma.d.ts +106 -0
  87. package/dist/database/adapters/prisma.d.ts.map +1 -0
  88. package/dist/database/adapters/prisma.js +494 -0
  89. package/dist/database/adapters/prisma.js.map +1 -0
  90. package/dist/database/defaults.d.ts +87 -0
  91. package/dist/database/defaults.d.ts.map +1 -0
  92. package/dist/database/defaults.js +271 -0
  93. package/dist/database/defaults.js.map +1 -0
  94. package/dist/database/index.d.ts +137 -0
  95. package/dist/database/index.d.ts.map +1 -0
  96. package/dist/database/index.js +490 -0
  97. package/dist/database/index.js.map +1 -0
  98. package/dist/email/defaults.d.ts +100 -0
  99. package/dist/email/defaults.d.ts.map +1 -0
  100. package/dist/email/defaults.js +400 -0
  101. package/dist/email/defaults.js.map +1 -0
  102. package/dist/email/email.d.ts +139 -0
  103. package/dist/email/email.d.ts.map +1 -0
  104. package/dist/email/email.js +316 -0
  105. package/dist/email/email.js.map +1 -0
  106. package/dist/email/index.d.ts +176 -0
  107. package/dist/email/index.d.ts.map +1 -0
  108. package/dist/email/index.js +251 -0
  109. package/dist/email/index.js.map +1 -0
  110. package/dist/email/strategies/console.d.ts +90 -0
  111. package/dist/email/strategies/console.d.ts.map +1 -0
  112. package/dist/email/strategies/console.js +268 -0
  113. package/dist/email/strategies/console.js.map +1 -0
  114. package/dist/email/strategies/resend.d.ts +84 -0
  115. package/dist/email/strategies/resend.d.ts.map +1 -0
  116. package/dist/email/strategies/resend.js +266 -0
  117. package/dist/email/strategies/resend.js.map +1 -0
  118. package/dist/email/strategies/smtp.d.ts +77 -0
  119. package/dist/email/strategies/smtp.d.ts.map +1 -0
  120. package/dist/email/strategies/smtp.js +286 -0
  121. package/dist/email/strategies/smtp.js.map +1 -0
  122. package/dist/error/defaults.d.ts +40 -0
  123. package/dist/error/defaults.d.ts.map +1 -0
  124. package/dist/error/defaults.js +75 -0
  125. package/dist/error/defaults.js.map +1 -0
  126. package/dist/error/error.d.ts +140 -0
  127. package/dist/error/error.d.ts.map +1 -0
  128. package/dist/error/error.js +200 -0
  129. package/dist/error/error.js.map +1 -0
  130. package/dist/error/index.d.ts +145 -0
  131. package/dist/error/index.d.ts.map +1 -0
  132. package/dist/error/index.js +145 -0
  133. package/dist/error/index.js.map +1 -0
  134. package/dist/event/defaults.d.ts +111 -0
  135. package/dist/event/defaults.d.ts.map +1 -0
  136. package/dist/event/defaults.js +378 -0
  137. package/dist/event/defaults.js.map +1 -0
  138. package/dist/event/event.d.ts +171 -0
  139. package/dist/event/event.d.ts.map +1 -0
  140. package/dist/event/event.js +391 -0
  141. package/dist/event/event.js.map +1 -0
  142. package/dist/event/index.d.ts +173 -0
  143. package/dist/event/index.d.ts.map +1 -0
  144. package/dist/event/index.js +302 -0
  145. package/dist/event/index.js.map +1 -0
  146. package/dist/event/strategies/memory.d.ts +122 -0
  147. package/dist/event/strategies/memory.d.ts.map +1 -0
  148. package/dist/event/strategies/memory.js +331 -0
  149. package/dist/event/strategies/memory.js.map +1 -0
  150. package/dist/event/strategies/redis.d.ts +115 -0
  151. package/dist/event/strategies/redis.d.ts.map +1 -0
  152. package/dist/event/strategies/redis.js +434 -0
  153. package/dist/event/strategies/redis.js.map +1 -0
  154. package/dist/index.d.ts +58 -0
  155. package/dist/index.d.ts.map +1 -0
  156. package/dist/index.js +72 -0
  157. package/dist/index.js.map +1 -0
  158. package/dist/logger/defaults.d.ts +67 -0
  159. package/dist/logger/defaults.d.ts.map +1 -0
  160. package/dist/logger/defaults.js +213 -0
  161. package/dist/logger/defaults.js.map +1 -0
  162. package/dist/logger/index.d.ts +84 -0
  163. package/dist/logger/index.d.ts.map +1 -0
  164. package/dist/logger/index.js +101 -0
  165. package/dist/logger/index.js.map +1 -0
  166. package/dist/logger/logger.d.ts +165 -0
  167. package/dist/logger/logger.d.ts.map +1 -0
  168. package/dist/logger/logger.js +843 -0
  169. package/dist/logger/logger.js.map +1 -0
  170. package/dist/logger/transports/console.d.ts +102 -0
  171. package/dist/logger/transports/console.d.ts.map +1 -0
  172. package/dist/logger/transports/console.js +276 -0
  173. package/dist/logger/transports/console.js.map +1 -0
  174. package/dist/logger/transports/database.d.ts +153 -0
  175. package/dist/logger/transports/database.d.ts.map +1 -0
  176. package/dist/logger/transports/database.js +539 -0
  177. package/dist/logger/transports/database.js.map +1 -0
  178. package/dist/logger/transports/file.d.ts +146 -0
  179. package/dist/logger/transports/file.d.ts.map +1 -0
  180. package/dist/logger/transports/file.js +464 -0
  181. package/dist/logger/transports/file.js.map +1 -0
  182. package/dist/logger/transports/http.d.ts +128 -0
  183. package/dist/logger/transports/http.d.ts.map +1 -0
  184. package/dist/logger/transports/http.js +401 -0
  185. package/dist/logger/transports/http.js.map +1 -0
  186. package/dist/logger/transports/webhook.d.ts +152 -0
  187. package/dist/logger/transports/webhook.d.ts.map +1 -0
  188. package/dist/logger/transports/webhook.js +485 -0
  189. package/dist/logger/transports/webhook.js.map +1 -0
  190. package/dist/queue/defaults.d.ts +66 -0
  191. package/dist/queue/defaults.d.ts.map +1 -0
  192. package/dist/queue/defaults.js +205 -0
  193. package/dist/queue/defaults.js.map +1 -0
  194. package/dist/queue/index.d.ts +124 -0
  195. package/dist/queue/index.d.ts.map +1 -0
  196. package/dist/queue/index.js +116 -0
  197. package/dist/queue/index.js.map +1 -0
  198. package/dist/queue/queue.d.ts +156 -0
  199. package/dist/queue/queue.d.ts.map +1 -0
  200. package/dist/queue/queue.js +387 -0
  201. package/dist/queue/queue.js.map +1 -0
  202. package/dist/queue/transports/database.d.ts +165 -0
  203. package/dist/queue/transports/database.d.ts.map +1 -0
  204. package/dist/queue/transports/database.js +595 -0
  205. package/dist/queue/transports/database.js.map +1 -0
  206. package/dist/queue/transports/memory.d.ts +143 -0
  207. package/dist/queue/transports/memory.d.ts.map +1 -0
  208. package/dist/queue/transports/memory.js +415 -0
  209. package/dist/queue/transports/memory.js.map +1 -0
  210. package/dist/queue/transports/redis.d.ts +203 -0
  211. package/dist/queue/transports/redis.d.ts.map +1 -0
  212. package/dist/queue/transports/redis.js +744 -0
  213. package/dist/queue/transports/redis.js.map +1 -0
  214. package/dist/security/defaults.d.ts +64 -0
  215. package/dist/security/defaults.d.ts.map +1 -0
  216. package/dist/security/defaults.js +159 -0
  217. package/dist/security/defaults.js.map +1 -0
  218. package/dist/security/index.d.ts +110 -0
  219. package/dist/security/index.d.ts.map +1 -0
  220. package/dist/security/index.js +160 -0
  221. package/dist/security/index.js.map +1 -0
  222. package/dist/security/security.d.ts +138 -0
  223. package/dist/security/security.d.ts.map +1 -0
  224. package/dist/security/security.js +419 -0
  225. package/dist/security/security.js.map +1 -0
  226. package/dist/storage/defaults.d.ts +79 -0
  227. package/dist/storage/defaults.d.ts.map +1 -0
  228. package/dist/storage/defaults.js +358 -0
  229. package/dist/storage/defaults.js.map +1 -0
  230. package/dist/storage/index.d.ts +153 -0
  231. package/dist/storage/index.d.ts.map +1 -0
  232. package/dist/storage/index.js +242 -0
  233. package/dist/storage/index.js.map +1 -0
  234. package/dist/storage/storage.d.ts +151 -0
  235. package/dist/storage/storage.d.ts.map +1 -0
  236. package/dist/storage/storage.js +439 -0
  237. package/dist/storage/storage.js.map +1 -0
  238. package/dist/storage/strategies/local.d.ts +117 -0
  239. package/dist/storage/strategies/local.d.ts.map +1 -0
  240. package/dist/storage/strategies/local.js +368 -0
  241. package/dist/storage/strategies/local.js.map +1 -0
  242. package/dist/storage/strategies/r2.d.ts +130 -0
  243. package/dist/storage/strategies/r2.d.ts.map +1 -0
  244. package/dist/storage/strategies/r2.js +470 -0
  245. package/dist/storage/strategies/r2.js.map +1 -0
  246. package/dist/storage/strategies/s3.d.ts +121 -0
  247. package/dist/storage/strategies/s3.d.ts.map +1 -0
  248. package/dist/storage/strategies/s3.js +461 -0
  249. package/dist/storage/strategies/s3.js.map +1 -0
  250. package/dist/util/defaults.d.ts +77 -0
  251. package/dist/util/defaults.d.ts.map +1 -0
  252. package/dist/util/defaults.js +193 -0
  253. package/dist/util/defaults.js.map +1 -0
  254. package/dist/util/index.d.ts +97 -0
  255. package/dist/util/index.d.ts.map +1 -0
  256. package/dist/util/index.js +165 -0
  257. package/dist/util/index.js.map +1 -0
  258. package/dist/util/util.d.ts +145 -0
  259. package/dist/util/util.d.ts.map +1 -0
  260. package/dist/util/util.js +481 -0
  261. package/dist/util/util.js.map +1 -0
  262. 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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"}