@pipeline-builder/pipeline-manager 0.0.1
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 +202 -0
- package/README.md +145 -0
- package/cdk.json +91 -0
- package/config.yml +94 -0
- package/dist/agent/ai.d.ts +48 -0
- package/dist/agent/ai.d.ts.map +1 -0
- package/dist/agent/ai.js +149 -0
- package/dist/agent/bootstrap.d.ts +39 -0
- package/dist/agent/bootstrap.d.ts.map +1 -0
- package/dist/agent/bootstrap.js +66 -0
- package/dist/agent/env-file.d.ts +17 -0
- package/dist/agent/env-file.d.ts.map +1 -0
- package/dist/agent/env-file.js +47 -0
- package/dist/agent/executor.d.ts +30 -0
- package/dist/agent/executor.d.ts.map +1 -0
- package/dist/agent/executor.js +60 -0
- package/dist/agent/health.d.ts +43 -0
- package/dist/agent/health.d.ts.map +1 -0
- package/dist/agent/health.js +109 -0
- package/dist/agent/ports.d.ts +26 -0
- package/dist/agent/ports.d.ts.map +1 -0
- package/dist/agent/ports.js +132 -0
- package/dist/agent/post-steps.d.ts +61 -0
- package/dist/agent/post-steps.d.ts.map +1 -0
- package/dist/agent/post-steps.js +131 -0
- package/dist/agent/prereqs.d.ts +26 -0
- package/dist/agent/prereqs.d.ts.map +1 -0
- package/dist/agent/prereqs.js +134 -0
- package/dist/agent/targets.d.ts +128 -0
- package/dist/agent/targets.d.ts.map +1 -0
- package/dist/agent/targets.js +265 -0
- package/dist/agent/tools.d.ts +13 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +75 -0
- package/dist/agent/troubleshoot.d.ts +30 -0
- package/dist/agent/troubleshoot.d.ts.map +1 -0
- package/dist/agent/troubleshoot.js +87 -0
- package/dist/boilerplate.d.ts +3 -0
- package/dist/boilerplate.d.ts.map +1 -0
- package/dist/boilerplate.js +54 -0
- package/dist/cdk.json +91 -0
- package/dist/cli.d.ts +62 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +463 -0
- package/dist/commands/audit-stacks.d.ts +24 -0
- package/dist/commands/audit-stacks.d.ts.map +1 -0
- package/dist/commands/audit-stacks.js +182 -0
- package/dist/commands/audit-tokens.d.ts +21 -0
- package/dist/commands/audit-tokens.d.ts.map +1 -0
- package/dist/commands/audit-tokens.js +153 -0
- package/dist/commands/bootstrap.d.ts +11 -0
- package/dist/commands/bootstrap.d.ts.map +1 -0
- package/dist/commands/bootstrap.js +159 -0
- package/dist/commands/create-pat.d.ts +27 -0
- package/dist/commands/create-pat.d.ts.map +1 -0
- package/dist/commands/create-pat.js +194 -0
- package/dist/commands/create-pipeline.d.ts +12 -0
- package/dist/commands/create-pipeline.d.ts.map +1 -0
- package/dist/commands/create-pipeline.js +315 -0
- package/dist/commands/deploy.d.ts +15 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +157 -0
- package/dist/commands/entity-get.d.ts +51 -0
- package/dist/commands/entity-get.d.ts.map +1 -0
- package/dist/commands/entity-get.js +69 -0
- package/dist/commands/entity-list.d.ts +39 -0
- package/dist/commands/entity-list.d.ts.map +1 -0
- package/dist/commands/entity-list.js +88 -0
- package/dist/commands/get-pipeline.d.ts +13 -0
- package/dist/commands/get-pipeline.d.ts.map +1 -0
- package/dist/commands/get-pipeline.js +49 -0
- package/dist/commands/get-plugin.d.ts +13 -0
- package/dist/commands/get-plugin.d.ts.map +1 -0
- package/dist/commands/get-plugin.js +51 -0
- package/dist/commands/instantiate-template.d.ts +20 -0
- package/dist/commands/instantiate-template.d.ts.map +1 -0
- package/dist/commands/instantiate-template.js +274 -0
- package/dist/commands/list-pipelines.d.ts +20 -0
- package/dist/commands/list-pipelines.d.ts.map +1 -0
- package/dist/commands/list-pipelines.js +99 -0
- package/dist/commands/list-plugins.d.ts +20 -0
- package/dist/commands/list-plugins.d.ts.map +1 -0
- package/dist/commands/list-plugins.js +92 -0
- package/dist/commands/login.d.ts +21 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +174 -0
- package/dist/commands/new-plugin.d.ts +12 -0
- package/dist/commands/new-plugin.d.ts.map +1 -0
- package/dist/commands/new-plugin.js +129 -0
- package/dist/commands/org-export.d.ts +25 -0
- package/dist/commands/org-export.d.ts.map +1 -0
- package/dist/commands/org-export.js +100 -0
- package/dist/commands/provision.d.ts +122 -0
- package/dist/commands/provision.d.ts.map +1 -0
- package/dist/commands/provision.js +867 -0
- package/dist/commands/redrive-events.d.ts +24 -0
- package/dist/commands/redrive-events.d.ts.map +1 -0
- package/dist/commands/redrive-events.js +127 -0
- package/dist/commands/register.d.ts +38 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +160 -0
- package/dist/commands/setup-events.d.ts +15 -0
- package/dist/commands/setup-events.d.ts.map +1 -0
- package/dist/commands/setup-events.js +168 -0
- package/dist/commands/status.d.ts +11 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +81 -0
- package/dist/commands/store-token.d.ts +26 -0
- package/dist/commands/store-token.d.ts.map +1 -0
- package/dist/commands/store-token.js +305 -0
- package/dist/commands/synth.d.ts +21 -0
- package/dist/commands/synth.d.ts.map +1 -0
- package/dist/commands/synth.js +158 -0
- package/dist/commands/upload-plugin.d.ts +21 -0
- package/dist/commands/upload-plugin.d.ts.map +1 -0
- package/dist/commands/upload-plugin.js +275 -0
- package/dist/commands/validate-plugin.d.ts +12 -0
- package/dist/commands/validate-plugin.d.ts.map +1 -0
- package/dist/commands/validate-plugin.js +175 -0
- package/dist/commands/validate-templates.d.ts +11 -0
- package/dist/commands/validate-templates.d.ts.map +1 -0
- package/dist/commands/validate-templates.js +116 -0
- package/dist/commands/version.d.ts +12 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +216 -0
- package/dist/config/cli.constants.d.ts +116 -0
- package/dist/config/cli.constants.d.ts.map +1 -0
- package/dist/config/cli.constants.js +194 -0
- package/dist/config.yml +94 -0
- package/dist/lambda/token-renew-handler.d.ts +2 -0
- package/dist/lambda/token-renew-handler.d.ts.map +1 -0
- package/dist/lambda/token-renew-handler.js +125 -0
- package/dist/templates/events-stack.json +174 -0
- package/dist/templates/token-renew-stack.json +122 -0
- package/dist/types/config.d.ts +53 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +4 -0
- package/dist/types/error.d.ts +61 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +35 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/pipeline-template.d.ts +48 -0
- package/dist/types/pipeline-template.d.ts.map +1 -0
- package/dist/types/pipeline-template.js +4 -0
- package/dist/types/pipeline.d.ts +121 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +4 -0
- package/dist/types/plugin.d.ts +135 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +4 -0
- package/dist/utils/api-client.d.ts +26 -0
- package/dist/utils/api-client.d.ts.map +1 -0
- package/dist/utils/api-client.js +151 -0
- package/dist/utils/audit-log.d.ts +8 -0
- package/dist/utils/audit-log.d.ts.map +1 -0
- package/dist/utils/audit-log.js +57 -0
- package/dist/utils/auth-guard.d.ts +20 -0
- package/dist/utils/auth-guard.d.ts.map +1 -0
- package/dist/utils/auth-guard.js +22 -0
- package/dist/utils/auth-utils.d.ts +68 -0
- package/dist/utils/auth-utils.d.ts.map +1 -0
- package/dist/utils/auth-utils.js +77 -0
- package/dist/utils/aws-env.d.ts +21 -0
- package/dist/utils/aws-env.d.ts.map +1 -0
- package/dist/utils/aws-env.js +34 -0
- package/dist/utils/aws-secrets.d.ts +48 -0
- package/dist/utils/aws-secrets.d.ts.map +1 -0
- package/dist/utils/aws-secrets.js +115 -0
- package/dist/utils/banner.d.ts +19 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +52 -0
- package/dist/utils/cdk-utils.d.ts +74 -0
- package/dist/utils/cdk-utils.d.ts.map +1 -0
- package/dist/utils/cdk-utils.js +152 -0
- package/dist/utils/command-utils.d.ts +75 -0
- package/dist/utils/command-utils.d.ts.map +1 -0
- package/dist/utils/command-utils.js +155 -0
- package/dist/utils/config-loader.d.ts +33 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +154 -0
- package/dist/utils/cron.d.ts +28 -0
- package/dist/utils/cron.d.ts.map +1 -0
- package/dist/utils/cron.js +119 -0
- package/dist/utils/deploy-runner.d.ts +38 -0
- package/dist/utils/deploy-runner.d.ts.map +1 -0
- package/dist/utils/deploy-runner.js +112 -0
- package/dist/utils/error-handler.d.ts +29 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +302 -0
- package/dist/utils/list-command-utils.d.ts +23 -0
- package/dist/utils/list-command-utils.d.ts.map +1 -0
- package/dist/utils/list-command-utils.js +57 -0
- package/dist/utils/output-utils.d.ts +40 -0
- package/dist/utils/output-utils.d.ts.map +1 -0
- package/dist/utils/output-utils.js +250 -0
- package/dist/utils/pipeline-config.d.ts +33 -0
- package/dist/utils/pipeline-config.d.ts.map +1 -0
- package/dist/utils/pipeline-config.js +55 -0
- package/dist/utils/platform-secret.d.ts +27 -0
- package/dist/utils/platform-secret.d.ts.map +1 -0
- package/dist/utils/platform-secret.js +92 -0
- package/dist/utils/plugin-resolver.d.ts +17 -0
- package/dist/utils/plugin-resolver.d.ts.map +1 -0
- package/dist/utils/plugin-resolver.js +101 -0
- package/dist/utils/preflight.d.ts +26 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +59 -0
- package/dist/utils/rate-limiter.d.ts +15 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +164 -0
- package/dist/utils/registry.d.ts +86 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +140 -0
- package/dist/utils/response-utils.d.ts +21 -0
- package/dist/utils/response-utils.d.ts.map +1 -0
- package/dist/utils/response-utils.js +70 -0
- package/dist/utils/tls.d.ts +52 -0
- package/dist/utils/tls.d.ts.map +1 -0
- package/dist/utils/tls.js +88 -0
- package/package.json +181 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { realpathSync } from 'node:fs';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { program } from 'commander';
|
|
7
|
+
import { auditStacks } from './commands/audit-stacks.js';
|
|
8
|
+
import { auditTokens } from './commands/audit-tokens.js';
|
|
9
|
+
import { bootstrap } from './commands/bootstrap.js';
|
|
10
|
+
import { createPat } from './commands/create-pat.js';
|
|
11
|
+
import { createPipeline } from './commands/create-pipeline.js';
|
|
12
|
+
import { deploy } from './commands/deploy.js';
|
|
13
|
+
import { getPipeline } from './commands/get-pipeline.js';
|
|
14
|
+
import { getPlugin } from './commands/get-plugin.js';
|
|
15
|
+
import { instantiateTemplate } from './commands/instantiate-template.js';
|
|
16
|
+
import { listPipelines } from './commands/list-pipelines.js';
|
|
17
|
+
import { listPlugins } from './commands/list-plugins.js';
|
|
18
|
+
import { login } from './commands/login.js';
|
|
19
|
+
import { newPlugin } from './commands/new-plugin.js';
|
|
20
|
+
import { orgExport } from './commands/org-export.js';
|
|
21
|
+
import { provision } from './commands/provision.js';
|
|
22
|
+
import { redriveEvents } from './commands/redrive-events.js';
|
|
23
|
+
import { register } from './commands/register.js';
|
|
24
|
+
import { setupEvents } from './commands/setup-events.js';
|
|
25
|
+
import { status } from './commands/status.js';
|
|
26
|
+
import { storeToken } from './commands/store-token.js';
|
|
27
|
+
import { synth } from './commands/synth.js';
|
|
28
|
+
import { uploadPlugin } from './commands/upload-plugin.js';
|
|
29
|
+
import { validatePlugin } from './commands/validate-plugin.js';
|
|
30
|
+
import { validateTemplatesCommand } from './commands/validate-templates.js';
|
|
31
|
+
import { version } from './commands/version.js';
|
|
32
|
+
import { APP_NAME, APP_DESCRIPTION, APP_VERSION, ENV_VARS, isDebugMode, generateExecutionId, } from './config/cli.constants.js';
|
|
33
|
+
import { banner, miniBanner } from './utils/banner.js';
|
|
34
|
+
import { ERROR_CODES, handleError } from './utils/error-handler.js';
|
|
35
|
+
import { printInfo, printError, printWarning, printDebug, printSection } from './utils/output-utils.js';
|
|
36
|
+
import { preflightCommandTools } from './utils/preflight.js';
|
|
37
|
+
/**
|
|
38
|
+
* Check environment and display warnings
|
|
39
|
+
*/
|
|
40
|
+
function checkEnvironment() {
|
|
41
|
+
const warnings = [];
|
|
42
|
+
// Check for required environment variables
|
|
43
|
+
if (!process.env[ENV_VARS.PLATFORM_TOKEN]) {
|
|
44
|
+
warnings.push('PLATFORM_TOKEN environment variable is not set');
|
|
45
|
+
warnings.push('Authentication will fail for API operations');
|
|
46
|
+
}
|
|
47
|
+
// Check Node version
|
|
48
|
+
const nodeVersion = process.version;
|
|
49
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0] || '0', 10);
|
|
50
|
+
if (majorVersion < 24) {
|
|
51
|
+
warnings.push(`Node.js ${nodeVersion} detected - version 24+ required (see package.json engines)`);
|
|
52
|
+
}
|
|
53
|
+
// Display warnings
|
|
54
|
+
if (warnings.length > 0) {
|
|
55
|
+
printSection('Environment Warnings');
|
|
56
|
+
warnings.forEach(warning => {
|
|
57
|
+
printWarning(warning);
|
|
58
|
+
});
|
|
59
|
+
console.log('');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Display startup information
|
|
64
|
+
*/
|
|
65
|
+
function displayStartupInfo(options) {
|
|
66
|
+
if (options.quiet)
|
|
67
|
+
return;
|
|
68
|
+
const executionId = generateExecutionId();
|
|
69
|
+
if (options.debug || options.verbose) {
|
|
70
|
+
printDebug('CLI Configuration', {
|
|
71
|
+
name: APP_NAME,
|
|
72
|
+
version: APP_VERSION,
|
|
73
|
+
executionId,
|
|
74
|
+
node: process.version,
|
|
75
|
+
platform: process.platform,
|
|
76
|
+
arch: process.arch,
|
|
77
|
+
cwd: process.cwd(),
|
|
78
|
+
env: {
|
|
79
|
+
debug: process.env.DEBUG,
|
|
80
|
+
token: process.env[ENV_VARS.PLATFORM_TOKEN] ? 'set' : 'not set',
|
|
81
|
+
url: process.env[ENV_VARS.PLATFORM_BASE_URL] || 'default',
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
printDebug('Starting CLI', {
|
|
87
|
+
version: APP_VERSION,
|
|
88
|
+
executionId,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Register all CLI commands
|
|
94
|
+
*/
|
|
95
|
+
function registerCommands() {
|
|
96
|
+
printDebug('Registering commands');
|
|
97
|
+
// Configure program
|
|
98
|
+
program
|
|
99
|
+
.name(APP_NAME)
|
|
100
|
+
.description(APP_DESCRIPTION)
|
|
101
|
+
.version(APP_VERSION, '-v, --version', 'Show CLI version')
|
|
102
|
+
.option('--debug', 'Enable debug output with stack traces', false)
|
|
103
|
+
.option('--verbose', 'Show detailed information', false)
|
|
104
|
+
.option('--quiet', 'Minimal output (errors only)', false)
|
|
105
|
+
.option('--no-color', 'Disable colored output', false)
|
|
106
|
+
.addHelpText('after', `
|
|
107
|
+
Command groups:
|
|
108
|
+
auth Authenticate and manage credentials (login, pat)
|
|
109
|
+
pipeline Create, inspect, and deploy pipelines (create, list, get, register, synth, deploy)
|
|
110
|
+
plugin Author, validate, and publish plugins (new, validate, upload, get, list)
|
|
111
|
+
template Instantiate golden-path pipeline templates and validate {{ ... }} syntax (instantiate, validate)
|
|
112
|
+
infra Set up and operate platform infrastructure (bootstrap, setup-events, redrive-events, store-token, provision)
|
|
113
|
+
audit Operator audits, cron-friendly (tokens, stacks)
|
|
114
|
+
org Organization data operations (export)
|
|
115
|
+
status / version / completions
|
|
116
|
+
|
|
117
|
+
Environment Variables:
|
|
118
|
+
${ENV_VARS.PLATFORM_TOKEN} Authentication token (required)
|
|
119
|
+
${ENV_VARS.PLATFORM_BASE_URL} API base URL (optional)
|
|
120
|
+
${ENV_VARS.CLI_CONFIG_PATH} Config file path (optional)
|
|
121
|
+
${ENV_VARS.TLS_REJECT_UNAUTHORIZED} Disable SSL verification if '0'
|
|
122
|
+
${ENV_VARS.DEBUG} Enable debug mode if 'true'
|
|
123
|
+
|
|
124
|
+
Examples:
|
|
125
|
+
$ ${APP_NAME} version
|
|
126
|
+
$ ${APP_NAME} auth login -u me@example.com
|
|
127
|
+
$ ${APP_NAME} pipeline list --project my-app
|
|
128
|
+
$ ${APP_NAME} pipeline get --id pipe-123 --format json
|
|
129
|
+
$ ${APP_NAME} pipeline create -f props.json --deploy --profile production
|
|
130
|
+
$ ${APP_NAME} template instantiate -n react-javascript -p react -o acme --input orgId=<uuid> --output props.json
|
|
131
|
+
$ ${APP_NAME} plugin upload --file plugin.zip --organization acme
|
|
132
|
+
$ ${APP_NAME} infra store-token --days 30 --region us-east-1
|
|
133
|
+
$ ${APP_NAME} infra bootstrap --account 123456789012 --region us-east-1
|
|
134
|
+
$ ${APP_NAME} pipeline deploy --id pipe-123 --profile production
|
|
135
|
+
|
|
136
|
+
Exit codes (0 = success; failures use a standard code by error type):
|
|
137
|
+
1 general · 2 validation · 3 api-request · 4 auth · 5 forbidden
|
|
138
|
+
6 not-found · 7 network · 8 config · 9 file-system · 10 timeout
|
|
139
|
+
|
|
140
|
+
Run '${APP_NAME} <group> --help' to see a group's subcommands.
|
|
141
|
+
`);
|
|
142
|
+
// Fail-fast preflight: before ANY command's action runs, verify the local
|
|
143
|
+
// tools that command needs. Commander skips this for --help/--version and for
|
|
144
|
+
// help output, so those always work; API-only commands declare no requirements
|
|
145
|
+
// and pass through untouched.
|
|
146
|
+
program.hook('preAction', (_thisCommand, actionCommand) => preflightCommandTools(actionCommand));
|
|
147
|
+
// Top-level meta commands (no namespace).
|
|
148
|
+
version(program);
|
|
149
|
+
status(program); // Show environment and connectivity status
|
|
150
|
+
// Task namespaces — commands are grouped by the job the user is doing, not by
|
|
151
|
+
// implementation. Each parent is a subcommand container; the leaf verb lives in
|
|
152
|
+
// the command file (e.g. `.command('list')`), so `pipeline list` reads as a task.
|
|
153
|
+
printDebug('Registering task namespaces');
|
|
154
|
+
// auth — authenticate and manage credentials
|
|
155
|
+
const auth = program.command('auth').description('Authenticate and manage credentials');
|
|
156
|
+
login(auth); // auth login — obtain PLATFORM_TOKEN (also supports --refresh)
|
|
157
|
+
createPat(auth); // auth pat — create a named Personal Access Token
|
|
158
|
+
// pipeline — create, inspect, and deploy pipelines
|
|
159
|
+
const pipeline = program.command('pipeline').description('Create, inspect, and deploy pipelines');
|
|
160
|
+
createPipeline(pipeline); // pipeline create
|
|
161
|
+
listPipelines(pipeline); // pipeline list
|
|
162
|
+
getPipeline(pipeline); // pipeline get
|
|
163
|
+
register(pipeline); // pipeline register — re-register a deployed ARN + drain pending intents
|
|
164
|
+
synth(pipeline); // pipeline synth — CDK synthesis from pipeline config
|
|
165
|
+
deploy(pipeline); // pipeline deploy — CDK deploy (--app prints boilerplate path)
|
|
166
|
+
// plugin — author, validate, and publish plugins
|
|
167
|
+
const plugin = program.command('plugin').description('Author, validate, and publish plugins');
|
|
168
|
+
newPlugin(plugin); // plugin new — scaffold a local plugin directory
|
|
169
|
+
validatePlugin(plugin); // plugin validate — validate a local plugin before upload
|
|
170
|
+
uploadPlugin(plugin); // plugin upload — upload and deploy
|
|
171
|
+
getPlugin(plugin); // plugin get
|
|
172
|
+
listPlugins(plugin); // plugin list
|
|
173
|
+
// template — instantiate golden-path pipeline templates, validate {{ ... }} syntax
|
|
174
|
+
const template = program.command('template').description('Instantiate pipeline templates and validate {{ ... }} template syntax');
|
|
175
|
+
instantiateTemplate(template); // template instantiate — render a template into pipeline props
|
|
176
|
+
validateTemplatesCommand(template); // template validate
|
|
177
|
+
// infra — set up and operate platform infrastructure
|
|
178
|
+
const infra = program.command('infra').description('Set up and operate platform infrastructure');
|
|
179
|
+
bootstrap(infra); // infra bootstrap — CDK toolkit stack
|
|
180
|
+
setupEvents(infra); // infra setup-events — EventBridge event ingestion
|
|
181
|
+
redriveEvents(infra); // infra redrive-events — manual DLQ → queue redrive fallback
|
|
182
|
+
storeToken(infra); // infra store-token — JWT token in Secrets Manager for CDK
|
|
183
|
+
provision(infra); // infra provision — AI-assisted deploy/teardown of the platform
|
|
184
|
+
// audit — operator audits (cron-friendly: exit 1 on findings)
|
|
185
|
+
const audit = program.command('audit').description('Operator audits (cron-friendly: exit 1 on findings)');
|
|
186
|
+
auditTokens(audit); // audit tokens — expiring platform tokens in Secrets Manager
|
|
187
|
+
auditStacks(audit); // audit stacks — CFN stacks vs pipeline_registry drift
|
|
188
|
+
// org — organization data operations
|
|
189
|
+
const org = program.command('org').description('Organization data operations');
|
|
190
|
+
orgExport(org); // org export — GDPR portability export
|
|
191
|
+
// Shell completions
|
|
192
|
+
printDebug('Registering completions command');
|
|
193
|
+
program
|
|
194
|
+
.command('completions')
|
|
195
|
+
.description('Generate shell completions (bash, zsh, fish)')
|
|
196
|
+
.argument('<shell>', 'Shell type: bash, zsh, or fish')
|
|
197
|
+
.action((shell) => {
|
|
198
|
+
// Walk commander's registered tree so completions never drift from the actual
|
|
199
|
+
// surface. `topLevel` is the first-word set (namespaces + meta commands);
|
|
200
|
+
// `subs` maps each namespace to its leaf verbs for second-word completion.
|
|
201
|
+
const topLevel = program.commands.map(c => c.name()).sort();
|
|
202
|
+
const subs = {};
|
|
203
|
+
for (const c of program.commands) {
|
|
204
|
+
if (c.commands.length > 0)
|
|
205
|
+
subs[c.name()] = c.commands.map(s => s.name()).sort();
|
|
206
|
+
}
|
|
207
|
+
const topLevelStr = topLevel.join(' ');
|
|
208
|
+
switch (shell) {
|
|
209
|
+
case 'bash': {
|
|
210
|
+
// Two-level: complete the group at word 1, its subcommands at word 2.
|
|
211
|
+
const cases = Object.entries(subs)
|
|
212
|
+
.map(([ns, leaves]) => ` ${ns}) COMPREPLY=($(compgen -W "${leaves.join(' ')}" -- "\${cur}"));;`)
|
|
213
|
+
.join('\n');
|
|
214
|
+
console.log(`# pipeline-manager bash completions
|
|
215
|
+
_pipeline_manager_completions() {
|
|
216
|
+
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
217
|
+
if [ "\${COMP_CWORD}" -eq 1 ]; then
|
|
218
|
+
COMPREPLY=($(compgen -W "${topLevelStr}" -- "\${cur}"))
|
|
219
|
+
return
|
|
220
|
+
fi
|
|
221
|
+
case "\${COMP_WORDS[1]}" in
|
|
222
|
+
${cases}
|
|
223
|
+
esac
|
|
224
|
+
}
|
|
225
|
+
complete -F _pipeline_manager_completions pipeline-manager`);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
case 'zsh': {
|
|
229
|
+
const cases = Object.entries(subs)
|
|
230
|
+
.map(([ns, leaves]) => ` ${ns}) _values 'subcommand' ${leaves.join(' ')};;`)
|
|
231
|
+
.join('\n');
|
|
232
|
+
console.log(`# pipeline-manager zsh completions
|
|
233
|
+
_pipeline_manager() {
|
|
234
|
+
if (( CURRENT == 2 )); then
|
|
235
|
+
_values 'command' ${topLevel.join(' ')}
|
|
236
|
+
return
|
|
237
|
+
fi
|
|
238
|
+
case "\${words[2]}" in
|
|
239
|
+
${cases}
|
|
240
|
+
esac
|
|
241
|
+
}
|
|
242
|
+
compdef _pipeline_manager pipeline-manager`);
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case 'fish': {
|
|
246
|
+
const lines = [
|
|
247
|
+
`complete -c pipeline-manager -n '__fish_use_subcommand' -a '${topLevelStr}'`,
|
|
248
|
+
...Object.entries(subs).map(([ns, leaves]) => `complete -c pipeline-manager -n '__fish_seen_subcommand_from ${ns}' -a '${leaves.join(' ')}'`),
|
|
249
|
+
];
|
|
250
|
+
console.log(`# pipeline-manager fish completions\n${lines.join('\n')}`);
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
default:
|
|
254
|
+
console.error(`Unknown shell: ${shell}. Use bash, zsh, or fish.`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
printDebug('All commands registered successfully');
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Handle program errors
|
|
262
|
+
*/
|
|
263
|
+
function setupErrorHandlers() {
|
|
264
|
+
// Handle uncaught exceptions
|
|
265
|
+
process.on('uncaughtException', (error) => {
|
|
266
|
+
console.error(''); // Empty line
|
|
267
|
+
printError('Uncaught exception', {
|
|
268
|
+
error: error.message,
|
|
269
|
+
name: error.name,
|
|
270
|
+
});
|
|
271
|
+
handleError(error, ERROR_CODES.GENERAL, {
|
|
272
|
+
debug: isDebugMode(program.opts()),
|
|
273
|
+
exit: true,
|
|
274
|
+
context: {
|
|
275
|
+
type: 'uncaughtException',
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
// Handle unhandled promise rejections
|
|
280
|
+
process.on('unhandledRejection', (reason) => {
|
|
281
|
+
console.error(''); // Empty line
|
|
282
|
+
printError('Unhandled promise rejection', {
|
|
283
|
+
reason: reason instanceof Error ? reason.message : String(reason),
|
|
284
|
+
});
|
|
285
|
+
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
286
|
+
handleError(error, ERROR_CODES.GENERAL, {
|
|
287
|
+
debug: isDebugMode(program.opts()),
|
|
288
|
+
exit: true,
|
|
289
|
+
context: {
|
|
290
|
+
type: 'unhandledRejection',
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
// Handle SIGINT (Ctrl+C)
|
|
295
|
+
process.on('SIGINT', () => {
|
|
296
|
+
console.log(''); // Empty line
|
|
297
|
+
printWarning('Process interrupted by user (SIGINT)');
|
|
298
|
+
console.log(''); // Empty line
|
|
299
|
+
process.exit(130); // Standard exit code for SIGINT
|
|
300
|
+
});
|
|
301
|
+
// Handle SIGTERM
|
|
302
|
+
process.on('SIGTERM', () => {
|
|
303
|
+
console.log(''); // Empty line
|
|
304
|
+
printWarning('Process terminated (SIGTERM)');
|
|
305
|
+
console.log(''); // Empty line
|
|
306
|
+
process.exit(143); // Standard exit code for SIGTERM
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Initialize CLI with options
|
|
311
|
+
*
|
|
312
|
+
* @param options - CLI initialization options
|
|
313
|
+
*/
|
|
314
|
+
export function initializeCli(options = {}) {
|
|
315
|
+
const { showBanner = true, minimalBanner = false, debug = false, verbose = false, quiet = false, noColor = false, } = options;
|
|
316
|
+
// Handle color output
|
|
317
|
+
if (noColor) {
|
|
318
|
+
process.env.NO_COLOR = '1';
|
|
319
|
+
}
|
|
320
|
+
// Display banner
|
|
321
|
+
if (showBanner && !quiet) {
|
|
322
|
+
if (minimalBanner) {
|
|
323
|
+
miniBanner();
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
banner({
|
|
327
|
+
minimal: false,
|
|
328
|
+
showDescription: true,
|
|
329
|
+
showTimestamp: debug || verbose,
|
|
330
|
+
showExecutionId: debug,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Display startup info
|
|
335
|
+
displayStartupInfo({ debug, verbose, quiet });
|
|
336
|
+
// Check environment
|
|
337
|
+
if (!quiet) {
|
|
338
|
+
checkEnvironment();
|
|
339
|
+
}
|
|
340
|
+
// Setup error handlers
|
|
341
|
+
setupErrorHandlers();
|
|
342
|
+
// Register commands
|
|
343
|
+
try {
|
|
344
|
+
registerCommands();
|
|
345
|
+
printDebug('CLI initialization complete');
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
printError('CLI initialization failed', {
|
|
349
|
+
error: error instanceof Error ? error.message : String(error),
|
|
350
|
+
});
|
|
351
|
+
handleError(error, ERROR_CODES.CONFIGURATION, {
|
|
352
|
+
debug: debug || isDebugMode(),
|
|
353
|
+
exit: true,
|
|
354
|
+
context: {
|
|
355
|
+
stage: 'initialization',
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Parse command line arguments
|
|
362
|
+
*/
|
|
363
|
+
function parseArguments() {
|
|
364
|
+
try {
|
|
365
|
+
program.parse(process.argv);
|
|
366
|
+
// Show help if no command provided
|
|
367
|
+
const args = process.argv.slice(2);
|
|
368
|
+
if (args.length === 0) {
|
|
369
|
+
printInfo('No command specified - displaying help');
|
|
370
|
+
console.log(''); // Empty line
|
|
371
|
+
program.outputHelp();
|
|
372
|
+
process.exit(0);
|
|
373
|
+
}
|
|
374
|
+
// Check if command exists
|
|
375
|
+
const command = args[0];
|
|
376
|
+
if (command && !command.startsWith('-')) {
|
|
377
|
+
const commandExists = program.commands.some(cmd => cmd.name() === command);
|
|
378
|
+
if (!commandExists) {
|
|
379
|
+
console.log(''); // Empty line
|
|
380
|
+
printError(`Unknown command: ${command}`);
|
|
381
|
+
console.log(''); // Empty line
|
|
382
|
+
printInfo('Available commands:');
|
|
383
|
+
program.commands.forEach(cmd => {
|
|
384
|
+
console.log(` • ${cmd.name()} - ${cmd.description()}`);
|
|
385
|
+
});
|
|
386
|
+
console.log(''); // Empty line
|
|
387
|
+
process.exit(1);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
printDebug('Command line arguments parsed successfully');
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
handleError(error, ERROR_CODES.GENERAL, {
|
|
394
|
+
debug: isDebugMode(program.opts()),
|
|
395
|
+
exit: true,
|
|
396
|
+
context: {
|
|
397
|
+
stage: 'argument-parsing',
|
|
398
|
+
argv: process.argv,
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Main CLI entry point
|
|
405
|
+
*
|
|
406
|
+
* @param options - CLI initialization options
|
|
407
|
+
*
|
|
408
|
+
* @example
|
|
409
|
+
* ```typescript
|
|
410
|
+
* // Standard initialization
|
|
411
|
+
* main();
|
|
412
|
+
*
|
|
413
|
+
* // Minimal mode
|
|
414
|
+
* main({ minimalBanner: true, quiet: true });
|
|
415
|
+
*
|
|
416
|
+
* // Debug mode
|
|
417
|
+
* main({ debug: true, verbose: true });
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
export function main(options = {}) {
|
|
421
|
+
try {
|
|
422
|
+
// Initialize CLI
|
|
423
|
+
initializeCli(options);
|
|
424
|
+
// Parse arguments and execute command
|
|
425
|
+
parseArguments();
|
|
426
|
+
// If we reach here, command completed successfully
|
|
427
|
+
printDebug('CLI execution completed successfully');
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
// Final catch-all error handler
|
|
431
|
+
console.error(''); // Empty line
|
|
432
|
+
printError('Fatal CLI error', {
|
|
433
|
+
error: error instanceof Error ? error.message : String(error),
|
|
434
|
+
});
|
|
435
|
+
handleError(error, ERROR_CODES.GENERAL, {
|
|
436
|
+
debug: isDebugMode(options),
|
|
437
|
+
exit: true,
|
|
438
|
+
context: {
|
|
439
|
+
stage: 'main',
|
|
440
|
+
options,
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Run CLI if executed directly. ESM has no `require.main`; compare the invoked
|
|
447
|
+
* script to this module's path, resolving symlinks on both sides so the `bin`
|
|
448
|
+
* symlink (node_modules/.bin/pipeline-manager → dist/cli.js) still matches.
|
|
449
|
+
*/
|
|
450
|
+
const invokedScript = process.argv[1];
|
|
451
|
+
const isMainModule = invokedScript !== undefined
|
|
452
|
+
&& realpathSync(invokedScript) === realpathSync(fileURLToPath(import.meta.url));
|
|
453
|
+
if (isMainModule) {
|
|
454
|
+
// Parse CLI options from environment or command line
|
|
455
|
+
const options = {
|
|
456
|
+
debug: process.env.DEBUG === 'true',
|
|
457
|
+
quiet: process.argv.includes('--quiet'),
|
|
458
|
+
verbose: process.argv.includes('--verbose'),
|
|
459
|
+
noColor: process.argv.includes('--no-color') || process.env.NO_COLOR === '1',
|
|
460
|
+
};
|
|
461
|
+
main(options);
|
|
462
|
+
}
|
|
463
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9B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Q0FBQyxhQUFhLENBQUMsS0FBSyxZQUFZLENBQUMsYUFBYSxDQUFDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDbEYsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUNqQixxREFBcUQ7SUFDckQsTUFBTSxPQUFPLEdBQWU7UUFDMUIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxLQUFLLE1BQU07UUFDbkMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUN2QyxPQUFPLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO1FBQzNDLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxHQUFHO0tBQzdFLENBQUM7SUFFRixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDaEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcbi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyByZWFscGF0aFN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgeyBwcm9ncmFtIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IGF1ZGl0U3RhY2tzIH0gZnJvbSAnLi9jb21tYW5kcy9hdWRpdC1zdGFja3MuanMnO1xuaW1wb3J0IHsgYXVkaXRUb2tlbnMgfSBmcm9tICcuL2NvbW1hbmRzL2F1ZGl0LXRva2Vucy5qcyc7XG5pbXBvcnQgeyBib290c3RyYXAgfSBmcm9tICcuL2NvbW1hbmRzL2Jvb3RzdHJhcC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVQYXQgfSBmcm9tICcuL2NvbW1hbmRzL2NyZWF0ZS1wYXQuanMnO1xuaW1wb3J0IHsgY3JlYXRlUGlwZWxpbmUgfSBmcm9tICcuL2NvbW1hbmRzL2NyZWF0ZS1waXBlbGluZS5qcyc7XG5pbXBvcnQgeyBkZXBsb3kgfSBmcm9tICcuL2NvbW1hbmRzL2RlcGxveS5qcyc7XG5pbXBvcnQgeyBnZXRQaXBlbGluZSB9IGZyb20gJy4vY29tbWFuZHMvZ2V0LXBpcGVsaW5lLmpzJztcbmltcG9ydCB7IGdldFBsdWdpbiB9IGZyb20gJy4vY29tbWFuZHMvZ2V0LXBsdWdpbi5qcyc7XG5pbXBvcnQgeyBpbnN0YW50aWF0ZVRlbXBsYXRlIH0gZnJvbSAnLi9jb21tYW5kcy9pbnN0YW50aWF0ZS10ZW1wbGF0ZS5qcyc7XG5pbXBvcnQgeyBsaXN0UGlwZWxpbmVzIH0gZnJvbSAnLi9jb21tYW5kcy9saXN0LXBpcGVsaW5lcy5qcyc7XG5pbXBvcnQgeyBsaXN0UGx1Z2lucyB9IGZyb20gJy4vY29tbWFuZHMvbGlzdC1wbHVnaW5zLmpzJztcbmltcG9ydCB7IGxvZ2luIH0gZnJvbSAnLi9jb21tYW5kcy9sb2dpbi5qcyc7XG5pbXBvcnQgeyBuZXdQbHVnaW4gfSBmcm9tICcuL2NvbW1hbmRzL25ldy1wbHVnaW4uanMnO1xuaW1wb3J0IHsgb3JnRXhwb3J0IH0gZnJvbSAnLi9jb21tYW5kcy9vcmctZXhwb3J0LmpzJztcbmltcG9ydCB7IHByb3Zpc2lvbiB9IGZyb20gJy4vY29tbWFuZHMvcHJvdmlzaW9uLmpzJztcbmltcG9ydCB7IHJlZHJpdmVFdmVudHMgfSBmcm9tICcuL2NvbW1hbmRzL3JlZHJpdmUtZXZlbnRzLmpzJztcbmltcG9ydCB7IHJlZ2lzdGVyIH0gZnJvbSAnLi9jb21tYW5kcy9yZWdpc3Rlci5qcyc7XG5pbXBvcnQgeyBzZXR1cEV2ZW50cyB9IGZyb20gJy4vY29tbWFuZHMvc2V0dXAtZXZlbnRzLmpzJztcbmltcG9ydCB7IHN0YXR1cyB9IGZyb20gJy4vY29tbWFuZHMvc3RhdHVzLmpzJztcbmltcG9ydCB7IHN0b3JlVG9rZW4gfSBmcm9tICcuL2NvbW1hbmRzL3N0b3JlLXRva2VuLmpzJztcbmltcG9ydCB7IHN5bnRoIH0gZnJvbSAnLi9jb21tYW5kcy9zeW50aC5qcyc7XG5pbXBvcnQgeyB1cGxvYWRQbHVnaW4gfSBmcm9tICcuL2NvbW1hbmRzL3VwbG9hZC1wbHVnaW4uanMnO1xuaW1wb3J0IHsgdmFsaWRhdGVQbHVnaW4gfSBmcm9tICcuL2NvbW1hbmRzL3ZhbGlkYXRlLXBsdWdpbi5qcyc7XG5pbXBvcnQgeyB2YWxpZGF0ZVRlbXBsYXRlc0NvbW1hbmQgfSBmcm9tICcuL2NvbW1hbmRzL3ZhbGlkYXRlLXRlbXBsYXRlcy5qcyc7XG5pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi9jb21tYW5kcy92ZXJzaW9uLmpzJztcbmltcG9ydCB7XG4gIEFQUF9OQU1FLFxuICBBUFBfREVTQ1JJUFRJT04sXG4gIEFQUF9WRVJTSU9OLFxuICBFTlZfVkFSUyxcbiAgaXNEZWJ1Z01vZGUsXG4gIGdlbmVyYXRlRXhlY3V0aW9uSWQsXG59IGZyb20gJy4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYmFubmVyLCBtaW5pQmFubmVyIH0gZnJvbSAnLi91dGlscy9iYW5uZXIuanMnO1xuaW1wb3J0IHsgRVJST1JfQ09ERVMsIGhhbmRsZUVycm9yIH0gZnJvbSAnLi91dGlscy9lcnJvci1oYW5kbGVyLmpzJztcbmltcG9ydCB7IHByaW50SW5mbywgcHJpbnRFcnJvciwgcHJpbnRXYXJuaW5nLCBwcmludERlYnVnLCBwcmludFNlY3Rpb24gfSBmcm9tICcuL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBwcmVmbGlnaHRDb21tYW5kVG9vbHMgfSBmcm9tICcuL3V0aWxzL3ByZWZsaWdodC5qcyc7XG5cbi8qKlxuICogQ0xJIGluaXRpYWxpemF0aW9uIG9wdGlvbnNcbiAqL1xuaW50ZXJmYWNlIENsaU9wdGlvbnMge1xuICAvKipcbiAgICogU2hvdyBiYW5uZXIgb24gc3RhcnR1cFxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBzaG93QmFubmVyPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTWluaW1hbCBiYW5uZXIgKG5vIEFTQ0lJIGFydClcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIG1pbmltYWxCYW5uZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBEZWJ1ZyBtb2RlXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBkZWJ1Zz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFZlcmJvc2Ugb3V0cHV0XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICB2ZXJib3NlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogUXVpZXQgbW9kZSAobWluaW1hbCBvdXRwdXQpXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBxdWlldD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE5vIGNvbG9yIG91dHB1dFxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgbm9Db2xvcj86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ2hlY2sgZW52aXJvbm1lbnQgYW5kIGRpc3BsYXkgd2FybmluZ3NcbiAqL1xuZnVuY3Rpb24gY2hlY2tFbnZpcm9ubWVudCgpOiB2b2lkIHtcbiAgY29uc3Qgd2FybmluZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gQ2hlY2sgZm9yIHJlcXVpcmVkIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICBpZiAoIXByb2Nlc3MuZW52W0VOVl9WQVJTLlBMQVRGT1JNX1RPS0VOXSkge1xuICAgIHdhcm5pbmdzLnB1c2goJ1BMQVRGT1JNX1RPS0VOIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIG5vdCBzZXQnKTtcbiAgICB3YXJuaW5ncy5wdXNoKCdBdXRoZW50aWNhdGlvbiB3aWxsIGZhaWwgZm9yIEFQSSBvcGVyYXRpb25zJyk7XG4gIH1cblxuICAvLyBDaGVjayBOb2RlIHZlcnNpb25cbiAgY29uc3Qgbm9kZVZlcnNpb24gPSBwcm9jZXNzLnZlcnNpb247XG4gIGNvbnN0IG1ham9yVmVyc2lvbiA9IHBhcnNlSW50KG5vZGVWZXJzaW9uLnNsaWNlKDEpLnNwbGl0KCcuJylbMF0gfHwgJzAnLCAxMCk7XG4gIGlmIChtYWpvclZlcnNpb24gPCAyNCkge1xuICAgIHdhcm5pbmdzLnB1c2goYE5vZGUuanMgJHtub2RlVmVyc2lvbn0gZGV0ZWN0ZWQgLSB2ZXJzaW9uIDI0KyByZXF1aXJlZCAoc2VlIHBhY2thZ2UuanNvbiBlbmdpbmVzKWApO1xuICB9XG5cbiAgLy8gRGlzcGxheSB3YXJuaW5nc1xuICBpZiAod2FybmluZ3MubGVuZ3RoID4gMCkge1xuICAgIHByaW50U2VjdGlvbignRW52aXJvbm1lbnQgV2FybmluZ3MnKTtcbiAgICB3YXJuaW5ncy5mb3JFYWNoKHdhcm5pbmcgPT4ge1xuICAgICAgcHJpbnRXYXJuaW5nKHdhcm5pbmcpO1xuICAgIH0pO1xuICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgfVxufVxuXG4vKipcbiAqIERpc3BsYXkgc3RhcnR1cCBpbmZvcm1hdGlvblxuICovXG5mdW5jdGlvbiBkaXNwbGF5U3RhcnR1cEluZm8ob3B0aW9uczogQ2xpT3B0aW9ucyk6IHZvaWQge1xuICBpZiAob3B0aW9ucy5xdWlldCkgcmV0dXJuO1xuXG4gIGNvbnN0IGV4ZWN1dGlvbklkID0gZ2VuZXJhdGVFeGVjdXRpb25JZCgpO1xuXG4gIGlmIChvcHRpb25zLmRlYnVnIHx8IG9wdGlvbnMudmVyYm9zZSkge1xuICAgIHByaW50RGVidWcoJ0NMSSBDb25maWd1cmF0aW9uJywge1xuICAgICAgbmFtZTogQVBQX05BTUUsXG4gICAgICB2ZXJzaW9uOiBBUFBfVkVSU0lPTixcbiAgICAgIGV4ZWN1dGlvbklkLFxuICAgICAgbm9kZTogcHJvY2Vzcy52ZXJzaW9uLFxuICAgICAgcGxhdGZvcm06IHByb2Nlc3MucGxhdGZvcm0sXG4gICAgICBhcmNoOiBwcm9jZXNzLmFyY2gsXG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICBlbnY6IHtcbiAgICAgICAgZGVidWc6IHByb2Nlc3MuZW52LkRFQlVHLFxuICAgICAgICB0b2tlbjogcHJvY2Vzcy5lbnZbRU5WX1ZBUlMuUExBVEZPUk1fVE9LRU5dID8gJ3NldCc6ICdub3Qgc2V0JyxcbiAgICAgICAgdXJsOiBwcm9jZXNzLmVudltFTlZfVkFSUy5QTEFURk9STV9CQVNFX1VSTF0gfHwgJ2RlZmF1bHQnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBwcmludERlYnVnKCdTdGFydGluZyBDTEknLCB7XG4gICAgICB2ZXJzaW9uOiBBUFBfVkVSU0lPTixcbiAgICAgIGV4ZWN1dGlvbklkLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYWxsIENMSSBjb21tYW5kc1xuICovXG5mdW5jdGlvbiByZWdpc3RlckNvbW1hbmRzKCk6IHZvaWQge1xuICBwcmludERlYnVnKCdSZWdpc3RlcmluZyBjb21tYW5kcycpO1xuXG4gIC8vIENvbmZpZ3VyZSBwcm9ncmFtXG4gIHByb2dyYW1cbiAgICAubmFtZShBUFBfTkFNRSlcbiAgICAuZGVzY3JpcHRpb24oQVBQX0RFU0NSSVBUSU9OKVxuICAgIC52ZXJzaW9uKEFQUF9WRVJTSU9OLCAnLXYsIC0tdmVyc2lvbicsICdTaG93IENMSSB2ZXJzaW9uJylcbiAgICAub3B0aW9uKCctLWRlYnVnJywgJ0VuYWJsZSBkZWJ1ZyBvdXRwdXQgd2l0aCBzdGFjayB0cmFjZXMnLCBmYWxzZSlcbiAgICAub3B0aW9uKCctLXZlcmJvc2UnLCAnU2hvdyBkZXRhaWxlZCBpbmZvcm1hdGlvbicsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tcXVpZXQnLCAnTWluaW1hbCBvdXRwdXQgKGVycm9ycyBvbmx5KScsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tbm8tY29sb3InLCAnRGlzYWJsZSBjb2xvcmVkIG91dHB1dCcsIGZhbHNlKVxuICAgIC5hZGRIZWxwVGV4dCgnYWZ0ZXInLCBgXG5Db21tYW5kIGdyb3VwczpcbiAgYXV0aCAgICAgIEF1dGhlbnRpY2F0ZSBhbmQgbWFuYWdlIGNyZWRlbnRpYWxzIChsb2dpbiwgcGF0KVxuICBwaXBlbGluZSAgQ3JlYXRlLCBpbnNwZWN0LCBhbmQgZGVwbG95IHBpcGVsaW5lcyAoY3JlYXRlLCBsaXN0LCBnZXQsIHJlZ2lzdGVyLCBzeW50aCwgZGVwbG95KVxuICBwbHVnaW4gICAgQXV0aG9yLCB2YWxpZGF0ZSwgYW5kIHB1Ymxpc2ggcGx1Z2lucyAobmV3LCB2YWxpZGF0ZSwgdXBsb2FkLCBnZXQsIGxpc3QpXG4gIHRlbXBsYXRlICBJbnN0YW50aWF0ZSBnb2xkZW4tcGF0aCBwaXBlbGluZSB0ZW1wbGF0ZXMgYW5kIHZhbGlkYXRlIHt7IC4uLiB9fSBzeW50YXggKGluc3RhbnRpYXRlLCB2YWxpZGF0ZSlcbiAgaW5mcmEgICAgIFNldCB1cCBhbmQgb3BlcmF0ZSBwbGF0Zm9ybSBpbmZyYXN0cnVjdHVyZSAoYm9vdHN0cmFwLCBzZXR1cC1ldmVudHMsIHJlZHJpdmUtZXZlbnRzLCBzdG9yZS10b2tlbiwgcHJvdmlzaW9uKVxuICBhdWRpdCAgICAgT3BlcmF0b3IgYXVkaXRzLCBjcm9uLWZyaWVuZGx5ICh0b2tlbnMsIHN0YWNrcylcbiAgb3JnICAgICAgIE9yZ2FuaXphdGlvbiBkYXRhIG9wZXJhdGlvbnMgKGV4cG9ydClcbiAgc3RhdHVzIC8gdmVyc2lvbiAvIGNvbXBsZXRpb25zXG5cbkVudmlyb25tZW50IFZhcmlhYmxlczpcbiAgJHtFTlZfVkFSUy5QTEFURk9STV9UT0tFTn0gQXV0aGVudGljYXRpb24gdG9rZW4gKHJlcXVpcmVkKVxuICAke0VOVl9WQVJTLlBMQVRGT1JNX0JBU0VfVVJMfSBBUEkgYmFzZSBVUkwgKG9wdGlvbmFsKVxuICAke0VOVl9WQVJTLkNMSV9DT05GSUdfUEFUSH0gQ29uZmlnIGZpbGUgcGF0aCAob3B0aW9uYWwpXG4gICR7RU5WX1ZBUlMuVExTX1JFSkVDVF9VTkFVVEhPUklaRUR9IERpc2FibGUgU1NMIHZlcmlmaWNhdGlvbiBpZiAnMCdcbiAgJHtFTlZfVkFSUy5ERUJVR30gRW5hYmxlIGRlYnVnIG1vZGUgaWYgJ3RydWUnXG5cbkV4YW1wbGVzOlxuICAkICR7QVBQX05BTUV9IHZlcnNpb25cbiAgJCAke0FQUF9OQU1FfSBhdXRoIGxvZ2luIC11IG1lQGV4YW1wbGUuY29tXG4gICQgJHtBUFBfTkFNRX0gcGlwZWxpbmUgbGlzdCAtLXByb2plY3QgbXktYXBwXG4gICQgJHtBUFBfTkFNRX0gcGlwZWxpbmUgZ2V0IC0taWQgcGlwZS0xMjMgLS1mb3JtYXQganNvblxuICAkICR7QVBQX05BTUV9IHBpcGVsaW5lIGNyZWF0ZSAtZiBwcm9wcy5qc29uIC0tZGVwbG95IC0tcHJvZmlsZSBwcm9kdWN0aW9uXG4gICQgJHtBUFBfTkFNRX0gdGVtcGxhdGUgaW5zdGFudGlhdGUgLW4gcmVhY3QtamF2YXNjcmlwdCAtcCByZWFjdCAtbyBhY21lIC0taW5wdXQgb3JnSWQ9PHV1aWQ+IC0tb3V0cHV0IHByb3BzLmpzb25cbiAgJCAke0FQUF9OQU1FfSBwbHVnaW4gdXBsb2FkIC0tZmlsZSBwbHVnaW4uemlwIC0tb3JnYW5pemF0aW9uIGFjbWVcbiAgJCAke0FQUF9OQU1FfSBpbmZyYSBzdG9yZS10b2tlbiAtLWRheXMgMzAgLS1yZWdpb24gdXMtZWFzdC0xXG4gICQgJHtBUFBfTkFNRX0gaW5mcmEgYm9vdHN0cmFwIC0tYWNjb3VudCAxMjM0NTY3ODkwMTIgLS1yZWdpb24gdXMtZWFzdC0xXG4gICQgJHtBUFBfTkFNRX0gcGlwZWxpbmUgZGVwbG95IC0taWQgcGlwZS0xMjMgLS1wcm9maWxlIHByb2R1Y3Rpb25cblxuRXhpdCBjb2RlcyAoMCA9IHN1Y2Nlc3M7IGZhaWx1cmVzIHVzZSBhIHN0YW5kYXJkIGNvZGUgYnkgZXJyb3IgdHlwZSk6XG4gIDEgZ2VuZXJhbCDCtyAyIHZhbGlkYXRpb24gwrcgMyBhcGktcmVxdWVzdCDCtyA0IGF1dGggwrcgNSBmb3JiaWRkZW5cbiAgNiBub3QtZm91bmQgwrcgNyBuZXR3b3JrIMK3IDggY29uZmlnIMK3IDkgZmlsZS1zeXN0ZW0gwrcgMTAgdGltZW91dFxuXG5SdW4gJyR7QVBQX05BTUV9IDxncm91cD4gLS1oZWxwJyB0byBzZWUgYSBncm91cCdzIHN1YmNvbW1hbmRzLlxuYCk7XG5cbiAgLy8gRmFpbC1mYXN0IHByZWZsaWdodDogYmVmb3JlIEFOWSBjb21tYW5kJ3MgYWN0aW9uIHJ1bnMsIHZlcmlmeSB0aGUgbG9jYWxcbiAgLy8gdG9vbHMgdGhhdCBjb21tYW5kIG5lZWRzLiBDb21tYW5kZXIgc2tpcHMgdGhpcyBmb3IgLS1oZWxwLy0tdmVyc2lvbiBhbmQgZm9yXG4gIC8vIGhlbHAgb3V0cHV0LCBzbyB0aG9zZSBhbHdheXMgd29yazsgQVBJLW9ubHkgY29tbWFuZHMgZGVjbGFyZSBubyByZXF1aXJlbWVudHNcbiAgLy8gYW5kIHBhc3MgdGhyb3VnaCB1bnRvdWNoZWQuXG4gIHByb2dyYW0uaG9vaygncHJlQWN0aW9uJywgKF90aGlzQ29tbWFuZCwgYWN0aW9uQ29tbWFuZCkgPT4gcHJlZmxpZ2h0Q29tbWFuZFRvb2xzKGFjdGlvbkNvbW1hbmQpKTtcblxuICAvLyBUb3AtbGV2ZWwgbWV0YSBjb21tYW5kcyAobm8gbmFtZXNwYWNlKS5cbiAgdmVyc2lvbihwcm9ncmFtKTtcbiAgc3RhdHVzKHByb2dyYW0pOyAvLyBTaG93IGVudmlyb25tZW50IGFuZCBjb25uZWN0aXZpdHkgc3RhdHVzXG5cbiAgLy8gVGFzayBuYW1lc3BhY2VzIOKAlCBjb21tYW5kcyBhcmUgZ3JvdXBlZCBieSB0aGUgam9iIHRoZSB1c2VyIGlzIGRvaW5nLCBub3QgYnlcbiAgLy8gaW1wbGVtZW50YXRpb24uIEVhY2ggcGFyZW50IGlzIGEgc3ViY29tbWFuZCBjb250YWluZXI7IHRoZSBsZWFmIHZlcmIgbGl2ZXMgaW5cbiAgLy8gdGhlIGNvbW1hbmQgZmlsZSAoZS5nLiBgLmNvbW1hbmQoJ2xpc3QnKWApLCBzbyBgcGlwZWxpbmUgbGlzdGAgcmVhZHMgYXMgYSB0YXNrLlxuICBwcmludERlYnVnKCdSZWdpc3RlcmluZyB0YXNrIG5hbWVzcGFjZXMnKTtcblxuICAvLyBhdXRoIOKAlCBhdXRoZW50aWNhdGUgYW5kIG1hbmFnZSBjcmVkZW50aWFsc1xuICBjb25zdCBhdXRoID0gcHJvZ3JhbS5jb21tYW5kKCdhdXRoJykuZGVzY3JpcHRpb24oJ0F1dGhlbnRpY2F0ZSBhbmQgbWFuYWdlIGNyZWRlbnRpYWxzJyk7XG4gIGxvZ2luKGF1dGgpOyAvLyBhdXRoIGxvZ2luIOKAlCBvYnRhaW4gUExBVEZPUk1fVE9LRU4gKGFsc28gc3VwcG9ydHMgLS1yZWZyZXNoKVxuICBjcmVhdGVQYXQoYXV0aCk7IC8vIGF1dGggcGF0IOKAlCBjcmVhdGUgYSBuYW1lZCBQZXJzb25hbCBBY2Nlc3MgVG9rZW5cblxuICAvLyBwaXBlbGluZSDigJQgY3JlYXRlLCBpbnNwZWN0LCBhbmQgZGVwbG95IHBpcGVsaW5lc1xuICBjb25zdCBwaXBlbGluZSA9IHByb2dyYW0uY29tbWFuZCgncGlwZWxpbmUnKS5kZXNjcmlwdGlvbignQ3JlYXRlLCBpbnNwZWN0LCBhbmQgZGVwbG95IHBpcGVsaW5lcycpO1xuICBjcmVhdGVQaXBlbGluZShwaXBlbGluZSk7IC8vIHBpcGVsaW5lIGNyZWF0ZVxuICBsaXN0UGlwZWxpbmVzKHBpcGVsaW5lKTsgLy8gcGlwZWxpbmUgbGlzdFxuICBnZXRQaXBlbGluZShwaXBlbGluZSk7IC8vIHBpcGVsaW5lIGdldFxuICByZWdpc3RlcihwaXBlbGluZSk7IC8vIHBpcGVsaW5lIHJlZ2lzdGVyIOKAlCByZS1yZWdpc3RlciBhIGRlcGxveWVkIEFSTiArIGRyYWluIHBlbmRpbmcgaW50ZW50c1xuICBzeW50aChwaXBlbGluZSk7IC8vIHBpcGVsaW5lIHN5bnRoIOKAlCBDREsgc3ludGhlc2lzIGZyb20gcGlwZWxpbmUgY29uZmlnXG4gIGRlcGxveShwaXBlbGluZSk7IC8vIHBpcGVsaW5lIGRlcGxveSDigJQgQ0RLIGRlcGxveSAoLS1hcHAgcHJpbnRzIGJvaWxlcnBsYXRlIHBhdGgpXG5cbiAgLy8gcGx1Z2luIOKAlCBhdXRob3IsIHZhbGlkYXRlLCBhbmQgcHVibGlzaCBwbHVnaW5zXG4gIGNvbnN0IHBsdWdpbiA9IHByb2dyYW0uY29tbWFuZCgncGx1Z2luJykuZGVzY3JpcHRpb24oJ0F1dGhvciwgdmFsaWRhdGUsIGFuZCBwdWJsaXNoIHBsdWdpbnMnKTtcbiAgbmV3UGx1Z2luKHBsdWdpbik7IC8vIHBsdWdpbiBuZXcg4oCUIHNjYWZmb2xkIGEgbG9jYWwgcGx1Z2luIGRpcmVjdG9yeVxuICB2YWxpZGF0ZVBsdWdpbihwbHVnaW4pOyAvLyBwbHVnaW4gdmFsaWRhdGUg4oCUIHZhbGlkYXRlIGEgbG9jYWwgcGx1Z2luIGJlZm9yZSB1cGxvYWRcbiAgdXBsb2FkUGx1Z2luKHBsdWdpbik7IC8vIHBsdWdpbiB1cGxvYWQg4oCUIHVwbG9hZCBhbmQgZGVwbG95XG4gIGdldFBsdWdpbihwbHVnaW4pOyAvLyBwbHVnaW4gZ2V0XG4gIGxpc3RQbHVnaW5zKHBsdWdpbik7IC8vIHBsdWdpbiBsaXN0XG5cbiAgLy8gdGVtcGxhdGUg4oCUIGluc3RhbnRpYXRlIGdvbGRlbi1wYXRoIHBpcGVsaW5lIHRlbXBsYXRlcywgdmFsaWRhdGUge3sgLi4uIH19IHN5bnRheFxuICBjb25zdCB0ZW1wbGF0ZSA9IHByb2dyYW0uY29tbWFuZCgndGVtcGxhdGUnKS5kZXNjcmlwdGlvbignSW5zdGFudGlhdGUgcGlwZWxpbmUgdGVtcGxhdGVzIGFuZCB2YWxpZGF0ZSB7eyAuLi4gfX0gdGVtcGxhdGUgc3ludGF4Jyk7XG4gIGluc3RhbnRpYXRlVGVtcGxhdGUodGVtcGxhdGUpOyAvLyB0ZW1wbGF0ZSBpbnN0YW50aWF0ZSDigJQgcmVuZGVyIGEgdGVtcGxhdGUgaW50byBwaXBlbGluZSBwcm9wc1xuICB2YWxpZGF0ZVRlbXBsYXRlc0NvbW1hbmQodGVtcGxhdGUpOyAvLyB0ZW1wbGF0ZSB2YWxpZGF0ZVxuXG4gIC8vIGluZnJhIOKAlCBzZXQgdXAgYW5kIG9wZXJhdGUgcGxhdGZvcm0gaW5mcmFzdHJ1Y3R1cmVcbiAgY29uc3QgaW5mcmEgPSBwcm9ncmFtLmNvbW1hbmQoJ2luZnJhJykuZGVzY3JpcHRpb24oJ1NldCB1cCBhbmQgb3BlcmF0ZSBwbGF0Zm9ybSBpbmZyYXN0cnVjdHVyZScpO1xuICBib290c3RyYXAoaW5mcmEpOyAvLyBpbmZyYSBib290c3RyYXAg4oCUIENESyB0b29sa2l0IHN0YWNrXG4gIHNldHVwRXZlbnRzKGluZnJhKTsgLy8gaW5mcmEgc2V0dXAtZXZlbnRzIOKAlCBFdmVudEJyaWRnZSBldmVudCBpbmdlc3Rpb25cbiAgcmVkcml2ZUV2ZW50cyhpbmZyYSk7IC8vIGluZnJhIHJlZHJpdmUtZXZlbnRzIOKAlCBtYW51YWwgRExRIOKGkiBxdWV1ZSByZWRyaXZlIGZhbGxiYWNrXG4gIHN0b3JlVG9rZW4oaW5mcmEpOyAvLyBpbmZyYSBzdG9yZS10b2tlbiDigJQgSldUIHRva2VuIGluIFNlY3JldHMgTWFuYWdlciBmb3IgQ0RLXG4gIHByb3Zpc2lvbihpbmZyYSk7IC8vIGluZnJhIHByb3Zpc2lvbiDigJQgQUktYXNzaXN0ZWQgZGVwbG95L3RlYXJkb3duIG9mIHRoZSBwbGF0Zm9ybVxuXG4gIC8vIGF1ZGl0IOKAlCBvcGVyYXRvciBhdWRpdHMgKGNyb24tZnJpZW5kbHk6IGV4aXQgMSBvbiBmaW5kaW5ncylcbiAgY29uc3QgYXVkaXQgPSBwcm9ncmFtLmNvbW1hbmQoJ2F1ZGl0JykuZGVzY3JpcHRpb24oJ09wZXJhdG9yIGF1ZGl0cyAoY3Jvbi1mcmllbmRseTogZXhpdCAxIG9uIGZpbmRpbmdzKScpO1xuICBhdWRpdFRva2VucyhhdWRpdCk7IC8vIGF1ZGl0IHRva2VucyDigJQgZXhwaXJpbmcgcGxhdGZvcm0gdG9rZW5zIGluIFNlY3JldHMgTWFuYWdlclxuICBhdWRpdFN0YWNrcyhhdWRpdCk7IC8vIGF1ZGl0IHN0YWNrcyDigJQgQ0ZOIHN0YWNrcyB2cyBwaXBlbGluZV9yZWdpc3RyeSBkcmlmdFxuXG4gIC8vIG9yZyDigJQgb3JnYW5pemF0aW9uIGRhdGEgb3BlcmF0aW9uc1xuICBjb25zdCBvcmcgPSBwcm9ncmFtLmNvbW1hbmQoJ29yZycpLmRlc2NyaXB0aW9uKCdPcmdhbml6YXRpb24gZGF0YSBvcGVyYXRpb25zJyk7XG4gIG9yZ0V4cG9ydChvcmcpOyAvLyBvcmcgZXhwb3J0IOKAlCBHRFBSIHBvcnRhYmlsaXR5IGV4cG9ydFxuXG4gIC8vIFNoZWxsIGNvbXBsZXRpb25zXG4gIHByaW50RGVidWcoJ1JlZ2lzdGVyaW5nIGNvbXBsZXRpb25zIGNvbW1hbmQnKTtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKCdjb21wbGV0aW9ucycpXG4gICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBzaGVsbCBjb21wbGV0aW9ucyAoYmFzaCwgenNoLCBmaXNoKScpXG4gICAgLmFyZ3VtZW50KCc8c2hlbGw+JywgJ1NoZWxsIHR5cGU6IGJhc2gsIHpzaCwgb3IgZmlzaCcpXG4gICAgLmFjdGlvbigoc2hlbGw6IHN0cmluZykgPT4ge1xuICAgICAgLy8gV2FsayBjb21tYW5kZXIncyByZWdpc3RlcmVkIHRyZWUgc28gY29tcGxldGlvbnMgbmV2ZXIgZHJpZnQgZnJvbSB0aGUgYWN0dWFsXG4gICAgICAvLyBzdXJmYWNlLiBgdG9wTGV2ZWxgIGlzIHRoZSBmaXJzdC13b3JkIHNldCAobmFtZXNwYWNlcyArIG1ldGEgY29tbWFuZHMpO1xuICAgICAgLy8gYHN1YnNgIG1hcHMgZWFjaCBuYW1lc3BhY2UgdG8gaXRzIGxlYWYgdmVyYnMgZm9yIHNlY29uZC13b3JkIGNvbXBsZXRpb24uXG4gICAgICBjb25zdCB0b3BMZXZlbCA9IHByb2dyYW0uY29tbWFuZHMubWFwKGMgPT4gYy5uYW1lKCkpLnNvcnQoKTtcbiAgICAgIGNvbnN0IHN1YnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9O1xuICAgICAgZm9yIChjb25zdCBjIG9mIHByb2dyYW0uY29tbWFuZHMpIHtcbiAgICAgICAgaWYgKGMuY29tbWFuZHMubGVuZ3RoID4gMCkgc3Vic1tjLm5hbWUoKV0gPSBjLmNvbW1hbmRzLm1hcChzID0+IHMubmFtZSgpKS5zb3J0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCB0b3BMZXZlbFN0ciA9IHRvcExldmVsLmpvaW4oJyAnKTtcbiAgICAgIHN3aXRjaCAoc2hlbGwpIHtcbiAgICAgICAgY2FzZSAnYmFzaCc6IHtcbiAgICAgICAgICAvLyBUd28tbGV2ZWw6IGNvbXBsZXRlIHRoZSBncm91cCBhdCB3b3JkIDEsIGl0cyBzdWJjb21tYW5kcyBhdCB3b3JkIDIuXG4gICAgICAgICAgY29uc3QgY2FzZXMgPSBPYmplY3QuZW50cmllcyhzdWJzKVxuICAgICAgICAgICAgLm1hcCgoW25zLCBsZWF2ZXNdKSA9PiBgICAgICAgJHtuc30pIENPTVBSRVBMWT0oJChjb21wZ2VuIC1XIFwiJHtsZWF2ZXMuam9pbignICcpfVwiIC0tIFwiXFwke2N1cn1cIikpOztgKVxuICAgICAgICAgICAgLmpvaW4oJ1xcbicpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAjIHBpcGVsaW5lLW1hbmFnZXIgYmFzaCBjb21wbGV0aW9uc1xuX3BpcGVsaW5lX21hbmFnZXJfY29tcGxldGlvbnMoKSB7XG4gIGxvY2FsIGN1cj1cIlxcJHtDT01QX1dPUkRTW0NPTVBfQ1dPUkRdfVwiXG4gIGlmIFsgXCJcXCR7Q09NUF9DV09SRH1cIiAtZXEgMSBdOyB0aGVuXG4gICAgQ09NUFJFUExZPSgkKGNvbXBnZW4gLVcgXCIke3RvcExldmVsU3RyfVwiIC0tIFwiXFwke2N1cn1cIikpXG4gICAgcmV0dXJuXG4gIGZpXG4gIGNhc2UgXCJcXCR7Q09NUF9XT1JEU1sxXX1cIiBpblxuJHtjYXNlc31cbiAgZXNhY1xufVxuY29tcGxldGUgLUYgX3BpcGVsaW5lX21hbmFnZXJfY29tcGxldGlvbnMgcGlwZWxpbmUtbWFuYWdlcmApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ3pzaCc6IHtcbiAgICAgICAgICBjb25zdCBjYXNlcyA9IE9iamVjdC5lbnRyaWVzKHN1YnMpXG4gICAgICAgICAgICAubWFwKChbbnMsIGxlYXZlc10pID0+IGAgICAgICAgICR7bnN9KSBfdmFsdWVzICdzdWJjb21tYW5kJyAke2xlYXZlcy5qb2luKCcgJyl9OztgKVxuICAgICAgICAgICAgLmpvaW4oJ1xcbicpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAjIHBpcGVsaW5lLW1hbmFnZXIgenNoIGNvbXBsZXRpb25zXG5fcGlwZWxpbmVfbWFuYWdlcigpIHtcbiAgaWYgKCggQ1VSUkVOVCA9PSAyICkpOyB0aGVuXG4gICAgX3ZhbHVlcyAnY29tbWFuZCcgJHt0b3BMZXZlbC5qb2luKCcgJyl9XG4gICAgcmV0dXJuXG4gIGZpXG4gIGNhc2UgXCJcXCR7d29yZHNbMl19XCIgaW5cbiR7Y2FzZXN9XG4gIGVzYWNcbn1cbmNvbXBkZWYgX3BpcGVsaW5lX21hbmFnZXIgcGlwZWxpbmUtbWFuYWdlcmApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2Zpc2gnOiB7XG4gICAgICAgICAgY29uc3QgbGluZXMgPSBbXG4gICAgICAgICAgICBgY29tcGxldGUgLWMgcGlwZWxpbmUtbWFuYWdlciAtbiAnX19maXNoX3VzZV9zdWJjb21tYW5kJyAtYSAnJHt0b3BMZXZlbFN0cn0nYCxcbiAgICAgICAgICAgIC4uLk9iamVjdC5lbnRyaWVzKHN1YnMpLm1hcCgoW25zLCBsZWF2ZXNdKSA9PlxuICAgICAgICAgICAgICBgY29tcGxldGUgLWMgcGlwZWxpbmUtbWFuYWdlciAtbiAnX19maXNoX3NlZW5fc3ViY29tbWFuZF9mcm9tICR7bnN9JyAtYSAnJHtsZWF2ZXMuam9pbignICcpfSdgKSxcbiAgICAgICAgICBdO1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAjIHBpcGVsaW5lLW1hbmFnZXIgZmlzaCBjb21wbGV0aW9uc1xcbiR7bGluZXMuam9pbignXFxuJyl9YCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBVbmtub3duIHNoZWxsOiAke3NoZWxsfS4gVXNlIGJhc2gsIHpzaCwgb3IgZmlzaC5gKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgcHJpbnREZWJ1ZygnQWxsIGNvbW1hbmRzIHJlZ2lzdGVyZWQgc3VjY2Vzc2Z1bGx5Jyk7XG59XG5cbi8qKlxuICogSGFuZGxlIHByb2dyYW0gZXJyb3JzXG4gKi9cbmZ1bmN0aW9uIHNldHVwRXJyb3JIYW5kbGVycygpOiB2b2lkIHtcbiAgLy8gSGFuZGxlIHVuY2F1Z2h0IGV4Y2VwdGlvbnNcbiAgcHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcignJyk7IC8vIEVtcHR5IGxpbmVcbiAgICBwcmludEVycm9yKCdVbmNhdWdodCBleGNlcHRpb24nLCB7XG4gICAgICBlcnJvcjogZXJyb3IubWVzc2FnZSxcbiAgICAgIG5hbWU6IGVycm9yLm5hbWUsXG4gICAgfSk7XG5cbiAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuR0VORVJBTCwge1xuICAgICAgZGVidWc6IGlzRGVidWdNb2RlKHByb2dyYW0ub3B0cygpKSxcbiAgICAgIGV4aXQ6IHRydWUsXG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIHR5cGU6ICd1bmNhdWdodEV4Y2VwdGlvbicsXG4gICAgICB9LFxuICAgIH0pO1xuICB9KTtcblxuICAvLyBIYW5kbGUgdW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uc1xuICBwcm9jZXNzLm9uKCd1bmhhbmRsZWRSZWplY3Rpb24nLCAocmVhc29uOiB1bmtub3duKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcignJyk7IC8vIEVtcHR5IGxpbmVcbiAgICBwcmludEVycm9yKCdVbmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24nLCB7XG4gICAgICByZWFzb246IHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yID8gcmVhc29uLm1lc3NhZ2U6IFN0cmluZyhyZWFzb24pLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZXJyb3IgPSByZWFzb24gaW5zdGFuY2VvZiBFcnJvciA/IHJlYXNvbjogbmV3IEVycm9yKFN0cmluZyhyZWFzb24pKTtcblxuICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5HRU5FUkFMLCB7XG4gICAgICBkZWJ1ZzogaXNEZWJ1Z01vZGUocHJvZ3JhbS5vcHRzKCkpLFxuICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgdHlwZTogJ3VuaGFuZGxlZFJlamVjdGlvbicsXG4gICAgICB9LFxuICAgIH0pO1xuICB9KTtcblxuICAvLyBIYW5kbGUgU0lHSU5UIChDdHJsK0MpXG4gIHByb2Nlc3Mub24oJ1NJR0lOVCcsICgpID0+IHtcbiAgICBjb25zb2xlLmxvZygnJyk7IC8vIEVtcHR5IGxpbmVcbiAgICBwcmludFdhcm5pbmcoJ1Byb2Nlc3MgaW50ZXJydXB0ZWQgYnkgdXNlciAoU0lHSU5UKScpO1xuICAgIGNvbnNvbGUubG9nKCcnKTsgLy8gRW1wdHkgbGluZVxuICAgIHByb2Nlc3MuZXhpdCgxMzApOyAvLyBTdGFuZGFyZCBleGl0IGNvZGUgZm9yIFNJR0lOVFxuICB9KTtcblxuICAvLyBIYW5kbGUgU0lHVEVSTVxuICBwcm9jZXNzLm9uKCdTSUdURVJNJywgKCkgPT4ge1xuICAgIGNvbnNvbGUubG9nKCcnKTsgLy8gRW1wdHkgbGluZVxuICAgIHByaW50V2FybmluZygnUHJvY2VzcyB0ZXJtaW5hdGVkIChTSUdURVJNKScpO1xuICAgIGNvbnNvbGUubG9nKCcnKTsgLy8gRW1wdHkgbGluZVxuICAgIHByb2Nlc3MuZXhpdCgxNDMpOyAvLyBTdGFuZGFyZCBleGl0IGNvZGUgZm9yIFNJR1RFUk1cbiAgfSk7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBDTEkgd2l0aCBvcHRpb25zXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBDTEkgaW5pdGlhbGl6YXRpb24gb3B0aW9uc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUNsaShvcHRpb25zOiBDbGlPcHRpb25zID0ge30pOiB2b2lkIHtcbiAgY29uc3Qge1xuICAgIHNob3dCYW5uZXIgPSB0cnVlLFxuICAgIG1pbmltYWxCYW5uZXIgPSBmYWxzZSxcbiAgICBkZWJ1ZyA9IGZhbHNlLFxuICAgIHZlcmJvc2UgPSBmYWxzZSxcbiAgICBxdWlldCA9IGZhbHNlLFxuICAgIG5vQ29sb3IgPSBmYWxzZSxcbiAgfSA9IG9wdGlvbnM7XG5cbiAgLy8gSGFuZGxlIGNvbG9yIG91dHB1dFxuICBpZiAobm9Db2xvcikge1xuICAgIHByb2Nlc3MuZW52Lk5PX0NPTE9SID0gJzEnO1xuICB9XG5cbiAgLy8gRGlzcGxheSBiYW5uZXJcbiAgaWYgKHNob3dCYW5uZXIgJiYgIXF1aWV0KSB7XG4gICAgaWYgKG1pbmltYWxCYW5uZXIpIHtcbiAgICAgIG1pbmlCYW5uZXIoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYmFubmVyKHtcbiAgICAgICAgbWluaW1hbDogZmFsc2UsXG4gICAgICAgIHNob3dEZXNjcmlwdGlvbjogdHJ1ZSxcbiAgICAgICAgc2hvd1RpbWVzdGFtcDogZGVidWcgfHwgdmVyYm9zZSxcbiAgICAgICAgc2hvd0V4ZWN1dGlvbklkOiBkZWJ1ZyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIERpc3BsYXkgc3RhcnR1cCBpbmZvXG4gIGRpc3BsYXlTdGFydHVwSW5mbyh7IGRlYnVnLCB2ZXJib3NlLCBxdWlldCB9KTtcblxuICAvLyBDaGVjayBlbnZpcm9ubWVudFxuICBpZiAoIXF1aWV0KSB7XG4gICAgY2hlY2tFbnZpcm9ubWVudCgpO1xuICB9XG5cbiAgLy8gU2V0dXAgZXJyb3IgaGFuZGxlcnNcbiAgc2V0dXBFcnJvckhhbmRsZXJzKCk7XG5cbiAgLy8gUmVnaXN0ZXIgY29tbWFuZHNcbiAgdHJ5IHtcbiAgICByZWdpc3RlckNvbW1hbmRzKCk7XG4gICAgcHJpbnREZWJ1ZygnQ0xJIGluaXRpYWxpemF0aW9uIGNvbXBsZXRlJyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcHJpbnRFcnJvcignQ0xJIGluaXRpYWxpemF0aW9uIGZhaWxlZCcsIHtcbiAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZTogU3RyaW5nKGVycm9yKSxcbiAgICB9KTtcblxuICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5DT05GSUdVUkFUSU9OLCB7XG4gICAgICBkZWJ1ZzogZGVidWcgfHwgaXNEZWJ1Z01vZGUoKSxcbiAgICAgIGV4aXQ6IHRydWUsXG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIHN0YWdlOiAnaW5pdGlhbGl6YXRpb24nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlIGNvbW1hbmQgbGluZSBhcmd1bWVudHNcbiAqL1xuZnVuY3Rpb24gcGFyc2VBcmd1bWVudHMoKTogdm9pZCB7XG4gIHRyeSB7XG4gICAgcHJvZ3JhbS5wYXJzZShwcm9jZXNzLmFyZ3YpO1xuXG4gICAgLy8gU2hvdyBoZWxwIGlmIG5vIGNvbW1hbmQgcHJvdmlkZWRcbiAgICBjb25zdCBhcmdzID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcHJpbnRJbmZvKCdObyBjb21tYW5kIHNwZWNpZmllZCAtIGRpc3BsYXlpbmcgaGVscCcpO1xuICAgICAgY29uc29sZS5sb2coJycpOyAvLyBFbXB0eSBsaW5lXG4gICAgICBwcm9ncmFtLm91dHB1dEhlbHAoKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiBjb21tYW5kIGV4aXN0c1xuICAgIGNvbnN0IGNvbW1hbmQgPSBhcmdzWzBdO1xuICAgIGlmIChjb21tYW5kICYmICFjb21tYW5kLnN0YXJ0c1dpdGgoJy0nKSkge1xuICAgICAgY29uc3QgY29tbWFuZEV4aXN0cyA9IHByb2dyYW0uY29tbWFuZHMuc29tZShjbWQgPT4gY21kLm5hbWUoKSA9PT0gY29tbWFuZCk7XG5cbiAgICAgIGlmICghY29tbWFuZEV4aXN0cykge1xuICAgICAgICBjb25zb2xlLmxvZygnJyk7IC8vIEVtcHR5IGxpbmVcbiAgICAgICAgcHJpbnRFcnJvcihgVW5rbm93biBjb21tYW5kOiAke2NvbW1hbmR9YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTsgLy8gRW1wdHkgbGluZVxuICAgICAgICBwcmludEluZm8oJ0F2YWlsYWJsZSBjb21tYW5kczonKTtcbiAgICAgICAgcHJvZ3JhbS5jb21tYW5kcy5mb3JFYWNoKGNtZCA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coYCDigKIgJHtjbWQubmFtZSgpfSAtICR7Y21kLmRlc2NyaXB0aW9uKCl9YCk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmxvZygnJyk7IC8vIEVtcHR5IGxpbmVcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaW50RGVidWcoJ0NvbW1hbmQgbGluZSBhcmd1bWVudHMgcGFyc2VkIHN1Y2Nlc3NmdWxseScpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5HRU5FUkFMLCB7XG4gICAgICBkZWJ1ZzogaXNEZWJ1Z01vZGUocHJvZ3JhbS5vcHRzKCkpLFxuICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgc3RhZ2U6ICdhcmd1bWVudC1wYXJzaW5nJyxcbiAgICAgICAgYXJndjogcHJvY2Vzcy5hcmd2LFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIE1haW4gQ0xJIGVudHJ5IHBvaW50XG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBDTEkgaW5pdGlhbGl6YXRpb24gb3B0aW9uc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBTdGFuZGFyZCBpbml0aWFsaXphdGlvblxuICogbWFpbigpO1xuICpcbiAqIC8vIE1pbmltYWwgbW9kZVxuICogbWFpbih7IG1pbmltYWxCYW5uZXI6IHRydWUsIHF1aWV0OiB0cnVlIH0pO1xuICpcbiAqIC8vIERlYnVnIG1vZGVcbiAqIG1haW4oeyBkZWJ1ZzogdHJ1ZSwgdmVyYm9zZTogdHJ1ZSB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWFpbihvcHRpb25zOiBDbGlPcHRpb25zID0ge30pOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICAvLyBJbml0aWFsaXplIENMSVxuICAgIGluaXRpYWxpemVDbGkob3B0aW9ucyk7XG5cbiAgICAvLyBQYXJzZSBhcmd1bWVudHMgYW5kIGV4ZWN1dGUgY29tbWFuZFxuICAgIHBhcnNlQXJndW1lbnRzKCk7XG5cbiAgICAvLyBJZiB3ZSByZWFjaCBoZXJlLCBjb21tYW5kIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHlcbiAgICBwcmludERlYnVnKCdDTEkgZXhlY3V0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBGaW5hbCBjYXRjaC1hbGwgZXJyb3IgaGFuZGxlclxuICAgIGNvbnNvbGUuZXJyb3IoJycpOyAvLyBFbXB0eSBsaW5lXG4gICAgcHJpbnRFcnJvcignRmF0YWwgQ0xJIGVycm9yJywge1xuICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlOiBTdHJpbmcoZXJyb3IpLFxuICAgIH0pO1xuXG4gICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkdFTkVSQUwsIHtcbiAgICAgIGRlYnVnOiBpc0RlYnVnTW9kZShvcHRpb25zKSxcbiAgICAgIGV4aXQ6IHRydWUsXG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIHN0YWdlOiAnbWFpbicsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogUnVuIENMSSBpZiBleGVjdXRlZCBkaXJlY3RseS4gRVNNIGhhcyBubyBgcmVxdWlyZS5tYWluYDsgY29tcGFyZSB0aGUgaW52b2tlZFxuICogc2NyaXB0IHRvIHRoaXMgbW9kdWxlJ3MgcGF0aCwgcmVzb2x2aW5nIHN5bWxpbmtzIG9uIGJvdGggc2lkZXMgc28gdGhlIGBiaW5gXG4gKiBzeW1saW5rIChub2RlX21vZHVsZXMvLmJpbi9waXBlbGluZS1tYW5hZ2VyIOKGkiBkaXN0L2NsaS5qcykgc3RpbGwgbWF0Y2hlcy5cbiAqL1xuY29uc3QgaW52b2tlZFNjcmlwdCA9IHByb2Nlc3MuYXJndlsxXTtcbmNvbnN0IGlzTWFpbk1vZHVsZSA9IGludm9rZWRTY3JpcHQgIT09IHVuZGVmaW5lZFxuICAmJiByZWFscGF0aFN5bmMoaW52b2tlZFNjcmlwdCkgPT09IHJlYWxwYXRoU3luYyhmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuaWYgKGlzTWFpbk1vZHVsZSkge1xuICAvLyBQYXJzZSBDTEkgb3B0aW9ucyBmcm9tIGVudmlyb25tZW50IG9yIGNvbW1hbmQgbGluZVxuICBjb25zdCBvcHRpb25zOiBDbGlPcHRpb25zID0ge1xuICAgIGRlYnVnOiBwcm9jZXNzLmVudi5ERUJVRyA9PT0gJ3RydWUnLFxuICAgIHF1aWV0OiBwcm9jZXNzLmFyZ3YuaW5jbHVkZXMoJy0tcXVpZXQnKSxcbiAgICB2ZXJib3NlOiBwcm9jZXNzLmFyZ3YuaW5jbHVkZXMoJy0tdmVyYm9zZScpLFxuICAgIG5vQ29sb3I6IHByb2Nlc3MuYXJndi5pbmNsdWRlcygnLS1uby1jb2xvcicpIHx8IHByb2Nlc3MuZW52Lk5PX0NPTE9SID09PSAnMScsXG4gIH07XG5cbiAgbWFpbihvcHRpb25zKTtcbn0iXX0=
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Registers the `audit-stacks` command with the CLI program.
|
|
4
|
+
*
|
|
5
|
+
* Diffs CloudFormation stacks (filtered to those tagged with `pipeline-builder`)
|
|
6
|
+
* against the platform's `pipeline_registry` table. Surfaces:
|
|
7
|
+
* - **Orphaned stacks**: tagged stacks with no DB record (likely leftovers after
|
|
8
|
+
* a pipeline was deleted from the dashboard but the CDK stack stayed in AWS).
|
|
9
|
+
* - **Missing stacks**: registry entries pointing to stacks that no longer exist
|
|
10
|
+
* in CloudFormation (likely after a manual `aws cloudformation delete-stack`).
|
|
11
|
+
*
|
|
12
|
+
* Designed for cron use:
|
|
13
|
+
* - Exits 0 when there are no findings.
|
|
14
|
+
* - Exits 1 when at least one orphaned or missing stack is found.
|
|
15
|
+
* - Exits 2 on AWS errors / scan failures.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```bash
|
|
19
|
+
* pipeline-manager audit stacks --region us-east-1
|
|
20
|
+
* pipeline-manager audit stacks --org acme --json
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function auditStacks(program: Command): void;
|
|
24
|
+
//# sourceMappingURL=audit-stacks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-stacks.d.ts","sourceRoot":"","sources":["../../src/commands/audit-stacks.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmJlD"}
|