@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,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook transport for real-time alerts with Slack and generic webhook support
|
|
3
|
+
* @module @bloomneo/appkit/logger
|
|
4
|
+
* @file src/logger/transports/webhook.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Need real-time error alerts or notifications to Slack/Discord/Teams
|
|
7
|
+
* @llm-rule AVOID: High-frequency logging - webhooks are for alerts, not all logs
|
|
8
|
+
* @llm-rule NOTE: Only sends errors by default, auto-detects Slack format, includes rate limiting
|
|
9
|
+
*/
|
|
10
|
+
import type { LogEntry, Transport } from '../logger.js';
|
|
11
|
+
import type { LoggingConfig } from '../defaults.js';
|
|
12
|
+
/**
|
|
13
|
+
* Webhook transport for real-time alerts with automatic service detection
|
|
14
|
+
*/
|
|
15
|
+
export declare class WebhookTransport implements Transport {
|
|
16
|
+
private url;
|
|
17
|
+
private level;
|
|
18
|
+
private rateLimit;
|
|
19
|
+
private minimal;
|
|
20
|
+
private parsedUrl;
|
|
21
|
+
private serviceType;
|
|
22
|
+
private rateLimitQueue;
|
|
23
|
+
private rateLimitWindow;
|
|
24
|
+
/**
|
|
25
|
+
* Creates webhook transport with direct environment access (like auth pattern)
|
|
26
|
+
* @llm-rule WHEN: Logger initialization with VOILA_LOGGING_WEBHOOK_URL environment variable
|
|
27
|
+
* @llm-rule AVOID: Manual webhook configuration - environment detection handles this
|
|
28
|
+
* @llm-rule NOTE: Auto-detects Slack URLs and formats messages appropriately
|
|
29
|
+
*/
|
|
30
|
+
constructor(config: LoggingConfig);
|
|
31
|
+
/**
|
|
32
|
+
* Detect webhook service type from URL
|
|
33
|
+
* @llm-rule WHEN: Determining message format based on webhook provider
|
|
34
|
+
* @llm-rule AVOID: Manual service configuration - URL detection is automatic
|
|
35
|
+
*/
|
|
36
|
+
private detectServiceType;
|
|
37
|
+
/**
|
|
38
|
+
* Write log entry to webhook (immediate, level-filtered)
|
|
39
|
+
* @llm-rule WHEN: Sending critical alerts and errors to notification services
|
|
40
|
+
* @llm-rule AVOID: Calling directly - logger routes entries automatically
|
|
41
|
+
*/
|
|
42
|
+
write(entry: LogEntry): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Check if log level should be sent to webhook
|
|
45
|
+
* @llm-rule WHEN: Filtering logs to only send important alerts
|
|
46
|
+
* @llm-rule AVOID: Sending all logs - webhooks are for errors and critical events
|
|
47
|
+
*/
|
|
48
|
+
private shouldSendLevel;
|
|
49
|
+
/**
|
|
50
|
+
* Check rate limiting to prevent webhook spam
|
|
51
|
+
* @llm-rule WHEN: Preventing too many webhook calls in short time
|
|
52
|
+
* @llm-rule AVOID: Unlimited webhook sending - can get you banned from services
|
|
53
|
+
*/
|
|
54
|
+
private checkRateLimit;
|
|
55
|
+
/**
|
|
56
|
+
* Optimize log entry for webhook alerts
|
|
57
|
+
* @llm-rule WHEN: Creating focused alert messages with essential information
|
|
58
|
+
* @llm-rule AVOID: Sending full log entries - webhooks need concise, actionable alerts
|
|
59
|
+
*/
|
|
60
|
+
private optimizeEntry;
|
|
61
|
+
/**
|
|
62
|
+
* Optimize error object for webhook alerts
|
|
63
|
+
* @llm-rule WHEN: Including error details in alerts without sensitive information
|
|
64
|
+
* @llm-rule AVOID: Including stack traces - security risk and too verbose for alerts
|
|
65
|
+
*/
|
|
66
|
+
private optimizeError;
|
|
67
|
+
/**
|
|
68
|
+
* Filter metadata for critical alert information only
|
|
69
|
+
* @llm-rule WHEN: Including only the most important context in alerts
|
|
70
|
+
* @llm-rule AVOID: Including all metadata - alerts should be concise and actionable
|
|
71
|
+
*/
|
|
72
|
+
private filterCriticalMeta;
|
|
73
|
+
/**
|
|
74
|
+
* Send log entry via webhook with service-specific formatting
|
|
75
|
+
* @llm-rule WHEN: Transmitting alert to webhook service
|
|
76
|
+
* @llm-rule AVOID: Generic format for known services - optimized formats are better
|
|
77
|
+
*/
|
|
78
|
+
private sendWebhook;
|
|
79
|
+
/**
|
|
80
|
+
* Format log entry for specific webhook services
|
|
81
|
+
* @llm-rule WHEN: Converting alerts to service-specific format for better presentation
|
|
82
|
+
* @llm-rule AVOID: Always using generic format - Slack format shows much better
|
|
83
|
+
*/
|
|
84
|
+
private formatWebhookPayload;
|
|
85
|
+
/**
|
|
86
|
+
* Format alert for Slack with rich formatting
|
|
87
|
+
* @llm-rule WHEN: Sending alerts to Slack channels for team notifications
|
|
88
|
+
* @llm-rule AVOID: Plain text format - Slack's rich format is much more readable
|
|
89
|
+
*/
|
|
90
|
+
private formatSlackPayload;
|
|
91
|
+
/**
|
|
92
|
+
* Get Slack color for different log levels
|
|
93
|
+
* @llm-rule WHEN: Styling Slack messages for visual priority
|
|
94
|
+
* @llm-rule AVOID: Same color for all levels - visual distinction helps prioritization
|
|
95
|
+
*/
|
|
96
|
+
private getSlackColor;
|
|
97
|
+
/**
|
|
98
|
+
* Get emoji for different log levels
|
|
99
|
+
* @llm-rule WHEN: Adding visual indicators to alerts for quick recognition
|
|
100
|
+
* @llm-rule AVOID: No visual indicators - emojis help with quick alert scanning
|
|
101
|
+
*/
|
|
102
|
+
private getLevelEmoji;
|
|
103
|
+
/**
|
|
104
|
+
* Map log level to alert severity
|
|
105
|
+
* @llm-rule WHEN: Converting log levels to standard alert severity levels
|
|
106
|
+
* @llm-rule AVOID: Using log levels directly - severity is more standardized
|
|
107
|
+
*/
|
|
108
|
+
private mapLevelToSeverity;
|
|
109
|
+
/**
|
|
110
|
+
* Make HTTP request with retry logic
|
|
111
|
+
* @llm-rule WHEN: Sending webhook with reliability for important alerts
|
|
112
|
+
* @llm-rule AVOID: Single attempt - webhooks can fail due to network issues
|
|
113
|
+
*/
|
|
114
|
+
private makeHttpRequest;
|
|
115
|
+
/**
|
|
116
|
+
* Execute single HTTP request with timeout
|
|
117
|
+
* @llm-rule WHEN: Making actual webhook call
|
|
118
|
+
* @llm-rule AVOID: Long timeouts - webhooks should respond quickly
|
|
119
|
+
*/
|
|
120
|
+
private executeHttpRequest;
|
|
121
|
+
/**
|
|
122
|
+
* Setup rate limit cleanup
|
|
123
|
+
* @llm-rule WHEN: Preventing memory leaks from rate limit tracking
|
|
124
|
+
* @llm-rule AVOID: Infinite memory growth - periodic cleanup is essential
|
|
125
|
+
*/
|
|
126
|
+
private setupRateLimitCleanup;
|
|
127
|
+
/**
|
|
128
|
+
* Sleep for specified milliseconds
|
|
129
|
+
* @llm-rule WHEN: Implementing retry delays
|
|
130
|
+
* @llm-rule AVOID: Busy waiting - proper sleep prevents CPU waste
|
|
131
|
+
*/
|
|
132
|
+
private sleep;
|
|
133
|
+
/**
|
|
134
|
+
* Check if this transport should log the given level
|
|
135
|
+
* @llm-rule WHEN: Logger asks if transport handles this level
|
|
136
|
+
* @llm-rule AVOID: Complex level logic - webhook uses own level filtering
|
|
137
|
+
*/
|
|
138
|
+
shouldLog(level: string, configLevel: string): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Flush pending logs (no-op for webhook - immediate sending)
|
|
141
|
+
* @llm-rule WHEN: Logger cleanup - webhooks send immediately
|
|
142
|
+
* @llm-rule AVOID: Expecting batching behavior - webhooks are immediate
|
|
143
|
+
*/
|
|
144
|
+
flush(): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Close webhook transport
|
|
147
|
+
* @llm-rule WHEN: Logger shutdown or cleanup
|
|
148
|
+
* @llm-rule AVOID: Expecting cleanup behavior - webhooks have no persistent resources
|
|
149
|
+
*/
|
|
150
|
+
close(): Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../../src/logger/transports/webhook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;GAEG;AACH,qBAAa,gBAAiB,YAAW,SAAS;IAChD,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAU;IAGzB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,eAAe,CAAS;IAEhC;;;;;OAKG;gBACS,MAAM,EAAE,aAAa;IAmBjC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B3C;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAStB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAqDrB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IA4BrB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;;;OAIG;YACW,WAAW;IAKzB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAoG1B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAUrB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAUrB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;;OAIG;YACW,eAAe;IAyB7B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAiD1B;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAS7B;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAIb;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAKtD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook transport for real-time alerts with Slack and generic webhook support
|
|
3
|
+
* @module @bloomneo/appkit/logger
|
|
4
|
+
* @file src/logger/transports/webhook.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Need real-time error alerts or notifications to Slack/Discord/Teams
|
|
7
|
+
* @llm-rule AVOID: High-frequency logging - webhooks are for alerts, not all logs
|
|
8
|
+
* @llm-rule NOTE: Only sends errors by default, auto-detects Slack format, includes rate limiting
|
|
9
|
+
*/
|
|
10
|
+
import https from 'https';
|
|
11
|
+
import http from 'http';
|
|
12
|
+
/**
|
|
13
|
+
* Webhook transport for real-time alerts with automatic service detection
|
|
14
|
+
*/
|
|
15
|
+
export class WebhookTransport {
|
|
16
|
+
url;
|
|
17
|
+
level;
|
|
18
|
+
rateLimit;
|
|
19
|
+
minimal;
|
|
20
|
+
// Webhook state
|
|
21
|
+
parsedUrl;
|
|
22
|
+
serviceType;
|
|
23
|
+
rateLimitQueue = [];
|
|
24
|
+
rateLimitWindow = 60000; // 1 minute
|
|
25
|
+
/**
|
|
26
|
+
* Creates webhook transport with direct environment access (like auth pattern)
|
|
27
|
+
* @llm-rule WHEN: Logger initialization with VOILA_LOGGING_WEBHOOK_URL environment variable
|
|
28
|
+
* @llm-rule AVOID: Manual webhook configuration - environment detection handles this
|
|
29
|
+
* @llm-rule NOTE: Auto-detects Slack URLs and formats messages appropriately
|
|
30
|
+
*/
|
|
31
|
+
constructor(config) {
|
|
32
|
+
// Direct access to config (like auth module pattern)
|
|
33
|
+
this.url = config.webhook.url;
|
|
34
|
+
this.level = config.webhook.level;
|
|
35
|
+
this.rateLimit = config.webhook.rateLimit;
|
|
36
|
+
this.minimal = config.minimal;
|
|
37
|
+
this.parsedUrl = new URL(this.url);
|
|
38
|
+
this.serviceType = this.detectServiceType();
|
|
39
|
+
// Adjust rate limiting for minimal mode (fewer alerts)
|
|
40
|
+
if (this.minimal) {
|
|
41
|
+
this.rateLimit = Math.min(this.rateLimit, 5);
|
|
42
|
+
}
|
|
43
|
+
// Initialize cleanup for rate limiting
|
|
44
|
+
this.setupRateLimitCleanup();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Detect webhook service type from URL
|
|
48
|
+
* @llm-rule WHEN: Determining message format based on webhook provider
|
|
49
|
+
* @llm-rule AVOID: Manual service configuration - URL detection is automatic
|
|
50
|
+
*/
|
|
51
|
+
detectServiceType() {
|
|
52
|
+
const hostname = this.parsedUrl.hostname.toLowerCase();
|
|
53
|
+
if (hostname.includes('slack.com'))
|
|
54
|
+
return 'slack';
|
|
55
|
+
return 'generic';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Write log entry to webhook (immediate, level-filtered)
|
|
59
|
+
* @llm-rule WHEN: Sending critical alerts and errors to notification services
|
|
60
|
+
* @llm-rule AVOID: Calling directly - logger routes entries automatically
|
|
61
|
+
*/
|
|
62
|
+
async write(entry) {
|
|
63
|
+
try {
|
|
64
|
+
// Check if this level should be sent
|
|
65
|
+
if (!this.shouldSendLevel(entry.level)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Check rate limiting to prevent spam
|
|
69
|
+
if (!this.checkRateLimit()) {
|
|
70
|
+
console.warn('Webhook rate limit exceeded, dropping alert');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Optimize entry for webhook transmission
|
|
74
|
+
const optimizedEntry = this.optimizeEntry(entry);
|
|
75
|
+
// Send immediately (webhooks are for real-time alerts)
|
|
76
|
+
await this.sendWebhook(optimizedEntry);
|
|
77
|
+
// Track for rate limiting
|
|
78
|
+
this.rateLimitQueue.push(Date.now());
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error('Webhook transport write error:', error.message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if log level should be sent to webhook
|
|
86
|
+
* @llm-rule WHEN: Filtering logs to only send important alerts
|
|
87
|
+
* @llm-rule AVOID: Sending all logs - webhooks are for errors and critical events
|
|
88
|
+
*/
|
|
89
|
+
shouldSendLevel(level) {
|
|
90
|
+
const levels = {
|
|
91
|
+
error: 0, warn: 1, info: 2, debug: 3
|
|
92
|
+
};
|
|
93
|
+
const configLevel = levels[this.level];
|
|
94
|
+
const entryLevel = levels[level];
|
|
95
|
+
return entryLevel <= configLevel;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check rate limiting to prevent webhook spam
|
|
99
|
+
* @llm-rule WHEN: Preventing too many webhook calls in short time
|
|
100
|
+
* @llm-rule AVOID: Unlimited webhook sending - can get you banned from services
|
|
101
|
+
*/
|
|
102
|
+
checkRateLimit() {
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
const recentWebhooks = this.rateLimitQueue.filter(timestamp => now - timestamp < this.rateLimitWindow);
|
|
105
|
+
return recentWebhooks.length < this.rateLimit;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Optimize log entry for webhook alerts
|
|
109
|
+
* @llm-rule WHEN: Creating focused alert messages with essential information
|
|
110
|
+
* @llm-rule AVOID: Sending full log entries - webhooks need concise, actionable alerts
|
|
111
|
+
*/
|
|
112
|
+
optimizeEntry(entry) {
|
|
113
|
+
const { timestamp, level, message, component, requestId, userId, method, url, statusCode, error, service, environment, ...rest } = entry;
|
|
114
|
+
const optimized = {
|
|
115
|
+
timestamp,
|
|
116
|
+
level,
|
|
117
|
+
message,
|
|
118
|
+
};
|
|
119
|
+
// Add essential context for alerts
|
|
120
|
+
if (component)
|
|
121
|
+
optimized.component = component;
|
|
122
|
+
if (requestId)
|
|
123
|
+
optimized.requestId = requestId;
|
|
124
|
+
if (userId)
|
|
125
|
+
optimized.userId = userId;
|
|
126
|
+
if (service)
|
|
127
|
+
optimized.service = service;
|
|
128
|
+
if (environment)
|
|
129
|
+
optimized.environment = environment;
|
|
130
|
+
// Add HTTP context for API errors
|
|
131
|
+
if (level === 'error') {
|
|
132
|
+
if (method)
|
|
133
|
+
optimized.method = method;
|
|
134
|
+
if (url)
|
|
135
|
+
optimized.url = url;
|
|
136
|
+
if (statusCode)
|
|
137
|
+
optimized.statusCode = statusCode;
|
|
138
|
+
}
|
|
139
|
+
// Optimize error information for alerts
|
|
140
|
+
if (error) {
|
|
141
|
+
optimized.error = this.optimizeError(error);
|
|
142
|
+
}
|
|
143
|
+
// Add only critical metadata for alerts
|
|
144
|
+
if (!this.minimal) {
|
|
145
|
+
const criticalMeta = this.filterCriticalMeta(rest);
|
|
146
|
+
if (Object.keys(criticalMeta).length > 0) {
|
|
147
|
+
optimized.meta = criticalMeta;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return optimized;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Optimize error object for webhook alerts
|
|
154
|
+
* @llm-rule WHEN: Including error details in alerts without sensitive information
|
|
155
|
+
* @llm-rule AVOID: Including stack traces - security risk and too verbose for alerts
|
|
156
|
+
*/
|
|
157
|
+
optimizeError(error) {
|
|
158
|
+
if (typeof error === 'string') {
|
|
159
|
+
return error;
|
|
160
|
+
}
|
|
161
|
+
if (typeof error === 'object' && error !== null) {
|
|
162
|
+
const optimized = {
|
|
163
|
+
message: error.message,
|
|
164
|
+
};
|
|
165
|
+
// Add important error fields for debugging
|
|
166
|
+
if (error.name && error.name !== 'Error') {
|
|
167
|
+
optimized.name = error.name;
|
|
168
|
+
}
|
|
169
|
+
if (error.code) {
|
|
170
|
+
optimized.code = error.code;
|
|
171
|
+
}
|
|
172
|
+
if (error.statusCode) {
|
|
173
|
+
optimized.statusCode = error.statusCode;
|
|
174
|
+
}
|
|
175
|
+
// Never include stack traces in webhooks (security + brevity)
|
|
176
|
+
return optimized;
|
|
177
|
+
}
|
|
178
|
+
return error;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Filter metadata for critical alert information only
|
|
182
|
+
* @llm-rule WHEN: Including only the most important context in alerts
|
|
183
|
+
* @llm-rule AVOID: Including all metadata - alerts should be concise and actionable
|
|
184
|
+
*/
|
|
185
|
+
filterCriticalMeta(meta) {
|
|
186
|
+
const critical = {};
|
|
187
|
+
// Only the most critical fields for alerts
|
|
188
|
+
const criticalKeys = [
|
|
189
|
+
'tenantId', 'appName', 'version'
|
|
190
|
+
];
|
|
191
|
+
for (const key of criticalKeys) {
|
|
192
|
+
if (meta[key] !== undefined) {
|
|
193
|
+
critical[key] = meta[key];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return critical;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Send log entry via webhook with service-specific formatting
|
|
200
|
+
* @llm-rule WHEN: Transmitting alert to webhook service
|
|
201
|
+
* @llm-rule AVOID: Generic format for known services - optimized formats are better
|
|
202
|
+
*/
|
|
203
|
+
async sendWebhook(entry) {
|
|
204
|
+
const payload = this.formatWebhookPayload(entry);
|
|
205
|
+
await this.makeHttpRequest(payload);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Format log entry for specific webhook services
|
|
209
|
+
* @llm-rule WHEN: Converting alerts to service-specific format for better presentation
|
|
210
|
+
* @llm-rule AVOID: Always using generic format - Slack format shows much better
|
|
211
|
+
*/
|
|
212
|
+
formatWebhookPayload(entry) {
|
|
213
|
+
switch (this.serviceType) {
|
|
214
|
+
case 'slack':
|
|
215
|
+
return JSON.stringify(this.formatSlackPayload(entry));
|
|
216
|
+
case 'generic':
|
|
217
|
+
default:
|
|
218
|
+
return JSON.stringify({
|
|
219
|
+
timestamp: entry.timestamp,
|
|
220
|
+
level: entry.level,
|
|
221
|
+
message: entry.message,
|
|
222
|
+
scope: this.minimal ? 'minimal' : 'full',
|
|
223
|
+
data: entry,
|
|
224
|
+
alert: {
|
|
225
|
+
severity: this.mapLevelToSeverity(entry.level),
|
|
226
|
+
service: entry.service || 'unknown',
|
|
227
|
+
component: entry.component || 'unknown',
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Format alert for Slack with rich formatting
|
|
234
|
+
* @llm-rule WHEN: Sending alerts to Slack channels for team notifications
|
|
235
|
+
* @llm-rule AVOID: Plain text format - Slack's rich format is much more readable
|
|
236
|
+
*/
|
|
237
|
+
formatSlackPayload(entry) {
|
|
238
|
+
const color = this.getSlackColor(entry.level);
|
|
239
|
+
const emoji = this.getLevelEmoji(entry.level);
|
|
240
|
+
const scopeIndicator = this.minimal ? '🔹' : '🔸';
|
|
241
|
+
const fields = [
|
|
242
|
+
{
|
|
243
|
+
title: 'Message',
|
|
244
|
+
value: entry.message,
|
|
245
|
+
short: false,
|
|
246
|
+
},
|
|
247
|
+
];
|
|
248
|
+
// Add context fields
|
|
249
|
+
if (entry.component) {
|
|
250
|
+
fields.push({
|
|
251
|
+
title: 'Component',
|
|
252
|
+
value: entry.component,
|
|
253
|
+
short: true,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
if (entry.service) {
|
|
257
|
+
fields.push({
|
|
258
|
+
title: 'Service',
|
|
259
|
+
value: entry.service,
|
|
260
|
+
short: true,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (entry.environment) {
|
|
264
|
+
fields.push({
|
|
265
|
+
title: 'Environment',
|
|
266
|
+
value: entry.environment,
|
|
267
|
+
short: true,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
// Add error details if present
|
|
271
|
+
if (entry.error) {
|
|
272
|
+
const errorText = typeof entry.error === 'object'
|
|
273
|
+
? entry.error.message
|
|
274
|
+
: entry.error;
|
|
275
|
+
fields.push({
|
|
276
|
+
title: 'Error Details',
|
|
277
|
+
value: errorText,
|
|
278
|
+
short: false,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
// Add HTTP context for API errors
|
|
282
|
+
if (entry.level === 'error' && (entry.method || entry.url || entry.statusCode)) {
|
|
283
|
+
let httpInfo = '';
|
|
284
|
+
if (entry.method && entry.url) {
|
|
285
|
+
httpInfo += `${entry.method} ${entry.url}`;
|
|
286
|
+
}
|
|
287
|
+
if (entry.statusCode) {
|
|
288
|
+
httpInfo += ` (${entry.statusCode})`;
|
|
289
|
+
}
|
|
290
|
+
if (httpInfo) {
|
|
291
|
+
fields.push({
|
|
292
|
+
title: 'HTTP Context',
|
|
293
|
+
value: httpInfo,
|
|
294
|
+
short: true,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// Add user context if available
|
|
299
|
+
if (entry.userId) {
|
|
300
|
+
fields.push({
|
|
301
|
+
title: 'User ID',
|
|
302
|
+
value: entry.userId,
|
|
303
|
+
short: true,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
if (entry.requestId) {
|
|
307
|
+
fields.push({
|
|
308
|
+
title: 'Request ID',
|
|
309
|
+
value: entry.requestId,
|
|
310
|
+
short: true,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
text: `${scopeIndicator} ${emoji} *${entry.level.toUpperCase()}* Alert`,
|
|
315
|
+
attachments: [
|
|
316
|
+
{
|
|
317
|
+
color: color,
|
|
318
|
+
fields: fields,
|
|
319
|
+
footer: 'VoilaJSX AppKit Logging',
|
|
320
|
+
ts: Math.floor(new Date(entry.timestamp).getTime() / 1000),
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get Slack color for different log levels
|
|
327
|
+
* @llm-rule WHEN: Styling Slack messages for visual priority
|
|
328
|
+
* @llm-rule AVOID: Same color for all levels - visual distinction helps prioritization
|
|
329
|
+
*/
|
|
330
|
+
getSlackColor(level) {
|
|
331
|
+
const colors = {
|
|
332
|
+
error: 'danger', // Red
|
|
333
|
+
warn: 'warning', // Yellow
|
|
334
|
+
info: 'good', // Green
|
|
335
|
+
debug: '#36a64f', // Light green
|
|
336
|
+
};
|
|
337
|
+
return colors[level] || 'good';
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Get emoji for different log levels
|
|
341
|
+
* @llm-rule WHEN: Adding visual indicators to alerts for quick recognition
|
|
342
|
+
* @llm-rule AVOID: No visual indicators - emojis help with quick alert scanning
|
|
343
|
+
*/
|
|
344
|
+
getLevelEmoji(level) {
|
|
345
|
+
const emojis = {
|
|
346
|
+
error: '🚨', // Siren
|
|
347
|
+
warn: '⚠️', // Warning
|
|
348
|
+
info: 'ℹ️', // Information
|
|
349
|
+
debug: '🐛', // Bug
|
|
350
|
+
};
|
|
351
|
+
return emojis[level] || 'ℹ️';
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Map log level to alert severity
|
|
355
|
+
* @llm-rule WHEN: Converting log levels to standard alert severity levels
|
|
356
|
+
* @llm-rule AVOID: Using log levels directly - severity is more standardized
|
|
357
|
+
*/
|
|
358
|
+
mapLevelToSeverity(level) {
|
|
359
|
+
const severityMap = {
|
|
360
|
+
error: 'critical',
|
|
361
|
+
warn: 'warning',
|
|
362
|
+
info: 'info',
|
|
363
|
+
debug: 'low',
|
|
364
|
+
};
|
|
365
|
+
return severityMap[level] || 'info';
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Make HTTP request with retry logic
|
|
369
|
+
* @llm-rule WHEN: Sending webhook with reliability for important alerts
|
|
370
|
+
* @llm-rule AVOID: Single attempt - webhooks can fail due to network issues
|
|
371
|
+
*/
|
|
372
|
+
async makeHttpRequest(payload) {
|
|
373
|
+
const maxRetries = 2; // Limited retries for webhooks
|
|
374
|
+
let lastError;
|
|
375
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
376
|
+
try {
|
|
377
|
+
await this.executeHttpRequest(payload);
|
|
378
|
+
return; // Success
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
lastError = error;
|
|
382
|
+
if (attempt < maxRetries) {
|
|
383
|
+
const delay = 1000 * attempt; // Linear backoff for webhooks
|
|
384
|
+
console.warn(`Webhook attempt ${attempt} failed, retrying in ${delay}ms:`, error.message);
|
|
385
|
+
await this.sleep(delay);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
throw lastError;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Execute single HTTP request with timeout
|
|
393
|
+
* @llm-rule WHEN: Making actual webhook call
|
|
394
|
+
* @llm-rule AVOID: Long timeouts - webhooks should respond quickly
|
|
395
|
+
*/
|
|
396
|
+
executeHttpRequest(payload) {
|
|
397
|
+
return new Promise((resolve, reject) => {
|
|
398
|
+
const isHttps = this.parsedUrl.protocol === 'https:';
|
|
399
|
+
const httpModule = isHttps ? https : http;
|
|
400
|
+
const options = {
|
|
401
|
+
hostname: this.parsedUrl.hostname,
|
|
402
|
+
port: this.parsedUrl.port || (isHttps ? 443 : 80),
|
|
403
|
+
path: this.parsedUrl.pathname + this.parsedUrl.search,
|
|
404
|
+
method: 'POST',
|
|
405
|
+
headers: {
|
|
406
|
+
'Content-Type': 'application/json',
|
|
407
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
408
|
+
'User-Agent': 'VoilaJSX-AppKit-Logging/1.0.0',
|
|
409
|
+
},
|
|
410
|
+
timeout: 10000, // 10 second timeout for webhooks
|
|
411
|
+
};
|
|
412
|
+
const req = httpModule.request(options, (res) => {
|
|
413
|
+
let responseData = '';
|
|
414
|
+
res.on('data', (chunk) => {
|
|
415
|
+
responseData += chunk;
|
|
416
|
+
});
|
|
417
|
+
res.on('end', () => {
|
|
418
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
419
|
+
resolve();
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
reject(new Error(`Webhook HTTP ${res.statusCode}: ${responseData}`));
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
req.on('timeout', () => {
|
|
427
|
+
req.destroy();
|
|
428
|
+
reject(new Error('Webhook timeout after 10000ms'));
|
|
429
|
+
});
|
|
430
|
+
req.on('error', (error) => {
|
|
431
|
+
reject(new Error(`Webhook request failed: ${error.message}`));
|
|
432
|
+
});
|
|
433
|
+
// Write payload and end request
|
|
434
|
+
req.write(payload);
|
|
435
|
+
req.end();
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Setup rate limit cleanup
|
|
440
|
+
* @llm-rule WHEN: Preventing memory leaks from rate limit tracking
|
|
441
|
+
* @llm-rule AVOID: Infinite memory growth - periodic cleanup is essential
|
|
442
|
+
*/
|
|
443
|
+
setupRateLimitCleanup() {
|
|
444
|
+
setInterval(() => {
|
|
445
|
+
const now = Date.now();
|
|
446
|
+
this.rateLimitQueue = this.rateLimitQueue.filter(timestamp => now - timestamp < this.rateLimitWindow);
|
|
447
|
+
}, this.rateLimitWindow);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Sleep for specified milliseconds
|
|
451
|
+
* @llm-rule WHEN: Implementing retry delays
|
|
452
|
+
* @llm-rule AVOID: Busy waiting - proper sleep prevents CPU waste
|
|
453
|
+
*/
|
|
454
|
+
sleep(ms) {
|
|
455
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Check if this transport should log the given level
|
|
459
|
+
* @llm-rule WHEN: Logger asks if transport handles this level
|
|
460
|
+
* @llm-rule AVOID: Complex level logic - webhook uses own level filtering
|
|
461
|
+
*/
|
|
462
|
+
shouldLog(level, configLevel) {
|
|
463
|
+
// Webhook uses its own level filtering via shouldSendLevel
|
|
464
|
+
return this.shouldSendLevel(level);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Flush pending logs (no-op for webhook - immediate sending)
|
|
468
|
+
* @llm-rule WHEN: Logger cleanup - webhooks send immediately
|
|
469
|
+
* @llm-rule AVOID: Expecting batching behavior - webhooks are immediate
|
|
470
|
+
*/
|
|
471
|
+
async flush() {
|
|
472
|
+
// Webhooks send immediately, no batching needed
|
|
473
|
+
return Promise.resolve();
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Close webhook transport
|
|
477
|
+
* @llm-rule WHEN: Logger shutdown or cleanup
|
|
478
|
+
* @llm-rule AVOID: Expecting cleanup behavior - webhooks have no persistent resources
|
|
479
|
+
*/
|
|
480
|
+
async close() {
|
|
481
|
+
// Webhook transport has no persistent resources to clean up
|
|
482
|
+
return Promise.resolve();
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../../src/logger/transports/webhook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB;;GAEG;AACH,MAAM,OAAO,gBAAgB;IACnB,GAAG,CAAS;IACZ,KAAK,CAAsC;IAC3C,SAAS,CAAS;IAClB,OAAO,CAAU;IAEzB,gBAAgB;IACR,SAAS,CAAM;IACf,WAAW,CAAsB;IACjC,cAAc,GAAa,EAAE,CAAC;IAC9B,eAAe,GAAG,KAAK,CAAC,CAAC,WAAW;IAE5C;;;;;OAKG;IACH,YAAY,MAAqB;QAC/B,qDAAqD;QACrD,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAI,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE9B,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE5C,uDAAuD;QACvD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,uCAAuC;QACvC,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACK,iBAAiB;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAEvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,OAAO,OAAO,CAAC;QAEnD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,KAAe;QACzB,IAAI,CAAC;YACH,qCAAqC;YACrC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,sCAAsC;YACtC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC3B,OAAO,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YAED,0CAA0C;YAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAEjD,uDAAuD;YACvD,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;YAEvC,0BAA0B;YAC1B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,eAAe,CAAC,KAAa;QACnC,MAAM,MAAM,GAA2B;YACrC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;SACrC,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjC,OAAO,UAAU,IAAI,WAAW,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACK,cAAc;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAC/C,SAAS,CAAC,EAAE,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,eAAe,CACpD,CAAC;QAEF,OAAO,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACK,aAAa,CAAC,KAAe;QACnC,MAAM,EACJ,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,MAAM,EACN,GAAG,EACH,UAAU,EACV,KAAK,EACL,OAAO,EACP,WAAW,EACX,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;QAEV,MAAM,SAAS,GAAQ;YACrB,SAAS;YACT,KAAK;YACL,OAAO;SACR,CAAC;QAEF,mCAAmC;QACnC,IAAI,SAAS;YAAE,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/C,IAAI,SAAS;YAAE,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/C,IAAI,MAAM;YAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;QACtC,IAAI,OAAO;YAAE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;QACzC,IAAI,WAAW;YAAE,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;QAErD,kCAAkC;QAClC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,IAAI,MAAM;gBAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;YACtC,IAAI,GAAG;gBAAE,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC;YAC7B,IAAI,UAAU;gBAAE,SAAS,CAAC,UAAU,GAAG,UAAU,CAAC;QACpD,CAAC;QAED,wCAAwC;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;QAED,wCAAwC;QACxC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACnD,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,SAAS,CAAC,IAAI,GAAG,YAAY,CAAC;YAChC,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACK,aAAa,CAAC,KAAU;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,MAAM,SAAS,GAAQ;gBACrB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC;YAEF,2CAA2C;YAC3C,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACzC,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YAC9B,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBACf,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YAC9B,CAAC;YACD,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,SAAS,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAC1C,CAAC;YAED,8DAA8D;YAC9D,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,IAAS;QAClC,MAAM,QAAQ,GAAQ,EAAE,CAAC;QAEzB,2CAA2C;QAC3C,MAAM,YAAY,GAAG;YACnB,UAAU,EAAE,SAAS,EAAE,SAAS;SACjC,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC5B,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,WAAW,CAAC,KAAU;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACK,oBAAoB,CAAC,KAAU;QACrC,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;YAExD,KAAK,SAAS,CAAC;YACf;gBACE,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;oBACxC,IAAI,EAAE,KAAK;oBACX,KAAK,EAAE;wBACL,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC;wBAC9C,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;wBACnC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;qBACxC;iBACF,CAAC,CAAC;QACP,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,KAAU;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAElD,MAAM,MAAM,GAAU;YACpB;gBACE,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,KAAK,EAAE,KAAK;aACb;SACF,CAAC;QAEF,qBAAqB;QACrB,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,WAAW;gBAClB,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,aAAa;gBACpB,KAAK,EAAE,KAAK,CAAC,WAAW;gBACxB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;gBAC/C,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO;gBACrB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;YAEhB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,eAAe;gBACtB,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;QAED,kCAAkC;QAClC,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/E,IAAI,QAAQ,GAAG,EAAE,CAAC;YAClB,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC9B,QAAQ,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7C,CAAC;YACD,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,QAAQ,IAAI,KAAK,KAAK,CAAC,UAAU,GAAG,CAAC;YACvC,CAAC;YAED,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,cAAc;oBACrB,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,IAAI;iBACZ,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,gCAAgC;QAChC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,YAAY;gBACnB,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,IAAI,EAAE,GAAG,cAAc,IAAI,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS;YACvE,WAAW,EAAE;gBACX;oBACE,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,yBAAyB;oBACjC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;iBAC3D;aACF;SACF,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,aAAa,CAAC,KAAa;QACjC,MAAM,MAAM,GAA2B;YACrC,KAAK,EAAE,QAAQ,EAAK,MAAM;YAC1B,IAAI,EAAE,SAAS,EAAK,WAAW;YAC/B,IAAI,EAAE,MAAM,EAAQ,QAAQ;YAC5B,KAAK,EAAE,SAAS,EAAI,cAAc;SACnC,CAAC;QACF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACK,aAAa,CAAC,KAAa;QACjC,MAAM,MAAM,GAA2B;YACrC,KAAK,EAAE,IAAI,EAAG,QAAQ;YACtB,IAAI,EAAE,IAAI,EAAI,UAAU;YACxB,IAAI,EAAE,IAAI,EAAI,cAAc;YAC5B,KAAK,EAAE,IAAI,EAAG,MAAM;SACrB,CAAC;QACF,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,KAAa;QACtC,MAAM,WAAW,GAA2B;YAC1C,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,KAAK;SACb,CAAC;QACF,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,eAAe,CAAC,OAAe;QAC3C,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,+BAA+B;QACrD,IAAI,SAAgB,CAAC;QAErB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACvC,OAAO,CAAC,UAAU;YACpB,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,SAAS,GAAG,KAAc,CAAC;gBAE3B,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;oBACzB,MAAM,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,8BAA8B;oBAC5D,OAAO,CAAC,IAAI,CACV,mBAAmB,OAAO,wBAAwB,KAAK,KAAK,EAC5D,KAAK,CAAC,OAAO,CACd,CAAC;oBACF,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAU,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,OAAe;QACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC;YACrD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAE1C,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ;gBACjC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM;gBACrD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;oBAC5C,YAAY,EAAE,+BAA+B;iBAC9C;gBACD,OAAO,EAAE,KAAK,EAAE,iCAAiC;aAClD,CAAC;YAEF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC9C,IAAI,YAAY,GAAG,EAAE,CAAC;gBAEtB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;oBACvB,YAAY,IAAI,KAAK,CAAC;gBACxB,CAAC,CAAC,CAAC;gBAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;wBACpE,OAAO,EAAE,CAAC;oBACZ,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,UAAU,KAAK,YAAY,EAAE,CAAC,CAAC,CAAC;oBACvE,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACrB,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACxB,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC,CAAC,CAAC;YAEH,gCAAgC;YAChC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,qBAAqB;QAC3B,WAAW,CAAC,GAAG,EAAE;YACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAC9C,SAAS,CAAC,EAAE,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,eAAe,CACpD,CAAC;QACJ,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,KAAa,EAAE,WAAmB;QAC1C,2DAA2D;QAC3D,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK;QACT,gDAAgD;QAChD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK;QACT,4DAA4D;QAC5D,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF"}
|