@bloomneo/appkit 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +902 -0
- package/bin/appkit.js +71 -0
- package/bin/commands/generate.js +1050 -0
- package/bin/templates/backend/README.md.template +39 -0
- package/bin/templates/backend/api.http.template +0 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
- package/bin/templates/backend/package.json.template +34 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
- package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
- package/bin/templates/backend/src/api/server.ts.template +188 -0
- package/bin/templates/backend/tsconfig.api.json.template +24 -0
- package/bin/templates/backend/tsconfig.json.template +40 -0
- package/bin/templates/feature/feature.http.template +63 -0
- package/bin/templates/feature/feature.route.ts.template +36 -0
- package/bin/templates/feature/feature.service.ts.template +81 -0
- package/bin/templates/feature/feature.types.ts.template +23 -0
- package/bin/templates/feature-db/feature.http.template +63 -0
- package/bin/templates/feature-db/feature.model.ts.template +74 -0
- package/bin/templates/feature-db/feature.route.ts.template +58 -0
- package/bin/templates/feature-db/feature.service.ts.template +231 -0
- package/bin/templates/feature-db/feature.types.ts.template +25 -0
- package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
- package/bin/templates/feature-db/seeding/README.md.template +57 -0
- package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
- package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
- package/bin/templates/feature-user/user.http.template +157 -0
- package/bin/templates/feature-user/user.model.ts.template +244 -0
- package/bin/templates/feature-user/user.route.ts.template +379 -0
- package/bin/templates/feature-user/user.seed.js.template +182 -0
- package/bin/templates/feature-user/user.service.ts.template +426 -0
- package/bin/templates/feature-user/user.types.ts.template +127 -0
- package/dist/auth/auth.d.ts +182 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +477 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/defaults.d.ts +104 -0
- package/dist/auth/defaults.d.ts.map +1 -0
- package/dist/auth/defaults.js +374 -0
- package/dist/auth/defaults.js.map +1 -0
- package/dist/auth/index.d.ts +70 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +94 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/cache.d.ts +118 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +249 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/defaults.d.ts +63 -0
- package/dist/cache/defaults.d.ts.map +1 -0
- package/dist/cache/defaults.js +193 -0
- package/dist/cache/defaults.js.map +1 -0
- package/dist/cache/index.d.ts +101 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +203 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/strategies/memory.d.ts +138 -0
- package/dist/cache/strategies/memory.d.ts.map +1 -0
- package/dist/cache/strategies/memory.js +348 -0
- package/dist/cache/strategies/memory.js.map +1 -0
- package/dist/cache/strategies/redis.d.ts +105 -0
- package/dist/cache/strategies/redis.d.ts.map +1 -0
- package/dist/cache/strategies/redis.js +318 -0
- package/dist/cache/strategies/redis.js.map +1 -0
- package/dist/config/config.d.ts +62 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +107 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +44 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +217 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +163 -0
- package/dist/config/index.js.map +1 -0
- package/dist/database/adapters/mongoose.d.ts +106 -0
- package/dist/database/adapters/mongoose.d.ts.map +1 -0
- package/dist/database/adapters/mongoose.js +480 -0
- package/dist/database/adapters/mongoose.js.map +1 -0
- package/dist/database/adapters/prisma.d.ts +106 -0
- package/dist/database/adapters/prisma.d.ts.map +1 -0
- package/dist/database/adapters/prisma.js +494 -0
- package/dist/database/adapters/prisma.js.map +1 -0
- package/dist/database/defaults.d.ts +87 -0
- package/dist/database/defaults.d.ts.map +1 -0
- package/dist/database/defaults.js +271 -0
- package/dist/database/defaults.js.map +1 -0
- package/dist/database/index.d.ts +137 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +490 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/defaults.d.ts +100 -0
- package/dist/email/defaults.d.ts.map +1 -0
- package/dist/email/defaults.js +400 -0
- package/dist/email/defaults.js.map +1 -0
- package/dist/email/email.d.ts +139 -0
- package/dist/email/email.d.ts.map +1 -0
- package/dist/email/email.js +316 -0
- package/dist/email/email.js.map +1 -0
- package/dist/email/index.d.ts +176 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +251 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/strategies/console.d.ts +90 -0
- package/dist/email/strategies/console.d.ts.map +1 -0
- package/dist/email/strategies/console.js +268 -0
- package/dist/email/strategies/console.js.map +1 -0
- package/dist/email/strategies/resend.d.ts +84 -0
- package/dist/email/strategies/resend.d.ts.map +1 -0
- package/dist/email/strategies/resend.js +266 -0
- package/dist/email/strategies/resend.js.map +1 -0
- package/dist/email/strategies/smtp.d.ts +77 -0
- package/dist/email/strategies/smtp.d.ts.map +1 -0
- package/dist/email/strategies/smtp.js +286 -0
- package/dist/email/strategies/smtp.js.map +1 -0
- package/dist/error/defaults.d.ts +40 -0
- package/dist/error/defaults.d.ts.map +1 -0
- package/dist/error/defaults.js +75 -0
- package/dist/error/defaults.js.map +1 -0
- package/dist/error/error.d.ts +140 -0
- package/dist/error/error.d.ts.map +1 -0
- package/dist/error/error.js +200 -0
- package/dist/error/error.js.map +1 -0
- package/dist/error/index.d.ts +145 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +145 -0
- package/dist/error/index.js.map +1 -0
- package/dist/event/defaults.d.ts +111 -0
- package/dist/event/defaults.d.ts.map +1 -0
- package/dist/event/defaults.js +378 -0
- package/dist/event/defaults.js.map +1 -0
- package/dist/event/event.d.ts +171 -0
- package/dist/event/event.d.ts.map +1 -0
- package/dist/event/event.js +391 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/index.d.ts +173 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/index.js +302 -0
- package/dist/event/index.js.map +1 -0
- package/dist/event/strategies/memory.d.ts +122 -0
- package/dist/event/strategies/memory.d.ts.map +1 -0
- package/dist/event/strategies/memory.js +331 -0
- package/dist/event/strategies/memory.js.map +1 -0
- package/dist/event/strategies/redis.d.ts +115 -0
- package/dist/event/strategies/redis.d.ts.map +1 -0
- package/dist/event/strategies/redis.js +434 -0
- package/dist/event/strategies/redis.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/defaults.d.ts +67 -0
- package/dist/logger/defaults.d.ts.map +1 -0
- package/dist/logger/defaults.js +213 -0
- package/dist/logger/defaults.js.map +1 -0
- package/dist/logger/index.d.ts +84 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +101 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/logger.d.ts +165 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +843 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logger/transports/console.d.ts +102 -0
- package/dist/logger/transports/console.d.ts.map +1 -0
- package/dist/logger/transports/console.js +276 -0
- package/dist/logger/transports/console.js.map +1 -0
- package/dist/logger/transports/database.d.ts +153 -0
- package/dist/logger/transports/database.d.ts.map +1 -0
- package/dist/logger/transports/database.js +539 -0
- package/dist/logger/transports/database.js.map +1 -0
- package/dist/logger/transports/file.d.ts +146 -0
- package/dist/logger/transports/file.d.ts.map +1 -0
- package/dist/logger/transports/file.js +464 -0
- package/dist/logger/transports/file.js.map +1 -0
- package/dist/logger/transports/http.d.ts +128 -0
- package/dist/logger/transports/http.d.ts.map +1 -0
- package/dist/logger/transports/http.js +401 -0
- package/dist/logger/transports/http.js.map +1 -0
- package/dist/logger/transports/webhook.d.ts +152 -0
- package/dist/logger/transports/webhook.d.ts.map +1 -0
- package/dist/logger/transports/webhook.js +485 -0
- package/dist/logger/transports/webhook.js.map +1 -0
- package/dist/queue/defaults.d.ts +66 -0
- package/dist/queue/defaults.d.ts.map +1 -0
- package/dist/queue/defaults.js +205 -0
- package/dist/queue/defaults.js.map +1 -0
- package/dist/queue/index.d.ts +124 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +116 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/queue.d.ts +156 -0
- package/dist/queue/queue.d.ts.map +1 -0
- package/dist/queue/queue.js +387 -0
- package/dist/queue/queue.js.map +1 -0
- package/dist/queue/transports/database.d.ts +165 -0
- package/dist/queue/transports/database.d.ts.map +1 -0
- package/dist/queue/transports/database.js +595 -0
- package/dist/queue/transports/database.js.map +1 -0
- package/dist/queue/transports/memory.d.ts +143 -0
- package/dist/queue/transports/memory.d.ts.map +1 -0
- package/dist/queue/transports/memory.js +415 -0
- package/dist/queue/transports/memory.js.map +1 -0
- package/dist/queue/transports/redis.d.ts +203 -0
- package/dist/queue/transports/redis.d.ts.map +1 -0
- package/dist/queue/transports/redis.js +744 -0
- package/dist/queue/transports/redis.js.map +1 -0
- package/dist/security/defaults.d.ts +64 -0
- package/dist/security/defaults.d.ts.map +1 -0
- package/dist/security/defaults.js +159 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/index.d.ts +110 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +160 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security.d.ts +138 -0
- package/dist/security/security.d.ts.map +1 -0
- package/dist/security/security.js +419 -0
- package/dist/security/security.js.map +1 -0
- package/dist/storage/defaults.d.ts +79 -0
- package/dist/storage/defaults.d.ts.map +1 -0
- package/dist/storage/defaults.js +358 -0
- package/dist/storage/defaults.js.map +1 -0
- package/dist/storage/index.d.ts +153 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +242 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/storage.d.ts +151 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +439 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/strategies/local.d.ts +117 -0
- package/dist/storage/strategies/local.d.ts.map +1 -0
- package/dist/storage/strategies/local.js +368 -0
- package/dist/storage/strategies/local.js.map +1 -0
- package/dist/storage/strategies/r2.d.ts +130 -0
- package/dist/storage/strategies/r2.d.ts.map +1 -0
- package/dist/storage/strategies/r2.js +470 -0
- package/dist/storage/strategies/r2.js.map +1 -0
- package/dist/storage/strategies/s3.d.ts +121 -0
- package/dist/storage/strategies/s3.d.ts.map +1 -0
- package/dist/storage/strategies/s3.js +461 -0
- package/dist/storage/strategies/s3.js.map +1 -0
- package/dist/util/defaults.d.ts +77 -0
- package/dist/util/defaults.d.ts.map +1 -0
- package/dist/util/defaults.js +193 -0
- package/dist/util/defaults.js.map +1 -0
- package/dist/util/index.d.ts +97 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +165 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/util.d.ts +145 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +481 -0
- package/dist/util/util.js.map +1 -0
- package/package.json +234 -0
|
@@ -0,0 +1,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":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;IACtD,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;IACvD,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;CACzD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,UAAU;IACd,MAAM,EAAE,WAAW,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAkD;IAClE,OAAO,CAAC,SAAS,CAAkB;gBAEvB,MAAM,EAAE,WAAW;IAK/B;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAatB;;;;;OAKG;IACG,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IA4BjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAE,MAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAgCpF;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ/E;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS9F;;;;;OAKG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;IAczE;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;;OAIG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;OAIG;IACH,SAAS,IAAI;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;KACpB;IAWD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAiDpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAYvB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd"}
|