@dotsetlabs/tollgate 0.1.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 (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +885 -0
  3. package/dist/analyzers/filesystem.d.ts +26 -0
  4. package/dist/analyzers/filesystem.d.ts.map +1 -0
  5. package/dist/analyzers/filesystem.js +284 -0
  6. package/dist/analyzers/filesystem.js.map +1 -0
  7. package/dist/analyzers/http.d.ts +90 -0
  8. package/dist/analyzers/http.d.ts.map +1 -0
  9. package/dist/analyzers/http.js +433 -0
  10. package/dist/analyzers/http.js.map +1 -0
  11. package/dist/analyzers/index.d.ts +101 -0
  12. package/dist/analyzers/index.d.ts.map +1 -0
  13. package/dist/analyzers/index.js +342 -0
  14. package/dist/analyzers/index.js.map +1 -0
  15. package/dist/analyzers/loader.d.ts +114 -0
  16. package/dist/analyzers/loader.d.ts.map +1 -0
  17. package/dist/analyzers/loader.js +184 -0
  18. package/dist/analyzers/loader.js.map +1 -0
  19. package/dist/analyzers/prompt-injection.d.ts +95 -0
  20. package/dist/analyzers/prompt-injection.d.ts.map +1 -0
  21. package/dist/analyzers/prompt-injection.js +725 -0
  22. package/dist/analyzers/prompt-injection.js.map +1 -0
  23. package/dist/analyzers/sdk.d.ts +230 -0
  24. package/dist/analyzers/sdk.d.ts.map +1 -0
  25. package/dist/analyzers/sdk.js +283 -0
  26. package/dist/analyzers/sdk.js.map +1 -0
  27. package/dist/analyzers/shell.d.ts +20 -0
  28. package/dist/analyzers/shell.d.ts.map +1 -0
  29. package/dist/analyzers/shell.js +297 -0
  30. package/dist/analyzers/shell.js.map +1 -0
  31. package/dist/analyzers/sql.d.ts +37 -0
  32. package/dist/analyzers/sql.d.ts.map +1 -0
  33. package/dist/analyzers/sql.js +455 -0
  34. package/dist/analyzers/sql.js.map +1 -0
  35. package/dist/analyzers/types.d.ts +117 -0
  36. package/dist/analyzers/types.d.ts.map +1 -0
  37. package/dist/analyzers/types.js +46 -0
  38. package/dist/analyzers/types.js.map +1 -0
  39. package/dist/approval/interactive.d.ts +72 -0
  40. package/dist/approval/interactive.d.ts.map +1 -0
  41. package/dist/approval/interactive.js +550 -0
  42. package/dist/approval/interactive.js.map +1 -0
  43. package/dist/approval/terminal.d.ts +59 -0
  44. package/dist/approval/terminal.d.ts.map +1 -0
  45. package/dist/approval/terminal.js +238 -0
  46. package/dist/approval/terminal.js.map +1 -0
  47. package/dist/approval/types.d.ts +66 -0
  48. package/dist/approval/types.d.ts.map +1 -0
  49. package/dist/approval/types.js +2 -0
  50. package/dist/approval/types.js.map +1 -0
  51. package/dist/audit/exporter.d.ts +138 -0
  52. package/dist/audit/exporter.d.ts.map +1 -0
  53. package/dist/audit/exporter.js +366 -0
  54. package/dist/audit/exporter.js.map +1 -0
  55. package/dist/audit/logger.d.ts +156 -0
  56. package/dist/audit/logger.d.ts.map +1 -0
  57. package/dist/audit/logger.js +406 -0
  58. package/dist/audit/logger.js.map +1 -0
  59. package/dist/audit/redaction.d.ts +110 -0
  60. package/dist/audit/redaction.d.ts.map +1 -0
  61. package/dist/audit/redaction.js +307 -0
  62. package/dist/audit/redaction.js.map +1 -0
  63. package/dist/audit/schema.d.ts +76 -0
  64. package/dist/audit/schema.d.ts.map +1 -0
  65. package/dist/audit/schema.js +122 -0
  66. package/dist/audit/schema.js.map +1 -0
  67. package/dist/cli/commands/doctor.d.ts +34 -0
  68. package/dist/cli/commands/doctor.d.ts.map +1 -0
  69. package/dist/cli/commands/doctor.js +431 -0
  70. package/dist/cli/commands/doctor.js.map +1 -0
  71. package/dist/cli/commands/export.d.ts +18 -0
  72. package/dist/cli/commands/export.d.ts.map +1 -0
  73. package/dist/cli/commands/export.js +63 -0
  74. package/dist/cli/commands/export.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +12 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +102 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/logs.d.ts +11 -0
  80. package/dist/cli/commands/logs.d.ts.map +1 -0
  81. package/dist/cli/commands/logs.js +60 -0
  82. package/dist/cli/commands/logs.js.map +1 -0
  83. package/dist/cli/commands/scan.d.ts +29 -0
  84. package/dist/cli/commands/scan.d.ts.map +1 -0
  85. package/dist/cli/commands/scan.js +251 -0
  86. package/dist/cli/commands/scan.js.map +1 -0
  87. package/dist/cli/commands/serve.d.ts +26 -0
  88. package/dist/cli/commands/serve.d.ts.map +1 -0
  89. package/dist/cli/commands/serve.js +424 -0
  90. package/dist/cli/commands/serve.js.map +1 -0
  91. package/dist/cli/commands/start.d.ts +20 -0
  92. package/dist/cli/commands/start.d.ts.map +1 -0
  93. package/dist/cli/commands/start.js +82 -0
  94. package/dist/cli/commands/start.js.map +1 -0
  95. package/dist/cli/commands/stats.d.ts +10 -0
  96. package/dist/cli/commands/stats.d.ts.map +1 -0
  97. package/dist/cli/commands/stats.js +42 -0
  98. package/dist/cli/commands/stats.js.map +1 -0
  99. package/dist/cli/commands/templates.d.ts +26 -0
  100. package/dist/cli/commands/templates.d.ts.map +1 -0
  101. package/dist/cli/commands/templates.js +221 -0
  102. package/dist/cli/commands/templates.js.map +1 -0
  103. package/dist/cli/commands/validate.d.ts +12 -0
  104. package/dist/cli/commands/validate.d.ts.map +1 -0
  105. package/dist/cli/commands/validate.js +107 -0
  106. package/dist/cli/commands/validate.js.map +1 -0
  107. package/dist/cli/commands/wrap.d.ts +19 -0
  108. package/dist/cli/commands/wrap.d.ts.map +1 -0
  109. package/dist/cli/commands/wrap.js +59 -0
  110. package/dist/cli/commands/wrap.js.map +1 -0
  111. package/dist/cli/index.d.ts +17 -0
  112. package/dist/cli/index.d.ts.map +1 -0
  113. package/dist/cli/index.js +202 -0
  114. package/dist/cli/index.js.map +1 -0
  115. package/dist/cli/ui.d.ts +139 -0
  116. package/dist/cli/ui.d.ts.map +1 -0
  117. package/dist/cli/ui.js +271 -0
  118. package/dist/cli/ui.js.map +1 -0
  119. package/dist/constants.d.ts +33 -0
  120. package/dist/constants.d.ts.map +1 -0
  121. package/dist/constants.js +54 -0
  122. package/dist/constants.js.map +1 -0
  123. package/dist/errors.d.ts +28 -0
  124. package/dist/errors.d.ts.map +1 -0
  125. package/dist/errors.js +37 -0
  126. package/dist/errors.js.map +1 -0
  127. package/dist/index.d.ts +49 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +82 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/orchestrator/index.d.ts +11 -0
  132. package/dist/orchestrator/index.d.ts.map +1 -0
  133. package/dist/orchestrator/index.js +10 -0
  134. package/dist/orchestrator/index.js.map +1 -0
  135. package/dist/orchestrator/manager.d.ts +127 -0
  136. package/dist/orchestrator/manager.d.ts.map +1 -0
  137. package/dist/orchestrator/manager.js +498 -0
  138. package/dist/orchestrator/manager.js.map +1 -0
  139. package/dist/orchestrator/types.d.ts +141 -0
  140. package/dist/orchestrator/types.d.ts.map +1 -0
  141. package/dist/orchestrator/types.js +9 -0
  142. package/dist/orchestrator/types.js.map +1 -0
  143. package/dist/policy/engine.d.ts +55 -0
  144. package/dist/policy/engine.d.ts.map +1 -0
  145. package/dist/policy/engine.js +288 -0
  146. package/dist/policy/engine.js.map +1 -0
  147. package/dist/policy/natural-language.d.ts +141 -0
  148. package/dist/policy/natural-language.d.ts.map +1 -0
  149. package/dist/policy/natural-language.js +552 -0
  150. package/dist/policy/natural-language.js.map +1 -0
  151. package/dist/policy/parser.d.ts +141 -0
  152. package/dist/policy/parser.d.ts.map +1 -0
  153. package/dist/policy/parser.js +314 -0
  154. package/dist/policy/parser.js.map +1 -0
  155. package/dist/policy/types.d.ts +428 -0
  156. package/dist/policy/types.d.ts.map +1 -0
  157. package/dist/policy/types.js +32 -0
  158. package/dist/policy/types.js.map +1 -0
  159. package/dist/policy/validator.d.ts +72 -0
  160. package/dist/policy/validator.d.ts.map +1 -0
  161. package/dist/policy/validator.js +453 -0
  162. package/dist/policy/validator.js.map +1 -0
  163. package/dist/proxy/bridge.d.ts +84 -0
  164. package/dist/proxy/bridge.d.ts.map +1 -0
  165. package/dist/proxy/bridge.js +217 -0
  166. package/dist/proxy/bridge.js.map +1 -0
  167. package/dist/proxy/client.d.ts +130 -0
  168. package/dist/proxy/client.d.ts.map +1 -0
  169. package/dist/proxy/client.js +290 -0
  170. package/dist/proxy/client.js.map +1 -0
  171. package/dist/proxy/server.d.ts +111 -0
  172. package/dist/proxy/server.d.ts.map +1 -0
  173. package/dist/proxy/server.js +444 -0
  174. package/dist/proxy/server.js.map +1 -0
  175. package/dist/scanner.d.ts +91 -0
  176. package/dist/scanner.d.ts.map +1 -0
  177. package/dist/scanner.js +373 -0
  178. package/dist/scanner.js.map +1 -0
  179. package/dist/session/index.d.ts +32 -0
  180. package/dist/session/index.d.ts.map +1 -0
  181. package/dist/session/index.js +31 -0
  182. package/dist/session/index.js.map +1 -0
  183. package/dist/session/manager.d.ts +166 -0
  184. package/dist/session/manager.d.ts.map +1 -0
  185. package/dist/session/manager.js +454 -0
  186. package/dist/session/manager.js.map +1 -0
  187. package/dist/session/sqlite-store.d.ts +54 -0
  188. package/dist/session/sqlite-store.d.ts.map +1 -0
  189. package/dist/session/sqlite-store.js +209 -0
  190. package/dist/session/sqlite-store.js.map +1 -0
  191. package/dist/session/types.d.ts +179 -0
  192. package/dist/session/types.d.ts.map +1 -0
  193. package/dist/session/types.js +38 -0
  194. package/dist/session/types.js.map +1 -0
  195. package/dist/templates.d.ts +64 -0
  196. package/dist/templates.d.ts.map +1 -0
  197. package/dist/templates.js +451 -0
  198. package/dist/templates.js.map +1 -0
  199. package/dist/utils/config.d.ts +57 -0
  200. package/dist/utils/config.d.ts.map +1 -0
  201. package/dist/utils/config.js +104 -0
  202. package/dist/utils/config.js.map +1 -0
  203. package/dist/utils/errors.d.ts +18 -0
  204. package/dist/utils/errors.d.ts.map +1 -0
  205. package/dist/utils/errors.js +35 -0
  206. package/dist/utils/errors.js.map +1 -0
  207. package/dist/utils/logger.d.ts +144 -0
  208. package/dist/utils/logger.d.ts.map +1 -0
  209. package/dist/utils/logger.js +300 -0
  210. package/dist/utils/logger.js.map +1 -0
  211. package/dist/wizard.d.ts +68 -0
  212. package/dist/wizard.d.ts.map +1 -0
  213. package/dist/wizard.js +395 -0
  214. package/dist/wizard.js.map +1 -0
  215. package/package.json +99 -0
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Tollgate CLI
4
+ *
5
+ * Local-first MCP security proxy with policy-based access control.
6
+ *
7
+ * Usage:
8
+ * tollgate start -s <server> - Start proxy for a configured server
9
+ * tollgate wrap <command> - Wrap an MCP server with protection
10
+ * tollgate logs - View recent audit logs
11
+ * tollgate stats - Show audit statistics
12
+ * tollgate export - Export audit logs
13
+ * tollgate init - Create configuration file
14
+ * tollgate validate - Validate configuration
15
+ */
16
+ import { Command } from 'commander';
17
+ import { readFileSync } from 'node:fs';
18
+ import { join, dirname } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+ import { startProxy } from './commands/start.js';
21
+ import { wrapCommand } from './commands/wrap.js';
22
+ import { showLogs } from './commands/logs.js';
23
+ import { showStats } from './commands/stats.js';
24
+ import { exportLogs } from './commands/export.js';
25
+ import { initConfig } from './commands/init.js';
26
+ import { validateConfig } from './commands/validate.js';
27
+ import { listTemplates, showTemplate, applyTemplate, } from './commands/templates.js';
28
+ import { runDoctor } from './commands/doctor.js';
29
+ import { runScan } from './commands/scan.js';
30
+ import { serve } from './commands/serve.js';
31
+ const __dirname = dirname(fileURLToPath(import.meta.url));
32
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf8'));
33
+ const version = pkg.version;
34
+ const program = new Command();
35
+ program
36
+ .name('tollgate')
37
+ .description('Local-first MCP security proxy with policy-based access control')
38
+ .version(version);
39
+ // Start command
40
+ program
41
+ .command('start')
42
+ .description('Start Tollgate proxy for a configured server')
43
+ .requiredOption('-s, --server <name>', 'Server name from config')
44
+ .option('-c, --config <path>', 'Path to tollgate.yaml config file')
45
+ .option('--audit-path <path>', 'Custom path for audit database')
46
+ .option('--timeout <ms>', 'Approval timeout in milliseconds', '60000')
47
+ .option('--approval <method>', 'Approval method: terminal, interactive', 'terminal')
48
+ .option('--approval-port <port>', 'Port for interactive approval UI', '9847')
49
+ .option('--persist-sessions', 'Persist session grants to disk')
50
+ .option('--session-path <path>', 'Path for persistent session database')
51
+ .option('--dry-run', 'Evaluate policies without executing tools')
52
+ .option('--failure-mode <mode>', 'Behavior when upstream fails: fail-closed, fail-open, fail-readonly')
53
+ .action(async (options) => {
54
+ await startProxy(options);
55
+ });
56
+ // Serve command (multi-server orchestration)
57
+ program
58
+ .command('serve')
59
+ .description('Start Tollgate orchestrator to manage multiple MCP servers')
60
+ .option('-c, --config <path>', 'Path to tollgate.yaml config file')
61
+ .option('--audit-path <path>', 'Custom path for audit database')
62
+ .option('--timeout <ms>', 'Approval timeout in milliseconds', '60000')
63
+ .option('--approval <method>', 'Approval method: terminal, interactive', 'terminal')
64
+ .option('--approval-port <port>', 'Port for interactive approval UI', '9847')
65
+ .option('--persist-sessions', 'Persist session grants to disk')
66
+ .option('--session-path <path>', 'Path for persistent session database')
67
+ .option('--dry-run', 'Evaluate policies without executing tools')
68
+ .option('--failure-mode <mode>', 'Behavior when upstream fails: fail-closed, fail-open, fail-readonly')
69
+ .option('--all', 'Auto-start all configured servers')
70
+ .option('-s, --servers <names...>', 'Specific servers to auto-start')
71
+ .option('--no-interactive', 'Run without interactive CLI')
72
+ .action(async (options) => {
73
+ await serve(options);
74
+ });
75
+ // Wrap command
76
+ program
77
+ .command('wrap <command> [args...]')
78
+ .description('Wrap an MCP server command with Tollgate protection')
79
+ .option('-d, --default <action>', 'Default action: allow, deny, or prompt', 'prompt')
80
+ .option('--audit-path <path>', 'Custom path for audit database')
81
+ .option('--timeout <ms>', 'Approval timeout in milliseconds', '60000')
82
+ .option('--approval <method>', 'Approval method: terminal, interactive', 'terminal')
83
+ .option('--approval-port <port>', 'Port for interactive approval UI', '9847')
84
+ .option('--persist-sessions', 'Persist session grants to disk')
85
+ .option('--session-path <path>', 'Path for persistent session database')
86
+ .option('--dry-run', 'Evaluate policies without executing tools')
87
+ .option('--failure-mode <mode>', 'Behavior when upstream fails: fail-closed, fail-open, fail-readonly')
88
+ .action(async (command, args, options) => {
89
+ await wrapCommand(command, args, options);
90
+ });
91
+ // Logs command
92
+ program
93
+ .command('logs')
94
+ .description('View recent audit logs')
95
+ .option('-n, --limit <count>', 'Number of entries to show', '20')
96
+ .option('--audit-path <path>', 'Custom path for audit database')
97
+ .action((options) => {
98
+ showLogs(options);
99
+ });
100
+ // Stats command
101
+ program
102
+ .command('stats')
103
+ .description('Show audit statistics')
104
+ .option('--audit-path <path>', 'Custom path for audit database')
105
+ .action((options) => {
106
+ showStats(options);
107
+ });
108
+ // Export command
109
+ program
110
+ .command('export')
111
+ .description('Export audit logs for compliance reporting')
112
+ .option('-f, --format <format>', 'Export format: json, jsonl, csv, or cef', 'jsonl')
113
+ .option('-o, --output <path>', 'Output file path (default: stdout)')
114
+ .option('--since <date>', 'Only include records since this date (ISO format)')
115
+ .option('--until <date>', 'Only include records until this date (ISO format)')
116
+ .option('-s, --server <name>', 'Filter by server name')
117
+ .option('-n, --limit <count>', 'Maximum number of records to export')
118
+ .option('--risk <level>', 'Filter by risk level: safe, read, write, destructive, dangerous')
119
+ .option('--no-redact', 'Include original (non-redacted) data')
120
+ .option('--audit-path <path>', 'Custom path for audit database')
121
+ .action(async (options) => {
122
+ await exportLogs(options);
123
+ });
124
+ // Init command
125
+ program
126
+ .command('init')
127
+ .description('Create a tollgate.yaml configuration file')
128
+ .option('-o, --output <path>', 'Output path', './tollgate.yaml')
129
+ .option('-i, --interactive', 'Use interactive wizard to configure')
130
+ .option('-f, --force', 'Overwrite existing file')
131
+ .action(async (options) => {
132
+ await initConfig(options);
133
+ });
134
+ // Validate command
135
+ program
136
+ .command('validate [path]')
137
+ .description('Validate a tollgate.yaml configuration file')
138
+ .option('-s, --server <name>', 'Only validate a specific server')
139
+ .option('--json', 'Output results as JSON')
140
+ .option('-q, --quiet', 'Only output errors (no warnings or info)')
141
+ .action(async (configPath, options) => {
142
+ await validateConfig(configPath, options);
143
+ });
144
+ // Doctor command
145
+ program
146
+ .command('doctor')
147
+ .description('Run diagnostics to verify configuration and environment')
148
+ .option('-c, --config <path>', 'Path to tollgate.yaml config file')
149
+ .option('-s, --server <name>', 'Check specific server only')
150
+ .option('--json', 'Output results as JSON')
151
+ .action(async (options) => {
152
+ await runDoctor(options);
153
+ });
154
+ // Scan command
155
+ program
156
+ .command('scan <package-or-command> [args...]')
157
+ .description('Scan an MCP server to discover tools and assess security risks')
158
+ .option('-o, --output <path>', 'Output generated config to file')
159
+ .option('-g, --generate-config', 'Generate recommended configuration')
160
+ .option('-a, --append', 'Append to existing config file')
161
+ .option('-n, --server-name <name>', 'Server name for generated config')
162
+ .option('-t, --timeout <ms>', 'Connection timeout in milliseconds', '30000')
163
+ .option('-e, --env <key=value...>', 'Environment variables to pass to server')
164
+ .option('--json', 'Output results as JSON')
165
+ .action(async (packageOrCommand, args, options) => {
166
+ await runScan(packageOrCommand, args, {
167
+ ...options,
168
+ timeout: typeof options.timeout === 'string' ? parseInt(options.timeout, 10) : options.timeout,
169
+ });
170
+ });
171
+ // Templates command group
172
+ const templatesCmd = program
173
+ .command('templates')
174
+ .description('Browse and apply MCP server configuration templates');
175
+ templatesCmd
176
+ .command('list')
177
+ .description('List all available server templates')
178
+ .option('-c, --category <category>', 'Filter by category (database, filesystem, web, productivity, developer, ai, communication)')
179
+ .option('-s, --search <query>', 'Search templates by keyword')
180
+ .option('--json', 'Output as JSON')
181
+ .action((options) => {
182
+ listTemplates(options);
183
+ });
184
+ templatesCmd
185
+ .command('show <name>')
186
+ .description('Show detailed information about a template')
187
+ .option('--json', 'Output as JSON')
188
+ .action((name, options) => {
189
+ showTemplate(name, options);
190
+ });
191
+ templatesCmd
192
+ .command('apply <names...>')
193
+ .description('Apply one or more templates to create/update tollgate.yaml')
194
+ .option('-o, --output <path>', 'Output path for configuration file', './tollgate.yaml')
195
+ .option('-f, --force', 'Overwrite existing file')
196
+ .option('-a, --append', 'Append to existing file instead of overwriting')
197
+ .option('-p, --preset <preset>', 'Policy preset: strict, balanced, or permissive', 'balanced')
198
+ .action((names, options) => {
199
+ applyTemplate(names, options);
200
+ });
201
+ program.parse();
202
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * CLI User Interface Utilities
3
+ *
4
+ * Provides formatted terminal output for CLI commands. This module handles
5
+ * user-facing display (banners, tables, progress, etc.) separate from
6
+ * operational logging.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { ui } from './cli/ui.js';
11
+ *
12
+ * ui.banner('Tollgate Server');
13
+ * ui.success('Configuration validated');
14
+ * ui.error('Failed to start server', error.message);
15
+ * ui.table(['Name', 'Status'], data);
16
+ * ```
17
+ *
18
+ * @module cli/ui
19
+ */
20
+ export interface TableColumn {
21
+ header: string;
22
+ width?: number;
23
+ align?: 'left' | 'right' | 'center';
24
+ }
25
+ export interface UIConfig {
26
+ /** Enable colored output */
27
+ colors: boolean;
28
+ /** Output stream (default: process.stdout for user output) */
29
+ stdout: NodeJS.WriteStream;
30
+ /** Error stream (default: process.stderr for errors) */
31
+ stderr: NodeJS.WriteStream;
32
+ }
33
+ /**
34
+ * CLI UI utility for formatted terminal output.
35
+ */
36
+ declare class CLIUI {
37
+ private config;
38
+ constructor(config?: Partial<UIConfig>);
39
+ private write;
40
+ private color;
41
+ /**
42
+ * Print a blank line.
43
+ */
44
+ blank(): void;
45
+ /**
46
+ * Print plain text.
47
+ */
48
+ print(message: string): void;
49
+ /**
50
+ * Print dimmed text (for secondary information).
51
+ */
52
+ dim(message: string): void;
53
+ /**
54
+ * Print bold text.
55
+ */
56
+ bold(message: string): void;
57
+ /**
58
+ * Print a success message with checkmark.
59
+ */
60
+ success(message: string): void;
61
+ /**
62
+ * Print an error message.
63
+ */
64
+ error(message: string, detail?: string): void;
65
+ /**
66
+ * Print a warning message.
67
+ */
68
+ warning(message: string): void;
69
+ /**
70
+ * Print an info message.
71
+ */
72
+ info(message: string): void;
73
+ /**
74
+ * Print a banner/header.
75
+ */
76
+ banner(title: string, subtitle?: string): void;
77
+ /**
78
+ * Print a section header.
79
+ */
80
+ section(title: string): void;
81
+ /**
82
+ * Print a horizontal divider.
83
+ */
84
+ divider(width?: number): void;
85
+ /**
86
+ * Print a key-value pair.
87
+ */
88
+ keyValue(key: string, value: string, keyWidth?: number): void;
89
+ /**
90
+ * Print a list item with bullet.
91
+ */
92
+ listItem(text: string, indent?: number): void;
93
+ /**
94
+ * Print a numbered list item.
95
+ */
96
+ numberedItem(number: number, text: string, indent?: number): void;
97
+ /**
98
+ * Print JSON data (for --json flag support).
99
+ */
100
+ json(data: unknown): void;
101
+ /**
102
+ * Print compact JSON data (single line).
103
+ */
104
+ jsonCompact(data: unknown): void;
105
+ /**
106
+ * Print a simple table.
107
+ */
108
+ table(headers: string[], rows: string[][]): void;
109
+ /**
110
+ * Print an approval prompt header.
111
+ */
112
+ approvalPrompt(title: string): void;
113
+ /**
114
+ * Print approval details.
115
+ */
116
+ approvalDetails(details: Record<string, string>): void;
117
+ /**
118
+ * Print approval options.
119
+ */
120
+ approvalOptions(options: string[]): void;
121
+ /**
122
+ * Update UI configuration.
123
+ */
124
+ configure(config: Partial<UIConfig>): void;
125
+ /**
126
+ * Get current configuration.
127
+ */
128
+ getConfig(): Readonly<UIConfig>;
129
+ }
130
+ /**
131
+ * Default CLI UI instance.
132
+ */
133
+ export declare const ui: CLIUI;
134
+ /**
135
+ * Create a new CLI UI instance with custom configuration.
136
+ */
137
+ export declare function createUI(config?: Partial<UIConfig>): CLIUI;
138
+ export {};
139
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;CACrC;AAED,MAAM,WAAW,QAAQ;IACvB,4BAA4B;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;IAC3B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAyBD;;GAEG;AACH,cAAM,KAAK;IACT,OAAO,CAAC,MAAM,CAAW;gBAEb,MAAM,GAAE,OAAO,CAAC,QAAQ,CAAM;IAQ1C,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,KAAK;IAQb;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ7C;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAS3B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAc9C;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B;;OAEG;IACH,OAAO,CAAC,KAAK,SAAK,GAAG,IAAI;IAIzB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,IAAI;IAKzD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAMxC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAU5D;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIzB;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAQhC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI;IAuBhD;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOnC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAMtD;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAYxC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAI1C;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC;CAGhC;AAMD;;GAEG;AACH,eAAO,MAAM,EAAE,OAAc,CAAC;AAE9B;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAE1D"}
package/dist/cli/ui.js ADDED
@@ -0,0 +1,271 @@
1
+ /**
2
+ * CLI User Interface Utilities
3
+ *
4
+ * Provides formatted terminal output for CLI commands. This module handles
5
+ * user-facing display (banners, tables, progress, etc.) separate from
6
+ * operational logging.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { ui } from './cli/ui.js';
11
+ *
12
+ * ui.banner('Tollgate Server');
13
+ * ui.success('Configuration validated');
14
+ * ui.error('Failed to start server', error.message);
15
+ * ui.table(['Name', 'Status'], data);
16
+ * ```
17
+ *
18
+ * @module cli/ui
19
+ */
20
+ import chalk from 'chalk';
21
+ // =============================================================================
22
+ // Configuration
23
+ // =============================================================================
24
+ /**
25
+ * Detect if colors should be enabled.
26
+ */
27
+ function detectColors() {
28
+ if (process.env.NO_COLOR !== undefined)
29
+ return false;
30
+ if (process.env.FORCE_COLOR !== undefined)
31
+ return true;
32
+ return process.stdout.isTTY ?? false;
33
+ }
34
+ const defaultConfig = {
35
+ colors: detectColors(),
36
+ stdout: process.stdout,
37
+ stderr: process.stderr,
38
+ };
39
+ // =============================================================================
40
+ // CLI UI Class
41
+ // =============================================================================
42
+ /**
43
+ * CLI UI utility for formatted terminal output.
44
+ */
45
+ class CLIUI {
46
+ config;
47
+ constructor(config = {}) {
48
+ this.config = { ...defaultConfig, ...config };
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Output Helpers
52
+ // ---------------------------------------------------------------------------
53
+ write(message, stream = 'stdout') {
54
+ const output = stream === 'stdout' ? this.config.stdout : this.config.stderr;
55
+ output.write(message + '\n');
56
+ }
57
+ color(fn, text) {
58
+ return this.config.colors ? fn(text) : text;
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Basic Output
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Print a blank line.
65
+ */
66
+ blank() {
67
+ this.write('');
68
+ }
69
+ /**
70
+ * Print plain text.
71
+ */
72
+ print(message) {
73
+ this.write(message);
74
+ }
75
+ /**
76
+ * Print dimmed text (for secondary information).
77
+ */
78
+ dim(message) {
79
+ this.write(this.color(chalk.dim, message));
80
+ }
81
+ /**
82
+ * Print bold text.
83
+ */
84
+ bold(message) {
85
+ this.write(this.color(chalk.bold, message));
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Status Messages
89
+ // ---------------------------------------------------------------------------
90
+ /**
91
+ * Print a success message with checkmark.
92
+ */
93
+ success(message) {
94
+ const prefix = this.config.colors ? chalk.green('✓') : '✓';
95
+ this.write(`${prefix} ${message}`);
96
+ }
97
+ /**
98
+ * Print an error message.
99
+ */
100
+ error(message, detail) {
101
+ const prefix = this.config.colors ? chalk.red('✗') : '✗';
102
+ this.write(`${prefix} ${this.color(chalk.red, message)}`, 'stderr');
103
+ if (detail) {
104
+ this.write(` ${this.color(chalk.dim, detail)}`, 'stderr');
105
+ }
106
+ }
107
+ /**
108
+ * Print a warning message.
109
+ */
110
+ warning(message) {
111
+ const prefix = this.config.colors ? chalk.yellow('⚠') : '⚠';
112
+ this.write(`${prefix} ${this.color(chalk.yellow, message)}`);
113
+ }
114
+ /**
115
+ * Print an info message.
116
+ */
117
+ info(message) {
118
+ const prefix = this.config.colors ? chalk.cyan('ℹ') : 'ℹ';
119
+ this.write(`${prefix} ${message}`);
120
+ }
121
+ // ---------------------------------------------------------------------------
122
+ // Structured Output
123
+ // ---------------------------------------------------------------------------
124
+ /**
125
+ * Print a banner/header.
126
+ */
127
+ banner(title, subtitle) {
128
+ const width = Math.max(title.length, subtitle?.length ?? 0) + 4;
129
+ const line = '═'.repeat(width);
130
+ this.blank();
131
+ this.write(this.color(chalk.cyan, `╔${line}╗`));
132
+ this.write(this.color(chalk.cyan, `║ ${title.padEnd(width - 2)}║`));
133
+ if (subtitle) {
134
+ this.write(this.color(chalk.cyan, `║ ${this.color(chalk.dim, subtitle.padEnd(width - 2))}║`));
135
+ }
136
+ this.write(this.color(chalk.cyan, `╚${line}╝`));
137
+ this.blank();
138
+ }
139
+ /**
140
+ * Print a section header.
141
+ */
142
+ section(title) {
143
+ this.blank();
144
+ this.write(this.color(chalk.bold.cyan, `━━ ${title} ━━`));
145
+ }
146
+ /**
147
+ * Print a horizontal divider.
148
+ */
149
+ divider(width = 40) {
150
+ this.write(this.color(chalk.dim, '─'.repeat(width)));
151
+ }
152
+ /**
153
+ * Print a key-value pair.
154
+ */
155
+ keyValue(key, value, keyWidth = 20) {
156
+ const paddedKey = key.padEnd(keyWidth);
157
+ this.write(`${this.color(chalk.dim, paddedKey)} ${value}`);
158
+ }
159
+ /**
160
+ * Print a list item with bullet.
161
+ */
162
+ listItem(text, indent = 0) {
163
+ const spaces = ' '.repeat(indent * 2);
164
+ const bullet = this.config.colors ? chalk.dim('•') : '•';
165
+ this.write(`${spaces}${bullet} ${text}`);
166
+ }
167
+ /**
168
+ * Print a numbered list item.
169
+ */
170
+ numberedItem(number, text, indent = 0) {
171
+ const spaces = ' '.repeat(indent * 2);
172
+ const num = this.color(chalk.dim, `${number}.`);
173
+ this.write(`${spaces}${num} ${text}`);
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // JSON Output
177
+ // ---------------------------------------------------------------------------
178
+ /**
179
+ * Print JSON data (for --json flag support).
180
+ */
181
+ json(data) {
182
+ this.write(JSON.stringify(data, null, 2));
183
+ }
184
+ /**
185
+ * Print compact JSON data (single line).
186
+ */
187
+ jsonCompact(data) {
188
+ this.write(JSON.stringify(data));
189
+ }
190
+ // ---------------------------------------------------------------------------
191
+ // Tables
192
+ // ---------------------------------------------------------------------------
193
+ /**
194
+ * Print a simple table.
195
+ */
196
+ table(headers, rows) {
197
+ // Calculate column widths
198
+ const widths = headers.map((h, i) => {
199
+ const maxRowWidth = Math.max(...rows.map(r => (r[i] ?? '').length));
200
+ return Math.max(h.length, maxRowWidth);
201
+ });
202
+ // Header
203
+ const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(' ');
204
+ this.write(this.color(chalk.bold, headerLine));
205
+ this.write(this.color(chalk.dim, widths.map(w => '─'.repeat(w)).join('──')));
206
+ // Rows
207
+ for (const row of rows) {
208
+ const rowLine = row.map((cell, i) => (cell ?? '').padEnd(widths[i])).join(' ');
209
+ this.write(rowLine);
210
+ }
211
+ }
212
+ // ---------------------------------------------------------------------------
213
+ // Interactive Prompts Display
214
+ // ---------------------------------------------------------------------------
215
+ /**
216
+ * Print an approval prompt header.
217
+ */
218
+ approvalPrompt(title) {
219
+ this.blank();
220
+ this.write(this.color(chalk.yellow.bold, '━'.repeat(60)));
221
+ this.write(this.color(chalk.yellow.bold, `⚠ ${title}`));
222
+ this.write(this.color(chalk.yellow.bold, '━'.repeat(60)));
223
+ }
224
+ /**
225
+ * Print approval details.
226
+ */
227
+ approvalDetails(details) {
228
+ for (const [key, value] of Object.entries(details)) {
229
+ this.keyValue(key, value);
230
+ }
231
+ }
232
+ /**
233
+ * Print approval options.
234
+ */
235
+ approvalOptions(options) {
236
+ this.blank();
237
+ for (const option of options) {
238
+ this.write(` ${option}`);
239
+ }
240
+ this.blank();
241
+ }
242
+ // ---------------------------------------------------------------------------
243
+ // Configuration
244
+ // ---------------------------------------------------------------------------
245
+ /**
246
+ * Update UI configuration.
247
+ */
248
+ configure(config) {
249
+ this.config = { ...this.config, ...config };
250
+ }
251
+ /**
252
+ * Get current configuration.
253
+ */
254
+ getConfig() {
255
+ return { ...this.config };
256
+ }
257
+ }
258
+ // =============================================================================
259
+ // Default Instance
260
+ // =============================================================================
261
+ /**
262
+ * Default CLI UI instance.
263
+ */
264
+ export const ui = new CLIUI();
265
+ /**
266
+ * Create a new CLI UI instance with custom configuration.
267
+ */
268
+ export function createUI(config) {
269
+ return new CLIUI(config);
270
+ }
271
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAqB1B,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF;;GAEG;AACH,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,aAAa,GAAa;IAC9B,MAAM,EAAE,YAAY,EAAE;IACtB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,MAAM,EAAE,OAAO,CAAC,MAAM;CACvB,CAAC;AAEF,gFAAgF;AAChF,eAAe;AACf,gFAAgF;AAEhF;;GAEG;AACH,MAAM,KAAK;IACD,MAAM,CAAW;IAEzB,YAAY,SAA4B,EAAE;QACxC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;IAChD,CAAC;IAED,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAEtE,KAAK,CAAC,OAAe,EAAE,SAA8B,QAAQ;QACnE,MAAM,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAmB,EAAoB,EAAE,IAAO;QAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9C,CAAC;IAED,8EAA8E;IAC9E,eAAe;IACf,8EAA8E;IAE9E;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,OAAe;QACjB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;OAEG;IACH,OAAO,CAAC,OAAe;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAe,EAAE,MAAe;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACpE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,OAAe;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAe;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,8EAA8E;IAC9E,oBAAoB;IACpB,8EAA8E;IAE9E;;OAEG;IACH,MAAM,CAAC,KAAa,EAAE,QAAiB;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACjG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAa;QACnB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAK,GAAG,EAAE;QAChB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,GAAW,EAAE,KAAa,EAAE,QAAQ,GAAG,EAAE;QAChD,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,IAAY,EAAE,MAAM,GAAG,CAAC;QAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,MAAc,EAAE,IAAY,EAAE,MAAM,GAAG,CAAC;QACnD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E;;OAEG;IACH,IAAI,CAAC,IAAa;QAChB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,IAAa;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,8EAA8E;IAC9E,SAAS;IACT,8EAA8E;IAE9E;;OAEG;IACH,KAAK,CAAC,OAAiB,EAAE,IAAgB;QACvC,0BAA0B;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAClC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACpE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,SAAS;QACT,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE7E,OAAO;QACP,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,8BAA8B;IAC9B,8EAA8E;IAE9E;;OAEG;IACH,cAAc,CAAC,KAAa;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAA+B;QAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAAiB;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,8EAA8E;IAC9E,gBAAgB;IAChB,8EAA8E;IAE9E;;OAEG;IACH,SAAS,CAAC,MAAyB;QACjC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;CACF;AAED,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,KAAK,EAAE,CAAC;AAE9B;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,MAA0B;IACjD,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC"}