@brainfish-ai/devdoc 0.1.45 → 0.1.46

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,871 @@
1
+ "use strict";
2
+ /**
3
+ * SDK Generation Module
4
+ *
5
+ * This module provides functionality for generating client SDKs from OpenAPI specifications.
6
+ * It supports multiple languages using both native generators and OpenAPI Generator.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.SUPPORTED_LANGUAGES = void 0;
46
+ exports.loadSDKConfig = loadSDKConfig;
47
+ exports.initSDKConfig = initSDKConfig;
48
+ exports.getEnabledGenerators = getEnabledGenerators;
49
+ exports.getGeneratorInfo = getGeneratorInfo;
50
+ exports.isNativeGenerator = isNativeGenerator;
51
+ exports.resolveSpecPath = resolveSpecPath;
52
+ exports.validateSpec = validateSpec;
53
+ exports.generateSDKs = generateSDKs;
54
+ const path_1 = __importDefault(require("path"));
55
+ const fs_extra_1 = __importDefault(require("fs-extra"));
56
+ const child_process_1 = require("child_process");
57
+ const util_1 = require("util");
58
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
59
+ // ============================================================================
60
+ // Constants
61
+ // ============================================================================
62
+ /**
63
+ * All supported languages
64
+ */
65
+ exports.SUPPORTED_LANGUAGES = [
66
+ 'typescript',
67
+ 'python',
68
+ 'go',
69
+ 'java',
70
+ 'csharp',
71
+ 'ruby',
72
+ 'php',
73
+ 'swift',
74
+ 'kotlin',
75
+ 'rust',
76
+ ];
77
+ /**
78
+ * Generator information for each language
79
+ */
80
+ const GENERATORS = [
81
+ { language: 'typescript', displayName: 'TypeScript', native: true, requiresJava: false },
82
+ { language: 'python', displayName: 'Python', native: true, requiresJava: false },
83
+ { language: 'go', displayName: 'Go', native: true, requiresJava: false },
84
+ { language: 'java', displayName: 'Java', native: false, requiresJava: true, generatorName: 'java' },
85
+ { language: 'csharp', displayName: 'C#', native: false, requiresJava: true, generatorName: 'csharp' },
86
+ { language: 'ruby', displayName: 'Ruby', native: false, requiresJava: true, generatorName: 'ruby' },
87
+ { language: 'php', displayName: 'PHP', native: false, requiresJava: true, generatorName: 'php' },
88
+ { language: 'swift', displayName: 'Swift', native: false, requiresJava: true, generatorName: 'swift5' },
89
+ { language: 'kotlin', displayName: 'Kotlin', native: false, requiresJava: true, generatorName: 'kotlin' },
90
+ { language: 'rust', displayName: 'Rust', native: false, requiresJava: true, generatorName: 'rust' },
91
+ ];
92
+ const CONFIG_FILENAME = 'sdk.json';
93
+ // ============================================================================
94
+ // Configuration Functions
95
+ // ============================================================================
96
+ /**
97
+ * Load SDK configuration from project directory
98
+ */
99
+ async function loadSDKConfig(projectRoot) {
100
+ const configPath = path_1.default.join(projectRoot, CONFIG_FILENAME);
101
+ if (!(await fs_extra_1.default.pathExists(configPath))) {
102
+ return { config: null, error: `${CONFIG_FILENAME} not found` };
103
+ }
104
+ try {
105
+ const config = await fs_extra_1.default.readJson(configPath);
106
+ return { config };
107
+ }
108
+ catch (error) {
109
+ return {
110
+ config: null,
111
+ error: `Failed to parse ${CONFIG_FILENAME}: ${error instanceof Error ? error.message : String(error)}`,
112
+ };
113
+ }
114
+ }
115
+ /**
116
+ * Initialize SDK configuration
117
+ */
118
+ async function initSDKConfig(projectRoot, options) {
119
+ const configPath = path_1.default.join(projectRoot, CONFIG_FILENAME);
120
+ // Check if config already exists
121
+ if ((await fs_extra_1.default.pathExists(configPath)) && !options.force) {
122
+ throw new Error(`${CONFIG_FILENAME} already exists. Use --force to overwrite.`);
123
+ }
124
+ // Create language configurations
125
+ const languages = {};
126
+ for (const lang of options.languages) {
127
+ languages[lang] = {
128
+ enabled: true,
129
+ packageName: getDefaultPackageName(options.packageName, lang),
130
+ };
131
+ }
132
+ const config = {
133
+ openapi: options.openapi,
134
+ packageName: options.packageName,
135
+ output: './sdks',
136
+ languages,
137
+ };
138
+ await fs_extra_1.default.writeJson(configPath, config, { spaces: 2 });
139
+ return { configPath, config };
140
+ }
141
+ /**
142
+ * Get enabled generators from config
143
+ */
144
+ function getEnabledGenerators(config) {
145
+ return Object.entries(config.languages)
146
+ .filter(([, langConfig]) => langConfig?.enabled)
147
+ .map(([lang]) => lang);
148
+ }
149
+ /**
150
+ * Get generator information for all languages
151
+ */
152
+ function getGeneratorInfo() {
153
+ return [...GENERATORS];
154
+ }
155
+ /**
156
+ * Check if a generator is native (doesn't require Java)
157
+ */
158
+ function isNativeGenerator(language) {
159
+ const generator = GENERATORS.find((g) => g.language === language);
160
+ return generator?.native ?? false;
161
+ }
162
+ // ============================================================================
163
+ // Path Utilities
164
+ // ============================================================================
165
+ /**
166
+ * Resolve OpenAPI spec path relative to project root
167
+ */
168
+ function resolveSpecPath(projectRoot, specPath) {
169
+ if (path_1.default.isAbsolute(specPath)) {
170
+ return specPath;
171
+ }
172
+ return path_1.default.resolve(projectRoot, specPath);
173
+ }
174
+ /**
175
+ * Get default package name for a language
176
+ */
177
+ function getDefaultPackageName(baseName, language) {
178
+ const sanitized = baseName.toLowerCase().replace(/[^a-z0-9]/g, '-');
179
+ switch (language) {
180
+ case 'typescript':
181
+ return `@${sanitized}/sdk`;
182
+ case 'python':
183
+ return sanitized.replace(/-/g, '_');
184
+ case 'go':
185
+ return sanitized;
186
+ case 'java':
187
+ return `com.${sanitized.replace(/-/g, '.')}`;
188
+ case 'csharp':
189
+ return sanitized.split('-').map(capitalize).join('.');
190
+ case 'ruby':
191
+ return sanitized.replace(/-/g, '_');
192
+ case 'php':
193
+ return sanitized.split('-').map(capitalize).join('\\');
194
+ case 'swift':
195
+ return sanitized.split('-').map(capitalize).join('');
196
+ case 'kotlin':
197
+ return `com.${sanitized.replace(/-/g, '.')}`;
198
+ case 'rust':
199
+ return sanitized.replace(/-/g, '_');
200
+ default:
201
+ return sanitized;
202
+ }
203
+ }
204
+ function capitalize(str) {
205
+ return str.charAt(0).toUpperCase() + str.slice(1);
206
+ }
207
+ // ============================================================================
208
+ // Validation
209
+ // ============================================================================
210
+ /**
211
+ * Validate an OpenAPI specification
212
+ */
213
+ async function validateSpec(specPath) {
214
+ const errors = [];
215
+ const warnings = [];
216
+ // Check file exists
217
+ if (!(await fs_extra_1.default.pathExists(specPath))) {
218
+ return {
219
+ valid: false,
220
+ errors: [`OpenAPI specification not found: ${specPath}`],
221
+ warnings: [],
222
+ };
223
+ }
224
+ try {
225
+ // Read and parse the spec
226
+ const content = await fs_extra_1.default.readFile(specPath, 'utf-8');
227
+ let spec;
228
+ if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
229
+ const yaml = await Promise.resolve().then(() => __importStar(require('js-yaml')));
230
+ spec = yaml.load(content);
231
+ }
232
+ else {
233
+ spec = JSON.parse(content);
234
+ }
235
+ // Basic validation
236
+ if (!spec.openapi && !spec.swagger) {
237
+ errors.push('Missing "openapi" or "swagger" version field');
238
+ }
239
+ if (!spec.info) {
240
+ errors.push('Missing "info" section');
241
+ }
242
+ else {
243
+ const info = spec.info;
244
+ if (!info.title) {
245
+ warnings.push('Missing "info.title"');
246
+ }
247
+ if (!info.version) {
248
+ warnings.push('Missing "info.version"');
249
+ }
250
+ }
251
+ if (!spec.paths || Object.keys(spec.paths).length === 0) {
252
+ warnings.push('No paths defined in specification');
253
+ }
254
+ // Check for common issues
255
+ const openapiVersion = spec.openapi;
256
+ if (openapiVersion && !openapiVersion.startsWith('3.')) {
257
+ warnings.push(`OpenAPI ${openapiVersion} detected. Version 3.x is recommended.`);
258
+ }
259
+ return {
260
+ valid: errors.length === 0,
261
+ errors,
262
+ warnings,
263
+ };
264
+ }
265
+ catch (error) {
266
+ return {
267
+ valid: false,
268
+ errors: [`Failed to parse specification: ${error instanceof Error ? error.message : String(error)}`],
269
+ warnings: [],
270
+ };
271
+ }
272
+ }
273
+ // ============================================================================
274
+ // SDK Generation
275
+ // ============================================================================
276
+ /**
277
+ * Generate SDKs for configured languages
278
+ */
279
+ async function generateSDKs(projectRoot, options = {}) {
280
+ const startTime = Date.now();
281
+ const results = [];
282
+ // Load config
283
+ const { config, error } = await loadSDKConfig(projectRoot);
284
+ if (!config) {
285
+ throw new Error(error || 'SDK configuration not found');
286
+ }
287
+ // Determine which languages to generate
288
+ let languagesToGenerate = getEnabledGenerators(config);
289
+ if (options.language) {
290
+ if (!languagesToGenerate.includes(options.language)) {
291
+ throw new Error(`Language "${options.language}" is not enabled in sdk.json`);
292
+ }
293
+ languagesToGenerate = [options.language];
294
+ }
295
+ // Resolve spec path
296
+ const specPath = resolveSpecPath(projectRoot, config.openapi);
297
+ // Validate spec exists
298
+ if (!(await fs_extra_1.default.pathExists(specPath))) {
299
+ throw new Error(`OpenAPI specification not found: ${config.openapi}`);
300
+ }
301
+ // Base output directory
302
+ const baseOutputDir = options.outputDir
303
+ ? path_1.default.resolve(projectRoot, options.outputDir)
304
+ : path_1.default.resolve(projectRoot, config.output);
305
+ // Generate SDKs for each language
306
+ for (const language of languagesToGenerate) {
307
+ const langStart = Date.now();
308
+ const langConfig = config.languages[language];
309
+ const outputPath = langConfig?.output
310
+ ? path_1.default.resolve(projectRoot, langConfig.output)
311
+ : path_1.default.join(baseOutputDir, language);
312
+ try {
313
+ if (options.preview) {
314
+ // Preview mode - just report what would be generated
315
+ results.push({
316
+ language,
317
+ success: true,
318
+ outputPath,
319
+ duration: Date.now() - langStart,
320
+ });
321
+ continue;
322
+ }
323
+ // Ensure output directory exists
324
+ await fs_extra_1.default.ensureDir(outputPath);
325
+ // Generate SDK based on generator type
326
+ const generator = GENERATORS.find((g) => g.language === language);
327
+ if (generator?.native) {
328
+ await generateNativeSDK(language, specPath, outputPath, config, langConfig);
329
+ }
330
+ else if (generator?.generatorName) {
331
+ await generateOpenAPIGeneratorSDK(generator.generatorName, specPath, outputPath, config, langConfig);
332
+ }
333
+ else {
334
+ throw new Error(`No generator found for ${language}`);
335
+ }
336
+ results.push({
337
+ language,
338
+ success: true,
339
+ outputPath,
340
+ duration: Date.now() - langStart,
341
+ });
342
+ }
343
+ catch (err) {
344
+ results.push({
345
+ language,
346
+ success: false,
347
+ outputPath,
348
+ error: err instanceof Error ? err.message : String(err),
349
+ duration: Date.now() - langStart,
350
+ });
351
+ }
352
+ }
353
+ return {
354
+ results,
355
+ successCount: results.filter((r) => r.success).length,
356
+ failureCount: results.filter((r) => !r.success).length,
357
+ totalDuration: Date.now() - startTime,
358
+ };
359
+ }
360
+ /**
361
+ * Generate SDK using native generator (TypeScript, Python, Go)
362
+ */
363
+ async function generateNativeSDK(language, specPath, outputPath, config, langConfig) {
364
+ const packageName = langConfig?.packageName || getDefaultPackageName(config.packageName, language);
365
+ switch (language) {
366
+ case 'typescript':
367
+ await generateTypeScriptSDK(specPath, outputPath, packageName);
368
+ break;
369
+ case 'python':
370
+ await generatePythonSDK(specPath, outputPath, packageName);
371
+ break;
372
+ case 'go':
373
+ await generateGoSDK(specPath, outputPath, packageName);
374
+ break;
375
+ default:
376
+ throw new Error(`Native generator not implemented for ${language}`);
377
+ }
378
+ }
379
+ /**
380
+ * Generate SDK using OpenAPI Generator (Java-based)
381
+ */
382
+ async function generateOpenAPIGeneratorSDK(generatorName, specPath, outputPath, config, langConfig) {
383
+ // Check if Java is available
384
+ try {
385
+ await execAsync('java -version');
386
+ }
387
+ catch {
388
+ throw new Error('Java is required for this generator. Please install Java 11 or later.');
389
+ }
390
+ // Check if openapi-generator is available
391
+ let generatorCmd = 'openapi-generator';
392
+ try {
393
+ await execAsync('openapi-generator version');
394
+ }
395
+ catch {
396
+ // Try npx fallback
397
+ generatorCmd = 'npx @openapitools/openapi-generator-cli';
398
+ }
399
+ const additionalProps = langConfig?.additionalOptions
400
+ ? Object.entries(langConfig.additionalOptions)
401
+ .map(([k, v]) => `${k}=${v}`)
402
+ .join(',')
403
+ : '';
404
+ const cmd = [
405
+ generatorCmd,
406
+ 'generate',
407
+ '-i',
408
+ specPath,
409
+ '-g',
410
+ generatorName,
411
+ '-o',
412
+ outputPath,
413
+ additionalProps ? `--additional-properties=${additionalProps}` : '',
414
+ ]
415
+ .filter(Boolean)
416
+ .join(' ');
417
+ await execAsync(cmd);
418
+ }
419
+ // ============================================================================
420
+ // Native Generator Implementations
421
+ // ============================================================================
422
+ /**
423
+ * Generate TypeScript SDK
424
+ */
425
+ async function generateTypeScriptSDK(specPath, outputPath, packageName) {
426
+ // Read the OpenAPI spec
427
+ const content = await fs_extra_1.default.readFile(specPath, 'utf-8');
428
+ let spec;
429
+ if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
430
+ const yaml = await Promise.resolve().then(() => __importStar(require('js-yaml')));
431
+ spec = yaml.load(content);
432
+ }
433
+ else {
434
+ spec = JSON.parse(content);
435
+ }
436
+ const info = (spec.info || {});
437
+ const paths = (spec.paths || {});
438
+ // Generate package.json
439
+ const packageJson = {
440
+ name: packageName,
441
+ version: info.version || '1.0.0',
442
+ description: info.description || 'Generated SDK',
443
+ main: 'dist/index.js',
444
+ types: 'dist/index.d.ts',
445
+ scripts: {
446
+ build: 'tsc',
447
+ prepublishOnly: 'npm run build',
448
+ },
449
+ devDependencies: {
450
+ typescript: '^5.0.0',
451
+ '@types/node': '^20.0.0',
452
+ },
453
+ };
454
+ await fs_extra_1.default.writeJson(path_1.default.join(outputPath, 'package.json'), packageJson, { spaces: 2 });
455
+ // Generate tsconfig.json
456
+ const tsConfig = {
457
+ compilerOptions: {
458
+ target: 'ES2020',
459
+ module: 'commonjs',
460
+ declaration: true,
461
+ outDir: './dist',
462
+ strict: true,
463
+ esModuleInterop: true,
464
+ skipLibCheck: true,
465
+ forceConsistentCasingInFileNames: true,
466
+ },
467
+ include: ['src/**/*'],
468
+ exclude: ['node_modules', 'dist'],
469
+ };
470
+ await fs_extra_1.default.writeJson(path_1.default.join(outputPath, 'tsconfig.json'), tsConfig, { spaces: 2 });
471
+ // Generate source files
472
+ await fs_extra_1.default.ensureDir(path_1.default.join(outputPath, 'src'));
473
+ // Generate types
474
+ const typesContent = generateTypeScriptTypes(spec);
475
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'src', 'types.ts'), typesContent);
476
+ // Generate client
477
+ const clientContent = generateTypeScriptClient(spec, paths);
478
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'src', 'client.ts'), clientContent);
479
+ // Generate index
480
+ const indexContent = `export * from './types';\nexport * from './client';\n`;
481
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'src', 'index.ts'), indexContent);
482
+ // Generate README
483
+ const readmeContent = `# ${packageName}
484
+
485
+ Generated TypeScript SDK for ${info.title || 'API'}.
486
+
487
+ ## Installation
488
+
489
+ \`\`\`bash
490
+ npm install ${packageName}
491
+ \`\`\`
492
+
493
+ ## Usage
494
+
495
+ \`\`\`typescript
496
+ import { ApiClient } from '${packageName}';
497
+
498
+ const client = new ApiClient({
499
+ baseUrl: 'https://api.example.com',
500
+ // apiKey: 'your-api-key',
501
+ });
502
+ \`\`\`
503
+ `;
504
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'README.md'), readmeContent);
505
+ }
506
+ function generateTypeScriptTypes(spec) {
507
+ let content = '/**\n * Generated types from OpenAPI specification\n */\n\n';
508
+ const schemas = (spec.components?.schemas || {});
509
+ // If no schemas, export a placeholder to make this a valid module
510
+ if (Object.keys(schemas).length === 0) {
511
+ content += '// No schemas defined in the OpenAPI specification\n';
512
+ content += 'export type ApiResponse<T> = T;\n';
513
+ content += 'export type ApiError = { message: string; code?: number };\n';
514
+ return content;
515
+ }
516
+ for (const [name, schema] of Object.entries(schemas)) {
517
+ content += `export interface ${name} {\n`;
518
+ const properties = schema.properties;
519
+ const required = (schema.required || []);
520
+ if (properties) {
521
+ for (const [propName, propSchema] of Object.entries(properties)) {
522
+ const isRequired = required.includes(propName);
523
+ const tsType = openApiTypeToTs(propSchema);
524
+ content += ` ${propName}${isRequired ? '' : '?'}: ${tsType};\n`;
525
+ }
526
+ }
527
+ content += '}\n\n';
528
+ }
529
+ return content;
530
+ }
531
+ function openApiTypeToTs(schema) {
532
+ const type = schema.type;
533
+ const format = schema.format;
534
+ const ref = schema.$ref;
535
+ if (ref) {
536
+ return ref.split('/').pop() || 'unknown';
537
+ }
538
+ switch (type) {
539
+ case 'string':
540
+ return 'string';
541
+ case 'integer':
542
+ case 'number':
543
+ return 'number';
544
+ case 'boolean':
545
+ return 'boolean';
546
+ case 'array':
547
+ const items = schema.items;
548
+ return `${openApiTypeToTs(items || {})}[]`;
549
+ case 'object':
550
+ return 'Record<string, unknown>';
551
+ default:
552
+ return 'unknown';
553
+ }
554
+ }
555
+ function generateTypeScriptClient(spec, paths) {
556
+ const info = (spec.info || {});
557
+ const servers = (spec.servers || []);
558
+ const defaultBaseUrl = servers[0]?.url || 'https://api.example.com';
559
+ let content = `/**
560
+ * ${info.title || 'API'} Client
561
+ * ${info.description || ''}
562
+ */
563
+
564
+ export interface ClientConfig {
565
+ baseUrl?: string;
566
+ apiKey?: string;
567
+ headers?: Record<string, string>;
568
+ }
569
+
570
+ export class ApiClient {
571
+ private baseUrl: string;
572
+ private headers: Record<string, string>;
573
+
574
+ constructor(config: ClientConfig = {}) {
575
+ this.baseUrl = config.baseUrl || '${defaultBaseUrl}';
576
+ this.headers = {
577
+ 'Content-Type': 'application/json',
578
+ ...config.headers,
579
+ };
580
+
581
+ if (config.apiKey) {
582
+ this.headers['Authorization'] = \`Bearer \${config.apiKey}\`;
583
+ }
584
+ }
585
+
586
+ private async request<T>(
587
+ method: string,
588
+ path: string,
589
+ options: { body?: unknown; query?: Record<string, string> } = {}
590
+ ): Promise<T> {
591
+ let url = \`\${this.baseUrl}\${path}\`;
592
+
593
+ if (options.query) {
594
+ const params = new URLSearchParams(options.query);
595
+ url += \`?\${params.toString()}\`;
596
+ }
597
+
598
+ const response = await fetch(url, {
599
+ method,
600
+ headers: this.headers,
601
+ body: options.body ? JSON.stringify(options.body) : undefined,
602
+ });
603
+
604
+ if (!response.ok) {
605
+ throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
606
+ }
607
+
608
+ return response.json();
609
+ }
610
+ `;
611
+ // Generate methods for each path
612
+ for (const [pathUrl, pathItem] of Object.entries(paths)) {
613
+ const methods = ['get', 'post', 'put', 'patch', 'delete'];
614
+ for (const method of methods) {
615
+ const operation = pathItem[method];
616
+ if (!operation)
617
+ continue;
618
+ const operationId = operation.operationId || `${method}${pathUrl.replace(/[^a-zA-Z0-9]/g, '_')}`;
619
+ const summary = operation.summary || '';
620
+ content += `
621
+ /**
622
+ * ${summary}
623
+ */
624
+ async ${operationId}(): Promise<unknown> {
625
+ return this.request('${method.toUpperCase()}', '${pathUrl}');
626
+ }
627
+ `;
628
+ }
629
+ }
630
+ content += '}\n';
631
+ return content;
632
+ }
633
+ /**
634
+ * Generate Python SDK
635
+ */
636
+ async function generatePythonSDK(specPath, outputPath, packageName) {
637
+ // Read the OpenAPI spec
638
+ const content = await fs_extra_1.default.readFile(specPath, 'utf-8');
639
+ let spec;
640
+ if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
641
+ const yaml = await Promise.resolve().then(() => __importStar(require('js-yaml')));
642
+ spec = yaml.load(content);
643
+ }
644
+ else {
645
+ spec = JSON.parse(content);
646
+ }
647
+ const info = (spec.info || {});
648
+ const servers = (spec.servers || []);
649
+ const defaultBaseUrl = servers[0]?.url || 'https://api.example.com';
650
+ // Create package directory
651
+ const pkgDir = path_1.default.join(outputPath, packageName);
652
+ await fs_extra_1.default.ensureDir(pkgDir);
653
+ // Generate setup.py
654
+ const setupPy = `from setuptools import setup, find_packages
655
+
656
+ setup(
657
+ name="${packageName}",
658
+ version="${info.version || '1.0.0'}",
659
+ description="${info.description || 'Generated SDK'}",
660
+ packages=find_packages(),
661
+ python_requires=">=3.8",
662
+ install_requires=[
663
+ "httpx>=0.24.0",
664
+ ],
665
+ )
666
+ `;
667
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'setup.py'), setupPy);
668
+ // Generate __init__.py
669
+ const initPy = `"""${info.title || 'API'} SDK"""
670
+
671
+ from .client import ApiClient
672
+
673
+ __all__ = ["ApiClient"]
674
+ __version__ = "${info.version || '1.0.0'}"
675
+ `;
676
+ await fs_extra_1.default.writeFile(path_1.default.join(pkgDir, '__init__.py'), initPy);
677
+ // Generate client.py
678
+ const clientPy = `"""API Client"""
679
+
680
+ import httpx
681
+ from typing import Optional, Dict, Any
682
+
683
+
684
+ class ApiClient:
685
+ """${info.title || 'API'} Client"""
686
+
687
+ def __init__(
688
+ self,
689
+ base_url: str = "${defaultBaseUrl}",
690
+ api_key: Optional[str] = None,
691
+ headers: Optional[Dict[str, str]] = None,
692
+ ):
693
+ self.base_url = base_url.rstrip("/")
694
+ self.headers = headers or {}
695
+ self.headers["Content-Type"] = "application/json"
696
+
697
+ if api_key:
698
+ self.headers["Authorization"] = f"Bearer {api_key}"
699
+
700
+ self._client = httpx.Client(headers=self.headers)
701
+
702
+ def _request(
703
+ self,
704
+ method: str,
705
+ path: str,
706
+ params: Optional[Dict[str, Any]] = None,
707
+ json: Optional[Dict[str, Any]] = None,
708
+ ) -> Any:
709
+ url = f"{self.base_url}{path}"
710
+ response = self._client.request(method, url, params=params, json=json)
711
+ response.raise_for_status()
712
+ return response.json()
713
+
714
+ def close(self):
715
+ self._client.close()
716
+
717
+ def __enter__(self):
718
+ return self
719
+
720
+ def __exit__(self, *args):
721
+ self.close()
722
+ `;
723
+ await fs_extra_1.default.writeFile(path_1.default.join(pkgDir, 'client.py'), clientPy);
724
+ // Generate README
725
+ const readme = `# ${packageName}
726
+
727
+ Generated Python SDK for ${info.title || 'API'}.
728
+
729
+ ## Installation
730
+
731
+ \`\`\`bash
732
+ pip install -e .
733
+ \`\`\`
734
+
735
+ ## Usage
736
+
737
+ \`\`\`python
738
+ from ${packageName} import ApiClient
739
+
740
+ client = ApiClient(
741
+ base_url="${defaultBaseUrl}",
742
+ api_key="your-api-key",
743
+ )
744
+ \`\`\`
745
+ `;
746
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'README.md'), readme);
747
+ }
748
+ /**
749
+ * Generate Go SDK
750
+ */
751
+ async function generateGoSDK(specPath, outputPath, packageName) {
752
+ // Read the OpenAPI spec
753
+ const content = await fs_extra_1.default.readFile(specPath, 'utf-8');
754
+ let spec;
755
+ if (specPath.endsWith('.yaml') || specPath.endsWith('.yml')) {
756
+ const yaml = await Promise.resolve().then(() => __importStar(require('js-yaml')));
757
+ spec = yaml.load(content);
758
+ }
759
+ else {
760
+ spec = JSON.parse(content);
761
+ }
762
+ const info = (spec.info || {});
763
+ const servers = (spec.servers || []);
764
+ const defaultBaseUrl = servers[0]?.url || 'https://api.example.com';
765
+ // Generate go.mod
766
+ const goMod = `module ${packageName}
767
+
768
+ go 1.21
769
+ `;
770
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'go.mod'), goMod);
771
+ // Generate client.go
772
+ const clientGo = `// Package ${packageName.split('/').pop()} provides a client for ${info.title || 'the API'}.
773
+ package ${packageName.split('/').pop() || 'sdk'}
774
+
775
+ import (
776
+ \t"bytes"
777
+ \t"encoding/json"
778
+ \t"fmt"
779
+ \t"io"
780
+ \t"net/http"
781
+ )
782
+
783
+ // Client represents an API client.
784
+ type Client struct {
785
+ \tBaseURL string
786
+ \tAPIKey string
787
+ \tHTTPClient *http.Client
788
+ }
789
+
790
+ // NewClient creates a new API client.
791
+ func NewClient(baseURL, apiKey string) *Client {
792
+ \tif baseURL == "" {
793
+ \t\tbaseURL = "${defaultBaseUrl}"
794
+ \t}
795
+ \treturn &Client{
796
+ \t\tBaseURL: baseURL,
797
+ \t\tAPIKey: apiKey,
798
+ \t\tHTTPClient: &http.Client{},
799
+ \t}
800
+ }
801
+
802
+ func (c *Client) doRequest(method, path string, body interface{}) ([]byte, error) {
803
+ \turl := c.BaseURL + path
804
+
805
+ \tvar reqBody io.Reader
806
+ \tif body != nil {
807
+ \t\tjsonBody, err := json.Marshal(body)
808
+ \t\tif err != nil {
809
+ \t\t\treturn nil, fmt.Errorf("failed to marshal request body: %w", err)
810
+ \t\t}
811
+ \t\treqBody = bytes.NewBuffer(jsonBody)
812
+ \t}
813
+
814
+ \treq, err := http.NewRequest(method, url, reqBody)
815
+ \tif err != nil {
816
+ \t\treturn nil, fmt.Errorf("failed to create request: %w", err)
817
+ \t}
818
+
819
+ \treq.Header.Set("Content-Type", "application/json")
820
+ \tif c.APIKey != "" {
821
+ \t\treq.Header.Set("Authorization", "Bearer "+c.APIKey)
822
+ \t}
823
+
824
+ \tresp, err := c.HTTPClient.Do(req)
825
+ \tif err != nil {
826
+ \t\treturn nil, fmt.Errorf("request failed: %w", err)
827
+ \t}
828
+ \tdefer resp.Body.Close()
829
+
830
+ \trespBody, err := io.ReadAll(resp.Body)
831
+ \tif err != nil {
832
+ \t\treturn nil, fmt.Errorf("failed to read response: %w", err)
833
+ \t}
834
+
835
+ \tif resp.StatusCode >= 400 {
836
+ \t\treturn nil, fmt.Errorf("API error %d: %s", resp.StatusCode, string(respBody))
837
+ \t}
838
+
839
+ \treturn respBody, nil
840
+ }
841
+ `;
842
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'client.go'), clientGo);
843
+ // Generate README
844
+ const readme = `# ${packageName}
845
+
846
+ Generated Go SDK for ${info.title || 'API'}.
847
+
848
+ ## Installation
849
+
850
+ \`\`\`bash
851
+ go get ${packageName}
852
+ \`\`\`
853
+
854
+ ## Usage
855
+
856
+ \`\`\`go
857
+ package main
858
+
859
+ import (
860
+ \t"${packageName}"
861
+ )
862
+
863
+ func main() {
864
+ \tclient := ${packageName.split('/').pop()}.NewClient("${defaultBaseUrl}", "your-api-key")
865
+ \t// Use client...
866
+ }
867
+ \`\`\`
868
+ `;
869
+ await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'README.md'), readme);
870
+ }
871
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2RrL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7R0FLRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkpILHNDQWtCQztBQUtELHNDQThCQztBQUtELG9EQUlDO0FBS0QsNENBRUM7QUFLRCw4Q0FHQztBQVNELDBDQUtDO0FBNkNELG9DQWdFQztBQVNELG9DQTZGQztBQXZjRCxnREFBd0I7QUFDeEIsd0RBQTBCO0FBQzFCLGlEQUE0QztBQUM1QywrQkFBaUM7QUFFakMsTUFBTSxTQUFTLEdBQUcsSUFBQSxnQkFBUyxFQUFDLG9CQUFJLENBQUMsQ0FBQztBQXVHbEMsK0VBQStFO0FBQy9FLFlBQVk7QUFDWiwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDVSxRQUFBLG1CQUFtQixHQUFrQjtJQUNoRCxZQUFZO0lBQ1osUUFBUTtJQUNSLElBQUk7SUFDSixNQUFNO0lBQ04sUUFBUTtJQUNSLE1BQU07SUFDTixLQUFLO0lBQ0wsT0FBTztJQUNQLFFBQVE7SUFDUixNQUFNO0NBQ1AsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLEdBQW9CO0lBQ2xDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRTtJQUN4RixFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUU7SUFDaEYsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFO0lBQ3hFLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLE1B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VUFBVSxFQUFFLFdBQVcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2pFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNESyBHZW5lcmF0aW9uIE1vZHVsZVxuICpcbiAqIFRoaXMgbW9kdWxlIHByb3ZpZGVzIGZ1bmN0aW9uYWxpdHkgZm9yIGdlbmVyYXRpbmcgY2xpZW50IFNES3MgZnJvbSBPcGVuQVBJIHNwZWNpZmljYXRpb25zLlxuICogSXQgc3VwcG9ydHMgbXVsdGlwbGUgbGFuZ3VhZ2VzIHVzaW5nIGJvdGggbmF0aXZlIGdlbmVyYXRvcnMgYW5kIE9wZW5BUEkgR2VuZXJhdG9yLlxuICovXG5cbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IGV4ZWMsIHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJztcblxuY29uc3QgZXhlY0FzeW5jID0gcHJvbWlzaWZ5KGV4ZWMpO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUeXBlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFN1cHBvcnRlZCBTREsgbGFuZ3VhZ2VzXG4gKi9cbmV4cG9ydCB0eXBlIFNES0xhbmd1YWdlID1cbiAgfCAndHlwZXNjcmlwdCdcbiAgfCAncHl0aG9uJ1xuICB8ICdnbydcbiAgfCAnamF2YSdcbiAgfCAnY3NoYXJwJ1xuICB8ICdydWJ5J1xuICB8ICdwaHAnXG4gIHwgJ3N3aWZ0J1xuICB8ICdrb3RsaW4nXG4gIHwgJ3J1c3QnO1xuXG4vKipcbiAqIFNESyBjb25maWd1cmF0aW9uIGZpbGUgKHNkay5qc29uKVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNES0NvbmZpZyB7XG4gIG9wZW5hcGk6IHN0cmluZztcbiAgcGFja2FnZU5hbWU6IHN0cmluZztcbiAgb3V0cHV0OiBzdHJpbmc7XG4gIGxhbmd1YWdlczoge1xuICAgIFtrZXkgaW4gU0RLTGFuZ3VhZ2VdPzogTGFuZ3VhZ2VDb25maWc7XG4gIH07XG59XG5cbi8qKlxuICogTGFuZ3VhZ2Utc3BlY2lmaWMgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbmd1YWdlQ29uZmlnIHtcbiAgZW5hYmxlZDogYm9vbGVhbjtcbiAgcGFja2FnZU5hbWU/OiBzdHJpbmc7XG4gIG91dHB1dD86IHN0cmluZztcbiAgYWRkaXRpb25hbE9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufVxuXG4vKipcbiAqIEdlbmVyYXRvciBpbmZvcm1hdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyYXRvckluZm8ge1xuICBsYW5ndWFnZTogU0RLTGFuZ3VhZ2U7XG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIG5hdGl2ZTogYm9vbGVhbjtcbiAgcmVxdWlyZXNKYXZhOiBib29sZWFuO1xuICBnZW5lcmF0b3JOYW1lPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFNESyBnZW5lcmF0aW9uIHJlc3VsdCBmb3IgYSBzaW5nbGUgbGFuZ3VhZ2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTREtHZW5lcmF0aW9uUmVzdWx0IHtcbiAgbGFuZ3VhZ2U6IFNES0xhbmd1YWdlO1xuICBzdWNjZXNzOiBib29sZWFuO1xuICBvdXRwdXRQYXRoOiBzdHJpbmc7XG4gIGVycm9yPzogc3RyaW5nO1xuICBkdXJhdGlvbjogbnVtYmVyO1xufVxuXG4vKipcbiAqIE92ZXJhbGwgU0RLIGdlbmVyYXRpb24gcmVzdWx0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZXJhdGVTREtzUmVzdWx0IHtcbiAgcmVzdWx0czogU0RLR2VuZXJhdGlvblJlc3VsdFtdO1xuICBzdWNjZXNzQ291bnQ6IG51bWJlcjtcbiAgZmFpbHVyZUNvdW50OiBudW1iZXI7XG4gIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbn1cblxuLyoqXG4gKiBWYWxpZGF0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25SZXN1bHQge1xuICB2YWxpZDogYm9vbGVhbjtcbiAgZXJyb3JzOiBzdHJpbmdbXTtcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIFNESyBnZW5lcmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZXJhdGVPcHRpb25zIHtcbiAgbGFuZ3VhZ2U/OiBTREtMYW5ndWFnZTtcbiAgcHJldmlldz86IGJvb2xlYW47XG4gIG91dHB1dERpcj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBTREsgY29uZmlnIGluaXRpYWxpemF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5pdENvbmZpZ09wdGlvbnMge1xuICBvcGVuYXBpOiBzdHJpbmc7XG4gIHBhY2thZ2VOYW1lOiBzdHJpbmc7XG4gIGxhbmd1YWdlczogU0RLTGFuZ3VhZ2VbXTtcbiAgZm9yY2U/OiBib29sZWFuO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb25zdGFudHNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBBbGwgc3VwcG9ydGVkIGxhbmd1YWdlc1xuICovXG5leHBvcnQgY29uc3QgU1VQUE9SVEVEX0xBTkdVQUdFUzogU0RLTGFuZ3VhZ2VbXSA9IFtcbiAgJ3R5cGVzY3JpcHQnLFxuICAncHl0aG9uJyxcbiAgJ2dvJyxcbiAgJ2phdmEnLFxuICAnY3NoYXJwJyxcbiAgJ3J1YnknLFxuICAncGhwJyxcbiAgJ3N3aWZ0JyxcbiAgJ2tvdGxpbicsXG4gICdydXN0Jyxcbl07XG5cbi8qKlxuICogR2VuZXJhdG9yIGluZm9ybWF0aW9uIGZvciBlYWNoIGxhbmd1YWdlXG4gKi9cbmNvbnN0IEdFTkVSQVRPUlM6IEdlbmVyYXRvckluZm9bXSA9IFtcbiAgeyBsYW5ndWFnZTogJ3R5cGVzY3JpcHQnLCBkaXNwbGF5TmFtZTogJ1R5cGVTY3JpcHQnLCBuYXRpdmU6IHRydWUsIHJlcXVpcmVzSmF2YTogZmFsc2UgfSxcbiAgeyBsYW5ndWFnZTogJ3B5dGhvbicsIGRpc3BsYXlOYW1lOiAnUHl0aG9uJywgbmF0aXZlOiB0cnVlLCByZXF1aXJlc0phdmE6IGZhbHNlIH0sXG4gIHsgbGFuZ3VhZ2U6ICdnbycsIGRpc3BsYXlOYW1lOiAnR28nLCBuYXRpdmU6IHRydWUsIHJlcXVpcmVzSmF2YTogZmFsc2UgfSxcbiAgeyBsYW5ndWFnZTogJ2phdmEnLCBkaXNwbGF5TmFtZTogJ0phdmEnLCBuYXRpdmU6IGZhbHNlLCByZXF1aXJlc0phdmE6IHRydWUsIGdlbmVyYXRvck5hbWU6ICdqYXZhJyB9LFxuICB7IGxhbmd1YWdlOiAnY3NoYXJwJywgZGlzcGxheU5hbWU6ICdDIycsIG5hdGl2ZTogZmFsc2UsIHJlcXVpcmVzSmF2YTogdHJ1ZSwgZ2VuZXJhdG9yTmFtZTogJ2NzaGFycCcgfSxcbiAgeyBsYW5ndWFnZTogJ3J1YnknLCBkaXNwbGF5TmFtZTogJ1J1YnknLCBuYXRpdmU6IGZhbHNlLCByZXF1aXJlc0phdmE6IHRydWUsIGdlbmVyYXRvck5hbWU6ICdydWJ5JyB9LFxuICB7IGxhbmd1YWdlOiAncGhwJywgZGlzcGxheU5hbWU6ICdQSFAnLCBuYXRpdmU6IGZhbHNlLCByZXF1aXJlc0phdmE6IHRydWUsIGdlbmVyYXRvck5hbWU6ICdwaHAnIH0sXG4gIHsgbGFuZ3VhZ2U6ICdzd2lmdCcsIGRpc3BsYXlOYW1lOiAnU3dpZnQnLCBuYXRpdmU6IGZhbHNlLCByZXF1aXJlc0phdmE6IHRydWUsIGdlbmVyYXRvck5hbWU6ICdzd2lmdDUnIH0sXG4gIHsgbGFuZ3VhZ2U6ICdrb3RsaW4nLCBkaXNwbGF5TmFtZTogJ0tvdGxpbicsIG5hdGl2ZTogZmFsc2UsIHJlcXVpcmVzSmF2YTogdHJ1ZSwgZ2VuZXJhdG9yTmFtZTogJ2tvdGxpbicgfSxcbiAgeyBsYW5ndWFnZTogJ3J1c3QnLCBkaXNwbGF5TmFtZTogJ1J1c3QnLCBuYXRpdmU6IGZhbHNlLCByZXF1aXJlc0phdmE6IHRydWUsIGdlbmVyYXRvck5hbWU6ICdydXN0JyB9LFxuXTtcblxuY29uc3QgQ09ORklHX0ZJTEVOQU1FID0gJ3Nkay5qc29uJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ29uZmlndXJhdGlvbiBGdW5jdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBMb2FkIFNESyBjb25maWd1cmF0aW9uIGZyb20gcHJvamVjdCBkaXJlY3RvcnlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRTREtDb25maWcoXG4gIHByb2plY3RSb290OiBzdHJpbmdcbik6IFByb21pc2U8eyBjb25maWc6IFNES0NvbmZpZyB8IG51bGw7IGVycm9yPzogc3RyaW5nIH0+IHtcbiAgY29uc3QgY29uZmlnUGF0aCA9IHBhdGguam9pbihwcm9qZWN0Um9vdCwgQ09ORklHX0ZJTEVOQU1FKTtcblxuICBpZiAoIShhd2FpdCBmcy5wYXRoRXhpc3RzKGNvbmZpZ1BhdGgpKSkge1xuICAgIHJldHVybiB7IGNvbmZpZzogbnVsbCwgZXJyb3I6IGAke0NPTkZJR19GSUxFTkFNRX0gbm90IGZvdW5kYCB9O1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjb25maWcgPSBhd2FpdCBmcy5yZWFkSnNvbihjb25maWdQYXRoKTtcbiAgICByZXR1cm4geyBjb25maWcgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29uZmlnOiBudWxsLFxuICAgICAgZXJyb3I6IGBGYWlsZWQgdG8gcGFyc2UgJHtDT05GSUdfRklMRU5BTUV9OiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gLFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIFNESyBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbml0U0RLQ29uZmlnKFxuICBwcm9qZWN0Um9vdDogc3RyaW5nLFxuICBvcHRpb25zOiBJbml0Q29uZmlnT3B0aW9uc1xuKTogUHJvbWlzZTx7IGNvbmZpZ1BhdGg6IHN0cmluZzsgY29uZmlnOiBTREtDb25maWcgfT4ge1xuICBjb25zdCBjb25maWdQYXRoID0gcGF0aC5qb2luKHByb2plY3RSb290LCBDT05GSUdfRklMRU5BTUUpO1xuXG4gIC8vIENoZWNrIGlmIGNvbmZpZyBhbHJlYWR5IGV4aXN0c1xuICBpZiAoKGF3YWl0IGZzLnBhdGhFeGlzdHMoY29uZmlnUGF0aCkpICYmICFvcHRpb25zLmZvcmNlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke0NPTkZJR19GSUxFTkFNRX0gYWxyZWFkeSBleGlzdHMuIFVzZSAtLWZvcmNlIHRvIG92ZXJ3cml0ZS5gKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBsYW5ndWFnZSBjb25maWd1cmF0aW9uc1xuICBjb25zdCBsYW5ndWFnZXM6IFNES0NvbmZpZ1snbGFuZ3VhZ2VzJ10gPSB7fTtcbiAgZm9yIChjb25zdCBsYW5nIG9mIG9wdGlvbnMubGFuZ3VhZ2VzKSB7XG4gICAgbGFuZ3VhZ2VzW2xhbmddID0ge1xuICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgIHBhY2thZ2VOYW1lOiBnZXREZWZhdWx0UGFja2FnZU5hbWUob3B0aW9ucy5wYWNrYWdlTmFtZSwgbGFuZyksXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IGNvbmZpZzogU0RLQ29uZmlnID0ge1xuICAgIG9wZW5hcGk6IG9wdGlvbnMub3BlbmFwaSxcbiAgICBwYWNrYWdlTmFtZTogb3B0aW9ucy5wYWNrYWdlTmFtZSxcbiAgICBvdXRwdXQ6ICcuL3Nka3MnLFxuICAgIGxhbmd1YWdlcyxcbiAgfTtcblxuICBhd2FpdCBmcy53cml0ZUpzb24oY29uZmlnUGF0aCwgY29uZmlnLCB7IHNwYWNlczogMiB9KTtcblxuICByZXR1cm4geyBjb25maWdQYXRoLCBjb25maWcgfTtcbn1cblxuLyoqXG4gKiBHZXQgZW5hYmxlZCBnZW5lcmF0b3JzIGZyb20gY29uZmlnXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbmFibGVkR2VuZXJhdG9ycyhjb25maWc6IFNES0NvbmZpZyk6IFNES0xhbmd1YWdlW10ge1xuICByZXR1cm4gT2JqZWN0LmVudHJpZXMoY29uZmlnLmxhbmd1YWdlcylcbiAgICAuZmlsdGVyKChbLCBsYW5nQ29uZmlnXSkgPT4gbGFuZ0NvbmZpZz8uZW5hYmxlZClcbiAgICAubWFwKChbbGFuZ10pID0+IGxhbmcgYXMgU0RLTGFuZ3VhZ2UpO1xufVxuXG4vKipcbiAqIEdldCBnZW5lcmF0b3IgaW5mb3JtYXRpb24gZm9yIGFsbCBsYW5ndWFnZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdlbmVyYXRvckluZm8oKTogR2VuZXJhdG9ySW5mb1tdIHtcbiAgcmV0dXJuIFsuLi5HRU5FUkFUT1JTXTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhIGdlbmVyYXRvciBpcyBuYXRpdmUgKGRvZXNuJ3QgcmVxdWlyZSBKYXZhKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOYXRpdmVHZW5lcmF0b3IobGFuZ3VhZ2U6IFNES0xhbmd1YWdlKTogYm9vbGVhbiB7XG4gIGNvbnN0IGdlbmVyYXRvciA9IEdFTkVSQVRPUlMuZmluZCgoZykgPT4gZy5sYW5ndWFnZSA9PT0gbGFuZ3VhZ2UpO1xuICByZXR1cm4gZ2VuZXJhdG9yPy5uYXRpdmUgPz8gZmFsc2U7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFBhdGggVXRpbGl0aWVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogUmVzb2x2ZSBPcGVuQVBJIHNwZWMgcGF0aCByZWxhdGl2ZSB0byBwcm9qZWN0IHJvb3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTcGVjUGF0aChwcm9qZWN0Um9vdDogc3RyaW5nLCBzcGVjUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHBhdGguaXNBYnNvbHV0ZShzcGVjUGF0aCkpIHtcbiAgICByZXR1cm4gc3BlY1BhdGg7XG4gIH1cbiAgcmV0dXJuIHBhdGgucmVzb2x2ZShwcm9qZWN0Um9vdCwgc3BlY1BhdGgpO1xufVxuXG4vKipcbiAqIEdldCBkZWZhdWx0IHBhY2thZ2UgbmFtZSBmb3IgYSBsYW5ndWFnZVxuICovXG5mdW5jdGlvbiBnZXREZWZhdWx0UGFja2FnZU5hbWUoYmFzZU5hbWU6IHN0cmluZywgbGFuZ3VhZ2U6IFNES0xhbmd1YWdlKTogc3RyaW5nIHtcbiAgY29uc3Qgc2FuaXRpemVkID0gYmFzZU5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bXmEtejAtOV0vZywgJy0nKTtcblxuICBzd2l0Y2ggKGxhbmd1YWdlKSB7XG4gICAgY2FzZSAndHlwZXNjcmlwdCc6XG4gICAgICByZXR1cm4gYEAke3Nhbml0aXplZH0vc2RrYDtcbiAgICBjYXNlICdweXRob24nOlxuICAgICAgcmV0dXJuIHNhbml0aXplZC5yZXBsYWNlKC8tL2csICdfJyk7XG4gICAgY2FzZSAnZ28nOlxuICAgICAgcmV0dXJuIHNhbml0aXplZDtcbiAgICBjYXNlICdqYXZhJzpcbiAgICAgIHJldHVybiBgY29tLiR7c2FuaXRpemVkLnJlcGxhY2UoLy0vZywgJy4nKX1gO1xuICAgIGNhc2UgJ2NzaGFycCc6XG4gICAgICByZXR1cm4gc2FuaXRpemVkLnNwbGl0KCctJykubWFwKGNhcGl0YWxpemUpLmpvaW4oJy4nKTtcbiAgICBjYXNlICdydWJ5JzpcbiAgICAgIHJldHVybiBzYW5pdGl6ZWQucmVwbGFjZSgvLS9nLCAnXycpO1xuICAgIGNhc2UgJ3BocCc6XG4gICAgICByZXR1cm4gc2FuaXRpemVkLnNwbGl0KCctJykubWFwKGNhcGl0YWxpemUpLmpvaW4oJ1xcXFwnKTtcbiAgICBjYXNlICdzd2lmdCc6XG4gICAgICByZXR1cm4gc2FuaXRpemVkLnNwbGl0KCctJykubWFwKGNhcGl0YWxpemUpLmpvaW4oJycpO1xuICAgIGNhc2UgJ2tvdGxpbic6XG4gICAgICByZXR1cm4gYGNvbS4ke3Nhbml0aXplZC5yZXBsYWNlKC8tL2csICcuJyl9YDtcbiAgICBjYXNlICdydXN0JzpcbiAgICAgIHJldHVybiBzYW5pdGl6ZWQucmVwbGFjZSgvLS9nLCAnXycpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc2FuaXRpemVkO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gc3RyLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyLnNsaWNlKDEpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBWYWxpZGF0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogVmFsaWRhdGUgYW4gT3BlbkFQSSBzcGVjaWZpY2F0aW9uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2YWxpZGF0ZVNwZWMoc3BlY1BhdGg6IHN0cmluZyk6IFByb21pc2U8VmFsaWRhdGlvblJlc3VsdD4ge1xuICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIENoZWNrIGZpbGUgZXhpc3RzXG4gIGlmICghKGF3YWl0IGZzLnBhdGhFeGlzdHMoc3BlY1BhdGgpKSkge1xuICAgIHJldHVybiB7XG4gICAgICB2YWxpZDogZmFsc2UsXG4gICAgICBlcnJvcnM6IFtgT3BlbkFQSSBzcGVjaWZpY2F0aW9uIG5vdCBmb3VuZDogJHtzcGVjUGF0aH1gXSxcbiAgICAgIHdhcm5pbmdzOiBbXSxcbiAgICB9O1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBSZWFkIGFuZCBwYXJzZSB0aGUgc3BlY1xuICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShzcGVjUGF0aCwgJ3V0Zi04Jyk7XG4gICAgbGV0IHNwZWM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgaWYgKHNwZWNQYXRoLmVuZHNXaXRoKCcueWFtbCcpIHx8IHNwZWNQYXRoLmVuZHNXaXRoKCcueW1sJykpIHtcbiAgICAgIGNvbnN0IHlhbWwgPSBhd2FpdCBpbXBvcnQoJ2pzLXlhbWwnKTtcbiAgICAgIHNwZWMgPSB5YW1sLmxvYWQoY29udGVudCkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwZWMgPSBKU09OLnBhcnNlKGNvbnRlbnQpO1xuICAgIH1cblxuICAgIC8vIEJhc2ljIHZhbGlkYXRpb25cbiAgICBpZiAoIXNwZWMub3BlbmFwaSAmJiAhc3BlYy5zd2FnZ2VyKSB7XG4gICAgICBlcnJvcnMucHVzaCgnTWlzc2luZyBcIm9wZW5hcGlcIiBvciBcInN3YWdnZXJcIiB2ZXJzaW9uIGZpZWxkJyk7XG4gICAgfVxuXG4gICAgaWYgKCFzcGVjLmluZm8pIHtcbiAgICAgIGVycm9ycy5wdXNoKCdNaXNzaW5nIFwiaW5mb1wiIHNlY3Rpb24nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaW5mbyA9IHNwZWMuaW5mbyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGlmICghaW5mby50aXRsZSkge1xuICAgICAgICB3YXJuaW5ncy5wdXNoKCdNaXNzaW5nIFwiaW5mby50aXRsZVwiJyk7XG4gICAgICB9XG4gICAgICBpZiAoIWluZm8udmVyc2lvbikge1xuICAgICAgICB3YXJuaW5ncy5wdXNoKCdNaXNzaW5nIFwiaW5mby52ZXJzaW9uXCInKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXNwZWMucGF0aHMgfHwgT2JqZWN0LmtleXMoc3BlYy5wYXRocyBhcyBvYmplY3QpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgd2FybmluZ3MucHVzaCgnTm8gcGF0aHMgZGVmaW5lZCBpbiBzcGVjaWZpY2F0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGNvbW1vbiBpc3N1ZXNcbiAgICBjb25zdCBvcGVuYXBpVmVyc2lvbiA9IHNwZWMub3BlbmFwaSBhcyBzdHJpbmc7XG4gICAgaWYgKG9wZW5hcGlWZXJzaW9uICYmICFvcGVuYXBpVmVyc2lvbi5zdGFydHNXaXRoKCczLicpKSB7XG4gICAgICB3YXJuaW5ncy5wdXNoKGBPcGVuQVBJICR7b3BlbmFwaVZlcnNpb259IGRldGVjdGVkLiBWZXJzaW9uIDMueCBpcyByZWNvbW1lbmRlZC5gKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsXG4gICAgICBlcnJvcnMsXG4gICAgICB3YXJuaW5ncyxcbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiB7XG4gICAgICB2YWxpZDogZmFsc2UsXG4gICAgICBlcnJvcnM6IFtgRmFpbGVkIHRvIHBhcnNlIHNwZWNpZmljYXRpb246ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWBdLFxuICAgICAgd2FybmluZ3M6IFtdLFxuICAgIH07XG4gIH1cbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gU0RLIEdlbmVyYXRpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZW5lcmF0ZSBTREtzIGZvciBjb25maWd1cmVkIGxhbmd1YWdlc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVTREtzKFxuICBwcm9qZWN0Um9vdDogc3RyaW5nLFxuICBvcHRpb25zOiBHZW5lcmF0ZU9wdGlvbnMgPSB7fVxuKTogUHJvbWlzZTxHZW5lcmF0ZVNES3NSZXN1bHQ+IHtcbiAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgcmVzdWx0czogU0RLR2VuZXJhdGlvblJlc3VsdFtdID0gW107XG5cbiAgLy8gTG9hZCBjb25maWdcbiAgY29uc3QgeyBjb25maWcsIGVycm9yIH0gPSBhd2FpdCBsb2FkU0RLQ29uZmlnKHByb2plY3RSb290KTtcbiAgaWYgKCFjb25maWcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IgfHwgJ1NESyBjb25maWd1cmF0aW9uIG5vdCBmb3VuZCcpO1xuICB9XG5cbiAgLy8gRGV0ZXJtaW5lIHdoaWNoIGxhbmd1YWdlcyB0byBnZW5lcmF0ZVxuICBsZXQgbGFuZ3VhZ2VzVG9HZW5lcmF0ZSA9IGdldEVuYWJsZWRHZW5lcmF0b3JzKGNvbmZpZyk7XG5cbiAgaWYgKG9wdGlvbnMubGFuZ3VhZ2UpIHtcbiAgICBpZiAoIWxhbmd1YWdlc1RvR2VuZXJhdGUuaW5jbHVkZXMob3B0aW9ucy5sYW5ndWFnZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTGFuZ3VhZ2UgXCIke29wdGlvbnMubGFuZ3VhZ2V9XCIgaXMgbm90IGVuYWJsZWQgaW4gc2RrLmpzb25gKTtcbiAgICB9XG4gICAgbGFuZ3VhZ2VzVG9HZW5lcmF0ZSA9IFtvcHRpb25zLmxhbmd1YWdlXTtcbiAgfVxuXG4gIC8vIFJlc29sdmUgc3BlYyBwYXRoXG4gIGNvbnN0IHNwZWNQYXRoID0gcmVzb2x2ZVNwZWNQYXRoKHByb2plY3RSb290LCBjb25maWcub3BlbmFwaSk7XG5cbiAgLy8gVmFsaWRhdGUgc3BlYyBleGlzdHNcbiAgaWYgKCEoYXdhaXQgZnMucGF0aEV4aXN0cyhzcGVjUGF0aCkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBPcGVuQVBJIHNwZWNpZmljYXRpb24gbm90IGZvdW5kOiAke2NvbmZpZy5vcGVuYXBpfWApO1xuICB9XG5cbiAgLy8gQmFzZSBvdXRwdXQgZGlyZWN0b3J5XG4gIGNvbnN0IGJhc2VPdXRwdXREaXIgPSBvcHRpb25zLm91dHB1dERpclxuICAgID8gcGF0aC5yZXNvbHZlKHByb2plY3RSb290LCBvcHRpb25zLm91dHB1dERpcilcbiAgICA6IHBhdGgucmVzb2x2ZShwcm9qZWN0Um9vdCwgY29uZmlnLm91dHB1dCk7XG5cbiAgLy8gR2VuZXJhdGUgU0RLcyBmb3IgZWFjaCBsYW5ndWFnZVxuICBmb3IgKGNvbnN0IGxhbmd1YWdlIG9mIGxhbmd1YWdlc1RvR2VuZXJhdGUpIHtcbiAgICBjb25zdCBsYW5nU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGxhbmdDb25maWcgPSBjb25maWcubGFuZ3VhZ2VzW2xhbmd1YWdlXTtcbiAgICBjb25zdCBvdXRwdXRQYXRoID0gbGFuZ0NvbmZpZz8ub3V0cHV0XG4gICAgICA/IHBhdGgucmVzb2x2ZShwcm9qZWN0Um9vdCwgbGFuZ0NvbmZpZy5vdXRwdXQpXG4gICAgICA6IHBhdGguam9pbihiYXNlT3V0cHV0RGlyLCBsYW5ndWFnZSk7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKG9wdGlvbnMucHJldmlldykge1xuICAgICAgICAvLyBQcmV2aWV3IG1vZGUgLSBqdXN0IHJlcG9ydCB3aGF0IHdvdWxkIGJlIGdlbmVyYXRlZFxuICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgIGxhbmd1YWdlLFxuICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgb3V0cHV0UGF0aCxcbiAgICAgICAgICBkdXJhdGlvbjogRGF0ZS5ub3coKSAtIGxhbmdTdGFydCxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBFbnN1cmUgb3V0cHV0IGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGF3YWl0IGZzLmVuc3VyZURpcihvdXRwdXRQYXRoKTtcblxuICAgICAgLy8gR2VuZXJhdGUgU0RLIGJhc2VkIG9uIGdlbmVyYXRvciB0eXBlXG4gICAgICBjb25zdCBnZW5lcmF0b3IgPSBHRU5FUkFUT1JTLmZpbmQoKGcpID0+IGcubGFuZ3VhZ2UgPT09IGxhbmd1YWdlKTtcblxuICAgICAgaWYgKGdlbmVyYXRvcj8ubmF0aXZlKSB7XG4gICAgICAgIGF3YWl0IGdlbmVyYXRlTmF0aXZlU0RLKGxhbmd1YWdlLCBzcGVjUGF0aCwgb3V0cHV0UGF0aCwgY29uZmlnLCBsYW5nQ29uZmlnKTtcbiAgICAgIH0gZWxzZSBpZiAoZ2VuZXJhdG9yPy5nZW5lcmF0b3JOYW1lKSB7XG4gICAgICAgIGF3YWl0IGdlbmVyYXRlT3BlbkFQSUdlbmVyYXRvclNESyhnZW5lcmF0b3IuZ2VuZXJhdG9yTmFtZSwgc3BlY1BhdGgsIG91dHB1dFBhdGgsIGNvbmZpZywgbGFuZ0NvbmZpZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGdlbmVyYXRvciBmb3VuZCBmb3IgJHtsYW5ndWFnZX1gKTtcbiAgICAgIH1cblxuICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgbGFuZ3VhZ2UsXG4gICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgIG91dHB1dFBhdGgsXG4gICAgICAgIGR1cmF0aW9uOiBEYXRlLm5vdygpIC0gbGFuZ1N0YXJ0LFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICBsYW5ndWFnZSxcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIG91dHB1dFBhdGgsXG4gICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgIGR1cmF0aW9uOiBEYXRlLm5vdygpIC0gbGFuZ1N0YXJ0LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICByZXN1bHRzLFxuICAgIHN1Y2Nlc3NDb3VudDogcmVzdWx0cy5maWx0ZXIoKHIpID0+IHIuc3VjY2VzcykubGVuZ3RoLFxuICAgIGZhaWx1cmVDb3VudDogcmVzdWx0cy5maWx0ZXIoKHIpID0+ICFyLnN1Y2Nlc3MpLmxlbmd0aCxcbiAgICB0b3RhbER1cmF0aW9uOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICB9O1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIFNESyB1c2luZyBuYXRpdmUgZ2VuZXJhdG9yIChUeXBlU2NyaXB0LCBQeXRob24sIEdvKVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZU5hdGl2ZVNESyhcbiAgbGFuZ3VhZ2U6IFNES0xhbmd1YWdlLFxuICBzcGVjUGF0aDogc3RyaW5nLFxuICBvdXRwdXRQYXRoOiBzdHJpbmcsXG4gIGNvbmZpZzogU0RLQ29uZmlnLFxuICBsYW5nQ29uZmlnPzogTGFuZ3VhZ2VDb25maWdcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwYWNrYWdlTmFtZSA9IGxhbmdDb25maWc/LnBhY2thZ2VOYW1lIHx8IGdldERlZmF1bHRQYWNrYWdlTmFtZShjb25maWcucGFja2FnZU5hbWUsIGxhbmd1YWdlKTtcblxuICBzd2l0Y2ggKGxhbmd1YWdlKSB7XG4gICAgY2FzZSAndHlwZXNjcmlwdCc6XG4gICAgICBhd2FpdCBnZW5lcmF0ZVR5cGVTY3JpcHRTREsoc3BlY1BhdGgsIG91dHB1dFBhdGgsIHBhY2thZ2VOYW1lKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3B5dGhvbic6XG4gICAgICBhd2FpdCBnZW5lcmF0ZVB5dGhvblNESyhzcGVjUGF0aCwgb3V0cHV0UGF0aCwgcGFja2FnZU5hbWUpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZ28nOlxuICAgICAgYXdhaXQgZ2VuZXJhdGVHb1NESyhzcGVjUGF0aCwgb3V0cHV0UGF0aCwgcGFja2FnZU5hbWUpO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTmF0aXZlIGdlbmVyYXRvciBub3QgaW1wbGVtZW50ZWQgZm9yICR7bGFuZ3VhZ2V9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBTREsgdXNpbmcgT3BlbkFQSSBHZW5lcmF0b3IgKEphdmEtYmFzZWQpXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlT3BlbkFQSUdlbmVyYXRvclNESyhcbiAgZ2VuZXJhdG9yTmFtZTogc3RyaW5nLFxuICBzcGVjUGF0aDogc3RyaW5nLFxuICBvdXRwdXRQYXRoOiBzdHJpbmcsXG4gIGNvbmZpZzogU0RLQ29uZmlnLFxuICBsYW5nQ29uZmlnPzogTGFuZ3VhZ2VDb25maWdcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBDaGVjayBpZiBKYXZhIGlzIGF2YWlsYWJsZVxuICB0cnkge1xuICAgIGF3YWl0IGV4ZWNBc3luYygnamF2YSAtdmVyc2lvbicpO1xuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0phdmEgaXMgcmVxdWlyZWQgZm9yIHRoaXMgZ2VuZXJhdG9yLiBQbGVhc2UgaW5zdGFsbCBKYXZhIDExIG9yIGxhdGVyLicpO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgb3BlbmFwaS1nZW5lcmF0b3IgaXMgYXZhaWxhYmxlXG4gIGxldCBnZW5lcmF0b3JDbWQgPSAnb3BlbmFwaS1nZW5lcmF0b3InO1xuICB0cnkge1xuICAgIGF3YWl0IGV4ZWNBc3luYygnb3BlbmFwaS1nZW5lcmF0b3IgdmVyc2lvbicpO1xuICB9IGNhdGNoIHtcbiAgICAvLyBUcnkgbnB4IGZhbGxiYWNrXG4gICAgZ2VuZXJhdG9yQ21kID0gJ25weCBAb3BlbmFwaXRvb2xzL29wZW5hcGktZ2VuZXJhdG9yLWNsaSc7XG4gIH1cblxuICBjb25zdCBhZGRpdGlvbmFsUHJvcHMgPSBsYW5nQ29uZmlnPy5hZGRpdGlvbmFsT3B0aW9uc1xuICAgID8gT2JqZWN0LmVudHJpZXMobGFuZ0NvbmZpZy5hZGRpdGlvbmFsT3B0aW9ucylcbiAgICAgICAgLm1hcCgoW2ssIHZdKSA9PiBgJHtrfT0ke3Z9YClcbiAgICAgICAgLmpvaW4oJywnKVxuICAgIDogJyc7XG5cbiAgY29uc3QgY21kID0gW1xuICAgIGdlbmVyYXRvckNtZCxcbiAgICAnZ2VuZXJhdGUnLFxuICAgICctaScsXG4gICAgc3BlY1BhdGgsXG4gICAgJy1nJyxcbiAgICBnZW5lcmF0b3JOYW1lLFxuICAgICctbycsXG4gICAgb3V0cHV0UGF0aCxcbiAgICBhZGRpdGlvbmFsUHJvcHMgPyBgLS1hZGRpdGlvbmFsLXByb3BlcnRpZXM9JHthZGRpdGlvbmFsUHJvcHN9YCA6ICcnLFxuICBdXG4gICAgLmZpbHRlcihCb29sZWFuKVxuICAgIC5qb2luKCcgJyk7XG5cbiAgYXdhaXQgZXhlY0FzeW5jKGNtZCk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIE5hdGl2ZSBHZW5lcmF0b3IgSW1wbGVtZW50YXRpb25zXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogR2VuZXJhdGUgVHlwZVNjcmlwdCBTREtcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVUeXBlU2NyaXB0U0RLKFxuICBzcGVjUGF0aDogc3RyaW5nLFxuICBvdXRwdXRQYXRoOiBzdHJpbmcsXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBSZWFkIHRoZSBPcGVuQVBJIHNwZWNcbiAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKHNwZWNQYXRoLCAndXRmLTgnKTtcbiAgbGV0IHNwZWM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gIGlmIChzcGVjUGF0aC5lbmRzV2l0aCgnLnlhbWwnKSB8fCBzcGVjUGF0aC5lbmRzV2l0aCgnLnltbCcpKSB7XG4gICAgY29uc3QgeWFtbCA9IGF3YWl0IGltcG9ydCgnanMteWFtbCcpO1xuICAgIHNwZWMgPSB5YW1sLmxvYWQoY29udGVudCkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH0gZWxzZSB7XG4gICAgc3BlYyA9IEpTT04ucGFyc2UoY29udGVudCk7XG4gIH1cblxuICBjb25zdCBpbmZvID0gKHNwZWMuaW5mbyB8fCB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHBhdGhzID0gKHNwZWMucGF0aHMgfHwge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gIC8vIEdlbmVyYXRlIHBhY2thZ2UuanNvblxuICBjb25zdCBwYWNrYWdlSnNvbiA9IHtcbiAgICBuYW1lOiBwYWNrYWdlTmFtZSxcbiAgICB2ZXJzaW9uOiAoaW5mby52ZXJzaW9uIGFzIHN0cmluZykgfHwgJzEuMC4wJyxcbiAgICBkZXNjcmlwdGlvbjogKGluZm8uZGVzY3JpcHRpb24gYXMgc3RyaW5nKSB8fCAnR2VuZXJhdGVkIFNESycsXG4gICAgbWFpbjogJ2Rpc3QvaW5kZXguanMnLFxuICAgIHR5cGVzOiAnZGlzdC9pbmRleC5kLnRzJyxcbiAgICBzY3JpcHRzOiB7XG4gICAgICBidWlsZDogJ3RzYycsXG4gICAgICBwcmVwdWJsaXNoT25seTogJ25wbSBydW4gYnVpbGQnLFxuICAgIH0sXG4gICAgZGV2RGVwZW5kZW5jaWVzOiB7XG4gICAgICB0eXBlc2NyaXB0OiAnXjUuMC4wJyxcbiAgICAgICdAdHlwZXMvbm9kZSc6ICdeMjAuMC4wJyxcbiAgICB9LFxuICB9O1xuXG4gIGF3YWl0IGZzLndyaXRlSnNvbihwYXRoLmpvaW4ob3V0cHV0UGF0aCwgJ3BhY2thZ2UuanNvbicpLCBwYWNrYWdlSnNvbiwgeyBzcGFjZXM6IDIgfSk7XG5cbiAgLy8gR2VuZXJhdGUgdHNjb25maWcuanNvblxuICBjb25zdCB0c0NvbmZpZyA9IHtcbiAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgIHRhcmdldDogJ0VTMjAyMCcsXG4gICAgICBtb2R1bGU6ICdjb21tb25qcycsXG4gICAgICBkZWNsYXJhdGlvbjogdHJ1ZSxcbiAgICAgIG91dERpcjogJy4vZGlzdCcsXG4gICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICBlc01vZHVsZUludGVyb3A6IHRydWUsXG4gICAgICBza2lwTGliQ2hlY2s6IHRydWUsXG4gICAgICBmb3JjZUNvbnNpc3RlbnRDYXNpbmdJbkZpbGVOYW1lczogdHJ1ZSxcbiAgICB9LFxuICAgIGluY2x1ZGU6IFsnc3JjLyoqLyonXSxcbiAgICBleGNsdWRlOiBbJ25vZGVfbW9kdWxlcycsICdkaXN0J10sXG4gIH07XG5cbiAgYXdhaXQgZnMud3JpdGVKc29uKHBhdGguam9pbihvdXRwdXRQYXRoLCAndHNjb25maWcuanNvbicpLCB0c0NvbmZpZywgeyBzcGFjZXM6IDIgfSk7XG5cbiAgLy8gR2VuZXJhdGUgc291cmNlIGZpbGVzXG4gIGF3YWl0IGZzLmVuc3VyZURpcihwYXRoLmpvaW4ob3V0cHV0UGF0aCwgJ3NyYycpKTtcblxuICAvLyBHZW5lcmF0ZSB0eXBlc1xuICBjb25zdCB0eXBlc0NvbnRlbnQgPSBnZW5lcmF0ZVR5cGVTY3JpcHRUeXBlcyhzcGVjKTtcbiAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGguam9pbihvdXRwdXRQYXRoLCAnc3JjJywgJ3R5cGVzLnRzJyksIHR5cGVzQ29udGVudCk7XG5cbiAgLy8gR2VuZXJhdGUgY2xpZW50XG4gIGNvbnN0IGNsaWVudENvbnRlbnQgPSBnZW5lcmF0ZVR5cGVTY3JpcHRDbGllbnQoc3BlYywgcGF0aHMpO1xuICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKG91dHB1dFBhdGgsICdzcmMnLCAnY2xpZW50LnRzJyksIGNsaWVudENvbnRlbnQpO1xuXG4gIC8vIEdlbmVyYXRlIGluZGV4XG4gIGNvbnN0IGluZGV4Q29udGVudCA9IGBleHBvcnQgKiBmcm9tICcuL3R5cGVzJztcXG5leHBvcnQgKiBmcm9tICcuL2NsaWVudCc7XFxuYDtcbiAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGguam9pbihvdXRwdXRQYXRoLCAnc3JjJywgJ2luZGV4LnRzJyksIGluZGV4Q29udGVudCk7XG5cbiAgLy8gR2VuZXJhdGUgUkVBRE1FXG4gIGNvbnN0IHJlYWRtZUNvbnRlbnQgPSBgIyAke3BhY2thZ2VOYW1lfVxuXG5HZW5lcmF0ZWQgVHlwZVNjcmlwdCBTREsgZm9yICR7KGluZm8udGl0bGUgYXMgc3RyaW5nKSB8fCAnQVBJJ30uXG5cbiMjIEluc3RhbGxhdGlvblxuXG5cXGBcXGBcXGBiYXNoXG5ucG0gaW5zdGFsbCAke3BhY2thZ2VOYW1lfVxuXFxgXFxgXFxgXG5cbiMjIFVzYWdlXG5cblxcYFxcYFxcYHR5cGVzY3JpcHRcbmltcG9ydCB7IEFwaUNsaWVudCB9IGZyb20gJyR7cGFja2FnZU5hbWV9JztcblxuY29uc3QgY2xpZW50ID0gbmV3IEFwaUNsaWVudCh7XG4gIGJhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gIC8vIGFwaUtleTogJ3lvdXItYXBpLWtleScsXG59KTtcblxcYFxcYFxcYFxuYDtcblxuICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKG91dHB1dFBhdGgsICdSRUFETUUubWQnKSwgcmVhZG1lQ29udGVudCk7XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlVHlwZVNjcmlwdFR5cGVzKHNwZWM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogc3RyaW5nIHtcbiAgbGV0IGNvbnRlbnQgPSAnLyoqXFxuICogR2VuZXJhdGVkIHR5cGVzIGZyb20gT3BlbkFQSSBzcGVjaWZpY2F0aW9uXFxuICovXFxuXFxuJztcblxuICBjb25zdCBzY2hlbWFzID0gKChzcGVjLmNvbXBvbmVudHMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5zY2hlbWFzIHx8IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAvLyBJZiBubyBzY2hlbWFzLCBleHBvcnQgYSBwbGFjZWhvbGRlciB0byBtYWtlIHRoaXMgYSB2YWxpZCBtb2R1bGVcbiAgaWYgKE9iamVjdC5rZXlzKHNjaGVtYXMpLmxlbmd0aCA9PT0gMCkge1xuICAgIGNvbnRlbnQgKz0gJy8vIE5vIHNjaGVtYXMgZGVmaW5lZCBpbiB0aGUgT3BlbkFQSSBzcGVjaWZpY2F0aW9uXFxuJztcbiAgICBjb250ZW50ICs9ICdleHBvcnQgdHlwZSBBcGlSZXNwb25zZTxUPiA9IFQ7XFxuJztcbiAgICBjb250ZW50ICs9ICdleHBvcnQgdHlwZSBBcGlFcnJvciA9IHsgbWVzc2FnZTogc3RyaW5nOyBjb2RlPzogbnVtYmVyIH07XFxuJztcbiAgICByZXR1cm4gY29udGVudDtcbiAgfVxuXG4gIGZvciAoY29uc3QgW25hbWUsIHNjaGVtYV0gb2YgT2JqZWN0LmVudHJpZXMoc2NoZW1hcykpIHtcbiAgICBjb250ZW50ICs9IGBleHBvcnQgaW50ZXJmYWNlICR7bmFtZX0ge1xcbmA7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IChzY2hlbWEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLnByb3BlcnRpZXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgcmVxdWlyZWQgPSAoKHNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikucmVxdWlyZWQgfHwgW10pIGFzIHN0cmluZ1tdO1xuXG4gICAgaWYgKHByb3BlcnRpZXMpIHtcbiAgICAgIGZvciAoY29uc3QgW3Byb3BOYW1lLCBwcm9wU2NoZW1hXSBvZiBPYmplY3QuZW50cmllcyhwcm9wZXJ0aWVzKSkge1xuICAgICAgICBjb25zdCBpc1JlcXVpcmVkID0gcmVxdWlyZWQuaW5jbHVkZXMocHJvcE5hbWUpO1xuICAgICAgICBjb25zdCB0c1R5cGUgPSBvcGVuQXBpVHlwZVRvVHMocHJvcFNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgICAgIGNvbnRlbnQgKz0gYCAgJHtwcm9wTmFtZX0ke2lzUmVxdWlyZWQgPyAnJyA6ICc/J306ICR7dHNUeXBlfTtcXG5gO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnRlbnQgKz0gJ31cXG5cXG4nO1xuICB9XG5cbiAgcmV0dXJuIGNvbnRlbnQ7XG59XG5cbmZ1bmN0aW9uIG9wZW5BcGlUeXBlVG9UcyhzY2hlbWE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogc3RyaW5nIHtcbiAgY29uc3QgdHlwZSA9IHNjaGVtYS50eXBlIGFzIHN0cmluZztcbiAgY29uc3QgZm9ybWF0ID0gc2NoZW1hLmZvcm1hdCBhcyBzdHJpbmc7XG4gIGNvbnN0IHJlZiA9IHNjaGVtYS4kcmVmIGFzIHN0cmluZztcblxuICBpZiAocmVmKSB7XG4gICAgcmV0dXJuIHJlZi5zcGxpdCgnLycpLnBvcCgpIHx8ICd1bmtub3duJztcbiAgfVxuXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gJ3N0cmluZyc7XG4gICAgY2FzZSAnaW50ZWdlcic6XG4gICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgIHJldHVybiAnbnVtYmVyJztcbiAgICBjYXNlICdib29sZWFuJzpcbiAgICAgIHJldHVybiAnYm9vbGVhbic7XG4gICAgY2FzZSAnYXJyYXknOlxuICAgICAgY29uc3QgaXRlbXMgPSBzY2hlbWEuaXRlbXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICByZXR1cm4gYCR7b3BlbkFwaVR5cGVUb1RzKGl0ZW1zIHx8IHt9KX1bXWA7XG4gICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgIHJldHVybiAnUmVjb3JkPHN0cmluZywgdW5rbm93bj4nO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gJ3Vua25vd24nO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlVHlwZVNjcmlwdENsaWVudChzcGVjOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgcGF0aHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogc3RyaW5nIHtcbiAgY29uc3QgaW5mbyA9IChzcGVjLmluZm8gfHwge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBzZXJ2ZXJzID0gKHNwZWMuc2VydmVycyB8fCBbXSkgYXMgeyB1cmw6IHN0cmluZyB9W107XG4gIGNvbnN0IGRlZmF1bHRCYXNlVXJsID0gc2VydmVyc1swXT8udXJsIHx8ICdodHRwczovL2FwaS5leGFtcGxlLmNvbSc7XG5cbiAgbGV0IGNvbnRlbnQgPSBgLyoqXG4gKiAkeyhpbmZvLnRpdGxlIGFzIHN0cmluZykgfHwgJ0FQSSd9IENsaWVudFxuICogJHsoaW5mby5kZXNjcmlwdGlvbiBhcyBzdHJpbmcpIHx8ICcnfVxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpZW50Q29uZmlnIHtcbiAgYmFzZVVybD86IHN0cmluZztcbiAgYXBpS2V5Pzogc3RyaW5nO1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cblxuZXhwb3J0IGNsYXNzIEFwaUNsaWVudCB7XG4gIHByaXZhdGUgYmFzZVVybDogc3RyaW5nO1xuICBwcml2YXRlIGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBDbGllbnRDb25maWcgPSB7fSkge1xuICAgIHRoaXMuYmFzZVVybCA9IGNvbmZpZy5iYXNlVXJsIHx8ICcke2RlZmF1bHRCYXNlVXJsfSc7XG4gICAgdGhpcy5oZWFkZXJzID0ge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIC4uLmNvbmZpZy5oZWFkZXJzLFxuICAgIH07XG5cbiAgICBpZiAoY29uZmlnLmFwaUtleSkge1xuICAgICAgdGhpcy5oZWFkZXJzWydBdXRob3JpemF0aW9uJ10gPSBcXGBCZWFyZXIgXFwke2NvbmZpZy5hcGlLZXl9XFxgO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVxdWVzdDxUPihcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgb3B0aW9uczogeyBib2R5PzogdW5rbm93bjsgcXVlcnk/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IH0gPSB7fVxuICApOiBQcm9taXNlPFQ+IHtcbiAgICBsZXQgdXJsID0gXFxgXFwke3RoaXMuYmFzZVVybH1cXCR7cGF0aH1cXGA7XG5cbiAgICBpZiAob3B0aW9ucy5xdWVyeSkge1xuICAgICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyhvcHRpb25zLnF1ZXJ5KTtcbiAgICAgIHVybCArPSBcXGA/XFwke3BhcmFtcy50b1N0cmluZygpfVxcYDtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczogdGhpcy5oZWFkZXJzLFxuICAgICAgYm9keTogb3B0aW9ucy5ib2R5ID8gSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5ib2R5KSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcXGBIVFRQIFxcJHtyZXNwb25zZS5zdGF0dXN9OiBcXCR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1cXGApO1xuICAgIH1cblxuICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gIH1cbmA7XG5cbiAgLy8gR2VuZXJhdGUgbWV0aG9kcyBmb3IgZWFjaCBwYXRoXG4gIGZvciAoY29uc3QgW3BhdGhVcmwsIHBhdGhJdGVtXSBvZiBPYmplY3QuZW50cmllcyhwYXRocykpIHtcbiAgICBjb25zdCBtZXRob2RzID0gWydnZXQnLCAncG9zdCcsICdwdXQnLCAncGF0Y2gnLCAnZGVsZXRlJ10gYXMgY29uc3Q7XG5cbiAgICBmb3IgKGNvbnN0IG1ldGhvZCBvZiBtZXRob2RzKSB7XG4gICAgICBjb25zdCBvcGVyYXRpb24gPSAocGF0aEl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW21ldGhvZF0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoIW9wZXJhdGlvbikgY29udGludWU7XG5cbiAgICAgIGNvbnN0IG9wZXJhdGlvbklkID0gKG9wZXJhdGlvbi5vcGVyYXRpb25JZCBhcyBzdHJpbmcpIHx8IGAke21ldGhvZH0ke3BhdGhVcmwucmVwbGFjZSgvW15hLXpBLVowLTldL2csICdfJyl9YDtcbiAgICAgIGNvbnN0IHN1bW1hcnkgPSAob3BlcmF0aW9uLnN1bW1hcnkgYXMgc3RyaW5nKSB8fCAnJztcblxuICAgICAgY29udGVudCArPSBgXG4gIC8qKlxuICAgKiAke3N1bW1hcnl9XG4gICAqL1xuICBhc3luYyAke29wZXJhdGlvbklkfSgpOiBQcm9taXNlPHVua25vd24+IHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KCcke21ldGhvZC50b1VwcGVyQ2FzZSgpfScsICcke3BhdGhVcmx9Jyk7XG4gIH1cbmA7XG4gICAgfVxuICB9XG5cbiAgY29udGVudCArPSAnfVxcbic7XG5cbiAgcmV0dXJuIGNvbnRlbnQ7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgUHl0aG9uIFNES1xuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZVB5dGhvblNESyhcbiAgc3BlY1BhdGg6IHN0cmluZyxcbiAgb3V0cHV0UGF0aDogc3RyaW5nLFxuICBwYWNrYWdlTmFtZTogc3RyaW5nXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gUmVhZCB0aGUgT3BlbkFQSSBzcGVjXG4gIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShzcGVjUGF0aCwgJ3V0Zi04Jyk7XG4gIGxldCBzcGVjOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICBpZiAoc3BlY1BhdGguZW5kc1dpdGgoJy55YW1sJykgfHwgc3BlY1BhdGguZW5kc1dpdGgoJy55bWwnKSkge1xuICAgIGNvbnN0IHlhbWwgPSBhd2FpdCBpbXBvcnQoJ2pzLXlhbWwnKTtcbiAgICBzcGVjID0geWFtbC5sb2FkKGNvbnRlbnQpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9IGVsc2Uge1xuICAgIHNwZWMgPSBKU09OLnBhcnNlKGNvbnRlbnQpO1xuICB9XG5cbiAgY29uc3QgaW5mbyA9IChzcGVjLmluZm8gfHwge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBzZXJ2ZXJzID0gKHNwZWMuc2VydmVycyB8fCBbXSkgYXMgeyB1cmw6IHN0cmluZyB9W107XG4gIGNvbnN0IGRlZmF1bHRCYXNlVXJsID0gc2VydmVyc1swXT8udXJsIHx8ICdodHRwczovL2FwaS5leGFtcGxlLmNvbSc7XG5cbiAgLy8gQ3JlYXRlIHBhY2thZ2UgZGlyZWN0b3J5XG4gIGNvbnN0IHBrZ0RpciA9IHBhdGguam9pbihvdXRwdXRQYXRoLCBwYWNrYWdlTmFtZSk7XG4gIGF3YWl0IGZzLmVuc3VyZURpcihwa2dEaXIpO1xuXG4gIC8vIEdlbmVyYXRlIHNldHVwLnB5XG4gIGNvbnN0IHNldHVwUHkgPSBgZnJvbSBzZXR1cHRvb2xzIGltcG9ydCBzZXR1cCwgZmluZF9wYWNrYWdlc1xuXG5zZXR1cChcbiAgICBuYW1lPVwiJHtwYWNrYWdlTmFtZX1cIixcbiAgICB2ZXJzaW9uPVwiJHsoaW5mby52ZXJzaW9uIGFzIHN0cmluZykgfHwgJzEuMC4wJ31cIixcbiAgICBkZXNjcmlwdGlvbj1cIiR7KGluZm8uZGVzY3JpcHRpb24gYXMgc3RyaW5nKSB8fCAnR2VuZXJhdGVkIFNESyd9XCIsXG4gICAgcGFja2FnZXM9ZmluZF9wYWNrYWdlcygpLFxuICAgIHB5dGhvbl9yZXF1aXJlcz1cIj49My44XCIsXG4gICAgaW5zdGFsbF9yZXF1aXJlcz1bXG4gICAgICAgIFwiaHR0cHg+PTAuMjQuMFwiLFxuICAgIF0sXG4pXG5gO1xuXG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4ob3V0cHV0UGF0aCwgJ3NldHVwLnB5JyksIHNldHVwUHkpO1xuXG4gIC8vIEdlbmVyYXRlIF9faW5pdF9fLnB5XG4gIGNvbnN0IGluaXRQeSA9IGBcIlwiXCIkeyhpbmZvLnRpdGxlIGFzIHN0cmluZykgfHwgJ0FQSSd9IFNES1wiXCJcIlxuXG5mcm9tIC5jbGllbnQgaW1wb3J0IEFwaUNsaWVudFxuXG5fX2FsbF9fID0gW1wiQXBpQ2xpZW50XCJdXG5fX3ZlcnNpb25fXyA9IFwiJHsoaW5mby52ZXJzaW9uIGFzIHN0cmluZykgfHwgJzEuMC4wJ31cIlxuYDtcblxuICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKHBrZ0RpciwgJ19faW5pdF9fLnB5JyksIGluaXRQeSk7XG5cbiAgLy8gR2VuZXJhdGUgY2xpZW50LnB5XG4gIGNvbnN0IGNsaWVudFB5ID0gYFwiXCJcIkFQSSBDbGllbnRcIlwiXCJcblxuaW1wb3J0IGh0dHB4XG5mcm9tIHR5cGluZyBpbXBvcnQgT3B0aW9uYWwsIERpY3QsIEFueVxuXG5cbmNsYXNzIEFwaUNsaWVudDpcbiAgICBcIlwiXCIkeyhpbmZvLnRpdGxlIGFzIHN0cmluZykgfHwgJ0FQSSd9IENsaWVudFwiXCJcIlxuXG4gICAgZGVmIF9faW5pdF9fKFxuICAgICAgICBzZWxmLFxuICAgICAgICBiYXNlX3VybDogc3RyID0gXCIke2RlZmF1bHRCYXNlVXJsfVwiLFxuICAgICAgICBhcGlfa2V5OiBPcHRpb25hbFtzdHJdID0gTm9uZSxcbiAgICAgICAgaGVhZGVyczogT3B0aW9uYWxbRGljdFtzdHIsIHN0cl1dID0gTm9uZSxcbiAgICApOlxuICAgICAgICBzZWxmLmJhc2VfdXJsID0gYmFzZV91cmwucnN0cmlwKFwiL1wiKVxuICAgICAgICBzZWxmLmhlYWRlcnMgPSBoZWFkZXJzIG9yIHt9XG4gICAgICAgIHNlbGYuaGVhZGVyc1tcIkNvbnRlbnQtVHlwZVwiXSA9IFwiYXBwbGljYXRpb24vanNvblwiXG5cbiAgICAgICAgaWYgYXBpX2tleTpcbiAgICAgICAgICAgIHNlbGYuaGVhZGVyc1tcIkF1dGhvcml6YXRpb25cIl0gPSBmXCJCZWFyZXIge2FwaV9rZXl9XCJcblxuICAgICAgICBzZWxmLl9jbGllbnQgPSBodHRweC5DbGllbnQoaGVhZGVycz1zZWxmLmhlYWRlcnMpXG5cbiAgICBkZWYgX3JlcXVlc3QoXG4gICAgICAgIHNlbGYsXG4gICAgICAgIG1ldGhvZDogc3RyLFxuICAgICAgICBwYXRoOiBzdHIsXG4gICAgICAgIHBhcmFtczogT3B0aW9uYWxbRGljdFtzdHIsIEFueV1dID0gTm9uZSxcbiAgICAgICAganNvbjogT3B0aW9uYWxbRGljdFtzdHIsIEFueV1dID0gTm9uZSxcbiAgICApIC0+IEFueTpcbiAgICAgICAgdXJsID0gZlwie3NlbGYuYmFzZV91cmx9e3BhdGh9XCJcbiAgICAgICAgcmVzcG9uc2UgPSBzZWxmLl9jbGllbnQucmVxdWVzdChtZXRob2QsIHVybCwgcGFyYW1zPXBhcmFtcywganNvbj1qc29uKVxuICAgICAgICByZXNwb25zZS5yYWlzZV9mb3Jfc3RhdHVzKClcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKVxuXG4gICAgZGVmIGNsb3NlKHNlbGYpOlxuICAgICAgICBzZWxmLl9jbGllbnQuY2xvc2UoKVxuXG4gICAgZGVmIF9fZW50ZXJfXyhzZWxmKTpcbiAgICAgICAgcmV0dXJuIHNlbGZcblxuICAgIGRlZiBfX2V4aXRfXyhzZWxmLCAqYXJncyk6XG4gICAgICAgIHNlbGYuY2xvc2UoKVxuYDtcblxuICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKHBrZ0RpciwgJ2NsaWVudC5weScpLCBjbGllbnRQeSk7XG5cbiAgLy8gR2VuZXJhdGUgUkVBRE1FXG4gIGNvbnN0IHJlYWRtZSA9IGAjICR7cGFja2FnZU5hbWV9XG5cbkdlbmVyYXRlZCBQeXRob24gU0RLIGZvciAkeyhpbmZvLnRpdGxlIGFzIHN0cmluZykgfHwgJ0FQSSd9LlxuXG4jIyBJbnN0YWxsYXRpb25cblxuXFxgXFxgXFxgYmFzaFxucGlwIGluc3RhbGwgLWUgLlxuXFxgXFxgXFxgXG5cbiMjIFVzYWdlXG5cblxcYFxcYFxcYHB5dGhvblxuZnJvbSAke3BhY2thZ2VOYW1lfSBpbXBvcnQgQXBpQ2xpZW50XG5cbmNsaWVudCA9IEFwaUNsaWVudChcbiAgICBiYXNlX3VybD1cIiR7ZGVmYXVsdEJhc2VVcmx9XCIsXG4gICAgYXBpX2tleT1cInlvdXItYXBpLWtleVwiLFxuKVxuXFxgXFxgXFxgXG5gO1xuXG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4ob3V0cHV0UGF0aCwgJ1JFQURNRS5tZCcpLCByZWFkbWUpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIEdvIFNES1xuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUdvU0RLKFxuICBzcGVjUGF0aDogc3RyaW5nLFxuICBvdXRwdXRQYXRoOiBzdHJpbmcsXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBSZWFkIHRoZSBPcGVuQVBJIHNwZWNcbiAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKHNwZWNQYXRoLCAndXRmLTgnKTtcbiAgbGV0IHNwZWM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gIGlmIChzcGVjUGF0aC5lbmRzV2l0aCgnLnlhbWwnKSB8fCBzcGVjUGF0aC5lbmRzV2l0aCgnLnltbCcpKSB7XG4gICAgY29uc3QgeWFtbCA9IGF3YWl0IGltcG9ydCgnanMteWFtbCcpO1xuICAgIHNwZWMgPSB5YW1sLmxvYWQoY29udGVudCkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH0gZWxzZSB7XG4gICAgc3BlYyA9IEpTT04ucGFyc2UoY29udGVudCk7XG4gIH1cblxuICBjb25zdCBpbmZvID0gKHNwZWMuaW5mbyB8fCB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHNlcnZlcnMgPSAoc3BlYy5zZXJ2ZXJzIHx8IFtdKSBhcyB7IHVybDogc3RyaW5nIH1bXTtcbiAgY29uc3QgZGVmYXVsdEJhc2VVcmwgPSBzZXJ2ZXJzWzBdPy51cmwgfHwgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJztcblxuICAvLyBHZW5lcmF0ZSBnby5tb2RcbiAgY29uc3QgZ29Nb2QgPSBgbW9kdWxlICR7cGFja2FnZU5hbWV9XG5cbmdvIDEuMjFcbmA7XG5cbiAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGguam9pbihvdXRwdXRQYXRoLCAnZ28ubW9kJyksIGdvTW9kKTtcblxuICAvLyBHZW5lcmF0ZSBjbGllbnQuZ29cbiAgY29uc3QgY2xpZW50R28gPSBgLy8gUGFja2FnZSAke3BhY2thZ2VOYW1lLnNwbGl0KCcvJykucG9wKCl9IHByb3ZpZGVzIGEgY2xpZW50IGZvciAkeyhpbmZvLnRpdGxlIGFzIHN0cmluZykgfHwgJ3RoZSBBUEknfS5cbnBhY2thZ2UgJHtwYWNrYWdlTmFtZS5zcGxpdCgnLycpLnBvcCgpIHx8ICdzZGsnfVxuXG5pbXBvcnQgKFxuXFx0XCJieXRlc1wiXG5cXHRcImVuY29kaW5nL2pzb25cIlxuXFx0XCJmbXRcIlxuXFx0XCJpb1wiXG5cXHRcIm5ldC9odHRwXCJcbilcblxuLy8gQ2xpZW50IHJlcHJlc2VudHMgYW4gQVBJIGNsaWVudC5cbnR5cGUgQ2xpZW50IHN0cnVjdCB7XG5cXHRCYXNlVVJMICAgIHN0cmluZ1xuXFx0QVBJS2V5ICAgICBzdHJpbmdcblxcdEhUVFBDbGllbnQgKmh0dHAuQ2xpZW50XG59XG5cbi8vIE5ld0NsaWVudCBjcmVhdGVzIGEgbmV3IEFQSSBjbGllbnQuXG5mdW5jIE5ld0NsaWVudChiYXNlVVJMLCBhcGlLZXkgc3RyaW5nKSAqQ2xpZW50IHtcblxcdGlmIGJhc2VVUkwgPT0gXCJcIiB7XG5cXHRcXHRiYXNlVVJMID0gXCIke2RlZmF1bHRCYXNlVXJsfVwiXG5cXHR9XG5cXHRyZXR1cm4gJkNsaWVudHtcblxcdFxcdEJhc2VVUkw6ICAgIGJhc2VVUkwsXG5cXHRcXHRBUElLZXk6ICAgICBhcGlLZXksXG5cXHRcXHRIVFRQQ2xpZW50OiAmaHR0cC5DbGllbnR7fSxcblxcdH1cbn1cblxuZnVuYyAoYyAqQ2xpZW50KSBkb1JlcXVlc3QobWV0aG9kLCBwYXRoIHN0cmluZywgYm9keSBpbnRlcmZhY2V7fSkgKFtdYnl0ZSwgZXJyb3IpIHtcblxcdHVybCA6PSBjLkJhc2VVUkwgKyBwYXRoXG5cblxcdHZhciByZXFCb2R5IGlvLlJlYWRlclxuXFx0aWYgYm9keSAhPSBuaWwge1xuXFx0XFx0anNvbkJvZHksIGVyciA6PSBqc29uLk1hcnNoYWwoYm9keSlcblxcdFxcdGlmIGVyciAhPSBuaWwge1xuXFx0XFx0XFx0cmV0dXJuIG5pbCwgZm10LkVycm9yZihcImZhaWxlZCB0byBtYXJzaGFsIHJlcXVlc3QgYm9keTogJXdcIiwgZXJyKVxuXFx0XFx0fVxuXFx0XFx0cmVxQm9keSA9IGJ5dGVzLk5ld0J1ZmZlcihqc29uQm9keSlcblxcdH1cblxuXFx0cmVxLCBlcnIgOj0gaHR0cC5OZXdSZXF1ZXN0KG1ldGhvZCwgdXJsLCByZXFCb2R5KVxuXFx0aWYgZXJyICE9IG5pbCB7XG5cXHRcXHRyZXR1cm4gbmlsLCBmbXQuRXJyb3JmKFwiZmFpbGVkIHRvIGNyZWF0ZSByZXF1ZXN0OiAld1wiLCBlcnIpXG5cXHR9XG5cblxcdHJlcS5IZWFkZXIuU2V0KFwiQ29udGVudC1UeXBlXCIsIFwiYXBwbGljYXRpb24vanNvblwiKVxuXFx0aWYgYy5BUElLZXkgIT0gXCJcIiB7XG5cXHRcXHRyZXEuSGVhZGVyLlNldChcIkF1dGhvcml6YXRpb25cIiwgXCJCZWFyZXIgXCIrYy5BUElLZXkpXG5cXHR9XG5cblxcdHJlc3AsIGVyciA6PSBjLkhUVFBDbGllbnQuRG8ocmVxKVxuXFx0aWYgZXJyICE9IG5pbCB7XG5cXHRcXHRyZXR1cm4gbmlsLCBmbXQuRXJyb3JmKFwicmVxdWVzdCBmYWlsZWQ6ICV3XCIsIGVycilcblxcdH1cblxcdGRlZmVyIHJlc3AuQm9keS5DbG9zZSgpXG5cblxcdHJlc3BCb2R5LCBlcnIgOj0gaW8uUmVhZEFsbChyZXNwLkJvZHkpXG5cXHRpZiBlcnIgIT0gbmlsIHtcblxcdFxcdHJldHVybiBuaWwsIGZtdC5FcnJvcmYoXCJmYWlsZWQgdG8gcmVhZCByZXNwb25zZTogJXdcIiwgZXJyKVxuXFx0fVxuXG5cXHRpZiByZXNwLlN0YXR1c0NvZGUgPj0gNDAwIHtcblxcdFxcdHJldHVybiBuaWwsIGZtdC5FcnJvcmYoXCJBUEkgZXJyb3IgJWQ6ICVzXCIsIHJlc3AuU3RhdHVzQ29kZSwgc3RyaW5nKHJlc3BCb2R5KSlcblxcdH1cblxuXFx0cmV0dXJuIHJlc3BCb2R5LCBuaWxcbn1cbmA7XG5cbiAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGguam9pbihvdXRwdXRQYXRoLCAnY2xpZW50LmdvJyksIGNsaWVudEdvKTtcblxuICAvLyBHZW5lcmF0ZSBSRUFETUVcbiAgY29uc3QgcmVhZG1lID0gYCMgJHtwYWNrYWdlTmFtZX1cblxuR2VuZXJhdGVkIEdvIFNESyBmb3IgJHsoaW5mby50aXRsZSBhcyBzdHJpbmcpIHx8ICdBUEknfS5cblxuIyMgSW5zdGFsbGF0aW9uXG5cblxcYFxcYFxcYGJhc2hcbmdvIGdldCAke3BhY2thZ2VOYW1lfVxuXFxgXFxgXFxgXG5cbiMjIFVzYWdlXG5cblxcYFxcYFxcYGdvXG5wYWNrYWdlIG1haW5cblxuaW1wb3J0IChcblxcdFwiJHtwYWNrYWdlTmFtZX1cIlxuKVxuXG5mdW5jIG1haW4oKSB7XG5cXHRjbGllbnQgOj0gJHtwYWNrYWdlTmFtZS5zcGxpdCgnLycpLnBvcCgpfS5OZXdDbGllbnQoXCIke2RlZmF1bHRCYXNlVXJsfVwiLCBcInlvdXItYXBpLWtleVwiKVxuXFx0Ly8gVXNlIGNsaWVudC4uLlxufVxuXFxgXFxgXFxgXG5gO1xuXG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4ob3V0cHV0UGF0aCwgJ1JFQURNRS5tZCcpLCByZWFkbWUpO1xufVxuIl19