@zincapp/zn-vault-agent 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +701 -0
  2. package/deploy/logrotate.d/zn-vault-agent +14 -0
  3. package/deploy/systemd/zn-vault-agent.service +75 -0
  4. package/dist/commands/certs.d.ts +3 -0
  5. package/dist/commands/certs.d.ts.map +1 -0
  6. package/dist/commands/certs.js +369 -0
  7. package/dist/commands/certs.js.map +1 -0
  8. package/dist/commands/exec.d.ts +3 -0
  9. package/dist/commands/exec.d.ts.map +1 -0
  10. package/dist/commands/exec.js +193 -0
  11. package/dist/commands/exec.js.map +1 -0
  12. package/dist/commands/login.d.ts +3 -0
  13. package/dist/commands/login.d.ts.map +1 -0
  14. package/dist/commands/login.js +234 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/commands/secrets.d.ts +3 -0
  17. package/dist/commands/secrets.d.ts.map +1 -0
  18. package/dist/commands/secrets.js +445 -0
  19. package/dist/commands/secrets.js.map +1 -0
  20. package/dist/commands/setup.d.ts +9 -0
  21. package/dist/commands/setup.d.ts.map +1 -0
  22. package/dist/commands/setup.js +346 -0
  23. package/dist/commands/setup.js.map +1 -0
  24. package/dist/commands/start.d.ts +3 -0
  25. package/dist/commands/start.d.ts.map +1 -0
  26. package/dist/commands/start.js +113 -0
  27. package/dist/commands/start.js.map +1 -0
  28. package/dist/commands/status.d.ts +3 -0
  29. package/dist/commands/status.d.ts.map +1 -0
  30. package/dist/commands/status.js +85 -0
  31. package/dist/commands/status.js.map +1 -0
  32. package/dist/commands/sync.d.ts +3 -0
  33. package/dist/commands/sync.d.ts.map +1 -0
  34. package/dist/commands/sync.js +126 -0
  35. package/dist/commands/sync.js.map +1 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +28 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/lib/api.d.ts +104 -0
  41. package/dist/lib/api.d.ts.map +1 -0
  42. package/dist/lib/api.js +338 -0
  43. package/dist/lib/api.js.map +1 -0
  44. package/dist/lib/config.d.ts +164 -0
  45. package/dist/lib/config.d.ts.map +1 -0
  46. package/dist/lib/config.js +299 -0
  47. package/dist/lib/config.js.map +1 -0
  48. package/dist/lib/deployer.d.ts +22 -0
  49. package/dist/lib/deployer.d.ts.map +1 -0
  50. package/dist/lib/deployer.js +407 -0
  51. package/dist/lib/deployer.js.map +1 -0
  52. package/dist/lib/health.d.ts +68 -0
  53. package/dist/lib/health.d.ts.map +1 -0
  54. package/dist/lib/health.js +216 -0
  55. package/dist/lib/health.js.map +1 -0
  56. package/dist/lib/logger.d.ts +38 -0
  57. package/dist/lib/logger.d.ts.map +1 -0
  58. package/dist/lib/logger.js +161 -0
  59. package/dist/lib/logger.js.map +1 -0
  60. package/dist/lib/metrics.d.ts +50 -0
  61. package/dist/lib/metrics.d.ts.map +1 -0
  62. package/dist/lib/metrics.js +273 -0
  63. package/dist/lib/metrics.js.map +1 -0
  64. package/dist/lib/secret-deployer.d.ts +22 -0
  65. package/dist/lib/secret-deployer.d.ts.map +1 -0
  66. package/dist/lib/secret-deployer.js +201 -0
  67. package/dist/lib/secret-deployer.js.map +1 -0
  68. package/dist/lib/validation.d.ts +25 -0
  69. package/dist/lib/validation.d.ts.map +1 -0
  70. package/dist/lib/validation.js +257 -0
  71. package/dist/lib/validation.js.map +1 -0
  72. package/dist/lib/websocket.d.ts +74 -0
  73. package/dist/lib/websocket.d.ts.map +1 -0
  74. package/dist/lib/websocket.js +441 -0
  75. package/dist/lib/websocket.js.map +1 -0
  76. package/dist/services/api-key-renewal.d.ts +13 -0
  77. package/dist/services/api-key-renewal.d.ts.map +1 -0
  78. package/dist/services/api-key-renewal.js +204 -0
  79. package/dist/services/api-key-renewal.js.map +1 -0
  80. package/dist/services/npm-auto-update.d.ts +60 -0
  81. package/dist/services/npm-auto-update.d.ts.map +1 -0
  82. package/dist/services/npm-auto-update.js +245 -0
  83. package/dist/services/npm-auto-update.js.map +1 -0
  84. package/dist/types/update.d.ts +19 -0
  85. package/dist/types/update.d.ts.map +1 -0
  86. package/dist/types/update.js +7 -0
  87. package/dist/types/update.js.map +1 -0
  88. package/package.json +74 -0
@@ -0,0 +1,216 @@
1
+ // Path: src/lib/health.ts
2
+ // HTTP health and metrics endpoint for zn-vault-agent
3
+ import http from 'node:http';
4
+ import { healthLogger as log } from './logger.js';
5
+ import { exportMetrics } from './metrics.js';
6
+ import { loadConfig, getTargets, isConfigured } from './config.js';
7
+ // Track health state
8
+ let certWsConnected = false;
9
+ let lastCertWsEvent = null;
10
+ let secretWsConnected = false;
11
+ let lastSecretWsEvent = null;
12
+ let vaultReachable = false;
13
+ let syncedCerts = 0;
14
+ let certErrors = 0;
15
+ let syncedSecrets = 0;
16
+ let secretErrors = 0;
17
+ let server = null;
18
+ /**
19
+ * Update WebSocket connection status for certificates
20
+ */
21
+ export function setWebSocketStatus(connected, eventTime) {
22
+ certWsConnected = connected;
23
+ if (eventTime) {
24
+ lastCertWsEvent = eventTime;
25
+ }
26
+ }
27
+ /**
28
+ * Update WebSocket connection status for secrets
29
+ */
30
+ export function setSecretWebSocketStatus(connected, eventTime) {
31
+ secretWsConnected = connected;
32
+ if (eventTime) {
33
+ lastSecretWsEvent = eventTime;
34
+ }
35
+ }
36
+ /**
37
+ * Update vault reachability status
38
+ */
39
+ export function setVaultReachable(reachable) {
40
+ vaultReachable = reachable;
41
+ }
42
+ /**
43
+ * Update certificate sync status
44
+ */
45
+ export function updateCertStatus(synced, errors) {
46
+ syncedCerts = synced;
47
+ certErrors = errors;
48
+ }
49
+ /**
50
+ * Update secret sync status
51
+ */
52
+ export function updateSecretStatus(synced, errors) {
53
+ syncedSecrets = synced;
54
+ secretErrors = errors;
55
+ }
56
+ /**
57
+ * Get current health status
58
+ */
59
+ export function getHealthStatus() {
60
+ const config = loadConfig();
61
+ const targets = getTargets();
62
+ const secretTargets = config.secretTargets || [];
63
+ let status = 'healthy';
64
+ // Determine overall status
65
+ const hasTargets = targets.length > 0 || secretTargets.length > 0;
66
+ const wsConnected = (targets.length === 0 || certWsConnected) &&
67
+ (secretTargets.length === 0 || secretWsConnected);
68
+ if (hasTargets && (!wsConnected || !vaultReachable)) {
69
+ status = 'degraded';
70
+ }
71
+ if (certErrors > 0 || secretErrors > 0) {
72
+ status = 'degraded';
73
+ }
74
+ if (!isConfigured()) {
75
+ status = 'unhealthy';
76
+ }
77
+ return {
78
+ status,
79
+ timestamp: new Date().toISOString(),
80
+ uptime: process.uptime(),
81
+ version: process.env.npm_package_version || '1.0.0',
82
+ websocket: {
83
+ certificates: {
84
+ connected: certWsConnected,
85
+ lastEvent: lastCertWsEvent?.toISOString(),
86
+ },
87
+ secrets: {
88
+ connected: secretWsConnected,
89
+ lastEvent: lastSecretWsEvent?.toISOString(),
90
+ },
91
+ },
92
+ vault: {
93
+ url: config.vaultUrl || 'not configured',
94
+ reachable: vaultReachable,
95
+ },
96
+ certificates: {
97
+ total: targets.length,
98
+ synced: syncedCerts,
99
+ errors: certErrors,
100
+ },
101
+ secrets: {
102
+ total: secretTargets.length,
103
+ synced: syncedSecrets,
104
+ errors: secretErrors,
105
+ },
106
+ };
107
+ }
108
+ /**
109
+ * Handle HTTP requests
110
+ */
111
+ function handleRequest(req, res) {
112
+ const url = req.url || '/';
113
+ log.debug({ method: req.method, url }, 'Health endpoint request');
114
+ // CORS headers for monitoring tools
115
+ res.setHeader('Access-Control-Allow-Origin', '*');
116
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
117
+ if (req.method === 'OPTIONS') {
118
+ res.writeHead(204);
119
+ res.end();
120
+ return;
121
+ }
122
+ if (req.method !== 'GET') {
123
+ res.writeHead(405, { 'Content-Type': 'application/json' });
124
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
125
+ return;
126
+ }
127
+ switch (url) {
128
+ case '/health':
129
+ case '/health/': {
130
+ const health = getHealthStatus();
131
+ const statusCode = health.status === 'unhealthy' ? 503 : 200;
132
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
133
+ res.end(JSON.stringify(health, null, 2));
134
+ break;
135
+ }
136
+ case '/ready':
137
+ case '/ready/': {
138
+ // Readiness probe - are we configured and at least one WebSocket connected?
139
+ const ready = isConfigured() && (certWsConnected || secretWsConnected);
140
+ res.writeHead(ready ? 200 : 503, { 'Content-Type': 'application/json' });
141
+ res.end(JSON.stringify({ ready, timestamp: new Date().toISOString() }));
142
+ break;
143
+ }
144
+ case '/live':
145
+ case '/live/': {
146
+ // Liveness probe - is the process running?
147
+ res.writeHead(200, { 'Content-Type': 'application/json' });
148
+ res.end(JSON.stringify({ alive: true, timestamp: new Date().toISOString() }));
149
+ break;
150
+ }
151
+ case '/metrics':
152
+ case '/metrics/': {
153
+ // Prometheus metrics
154
+ res.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8' });
155
+ res.end(exportMetrics());
156
+ break;
157
+ }
158
+ default:
159
+ res.writeHead(404, { 'Content-Type': 'application/json' });
160
+ res.end(JSON.stringify({ error: 'Not found' }));
161
+ }
162
+ }
163
+ /**
164
+ * Start the health HTTP server
165
+ */
166
+ export function startHealthServer(port = 9100) {
167
+ return new Promise((resolve, reject) => {
168
+ if (server) {
169
+ log.warn('Health server already running');
170
+ resolve(server);
171
+ return;
172
+ }
173
+ server = http.createServer(handleRequest);
174
+ server.on('error', (err) => {
175
+ if (err.code === 'EADDRINUSE') {
176
+ log.error({ port }, 'Health server port already in use');
177
+ }
178
+ else {
179
+ log.error({ err }, 'Health server error');
180
+ }
181
+ reject(err);
182
+ });
183
+ server.listen(port, '0.0.0.0', () => {
184
+ log.info({ port }, 'Health server started');
185
+ resolve(server);
186
+ });
187
+ });
188
+ }
189
+ /**
190
+ * Stop the health HTTP server
191
+ */
192
+ export function stopHealthServer() {
193
+ return new Promise((resolve) => {
194
+ if (!server) {
195
+ resolve();
196
+ return;
197
+ }
198
+ server.close((err) => {
199
+ if (err) {
200
+ log.warn({ err }, 'Error closing health server');
201
+ }
202
+ else {
203
+ log.info('Health server stopped');
204
+ }
205
+ server = null;
206
+ resolve();
207
+ });
208
+ });
209
+ }
210
+ /**
211
+ * Check if health server is running
212
+ */
213
+ export function isHealthServerRunning() {
214
+ return server !== null && server.listening;
215
+ }
216
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/lib/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import pino from 'pino';
2
+ /**
3
+ * Base logger instance
4
+ *
5
+ * In development: Uses pino-pretty with colorized output
6
+ * In production: JSON logs to stdout (captured by journald) + optional file
7
+ *
8
+ * Configure via environment variables:
9
+ * - LOG_LEVEL: trace, debug, info, warn, error, fatal (default: debug in dev, info in prod)
10
+ * - LOG_FILE: Path to log file (default: /var/log/zn-vault-agent/agent.log in prod)
11
+ */
12
+ export declare const logger: pino.Logger<never, boolean>;
13
+ /**
14
+ * Create a child logger with additional context
15
+ *
16
+ * @example
17
+ * const log = createLogger({ module: 'deployer' });
18
+ * log.info({ certId: 'xxx' }, 'Certificate deployed');
19
+ */
20
+ export declare function createLogger(context: Record<string, unknown>): pino.Logger;
21
+ export declare const wsLogger: pino.Logger<never, boolean>;
22
+ export declare const apiLogger: pino.Logger<never, boolean>;
23
+ export declare const deployLogger: pino.Logger<never, boolean>;
24
+ export declare const configLogger: pino.Logger<never, boolean>;
25
+ export declare const metricsLogger: pino.Logger<never, boolean>;
26
+ export declare const healthLogger: pino.Logger<never, boolean>;
27
+ /**
28
+ * Flush logs and close file streams
29
+ * Call this before process exit for clean shutdown
30
+ */
31
+ export declare function flushLogs(): Promise<void>;
32
+ /**
33
+ * Handle log rotation signal (USR1)
34
+ * Reopens the log file destination
35
+ */
36
+ export declare function setupLogRotation(): void;
37
+ export type Logger = pino.Logger;
38
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,MAAM,CAAC;AAoFxB;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,6BA6BlB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAE1E;AAGD,eAAO,MAAM,QAAQ,6BAAwC,CAAC;AAC9D,eAAO,MAAM,SAAS,6BAAkC,CAAC;AACzD,eAAO,MAAM,YAAY,6BAAuC,CAAC;AACjE,eAAO,MAAM,YAAY,6BAAqC,CAAC;AAC/D,eAAO,MAAM,aAAa,6BAAsC,CAAC;AACjE,eAAO,MAAM,YAAY,6BAAqC,CAAC;AAE/D;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC;AAED,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC"}
@@ -0,0 +1,161 @@
1
+ // Path: src/lib/logger.ts
2
+ // Centralized Pino logger for zn-vault-agent
3
+ import pino from 'pino';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ const isDev = process.env.NODE_ENV !== 'production';
7
+ const logFile = process.env.LOG_FILE || (isDev ? undefined : '/var/log/zn-vault-agent/agent.log');
8
+ /**
9
+ * Create file stream for logging if LOG_FILE is set
10
+ */
11
+ function createFileStream() {
12
+ if (!logFile)
13
+ return undefined;
14
+ // Ensure log directory exists
15
+ const logDir = path.dirname(logFile);
16
+ if (!fs.existsSync(logDir)) {
17
+ try {
18
+ fs.mkdirSync(logDir, { recursive: true, mode: 0o750 });
19
+ }
20
+ catch {
21
+ // Can't create log directory, skip file logging
22
+ return undefined;
23
+ }
24
+ }
25
+ try {
26
+ return pino.destination({
27
+ dest: logFile,
28
+ sync: false, // Async writes for performance
29
+ mkdir: true,
30
+ });
31
+ }
32
+ catch {
33
+ return undefined;
34
+ }
35
+ }
36
+ /**
37
+ * Check if pino-pretty is available
38
+ */
39
+ async function hasPinoPretty() {
40
+ try {
41
+ await import('pino-pretty');
42
+ return true;
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
48
+ // Cache the result
49
+ let pinoPrettyAvailable = null;
50
+ /**
51
+ * Create multi-stream transport for dual output (stdout + file)
52
+ */
53
+ function createTransport() {
54
+ if (isDev) {
55
+ // Check if pino-pretty is available (sync check using require.resolve)
56
+ if (pinoPrettyAvailable === null) {
57
+ try {
58
+ require.resolve('pino-pretty');
59
+ pinoPrettyAvailable = true;
60
+ }
61
+ catch {
62
+ pinoPrettyAvailable = false;
63
+ }
64
+ }
65
+ if (pinoPrettyAvailable) {
66
+ // Development: pretty print to stdout only
67
+ return {
68
+ target: 'pino-pretty',
69
+ options: {
70
+ colorize: true,
71
+ translateTime: 'SYS:standard',
72
+ ignore: 'pid,hostname',
73
+ },
74
+ };
75
+ }
76
+ // Fall through to JSON output if pino-pretty not available
77
+ }
78
+ // Production: JSON to stdout (for journald)
79
+ // File output is handled separately via destination stream
80
+ return undefined;
81
+ }
82
+ /**
83
+ * Base logger instance
84
+ *
85
+ * In development: Uses pino-pretty with colorized output
86
+ * In production: JSON logs to stdout (captured by journald) + optional file
87
+ *
88
+ * Configure via environment variables:
89
+ * - LOG_LEVEL: trace, debug, info, warn, error, fatal (default: debug in dev, info in prod)
90
+ * - LOG_FILE: Path to log file (default: /var/log/zn-vault-agent/agent.log in prod)
91
+ */
92
+ export const logger = pino({
93
+ level: process.env.LOG_LEVEL ?? (isDev ? 'debug' : 'info'),
94
+ transport: createTransport(),
95
+ base: {
96
+ service: 'zn-vault-agent',
97
+ pid: process.pid,
98
+ },
99
+ // Redact sensitive fields
100
+ redact: {
101
+ paths: [
102
+ 'password',
103
+ 'apiKey',
104
+ 'token',
105
+ 'secret',
106
+ 'auth.password',
107
+ 'auth.apiKey',
108
+ 'config.auth.password',
109
+ 'config.auth.apiKey',
110
+ 'headers.authorization',
111
+ 'headers["x-api-key"]',
112
+ ],
113
+ censor: '[REDACTED]',
114
+ },
115
+ // Add timestamp in ISO format
116
+ timestamp: pino.stdTimeFunctions.isoTime,
117
+ },
118
+ // In production without transport, we can use multistream for file output
119
+ !isDev && logFile ? createFileStream() : undefined);
120
+ /**
121
+ * Create a child logger with additional context
122
+ *
123
+ * @example
124
+ * const log = createLogger({ module: 'deployer' });
125
+ * log.info({ certId: 'xxx' }, 'Certificate deployed');
126
+ */
127
+ export function createLogger(context) {
128
+ return logger.child(context);
129
+ }
130
+ // Pre-configured module loggers
131
+ export const wsLogger = createLogger({ module: 'websocket' });
132
+ export const apiLogger = createLogger({ module: 'api' });
133
+ export const deployLogger = createLogger({ module: 'deployer' });
134
+ export const configLogger = createLogger({ module: 'config' });
135
+ export const metricsLogger = createLogger({ module: 'metrics' });
136
+ export const healthLogger = createLogger({ module: 'health' });
137
+ /**
138
+ * Flush logs and close file streams
139
+ * Call this before process exit for clean shutdown
140
+ */
141
+ export async function flushLogs() {
142
+ return new Promise((resolve) => {
143
+ logger.flush();
144
+ // Give some time for async writes to complete
145
+ setTimeout(resolve, 100);
146
+ });
147
+ }
148
+ /**
149
+ * Handle log rotation signal (USR1)
150
+ * Reopens the log file destination
151
+ */
152
+ export function setupLogRotation() {
153
+ if (process.platform !== 'win32') {
154
+ process.on('SIGUSR1', () => {
155
+ logger.info('Received SIGUSR1, reopening log files');
156
+ // Pino destination handles file reopening on next write
157
+ logger.flush();
158
+ });
159
+ }
160
+ }
161
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Register a counter metric
3
+ */
4
+ export declare function registerCounter(name: string, help: string): void;
5
+ /**
6
+ * Increment a counter
7
+ */
8
+ export declare function incCounter(name: string, labels?: Record<string, string>, value?: number): void;
9
+ /**
10
+ * Register a gauge metric
11
+ */
12
+ export declare function registerGauge(name: string, help: string): void;
13
+ /**
14
+ * Set a gauge value
15
+ */
16
+ export declare function setGauge(name: string, value: number, labels?: Record<string, string>): void;
17
+ /**
18
+ * Register a histogram metric
19
+ */
20
+ export declare function registerHistogram(name: string, help: string, buckets?: number[]): void;
21
+ /**
22
+ * Observe a histogram value
23
+ */
24
+ export declare function observeHistogram(name: string, value: number, labels?: Record<string, string>): void;
25
+ /**
26
+ * Export all metrics in Prometheus text format
27
+ */
28
+ export declare function exportMetrics(): string;
29
+ /**
30
+ * Reset all metrics (useful for testing)
31
+ */
32
+ export declare function resetMetrics(): void;
33
+ export declare function initializeMetrics(): void;
34
+ export declare const metrics: {
35
+ syncSuccess: (certName: string) => void;
36
+ syncFailure: (certName: string, reason: string) => void;
37
+ syncDuration: (certName: string, durationMs: number) => void;
38
+ wsConnected: () => void;
39
+ wsDisconnected: () => void;
40
+ wsReconnect: () => void;
41
+ apiRequest: (method: string, status: number, durationMs: number) => void;
42
+ setCertsTracked: (count: number) => void;
43
+ setCertExpiry: (certId: string, certName: string, days: number) => void;
44
+ secretDeployed: (secretName: string, success: boolean, durationMs: number) => void;
45
+ setSecretsTracked: (count: number) => void;
46
+ updateCheck: (status: "success" | "error") => void;
47
+ updateInstall: (status: "success" | "error" | "permission_denied") => void;
48
+ setVersionInfo: (version: string, channel: string) => void;
49
+ };
50
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/lib/metrics.ts"],"names":[],"mappings":"AA6CA;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMhE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,KAAK,SAAI,GAAG,IAAI,CAe7F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,IAAI,CAgB/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,EAAoB,GAClC,IAAI,CAQN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,IAAI,CA6BN;AAWD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA+DtC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAUnC;AAGD,wBAAgB,iBAAiB,IAAI,IAAI,CAyBxC;AAGD,eAAO,MAAM,OAAO;4BAEM,MAAM;4BAIN,MAAM,UAAU,MAAM;6BAIrB,MAAM,cAAc,MAAM;;;;yBAU9B,MAAM,UAAU,MAAM,cAAc,MAAM;6BAMtC,MAAM;4BACP,MAAM,YAAY,MAAM,QAAQ,MAAM;iCAKjC,MAAM,WAAW,OAAO,cAAc,MAAM;+BAU9C,MAAM;0BAGX,SAAS,GAAG,OAAO;4BAGjB,SAAS,GAAG,OAAO,GAAG,mBAAmB;8BAGvC,MAAM,WAAW,MAAM;CAGlD,CAAC"}