@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,400 @@
1
+ /**
2
+ * Smart defaults and environment validation for email with auto-strategy detection
3
+ * @module @bloomneo/appkit/email
4
+ * @file src/email/defaults.ts
5
+ *
6
+ * @llm-rule WHEN: App startup - need to configure email strategy and connection settings
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 Resend → SMTP → Console 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 email configuration
14
+ * @llm-rule AVOID: Calling repeatedly - expensive validation, cache the result
15
+ * @llm-rule NOTE: Auto-detects strategy: RESEND_API_KEY → Resend, SMTP_HOST → SMTP, default → Console
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 = detectEmailStrategy();
25
+ return {
26
+ // Strategy selection with smart detection
27
+ strategy,
28
+ // Default sender with service identification
29
+ from: {
30
+ name: process.env.VOILA_EMAIL_FROM_NAME || process.env.VOILA_SERVICE_NAME || 'App',
31
+ email: process.env.VOILA_EMAIL_FROM_EMAIL || getDefaultFromEmail(strategy),
32
+ },
33
+ // Resend configuration (only used when strategy is 'resend')
34
+ resend: {
35
+ apiKey: process.env.RESEND_API_KEY || '',
36
+ baseURL: process.env.RESEND_BASE_URL || 'https://api.resend.com',
37
+ timeout: parseInt(process.env.VOILA_EMAIL_RESEND_TIMEOUT || '30000'),
38
+ },
39
+ // SMTP configuration (only used when strategy is 'smtp')
40
+ smtp: {
41
+ host: process.env.SMTP_HOST || 'localhost',
42
+ port: parseInt(process.env.SMTP_PORT || getDefaultSmtpPort()),
43
+ secure: process.env.SMTP_SECURE === 'true' || isDefaultSecurePort(),
44
+ auth: {
45
+ user: process.env.SMTP_USER || '',
46
+ pass: process.env.SMTP_PASS || '',
47
+ },
48
+ timeout: parseInt(process.env.VOILA_EMAIL_SMTP_TIMEOUT || '30000'),
49
+ pool: process.env.SMTP_POOL !== 'false', // Default to true for performance
50
+ },
51
+ // Console configuration (only used when strategy is 'console')
52
+ console: {
53
+ colorize: process.env.VOILA_EMAIL_CONSOLE_COLOR !== 'false' && !isProduction,
54
+ showPreview: process.env.VOILA_EMAIL_CONSOLE_PREVIEW !== 'false' && isDevelopment,
55
+ format: process.env.VOILA_EMAIL_CONSOLE_FORMAT || 'simple',
56
+ },
57
+ // Environment information
58
+ environment: {
59
+ isDevelopment,
60
+ isProduction,
61
+ isTest,
62
+ nodeEnv,
63
+ },
64
+ };
65
+ }
66
+ /**
67
+ * Auto-detect email strategy from environment variables
68
+ * @llm-rule WHEN: Determining which email strategy to use automatically
69
+ * @llm-rule AVOID: Manual strategy selection - environment detection handles most cases
70
+ * @llm-rule NOTE: Priority: RESEND_API_KEY → SMTP_HOST → Console (perfect for dev/prod)
71
+ */
72
+ function detectEmailStrategy() {
73
+ // Explicit override wins (for testing/debugging)
74
+ const explicit = process.env.VOILA_EMAIL_STRATEGY?.toLowerCase();
75
+ if (explicit === 'resend' || explicit === 'smtp' || explicit === 'console') {
76
+ return explicit;
77
+ }
78
+ // Auto-detection logic (priority order)
79
+ if (process.env.RESEND_API_KEY) {
80
+ return 'resend'; // Resend API key available
81
+ }
82
+ if (process.env.SMTP_HOST) {
83
+ return 'smtp'; // SMTP configuration available
84
+ }
85
+ // Default to console for development/testing
86
+ if (process.env.NODE_ENV === 'production') {
87
+ console.warn('[VoilaJSX AppKit] No email provider configured in production. ' +
88
+ 'Using console strategy which will only log emails. ' +
89
+ 'Set RESEND_API_KEY or SMTP_HOST for production email sending.');
90
+ }
91
+ return 'console'; // Default to console for development
92
+ }
93
+ /**
94
+ * Get default FROM email based on strategy
95
+ * @llm-rule WHEN: No explicit FROM email configured - provides sensible defaults
96
+ * @llm-rule AVOID: Hardcoded defaults - strategy-specific defaults work better
97
+ */
98
+ function getDefaultFromEmail(strategy) {
99
+ switch (strategy) {
100
+ case 'resend':
101
+ return 'noreply@example.com'; // Resend requires verified domain
102
+ case 'smtp':
103
+ return process.env.SMTP_USER || 'noreply@localhost';
104
+ case 'console':
105
+ return 'noreply@localhost';
106
+ default:
107
+ return 'noreply@localhost';
108
+ }
109
+ }
110
+ /**
111
+ * Get default SMTP port based on configuration
112
+ * @llm-rule WHEN: No explicit SMTP port configured - uses standard ports
113
+ * @llm-rule AVOID: Hardcoded port - security settings affect port choice
114
+ */
115
+ function getDefaultSmtpPort() {
116
+ const secure = process.env.SMTP_SECURE === 'true';
117
+ const host = process.env.SMTP_HOST?.toLowerCase() || '';
118
+ // Gmail and common providers use specific ports
119
+ if (host.includes('gmail.com')) {
120
+ return secure ? '465' : '587';
121
+ }
122
+ // Standard SMTP ports
123
+ return secure ? '465' : '587';
124
+ }
125
+ /**
126
+ * Check if SMTP should use secure connection by default
127
+ * @llm-rule WHEN: No explicit SMTP_SECURE setting - auto-detects from port
128
+ * @llm-rule AVOID: Insecure connections - defaults to secure when possible
129
+ */
130
+ function isDefaultSecurePort() {
131
+ const port = parseInt(process.env.SMTP_PORT || '587');
132
+ return port === 465; // Port 465 is SSL, 587 is TLS
133
+ }
134
+ /**
135
+ * Validates environment variables for email configuration
136
+ * @llm-rule WHEN: App startup to ensure proper email environment configuration
137
+ * @llm-rule AVOID: Skipping validation - improper config causes silent email failures
138
+ * @llm-rule NOTE: Validates API keys, email addresses, and SMTP settings
139
+ */
140
+ function validateEnvironment() {
141
+ // Validate email strategy if explicitly set
142
+ const strategy = process.env.VOILA_EMAIL_STRATEGY;
143
+ if (strategy && !['resend', 'smtp', 'console'].includes(strategy.toLowerCase())) {
144
+ throw new Error(`Invalid VOILA_EMAIL_STRATEGY: "${strategy}". Must be "resend", "smtp", or "console"`);
145
+ }
146
+ // Validate Resend API key format if provided
147
+ const resendApiKey = process.env.RESEND_API_KEY;
148
+ if (resendApiKey && !resendApiKey.startsWith('re_')) {
149
+ throw new Error(`Invalid RESEND_API_KEY format: "${resendApiKey}". Must start with "re_"`);
150
+ }
151
+ // Validate SMTP configuration if provided
152
+ const smtpHost = process.env.SMTP_HOST;
153
+ if (smtpHost) {
154
+ validateSmtpConfig();
155
+ }
156
+ // Validate FROM email if provided
157
+ const fromEmail = process.env.VOILA_EMAIL_FROM_EMAIL;
158
+ if (fromEmail && !isValidEmail(fromEmail)) {
159
+ throw new Error(`Invalid VOILA_EMAIL_FROM_EMAIL: "${fromEmail}". Must be a valid email address`);
160
+ }
161
+ // Validate numeric values
162
+ validateNumericEnv('SMTP_PORT', 1, 65535);
163
+ validateNumericEnv('VOILA_EMAIL_RESEND_TIMEOUT', 1000, 300000); // 1s to 5min
164
+ validateNumericEnv('VOILA_EMAIL_SMTP_TIMEOUT', 1000, 300000); // 1s to 5min
165
+ // Validate console format if provided
166
+ const consoleFormat = process.env.VOILA_EMAIL_CONSOLE_FORMAT;
167
+ if (consoleFormat && !['simple', 'detailed'].includes(consoleFormat)) {
168
+ throw new Error(`Invalid VOILA_EMAIL_CONSOLE_FORMAT: "${consoleFormat}". Must be "simple" or "detailed"`);
169
+ }
170
+ // Production-specific validations
171
+ const nodeEnv = process.env.NODE_ENV;
172
+ if (nodeEnv === 'production') {
173
+ validateProductionConfig();
174
+ }
175
+ // Validate NODE_ENV
176
+ if (nodeEnv && !['development', 'production', 'test', 'staging'].includes(nodeEnv)) {
177
+ console.warn(`[VoilaJSX AppKit] Unusual NODE_ENV: "${nodeEnv}". ` +
178
+ `Expected: development, production, test, or staging`);
179
+ }
180
+ }
181
+ /**
182
+ * Validates SMTP configuration for completeness
183
+ * @llm-rule WHEN: SMTP_HOST is configured - ensures complete SMTP setup
184
+ * @llm-rule AVOID: Partial SMTP config - causes authentication failures
185
+ */
186
+ function validateSmtpConfig() {
187
+ const host = process.env.SMTP_HOST;
188
+ const user = process.env.SMTP_USER;
189
+ const pass = process.env.SMTP_PASS;
190
+ if (!host) {
191
+ throw new Error('SMTP_HOST is required when using SMTP strategy');
192
+ }
193
+ // Many SMTP servers require authentication
194
+ if (!user && !pass) {
195
+ console.warn('[VoilaJSX AppKit] SMTP configured without authentication. ' +
196
+ 'Set SMTP_USER and SMTP_PASS if your server requires authentication.');
197
+ }
198
+ if (user && !pass) {
199
+ throw new Error('SMTP_PASS is required when SMTP_USER is set');
200
+ }
201
+ if (!user && pass) {
202
+ throw new Error('SMTP_USER is required when SMTP_PASS is set');
203
+ }
204
+ }
205
+ /**
206
+ * Validates production email configuration
207
+ * @llm-rule WHEN: Running in production environment
208
+ * @llm-rule AVOID: Console strategy in production - emails won't be sent
209
+ */
210
+ function validateProductionConfig() {
211
+ const strategy = detectEmailStrategy();
212
+ if (strategy === 'console') {
213
+ console.warn('[VoilaJSX AppKit] Using console email strategy in production. ' +
214
+ 'Emails will only be logged, not sent. ' +
215
+ 'Set RESEND_API_KEY or SMTP_HOST for production email sending.');
216
+ }
217
+ // Validate FROM email is set in production
218
+ const fromEmail = process.env.VOILA_EMAIL_FROM_EMAIL;
219
+ if (!fromEmail) {
220
+ console.warn('[VoilaJSX AppKit] No FROM email configured in production. ' +
221
+ 'Set VOILA_EMAIL_FROM_EMAIL for professional email sending.');
222
+ }
223
+ }
224
+ /**
225
+ * Validates email address format
226
+ * @llm-rule WHEN: Validating email addresses in configuration
227
+ * @llm-rule AVOID: Complex regex - simple validation for config purposes
228
+ */
229
+ function isValidEmail(email) {
230
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
231
+ return emailRegex.test(email);
232
+ }
233
+ /**
234
+ * Validates numeric environment variable within acceptable range
235
+ * @llm-rule WHEN: Validating email configuration numeric values
236
+ * @llm-rule AVOID: Using values outside safe ranges - causes timeout or connection issues
237
+ */
238
+ function validateNumericEnv(name, min, max) {
239
+ const value = process.env[name];
240
+ if (!value)
241
+ return;
242
+ const num = parseInt(value);
243
+ if (isNaN(num) || num < min || num > max) {
244
+ throw new Error(`Invalid ${name}: "${value}". Must be a number between ${min} and ${max}`);
245
+ }
246
+ }
247
+ /**
248
+ * Gets email configuration summary for debugging and health checks
249
+ * @llm-rule WHEN: Debugging email configuration or building health check endpoints
250
+ * @llm-rule AVOID: Exposing sensitive API keys or passwords - this only shows safe info
251
+ */
252
+ export function getConfigSummary() {
253
+ const config = getSmartDefaults();
254
+ return {
255
+ strategy: config.strategy,
256
+ fromName: config.from.name,
257
+ fromEmail: config.from.email,
258
+ resendConfigured: config.strategy === 'resend' && !!config.resend?.apiKey,
259
+ smtpConfigured: config.strategy === 'smtp' && !!config.smtp?.host,
260
+ environment: config.environment.nodeEnv,
261
+ };
262
+ }
263
+ /**
264
+ * Validates that required email configuration is present for production
265
+ * @llm-rule WHEN: App startup validation for production deployments
266
+ * @llm-rule AVOID: Skipping validation - missing email config causes runtime issues
267
+ */
268
+ export function validateProductionRequirements() {
269
+ const config = getSmartDefaults();
270
+ if (config.environment.isProduction) {
271
+ if (config.strategy === 'console') {
272
+ console.warn('[VoilaJSX AppKit] Using console email strategy in production. ' +
273
+ 'Emails will only be logged, not sent. ' +
274
+ 'Set RESEND_API_KEY or SMTP_HOST for production email sending.');
275
+ }
276
+ if (config.strategy === 'resend' && !config.resend?.apiKey) {
277
+ throw new Error('Resend strategy selected but RESEND_API_KEY not configured. ' +
278
+ 'Set RESEND_API_KEY environment variable for Resend email sending.');
279
+ }
280
+ if (config.strategy === 'smtp' && !config.smtp?.host) {
281
+ throw new Error('SMTP strategy selected but SMTP_HOST not configured. ' +
282
+ 'Set SMTP_HOST environment variable for SMTP email sending.');
283
+ }
284
+ }
285
+ }
286
+ /**
287
+ * Validates startup configuration and throws detailed errors
288
+ * @llm-rule WHEN: App startup to ensure email configuration is valid before starting
289
+ * @llm-rule AVOID: Skipping validation - catches config issues early
290
+ * @llm-rule NOTE: Comprehensive validation for production readiness
291
+ */
292
+ export function validateStartupConfiguration() {
293
+ const warnings = [];
294
+ const errors = [];
295
+ try {
296
+ const config = getSmartDefaults();
297
+ const strategy = config.strategy;
298
+ // Strategy-specific validation
299
+ switch (strategy) {
300
+ case 'resend':
301
+ if (!config.resend?.apiKey) {
302
+ errors.push('RESEND_API_KEY is required for Resend strategy');
303
+ }
304
+ else if (!config.resend.apiKey.startsWith('re_')) {
305
+ errors.push('RESEND_API_KEY must start with "re_"');
306
+ }
307
+ break;
308
+ case 'smtp':
309
+ if (!config.smtp?.host) {
310
+ errors.push('SMTP_HOST is required for SMTP strategy');
311
+ }
312
+ if (config.smtp?.auth.user && !config.smtp?.auth.pass) {
313
+ errors.push('SMTP_PASS is required when SMTP_USER is set');
314
+ }
315
+ if (!config.smtp?.auth.user && config.smtp?.auth.pass) {
316
+ errors.push('SMTP_USER is required when SMTP_PASS is set');
317
+ }
318
+ break;
319
+ case 'console':
320
+ if (config.environment.isProduction) {
321
+ warnings.push('Console strategy in production - emails will only be logged');
322
+ }
323
+ break;
324
+ }
325
+ // FROM email validation
326
+ if (!config.from.email || config.from.email.includes('example.com')) {
327
+ if (config.environment.isProduction) {
328
+ errors.push('VOILA_EMAIL_FROM_EMAIL must be set in production');
329
+ }
330
+ else {
331
+ warnings.push('VOILA_EMAIL_FROM_EMAIL not configured - using default');
332
+ }
333
+ }
334
+ // Environment-specific warnings
335
+ if (config.environment.isProduction && strategy === 'console') {
336
+ warnings.push('No real email provider configured in production');
337
+ }
338
+ if (config.environment.isDevelopment && strategy !== 'console') {
339
+ warnings.push('Using real email provider in development');
340
+ }
341
+ return {
342
+ strategy,
343
+ warnings,
344
+ errors,
345
+ ready: errors.length === 0,
346
+ };
347
+ }
348
+ catch (error) {
349
+ errors.push(`Configuration validation failed: ${error.message}`);
350
+ return {
351
+ strategy: 'unknown',
352
+ warnings,
353
+ errors,
354
+ ready: false,
355
+ };
356
+ }
357
+ }
358
+ /**
359
+ * Performs comprehensive email system health check
360
+ * @llm-rule WHEN: Health check endpoints or monitoring systems
361
+ * @llm-rule AVOID: Running in critical path - this is for monitoring only
362
+ * @llm-rule NOTE: Returns detailed health status without exposing sensitive data
363
+ */
364
+ export function performHealthCheck() {
365
+ const issues = [];
366
+ let status = 'healthy';
367
+ try {
368
+ const validation = validateStartupConfiguration();
369
+ // Determine overall status
370
+ if (validation.errors.length > 0) {
371
+ status = 'error';
372
+ issues.push(...validation.errors);
373
+ }
374
+ else if (validation.warnings.length > 0) {
375
+ status = 'warning';
376
+ issues.push(...validation.warnings);
377
+ }
378
+ const configured = validation.strategy !== 'console' ||
379
+ process.env.NODE_ENV !== 'production';
380
+ return {
381
+ status,
382
+ strategy: validation.strategy,
383
+ configured,
384
+ issues,
385
+ ready: validation.ready,
386
+ timestamp: new Date().toISOString(),
387
+ };
388
+ }
389
+ catch (error) {
390
+ return {
391
+ status: 'error',
392
+ strategy: 'unknown',
393
+ configured: false,
394
+ issues: [`Health check failed: ${error.message}`],
395
+ ready: false,
396
+ timestamp: new Date().toISOString(),
397
+ };
398
+ }
399
+ }
400
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/email/defaults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Core email class with automatic strategy selection and ultra-simple API
3
+ * @module @bloomneo/appkit/email
4
+ * @file src/email/email.ts
5
+ *
6
+ * @llm-rule WHEN: Building apps that need email sending with automatic provider selection
7
+ * @llm-rule AVOID: Using directly - always get instance via emailClass.get()
8
+ * @llm-rule NOTE: Auto-detects Resend → SMTP → Console based on environment variables
9
+ */
10
+ import type { EmailConfig } from './defaults.js';
11
+ export interface EmailAddress {
12
+ name?: string;
13
+ email: string;
14
+ }
15
+ export interface EmailAttachment {
16
+ filename: string;
17
+ content: Buffer | string;
18
+ contentType?: string;
19
+ }
20
+ export interface EmailData {
21
+ to: string | EmailAddress | (string | EmailAddress)[];
22
+ from?: string | EmailAddress;
23
+ subject: string;
24
+ text?: string;
25
+ html?: string;
26
+ attachments?: EmailAttachment[];
27
+ replyTo?: string | EmailAddress;
28
+ cc?: string | EmailAddress | (string | EmailAddress)[];
29
+ bcc?: string | EmailAddress | (string | EmailAddress)[];
30
+ }
31
+ export interface EmailStrategy {
32
+ send(data: EmailData): Promise<EmailResult>;
33
+ disconnect(): Promise<void>;
34
+ }
35
+ export interface EmailResult {
36
+ success: boolean;
37
+ messageId?: string;
38
+ error?: string;
39
+ }
40
+ /**
41
+ * Email class with automatic strategy selection and ultra-simple API
42
+ */
43
+ export declare class EmailClass {
44
+ config: EmailConfig;
45
+ private strategy;
46
+ private connected;
47
+ constructor(config: EmailConfig);
48
+ /**
49
+ * Creates appropriate strategy based on configuration
50
+ * @llm-rule WHEN: Email initialization - selects Resend, SMTP, or Console based on environment
51
+ * @llm-rule AVOID: Manual strategy creation - configuration handles strategy selection
52
+ */
53
+ private createStrategy;
54
+ /**
55
+ * Sends email with automatic strategy handling
56
+ * @llm-rule WHEN: Sending any email - this is the main email sending method
57
+ * @llm-rule AVOID: Manual strategy calls - this handles all email complexity
58
+ * @llm-rule NOTE: Auto-fills FROM address from config if not provided
59
+ */
60
+ send(data: EmailData): Promise<EmailResult>;
61
+ /**
62
+ * Sends multiple emails efficiently (batch operation)
63
+ * @llm-rule WHEN: Sending multiple emails like newsletters or notifications
64
+ * @llm-rule AVOID: Multiple individual send() calls - this handles batching efficiently
65
+ * @llm-rule NOTE: Processes in batches to avoid overwhelming email providers
66
+ */
67
+ sendBatch(emails: EmailData[], batchSize?: number): Promise<EmailResult[]>;
68
+ /**
69
+ * Sends simple text email (convenience method)
70
+ * @llm-rule WHEN: Sending simple text-only emails quickly
71
+ * @llm-rule AVOID: Complex EmailData object for simple emails - this is more convenient
72
+ */
73
+ sendText(to: string, subject: string, text: string): Promise<EmailResult>;
74
+ /**
75
+ * Sends HTML email (convenience method)
76
+ * @llm-rule WHEN: Sending HTML emails with formatting
77
+ * @llm-rule AVOID: Manual HTML/text preparation - this handles both formats
78
+ */
79
+ sendHtml(to: string, subject: string, html: string, text?: string): Promise<EmailResult>;
80
+ /**
81
+ * Sends email with template (future extension point)
82
+ * @llm-rule WHEN: Sending templated emails with data substitution
83
+ * @llm-rule AVOID: Manual template processing - this will handle template rendering
84
+ * @llm-rule NOTE: Basic implementation - can be extended with template engines
85
+ */
86
+ sendTemplate(templateName: string, data: any): Promise<EmailResult>;
87
+ /**
88
+ * Disconnects email strategy gracefully
89
+ * @llm-rule WHEN: App shutdown or email cleanup
90
+ * @llm-rule AVOID: Abrupt disconnection - graceful shutdown prevents connection issues
91
+ */
92
+ disconnect(): Promise<void>;
93
+ /**
94
+ * Gets current email strategy name for debugging
95
+ * @llm-rule WHEN: Debugging or health checks to see which strategy is active
96
+ * @llm-rule AVOID: Using for application logic - email should be transparent
97
+ */
98
+ getStrategy(): string;
99
+ /**
100
+ * Gets email configuration summary for debugging
101
+ * @llm-rule WHEN: Health checks or debugging email configuration
102
+ * @llm-rule AVOID: Exposing sensitive details - this only shows safe info
103
+ */
104
+ getConfig(): {
105
+ strategy: string;
106
+ fromName: string;
107
+ fromEmail: string;
108
+ connected: boolean;
109
+ };
110
+ /**
111
+ * Validates email data before sending
112
+ */
113
+ private validateEmailData;
114
+ /**
115
+ * Prepares email data with defaults
116
+ */
117
+ private prepareEmailData;
118
+ /**
119
+ * Validates email address format
120
+ */
121
+ private isValidEmail;
122
+ /**
123
+ * Converts HTML to plain text (basic implementation)
124
+ */
125
+ private htmlToText;
126
+ /**
127
+ * Loads email template (basic implementation)
128
+ */
129
+ private loadTemplate;
130
+ /**
131
+ * Processes template with data substitution
132
+ */
133
+ private processTemplate;
134
+ /**
135
+ * Sleep for specified milliseconds
136
+ */
137
+ private sleep;
138
+ }
139
+ //# sourceMappingURL=email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/email/email.ts"],"names":[],"mappings":"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"}