@brainfish-ai/devdoc 0.1.21
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.
- package/LICENSE +33 -0
- package/README.md +415 -0
- package/bin/devdoc.js +13 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +87 -0
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.js +143 -0
- package/dist/cli/commands/create.d.ts +24 -0
- package/dist/cli/commands/create.js +387 -0
- package/dist/cli/commands/deploy.d.ts +9 -0
- package/dist/cli/commands/deploy.js +433 -0
- package/dist/cli/commands/dev.d.ts +6 -0
- package/dist/cli/commands/dev.js +139 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.js +238 -0
- package/dist/cli/commands/keys.d.ts +12 -0
- package/dist/cli/commands/keys.js +165 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +56 -0
- package/dist/cli/commands/upload.d.ts +13 -0
- package/dist/cli/commands/upload.js +238 -0
- package/dist/cli/commands/whoami.d.ts +8 -0
- package/dist/cli/commands/whoami.js +91 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/config/index.d.ts +80 -0
- package/dist/config/index.js +133 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.js +50 -0
- package/package.json +51 -0
- package/renderer/app/api/assets/[...path]/route.ts +123 -0
- package/renderer/app/api/assets/route.ts +124 -0
- package/renderer/app/api/assets/upload/route.ts +177 -0
- package/renderer/app/api/auth-schemes/route.ts +77 -0
- package/renderer/app/api/chat/route.ts +858 -0
- package/renderer/app/api/codegen/route.ts +72 -0
- package/renderer/app/api/collections/route.ts +1016 -0
- package/renderer/app/api/debug/route.ts +53 -0
- package/renderer/app/api/deploy/route.ts +234 -0
- package/renderer/app/api/device/route.ts +42 -0
- package/renderer/app/api/docs/route.ts +187 -0
- package/renderer/app/api/keys/regenerate/route.ts +80 -0
- package/renderer/app/api/openapi-spec/route.ts +151 -0
- package/renderer/app/api/projects/[slug]/route.ts +153 -0
- package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
- package/renderer/app/api/projects/register/route.ts +152 -0
- package/renderer/app/api/proxy/route.ts +149 -0
- package/renderer/app/api/proxy-stream/route.ts +168 -0
- package/renderer/app/api/redirects/route.ts +47 -0
- package/renderer/app/api/schema/route.ts +65 -0
- package/renderer/app/api/subdomains/check/route.ts +172 -0
- package/renderer/app/api/suggestions/route.ts +144 -0
- package/renderer/app/favicon.ico +0 -0
- package/renderer/app/globals.css +1103 -0
- package/renderer/app/layout.tsx +47 -0
- package/renderer/app/llms-full.txt/route.ts +346 -0
- package/renderer/app/llms.txt/route.ts +279 -0
- package/renderer/app/page.tsx +14 -0
- package/renderer/app/robots.txt/route.ts +84 -0
- package/renderer/app/sitemap.xml/route.ts +199 -0
- package/renderer/components/docs/index.ts +12 -0
- package/renderer/components/docs/mdx/accordion.tsx +169 -0
- package/renderer/components/docs/mdx/badge.tsx +132 -0
- package/renderer/components/docs/mdx/callouts.tsx +154 -0
- package/renderer/components/docs/mdx/cards.tsx +213 -0
- package/renderer/components/docs/mdx/changelog.tsx +120 -0
- package/renderer/components/docs/mdx/code-block.tsx +186 -0
- package/renderer/components/docs/mdx/code-group.tsx +421 -0
- package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
- package/renderer/components/docs/mdx/frame.tsx +112 -0
- package/renderer/components/docs/mdx/highlight.tsx +151 -0
- package/renderer/components/docs/mdx/iframe.tsx +134 -0
- package/renderer/components/docs/mdx/image.tsx +235 -0
- package/renderer/components/docs/mdx/index.ts +204 -0
- package/renderer/components/docs/mdx/mermaid.tsx +240 -0
- package/renderer/components/docs/mdx/param-field.tsx +200 -0
- package/renderer/components/docs/mdx/steps.tsx +113 -0
- package/renderer/components/docs/mdx/tabs.tsx +86 -0
- package/renderer/components/docs/mdx-renderer.tsx +100 -0
- package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
- package/renderer/components/docs/navigation/index.ts +8 -0
- package/renderer/components/docs/navigation/page-nav.tsx +64 -0
- package/renderer/components/docs/navigation/sidebar.tsx +515 -0
- package/renderer/components/docs/navigation/toc.tsx +113 -0
- package/renderer/components/docs/notice.tsx +105 -0
- package/renderer/components/docs-header.tsx +274 -0
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
- package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
- package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
- package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
- package/renderer/components/docs-viewer/agent/index.tsx +6 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
- package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
- package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
- package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
- package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
- package/renderer/components/docs-viewer/content/index.tsx +29 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
- package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
- package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
- package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
- package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
- package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
- package/renderer/components/docs-viewer/index.tsx +1466 -0
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
- package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
- package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
- package/renderer/components/docs-viewer/playground/index.tsx +671 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
- package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
- package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
- package/renderer/components/docs-viewer/search/index.ts +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
- package/renderer/components/docs-viewer/search/use-search.ts +117 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
- package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
- package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
- package/renderer/components/theme-provider.tsx +11 -0
- package/renderer/components/theme-toggle.tsx +76 -0
- package/renderer/components/ui/badge.tsx +46 -0
- package/renderer/components/ui/button.tsx +59 -0
- package/renderer/components/ui/dialog.tsx +118 -0
- package/renderer/components/ui/dropdown-menu.tsx +257 -0
- package/renderer/components/ui/input.tsx +21 -0
- package/renderer/components/ui/label.tsx +24 -0
- package/renderer/components/ui/navigation-menu.tsx +168 -0
- package/renderer/components/ui/select.tsx +190 -0
- package/renderer/components/ui/spinner.tsx +114 -0
- package/renderer/components/ui/tabs.tsx +66 -0
- package/renderer/components/ui/tooltip.tsx +61 -0
- package/renderer/hooks/use-code-copy.ts +88 -0
- package/renderer/hooks/use-openapi-title.ts +44 -0
- package/renderer/lib/api-docs/agent/index.ts +6 -0
- package/renderer/lib/api-docs/agent/indexer.ts +323 -0
- package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
- package/renderer/lib/api-docs/agent/types.ts +116 -0
- package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
- package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
- package/renderer/lib/api-docs/auth/crypto.ts +89 -0
- package/renderer/lib/api-docs/auth/index.ts +4 -0
- package/renderer/lib/api-docs/code-editor/db.ts +164 -0
- package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
- package/renderer/lib/api-docs/code-editor/index.ts +6 -0
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
- package/renderer/lib/api-docs/code-editor/types.ts +105 -0
- package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
- package/renderer/lib/api-docs/codegen/har.ts +251 -0
- package/renderer/lib/api-docs/codegen/index.ts +159 -0
- package/renderer/lib/api-docs/factories.ts +151 -0
- package/renderer/lib/api-docs/index.ts +17 -0
- package/renderer/lib/api-docs/mobile-context.tsx +112 -0
- package/renderer/lib/api-docs/navigation-context.tsx +88 -0
- package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
- package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
- package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
- package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
- package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
- package/renderer/lib/api-docs/playground/context.tsx +107 -0
- package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
- package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
- package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
- package/renderer/lib/api-docs/playground/types.ts +35 -0
- package/renderer/lib/api-docs/types.ts +269 -0
- package/renderer/lib/api-docs/utils.ts +311 -0
- package/renderer/lib/cache.ts +193 -0
- package/renderer/lib/docs/config/index.ts +29 -0
- package/renderer/lib/docs/config/loader.ts +142 -0
- package/renderer/lib/docs/config/schema.ts +298 -0
- package/renderer/lib/docs/index.ts +12 -0
- package/renderer/lib/docs/mdx/compiler.ts +176 -0
- package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
- package/renderer/lib/docs/mdx/index.ts +26 -0
- package/renderer/lib/docs/navigation/generator.ts +348 -0
- package/renderer/lib/docs/navigation/index.ts +12 -0
- package/renderer/lib/docs/navigation/types.ts +123 -0
- package/renderer/lib/docs-navigation-context.tsx +80 -0
- package/renderer/lib/multi-tenant/context.ts +105 -0
- package/renderer/lib/storage/blob.ts +845 -0
- package/renderer/lib/utils.ts +6 -0
- package/renderer/next.config.ts +76 -0
- package/renderer/package.json +66 -0
- package/renderer/postcss.config.mjs +5 -0
- package/renderer/public/assets/images/screenshot.png +0 -0
- package/renderer/public/assets/logo/dark.svg +9 -0
- package/renderer/public/assets/logo/light.svg +9 -0
- package/renderer/public/assets/logo.svg +9 -0
- package/renderer/public/file.svg +1 -0
- package/renderer/public/globe.svg +1 -0
- package/renderer/public/icon.png +0 -0
- package/renderer/public/logo.svg +9 -0
- package/renderer/public/window.svg +1 -0
- package/renderer/tsconfig.json +28 -0
- package/templates/basic/README.md +139 -0
- package/templates/basic/assets/favicon.svg +4 -0
- package/templates/basic/assets/logo.svg +9 -0
- package/templates/basic/docs.json +47 -0
- package/templates/basic/guides/configuration.mdx +149 -0
- package/templates/basic/guides/overview.mdx +96 -0
- package/templates/basic/index.mdx +39 -0
- package/templates/basic/package.json +14 -0
- package/templates/basic/quickstart.mdx +92 -0
- package/templates/basic/vercel.json +6 -0
- package/templates/graphql/README.md +139 -0
- package/templates/graphql/api-reference/schema.graphql +305 -0
- package/templates/graphql/assets/favicon.svg +4 -0
- package/templates/graphql/assets/logo.svg +9 -0
- package/templates/graphql/docs.json +54 -0
- package/templates/graphql/guides/configuration.mdx +149 -0
- package/templates/graphql/guides/overview.mdx +96 -0
- package/templates/graphql/index.mdx +39 -0
- package/templates/graphql/package.json +14 -0
- package/templates/graphql/quickstart.mdx +92 -0
- package/templates/graphql/vercel.json +6 -0
- package/templates/openapi/README.md +139 -0
- package/templates/openapi/api-reference/openapi.json +419 -0
- package/templates/openapi/assets/favicon.svg +4 -0
- package/templates/openapi/assets/logo.svg +9 -0
- package/templates/openapi/docs.json +61 -0
- package/templates/openapi/guides/configuration.mdx +149 -0
- package/templates/openapi/guides/overview.mdx +96 -0
- package/templates/openapi/index.mdx +39 -0
- package/templates/openapi/package.json +14 -0
- package/templates/openapi/quickstart.mdx +92 -0
- package/templates/openapi/vercel.json +6 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deploy = deploy;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const config_1 = require("../../config");
|
|
10
|
+
const logger_1 = require("../../utils/logger");
|
|
11
|
+
const constants_1 = require("../../constants");
|
|
12
|
+
// Max asset size: 25MB
|
|
13
|
+
const MAX_ASSET_SIZE = 25 * 1024 * 1024;
|
|
14
|
+
// Binary asset extensions to upload separately
|
|
15
|
+
const BINARY_EXTENSIONS = [
|
|
16
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico',
|
|
17
|
+
'.mp4', '.webm', '.mov',
|
|
18
|
+
'.mp3', '.wav', '.ogg',
|
|
19
|
+
'.woff', '.woff2', '.ttf', '.otf', '.eot',
|
|
20
|
+
'.pdf',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Deploy documentation to DevDoc platform
|
|
24
|
+
*/
|
|
25
|
+
async function deploy(options) {
|
|
26
|
+
const projectRoot = process.cwd();
|
|
27
|
+
const apiUrl = options.url || process.env.DEVDOC_API_URL || constants_1.DEFAULT_API_URL;
|
|
28
|
+
logger_1.logger.info('Deploying to DevDoc...\n');
|
|
29
|
+
// Check for docs.json
|
|
30
|
+
const configPath = path_1.default.join(projectRoot, 'docs.json');
|
|
31
|
+
if (!fs_extra_1.default.existsSync(configPath)) {
|
|
32
|
+
logger_1.logger.error('docs.json not found in current directory');
|
|
33
|
+
logger_1.logger.info('Make sure you are in a DevDoc documentation project directory');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
// Load and validate configuration
|
|
37
|
+
let config;
|
|
38
|
+
try {
|
|
39
|
+
config = await (0, config_1.loadConfig)(projectRoot);
|
|
40
|
+
const validation = (0, config_1.validateConfig)(config);
|
|
41
|
+
if (!validation.valid) {
|
|
42
|
+
logger_1.logger.error('Invalid docs.json configuration:');
|
|
43
|
+
validation.errors.forEach(err => logger_1.logger.error(` - ${err}`));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
logger_1.logger.success(`✓ Configuration valid: ${config.name || 'Untitled'}`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
logger_1.logger.error(`Failed to load configuration: ${message}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
// Check for existing project config
|
|
54
|
+
const devdocConfigPath = path_1.default.join(projectRoot, '.devdoc.json');
|
|
55
|
+
let existingSlug = null;
|
|
56
|
+
let existingApiKey = null;
|
|
57
|
+
if (fs_extra_1.default.existsSync(devdocConfigPath)) {
|
|
58
|
+
try {
|
|
59
|
+
const devdocConfig = fs_extra_1.default.readJsonSync(devdocConfigPath);
|
|
60
|
+
existingSlug = devdocConfig.slug || null;
|
|
61
|
+
existingApiKey = devdocConfig.apiKey || null;
|
|
62
|
+
if (existingSlug) {
|
|
63
|
+
logger_1.logger.info(`Deploying project: ${existingSlug}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Ignore errors reading .devdoc.json
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Get API key from options, env var, or .devdoc.json
|
|
71
|
+
const apiKey = options.apiKey || process.env.DEVDOC_API_KEY || existingApiKey;
|
|
72
|
+
// API key is always required for deployment
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
logger_1.logger.error('API key required for deployment.');
|
|
75
|
+
console.log('');
|
|
76
|
+
if (!existingSlug) {
|
|
77
|
+
logger_1.logger.info('Run "devdoc init" first to register your project and get an API key');
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
logger_1.logger.info('Your project is not registered. Run "devdoc init --force" to register and get an API key');
|
|
81
|
+
}
|
|
82
|
+
logger_1.logger.info('Or provide via --api-key flag or DEVDOC_API_KEY env var');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
// Collect all content files
|
|
86
|
+
logger_1.logger.info('Bundling content...');
|
|
87
|
+
const files = await collectFiles(projectRoot);
|
|
88
|
+
logger_1.logger.success(`✓ Found ${files.length} content files`);
|
|
89
|
+
// Collect binary assets
|
|
90
|
+
const assets = await collectAssets(projectRoot);
|
|
91
|
+
if (assets.length > 0) {
|
|
92
|
+
const totalAssetSize = assets.reduce((sum, a) => sum + a.size, 0);
|
|
93
|
+
logger_1.logger.success(`✓ Found ${assets.length} assets (${formatSize(totalAssetSize)})`);
|
|
94
|
+
}
|
|
95
|
+
// Calculate bundle size
|
|
96
|
+
const totalSize = files.reduce((sum, f) => sum + f.content.length, 0);
|
|
97
|
+
const sizeKB = (totalSize / 1024).toFixed(1);
|
|
98
|
+
logger_1.logger.info(`Content bundle: ${sizeKB} KB`);
|
|
99
|
+
// Upload binary assets first (with progress)
|
|
100
|
+
if (assets.length > 0 && existingSlug) {
|
|
101
|
+
console.log('');
|
|
102
|
+
logger_1.logger.info('Uploading assets...');
|
|
103
|
+
const assetResults = await uploadAssets(assets, apiUrl, existingSlug, apiKey);
|
|
104
|
+
const successCount = assetResults.filter(r => r.success).length;
|
|
105
|
+
const failCount = assetResults.filter(r => !r.success).length;
|
|
106
|
+
if (failCount > 0) {
|
|
107
|
+
logger_1.logger.warn(`${successCount} assets uploaded, ${failCount} failed`);
|
|
108
|
+
}
|
|
109
|
+
else if (successCount > 0) {
|
|
110
|
+
logger_1.logger.success(`✓ ${successCount} assets uploaded`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else if (assets.length > 0 && !existingSlug) {
|
|
114
|
+
logger_1.logger.info('Assets will be uploaded on next deploy (after project registration)');
|
|
115
|
+
}
|
|
116
|
+
// Deploy content to API
|
|
117
|
+
console.log('');
|
|
118
|
+
logger_1.logger.info('Uploading content...');
|
|
119
|
+
try {
|
|
120
|
+
const headers = {
|
|
121
|
+
'Content-Type': 'application/json',
|
|
122
|
+
};
|
|
123
|
+
// Add API key header for updates
|
|
124
|
+
if (apiKey) {
|
|
125
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
126
|
+
}
|
|
127
|
+
const response = await fetch(`${apiUrl}/api/deploy`, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers,
|
|
130
|
+
redirect: 'follow', // Follow redirects
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
name: config.name || 'My Documentation',
|
|
133
|
+
slug: existingSlug,
|
|
134
|
+
docsJson: config,
|
|
135
|
+
files,
|
|
136
|
+
apiKey, // Also send in body as fallback
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
141
|
+
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
142
|
+
const details = errorData.details ? `\n Details: ${errorData.details}` : '';
|
|
143
|
+
throw new Error(`${errorMessage}${details}`);
|
|
144
|
+
}
|
|
145
|
+
const result = await response.json();
|
|
146
|
+
// Save project config for future updates
|
|
147
|
+
const newDevDocConfig = {
|
|
148
|
+
slug: result.slug,
|
|
149
|
+
url: result.url,
|
|
150
|
+
lastDeployed: new Date().toISOString(),
|
|
151
|
+
};
|
|
152
|
+
// Save API key (from response for new projects, or existing for updates)
|
|
153
|
+
if (result.apiKey) {
|
|
154
|
+
newDevDocConfig.apiKey = result.apiKey;
|
|
155
|
+
}
|
|
156
|
+
else if (apiKey) {
|
|
157
|
+
newDevDocConfig.apiKey = apiKey;
|
|
158
|
+
}
|
|
159
|
+
fs_extra_1.default.writeJsonSync(devdocConfigPath, newDevDocConfig, { spaces: 2 });
|
|
160
|
+
// Success message
|
|
161
|
+
console.log('');
|
|
162
|
+
logger_1.logger.success('Deployment successful!');
|
|
163
|
+
console.log('');
|
|
164
|
+
console.log(` Your docs are live at:`);
|
|
165
|
+
console.log(` ${logger_1.logger.cyan(result.url)}`);
|
|
166
|
+
console.log('');
|
|
167
|
+
if (result.isUpdate) {
|
|
168
|
+
logger_1.logger.info('Project updated with new content');
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
logger_1.logger.info(`Project slug: ${result.slug}`);
|
|
172
|
+
logger_1.logger.info('Run "devdoc deploy" again to update');
|
|
173
|
+
// Show API key warning for new projects
|
|
174
|
+
if (result.apiKey) {
|
|
175
|
+
console.log('');
|
|
176
|
+
logger_1.logger.warn('⚠️ Save your API key for CI/CD deployments:');
|
|
177
|
+
console.log(` ${result.apiKey}`);
|
|
178
|
+
console.log('');
|
|
179
|
+
logger_1.logger.info('API key saved to .devdoc.json (add to .gitignore!)');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
logger_1.logger.error(`Deployment failed: ${message}`);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Collect all MDX and content files from the project
|
|
191
|
+
*/
|
|
192
|
+
async function collectFiles(projectRoot) {
|
|
193
|
+
const files = [];
|
|
194
|
+
// Directories to scan
|
|
195
|
+
const scanDirs = [
|
|
196
|
+
'', // Root directory (for index.mdx, quickstart.mdx, etc.)
|
|
197
|
+
'guides',
|
|
198
|
+
'essentials',
|
|
199
|
+
'components',
|
|
200
|
+
'api-reference',
|
|
201
|
+
'changelog',
|
|
202
|
+
];
|
|
203
|
+
for (const dir of scanDirs) {
|
|
204
|
+
const fullDir = path_1.default.join(projectRoot, dir);
|
|
205
|
+
if (!fs_extra_1.default.existsSync(fullDir))
|
|
206
|
+
continue;
|
|
207
|
+
await scanDirectory(fullDir, projectRoot, files);
|
|
208
|
+
}
|
|
209
|
+
// Include text-based assets from assets folder (new convention)
|
|
210
|
+
const assetsDir = path_1.default.join(projectRoot, 'assets');
|
|
211
|
+
if (fs_extra_1.default.existsSync(assetsDir)) {
|
|
212
|
+
await scanPublicAssets(assetsDir, projectRoot, files);
|
|
213
|
+
}
|
|
214
|
+
// Also include public assets for backwards compatibility
|
|
215
|
+
const publicDir = path_1.default.join(projectRoot, 'public');
|
|
216
|
+
if (fs_extra_1.default.existsSync(publicDir)) {
|
|
217
|
+
await scanPublicAssets(publicDir, projectRoot, files);
|
|
218
|
+
}
|
|
219
|
+
return files;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Recursively scan a directory for MDX files
|
|
223
|
+
*/
|
|
224
|
+
async function scanDirectory(dir, projectRoot, files) {
|
|
225
|
+
const items = fs_extra_1.default.readdirSync(dir);
|
|
226
|
+
for (const item of items) {
|
|
227
|
+
// Skip common directories
|
|
228
|
+
if (['node_modules', 'dist', '.next', '.git', 'public'].includes(item)) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const fullPath = path_1.default.join(dir, item);
|
|
232
|
+
const stat = fs_extra_1.default.statSync(fullPath);
|
|
233
|
+
if (stat.isDirectory()) {
|
|
234
|
+
await scanDirectory(fullPath, projectRoot, files);
|
|
235
|
+
}
|
|
236
|
+
else if (item.endsWith('.mdx') || item.endsWith('.md')) {
|
|
237
|
+
const relativePath = path_1.default.relative(projectRoot, fullPath);
|
|
238
|
+
const content = fs_extra_1.default.readFileSync(fullPath, 'utf-8');
|
|
239
|
+
files.push({
|
|
240
|
+
path: relativePath,
|
|
241
|
+
content,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Scan public assets (SVG, images) - text-based only for content bundle
|
|
248
|
+
*/
|
|
249
|
+
async function scanPublicAssets(dir, projectRoot, files) {
|
|
250
|
+
const items = fs_extra_1.default.readdirSync(dir);
|
|
251
|
+
for (const item of items) {
|
|
252
|
+
const fullPath = path_1.default.join(dir, item);
|
|
253
|
+
const stat = fs_extra_1.default.statSync(fullPath);
|
|
254
|
+
if (stat.isDirectory()) {
|
|
255
|
+
await scanPublicAssets(fullPath, projectRoot, files);
|
|
256
|
+
}
|
|
257
|
+
else if (item.endsWith('.svg') || item.endsWith('.json')) {
|
|
258
|
+
// Only include text-based assets in content bundle
|
|
259
|
+
const relativePath = path_1.default.relative(projectRoot, fullPath);
|
|
260
|
+
const content = fs_extra_1.default.readFileSync(fullPath, 'utf-8');
|
|
261
|
+
files.push({
|
|
262
|
+
path: relativePath,
|
|
263
|
+
content,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Collect binary assets from assets folder (convention: /assets)
|
|
270
|
+
*/
|
|
271
|
+
async function collectAssets(projectRoot) {
|
|
272
|
+
const assets = [];
|
|
273
|
+
// Check assets folder first (new convention)
|
|
274
|
+
const assetsDir = path_1.default.join(projectRoot, 'assets');
|
|
275
|
+
if (fs_extra_1.default.existsSync(assetsDir)) {
|
|
276
|
+
await scanBinaryAssets(assetsDir, projectRoot, assets);
|
|
277
|
+
}
|
|
278
|
+
// Also check public folder for backwards compatibility
|
|
279
|
+
const publicDir = path_1.default.join(projectRoot, 'public');
|
|
280
|
+
if (fs_extra_1.default.existsSync(publicDir)) {
|
|
281
|
+
await scanBinaryAssets(publicDir, projectRoot, assets);
|
|
282
|
+
}
|
|
283
|
+
return assets;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Recursively scan for binary assets
|
|
287
|
+
*/
|
|
288
|
+
async function scanBinaryAssets(dir, projectRoot, assets) {
|
|
289
|
+
const items = fs_extra_1.default.readdirSync(dir);
|
|
290
|
+
for (const item of items) {
|
|
291
|
+
const fullPath = path_1.default.join(dir, item);
|
|
292
|
+
const stat = fs_extra_1.default.statSync(fullPath);
|
|
293
|
+
if (stat.isDirectory()) {
|
|
294
|
+
await scanBinaryAssets(fullPath, projectRoot, assets);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
const ext = path_1.default.extname(item).toLowerCase();
|
|
298
|
+
if (BINARY_EXTENSIONS.includes(ext)) {
|
|
299
|
+
// Check size limit
|
|
300
|
+
if (stat.size > MAX_ASSET_SIZE) {
|
|
301
|
+
logger_1.logger.warn(`Skipping ${item}: exceeds 25MB limit (${formatSize(stat.size)})`);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const relativePath = path_1.default.relative(projectRoot, fullPath);
|
|
305
|
+
assets.push({
|
|
306
|
+
path: relativePath,
|
|
307
|
+
fullPath,
|
|
308
|
+
size: stat.size,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Upload assets with progress tracking
|
|
316
|
+
*/
|
|
317
|
+
async function uploadAssets(assets, apiUrl, slug, apiKey) {
|
|
318
|
+
const results = [];
|
|
319
|
+
for (const asset of assets) {
|
|
320
|
+
const fileName = path_1.default.basename(asset.path);
|
|
321
|
+
process.stdout.write(` ${fileName}: `);
|
|
322
|
+
try {
|
|
323
|
+
const result = await uploadAssetWithProgress(asset, apiUrl, slug, apiKey, (progress, loaded, total) => {
|
|
324
|
+
process.stdout.clearLine(0);
|
|
325
|
+
process.stdout.cursorTo(0);
|
|
326
|
+
process.stdout.write(` ${fileName}: ${createProgressBar(progress)} ${formatSize(loaded)}/${formatSize(total)}`);
|
|
327
|
+
});
|
|
328
|
+
process.stdout.clearLine(0);
|
|
329
|
+
process.stdout.cursorTo(0);
|
|
330
|
+
console.log(` ${logger_1.logger.green('✓')} ${fileName} (${formatSize(asset.size)})`);
|
|
331
|
+
results.push({ file: fileName, success: true, url: result.url });
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
335
|
+
process.stdout.clearLine(0);
|
|
336
|
+
process.stdout.cursorTo(0);
|
|
337
|
+
console.log(` ${logger_1.logger.red('✗')} ${fileName}: ${message}`);
|
|
338
|
+
results.push({ file: fileName, success: false, error: message });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return results;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Upload a single asset with progress
|
|
345
|
+
*/
|
|
346
|
+
async function uploadAssetWithProgress(asset, apiUrl, slug, apiKey, onProgress) {
|
|
347
|
+
const fileBuffer = fs_extra_1.default.readFileSync(asset.fullPath);
|
|
348
|
+
const fileName = path_1.default.basename(asset.path);
|
|
349
|
+
// Build multipart form data
|
|
350
|
+
const boundary = `----DevDocDeploy${Date.now()}`;
|
|
351
|
+
const CRLF = '\r\n';
|
|
352
|
+
const header = [
|
|
353
|
+
`--${boundary}`,
|
|
354
|
+
`Content-Disposition: form-data; name="file"; filename="${fileName}"`,
|
|
355
|
+
`Content-Type: application/octet-stream`,
|
|
356
|
+
'',
|
|
357
|
+
''
|
|
358
|
+
].join(CRLF);
|
|
359
|
+
const slugPart = [
|
|
360
|
+
'',
|
|
361
|
+
`--${boundary}`,
|
|
362
|
+
`Content-Disposition: form-data; name="slug"`,
|
|
363
|
+
'',
|
|
364
|
+
slug,
|
|
365
|
+
''
|
|
366
|
+
].join(CRLF);
|
|
367
|
+
const pathPart = [
|
|
368
|
+
`--${boundary}`,
|
|
369
|
+
`Content-Disposition: form-data; name="path"`,
|
|
370
|
+
'',
|
|
371
|
+
asset.path.replace(/^public\//, ''), // Remove public/ prefix
|
|
372
|
+
''
|
|
373
|
+
].join(CRLF);
|
|
374
|
+
const footer = `${CRLF}--${boundary}--${CRLF}`;
|
|
375
|
+
const headerBuffer = Buffer.from(header);
|
|
376
|
+
const slugBuffer = Buffer.from(slugPart);
|
|
377
|
+
const pathBuffer = Buffer.from(pathPart);
|
|
378
|
+
const footerBuffer = Buffer.from(footer);
|
|
379
|
+
const totalSize = headerBuffer.length + fileBuffer.length + slugBuffer.length + pathBuffer.length + footerBuffer.length;
|
|
380
|
+
const body = Buffer.concat([headerBuffer, fileBuffer, slugBuffer, pathBuffer, footerBuffer]);
|
|
381
|
+
// Simulate progress
|
|
382
|
+
let uploaded = 0;
|
|
383
|
+
const chunkSize = Math.ceil(totalSize / 20);
|
|
384
|
+
const progressInterval = setInterval(() => {
|
|
385
|
+
if (uploaded < totalSize * 0.9) {
|
|
386
|
+
uploaded = Math.min(uploaded + chunkSize, totalSize * 0.9);
|
|
387
|
+
onProgress(uploaded / totalSize, uploaded, totalSize);
|
|
388
|
+
}
|
|
389
|
+
}, 50);
|
|
390
|
+
try {
|
|
391
|
+
const response = await fetch(`${apiUrl}/api/assets/upload`, {
|
|
392
|
+
method: 'POST',
|
|
393
|
+
headers: {
|
|
394
|
+
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
|
395
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
396
|
+
},
|
|
397
|
+
body,
|
|
398
|
+
});
|
|
399
|
+
clearInterval(progressInterval);
|
|
400
|
+
onProgress(1, totalSize, totalSize);
|
|
401
|
+
if (!response.ok) {
|
|
402
|
+
const error = await response.json().catch(() => ({ error: 'Upload failed' }));
|
|
403
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
404
|
+
}
|
|
405
|
+
const result = await response.json();
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
clearInterval(progressInterval);
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Format file size for display
|
|
415
|
+
*/
|
|
416
|
+
function formatSize(bytes) {
|
|
417
|
+
if (bytes < 1024)
|
|
418
|
+
return `${bytes} B`;
|
|
419
|
+
if (bytes < 1024 * 1024)
|
|
420
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
421
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Create a progress bar string
|
|
425
|
+
*/
|
|
426
|
+
function createProgressBar(progress, width = 30) {
|
|
427
|
+
const filled = Math.round(width * progress);
|
|
428
|
+
const empty = width - filled;
|
|
429
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
430
|
+
const percentage = Math.round(progress * 100);
|
|
431
|
+
return `[${bar}] ${percentage}%`;
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NsaS9jb21tYW5kcy9kZXBsb3kudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUE0Q0Esd0JBa01DO0FBOU9ELGdEQUF1QjtBQUN2Qix3REFBeUI7QUFDekIseUNBQXlEO0FBQ3pELCtDQUEyQztBQUMzQywrQ0FBaUQ7QUFFakQsdUJBQXVCO0FBQ3ZCLE1BQU0sY0FBYyxHQUFHLEVBQUUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFBO0FBRXZDLCtDQUErQztBQUMvQyxNQUFNLGlCQUFpQixHQUFHO0lBQ3hCLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTTtJQUNoRCxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU07SUFDdkIsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNO0lBQ3RCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNO0lBQ3pDLE1BQU07Q0FDUCxDQUFBO0FBeUJEOztHQUVHO0FBQ0ksS0FBSyxVQUFVLE1BQU0sQ0FBQyxPQUFzQjtJQUNqRCxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUE7SUFDakMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsSUFBSSwyQkFBZSxDQUFBO0lBRTNFLGVBQU0sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsQ0FBQTtJQUV2QyxzQkFBc0I7SUFDdEIsTUFBTSxVQUFVLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDdEQsSUFBSSxDQUFDLGtCQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDL0IsZUFBTSxDQUFDLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFBO1FBQ3hELGVB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L0IsTUFBTSxLQUFLLENBQUE7SUFDYixDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxVQUFVLENBQUMsS0FBYTtJQUMvQixJQUFJLEtBQUssR0FBRyxJQUFJO1FBQUUsT0FBTyxHQUFHLEtBQUssSUFBSSxDQUFBO0lBQ3JDLElBQUksS0FBSyxHQUFHLElBQUksR0FBRyxJQUFJO1FBQUUsT0FBTyxHQUFHLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFBO0lBQ2pFLE9BQU8sR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFBO0FBQ25ELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsaUJBQWlCLENBQUMsUUFBZ0IsRUFBRSxRQUFnQixFQUFFO0lBQzdELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFBO0lBQzNDLE1BQU0sS0FBSyxHQUFHLEtBQUssR0FBRyxNQUFNLENBQUE7SUFDNUIsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ2xELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxDQUFBO0lBQzdDLE9BQU8sSUFBSSxHQUFHLEtBQUssVUFBVSxHQUFHLENBQUE7QUFDbEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5pbXBvcnQgZnMgZnJvbSAnZnMtZXh0cmEnXG5pbXBvcnQgeyBsb2FkQ29uZmlnLCB2YWxpZGF0ZUNvbmZpZyB9IGZyb20gJy4uLy4uL2NvbmZpZydcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlcidcbmltcG9ydCB7IERFRkFVTFRfQVBJX1VSTCB9IGZyb20gJy4uLy4uL2NvbnN0YW50cydcblxuLy8gTWF4IGFzc2V0IHNpemU6IDI1TUJcbmNvbnN0IE1BWF9BU1NFVF9TSVpFID0gMjUgKiAxMDI0ICogMTAyNFxuXG4vLyBCaW5hcnkgYXNzZXQgZXh0ZW5zaW9ucyB0byB1cGxvYWQgc2VwYXJhdGVseVxuY29uc3QgQklOQVJZX0VYVEVOU0lPTlMgPSBbXG4gICcucG5nJywgJy5qcGcnLCAnLmpwZWcnLCAnLmdpZicsICcud2VicCcsICcuaWNvJyxcbiAgJy5tcDQnLCAnLndlYm0nLCAnLm1vdicsXG4gICcubXAzJywgJy53YXYnLCAnLm9nZycsXG4gICcud29mZicsICcud29mZjInLCAnLnR0ZicsICcub3RmJywgJy5lb3QnLFxuICAnLnBkZicsXG5dXG5cbmludGVyZmFjZSBEZXBsb3lPcHRpb25zIHtcbiAgdXJsPzogc3RyaW5nXG4gIGFwaUtleT86IHN0cmluZ1xufVxuXG5pbnRlcmZhY2UgUHJvamVjdEZpbGUge1xuICBwYXRoOiBzdHJpbmdcbiAgY29udGVudDogc3RyaW5nXG59XG5cbmludGVyZmFjZSBBc3NldEZpbGUge1xuICBwYXRoOiBzdHJpbmdcbiAgZnVsbFBhdGg6IHN0cmluZ1xuICBzaXplOiBudW1iZXJcbn1cblxuaW50ZXJmYWNlIERldkRvY0NvbmZpZyB7XG4gIHNsdWc/OiBzdHJpbmdcbiAgYXBpS2V5Pzogc3RyaW5nXG4gIHVybD86IHN0cmluZ1xuICBsYXN0RGVwbG95ZWQ/OiBzdHJpbmdcbn1cblxuLyoqXG4gKiBEZXBsb3kgZG9jdW1lbnRhdGlvbiB0byBEZXZEb2MgcGxhdGZvcm1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlcGxveShvcHRpb25zOiBEZXBsb3lPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHByb2plY3RSb290ID0gcHJvY2Vzcy5jd2QoKVxuICBjb25zdCBhcGlVcmwgPSBvcHRpb25zLnVybCB8fCBwcm9jZXNzLmVudi5ERVZET0NfQVBJX1VSTCB8fCBERUZBVUxUX0FQSV9VUkxcbiAgXG4gIGxvZ2dlci5pbmZvKCdEZXBsb3lpbmcgdG8gRGV2RG9jLi4uXFxuJylcbiAgXG4gIC8vIENoZWNrIGZvciBkb2NzLmpzb25cbiAgY29uc3QgY29uZmlnUGF0aCA9IHBhdGguam9pbihwcm9qZWN0Um9vdCwgJ2RvY3MuanNvbicpXG4gIGlmICghZnMuZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgIGxvZ2dlci5lcnJvcignZG9jcy5qc29uIG5vdCBmb3VuZCBpbiBjdXJyZW50IGRpcmVjdG9yeScpXG4gICAgbG9nZ2VyLmluZm8oJ01ha2Ugc3VyZSB5b3UgYXJlIGluIGEgRGV2RG9jIGRvY3VtZW50YXRpb24gcHJvamVjdCBkaXJlY3RvcnknKVxuICAgIHByb2Nlc3MuZXhpdCgxKVxuICB9XG4gIFxuICAvLyBMb2FkIGFuZCB2YWxpZGF0ZSBjb25maWd1cmF0aW9uXG4gIGxldCBjb25maWc6IFJldHVyblR5cGU8dHlwZW9mIGxvYWRDb25maWc+IGV4dGVuZHMgUHJvbWlzZTxpbmZlciBUPiA/IFQgOiBuZXZlclxuICB0cnkge1xuICAgIGNvbmZpZyA9IGF3YWl0IGxvYWRDb25maWcocHJvamVjdFJvb3QpXG4gICAgY29uc3QgdmFsaWRhdGlvbiA9IHZhbGlkYXRlQ29uZmlnKGNvbmZpZylcbiAgICBcbiAgICBpZiAoIXZhbGlkYXRpb24udmFsaWQpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignSW52YWxpZCBkb2NzLmpzb24gY29uZmlndXJhdGlvbjonKVxuICAgICAgdmFsaWRhdGlvbi5lcnJvcnMuZm9yRWFjaChlcnIgPT4gbG9nZ2VyLmVycm9yKGAgIC0gJHtlcnJ9YCkpXG4gICAgICBwcm9jZXNzLmV4aXQoMSlcbiAgICB9XG4gICAgXG4gICAgbG9nZ2VyLnN1Y2Nlc3MoYOKckyBDb25maWd1cmF0aW9uIHZhbGlkOiAke2NvbmZpZy5uYW1lIHx8ICdVbnRpdGxlZCd9YClcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgbG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gbG9hZCBjb25maWd1cmF0aW9uOiAke21lc3NhZ2V9YClcbiAgICBwcm9jZXNzLmV4aXQoMSlcbiAgfVxuICBcbiAgLy8gQ2hlY2sgZm9yIGV4aXN0aW5nIHByb2plY3QgY29uZmlnXG4gIGNvbnN0IGRldmRvY0NvbmZpZ1BhdGggPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsICcuZGV2ZG9jLmpzb24nKVxuICBsZXQgZXhpc3RpbmdTbHVnOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICBsZXQgZXhpc3RpbmdBcGlLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsXG4gIFxuICBpZiAoZnMuZXhpc3RzU3luYyhkZXZkb2NDb25maWdQYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZXZkb2NDb25maWcgPSBmcy5yZWFkSnNvblN5bmMoZGV2ZG9jQ29uZmlnUGF0aCkgYXMgRGV2RG9jQ29uZmlnXG4gICAgICBleGlzdGluZ1NsdWcgPSBkZXZkb2NDb25maWcuc2x1ZyB8fCBudWxsXG4gICAgICBleGlzdGluZ0FwaUtleSA9IGRldmRvY0NvbmZpZy5hcGlLZXkgfHwgbnVsbFxuICAgICAgaWYgKGV4aXN0aW5nU2x1Zykge1xuICAgICAgICBsb2dnZXIuaW5mbyhgRGVwbG95aW5nIHByb2plY3Q6ICR7ZXhpc3RpbmdTbHVnfWApXG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBJZ25vcmUgZXJyb3JzIHJlYWRpbmcgLmRldmRvYy5qc29uXG4gICAgfVxuICB9XG4gIFxuICAvLyBHZXQgQVBJIGtleSBmcm9tIG9wdGlvbnMsIGVudiB2YXIsIG9yIC5kZXZkb2MuanNvblxuICBjb25zdCBhcGlLZXkgPSBvcHRpb25zLmFwaUtleSB8fCBwcm9jZXNzLmVudi5ERVZET0NfQVBJX0tFWSB8fCBleGlzdGluZ0FwaUtleVxuICBcbiAgLy8gQVBJIGtleSBpcyBhbHdheXMgcmVxdWlyZWQgZm9yIGRlcGxveW1lbnRcbiAgaWYgKCFhcGlLZXkpIHtcbiAgICBsb2dnZXIuZXJyb3IoJ0FQSSBrZXkgcmVxdWlyZWQgZm9yIGRlcGxveW1lbnQuJylcbiAgICBjb25zb2xlLmxvZygnJylcbiAgICBpZiAoIWV4aXN0aW5nU2x1Zykge1xuICAgICAgbG9nZ2VyLmluZm8oJ1J1biBcImRldmRvYyBpbml0XCIgZmlyc3QgdG8gcmVnaXN0ZXIgeW91ciBwcm9qZWN0IGFuZCBnZXQgYW4gQVBJIGtleScpXG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdZb3VyIHByb2plY3QgaXMgbm90IHJlZ2lzdGVyZWQuIFJ1biBcImRldmRvYyBpbml0IC0tZm9yY2VcIiB0byByZWdpc3RlciBhbmQgZ2V0IGFuIEFQSSBrZXknKVxuICAgIH1cbiAgICBsb2dnZXIuaW5mbygnT3IgcHJvdmlkZSB2aWEgLS1hcGkta2V5IGZsYWcgb3IgREVWRE9DX0FQSV9LRVkgZW52IHZhcicpXG4gICAgcHJvY2Vzcy5leGl0KDEpXG4gIH1cbiAgXG4gIC8vIENvbGxlY3QgYWxsIGNvbnRlbnQgZmlsZXNcbiAgbG9nZ2VyLmluZm8oJ0J1bmRsaW5nIGNvbnRlbnQuLi4nKVxuICBjb25zdCBmaWxlcyA9IGF3YWl0IGNvbGxlY3RGaWxlcyhwcm9qZWN0Um9vdClcbiAgbG9nZ2VyLnN1Y2Nlc3MoYOKckyBGb3VuZCAke2ZpbGVzLmxlbmd0aH0gY29udGVudCBmaWxlc2ApXG4gIFxuICAvLyBDb2xsZWN0IGJpbmFyeSBhc3NldHNcbiAgY29uc3QgYXNzZXRzID0gYXdhaXQgY29sbGVjdEFzc2V0cyhwcm9qZWN0Um9vdClcbiAgaWYgKGFzc2V0cy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgdG90YWxBc3NldFNpemUgPSBhc3NldHMucmVkdWNlKChzdW0sIGEpID0+IHN1bSArIGEuc2l6ZSwgMClcbiAgICBsb2dnZXIuc3VjY2Vzcyhg4pyTIEZvdW5kICR7YXNzZXRzLmxlbmd0aH0gYXNzZXRzICgke2Zvcm1hdFNpemUodG90YWxBc3NldFNpemUpfSlgKVxuICB9XG4gIFxuICAvLyBDYWxjdWxhdGUgYnVuZGxlIHNpemVcbiAgY29uc3QgdG90YWxTaXplID0gZmlsZXMucmVkdWNlKChzdW0sIGYpID0+IHN1bSArIGYuY29udGVudC5sZW5ndGgsIDApXG4gIGNvbnN0IHNpemVLQiA9ICh0b3RhbFNpemUgLyAxMDI0KS50b0ZpeGVkKDEpXG4gIGxvZ2dlci5pbmZvKGBDb250ZW50IGJ1bmRsZTogJHtzaXplS0J9IEtCYClcbiAgXG4gIC8vIFVwbG9hZCBiaW5hcnkgYXNzZXRzIGZpcnN0ICh3aXRoIHByb2dyZXNzKVxuICBpZiAoYXNzZXRzLmxlbmd0aCA+IDAgJiYgZXhpc3RpbmdTbHVnKSB7XG4gICAgY29uc29sZS5sb2coJycpXG4gICAgbG9nZ2VyLmluZm8oJ1VwbG9hZGluZyBhc3NldHMuLi4nKVxuICAgIFxuICAgIGNvbnN0IGFzc2V0UmVzdWx0cyA9IGF3YWl0IHVwbG9hZEFzc2V0cyhhc3NldHMsIGFwaVVybCwgZXhpc3RpbmdTbHVnLCBhcGlLZXkpXG4gICAgY29uc3Qgc3VjY2Vzc0NvdW50ID0gYXNzZXRSZXN1bHRzLmZpbHRlcihyID0+IHIuc3VjY2VzcykubGVuZ3RoXG4gICAgY29uc3QgZmFpbENvdW50ID0gYXNzZXRSZXN1bHRzLmZpbHRlcihyID0+ICFyLnN1Y2Nlc3MpLmxlbmd0aFxuICAgIFxuICAgIGlmIChmYWlsQ291bnQgPiAwKSB7XG4gICAgICBsb2dnZXIud2FybihgJHtzdWNjZXNzQ291bnR9IGFzc2V0cyB1cGxvYWRlZCwgJHtmYWlsQ291bnR9IGZhaWxlZGApXG4gICAgfSBlbHNlIGlmIChzdWNjZXNzQ291bnQgPiAwKSB7XG4gICAgICBsb2dnZXIuc3VjY2Vzcyhg4pyTICR7c3VjY2Vzc0NvdW50fSBhc3NldHMgdXBsb2FkZWRgKVxuICAgIH1cbiAgfSBlbHNlIGlmIChhc3NldHMubGVuZ3RoID4gMCAmJiAhZXhpc3RpbmdTbHVnKSB7XG4gICAgbG9nZ2VyLmluZm8oJ0Fzc2V0cyB3aWxsIGJlIHVwbG9hZGVkIG9uIG5leHQgZGVwbG95IChhZnRlciBwcm9qZWN0IHJlZ2lzdHJhdGlvbiknKVxuICB9XG4gIFxuICAvLyBEZXBsb3kgY29udGVudCB0byBBUElcbiAgY29uc29sZS5sb2coJycpXG4gIGxvZ2dlci5pbmZvKCdVcGxvYWRpbmcgY29udGVudC4uLicpXG4gIFxuICB0cnkge1xuICAgIGludGVyZmFjZSBEZXBsb3lSZXNwb25zZSB7XG4gICAgICBzdWNjZXNzOiBib29sZWFuXG4gICAgICBzbHVnOiBzdHJpbmdcbiAgICAgIHVybDogc3RyaW5nXG4gICAgICBibG9iVXJsOiBzdHJpbmdcbiAgICAgIGlzVXBkYXRlOiBib29sZWFuXG4gICAgICBmaWxlc0NvdW50OiBudW1iZXJcbiAgICAgIGFwaUtleT86IHN0cmluZ1xuICAgICAgZXJyb3I/OiBzdHJpbmdcbiAgICB9XG4gICAgXG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgfVxuICAgIFxuICAgIC8vIEFkZCBBUEkga2V5IGhlYWRlciBmb3IgdXBkYXRlc1xuICAgIGlmIChhcGlLZXkpIHtcbiAgICAgIGhlYWRlcnNbJ0F1dGhvcml6YXRpb24nXSA9IGBCZWFyZXIgJHthcGlLZXl9YFxuICAgIH1cbiAgICBcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke2FwaVVybH0vYXBpL2RlcGxveWAsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVycyxcbiAgICAgIHJlZGlyZWN0OiAnZm9sbG93JywgLy8gRm9sbG93IHJlZGlyZWN0c1xuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBuYW1lOiBjb25maWcubmFtZSB8fCAnTXkgRG9jdW1lbnRhdGlvbicsXG4gICAgICAgIHNsdWc6IGV4aXN0aW5nU2x1ZyxcbiAgICAgICAgZG9jc0pzb246IGNvbmZpZyxcbiAgICAgICAgZmlsZXMsXG4gICAgICAgIGFwaUtleSwgLy8gQWxzbyBzZW5kIGluIGJvZHkgYXMgZmFsbGJhY2tcbiAgICAgIH0pLFxuICAgIH0pXG4gICAgXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgY29uc3QgZXJyb3JEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpLmNhdGNoKCgpID0+ICh7IGVycm9yOiAnVW5rbm93biBlcnJvcicgfSkpIGFzIHsgZXJyb3I/OiBzdHJpbmc7IGRldGFpbHM/OiBzdHJpbmcgfVxuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3JEYXRhLmVycm9yIHx8IGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWBcbiAgICAgIGNvbnN0IGRldGFpbHMgPSBlcnJvckRhdGEuZGV0YWlscyA/IGBcXG4gICBEZXRhaWxzOiAke2Vycm9yRGF0YS5kZXRhaWxzfWAgOiAnJ1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vycm9yTWVzc2FnZX0ke2RldGFpbHN9YClcbiAgICB9XG4gICAgXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIERlcGxveVJlc3BvbnNlXG4gICAgXG4gICAgLy8gU2F2ZSBwcm9qZWN0IGNvbmZpZyBmb3IgZnV0dXJlIHVwZGF0ZXNcbiAgICBjb25zdCBuZXdEZXZEb2NDb25maWc6IERldkRvY0NvbmZpZyA9IHtcbiAgICAgIHNsdWc6IHJlc3VsdC5zbHVnLFxuICAgICAgdXJsOiByZXN1bHQudXJsLFxuICAgICAgbGFzdERlcGxveWVkOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgfVxuICAgIFxuICAgIC8vIFNhdmUgQVBJIGtleSAoZnJvbSByZXNwb25zZSBmb3IgbmV3IHByb2plY3RzLCBvciBleGlzdGluZyBmb3IgdXBkYXRlcylcbiAgICBpZiAocmVzdWx0LmFwaUtleSkge1xuICAgICAgbmV3RGV2RG9jQ29uZmlnLmFwaUtleSA9IHJlc3VsdC5hcGlLZXlcbiAgICB9IGVsc2UgaWYgKGFwaUtleSkge1xuICAgICAgbmV3RGV2RG9jQ29uZmlnLmFwaUtleSA9IGFwaUtleVxuICAgIH1cbiAgICBcbiAgICBmcy53cml0ZUpzb25TeW5jKGRldmRvY0NvbmZpZ1BhdGgsIG5ld0RldkRvY0NvbmZpZywgeyBzcGFjZXM6IDIgfSlcbiAgICBcbiAgICAvLyBTdWNjZXNzIG1lc3NhZ2VcbiAgICBjb25zb2xlLmxvZygnJylcbiAgICBsb2dnZXIuc3VjY2VzcygnRGVwbG95bWVudCBzdWNjZXNzZnVsIScpXG4gICAgY29uc29sZS5sb2coJycpXG4gICAgY29uc29sZS5sb2coYCAgWW91ciBkb2NzIGFyZSBsaXZlIGF0OmApXG4gICAgY29uc29sZS5sb2coYCAgJHtsb2dnZXIuY3lhbihyZXN1bHQudXJsKX1gKVxuICAgIGNvbnNvbGUubG9nKCcnKVxuICAgIFxuICAgIGlmIChyZXN1bHQuaXNVcGRhdGUpIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdQcm9qZWN0IHVwZGF0ZWQgd2l0aCBuZXcgY29udGVudCcpXG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5pbmZvKGBQcm9qZWN0IHNsdWc6ICR7cmVzdWx0LnNsdWd9YClcbiAgICAgIGxvZ2dlci5pbmZvKCdSdW4gXCJkZXZkb2MgZGVwbG95XCIgYWdhaW4gdG8gdXBkYXRlJylcbiAgICAgIFxuICAgICAgLy8gU2hvdyBBUEkga2V5IHdhcm5pbmcgZm9yIG5ldyBwcm9qZWN0c1xuICAgICAgaWYgKHJlc3VsdC5hcGlLZXkpIHtcbiAgICAgICAgY29uc29sZS5sb2coJycpXG4gICAgICAgIGxvZ2dlci53YXJuKCfimqDvuI8gIFNhdmUgeW91ciBBUEkga2V5IGZvciBDSS9DRCBkZXBsb3ltZW50czonKVxuICAgICAgICBjb25zb2xlLmxvZyhgICAgICR7cmVzdWx0LmFwaUtleX1gKVxuICAgICAgICBjb25zb2xlLmxvZygnJylcbiAgICAgICAgbG9nZ2VyLmluZm8oJ0FQSSBrZXkgc2F2ZWQgdG8gLmRldmRvYy5qc29uIChhZGQgdG8gLmdpdGlnbm9yZSEpJylcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgIGxvZ2dlci5lcnJvcihgRGVwbG95bWVudCBmYWlsZWQ6ICR7bWVzc2FnZX1gKVxuICAgIHByb2Nlc3MuZXhpdCgxKVxuICB9XG59XG5cbi8qKlxuICogQ29sbGVjdCBhbGwgTURYIGFuZCBjb250ZW50IGZpbGVzIGZyb20gdGhlIHByb2plY3RcbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29sbGVjdEZpbGVzKHByb2plY3RSb290OiBzdHJpbmcpOiBQcm9taXNlPFByb2plY3RGaWxlW10+IHtcbiAgY29uc3QgZmlsZXM6IFByb2plY3RGaWxlW10gPSBbXVxuICBcbiAgLy8gRGlyZWN0b3JpZXMgdG8gc2NhblxuICBjb25zdCBzY2FuRGlycyA9IFtcbiAgICAnJywgLy8gUm9vdCBkaXJlY3RvcnkgKGZvciBpbmRleC5tZHgsIHF1aWNrc3RhcnQubWR4LCBldGMuKVxuICAgICdndWlkZXMnLFxuICAgICdlc3NlbnRpYWxzJyxcbiAgICAnY29tcG9uZW50cycsXG4gICAgJ2FwaS1yZWZlcmVuY2UnLFxuICAgICdjaGFuZ2Vsb2cnLFxuICBdXG4gIFxuICBmb3IgKGNvbnN0IGRpciBvZiBzY2FuRGlycykge1xuICAgIGNvbnN0IGZ1bGxEaXIgPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsIGRpcilcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZnVsbERpcikpIGNvbnRpbnVlXG4gICAgXG4gICAgYXdhaXQgc2NhbkRpcmVjdG9yeShmdWxsRGlyLCBwcm9qZWN0Um9vdCwgZmlsZXMpXG4gIH1cbiAgXG4gIC8vIEluY2x1ZGUgdGV4dC1iYXNlZCBhc3NldHMgZnJvbSBhc3NldHMgZm9sZGVyIChuZXcgY29udmVudGlvbilcbiAgY29uc3QgYXNzZXRzRGlyID0gcGF0aC5qb2luKHByb2plY3RSb290LCAnYXNzZXRzJylcbiAgaWYgKGZzLmV4aXN0c1N5bmMoYXNzZXRzRGlyKSkge1xuICAgIGF3YWl0IHNjYW5QdWJsaWNBc3NldHMoYXNzZXRzRGlyLCBwcm9qZWN0Um9vdCwgZmlsZXMpXG4gIH1cbiAgXG4gIC8vIEFsc28gaW5jbHVkZSBwdWJsaWMgYXNzZXRzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICBjb25zdCBwdWJsaWNEaXIgPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsICdwdWJsaWMnKVxuICBpZiAoZnMuZXhpc3RzU3luYyhwdWJsaWNEaXIpKSB7XG4gICAgYXdhaXQgc2NhblB1YmxpY0Fzc2V0cyhwdWJsaWNEaXIsIHByb2plY3RSb290LCBmaWxlcylcbiAgfVxuICBcbiAgcmV0dXJuIGZpbGVzXG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgc2NhbiBhIGRpcmVjdG9yeSBmb3IgTURYIGZpbGVzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNjYW5EaXJlY3RvcnkoXG4gIGRpcjogc3RyaW5nLFxuICBwcm9qZWN0Um9vdDogc3RyaW5nLFxuICBmaWxlczogUHJvamVjdEZpbGVbXVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGl0ZW1zID0gZnMucmVhZGRpclN5bmMoZGlyKVxuICBcbiAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgLy8gU2tpcCBjb21tb24gZGlyZWN0b3JpZXNcbiAgICBpZiAoWydub2RlX21vZHVsZXMnLCAnZGlzdCcsICcubmV4dCcsICcuZ2l0JywgJ3B1YmxpYyddLmluY2x1ZGVzKGl0ZW0pKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXIsIGl0ZW0pXG4gICAgY29uc3Qgc3RhdCA9IGZzLnN0YXRTeW5jKGZ1bGxQYXRoKVxuICAgIFxuICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGF3YWl0IHNjYW5EaXJlY3RvcnkoZnVsbFBhdGgsIHByb2plY3RSb290LCBmaWxlcylcbiAgICB9IGVsc2UgaWYgKGl0ZW0uZW5kc1dpdGgoJy5tZHgnKSB8fCBpdGVtLmVuZHNXaXRoKCcubWQnKSkge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZShwcm9qZWN0Um9vdCwgZnVsbFBhdGgpXG4gICAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGZ1bGxQYXRoLCAndXRmLTgnKVxuICAgICAgXG4gICAgICBmaWxlcy5wdXNoKHtcbiAgICAgICAgcGF0aDogcmVsYXRpdmVQYXRoLFxuICAgICAgICBjb250ZW50LFxuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBTY2FuIHB1YmxpYyBhc3NldHMgKFNWRywgaW1hZ2VzKSAtIHRleHQtYmFzZWQgb25seSBmb3IgY29udGVudCBidW5kbGVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2NhblB1YmxpY0Fzc2V0cyhcbiAgZGlyOiBzdHJpbmcsXG4gIHByb2plY3RSb290OiBzdHJpbmcsXG4gIGZpbGVzOiBQcm9qZWN0RmlsZVtdXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgaXRlbXMgPSBmcy5yZWFkZGlyU3luYyhkaXIpXG4gIFxuICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXIsIGl0ZW0pXG4gICAgY29uc3Qgc3RhdCA9IGZzLnN0YXRTeW5jKGZ1bGxQYXRoKVxuICAgIFxuICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGF3YWl0IHNjYW5QdWJsaWNBc3NldHMoZnVsbFBhdGgsIHByb2plY3RSb290LCBmaWxlcylcbiAgICB9IGVsc2UgaWYgKGl0ZW0uZW5kc1dpdGgoJy5zdmcnKSB8fCBpdGVtLmVuZHNXaXRoKCcuanNvbicpKSB7XG4gICAgICAvLyBPbmx5IGluY2x1ZGUgdGV4dC1iYXNlZCBhc3NldHMgaW4gY29udGVudCBidW5kbGVcbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGgucmVsYXRpdmUocHJvamVjdFJvb3QsIGZ1bGxQYXRoKVxuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmdWxsUGF0aCwgJ3V0Zi04JylcbiAgICAgIFxuICAgICAgZmlsZXMucHVzaCh7XG4gICAgICAgIHBhdGg6IHJlbGF0aXZlUGF0aCxcbiAgICAgICAgY29udGVudCxcbiAgICAgIH0pXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29sbGVjdCBiaW5hcnkgYXNzZXRzIGZyb20gYXNzZXRzIGZvbGRlciAoY29udmVudGlvbjogL2Fzc2V0cylcbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29sbGVjdEFzc2V0cyhwcm9qZWN0Um9vdDogc3RyaW5nKTogUHJvbWlzZTxBc3NldEZpbGVbXT4ge1xuICBjb25zdCBhc3NldHM6IEFzc2V0RmlsZVtdID0gW11cbiAgXG4gIC8vIENoZWNrIGFzc2V0cyBmb2xkZXIgZmlyc3QgKG5ldyBjb252ZW50aW9uKVxuICBjb25zdCBhc3NldHNEaXIgPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsICdhc3NldHMnKVxuICBpZiAoZnMuZXhpc3RzU3luYyhhc3NldHNEaXIpKSB7XG4gICAgYXdhaXQgc2NhbkJpbmFyeUFzc2V0cyhhc3NldHNEaXIsIHByb2plY3RSb290LCBhc3NldHMpXG4gIH1cbiAgXG4gIC8vIEFsc28gY2hlY2sgcHVibGljIGZvbGRlciBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgY29uc3QgcHVibGljRGlyID0gcGF0aC5qb2luKHByb2plY3RSb290LCAncHVibGljJylcbiAgaWYgKGZzLmV4aXN0c1N5bmMocHVibGljRGlyKSkge1xuICAgIGF3YWl0IHNjYW5CaW5hcnlBc3NldHMocHVibGljRGlyLCBwcm9qZWN0Um9vdCwgYXNzZXRzKVxuICB9XG4gIFxuICByZXR1cm4gYXNzZXRzXG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgc2NhbiBmb3IgYmluYXJ5IGFzc2V0c1xuICovXG5hc3luYyBmdW5jdGlvbiBzY2FuQmluYXJ5QXNzZXRzKFxuICBkaXI6IHN0cmluZyxcbiAgcHJvamVjdFJvb3Q6IHN0cmluZyxcbiAgYXNzZXRzOiBBc3NldEZpbGVbXVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGl0ZW1zID0gZnMucmVhZGRpclN5bmMoZGlyKVxuICBcbiAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyLCBpdGVtKVxuICAgIGNvbnN0IHN0YXQgPSBmcy5zdGF0U3luYyhmdWxsUGF0aClcbiAgICBcbiAgICBpZiAoc3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBhd2FpdCBzY2FuQmluYXJ5QXNzZXRzKGZ1bGxQYXRoLCBwcm9qZWN0Um9vdCwgYXNzZXRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBleHQgPSBwYXRoLmV4dG5hbWUoaXRlbSkudG9Mb3dlckNhc2UoKVxuICAgICAgaWYgKEJJTkFSWV9FWFRFTlNJT05TLmluY2x1ZGVzKGV4dCkpIHtcbiAgICAgICAgLy8gQ2hlY2sgc2l6ZSBsaW1pdFxuICAgICAgICBpZiAoc3RhdC5zaXplID4gTUFYX0FTU0VUX1NJWkUpIHtcbiAgICAgICAgICBsb2dnZXIud2FybihgU2tpcHBpbmcgJHtpdGVtfTogZXhjZWVkcyAyNU1CIGxpbWl0ICgke2Zvcm1hdFNpemUoc3RhdC5zaXplKX0pYClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBwYXRoLnJlbGF0aXZlKHByb2plY3RSb290LCBmdWxsUGF0aClcbiAgICAgICAgYXNzZXRzLnB1c2goe1xuICAgICAgICAgIHBhdGg6IHJlbGF0aXZlUGF0aCxcbiAgICAgICAgICBmdWxsUGF0aCxcbiAgICAgICAgICBzaXplOiBzdGF0LnNpemUsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVXBsb2FkIGFzc2V0cyB3aXRoIHByb2dyZXNzIHRyYWNraW5nXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHVwbG9hZEFzc2V0cyhcbiAgYXNzZXRzOiBBc3NldEZpbGVbXSxcbiAgYXBpVXJsOiBzdHJpbmcsXG4gIHNsdWc6IHN0cmluZyxcbiAgYXBpS2V5OiBzdHJpbmdcbik6IFByb21pc2U8QXJyYXk8eyBmaWxlOiBzdHJpbmc7IHN1Y2Nlc3M6IGJvb2xlYW47IHVybD86IHN0cmluZzsgZXJyb3I/OiBzdHJpbmcgfT4+IHtcbiAgY29uc3QgcmVzdWx0czogQXJyYXk8eyBmaWxlOiBzdHJpbmc7IHN1Y2Nlc3M6IGJvb2xlYW47IHVybD86IHN0cmluZzsgZXJyb3I/OiBzdHJpbmcgfT4gPSBbXVxuICBcbiAgZm9yIChjb25zdCBhc3NldCBvZiBhc3NldHMpIHtcbiAgICBjb25zdCBmaWxlTmFtZSA9IHBhdGguYmFzZW5hbWUoYXNzZXQucGF0aClcbiAgICBcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgICAke2ZpbGVOYW1lfTogYClcbiAgICBcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdXBsb2FkQXNzZXRXaXRoUHJvZ3Jlc3MoXG4gICAgICAgIGFzc2V0LFxuICAgICAgICBhcGlVcmwsXG4gICAgICAgIHNsdWcsXG4gICAgICAgIGFwaUtleSxcbiAgICAgICAgKHByb2dyZXNzLCBsb2FkZWQsIHRvdGFsKSA9PiB7XG4gICAgICAgICAgcHJvY2Vzcy5zdGRvdXQuY2xlYXJMaW5lKDApXG4gICAgICAgICAgcHJvY2Vzcy5zdGRvdXQuY3Vyc29yVG8oMClcbiAgICAgICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgICAke2ZpbGVOYW1lfTogJHtjcmVhdGVQcm9ncmVzc0Jhcihwcm9ncmVzcyl9ICR7Zm9ybWF0U2l6ZShsb2FkZWQpfS8ke2Zvcm1hdFNpemUodG90YWwpfWApXG4gICAgICAgIH1cbiAgICAgIClcbiAgICAgIFxuICAgICAgcHJvY2Vzcy5zdGRvdXQuY2xlYXJMaW5lKDApXG4gICAgICBwcm9jZXNzLnN0ZG91dC5jdXJzb3JUbygwKVxuICAgICAgY29uc29sZS5sb2coYCAgJHtsb2dnZXIuZ3JlZW4oJ+KckycpfSAke2ZpbGVOYW1lfSAoJHtmb3JtYXRTaXplKGFzc2V0LnNpemUpfSlgKVxuICAgICAgXG4gICAgICByZXN1bHRzLnB1c2goeyBmaWxlOiBmaWxlTmFtZSwgc3VjY2VzczogdHJ1ZSwgdXJsOiByZXN1bHQudXJsIH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgIFxuICAgICAgcHJvY2Vzcy5zdGRvdXQuY2xlYXJMaW5lKDApXG4gICAgICBwcm9jZXNzLnN0ZG91dC5jdXJzb3JUbygwKVxuICAgICAgY29uc29sZS5sb2coYCAgJHtsb2dnZXIucmVkKCfinJcnKX0gJHtmaWxlTmFtZX06ICR7bWVzc2FnZX1gKVxuICAgICAgXG4gICAgICByZXN1bHRzLnB1c2goeyBmaWxlOiBmaWxlTmFtZSwgc3VjY2VzczogZmFsc2UsIGVycm9yOiBtZXNzYWdlIH0pXG4gICAgfVxuICB9XG4gIFxuICByZXR1cm4gcmVzdWx0c1xufVxuXG4vKipcbiAqIFVwbG9hZCBhIHNpbmdsZSBhc3NldCB3aXRoIHByb2dyZXNzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHVwbG9hZEFzc2V0V2l0aFByb2dyZXNzKFxuICBhc3NldDogQXNzZXRGaWxlLFxuICBhcGlVcmw6IHN0cmluZyxcbiAgc2x1Zzogc3RyaW5nLFxuICBhcGlLZXk6IHN0cmluZyxcbiAgb25Qcm9ncmVzczogKHByb2dyZXNzOiBudW1iZXIsIGxvYWRlZDogbnVtYmVyLCB0b3RhbDogbnVtYmVyKSA9PiB2b2lkXG4pOiBQcm9taXNlPHsgdXJsOiBzdHJpbmcgfT4ge1xuICBjb25zdCBmaWxlQnVmZmVyID0gZnMucmVhZEZpbGVTeW5jKGFzc2V0LmZ1bGxQYXRoKVxuICBjb25zdCBmaWxlTmFtZSA9IHBhdGguYmFzZW5hbWUoYXNzZXQucGF0aClcbiAgXG4gIC8vIEJ1aWxkIG11bHRpcGFydCBmb3JtIGRhdGFcbiAgY29uc3QgYm91bmRhcnkgPSBgLS0tLURldkRvY0RlcGxveSR7RGF0ZS5ub3coKX1gXG4gIGNvbnN0IENSTEYgPSAnXFxyXFxuJ1xuICBcbiAgY29uc3QgaGVhZGVyID0gW1xuICAgIGAtLSR7Ym91bmRhcnl9YCxcbiAgICBgQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPVwiZmlsZVwiOyBmaWxlbmFtZT1cIiR7ZmlsZU5hbWV9XCJgLFxuICAgIGBDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbWAsXG4gICAgJycsXG4gICAgJydcbiAgXS5qb2luKENSTEYpXG4gIFxuICBjb25zdCBzbHVnUGFydCA9IFtcbiAgICAnJyxcbiAgICBgLS0ke2JvdW5kYXJ5fWAsXG4gICAgYENvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT1cInNsdWdcImAsXG4gICAgJycsXG4gICAgc2x1ZyxcbiAgICAnJ1xuICBdLmpvaW4oQ1JMRilcbiAgXG4gIGNvbnN0IHBhdGhQYXJ0ID0gW1xuICAgIGAtLSR7Ym91bmRhcnl9YCxcbiAgICBgQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPVwicGF0aFwiYCxcbiAgICAnJyxcbiAgICBhc3NldC5wYXRoLnJlcGxhY2UoL15wdWJsaWNcXC8vLCAnJyksIC8vIFJlbW92ZSBwdWJsaWMvIHByZWZpeFxuICAgICcnXG4gIF0uam9pbihDUkxGKVxuICBcbiAgY29uc3QgZm9vdGVyID0gYCR7Q1JMRn0tLSR7Ym91bmRhcnl9LS0ke0NSTEZ9YFxuICBcbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gQnVmZmVyLmZyb20oaGVhZGVyKVxuICBjb25zdCBzbHVnQnVmZmVyID0gQnVmZmVyLmZyb20oc2x1Z1BhcnQpXG4gIGNvbnN0IHBhdGhCdWZmZXIgPSBCdWZmZXIuZnJvbShwYXRoUGFydClcbiAgY29uc3QgZm9vdGVyQnVmZmVyID0gQnVmZmVyLmZyb20oZm9vdGVyKVxuICBcbiAgY29uc3QgdG90YWxTaXplID0gaGVhZGVyQnVmZmVyLmxlbmd0aCArIGZpbGVCdWZmZXIubGVuZ3RoICsgc2x1Z0J1ZmZlci5sZW5ndGggKyBwYXRoQnVmZmVyLmxlbmd0aCArIGZvb3RlckJ1ZmZlci5sZW5ndGhcbiAgY29uc3QgYm9keSA9IEJ1ZmZlci5jb25jYXQoW2hlYWRlckJ1ZmZlciwgZmlsZUJ1ZmZlciwgc2x1Z0J1ZmZlciwgcGF0aEJ1ZmZlciwgZm9vdGVyQnVmZmVyXSlcbiAgXG4gIC8vIFNpbXVsYXRlIHByb2dyZXNzXG4gIGxldCB1cGxvYWRlZCA9IDBcbiAgY29uc3QgY2h1bmtTaXplID0gTWF0aC5jZWlsKHRvdGFsU2l6ZSAvIDIwKVxuICBcbiAgY29uc3QgcHJvZ3Jlc3NJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICBpZiAodXBsb2FkZWQgPCB0b3RhbFNpemUgKiAwLjkpIHtcbiAgICAgIHVwbG9hZGVkID0gTWF0aC5taW4odXBsb2FkZWQgKyBjaHVua1NpemUsIHRvdGFsU2l6ZSAqIDAuOSlcbiAgICAgIG9uUHJvZ3Jlc3ModXBsb2FkZWQgLyB0b3RhbFNpemUsIHVwbG9hZGVkLCB0b3RhbFNpemUpXG4gICAgfVxuICB9LCA1MClcbiAgXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHthcGlVcmx9L2FwaS9hc3NldHMvdXBsb2FkYCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiBgbXVsdGlwYXJ0L2Zvcm0tZGF0YTsgYm91bmRhcnk9JHtib3VuZGFyeX1gLFxuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgIH0sXG4gICAgICBib2R5LFxuICAgIH0pXG4gICAgXG4gICAgY2xlYXJJbnRlcnZhbChwcm9ncmVzc0ludGVydmFsKVxuICAgIG9uUHJvZ3Jlc3MoMSwgdG90YWxTaXplLCB0b3RhbFNpemUpXG4gICAgXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgY29uc3QgZXJyb3IgPSBhd2FpdCByZXNwb25zZS5qc29uKCkuY2F0Y2goKCkgPT4gKHsgZXJyb3I6ICdVcGxvYWQgZmFpbGVkJyB9KSkgYXMgeyBlcnJvcj86IHN0cmluZyB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IuZXJyb3IgfHwgYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9YClcbiAgICB9XG4gICAgXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIHsgdXJsOiBzdHJpbmcgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjbGVhckludGVydmFsKHByb2dyZXNzSW50ZXJ2YWwpXG4gICAgdGhyb3cgZXJyb3JcbiAgfVxufVxuXG4vKipcbiAqIEZvcm1hdCBmaWxlIHNpemUgZm9yIGRpc3BsYXlcbiAqL1xuZnVuY3Rpb24gZm9ybWF0U2l6ZShieXRlczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKGJ5dGVzIDwgMTAyNCkgcmV0dXJuIGAke2J5dGVzfSBCYFxuICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCkgcmV0dXJuIGAkeyhieXRlcyAvIDEwMjQpLnRvRml4ZWQoMSl9IEtCYFxuICByZXR1cm4gYCR7KGJ5dGVzIC8gKDEwMjQgKiAxMDI0KSkudG9GaXhlZCgyKX0gTUJgXG59XG5cbi8qKlxuICogQ3JlYXRlIGEgcHJvZ3Jlc3MgYmFyIHN0cmluZ1xuICovXG5mdW5jdGlvbiBjcmVhdGVQcm9ncmVzc0Jhcihwcm9ncmVzczogbnVtYmVyLCB3aWR0aDogbnVtYmVyID0gMzApOiBzdHJpbmcge1xuICBjb25zdCBmaWxsZWQgPSBNYXRoLnJvdW5kKHdpZHRoICogcHJvZ3Jlc3MpXG4gIGNvbnN0IGVtcHR5ID0gd2lkdGggLSBmaWxsZWRcbiAgY29uc3QgYmFyID0gJ+KWiCcucmVwZWF0KGZpbGxlZCkgKyAn4paRJy5yZXBlYXQoZW1wdHkpXG4gIGNvbnN0IHBlcmNlbnRhZ2UgPSBNYXRoLnJvdW5kKHByb2dyZXNzICogMTAwKVxuICByZXR1cm4gYFske2Jhcn1dICR7cGVyY2VudGFnZX0lYFxufVxuIl19
|