@zincapp/zn-vault-agent 1.6.13 → 1.6.14

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.
@@ -0,0 +1,399 @@
1
+ // Path: src/plugins/loader.ts
2
+ // Plugin discovery, loading, and lifecycle management
3
+ import { EventEmitter } from 'node:events';
4
+ import path from 'node:path';
5
+ import fs from 'node:fs';
6
+ import { createLogger } from '../lib/logger.js';
7
+ import { createPluginContext } from './context.js';
8
+ const log = createLogger({ module: 'plugin-loader' });
9
+ /**
10
+ * Plugin event handler method names mapping
11
+ */
12
+ const EVENT_HANDLERS = {
13
+ certificateDeployed: 'onCertificateDeployed',
14
+ secretDeployed: 'onSecretDeployed',
15
+ keyRotated: 'onKeyRotated',
16
+ childProcess: 'onChildProcessEvent',
17
+ };
18
+ /**
19
+ * Manages plugin discovery, loading, and lifecycle
20
+ */
21
+ export class PluginLoader extends EventEmitter {
22
+ plugins = new Map();
23
+ agentInternals;
24
+ options;
25
+ isStarted = false;
26
+ constructor(agentInternals, options = {}) {
27
+ super();
28
+ this.agentInternals = agentInternals;
29
+ this.options = options;
30
+ }
31
+ /**
32
+ * Load all plugins from config and auto-discovered locations
33
+ */
34
+ async loadPlugins(config) {
35
+ log.info('Loading plugins');
36
+ // Load plugins from config
37
+ const pluginConfigs = config.plugins || [];
38
+ for (const pluginConfig of pluginConfigs) {
39
+ // Skip disabled plugins
40
+ if (pluginConfig.enabled === false) {
41
+ log.debug({ package: pluginConfig.package, path: pluginConfig.path }, 'Plugin disabled, skipping');
42
+ continue;
43
+ }
44
+ try {
45
+ await this.loadPlugin(pluginConfig);
46
+ }
47
+ catch (err) {
48
+ log.error({ err, config: pluginConfig }, 'Failed to load plugin');
49
+ // Continue loading other plugins
50
+ }
51
+ }
52
+ // Discover local plugins if plugin directory exists
53
+ if (this.options.pluginDir) {
54
+ await this.loadLocalPlugins(this.options.pluginDir);
55
+ }
56
+ log.info({ count: this.plugins.size }, 'Plugins loaded');
57
+ }
58
+ /**
59
+ * Load a single plugin by config
60
+ */
61
+ async loadPlugin(config) {
62
+ const { package: packageName, path: localPath, config: pluginOptions } = config;
63
+ if (!packageName && !localPath) {
64
+ throw new Error('Plugin config must specify package or path');
65
+ }
66
+ const identifier = packageName || localPath;
67
+ log.debug({ package: packageName, path: localPath }, 'Loading plugin');
68
+ try {
69
+ let module;
70
+ if (localPath) {
71
+ // Resolve local path relative to config dir or as absolute
72
+ const resolvedPath = path.isAbsolute(localPath)
73
+ ? localPath
74
+ : path.resolve(process.cwd(), localPath);
75
+ if (!fs.existsSync(resolvedPath)) {
76
+ throw new Error(`Plugin file not found: ${resolvedPath}`);
77
+ }
78
+ module = await import(resolvedPath);
79
+ }
80
+ else if (packageName) {
81
+ // Import npm package
82
+ module = await import(packageName);
83
+ }
84
+ else {
85
+ throw new Error('Plugin config must specify package or path');
86
+ }
87
+ // Support both direct export and factory function
88
+ let plugin;
89
+ if (typeof module.default === 'function') {
90
+ // Factory function - pass plugin options
91
+ plugin = module.default(pluginOptions || {});
92
+ }
93
+ else if (module.default && typeof module.default === 'object') {
94
+ // Direct export
95
+ plugin = module.default;
96
+ }
97
+ else {
98
+ throw new Error(`Invalid plugin export from ${identifier}`);
99
+ }
100
+ // Validate plugin interface
101
+ this.validatePlugin(plugin);
102
+ // Check for duplicate names
103
+ if (this.plugins.has(plugin.name)) {
104
+ log.warn({ name: plugin.name }, 'Plugin with same name already loaded, skipping');
105
+ return null;
106
+ }
107
+ // Store loaded plugin
108
+ this.plugins.set(plugin.name, {
109
+ plugin,
110
+ config: pluginOptions,
111
+ status: 'loaded',
112
+ });
113
+ log.info({ name: plugin.name, version: plugin.version }, 'Plugin loaded');
114
+ return plugin;
115
+ }
116
+ catch (err) {
117
+ const error = err instanceof Error ? err : new Error(String(err));
118
+ log.error({ err: error, identifier }, 'Failed to load plugin');
119
+ throw error;
120
+ }
121
+ }
122
+ /**
123
+ * Load plugins from local directory
124
+ */
125
+ async loadLocalPlugins(pluginDir) {
126
+ if (!fs.existsSync(pluginDir)) {
127
+ log.debug({ pluginDir }, 'Plugin directory does not exist');
128
+ return;
129
+ }
130
+ const entries = fs.readdirSync(pluginDir, { withFileTypes: true });
131
+ for (const entry of entries) {
132
+ if (!entry.isFile())
133
+ continue;
134
+ if (!entry.name.endsWith('.js') && !entry.name.endsWith('.mjs'))
135
+ continue;
136
+ const pluginPath = path.join(pluginDir, entry.name);
137
+ try {
138
+ await this.loadPlugin({ path: pluginPath });
139
+ }
140
+ catch (err) {
141
+ log.warn({ err, path: pluginPath }, 'Failed to load local plugin');
142
+ }
143
+ }
144
+ }
145
+ /**
146
+ * Validate plugin has required fields
147
+ */
148
+ validatePlugin(plugin) {
149
+ if (!plugin || typeof plugin !== 'object') {
150
+ throw new Error('Plugin must be an object');
151
+ }
152
+ const p = plugin;
153
+ if (typeof p.name !== 'string' || !p.name) {
154
+ throw new Error('Plugin must have a name property');
155
+ }
156
+ if (typeof p.version !== 'string' || !p.version) {
157
+ throw new Error('Plugin must have a version property');
158
+ }
159
+ // Validate optional lifecycle methods are functions
160
+ const methods = ['onInit', 'onStart', 'onStop', 'routes', 'onCertificateDeployed',
161
+ 'onSecretDeployed', 'onKeyRotated', 'onChildProcessEvent', 'healthCheck'];
162
+ for (const method of methods) {
163
+ if (p[method] !== undefined && typeof p[method] !== 'function') {
164
+ throw new Error(`Plugin ${p.name}: ${method} must be a function`);
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * Initialize all loaded plugins
170
+ */
171
+ async initializePlugins() {
172
+ log.debug('Initializing plugins');
173
+ for (const [name, loaded] of this.plugins) {
174
+ if (loaded.status !== 'loaded')
175
+ continue;
176
+ const ctx = createPluginContext(name, this.agentInternals, this);
177
+ if (loaded.plugin.onInit) {
178
+ try {
179
+ await loaded.plugin.onInit(ctx);
180
+ loaded.status = 'initialized';
181
+ log.debug({ name }, 'Plugin initialized');
182
+ }
183
+ catch (err) {
184
+ const error = err instanceof Error ? err : new Error(String(err));
185
+ log.error({ err: error, name }, 'Plugin initialization failed');
186
+ loaded.status = 'error';
187
+ loaded.error = error;
188
+ }
189
+ }
190
+ else {
191
+ // No init hook - mark as initialized
192
+ loaded.status = 'initialized';
193
+ }
194
+ }
195
+ }
196
+ /**
197
+ * Start all initialized plugins
198
+ */
199
+ async startPlugins() {
200
+ if (this.isStarted) {
201
+ log.warn('Plugins already started');
202
+ return;
203
+ }
204
+ log.debug('Starting plugins');
205
+ for (const [name, loaded] of this.plugins) {
206
+ if (loaded.status !== 'initialized')
207
+ continue;
208
+ const ctx = createPluginContext(name, this.agentInternals, this);
209
+ if (loaded.plugin.onStart) {
210
+ try {
211
+ await loaded.plugin.onStart(ctx);
212
+ loaded.status = 'running';
213
+ log.debug({ name }, 'Plugin started');
214
+ }
215
+ catch (err) {
216
+ const error = err instanceof Error ? err : new Error(String(err));
217
+ log.error({ err: error, name }, 'Plugin start failed');
218
+ loaded.status = 'error';
219
+ loaded.error = error;
220
+ }
221
+ }
222
+ else {
223
+ // No start hook - mark as running
224
+ loaded.status = 'running';
225
+ }
226
+ }
227
+ this.isStarted = true;
228
+ }
229
+ /**
230
+ * Stop all running plugins
231
+ */
232
+ async stopPlugins() {
233
+ if (!this.isStarted) {
234
+ return;
235
+ }
236
+ log.debug('Stopping plugins');
237
+ // Stop in reverse order
238
+ const plugins = Array.from(this.plugins.entries()).reverse();
239
+ for (const [name, loaded] of plugins) {
240
+ if (loaded.status !== 'running')
241
+ continue;
242
+ const ctx = createPluginContext(name, this.agentInternals, this);
243
+ if (loaded.plugin.onStop) {
244
+ try {
245
+ await loaded.plugin.onStop(ctx);
246
+ loaded.status = 'stopped';
247
+ log.debug({ name }, 'Plugin stopped');
248
+ }
249
+ catch (err) {
250
+ log.warn({ err, name }, 'Plugin stop error');
251
+ loaded.status = 'stopped';
252
+ }
253
+ }
254
+ else {
255
+ loaded.status = 'stopped';
256
+ }
257
+ }
258
+ this.isStarted = false;
259
+ }
260
+ /**
261
+ * Register plugin routes on Fastify server
262
+ */
263
+ async registerRoutes(fastify) {
264
+ for (const [name, loaded] of this.plugins) {
265
+ if (!loaded.plugin.routes)
266
+ continue;
267
+ const ctx = createPluginContext(name, this.agentInternals, this);
268
+ try {
269
+ // Register under /plugins/<name>/ prefix
270
+ await fastify.register(async (instance) => {
271
+ await loaded.plugin.routes(instance, ctx);
272
+ }, { prefix: `/plugins/${name}` });
273
+ log.debug({ name, prefix: `/plugins/${name}` }, 'Plugin routes registered');
274
+ }
275
+ catch (err) {
276
+ log.error({ err, name }, 'Failed to register plugin routes');
277
+ }
278
+ }
279
+ }
280
+ /**
281
+ * Dispatch event to all plugins
282
+ */
283
+ async dispatchEvent(eventType, event) {
284
+ const handlerName = EVENT_HANDLERS[eventType];
285
+ log.debug({ eventType, plugins: this.plugins.size }, 'Dispatching event to plugins');
286
+ for (const [name, loaded] of this.plugins) {
287
+ if (loaded.status !== 'running')
288
+ continue;
289
+ const handler = loaded.plugin[handlerName];
290
+ if (!handler)
291
+ continue;
292
+ const ctx = createPluginContext(name, this.agentInternals, this);
293
+ try {
294
+ await handler.call(loaded.plugin, event, ctx);
295
+ }
296
+ catch (err) {
297
+ log.error({ err, name, eventType }, 'Plugin event handler error');
298
+ // Don't fail other plugins
299
+ }
300
+ }
301
+ }
302
+ /**
303
+ * Collect health status from all plugins
304
+ */
305
+ async collectHealthStatus() {
306
+ const statuses = [];
307
+ for (const [name, loaded] of this.plugins) {
308
+ // Include status for errored plugins
309
+ if (loaded.status === 'error') {
310
+ statuses.push({
311
+ name,
312
+ status: 'unhealthy',
313
+ message: loaded.error?.message || 'Plugin failed to load',
314
+ });
315
+ continue;
316
+ }
317
+ if (loaded.status !== 'running' || !loaded.plugin.healthCheck)
318
+ continue;
319
+ const ctx = createPluginContext(name, this.agentInternals, this);
320
+ try {
321
+ const status = await loaded.plugin.healthCheck(ctx);
322
+ statuses.push(status);
323
+ }
324
+ catch (err) {
325
+ const error = err instanceof Error ? err : new Error(String(err));
326
+ statuses.push({
327
+ name,
328
+ status: 'unhealthy',
329
+ message: `Health check failed: ${error.message}`,
330
+ });
331
+ }
332
+ }
333
+ return statuses;
334
+ }
335
+ /**
336
+ * Get loaded plugins
337
+ */
338
+ getPlugins() {
339
+ return Array.from(this.plugins.values()).map(l => l.plugin);
340
+ }
341
+ /**
342
+ * Get plugin by name
343
+ */
344
+ getPlugin(name) {
345
+ return this.plugins.get(name)?.plugin;
346
+ }
347
+ /**
348
+ * Get plugin status
349
+ */
350
+ getPluginStatus(name) {
351
+ return this.plugins.get(name)?.status;
352
+ }
353
+ /**
354
+ * Get all plugin statuses
355
+ */
356
+ getAllPluginStatuses() {
357
+ return Array.from(this.plugins.entries()).map(([name, loaded]) => ({
358
+ name,
359
+ status: loaded.status,
360
+ error: loaded.error?.message,
361
+ }));
362
+ }
363
+ /**
364
+ * Check if any plugins are loaded
365
+ */
366
+ hasPlugins() {
367
+ return this.plugins.size > 0;
368
+ }
369
+ /**
370
+ * Update agent internals (called when config changes)
371
+ */
372
+ updateInternals(internals) {
373
+ this.agentInternals = { ...this.agentInternals, ...internals };
374
+ }
375
+ }
376
+ /**
377
+ * Singleton plugin loader instance
378
+ */
379
+ let pluginLoaderInstance = null;
380
+ /**
381
+ * Get or create the plugin loader instance
382
+ */
383
+ export function getPluginLoader() {
384
+ return pluginLoaderInstance;
385
+ }
386
+ /**
387
+ * Create and set the plugin loader instance
388
+ */
389
+ export function createPluginLoader(agentInternals, options) {
390
+ pluginLoaderInstance = new PluginLoader(agentInternals, options);
391
+ return pluginLoaderInstance;
392
+ }
393
+ /**
394
+ * Clear the plugin loader instance (for testing)
395
+ */
396
+ export function clearPluginLoader() {
397
+ pluginLoaderInstance = null;
398
+ }
399
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { PluginStorage } from './types.js';
2
+ /**
3
+ * Create a PluginStorage instance for a specific plugin
4
+ */
5
+ export declare function getPluginStorage(pluginName: string): PluginStorage;
6
+ /**
7
+ * Delete all storage for a plugin (for uninstall/cleanup)
8
+ */
9
+ export declare function deletePluginStorage(pluginName: string): void;
10
+ /**
11
+ * List all plugins with storage
12
+ */
13
+ export declare function listPluginsWithStorage(): string[];
14
+ /**
15
+ * Clear storage cache (for testing)
16
+ */
17
+ export declare function clearStorageCache(): void;
18
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/plugins/storage.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqGhD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAiClE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAY5D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAejD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,166 @@
1
+ // Path: src/plugins/storage.ts
2
+ // Persistent key-value storage for plugins
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { createLogger } from '../lib/logger.js';
6
+ const log = createLogger({ module: 'plugin-storage' });
7
+ /**
8
+ * Get storage directory for plugins
9
+ * Uses /etc/zn-vault-agent/plugins/ for system config or ~/.zn-vault-agent/plugins/ for user
10
+ */
11
+ function getStorageDir() {
12
+ const customDir = process.env.ZNVAULT_AGENT_CONFIG_DIR;
13
+ if (customDir) {
14
+ return path.join(customDir, 'plugin-data');
15
+ }
16
+ // System config dir
17
+ const systemDir = '/etc/zn-vault-agent/plugin-data';
18
+ if (process.getuid?.() === 0 || fs.existsSync('/etc/zn-vault-agent')) {
19
+ return systemDir;
20
+ }
21
+ // User config dir
22
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp';
23
+ return path.join(homeDir, '.zn-vault-agent', 'plugin-data');
24
+ }
25
+ /**
26
+ * Storage file cache to avoid repeated disk reads
27
+ */
28
+ const storageCache = new Map();
29
+ /**
30
+ * Get storage file path for a plugin
31
+ */
32
+ function getStoragePath(pluginName) {
33
+ const storageDir = getStorageDir();
34
+ // Sanitize plugin name for filename
35
+ const safeName = pluginName.replace(/[^a-zA-Z0-9_-]/g, '_');
36
+ return path.join(storageDir, `${safeName}.json`);
37
+ }
38
+ /**
39
+ * Ensure storage directory exists
40
+ */
41
+ function ensureStorageDir() {
42
+ const storageDir = getStorageDir();
43
+ if (!fs.existsSync(storageDir)) {
44
+ fs.mkdirSync(storageDir, { recursive: true, mode: 0o700 });
45
+ log.debug({ storageDir }, 'Created plugin storage directory');
46
+ }
47
+ }
48
+ /**
49
+ * Load storage data from disk
50
+ */
51
+ function loadStorageData(pluginName) {
52
+ // Check cache first
53
+ if (storageCache.has(pluginName)) {
54
+ return storageCache.get(pluginName);
55
+ }
56
+ const storagePath = getStoragePath(pluginName);
57
+ if (!fs.existsSync(storagePath)) {
58
+ const empty = {};
59
+ storageCache.set(pluginName, empty);
60
+ return empty;
61
+ }
62
+ try {
63
+ const content = fs.readFileSync(storagePath, 'utf-8');
64
+ const data = JSON.parse(content);
65
+ storageCache.set(pluginName, data);
66
+ return data;
67
+ }
68
+ catch (err) {
69
+ log.warn({ err, pluginName, path: storagePath }, 'Failed to load plugin storage');
70
+ const empty = {};
71
+ storageCache.set(pluginName, empty);
72
+ return empty;
73
+ }
74
+ }
75
+ /**
76
+ * Save storage data to disk
77
+ */
78
+ function saveStorageData(pluginName, data) {
79
+ ensureStorageDir();
80
+ const storagePath = getStoragePath(pluginName);
81
+ try {
82
+ // Atomic write with temp file
83
+ const tempPath = `${storagePath}.tmp`;
84
+ fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), { mode: 0o600 });
85
+ fs.renameSync(tempPath, storagePath);
86
+ storageCache.set(pluginName, data);
87
+ log.debug({ pluginName, path: storagePath }, 'Plugin storage saved');
88
+ }
89
+ catch (err) {
90
+ log.error({ err, pluginName, path: storagePath }, 'Failed to save plugin storage');
91
+ throw err;
92
+ }
93
+ }
94
+ /**
95
+ * Create a PluginStorage instance for a specific plugin
96
+ */
97
+ export function getPluginStorage(pluginName) {
98
+ return {
99
+ get(key) {
100
+ const data = loadStorageData(pluginName);
101
+ return data[key];
102
+ },
103
+ set(key, value) {
104
+ const data = loadStorageData(pluginName);
105
+ data[key] = value;
106
+ saveStorageData(pluginName, data);
107
+ },
108
+ delete(key) {
109
+ const data = loadStorageData(pluginName);
110
+ delete data[key];
111
+ saveStorageData(pluginName, data);
112
+ },
113
+ clear() {
114
+ saveStorageData(pluginName, {});
115
+ },
116
+ has(key) {
117
+ const data = loadStorageData(pluginName);
118
+ return key in data;
119
+ },
120
+ keys() {
121
+ const data = loadStorageData(pluginName);
122
+ return Object.keys(data);
123
+ },
124
+ };
125
+ }
126
+ /**
127
+ * Delete all storage for a plugin (for uninstall/cleanup)
128
+ */
129
+ export function deletePluginStorage(pluginName) {
130
+ const storagePath = getStoragePath(pluginName);
131
+ storageCache.delete(pluginName);
132
+ if (fs.existsSync(storagePath)) {
133
+ try {
134
+ fs.unlinkSync(storagePath);
135
+ log.debug({ pluginName, path: storagePath }, 'Plugin storage deleted');
136
+ }
137
+ catch (err) {
138
+ log.warn({ err, pluginName, path: storagePath }, 'Failed to delete plugin storage');
139
+ }
140
+ }
141
+ }
142
+ /**
143
+ * List all plugins with storage
144
+ */
145
+ export function listPluginsWithStorage() {
146
+ const storageDir = getStorageDir();
147
+ if (!fs.existsSync(storageDir)) {
148
+ return [];
149
+ }
150
+ try {
151
+ const files = fs.readdirSync(storageDir);
152
+ return files
153
+ .filter(f => f.endsWith('.json'))
154
+ .map(f => f.replace(/\.json$/, ''));
155
+ }
156
+ catch {
157
+ return [];
158
+ }
159
+ }
160
+ /**
161
+ * Clear storage cache (for testing)
162
+ */
163
+ export function clearStorageCache() {
164
+ storageCache.clear();
165
+ }
166
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/plugins/storage.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2CAA2C;AAE3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAEvD;;;GAGG;AACH,SAAS,aAAa;IACpB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IACvD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,oBAAoB;IACpB,MAAM,SAAS,GAAG,iCAAiC,CAAC;IACpD,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACrE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,kBAAkB;IAClB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC;IACtE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAmC,CAAC;AAEhE;;GAEG;AACH,SAAS,cAAc,CAAC,UAAkB;IACxC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,oCAAoC;IACpC,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,kCAAkC,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,UAAkB;IACzC,oBAAoB;IACpB,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC;IACvC,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,GAA4B,EAAE,CAAC;QAC1C,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC5D,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAClF,MAAM,KAAK,GAA4B,EAAE,CAAC;QAC1C,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,UAAkB,EAAE,IAA6B;IACxE,gBAAgB,EAAE,CAAC;IACnB,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,GAAG,WAAW,MAAM,CAAC;QACtC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,sBAAsB,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,+BAA+B,CAAC,CAAC;QACnF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO;QACL,GAAG,CAAI,GAAW;YAChB,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,GAAG,CAAkB,CAAC;QACpC,CAAC;QAED,GAAG,CAAI,GAAW,EAAE,KAAQ;YAC1B,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAgB,CAAC;YAC7B,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,CAAC,GAAW;YAChB,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,KAAK;YACH,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,GAAG,CAAC,GAAW;YACb,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,GAAG,IAAI,IAAI,CAAC;QACrB,CAAC;QAED,IAAI;YACF,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC/C,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAEhC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC3B,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,iCAAiC,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}