opentunnel-cli 1.0.22 → 1.0.25

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 (50) hide show
  1. package/README.md +69 -864
  2. package/dist/cli/index.js +712 -84
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/client/CloudflareTunnelClient.d.ts +110 -0
  5. package/dist/client/CloudflareTunnelClient.d.ts.map +1 -0
  6. package/dist/client/CloudflareTunnelClient.js +531 -0
  7. package/dist/client/CloudflareTunnelClient.js.map +1 -0
  8. package/dist/client/NgrokClient.d.ts +18 -1
  9. package/dist/client/NgrokClient.d.ts.map +1 -1
  10. package/dist/client/NgrokClient.js +130 -4
  11. package/dist/client/NgrokClient.js.map +1 -1
  12. package/dist/client/TunnelClient.d.ts +0 -1
  13. package/dist/client/TunnelClient.d.ts.map +1 -1
  14. package/dist/client/TunnelClient.js +2 -96
  15. package/dist/client/TunnelClient.js.map +1 -1
  16. package/dist/client/index.d.ts +1 -0
  17. package/dist/client/index.d.ts.map +1 -1
  18. package/dist/client/index.js +3 -1
  19. package/dist/client/index.js.map +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/lib/index.d.ts +2 -0
  25. package/dist/lib/index.d.ts.map +1 -0
  26. package/dist/lib/index.js +18 -0
  27. package/dist/lib/index.js.map +1 -0
  28. package/dist/lib/pages/index.d.ts +2 -0
  29. package/dist/lib/pages/index.d.ts.map +1 -0
  30. package/dist/lib/pages/index.js +6 -0
  31. package/dist/lib/pages/index.js.map +1 -0
  32. package/dist/lib/pages/not-running.d.ts +10 -0
  33. package/dist/lib/pages/not-running.d.ts.map +1 -0
  34. package/dist/lib/pages/not-running.js +117 -0
  35. package/dist/lib/pages/not-running.js.map +1 -0
  36. package/dist/server/TunnelServer.d.ts +7 -3
  37. package/dist/server/TunnelServer.d.ts.map +1 -1
  38. package/dist/server/TunnelServer.js +164 -51
  39. package/dist/server/TunnelServer.js.map +1 -1
  40. package/dist/shared/credentials.d.ts +101 -0
  41. package/dist/shared/credentials.d.ts.map +1 -0
  42. package/dist/shared/credentials.js +302 -0
  43. package/dist/shared/credentials.js.map +1 -0
  44. package/dist/shared/ip-filter.d.ts +75 -0
  45. package/dist/shared/ip-filter.d.ts.map +1 -0
  46. package/dist/shared/ip-filter.js +203 -0
  47. package/dist/shared/ip-filter.js.map +1 -0
  48. package/dist/shared/types.d.ts +46 -0
  49. package/dist/shared/types.d.ts.map +1 -1
  50. package/package.json +7 -3
@@ -0,0 +1,101 @@
1
+ import { CloudflareCredentials, NgrokCredentials, GlobalCredentials } from "./types";
2
+ /**
3
+ * Credentials Manager
4
+ *
5
+ * Handles secure storage and retrieval of provider credentials.
6
+ * Credential resolution priority: CLI > ENV > YAML > credentials.json
7
+ */
8
+ export declare class CredentialsManager {
9
+ private credentials;
10
+ constructor();
11
+ /**
12
+ * Get the credentials directory path
13
+ */
14
+ static getCredentialsDir(): string;
15
+ /**
16
+ * Get the credentials file path
17
+ */
18
+ static getCredentialsFile(): string;
19
+ /**
20
+ * Ensure the credentials directory exists with secure permissions
21
+ */
22
+ private ensureDir;
23
+ /**
24
+ * Load credentials from file
25
+ */
26
+ load(): GlobalCredentials;
27
+ /**
28
+ * Save credentials to file with secure permissions (0600)
29
+ */
30
+ save(): void;
31
+ /**
32
+ * Get all credentials
33
+ */
34
+ getAll(): GlobalCredentials;
35
+ /**
36
+ * Get ngrok credentials
37
+ */
38
+ getNgrok(): NgrokCredentials | undefined;
39
+ /**
40
+ * Set ngrok credentials
41
+ */
42
+ setNgrok(creds: NgrokCredentials): void;
43
+ /**
44
+ * Remove ngrok credentials
45
+ */
46
+ removeNgrok(): boolean;
47
+ /**
48
+ * Get Cloudflare credentials
49
+ */
50
+ getCloudflare(): CloudflareCredentials | undefined;
51
+ /**
52
+ * Set Cloudflare credentials
53
+ */
54
+ setCloudflare(creds: CloudflareCredentials): void;
55
+ /**
56
+ * Remove Cloudflare credentials
57
+ */
58
+ removeCloudflare(): boolean;
59
+ /**
60
+ * Remove all credentials for a provider
61
+ */
62
+ removeProvider(provider: "ngrok" | "cloudflare"): boolean;
63
+ /**
64
+ * Set a specific credential value using dot notation
65
+ * e.g., "ngrok.token", "cloudflare.accountId"
66
+ */
67
+ set(key: string, value: string): void;
68
+ /**
69
+ * Get a specific credential value using dot notation
70
+ * e.g., "ngrok.token", "cloudflare.accountId"
71
+ */
72
+ get(key: string): string | undefined;
73
+ /**
74
+ * List all stored credential keys (not values for security)
75
+ */
76
+ listKeys(): string[];
77
+ /**
78
+ * Clear all credentials
79
+ */
80
+ clear(): void;
81
+ }
82
+ /**
83
+ * Resolve ngrok token with priority: CLI > ENV > YAML > credentials.json
84
+ */
85
+ export declare function resolveNgrokToken(options: {
86
+ cliToken?: string;
87
+ yamlToken?: string;
88
+ }): string | undefined;
89
+ /**
90
+ * Resolve Cloudflare credentials with priority: CLI > ENV > YAML > credentials.json
91
+ */
92
+ export declare function resolveCloudflareCredentials(options: {
93
+ cliAccountId?: string;
94
+ cliTunnelToken?: string;
95
+ cliCertPath?: string;
96
+ yamlAccountId?: string;
97
+ yamlTunnelToken?: string;
98
+ yamlCertPath?: string;
99
+ }): CloudflareCredentials;
100
+ export declare function getCredentialsManager(): CredentialsManager;
101
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/shared/credentials.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAMrF;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,WAAW,CAAyB;;IAM5C;;OAEG;IACH,MAAM,CAAC,iBAAiB,IAAI,MAAM;IAIlC;;OAEG;IACH,MAAM,CAAC,kBAAkB,IAAI,MAAM;IAInC;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,IAAI,IAAI,iBAAiB;IAYzB;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,MAAM,IAAI,iBAAiB;IAI3B;;OAEG;IACH,QAAQ,IAAI,gBAAgB,GAAG,SAAS;IAIxC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAKvC;;OAEG;IACH,WAAW,IAAI,OAAO;IAStB;;OAEG;IACH,aAAa,IAAI,qBAAqB,GAAG,SAAS;IAIlD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAQjD;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAS3B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,OAAO,GAAG,YAAY,GAAG,OAAO;IASzD;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IA0BrC;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAoBpC;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;IAgBpB;;OAEG;IACH,KAAK,IAAI,IAAI;CAIhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,GAAG,SAAS,CAoBrB;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,qBAAqB,CAkBxB;AAKD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D"}
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CredentialsManager = void 0;
37
+ exports.resolveNgrokToken = resolveNgrokToken;
38
+ exports.resolveCloudflareCredentials = resolveCloudflareCredentials;
39
+ exports.getCredentialsManager = getCredentialsManager;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const os = __importStar(require("os"));
43
+ // Credentials file location
44
+ const OPENTUNNEL_DIR = path.join(os.homedir(), ".opentunnel");
45
+ const CREDENTIALS_FILE = path.join(OPENTUNNEL_DIR, "credentials.json");
46
+ /**
47
+ * Credentials Manager
48
+ *
49
+ * Handles secure storage and retrieval of provider credentials.
50
+ * Credential resolution priority: CLI > ENV > YAML > credentials.json
51
+ */
52
+ class CredentialsManager {
53
+ constructor() {
54
+ this.credentials = {};
55
+ this.load();
56
+ }
57
+ /**
58
+ * Get the credentials directory path
59
+ */
60
+ static getCredentialsDir() {
61
+ return OPENTUNNEL_DIR;
62
+ }
63
+ /**
64
+ * Get the credentials file path
65
+ */
66
+ static getCredentialsFile() {
67
+ return CREDENTIALS_FILE;
68
+ }
69
+ /**
70
+ * Ensure the credentials directory exists with secure permissions
71
+ */
72
+ ensureDir() {
73
+ if (!fs.existsSync(OPENTUNNEL_DIR)) {
74
+ fs.mkdirSync(OPENTUNNEL_DIR, { recursive: true, mode: 0o700 });
75
+ }
76
+ }
77
+ /**
78
+ * Load credentials from file
79
+ */
80
+ load() {
81
+ try {
82
+ if (fs.existsSync(CREDENTIALS_FILE)) {
83
+ const content = fs.readFileSync(CREDENTIALS_FILE, "utf-8");
84
+ this.credentials = JSON.parse(content);
85
+ }
86
+ }
87
+ catch {
88
+ this.credentials = {};
89
+ }
90
+ return this.credentials;
91
+ }
92
+ /**
93
+ * Save credentials to file with secure permissions (0600)
94
+ */
95
+ save() {
96
+ this.ensureDir();
97
+ fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(this.credentials, null, 2), {
98
+ mode: 0o600,
99
+ });
100
+ }
101
+ /**
102
+ * Get all credentials
103
+ */
104
+ getAll() {
105
+ return this.credentials;
106
+ }
107
+ /**
108
+ * Get ngrok credentials
109
+ */
110
+ getNgrok() {
111
+ return this.credentials.ngrok;
112
+ }
113
+ /**
114
+ * Set ngrok credentials
115
+ */
116
+ setNgrok(creds) {
117
+ this.credentials.ngrok = creds;
118
+ this.save();
119
+ }
120
+ /**
121
+ * Remove ngrok credentials
122
+ */
123
+ removeNgrok() {
124
+ if (this.credentials.ngrok) {
125
+ delete this.credentials.ngrok;
126
+ this.save();
127
+ return true;
128
+ }
129
+ return false;
130
+ }
131
+ /**
132
+ * Get Cloudflare credentials
133
+ */
134
+ getCloudflare() {
135
+ return this.credentials.cloudflare;
136
+ }
137
+ /**
138
+ * Set Cloudflare credentials
139
+ */
140
+ setCloudflare(creds) {
141
+ this.credentials.cloudflare = {
142
+ ...this.credentials.cloudflare,
143
+ ...creds,
144
+ };
145
+ this.save();
146
+ }
147
+ /**
148
+ * Remove Cloudflare credentials
149
+ */
150
+ removeCloudflare() {
151
+ if (this.credentials.cloudflare) {
152
+ delete this.credentials.cloudflare;
153
+ this.save();
154
+ return true;
155
+ }
156
+ return false;
157
+ }
158
+ /**
159
+ * Remove all credentials for a provider
160
+ */
161
+ removeProvider(provider) {
162
+ if (provider === "ngrok") {
163
+ return this.removeNgrok();
164
+ }
165
+ else if (provider === "cloudflare") {
166
+ return this.removeCloudflare();
167
+ }
168
+ return false;
169
+ }
170
+ /**
171
+ * Set a specific credential value using dot notation
172
+ * e.g., "ngrok.token", "cloudflare.accountId"
173
+ */
174
+ set(key, value) {
175
+ const [provider, field] = key.split(".");
176
+ if (provider === "ngrok") {
177
+ if (!this.credentials.ngrok) {
178
+ this.credentials.ngrok = { token: "" };
179
+ }
180
+ if (field === "token") {
181
+ this.credentials.ngrok.token = value;
182
+ }
183
+ }
184
+ else if (provider === "cloudflare") {
185
+ if (!this.credentials.cloudflare) {
186
+ this.credentials.cloudflare = {};
187
+ }
188
+ if (field === "accountId") {
189
+ this.credentials.cloudflare.accountId = value;
190
+ }
191
+ else if (field === "tunnelToken") {
192
+ this.credentials.cloudflare.tunnelToken = value;
193
+ }
194
+ else if (field === "certPath") {
195
+ this.credentials.cloudflare.certPath = value;
196
+ }
197
+ }
198
+ this.save();
199
+ }
200
+ /**
201
+ * Get a specific credential value using dot notation
202
+ * e.g., "ngrok.token", "cloudflare.accountId"
203
+ */
204
+ get(key) {
205
+ const [provider, field] = key.split(".");
206
+ if (provider === "ngrok" && this.credentials.ngrok) {
207
+ if (field === "token") {
208
+ return this.credentials.ngrok.token;
209
+ }
210
+ }
211
+ else if (provider === "cloudflare" && this.credentials.cloudflare) {
212
+ if (field === "accountId") {
213
+ return this.credentials.cloudflare.accountId;
214
+ }
215
+ else if (field === "tunnelToken") {
216
+ return this.credentials.cloudflare.tunnelToken;
217
+ }
218
+ else if (field === "certPath") {
219
+ return this.credentials.cloudflare.certPath;
220
+ }
221
+ }
222
+ return undefined;
223
+ }
224
+ /**
225
+ * List all stored credential keys (not values for security)
226
+ */
227
+ listKeys() {
228
+ const keys = [];
229
+ if (this.credentials.ngrok) {
230
+ if (this.credentials.ngrok.token)
231
+ keys.push("ngrok.token");
232
+ }
233
+ if (this.credentials.cloudflare) {
234
+ if (this.credentials.cloudflare.accountId)
235
+ keys.push("cloudflare.accountId");
236
+ if (this.credentials.cloudflare.tunnelToken)
237
+ keys.push("cloudflare.tunnelToken");
238
+ if (this.credentials.cloudflare.certPath)
239
+ keys.push("cloudflare.certPath");
240
+ }
241
+ return keys;
242
+ }
243
+ /**
244
+ * Clear all credentials
245
+ */
246
+ clear() {
247
+ this.credentials = {};
248
+ this.save();
249
+ }
250
+ }
251
+ exports.CredentialsManager = CredentialsManager;
252
+ /**
253
+ * Resolve ngrok token with priority: CLI > ENV > YAML > credentials.json
254
+ */
255
+ function resolveNgrokToken(options) {
256
+ // 1. CLI flag (highest priority)
257
+ if (options.cliToken) {
258
+ return options.cliToken;
259
+ }
260
+ // 2. Environment variable
261
+ const envToken = process.env.NGROK_TOKEN || process.env.NGROK_AUTHTOKEN;
262
+ if (envToken) {
263
+ return envToken;
264
+ }
265
+ // 3. YAML config
266
+ if (options.yamlToken) {
267
+ return options.yamlToken;
268
+ }
269
+ // 4. Stored credentials (lowest priority)
270
+ const manager = new CredentialsManager();
271
+ return manager.getNgrok()?.token;
272
+ }
273
+ /**
274
+ * Resolve Cloudflare credentials with priority: CLI > ENV > YAML > credentials.json
275
+ */
276
+ function resolveCloudflareCredentials(options) {
277
+ const manager = new CredentialsManager();
278
+ const stored = manager.getCloudflare() || {};
279
+ return {
280
+ accountId: options.cliAccountId
281
+ || process.env.CLOUDFLARE_ACCOUNT_ID
282
+ || options.yamlAccountId
283
+ || stored.accountId,
284
+ tunnelToken: options.cliTunnelToken
285
+ || process.env.CLOUDFLARE_TUNNEL_TOKEN
286
+ || options.yamlTunnelToken
287
+ || stored.tunnelToken,
288
+ certPath: options.cliCertPath
289
+ || process.env.CLOUDFLARE_CERT_PATH
290
+ || options.yamlCertPath
291
+ || stored.certPath,
292
+ };
293
+ }
294
+ // Singleton instance for convenience
295
+ let _instance = null;
296
+ function getCredentialsManager() {
297
+ if (!_instance) {
298
+ _instance = new CredentialsManager();
299
+ }
300
+ return _instance;
301
+ }
302
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/shared/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import { IncomingMessage } from "http";
2
+ import { IpAccessConfig } from "./types";
3
+ /**
4
+ * Result of an IP access check
5
+ */
6
+ export interface IpCheckResult {
7
+ allowed: boolean;
8
+ reason?: string;
9
+ }
10
+ /**
11
+ * Shared IP filtering class for cross-provider security
12
+ *
13
+ * Supports:
14
+ * - Allowlist mode: Only IPs in the list are allowed
15
+ * - Denylist mode: IPs in the list are denied, others allowed
16
+ * - CIDR notation (e.g., 192.168.0.0/16)
17
+ * - IPv6-mapped IPv4 normalization
18
+ * - X-Forwarded-For / CF-Connecting-IP header extraction
19
+ */
20
+ export declare class IpFilter {
21
+ private config;
22
+ constructor(config?: IpAccessConfig);
23
+ /**
24
+ * Update the filter configuration
25
+ */
26
+ setConfig(config: IpAccessConfig): void;
27
+ /**
28
+ * Get the current configuration
29
+ */
30
+ getConfig(): IpAccessConfig;
31
+ /**
32
+ * Check if an IP matches a CIDR range or single IP
33
+ */
34
+ ipMatchesCidr(ip: string, cidr: string): boolean;
35
+ /**
36
+ * Check if an IP is in a list (supports CIDR notation)
37
+ */
38
+ ipInList(ip: string, list: string[]): boolean;
39
+ /**
40
+ * Check if an IP is allowed based on the access config
41
+ */
42
+ isAllowed(ip: string): IpCheckResult;
43
+ /**
44
+ * Normalize an IP address (removes IPv6-mapped IPv4 prefix)
45
+ */
46
+ static normalizeIp(ip: string): string;
47
+ /**
48
+ * Extract client IP from various headers and socket
49
+ *
50
+ * Priority:
51
+ * 1. CF-Connecting-IP (Cloudflare)
52
+ * 2. X-Real-IP (nginx, common proxies)
53
+ * 3. X-Forwarded-For (first IP, standard proxy header)
54
+ * 4. Socket remoteAddress (direct connection)
55
+ */
56
+ static extractClientIp(req: IncomingMessage): string;
57
+ /**
58
+ * Extract client IP from headers object (for use without IncomingMessage)
59
+ */
60
+ static extractClientIpFromHeaders(headers: Record<string, string | string[] | undefined>, socketAddress?: string): string;
61
+ /**
62
+ * Merge two IP access configs, with the second one taking priority for non-undefined values
63
+ * Useful for per-tunnel config overriding global config
64
+ */
65
+ static mergeConfigs(base?: IpAccessConfig, override?: IpAccessConfig): IpAccessConfig | undefined;
66
+ }
67
+ /**
68
+ * Create a filter middleware function for HTTP servers
69
+ *
70
+ * @param config IP access configuration
71
+ * @param onDenied Optional callback when access is denied
72
+ * @returns Middleware function that returns true if allowed, false if denied
73
+ */
74
+ export declare function createIpFilterMiddleware(config?: IpAccessConfig, onDenied?: (ip: string, reason: string) => void): (req: IncomingMessage) => IpCheckResult;
75
+ //# sourceMappingURL=ip-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip-filter.d.ts","sourceRoot":"","sources":["../../src/shared/ip-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,qBAAa,QAAQ;IACjB,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,CAAC,EAAE,cAAc;IAInC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIvC;;OAEG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IA6BhD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO;IAI7C;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa;IA4BpC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAItC;;;;;;;;OAQG;IACH,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM;IAkCpD;;OAEG;IACH,MAAM,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM;IAiCzH;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS;CAmBpG;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,CAAC,EAAE,cAAc,EACvB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAChD,CAAC,GAAG,EAAE,eAAe,KAAK,aAAa,CAazC"}