@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 @@
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":"AAAA;;;;;;;;;GASG;AA2CH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,mBAAmB,EAAE,CAAC;IAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;IACtD,MAAM,aAAa,GAAG,OAAO,KAAK,aAAa,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,KAAK,YAAY,CAAC;IAC9C,MAAM,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC;IAElC,wCAAwC;IACxC,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IAEzC,OAAO;QACL,0CAA0C;QAC1C,QAAQ;QAER,2DAA2D;QAC3D,KAAK,EAAE;YACL,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,WAAW;YACjD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,UAAU;YACzD,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,UAAU,CAAC,EAAE,eAAe;YACxF,YAAY,EAAE,iBAAiB,EAAE;YACjC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,OAAO;SAC9D;QAED,qDAAqD;QACrD,EAAE,EAAE;YACF,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE;YAChE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,WAAW;YACtE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;YACjC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;YAChF,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;YAC5F,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM;YAC1D,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,MAAM,CAAC,EAAE,SAAS;YACvF,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;SAC1C;QAED,qDAAqD;QACrD,EAAE,EAAE;YACF,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;YAC9C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE;YAClD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE;YAC1D,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,EAAE;YAClE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YACzC,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,MAAM,CAAC,EAAE,SAAS;SACxF;QAED,0BAA0B;QAC1B,WAAW,EAAE;YACX,aAAa;YACb,YAAY;YACZ,MAAM;YACN,OAAO;SACR;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB;IAC5B,iDAAiD;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,WAAW,EAAE,CAAC;IACnE,IAAI,QAAQ,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,OAAO,QAAe,CAAC;IACzB,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,CAAC,mCAAmC;IAClD,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC,CAAC,yBAAyB;IACxC,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CACV,+DAA+D;YAC/D,8CAA8C;YAC9C,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,8BAA8B;AAChD,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB;IACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAEzD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,wCAAwC;QACxC,OAAO;YACL,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe;YACrE,YAAY,EAAE,UAAU,EAAE,kBAAkB;YAC5C,iBAAiB,EAAE,iBAAiB;YACpC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW;SACrD,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC1C,OAAO,CAAC,IAAI,CACV,4EAA4E;gBAC5E,iEAAiE,CAClE,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,qCAAqC;IACrD,CAAC;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB;IAC1B,8CAA8C;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACpD,IAAI,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CACb,oCAAoC,QAAQ,mCAAmC,CAChF,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,kBAAkB,CAAC,wBAAwB,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa;IAChF,kBAAkB,CAAC,6BAA6B,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,qBAAqB;IAEpF,oDAAoD;IACpD,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,gBAAgB,EAAE,CAAC;IACrB,CAAC;IAED,oDAAoD;IACpD,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,gBAAgB,EAAE,CAAC;IACrB,CAAC;IAED,iDAAiD;IACjD,IAAI,mBAAmB,EAAE,EAAE,CAAC;QAC1B,mBAAmB,EAAE,CAAC;IACxB,CAAC;IAED,kCAAkC;IAClC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACrC,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,wBAAwB,EAAE,CAAC;IAC7B,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACnF,OAAO,CAAC,IAAI,CACV,wCAAwC,OAAO,KAAK;YACpD,qDAAqD,CACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC3F,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB;IAC1B,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IAClE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAClG,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,gDAAgD,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAChF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAExF,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IACzC,IAAI,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,wBAAwB,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,uCAAuC,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;IAE9D,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,4IAA4I,CAC7I,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC1C,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,EAAE,CAAC;QAChG,OAAO,CAAC,IAAI,CACV,4DAA4D,GAAG,KAAK;YACpE,8CAA8C,CAC/C,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACnD,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,oCAAoC,OAAO,gCAAgC,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB;IAC/B,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IAEzC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CACV,uDAAuD;YACvD,mDAAmD;YACnD,oEAAoE,CACrE,CAAC;IACJ,CAAC;IAED,uCAAuC;IACvC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACtF,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CACV,yDAAyD;YACzD,mDAAmD,CACpD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpF,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7D,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAY,EAAE,GAAW,EAAE,GAAW;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACb,WAAW,IAAI,MAAM,KAAK,+BAA+B,GAAG,QAAQ,GAAG,EAAE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAO9B,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAElC,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,QAAQ,KAAK,OAAO;QAClC,EAAE,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI;QAC5B,EAAE,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI;QAC5B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO;KACxC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,OAAO,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA8C;IAChF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa;YAChB,OAAO;gBACL,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE;oBACL,GAAG,EAAE,WAAW;oBAChB,OAAO,EAAE,UAAU;oBACnB,WAAW,EAAE,QAAQ,EAAE,OAAO;oBAC9B,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,4BAA4B;oBACjD,UAAU,EAAE,IAAI;iBACjB;aACF,CAAC;QAEJ,KAAK,SAAS;YACZ,OAAO;gBACL,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,OAAO;gBAC/D,KAAK,EAAE;oBACL,GAAG,EAAE,mBAAmB;oBACxB,OAAO,EAAE,UAAU;oBACnB,WAAW,EAAE,QAAQ,EAAE,OAAO;oBAC9B,YAAY,EAAE,iBAAiB,EAAE;oBACjC,UAAU,EAAE,IAAI;iBACjB;aACF,CAAC;QAEJ,KAAK,YAAY;YACf,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;YACzC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;YACjF,CAAC;YACD,OAAO;gBACL,QAAQ;gBACR,KAAK,EAAE;oBACL,GAAG,EAAE,gBAAgB;oBACrB,OAAO,EAAE,UAAU;oBACnB,WAAW,EAAE,QAAQ,EAAE,OAAO;oBAC9B,YAAY,EAAE,iBAAiB,EAAE;oBACjC,UAAU,EAAE,KAAK,EAAE,kCAAkC;iBACtD;aACF,CAAC;QAEJ;YACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
@@ -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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"}