@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.
Files changed (222) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +145 -0
  3. package/cdk.json +91 -0
  4. package/config.yml +94 -0
  5. package/dist/agent/ai.d.ts +48 -0
  6. package/dist/agent/ai.d.ts.map +1 -0
  7. package/dist/agent/ai.js +149 -0
  8. package/dist/agent/bootstrap.d.ts +39 -0
  9. package/dist/agent/bootstrap.d.ts.map +1 -0
  10. package/dist/agent/bootstrap.js +66 -0
  11. package/dist/agent/env-file.d.ts +17 -0
  12. package/dist/agent/env-file.d.ts.map +1 -0
  13. package/dist/agent/env-file.js +47 -0
  14. package/dist/agent/executor.d.ts +30 -0
  15. package/dist/agent/executor.d.ts.map +1 -0
  16. package/dist/agent/executor.js +60 -0
  17. package/dist/agent/health.d.ts +43 -0
  18. package/dist/agent/health.d.ts.map +1 -0
  19. package/dist/agent/health.js +109 -0
  20. package/dist/agent/ports.d.ts +26 -0
  21. package/dist/agent/ports.d.ts.map +1 -0
  22. package/dist/agent/ports.js +132 -0
  23. package/dist/agent/post-steps.d.ts +61 -0
  24. package/dist/agent/post-steps.d.ts.map +1 -0
  25. package/dist/agent/post-steps.js +131 -0
  26. package/dist/agent/prereqs.d.ts +26 -0
  27. package/dist/agent/prereqs.d.ts.map +1 -0
  28. package/dist/agent/prereqs.js +134 -0
  29. package/dist/agent/targets.d.ts +128 -0
  30. package/dist/agent/targets.d.ts.map +1 -0
  31. package/dist/agent/targets.js +265 -0
  32. package/dist/agent/tools.d.ts +13 -0
  33. package/dist/agent/tools.d.ts.map +1 -0
  34. package/dist/agent/tools.js +75 -0
  35. package/dist/agent/troubleshoot.d.ts +30 -0
  36. package/dist/agent/troubleshoot.d.ts.map +1 -0
  37. package/dist/agent/troubleshoot.js +87 -0
  38. package/dist/boilerplate.d.ts +3 -0
  39. package/dist/boilerplate.d.ts.map +1 -0
  40. package/dist/boilerplate.js +54 -0
  41. package/dist/cdk.json +91 -0
  42. package/dist/cli.d.ts +62 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +463 -0
  45. package/dist/commands/audit-stacks.d.ts +24 -0
  46. package/dist/commands/audit-stacks.d.ts.map +1 -0
  47. package/dist/commands/audit-stacks.js +182 -0
  48. package/dist/commands/audit-tokens.d.ts +21 -0
  49. package/dist/commands/audit-tokens.d.ts.map +1 -0
  50. package/dist/commands/audit-tokens.js +153 -0
  51. package/dist/commands/bootstrap.d.ts +11 -0
  52. package/dist/commands/bootstrap.d.ts.map +1 -0
  53. package/dist/commands/bootstrap.js +159 -0
  54. package/dist/commands/create-pat.d.ts +27 -0
  55. package/dist/commands/create-pat.d.ts.map +1 -0
  56. package/dist/commands/create-pat.js +194 -0
  57. package/dist/commands/create-pipeline.d.ts +12 -0
  58. package/dist/commands/create-pipeline.d.ts.map +1 -0
  59. package/dist/commands/create-pipeline.js +315 -0
  60. package/dist/commands/deploy.d.ts +15 -0
  61. package/dist/commands/deploy.d.ts.map +1 -0
  62. package/dist/commands/deploy.js +157 -0
  63. package/dist/commands/entity-get.d.ts +51 -0
  64. package/dist/commands/entity-get.d.ts.map +1 -0
  65. package/dist/commands/entity-get.js +69 -0
  66. package/dist/commands/entity-list.d.ts +39 -0
  67. package/dist/commands/entity-list.d.ts.map +1 -0
  68. package/dist/commands/entity-list.js +88 -0
  69. package/dist/commands/get-pipeline.d.ts +13 -0
  70. package/dist/commands/get-pipeline.d.ts.map +1 -0
  71. package/dist/commands/get-pipeline.js +49 -0
  72. package/dist/commands/get-plugin.d.ts +13 -0
  73. package/dist/commands/get-plugin.d.ts.map +1 -0
  74. package/dist/commands/get-plugin.js +51 -0
  75. package/dist/commands/instantiate-template.d.ts +20 -0
  76. package/dist/commands/instantiate-template.d.ts.map +1 -0
  77. package/dist/commands/instantiate-template.js +274 -0
  78. package/dist/commands/list-pipelines.d.ts +20 -0
  79. package/dist/commands/list-pipelines.d.ts.map +1 -0
  80. package/dist/commands/list-pipelines.js +99 -0
  81. package/dist/commands/list-plugins.d.ts +20 -0
  82. package/dist/commands/list-plugins.d.ts.map +1 -0
  83. package/dist/commands/list-plugins.js +92 -0
  84. package/dist/commands/login.d.ts +21 -0
  85. package/dist/commands/login.d.ts.map +1 -0
  86. package/dist/commands/login.js +174 -0
  87. package/dist/commands/new-plugin.d.ts +12 -0
  88. package/dist/commands/new-plugin.d.ts.map +1 -0
  89. package/dist/commands/new-plugin.js +129 -0
  90. package/dist/commands/org-export.d.ts +25 -0
  91. package/dist/commands/org-export.d.ts.map +1 -0
  92. package/dist/commands/org-export.js +100 -0
  93. package/dist/commands/provision.d.ts +122 -0
  94. package/dist/commands/provision.d.ts.map +1 -0
  95. package/dist/commands/provision.js +867 -0
  96. package/dist/commands/redrive-events.d.ts +24 -0
  97. package/dist/commands/redrive-events.d.ts.map +1 -0
  98. package/dist/commands/redrive-events.js +127 -0
  99. package/dist/commands/register.d.ts +38 -0
  100. package/dist/commands/register.d.ts.map +1 -0
  101. package/dist/commands/register.js +160 -0
  102. package/dist/commands/setup-events.d.ts +15 -0
  103. package/dist/commands/setup-events.d.ts.map +1 -0
  104. package/dist/commands/setup-events.js +168 -0
  105. package/dist/commands/status.d.ts +11 -0
  106. package/dist/commands/status.d.ts.map +1 -0
  107. package/dist/commands/status.js +81 -0
  108. package/dist/commands/store-token.d.ts +26 -0
  109. package/dist/commands/store-token.d.ts.map +1 -0
  110. package/dist/commands/store-token.js +305 -0
  111. package/dist/commands/synth.d.ts +21 -0
  112. package/dist/commands/synth.d.ts.map +1 -0
  113. package/dist/commands/synth.js +158 -0
  114. package/dist/commands/upload-plugin.d.ts +21 -0
  115. package/dist/commands/upload-plugin.d.ts.map +1 -0
  116. package/dist/commands/upload-plugin.js +275 -0
  117. package/dist/commands/validate-plugin.d.ts +12 -0
  118. package/dist/commands/validate-plugin.d.ts.map +1 -0
  119. package/dist/commands/validate-plugin.js +175 -0
  120. package/dist/commands/validate-templates.d.ts +11 -0
  121. package/dist/commands/validate-templates.d.ts.map +1 -0
  122. package/dist/commands/validate-templates.js +116 -0
  123. package/dist/commands/version.d.ts +12 -0
  124. package/dist/commands/version.d.ts.map +1 -0
  125. package/dist/commands/version.js +216 -0
  126. package/dist/config/cli.constants.d.ts +116 -0
  127. package/dist/config/cli.constants.d.ts.map +1 -0
  128. package/dist/config/cli.constants.js +194 -0
  129. package/dist/config.yml +94 -0
  130. package/dist/lambda/token-renew-handler.d.ts +2 -0
  131. package/dist/lambda/token-renew-handler.d.ts.map +1 -0
  132. package/dist/lambda/token-renew-handler.js +125 -0
  133. package/dist/templates/events-stack.json +174 -0
  134. package/dist/templates/token-renew-stack.json +122 -0
  135. package/dist/types/config.d.ts +53 -0
  136. package/dist/types/config.d.ts.map +1 -0
  137. package/dist/types/config.js +4 -0
  138. package/dist/types/error.d.ts +61 -0
  139. package/dist/types/error.d.ts.map +1 -0
  140. package/dist/types/error.js +35 -0
  141. package/dist/types/index.d.ts +9 -0
  142. package/dist/types/index.d.ts.map +1 -0
  143. package/dist/types/index.js +11 -0
  144. package/dist/types/pipeline-template.d.ts +48 -0
  145. package/dist/types/pipeline-template.d.ts.map +1 -0
  146. package/dist/types/pipeline-template.js +4 -0
  147. package/dist/types/pipeline.d.ts +121 -0
  148. package/dist/types/pipeline.d.ts.map +1 -0
  149. package/dist/types/pipeline.js +4 -0
  150. package/dist/types/plugin.d.ts +135 -0
  151. package/dist/types/plugin.d.ts.map +1 -0
  152. package/dist/types/plugin.js +4 -0
  153. package/dist/utils/api-client.d.ts +26 -0
  154. package/dist/utils/api-client.d.ts.map +1 -0
  155. package/dist/utils/api-client.js +151 -0
  156. package/dist/utils/audit-log.d.ts +8 -0
  157. package/dist/utils/audit-log.d.ts.map +1 -0
  158. package/dist/utils/audit-log.js +57 -0
  159. package/dist/utils/auth-guard.d.ts +20 -0
  160. package/dist/utils/auth-guard.d.ts.map +1 -0
  161. package/dist/utils/auth-guard.js +22 -0
  162. package/dist/utils/auth-utils.d.ts +68 -0
  163. package/dist/utils/auth-utils.d.ts.map +1 -0
  164. package/dist/utils/auth-utils.js +77 -0
  165. package/dist/utils/aws-env.d.ts +21 -0
  166. package/dist/utils/aws-env.d.ts.map +1 -0
  167. package/dist/utils/aws-env.js +34 -0
  168. package/dist/utils/aws-secrets.d.ts +48 -0
  169. package/dist/utils/aws-secrets.d.ts.map +1 -0
  170. package/dist/utils/aws-secrets.js +115 -0
  171. package/dist/utils/banner.d.ts +19 -0
  172. package/dist/utils/banner.d.ts.map +1 -0
  173. package/dist/utils/banner.js +52 -0
  174. package/dist/utils/cdk-utils.d.ts +74 -0
  175. package/dist/utils/cdk-utils.d.ts.map +1 -0
  176. package/dist/utils/cdk-utils.js +152 -0
  177. package/dist/utils/command-utils.d.ts +75 -0
  178. package/dist/utils/command-utils.d.ts.map +1 -0
  179. package/dist/utils/command-utils.js +155 -0
  180. package/dist/utils/config-loader.d.ts +33 -0
  181. package/dist/utils/config-loader.d.ts.map +1 -0
  182. package/dist/utils/config-loader.js +154 -0
  183. package/dist/utils/cron.d.ts +28 -0
  184. package/dist/utils/cron.d.ts.map +1 -0
  185. package/dist/utils/cron.js +119 -0
  186. package/dist/utils/deploy-runner.d.ts +38 -0
  187. package/dist/utils/deploy-runner.d.ts.map +1 -0
  188. package/dist/utils/deploy-runner.js +112 -0
  189. package/dist/utils/error-handler.d.ts +29 -0
  190. package/dist/utils/error-handler.d.ts.map +1 -0
  191. package/dist/utils/error-handler.js +302 -0
  192. package/dist/utils/list-command-utils.d.ts +23 -0
  193. package/dist/utils/list-command-utils.d.ts.map +1 -0
  194. package/dist/utils/list-command-utils.js +57 -0
  195. package/dist/utils/output-utils.d.ts +40 -0
  196. package/dist/utils/output-utils.d.ts.map +1 -0
  197. package/dist/utils/output-utils.js +250 -0
  198. package/dist/utils/pipeline-config.d.ts +33 -0
  199. package/dist/utils/pipeline-config.d.ts.map +1 -0
  200. package/dist/utils/pipeline-config.js +55 -0
  201. package/dist/utils/platform-secret.d.ts +27 -0
  202. package/dist/utils/platform-secret.d.ts.map +1 -0
  203. package/dist/utils/platform-secret.js +92 -0
  204. package/dist/utils/plugin-resolver.d.ts +17 -0
  205. package/dist/utils/plugin-resolver.d.ts.map +1 -0
  206. package/dist/utils/plugin-resolver.js +101 -0
  207. package/dist/utils/preflight.d.ts +26 -0
  208. package/dist/utils/preflight.d.ts.map +1 -0
  209. package/dist/utils/preflight.js +59 -0
  210. package/dist/utils/rate-limiter.d.ts +15 -0
  211. package/dist/utils/rate-limiter.d.ts.map +1 -0
  212. package/dist/utils/rate-limiter.js +164 -0
  213. package/dist/utils/registry.d.ts +86 -0
  214. package/dist/utils/registry.d.ts.map +1 -0
  215. package/dist/utils/registry.js +140 -0
  216. package/dist/utils/response-utils.d.ts +21 -0
  217. package/dist/utils/response-utils.d.ts.map +1 -0
  218. package/dist/utils/response-utils.js +70 -0
  219. package/dist/utils/tls.d.ts +52 -0
  220. package/dist/utils/tls.d.ts.map +1 -0
  221. package/dist/utils/tls.js +88 -0
  222. package/package.json +181 -0
@@ -0,0 +1,305 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { execFileSync } from 'child_process';
4
+ import * as fs from 'fs';
5
+ import { fileURLToPath } from 'node:url';
6
+ import * as os from 'os';
7
+ import path from 'path';
8
+ import { LambdaClient, UpdateFunctionCodeCommand } from '@aws-sdk/client-lambda';
9
+ import { Command } from 'commander';
10
+ import { APP_VERSION, validateNumber } from '../config/cli.constants.js';
11
+ import { auditLog } from '../utils/audit-log.js';
12
+ import { decodeTokenPayload } from '../utils/auth-guard.js';
13
+ import { resolveAwsRegion } from '../utils/aws-env.js';
14
+ import { upsertSecret, getSecretArn } from '../utils/aws-secrets.js';
15
+ import { createAuthenticatedClientAsync, printCommandHeader, printSslWarning, withProfileOption, withRegionOption, withSslOptions } from '../utils/command-utils.js';
16
+ import { toEventBridgeCron } from '../utils/cron.js';
17
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
18
+ import { printInfo, printKeyValue, printSection, printSuccess } from '../utils/output-utils.js';
19
+ import { ensurePlatformToken, resolveSecretName } from '../utils/platform-secret.js';
20
+ // ESM has no __dirname; derive it from this module's URL.
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
+ const RENEW_STACK_NAME = 'pipeline-builder-token-renew';
23
+ // CFN-managed Lambda function name — keep in sync with token-renew-stack.json.
24
+ const RENEW_LAMBDA_NAME = 'pipeline-builder-token-renew';
25
+ // Default 5-field cron (daily at midnight) when neither --cron nor TOKEN_RENEW_SCHEDULE is set.
26
+ const DEFAULT_RENEW_CRON = '0 0 * * *';
27
+ /**
28
+ * Deploy (or update) the once-a-day token-renewal stack: a scheduled Lambda that
29
+ * re-mints the platform JWT in this same secret before it expires. Mirrors
30
+ * setup-events — `aws cloudformation deploy` for the infra, then a direct
31
+ * UpdateFunctionCode with the thin orchestrator handler compiled alongside this
32
+ * CLI (the handler npm-installs pipeline-manager at runtime and re-runs
33
+ * store-token; see src/lambda/token-renew-handler.ts).
34
+ */
35
+ async function deployRenewSchedule(opts) {
36
+ const scheduleExpression = toEventBridgeCron(opts.fiveFieldCron); // validates + 15-min guard
37
+ // Name renewal resources per-secret so a scoped-token stack (e.g. the
38
+ // reporting-ingest credential the event Lambda reads) coexists with the
39
+ // platform-token stack instead of colliding on the (account-global) IAM
40
+ // role / Lambda / rule names. The platform secret keeps the bare name
41
+ // (suffix '') so existing deployments' stack is updated in place, not
42
+ // duplicated; any other secret appends its trailing path segment.
43
+ const secretLeaf = opts.secretName.replace(/.*\//, ''); // 'platform' | 'reporting-ingest' | …
44
+ const nameSuffix = secretLeaf === 'platform' ? '' : `-${secretLeaf.replace(/[^a-z0-9]+/gi, '-')}`;
45
+ const stackName = `${RENEW_STACK_NAME}${nameSuffix}`;
46
+ const lambdaName = `${RENEW_LAMBDA_NAME}${nameSuffix}`;
47
+ printSection('Schedule Renewal');
48
+ printInfo('Parameters', {
49
+ stack: stackName,
50
+ schedule: opts.fiveFieldCron,
51
+ eventbridge: scheduleExpression,
52
+ renewDays: opts.days,
53
+ });
54
+ // Step 1: infra (Lambda gets placeholder code on first create).
55
+ const templatePath = path.join(__dirname, '../templates/token-renew-stack.json');
56
+ const cfnArgs = [
57
+ 'cloudformation', 'deploy',
58
+ '--stack-name', stackName,
59
+ '--template-file', templatePath,
60
+ '--parameter-overrides',
61
+ `PlatformBaseUrl=${opts.platformUrl}`,
62
+ `PlatformSecretName=${opts.secretName}`,
63
+ `RenewDays=${opts.days}`,
64
+ `ScheduleExpression=${scheduleExpression}`,
65
+ `NameSuffix=${nameSuffix}`,
66
+ // Pin the handler's runtime npm install to THIS CLI's version (reproducible
67
+ // renewals instead of a floating "latest").
68
+ `PipelineManagerVersion=${APP_VERSION}`,
69
+ '--capabilities', 'CAPABILITY_NAMED_IAM',
70
+ '--no-fail-on-empty-changeset',
71
+ '--region', opts.region,
72
+ ];
73
+ if (opts.profile)
74
+ cfnArgs.push('--profile', opts.profile);
75
+ execFileSync('aws', cfnArgs, { stdio: 'inherit' });
76
+ // Step 2: upload the real handler. It's ESM, so the zip entry must be index.mjs
77
+ // (Handler stays index.handler — nodejs24.x resolves the .mjs extension).
78
+ const handlerSrc = path.join(__dirname, '../lambda/token-renew-handler.js');
79
+ if (!fs.existsSync(handlerSrc)) {
80
+ throw new Error(`Token-renew handler not found at ${handlerSrc} — was the package built?`);
81
+ }
82
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'token-renew-'));
83
+ try {
84
+ fs.copyFileSync(handlerSrc, path.join(tmpDir, 'index.mjs'));
85
+ const zipPath = path.join(tmpDir, 'index.zip');
86
+ execFileSync('zip', ['-j', zipPath, 'index.mjs'], { cwd: tmpDir, stdio: 'pipe' });
87
+ const lambdaClient = new LambdaClient({ region: opts.region });
88
+ await lambdaClient.send(new UpdateFunctionCodeCommand({
89
+ FunctionName: lambdaName,
90
+ ZipFile: fs.readFileSync(zipPath),
91
+ }));
92
+ }
93
+ finally {
94
+ fs.rmSync(tmpDir, { recursive: true, force: true });
95
+ }
96
+ printSuccess(`Renewal scheduled (${scheduleExpression})`);
97
+ return scheduleExpression;
98
+ }
99
+ /**
100
+ * Registers the `store-token` command with the CLI program.
101
+ *
102
+ * Generates a long-lived JWT token via the platform API and stores it
103
+ * in AWS Secrets Manager for use by the synth/deploy --store-tokens flag.
104
+ *
105
+ * Requires PLATFORM_TOKEN to be set, or use --email/--password to login inline.
106
+ *
107
+ * By default it ONLY writes the secret. Pass --schedule to also deploy the daily
108
+ * token-renewal stack (a Lambda that auto-renews this token before it expires).
109
+ *
110
+ * @example
111
+ * ```bash
112
+ * pipeline-manager infra store-token --region us-east-1
113
+ * pipeline-manager infra store-token --days 90 --region us-east-1
114
+ * pipeline-manager infra store-token --schedule --region us-east-1 # + daily auto-renewal
115
+ * pipeline-manager infra store-token --schedule --cron '0 3 * * *' # custom renewal time
116
+ * pipeline-manager infra store-token --days 7 --no-verify-ssl
117
+ * PLATFORM_SECRET_NAME=my-custom-secret pipeline-manager infra store-token # override the derived name
118
+ * pipeline-manager infra store-token --dry-run
119
+ * pipeline-manager infra store-token -e admin -p '***' --region us-east-1
120
+ * ```
121
+ */
122
+ export function storeToken(program) {
123
+ withSslOptions(withProfileOption(withRegionOption(program
124
+ .command('store-token')
125
+ .description('Generate JWT token and store in AWS Secrets Manager for CDK deployments')
126
+ .option('-u, --identifier <identifier>', 'Username or email (skips PLATFORM_TOKEN requirement)')
127
+ .option('-p, --password <password>', 'Login password (used with --identifier)')
128
+ .option('--days <days>', 'Token lifetime in days', '30')
129
+ .option('--scope <scope>', 'Mint a narrow-scope machine token (e.g. "reporting:ingest") and store it at a scope-specific secret path instead of the shared platform secret')
130
+ .option('--dry-run', 'Show what would be stored without writing to Secrets Manager', false)))
131
+ .option('--schedule', 'Also deploy the daily token-renewal stack that auto-renews this token (off by default)', false)
132
+ .option('--cron <expr>', 'Renewal schedule as a 5-field cron, used with --schedule (default: TOKEN_RENEW_SCHEDULE env or "0 0 * * *"; min every 15 minutes)')
133
+ .option('--json', 'Output result as JSON', false))
134
+ .action(async (options) => {
135
+ const executionId = printCommandHeader('Store Token', undefined, { quiet: options.json });
136
+ try {
137
+ printSslWarning(options.verifySsl);
138
+ const region = resolveAwsRegion(options.region);
139
+ const days = validateNumber(options.days, 'days', 1, 365);
140
+ const expiresInSeconds = days * 24 * 60 * 60;
141
+ // Step 0: log in first when creds are available and no PLATFORM_TOKEN is set
142
+ // (shared with setup-events). Creds come from --email/--password OR the env
143
+ // vars PLATFORM_IDENTIFIER/PLATFORM_PASSWORD — the env path lets callers like
144
+ // `provision --with-events` pass them without putting the password on the
145
+ // command line (where it would show in plans/logs).
146
+ await ensurePlatformToken(options);
147
+ // Step 1: Authenticate and generate long-lived token
148
+ printSection('Generate Token');
149
+ const client = await createAuthenticatedClientAsync(options);
150
+ // Resolve secret name from the token's organizationId. An explicit
151
+ // PLATFORM_SECRET_NAME env wins (escape hatch for system/no-org tokens and
152
+ // the renewal Lambda); otherwise derive `{prefix}/{orgId}/platform`.
153
+ // A `--scope` token is a distinct machine credential — store it at a
154
+ // scope-specific path (`.../reporting-ingest`) so it never clobbers the
155
+ // full-privilege platform token used by synth/deploy callbacks.
156
+ const scope = options.scope;
157
+ const baseSecretName = process.env.PLATFORM_SECRET_NAME || resolveSecretName(process.env.PLATFORM_TOKEN);
158
+ const secretName = scope && !process.env.PLATFORM_SECRET_NAME
159
+ ? baseSecretName.replace(/\/platform$/, `/${scope.replace(/[^a-z0-9]+/gi, '-')}`)
160
+ : baseSecretName;
161
+ auditLog('store-token', { executionId, secretName, days, dryRun: options.dryRun });
162
+ printInfo('Parameters', {
163
+ secretName,
164
+ region,
165
+ days,
166
+ expiresIn: `${expiresInSeconds}s`,
167
+ dryRun: options.dryRun,
168
+ });
169
+ printInfo('Requesting token', { expiresIn: `${expiresInSeconds}s (${days} days)` });
170
+ const tokenResponse = await client.post('/api/user/generate-token', { expiresIn: expiresInSeconds, ...(scope ? { scope } : {}) });
171
+ const tokenData = tokenResponse?.data ?? tokenResponse;
172
+ const accessToken = tokenData?.accessToken;
173
+ const refreshToken = tokenData?.refreshToken;
174
+ const actualExpiresIn = tokenData?.expiresIn ?? expiresInSeconds;
175
+ if (!accessToken) {
176
+ throw new Error('Token generation failed — no access token in response');
177
+ }
178
+ printSuccess(`Token generated (expires in ${actualExpiresIn}s)`);
179
+ const expiresAt = new Date(Date.now() + actualExpiresIn * 1000).toISOString();
180
+ // Schema: { username: orgId, password: JWT, ...metadata }
181
+ // - username/password fields satisfy CodeBuild's `secretsManagerCredentials`
182
+ // (HTTP Basic, sent to pipeline-image-registry's /token endpoint)
183
+ // - The same JWT is consumed by the plugin-lookup Lambda by reading
184
+ // the `password` field
185
+ // - One Secret per customer account replaces the previous two-secret model
186
+ // Decode JWT for orgId — it's a stable identifier for the username field;
187
+ // the actual auth uses the password (JWT) which the token service verifies.
188
+ // `||` (not `??`): an EMPTY-string organizationId must also fall back. A
189
+ // sysadmin/system token often carries organizationId="", and CodeBuild
190
+ // rejects a registry credential whose `username` field is empty with
191
+ // "AuthorizationData is malformed, empty field" — so username must always
192
+ // be a non-empty value.
193
+ const payload = decodeTokenPayload(accessToken);
194
+ const orgId = payload?.organizationId?.trim() || 'unknown-org';
195
+ const secretValue = JSON.stringify({
196
+ username: orgId,
197
+ // `password` is the canonical JWT field — read by CodeBuild creds,
198
+ // plugin-lookup, token-renew, and the event-ingestion Lambda.
199
+ password: accessToken,
200
+ ...(refreshToken && { refreshToken }),
201
+ platformUrl: client.getBaseUrl(),
202
+ expiresIn: actualExpiresIn,
203
+ expiresAt,
204
+ createdAt: new Date().toISOString(),
205
+ });
206
+ // Dry-run: show what would be stored
207
+ if (options.dryRun) {
208
+ if (options.json) {
209
+ console.log(JSON.stringify({
210
+ success: true,
211
+ dryRun: true,
212
+ secretName,
213
+ region,
214
+ expiresInDays: days,
215
+ expiresAt,
216
+ tokenLength: accessToken.length,
217
+ hasRefreshToken: !!refreshToken,
218
+ }, null, 2));
219
+ }
220
+ else {
221
+ console.log('');
222
+ printSection('Dry Run — No Changes Made');
223
+ printKeyValue({
224
+ 'Secret Name': secretName,
225
+ 'Region': region,
226
+ 'Expires In': `${days} days`,
227
+ 'Renew By': expiresAt,
228
+ 'Token Length': `${accessToken.length} chars`,
229
+ 'Has Refresh Token': refreshToken ? 'Yes' : 'No',
230
+ });
231
+ printSuccess('Dry run complete — no secret was created or updated');
232
+ }
233
+ return;
234
+ }
235
+ // Step 2: Store token in Secrets Manager
236
+ printSection('Store Token');
237
+ const description = `Platform JWT token (renew by ${expiresAt})`;
238
+ await upsertSecret(secretName, secretValue, description, { region, profile: options.profile });
239
+ const arn = await getSecretArn(secretName, { region, profile: options.profile });
240
+ // Optionally install the once-a-day renewal stack so this token never lapses.
241
+ // Off by default — opt in with --schedule (e.g. for the AWS event-ingestion
242
+ // bundle whose Lambda needs a non-expiring token).
243
+ let scheduleExpression;
244
+ if (options.schedule) {
245
+ const fiveFieldCron = options.cron || process.env.TOKEN_RENEW_SCHEDULE || DEFAULT_RENEW_CRON;
246
+ scheduleExpression = await deployRenewSchedule({
247
+ platformUrl: client.getBaseUrl(),
248
+ secretName,
249
+ days,
250
+ fiveFieldCron,
251
+ region,
252
+ profile: options.profile,
253
+ });
254
+ }
255
+ if (options.json) {
256
+ console.log(JSON.stringify({
257
+ success: true,
258
+ secretName,
259
+ secretArn: arn,
260
+ region,
261
+ expiresInDays: days,
262
+ expiresAt,
263
+ schedule: scheduleExpression ?? null,
264
+ }, null, 2));
265
+ }
266
+ else {
267
+ console.log('');
268
+ printSection('Token Stored');
269
+ printKeyValue({
270
+ 'Secret Name': secretName,
271
+ 'Secret ARN': arn,
272
+ 'Region': region,
273
+ 'Expires In': `${days} days`,
274
+ 'Renew By': expiresAt,
275
+ 'Auto-Renew': scheduleExpression ? `✓ ${scheduleExpression}` : 'off (pass --schedule to enable)',
276
+ 'Status': '✓ Stored',
277
+ });
278
+ console.log('');
279
+ printSuccess('Token stored. To use with synth/deploy:');
280
+ printInfo(` export PLATFORM_SECRET_NAME=${secretName}`);
281
+ printInfo(' pipeline-manager pipeline synth --id <pipeline-id> --store-tokens');
282
+ console.log('');
283
+ if (scheduleExpression) {
284
+ printInfo(`Auto-renewal is active (${scheduleExpression}); the secret refreshes before ${expiresAt}.`);
285
+ }
286
+ else {
287
+ printInfo(`Renew before ${expiresAt} with: pipeline-manager infra store-token --days ${days}`);
288
+ printInfo(' (or pass --schedule to install a daily auto-renewal stack)');
289
+ }
290
+ }
291
+ }
292
+ catch (error) {
293
+ handleError(error, ERROR_CODES.API_REQUEST, {
294
+ debug: program.opts().debug,
295
+ exit: true,
296
+ context: {
297
+ command: 'store-token',
298
+ executionId,
299
+ secretName: process.env.PLATFORM_SECRET_NAME || '(derived from token)',
300
+ },
301
+ });
302
+ }
303
+ });
304
+ }
305
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckUsT0FBTyxFQUFFLDhCQUE4QixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNySyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVyRiwwREFBMEQ7QUFDMUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUUvRCxNQUFNLGdCQUFnQixHQUFHLDhCQUE4QixDQUFDO0FBQ3hELCtFQUErRTtBQUMvRSxNQUFNLGlCQUFpQixHQUFHLDhCQUE4QixDQUFDO0FBQ3pELGdHQUFnRztBQUNoRyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQztBQUV2Qzs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLElBT2xDO0lBQ0MsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQywyQkFBMkI7SUFFN0Ysc0VBQXNFO0lBQ3RFLHdFQUF3RTtJQUN4RSx3RUFBd0U7SUFDeEUsc0VBQXNFO0lBQ3RFLHNFQUFzRTtJQUN0RSxrRUFBa0U7SUFDbEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsc0NBQXNDO0lBQzlGLE1BQU0sVUFBVSxHQUFHLFVBQVUsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQ2xHLE1BQU0sU0FBUyxHQUFHLEdBQUcsZ0JBQWdCLEdBQUcsVUFBVSxFQUFFLENBQUM7SUFDckQsTUFBTSxVQUFVLEdBQUcsR0FBRyxpQkFBaUIsR0FBRyxVQUFVLEVBQUUsQ0FBQztJQUV2RCxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNqQyxTQUFTLENBQUMsWUFBWSxFQUFFO1FBQ3RCLEtBQUssRUFBRSxTQUFTO1FBQ2hCLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYTtRQUM1QixXQUFXLEVBQUUsa0JBQWtCO1FBQy9CLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSTtLQUNyQixDQUFDLENBQUM7SUFFSCxnRUFBZ0U7SUFDaEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUscUNBQXFDLENBQUMsQ0FBQztJQUNqRixNQUFNLE9BQU8sR0FBRztRQUNkLGdCQUFnQixFQUFFLFFBQVE7UUFDMUIsY0FBYyxFQUFFLFNBQVM7UUFDekIsaUJBQWlCLEVBQUUsWUFBWTtRQUMvQix1QkFBdUI7UUFDdkIsbUJBQW1CLElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDckMsc0JBQXNCLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDdkMsYUFBYSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ3hCLHNCQUFzQixrQkFBa0IsRUFBRTtRQUMxQyxjQUFjLFVBQVUsRUFBRTtRQUMxQiw0RUFBNEU7UUFDNUUsNENBQTRDO1FBQzVDLDBCQUEwQixXQUFXLEVBQUU7UUFDdkMsZ0JBQWdCLEVBQUUsc0JBQXNCO1FBQ3hDLDhCQUE4QjtRQUM5QixVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU07S0FDeEIsQ0FBQztJQUNGLElBQUksSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUQsWUFBWSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUVuRCxnRkFBZ0Y7SUFDaEYsMEVBQTBFO0lBQzFFLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGtDQUFrQyxDQUFDLENBQUM7SUFDNUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxVQUFVLDJCQUEyQixDQUFDLENBQUM7SUFDN0YsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUN0RSxJQUFJLENBQUM7UUFDSCxFQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQzVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQy9DLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUVsRixNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMvRCxNQUFNLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSx5QkFBeUIsQ0FBQztZQUNwRCxZQUFZLEVBQUUsVUFBVTtZQUN4QixPQUFPLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7U0FDbEMsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO1lBQVMsQ0FBQztRQUNULEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsWUFBWSxDQUFDLHNCQUFzQixrQkFBa0IsR0FBRyxDQUFDLENBQUM7SUFDMUQsT0FBTyxrQkFBa0IsQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLE9BQWdCO0lBQ3pDLGNBQWMsQ0FDWixpQkFBaUIsQ0FDZixnQkFBZ0IsQ0FBQyxPQUFPO1NBQ3JCLE9BQU8sQ0FBQyxhQUFhLENBQUM7U0FDdEIsV0FBVyxDQUFDLHlFQUF5RSxDQUFDO1NBQ3RGLE1BQU0sQ0FBQywrQkFBK0IsRUFBRSxzREFBc0QsQ0FBQztTQUMvRixNQUFNLENBQUMsMkJBQTJCLEVBQUUseUNBQXlDLENBQUM7U0FDOUUsTUFBTSxDQUFDLGVBQWUsRUFBRSx3QkFBd0IsRUFBRSxJQUFJLENBQUM7U0FDdkQsTUFBTSxDQUFDLGlCQUFpQixFQUFFLGdKQUFnSixDQUFDO1NBQzNLLE1BQU0sQ0FBQyxXQUFXLEVBQUUsOERBQThELEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FDL0Y7U0FDRSxNQUFNLENBQUMsWUFBWSxFQUFFLHdGQUF3RixFQUFFLEtBQUssQ0FBQztTQUNySCxNQUFNLENBQUMsZUFBZSxFQUFFLG1JQUFtSSxDQUFDO1NBQzVKLE1BQU0sQ0FBQyxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLENBQ3BEO1NBQ0UsTUFBTSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUN4QixNQUFNLFdBQVcsR0FBRyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsU0FBUyxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRTFGLElBQUksQ0FBQztZQUNILGVBQWUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFbkMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWhELE1BQU0sSUFBSSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDMUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFFN0MsNkVBQTZFO1lBQzdFLDRFQUE0RTtZQUM1RSw4RUFBOEU7WUFDOUUsMEVBQTBFO1lBQzFFLG9EQUFvRDtZQUNwRCxNQUFNLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRW5DLHFEQUFxRDtZQUNyRCxZQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUUvQixNQUFNLE1BQU0sR0FBRyxNQUFNLDhCQUE4QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTdELG1FQUFtRTtZQUNuRSwyRUFBMkU7WUFDM0UscUVBQXFFO1lBQ3JFLHFFQUFxRTtZQUNyRSx3RUFBd0U7WUFDeEUsZ0VBQWdFO1lBQ2hFLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUEyQixDQUFDO1lBQ2xELE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksaUJBQWlCLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFlLENBQUMsQ0FBQztZQUMxRyxNQUFNLFVBQVUsR0FBRyxLQUFLLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQjtnQkFDM0QsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDakYsQ0FBQyxDQUFDLGNBQWMsQ0FBQztZQUVuQixRQUFRLENBQUMsYUFBYSxFQUFFLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBRW5GLFNBQVMsQ0FBQyxZQUFZLEVBQUU7Z0JBQ3RCLFVBQVU7Z0JBQ1YsTUFBTTtnQkFDTixJQUFJO2dCQUNKLFNBQVMsRUFBRSxHQUFHLGdCQUFnQixHQUFHO2dCQUNqQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07YUFDdkIsQ0FBQyxDQUFDO1lBRUgsU0FBUyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsZ0JBQWdCLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRXBGLE1BQU0sYUFBYSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FDckMsMEJBQTBCLEVBQzFCLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQzdELENBQUM7WUFFRixNQUFNLFNBQVMsR0FBSSxhQUF5QyxFQUFFLElBQUksSUFBSSxhQUFhLENBQUM7WUFDcEYsTUFBTSxXQUFXLEdBQUksU0FBcUMsRUFBRSxXQUFpQyxDQUFDO1lBQzlGLE1BQU0sWUFBWSxHQUFJLFNBQXFDLEVBQUUsWUFBa0MsQ0FBQztZQUNoRyxNQUFNLGVBQWUsR0FBSyxTQUFxQyxFQUFFLFNBQW9CLElBQUksZ0JBQWdCLENBQUM7WUFFMUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7WUFDM0UsQ0FBQztZQUVELFlBQVksQ0FBQywrQkFBK0IsZUFBZSxJQUFJLENBQUMsQ0FBQztZQUVqRSxNQUFNLFNBQVMsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRTlFLDBEQUEwRDtZQUMxRCw2RUFBNkU7WUFDN0Usb0VBQW9FO1lBQ3BFLG9FQUFvRTtZQUNwRSx5QkFBeUI7WUFDekIsMkVBQTJFO1lBQzNFLDBFQUEwRTtZQUMxRSw0RUFBNEU7WUFDNUUseUVBQXlFO1lBQ3pFLHVFQUF1RTtZQUN2RSxxRUFBcUU7WUFDckUsMEVBQTBFO1lBQzFFLHdCQUF3QjtZQUN4QixNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRCxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxJQUFJLGFBQWEsQ0FBQztZQUUvRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNqQyxRQUFRLEVBQUUsS0FBSztnQkFDZixtRUFBbUU7Z0JBQ25FLDhEQUE4RDtnQkFDOUQsUUFBUSxFQUFFLFdBQVc7Z0JBQ3JCLEdBQUcsQ0FBQyxZQUFZLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztnQkFDckMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUU7Z0JBQ2hDLFNBQVMsRUFBRSxlQUFlO2dCQUMxQixTQUFTO2dCQUNULFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTthQUNwQyxDQUFDLENBQUM7WUFFSCxxQ0FBcUM7WUFDckMsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ25CLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQ3pCLE9BQU8sRUFBRSxJQUFJO3dCQUNiLE1BQU0sRUFBRSxJQUFJO3dCQUNaLFVBQVU7d0JBQ1YsTUFBTTt3QkFDTixhQUFhLEVBQUUsSUFBSTt3QkFDbkIsU0FBUzt3QkFDVCxXQUFXLEVBQUUsV0FBVyxDQUFDLE1BQU07d0JBQy9CLGVBQWUsRUFBRSxDQUFDLENBQUMsWUFBWTtxQkFDaEMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZixDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDaEIsWUFBWSxDQUFDLDJCQUEyQixDQUFDLENBQUM7b0JBQzFDLGFBQWEsQ0FBQzt3QkFDWixhQUFhLEVBQUUsVUFBVTt3QkFDekIsUUFBUSxFQUFFLE1BQU07d0JBQ2hCLFlBQVksRUFBRSxHQUFHLElBQUksT0FBTzt3QkFDNUIsVUFBVSxFQUFFLFNBQVM7d0JBQ3JCLGNBQWMsRUFBRSxHQUFHLFdBQVcsQ0FBQyxNQUFNLFFBQVE7d0JBQzdDLG1CQUFtQixFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO3FCQUNqRCxDQUFDLENBQUM7b0JBQ0gsWUFBWSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7Z0JBQ3RFLENBQUM7Z0JBQ0QsT0FBTztZQUNULENBQUM7WUFFRCx5Q0FBeUM7WUFDekMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRTVCLE1BQU0sV0FBVyxHQUFHLGdDQUFnQyxTQUFTLEdBQUcsQ0FBQztZQUNqRSxNQUFNLFlBQVksQ0FBQyxVQUFVLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFL0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxZQUFZLENBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUVqRiw4RUFBOEU7WUFDOUUsNEVBQTRFO1lBQzVFLG1EQUFtRDtZQUNuRCxJQUFJLGtCQUFzQyxDQUFDO1lBQzNDLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNyQixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksa0JBQWtCLENBQUM7Z0JBQzdGLGtCQUFrQixHQUFHLE1BQU0sbUJBQW1CLENBQUM7b0JBQzdDLFdBQVcsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFO29CQUNoQyxVQUFVO29CQUNWLElBQUk7b0JBQ0osYUFBYTtvQkFDYixNQUFNO29CQUNOLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztpQkFDekIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQ3pCLE9BQU8sRUFBRSxJQUFJO29CQUNiLFVBQVU7b0JBQ1YsU0FBUyxFQUFFLEdBQUc7b0JBQ2QsTUFBTTtvQkFDTixhQUFhLEVBQUUsSUFBSTtvQkFDbkIsU0FBUztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCLElBQUksSUFBSTtpQkFDckMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNmLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBRTdCLGFBQWEsQ0FBQztvQkFDWixhQUFhLEVBQUUsVUFBVTtvQkFDekIsWUFBWSxFQUFFLEdBQUc7b0JBQ2pCLFFBQVEsRUFBRSxNQUFNO29CQUNoQixZQUFZLEVBQUUsR0FBRyxJQUFJLE9BQU87b0JBQzVCLFVBQVUsRUFBRSxTQUFTO29CQUNyQixZQUFZLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLEtBQUssa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUMsaUNBQWlDO29CQUNoRyxRQUFRLEVBQUUsVUFBVTtpQkFDckIsQ0FBQyxDQUFDO2dCQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLFlBQVksQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO2dCQUN4RCxTQUFTLENBQUMsaUNBQWlDLFVBQVUsRUFBRSxDQUFDLENBQUM7Z0JBQ3pELFNBQVMsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDO2dCQUNqRixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixJQUFJLGtCQUFrQixFQUFFLENBQUM7b0JBQ3ZCLFNBQVMsQ0FBQywyQkFBMkIsa0JBQWtCLGtDQUFrQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO2dCQUN6RyxDQUFDO3FCQUFNLENBQUM7b0JBQ04sU0FBUyxDQUFDLGdCQUFnQixTQUFTLG9EQUFvRCxJQUFJLEVBQUUsQ0FBQyxDQUFDO29CQUMvRixTQUFTLENBQUMsOERBQThELENBQUMsQ0FBQztnQkFDNUUsQ0FBQztZQUNILENBQUM7UUFFSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUU7b0JBQ1AsT0FBTyxFQUFFLGFBQWE7b0JBQ3RCLFdBQVc7b0JBQ1gsVUFBVSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksc0JBQXNCO2lCQUN2RTthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgZXhlY0ZpbGVTeW5jIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBMYW1iZGFDbGllbnQsIFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtbGFtYmRhJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IHsgQVBQX1ZFUlNJT04sIHZhbGlkYXRlTnVtYmVyIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXVkaXRMb2cgfSBmcm9tICcuLi91dGlscy9hdWRpdC1sb2cuanMnO1xuaW1wb3J0IHsgZGVjb2RlVG9rZW5QYXlsb2FkIH0gZnJvbSAnLi4vdXRpbHMvYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyByZXNvbHZlQXdzUmVnaW9uIH0gZnJvbSAnLi4vdXRpbHMvYXdzLWVudi5qcyc7XG5pbXBvcnQgeyB1cHNlcnRTZWNyZXQsIGdldFNlY3JldEFybiB9IGZyb20gJy4uL3V0aWxzL2F3cy1zZWNyZXRzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYywgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgdG9FdmVudEJyaWRnZUNyb24gfSBmcm9tICcuLi91dGlscy9jcm9uLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBlbnN1cmVQbGF0Zm9ybVRva2VuLCByZXNvbHZlU2VjcmV0TmFtZSB9IGZyb20gJy4uL3V0aWxzL3BsYXRmb3JtLXNlY3JldC5qcyc7XG5cbi8vIEVTTSBoYXMgbm8gX19kaXJuYW1lOyBkZXJpdmUgaXQgZnJvbSB0aGlzIG1vZHVsZSdzIFVSTC5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuXG5jb25zdCBSRU5FV19TVEFDS19OQU1FID0gJ3BpcGVsaW5lLWJ1aWxkZXItdG9rZW4tcmVuZXcnO1xuLy8gQ0ZOLW1hbmFnZWQgTGFtYmRhIGZ1bmN0aW9uIG5hbWUg4oCUIGtlZXAgaW4gc3luYyB3aXRoIHRva2VuLXJlbmV3LXN0YWNrLmpzb24uXG5jb25zdCBSRU5FV19MQU1CREFfTkFNRSA9ICdwaXBlbGluZS1idWlsZGVyLXRva2VuLXJlbmV3Jztcbi8vIERlZmF1bHQgNS1maWVsZCBjcm9uIChkYWlseSBhdCBtaWRuaWdodCkgd2hlbiBuZWl0aGVyIC0tY3JvbiBub3IgVE9LRU5fUkVORVdfU0NIRURVTEUgaXMgc2V0LlxuY29uc3QgREVGQVVMVF9SRU5FV19DUk9OID0gJzAgMCAqICogKic7XG5cbi8qKlxuICogRGVwbG95IChvciB1cGRhdGUpIHRoZSBvbmNlLWEtZGF5IHRva2VuLXJlbmV3YWwgc3RhY2s6IGEgc2NoZWR1bGVkIExhbWJkYSB0aGF0XG4gKiByZS1taW50cyB0aGUgcGxhdGZvcm0gSldUIGluIHRoaXMgc2FtZSBzZWNyZXQgYmVmb3JlIGl0IGV4cGlyZXMuIE1pcnJvcnNcbiAqIHNldHVwLWV2ZW50cyDigJQgYGF3cyBjbG91ZGZvcm1hdGlvbiBkZXBsb3lgIGZvciB0aGUgaW5mcmEsIHRoZW4gYSBkaXJlY3RcbiAqIFVwZGF0ZUZ1bmN0aW9uQ29kZSB3aXRoIHRoZSB0aGluIG9yY2hlc3RyYXRvciBoYW5kbGVyIGNvbXBpbGVkIGFsb25nc2lkZSB0aGlzXG4gKiBDTEkgKHRoZSBoYW5kbGVyIG5wbS1pbnN0YWxscyBwaXBlbGluZS1tYW5hZ2VyIGF0IHJ1bnRpbWUgYW5kIHJlLXJ1bnNcbiAqIHN0b3JlLXRva2VuOyBzZWUgc3JjL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLnRzKS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95UmVuZXdTY2hlZHVsZShvcHRzOiB7XG4gIHBsYXRmb3JtVXJsOiBzdHJpbmc7XG4gIHNlY3JldE5hbWU6IHN0cmluZztcbiAgZGF5czogbnVtYmVyO1xuICBmaXZlRmllbGRDcm9uOiBzdHJpbmc7XG4gIHJlZ2lvbjogc3RyaW5nO1xuICBwcm9maWxlPzogc3RyaW5nO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHNjaGVkdWxlRXhwcmVzc2lvbiA9IHRvRXZlbnRCcmlkZ2VDcm9uKG9wdHMuZml2ZUZpZWxkQ3Jvbik7IC8vIHZhbGlkYXRlcyArIDE1LW1pbiBndWFyZFxuXG4gIC8vIE5hbWUgcmVuZXdhbCByZXNvdXJjZXMgcGVyLXNlY3JldCBzbyBhIHNjb3BlZC10b2tlbiBzdGFjayAoZS5nLiB0aGVcbiAgLy8gcmVwb3J0aW5nLWluZ2VzdCBjcmVkZW50aWFsIHRoZSBldmVudCBMYW1iZGEgcmVhZHMpIGNvZXhpc3RzIHdpdGggdGhlXG4gIC8vIHBsYXRmb3JtLXRva2VuIHN0YWNrIGluc3RlYWQgb2YgY29sbGlkaW5nIG9uIHRoZSAoYWNjb3VudC1nbG9iYWwpIElBTVxuICAvLyByb2xlIC8gTGFtYmRhIC8gcnVsZSBuYW1lcy4gVGhlIHBsYXRmb3JtIHNlY3JldCBrZWVwcyB0aGUgYmFyZSBuYW1lXG4gIC8vIChzdWZmaXggJycpIHNvIGV4aXN0aW5nIGRlcGxveW1lbnRzJyBzdGFjayBpcyB1cGRhdGVkIGluIHBsYWNlLCBub3RcbiAgLy8gZHVwbGljYXRlZDsgYW55IG90aGVyIHNlY3JldCBhcHBlbmRzIGl0cyB0cmFpbGluZyBwYXRoIHNlZ21lbnQuXG4gIGNvbnN0IHNlY3JldExlYWYgPSBvcHRzLnNlY3JldE5hbWUucmVwbGFjZSgvLipcXC8vLCAnJyk7IC8vICdwbGF0Zm9ybScgfCAncmVwb3J0aW5nLWluZ2VzdCcgfCDigKZcbiAgY29uc3QgbmFtZVN1ZmZpeCA9IHNlY3JldExlYWYgPT09ICdwbGF0Zm9ybScgPyAnJyA6IGAtJHtzZWNyZXRMZWFmLnJlcGxhY2UoL1teYS16MC05XSsvZ2ksICctJyl9YDtcbiAgY29uc3Qgc3RhY2tOYW1lID0gYCR7UkVORVdfU1RBQ0tfTkFNRX0ke25hbWVTdWZmaXh9YDtcbiAgY29uc3QgbGFtYmRhTmFtZSA9IGAke1JFTkVXX0xBTUJEQV9OQU1FfSR7bmFtZVN1ZmZpeH1gO1xuXG4gIHByaW50U2VjdGlvbignU2NoZWR1bGUgUmVuZXdhbCcpO1xuICBwcmludEluZm8oJ1BhcmFtZXRlcnMnLCB7XG4gICAgc3RhY2s6IHN0YWNrTmFtZSxcbiAgICBzY2hlZHVsZTogb3B0cy5maXZlRmllbGRDcm9uLFxuICAgIGV2ZW50YnJpZGdlOiBzY2hlZHVsZUV4cHJlc3Npb24sXG4gICAgcmVuZXdEYXlzOiBvcHRzLmRheXMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMTogaW5mcmEgKExhbWJkYSBnZXRzIHBsYWNlaG9sZGVyIGNvZGUgb24gZmlyc3QgY3JlYXRlKS5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL3RlbXBsYXRlcy90b2tlbi1yZW5ldy1zdGFjay5qc29uJyk7XG4gIGNvbnN0IGNmbkFyZ3MgPSBbXG4gICAgJ2Nsb3VkZm9ybWF0aW9uJywgJ2RlcGxveScsXG4gICAgJy0tc3RhY2stbmFtZScsIHN0YWNrTmFtZSxcbiAgICAnLS10ZW1wbGF0ZS1maWxlJywgdGVtcGxhdGVQYXRoLFxuICAgICctLXBhcmFtZXRlci1vdmVycmlkZXMnLFxuICAgIGBQbGF0Zm9ybUJhc2VVcmw9JHtvcHRzLnBsYXRmb3JtVXJsfWAsXG4gICAgYFBsYXRmb3JtU2VjcmV0TmFtZT0ke29wdHMuc2VjcmV0TmFtZX1gLFxuICAgIGBSZW5ld0RheXM9JHtvcHRzLmRheXN9YCxcbiAgICBgU2NoZWR1bGVFeHByZXNzaW9uPSR7c2NoZWR1bGVFeHByZXNzaW9ufWAsXG4gICAgYE5hbWVTdWZmaXg9JHtuYW1lU3VmZml4fWAsXG4gICAgLy8gUGluIHRoZSBoYW5kbGVyJ3MgcnVudGltZSBucG0gaW5zdGFsbCB0byBUSElTIENMSSdzIHZlcnNpb24gKHJlcHJvZHVjaWJsZVxuICAgIC8vIHJlbmV3YWxzIGluc3RlYWQgb2YgYSBmbG9hdGluZyBcImxhdGVzdFwiKS5cbiAgICBgUGlwZWxpbmVNYW5hZ2VyVmVyc2lvbj0ke0FQUF9WRVJTSU9OfWAsXG4gICAgJy0tY2FwYWJpbGl0aWVzJywgJ0NBUEFCSUxJVFlfTkFNRURfSUFNJyxcbiAgICAnLS1uby1mYWlsLW9uLWVtcHR5LWNoYW5nZXNldCcsXG4gICAgJy0tcmVnaW9uJywgb3B0cy5yZWdpb24sXG4gIF07XG4gIGlmIChvcHRzLnByb2ZpbGUpIGNmbkFyZ3MucHVzaCgnLS1wcm9maWxlJywgb3B0cy5wcm9maWxlKTtcbiAgZXhlY0ZpbGVTeW5jKCdhd3MnLCBjZm5BcmdzLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7XG5cbiAgLy8gU3RlcCAyOiB1cGxvYWQgdGhlIHJlYWwgaGFuZGxlci4gSXQncyBFU00sIHNvIHRoZSB6aXAgZW50cnkgbXVzdCBiZSBpbmRleC5tanNcbiAgLy8gKEhhbmRsZXIgc3RheXMgaW5kZXguaGFuZGxlciDigJQgbm9kZWpzMjQueCByZXNvbHZlcyB0aGUgLm1qcyBleHRlbnNpb24pLlxuICBjb25zdCBoYW5kbGVyU3JjID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLmpzJyk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhoYW5kbGVyU3JjKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4tcmVuZXcgaGFuZGxlciBub3QgZm91bmQgYXQgJHtoYW5kbGVyU3JjfSDigJQgd2FzIHRoZSBwYWNrYWdlIGJ1aWx0P2ApO1xuICB9XG4gIGNvbnN0IHRtcERpciA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgJ3Rva2VuLXJlbmV3LScpKTtcbiAgdHJ5IHtcbiAgICBmcy5jb3B5RmlsZVN5bmMoaGFuZGxlclNyYywgcGF0aC5qb2luKHRtcERpciwgJ2luZGV4Lm1qcycpKTtcbiAgICBjb25zdCB6aXBQYXRoID0gcGF0aC5qb2luKHRtcERpciwgJ2luZGV4LnppcCcpO1xuICAgIGV4ZWNGaWxlU3luYygnemlwJywgWyctaicsIHppcFBhdGgsICdpbmRleC5tanMnXSwgeyBjd2Q6IHRtcERpciwgc3RkaW86ICdwaXBlJyB9KTtcblxuICAgIGNvbnN0IGxhbWJkYUNsaWVudCA9IG5ldyBMYW1iZGFDbGllbnQoeyByZWdpb246IG9wdHMucmVnaW9uIH0pO1xuICAgIGF3YWl0IGxhbWJkYUNsaWVudC5zZW5kKG5ldyBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kKHtcbiAgICAgIEZ1bmN0aW9uTmFtZTogbGFtYmRhTmFtZSxcbiAgICAgIFppcEZpbGU6IGZzLnJlYWRGaWxlU3luYyh6aXBQYXRoKSxcbiAgICB9KSk7XG4gIH0gZmluYWxseSB7XG4gICAgZnMucm1TeW5jKHRtcERpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9XG5cbiAgcHJpbnRTdWNjZXNzKGBSZW5ld2FsIHNjaGVkdWxlZCAoJHtzY2hlZHVsZUV4cHJlc3Npb259KWApO1xuICByZXR1cm4gc2NoZWR1bGVFeHByZXNzaW9uO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgYHN0b3JlLXRva2VuYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIEdlbmVyYXRlcyBhIGxvbmctbGl2ZWQgSldUIHRva2VuIHZpYSB0aGUgcGxhdGZvcm0gQVBJIGFuZCBzdG9yZXMgaXRcbiAqIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIHVzZSBieSB0aGUgc3ludGgvZGVwbG95IC0tc3RvcmUtdG9rZW5zIGZsYWcuXG4gKlxuICogUmVxdWlyZXMgUExBVEZPUk1fVE9LRU4gdG8gYmUgc2V0LCBvciB1c2UgLS1lbWFpbC8tLXBhc3N3b3JkIHRvIGxvZ2luIGlubGluZS5cbiAqXG4gKiBCeSBkZWZhdWx0IGl0IE9OTFkgd3JpdGVzIHRoZSBzZWNyZXQuIFBhc3MgLS1zY2hlZHVsZSB0byBhbHNvIGRlcGxveSB0aGUgZGFpbHlcbiAqIHRva2VuLXJlbmV3YWwgc3RhY2sgKGEgTGFtYmRhIHRoYXQgYXV0by1yZW5ld3MgdGhpcyB0b2tlbiBiZWZvcmUgaXQgZXhwaXJlcykuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1yZWdpb24gdXMtZWFzdC0xXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tZGF5cyA5MCAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1zY2hlZHVsZSAtLXJlZ2lvbiB1cy1lYXN0LTEgICAgICAgICAgIyArIGRhaWx5IGF1dG8tcmVuZXdhbFxuICogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzdG9yZS10b2tlbiAtLXNjaGVkdWxlIC0tY3JvbiAnMCAzICogKiAqJyAgICAgICAgICAjIGN1c3RvbSByZW5ld2FsIHRpbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzIDcgLS1uby12ZXJpZnktc3NsXG4gKiBQTEFURk9STV9TRUNSRVRfTkFNRT1teS1jdXN0b20tc2VjcmV0IHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gICAjIG92ZXJyaWRlIHRoZSBkZXJpdmVkIG5hbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kcnktcnVuXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC1lIGFkbWluIC1wICcqKionIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9yZVRva2VuKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgd2l0aFByb2ZpbGVPcHRpb24oXG4gICAgICB3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAgICAgLmNvbW1hbmQoJ3N0b3JlLXRva2VuJylcbiAgICAgICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBKV1QgdG9rZW4gYW5kIHN0b3JlIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIENESyBkZXBsb3ltZW50cycpXG4gICAgICAgIC5vcHRpb24oJy11LCAtLWlkZW50aWZpZXIgPGlkZW50aWZpZXI+JywgJ1VzZXJuYW1lIG9yIGVtYWlsIChza2lwcyBQTEFURk9STV9UT0tFTiByZXF1aXJlbWVudCknKVxuICAgICAgICAub3B0aW9uKCctcCwgLS1wYXNzd29yZCA8cGFzc3dvcmQ+JywgJ0xvZ2luIHBhc3N3b3JkICh1c2VkIHdpdGggLS1pZGVudGlmaWVyKScpXG4gICAgICAgIC5vcHRpb24oJy0tZGF5cyA8ZGF5cz4nLCAnVG9rZW4gbGlmZXRpbWUgaW4gZGF5cycsICczMCcpXG4gICAgICAgIC5vcHRpb24oJy0tc2NvcGUgPHNjb3BlPicsICdNaW50IGEgbmFycm93LXNjb3BlIG1hY2hpbmUgdG9rZW4gKGUuZy4gXCJyZXBvcnRpbmc6aW5nZXN0XCIpIGFuZCBzdG9yZSBpdCBhdCBhIHNjb3BlLXNwZWNpZmljIHNlY3JldCBwYXRoIGluc3RlYWQgb2YgdGhlIHNoYXJlZCBwbGF0Zm9ybSBzZWNyZXQnKVxuICAgICAgICAub3B0aW9uKCctLWRyeS1ydW4nLCAnU2hvdyB3aGF0IHdvdWxkIGJlIHN0b3JlZCB3aXRob3V0IHdyaXRpbmcgdG8gU2VjcmV0cyBNYW5hZ2VyJywgZmFsc2UpKSxcbiAgICApXG4gICAgICAub3B0aW9uKCctLXNjaGVkdWxlJywgJ0Fsc28gZGVwbG95IHRoZSBkYWlseSB0b2tlbi1yZW5ld2FsIHN0YWNrIHRoYXQgYXV0by1yZW5ld3MgdGhpcyB0b2tlbiAob2ZmIGJ5IGRlZmF1bHQpJywgZmFsc2UpXG4gICAgICAub3B0aW9uKCctLWNyb24gPGV4cHI+JywgJ1JlbmV3YWwgc2NoZWR1bGUgYXMgYSA1LWZpZWxkIGNyb24sIHVzZWQgd2l0aCAtLXNjaGVkdWxlIChkZWZhdWx0OiBUT0tFTl9SRU5FV19TQ0hFRFVMRSBlbnYgb3IgXCIwIDAgKiAqICpcIjsgbWluIGV2ZXJ5IDE1IG1pbnV0ZXMpJylcbiAgICAgIC5vcHRpb24oJy0tanNvbicsICdPdXRwdXQgcmVzdWx0IGFzIEpTT04nLCBmYWxzZSksXG4gIClcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignU3RvcmUgVG9rZW4nLCB1bmRlZmluZWQsIHsgcXVpZXQ6IG9wdGlvbnMuanNvbiB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgcHJpbnRTc2xXYXJuaW5nKG9wdGlvbnMudmVyaWZ5U3NsKTtcblxuICAgICAgICBjb25zdCByZWdpb24gPSByZXNvbHZlQXdzUmVnaW9uKG9wdGlvbnMucmVnaW9uKTtcblxuICAgICAgICBjb25zdCBkYXlzID0gdmFsaWRhdGVOdW1iZXIob3B0aW9ucy5kYXlzLCAnZGF5cycsIDEsIDM2NSk7XG4gICAgICAgIGNvbnN0IGV4cGlyZXNJblNlY29uZHMgPSBkYXlzICogMjQgKiA2MCAqIDYwO1xuXG4gICAgICAgIC8vIFN0ZXAgMDogbG9nIGluIGZpcnN0IHdoZW4gY3JlZHMgYXJlIGF2YWlsYWJsZSBhbmQgbm8gUExBVEZPUk1fVE9LRU4gaXMgc2V0XG4gICAgICAgIC8vIChzaGFyZWQgd2l0aCBzZXR1cC1ldmVudHMpLiBDcmVkcyBjb21lIGZyb20gLS1lbWFpbC8tLXBhc3N3b3JkIE9SIHRoZSBlbnZcbiAgICAgICAgLy8gdmFycyBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEIOKAlCB0aGUgZW52IHBhdGggbGV0cyBjYWxsZXJzIGxpa2VcbiAgICAgICAgLy8gYHByb3Zpc2lvbiAtLXdpdGgtZXZlbnRzYCBwYXNzIHRoZW0gd2l0aG91dCBwdXR0aW5nIHRoZSBwYXNzd29yZCBvbiB0aGVcbiAgICAgICAgLy8gY29tbWFuZCBsaW5lICh3aGVyZSBpdCB3b3VsZCBzaG93IGluIHBsYW5zL2xvZ3MpLlxuICAgICAgICBhd2FpdCBlbnN1cmVQbGF0Zm9ybVRva2VuKG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIFN0ZXAgMTogQXV0aGVudGljYXRlIGFuZCBnZW5lcmF0ZSBsb25nLWxpdmVkIHRva2VuXG4gICAgICAgIHByaW50U2VjdGlvbignR2VuZXJhdGUgVG9rZW4nKTtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50QXN5bmMob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBzZWNyZXQgbmFtZSBmcm9tIHRoZSB0b2tlbidzIG9yZ2FuaXphdGlvbklkLiBBbiBleHBsaWNpdFxuICAgICAgICAvLyBQTEFURk9STV9TRUNSRVRfTkFNRSBlbnYgd2lucyAoZXNjYXBlIGhhdGNoIGZvciBzeXN0ZW0vbm8tb3JnIHRva2VucyBhbmRcbiAgICAgICAgLy8gdGhlIHJlbmV3YWwgTGFtYmRhKTsgb3RoZXJ3aXNlIGRlcml2ZSBge3ByZWZpeH0ve29yZ0lkfS9wbGF0Zm9ybWAuXG4gICAgICAgIC8vIEEgYC0tc2NvcGVgIHRva2VuIGlzIGEgZGlzdGluY3QgbWFjaGluZSBjcmVkZW50aWFsIOKAlCBzdG9yZSBpdCBhdCBhXG4gICAgICAgIC8vIHNjb3BlLXNwZWNpZmljIHBhdGggKGAuLi4vcmVwb3J0aW5nLWluZ2VzdGApIHNvIGl0IG5ldmVyIGNsb2JiZXJzIHRoZVxuICAgICAgICAvLyBmdWxsLXByaXZpbGVnZSBwbGF0Zm9ybSB0b2tlbiB1c2VkIGJ5IHN5bnRoL2RlcGxveSBjYWxsYmFja3MuXG4gICAgICAgIGNvbnN0IHNjb3BlID0gb3B0aW9ucy5zY29wZSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGJhc2VTZWNyZXROYW1lID0gcHJvY2Vzcy5lbnYuUExBVEZPUk1fU0VDUkVUX05BTUUgfHwgcmVzb2x2ZVNlY3JldE5hbWUocHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4hKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0TmFtZSA9IHNjb3BlICYmICFwcm9jZXNzLmVudi5QTEFURk9STV9TRUNSRVRfTkFNRVxuICAgICAgICAgID8gYmFzZVNlY3JldE5hbWUucmVwbGFjZSgvXFwvcGxhdGZvcm0kLywgYC8ke3Njb3BlLnJlcGxhY2UoL1teYS16MC05XSsvZ2ksICctJyl9YClcbiAgICAgICAgICA6IGJhc2VTZWNyZXROYW1lO1xuXG4gICAgICAgIGF1ZGl0TG9nKCdzdG9yZS10b2tlbicsIHsgZXhlY3V0aW9uSWQsIHNlY3JldE5hbWUsIGRheXMsIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4gfSk7XG5cbiAgICAgICAgcHJpbnRJbmZvKCdQYXJhbWV0ZXJzJywge1xuICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgIGRheXMsXG4gICAgICAgICAgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXNgLFxuICAgICAgICAgIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByaW50SW5mbygnUmVxdWVzdGluZyB0b2tlbicsIHsgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXMgKCR7ZGF5c30gZGF5cylgIH0pO1xuXG4gICAgICAgIGNvbnN0IHRva2VuUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgICAgICAgJy9hcGkvdXNlci9nZW5lcmF0ZS10b2tlbicsXG4gICAgICAgICAgeyBleHBpcmVzSW46IGV4cGlyZXNJblNlY29uZHMsIC4uLihzY29wZSA/IHsgc2NvcGUgfSA6IHt9KSB9LFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHRva2VuRGF0YSA9ICh0b2tlblJlc3BvbnNlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uZGF0YSA/PyB0b2tlblJlc3BvbnNlO1xuICAgICAgICBjb25zdCBhY2Nlc3NUb2tlbiA9ICh0b2tlbkRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5hY2Nlc3NUb2tlbiBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJlZnJlc2hUb2tlbiA9ICh0b2tlbkRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5yZWZyZXNoVG9rZW4gYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBhY3R1YWxFeHBpcmVzSW4gPSAoKHRva2VuRGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/LmV4cGlyZXNJbiBhcyBudW1iZXIpID8/IGV4cGlyZXNJblNlY29uZHM7XG5cbiAgICAgICAgaWYgKCFhY2Nlc3NUb2tlbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVG9rZW4gZ2VuZXJhdGlvbiBmYWlsZWQg4oCUIG5vIGFjY2VzcyB0b2tlbiBpbiByZXNwb25zZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJpbnRTdWNjZXNzKGBUb2tlbiBnZW5lcmF0ZWQgKGV4cGlyZXMgaW4gJHthY3R1YWxFeHBpcmVzSW59cylgKTtcblxuICAgICAgICBjb25zdCBleHBpcmVzQXQgPSBuZXcgRGF0ZShEYXRlLm5vdygpICsgYWN0dWFsRXhwaXJlc0luICogMTAwMCkudG9JU09TdHJpbmcoKTtcblxuICAgICAgICAvLyBTY2hlbWE6IHsgdXNlcm5hbWU6IG9yZ0lkLCBwYXNzd29yZDogSldULCAuLi5tZXRhZGF0YSB9XG4gICAgICAgIC8vIC0gdXNlcm5hbWUvcGFzc3dvcmQgZmllbGRzIHNhdGlzZnkgQ29kZUJ1aWxkJ3MgYHNlY3JldHNNYW5hZ2VyQ3JlZGVudGlhbHNgXG4gICAgICAgIC8vICAgKEhUVFAgQmFzaWMsIHNlbnQgdG8gcGlwZWxpbmUtaW1hZ2UtcmVnaXN0cnkncyAvdG9rZW4gZW5kcG9pbnQpXG4gICAgICAgIC8vIC0gVGhlIHNhbWUgSldUIGlzIGNvbnN1bWVkIGJ5IHRoZSBwbHVnaW4tbG9va3VwIExhbWJkYSBieSByZWFkaW5nXG4gICAgICAgIC8vICAgdGhlIGBwYXNzd29yZGAgZmllbGRcbiAgICAgICAgLy8gLSBPbmUgU2VjcmV0IHBlciBjdXN0b21lciBhY2NvdW50IHJlcGxhY2VzIHRoZSBwcmV2aW91cyB0d28tc2VjcmV0IG1vZGVsXG4gICAgICAgIC8vIERlY29kZSBKV1QgZm9yIG9yZ0lkIOKAlCBpdCdzIGEgc3RhYmxlIGlkZW50aWZpZXIgZm9yIHRoZSB1c2VybmFtZSBmaWVsZDtcbiAgICAgICAgLy8gdGhlIGFjdHVhbCBhdXRoIHVzZXMgdGhlIHBhc3N3b3JkIChKV1QpIHdoaWNoIHRoZSB0b2tlbiBzZXJ2aWNlIHZlcmlmaWVzLlxuICAgICAgICAvLyBgfHxgIChub3QgYD8/YCk6IGFuIEVNUFRZLXN0cmluZyBvcmdhbml6YXRpb25JZCBtdXN0IGFsc28gZmFsbCBiYWNrLiBBXG4gICAgICAgIC8vIHN5c2FkbWluL3N5c3RlbSB0b2tlbiBvZnRlbiBjYXJyaWVzIG9yZ2FuaXphdGlvbklkPVwiXCIsIGFuZCBDb2RlQnVpbGRcbiAgICAgICAgLy8gcmVqZWN0cyBhIHJlZ2lzdHJ5IGNyZWRlbnRpYWwgd2hvc2UgYHVzZXJuYW1lYCBmaWVsZCBpcyBlbXB0eSB3aXRoXG4gICAgICAgIC8vIFwiQXV0aG9yaXphdGlvbkRhdGEgaXMgbWFsZm9ybWVkLCBlbXB0eSBmaWVsZFwiIOKAlCBzbyB1c2VybmFtZSBtdXN0IGFsd2F5c1xuICAgICAgICAvLyBiZSBhIG5vbi1lbXB0eSB2YWx1ZS5cbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IGRlY29kZVRva2VuUGF5bG9hZChhY2Nlc3NUb2tlbik7XG4gICAgICAgIGNvbnN0IG9yZ0lkID0gcGF5bG9hZD8ub3JnYW5pemF0aW9uSWQ/LnRyaW0oKSB8fCAndW5rbm93bi1vcmcnO1xuXG4gICAgICAgIGNvbnN0IHNlY3JldFZhbHVlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIHVzZXJuYW1lOiBvcmdJZCxcbiAgICAgICAgICAvLyBgcGFzc3dvcmRgIGlzIHRoZSBjYW5vbmljYWwgSldUIGZpZWxkIOKAlCByZWFkIGJ5IENvZGVCdWlsZCBjcmVkcyxcbiAgICAgICAgICAvLyBwbHVnaW4tbG9va3VwLCB0b2tlbi1yZW5ldywgYW5kIHRoZSBldmVudC1pbmdlc3Rpb24gTGFtYmRhLlxuICAgICAgICAgIHBhc3N3b3JkOiBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAuLi4ocmVmcmVzaFRva2VuICYmIHsgcmVmcmVzaFRva2VuIH0pLFxuICAgICAgICAgIHBsYXRmb3JtVXJsOiBjbGllbnQuZ2V0QmFzZVVybCgpLFxuICAgICAgICAgIGV4cGlyZXNJbjogYWN0dWFsRXhwaXJlc0luLFxuICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRHJ5LXJ1bjogc2hvdyB3aGF0IHdvdWxkIGJlIHN0b3JlZFxuICAgICAgICBpZiAob3B0aW9ucy5kcnlSdW4pIHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICAgIGRyeVJ1bjogdHJ1ZSxcbiAgICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgICBleHBpcmVzSW5EYXlzOiBkYXlzLFxuICAgICAgICAgICAgICBleHBpcmVzQXQsXG4gICAgICAgICAgICAgIHRva2VuTGVuZ3RoOiBhY2Nlc3NUb2tlbi5sZW5ndGgsXG4gICAgICAgICAgICAgIGhhc1JlZnJlc2hUb2tlbjogISFyZWZyZXNoVG9rZW4sXG4gICAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICAgIHByaW50U2VjdGlvbignRHJ5IFJ1biDigJQgTm8gQ2hhbmdlcyBNYWRlJyk7XG4gICAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICAgJ1NlY3JldCBOYW1lJzogc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgJ1JlZ2lvbic6IHJlZ2lvbixcbiAgICAgICAgICAgICAgJ0V4cGlyZXMgSW4nOiBgJHtkYXlzfSBkYXlzYCxcbiAgICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgICAnVG9rZW4gTGVuZ3RoJzogYCR7YWNjZXNzVG9rZW4ubGVuZ3RofSBjaGFyc2AsXG4gICAgICAgICAgICAgICdIYXMgUmVmcmVzaCBUb2tlbic6IHJlZnJlc2hUb2tlbiA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcHJpbnRTdWNjZXNzKCdEcnkgcnVuIGNvbXBsZXRlIOKAlCBubyBzZWNyZXQgd2FzIGNyZWF0ZWQgb3IgdXBkYXRlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdGVwIDI6IFN0b3JlIHRva2VuIGluIFNlY3JldHMgTWFuYWdlclxuICAgICAgICBwcmludFNlY3Rpb24oJ1N0b3JlIFRva2VuJyk7XG5cbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBgUGxhdGZvcm0gSldUIHRva2VuIChyZW5ldyBieSAke2V4cGlyZXNBdH0pYDtcbiAgICAgICAgYXdhaXQgdXBzZXJ0U2VjcmV0KHNlY3JldE5hbWUsIHNlY3JldFZhbHVlLCBkZXNjcmlwdGlvbiwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICBjb25zdCBhcm4gPSBhd2FpdCBnZXRTZWNyZXRBcm4oc2VjcmV0TmFtZSwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICAvLyBPcHRpb25hbGx5IGluc3RhbGwgdGhlIG9uY2UtYS1kYXkgcmVuZXdhbCBzdGFjayBzbyB0aGlzIHRva2VuIG5ldmVyIGxhcHNlcy5cbiAgICAgICAgLy8gT2ZmIGJ5IGRlZmF1bHQg4oCUIG9wdCBpbiB3aXRoIC0tc2NoZWR1bGUgKGUuZy4gZm9yIHRoZSBBV1MgZXZlbnQtaW5nZXN0aW9uXG4gICAgICAgIC8vIGJ1bmRsZSB3aG9zZSBMYW1iZGEgbmVlZHMgYSBub24tZXhwaXJpbmcgdG9rZW4pLlxuICAgICAgICBsZXQgc2NoZWR1bGVFeHByZXNzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChvcHRpb25zLnNjaGVkdWxlKSB7XG4gICAgICAgICAgY29uc3QgZml2ZUZpZWxkQ3JvbiA9IG9wdGlvbnMuY3JvbiB8fCBwcm9jZXNzLmVudi5UT0tFTl9SRU5FV19TQ0hFRFVMRSB8fCBERUZBVUxUX1JFTkVXX0NST047XG4gICAgICAgICAgc2NoZWR1bGVFeHByZXNzaW9uID0gYXdhaXQgZGVwbG95UmVuZXdTY2hlZHVsZSh7XG4gICAgICAgICAgICBwbGF0Zm9ybVVybDogY2xpZW50LmdldEJhc2VVcmwoKSxcbiAgICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgICBkYXlzLFxuICAgICAgICAgICAgZml2ZUZpZWxkQ3JvbixcbiAgICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICAgIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmpzb24pIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgIHNlY3JldEFybjogYXJuLFxuICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgZXhwaXJlc0luRGF5czogZGF5cyxcbiAgICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICAgIHNjaGVkdWxlOiBzY2hlZHVsZUV4cHJlc3Npb24gPz8gbnVsbCxcbiAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignVG9rZW4gU3RvcmVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdTZWNyZXQgTmFtZSc6IHNlY3JldE5hbWUsXG4gICAgICAgICAgICAnU2VjcmV0IEFSTic6IGFybixcbiAgICAgICAgICAgICdSZWdpb24nOiByZWdpb24sXG4gICAgICAgICAgICAnRXhwaXJlcyBJbic6IGAke2RheXN9IGRheXNgLFxuICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgJ0F1dG8tUmVuZXcnOiBzY2hlZHVsZUV4cHJlc3Npb24gPyBg4pyTICR7c2NoZWR1bGVFeHByZXNzaW9ufWAgOiAnb2ZmIChwYXNzIC0tc2NoZWR1bGUgdG8gZW5hYmxlKScsXG4gICAgICAgICAgICAnU3RhdHVzJzogJ+KckyBTdG9yZWQnLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U3VjY2VzcygnVG9rZW4gc3RvcmVkLiBUbyB1c2Ugd2l0aCBzeW50aC9kZXBsb3k6Jyk7XG4gICAgICAgICAgcHJpbnRJbmZvKGAgIGV4cG9ydCBQTEFURk9STV9TRUNSRVRfTkFNRT0ke3NlY3JldE5hbWV9YCk7XG4gICAgICAgICAgcHJpbnRJbmZvKCcgIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgc3ludGggLS1pZCA8cGlwZWxpbmUtaWQ+IC0tc3RvcmUtdG9rZW5zJyk7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIGlmIChzY2hlZHVsZUV4cHJlc3Npb24pIHtcbiAgICAgICAgICAgIHByaW50SW5mbyhgQXV0by1yZW5ld2FsIGlzIGFjdGl2ZSAoJHtzY2hlZHVsZUV4cHJlc3Npb259KTsgdGhlIHNlY3JldCByZWZyZXNoZXMgYmVmb3JlICR7ZXhwaXJlc0F0fS5gKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJpbnRJbmZvKGBSZW5ldyBiZWZvcmUgJHtleHBpcmVzQXR9IHdpdGg6IHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzICR7ZGF5c31gKTtcbiAgICAgICAgICAgIHByaW50SW5mbygnICAob3IgcGFzcyAtLXNjaGVkdWxlIHRvIGluc3RhbGwgYSBkYWlseSBhdXRvLXJlbmV3YWwgc3RhY2spJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdzdG9yZS10b2tlbicsXG4gICAgICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgICAgIHNlY3JldE5hbWU6IHByb2Nlc3MuZW52LlBMQVRGT1JNX1NFQ1JFVF9OQU1FIHx8ICcoZGVyaXZlZCBmcm9tIHRva2VuKScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG59XG4iXX0=
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `synth` command with the CLI program.
4
+ *
5
+ * Runs CDK synthesis using the boilerplate app. Pipeline config is resolved from:
6
+ * 1. --id flag or PIPELINE_ID env var → fetches config from platform API
7
+ * 2. PIPELINE_PROPS env var (pre-encoded, from deploy command)
8
+ *
9
+ * Authentication methods (in priority order):
10
+ * - PLATFORM_TOKEN env var
11
+ * - --store-tokens → fetch from AWS Secrets Manager
12
+ *
13
+ * @example
14
+ * ```bash
15
+ * pipeline-manager pipeline synth --id <pipeline-id> --no-verify-ssl
16
+ * pipeline-manager pipeline synth --id <pipeline-id> --store-tokens
17
+ * pipeline-manager pipeline synth --quiet --no-notices # CodePipeline (uses env vars)
18
+ * ```
19
+ */
20
+ export declare function synth(program: Command): void;
21
+ //# sourceMappingURL=synth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synth.d.ts","sourceRoot":"","sources":["../../src/commands/synth.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsCpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsG5C"}
@@ -0,0 +1,158 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { Command } from 'commander';
6
+ import { assertShellSafe } from '../config/cli.constants.js';
7
+ import { auditLog } from '../utils/audit-log.js';
8
+ import { executeCdkShellCommand, resolveBoilerplatePath } from '../utils/cdk-utils.js';
9
+ import { createAuthenticatedClientAsync, printCommandHeader, printSslWarning, withProfileOption, withRegionOption, withSslOptions } from '../utils/command-utils.js';
10
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
11
+ import { printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
12
+ import { fetchPipelineProps, printResolvedOrExit } from '../utils/pipeline-config.js';
13
+ import { relaxTlsForCli } from '../utils/tls.js';
14
+ // ESM has no __dirname; derive it from this module's URL.
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ /**
17
+ * Fetch pipeline config and set PIPELINE_PROPS env var for the boilerplate app.
18
+ * Uses createAuthenticatedClientAsync which supports all three auth methods.
19
+ */
20
+ async function fetchPipelineConfig(pipelineId, options) {
21
+ const client = await createAuthenticatedClientAsync(options);
22
+ const { propsWithIds, baseUrl } = await fetchPipelineProps(client, pipelineId);
23
+ process.env.PIPELINE_PROPS = Buffer.from(JSON.stringify(propsWithIds)).toString('base64');
24
+ // Propagate the resolved platform base URL into the boilerplate synth (which
25
+ // inherits process.env). The synth uses it for serverConfig.platformUrl (the
26
+ // PluginLookup Lambda endpoint) and as the loadRegistryConfig pull-host
27
+ // fallback. Without this, a URL configured via ~/.pipeline-manager/config.yml
28
+ // is invisible to the synth subprocess (it reads only the env).
29
+ if (baseUrl) {
30
+ process.env.PLATFORM_BASE_URL = baseUrl;
31
+ }
32
+ printSuccess('Pipeline configuration loaded');
33
+ }
34
+ /**
35
+ * Registers the `synth` command with the CLI program.
36
+ *
37
+ * Runs CDK synthesis using the boilerplate app. Pipeline config is resolved from:
38
+ * 1. --id flag or PIPELINE_ID env var → fetches config from platform API
39
+ * 2. PIPELINE_PROPS env var (pre-encoded, from deploy command)
40
+ *
41
+ * Authentication methods (in priority order):
42
+ * - PLATFORM_TOKEN env var
43
+ * - --store-tokens → fetch from AWS Secrets Manager
44
+ *
45
+ * @example
46
+ * ```bash
47
+ * pipeline-manager pipeline synth --id <pipeline-id> --no-verify-ssl
48
+ * pipeline-manager pipeline synth --id <pipeline-id> --store-tokens
49
+ * pipeline-manager pipeline synth --quiet --no-notices # CodePipeline (uses env vars)
50
+ * ```
51
+ */
52
+ export function synth(program) {
53
+ withSslOptions(withRegionOption(withProfileOption(program
54
+ .command('synth')
55
+ .description('Run CDK synthesis using pipeline configuration')
56
+ .option('-i, --id <id>', 'Pipeline ID (or set PIPELINE_ID env var)')
57
+ .option('--store-tokens', 'Authenticate using token from AWS Secrets Manager (requires PLATFORM_SECRET_NAME env var)', false)
58
+ .option('--output <dir>', 'CDK output directory', 'cdk.out')))
59
+ .option('--quiet', 'Suppress CDK output', false)
60
+ .option('--no-notices', 'Suppress CDK notices')
61
+ .option('--verbose', 'Show verbose CDK output', false)
62
+ .option('--json', 'Output result as JSON', false))
63
+ .option('--show-resolved', 'Print the resolved pipeline config (with {{ ... }} templates expanded) and exit without running CDK', false)
64
+ .action(async (options) => {
65
+ const executionId = printCommandHeader('CDK Synthesis', undefined, { quiet: options.json });
66
+ try {
67
+ const pipelineId = options.id || process.env.PIPELINE_ID;
68
+ // --show-resolved: preview templates and exit
69
+ if (options.showResolved) {
70
+ await showResolvedPipeline(pipelineId, options);
71
+ return;
72
+ }
73
+ auditLog('synth', { executionId, pipelineId, output: options.output, profile: options.profile });
74
+ printSslWarning(options.verifySsl);
75
+ // Propagate to process.env so CDK constructs (Lambda, CodeBuild) inherit it,
76
+ // but refuse in production (see relaxTlsForCli) — the flag disables cert
77
+ // validation for ALL outbound TLS, including the AWS SDK.
78
+ relaxTlsForCli(options.verifySsl, printWarning);
79
+ // Fetch pipeline config if ID is available and PIPELINE_PROPS not already set
80
+ if (pipelineId && !process.env.PIPELINE_PROPS) {
81
+ printInfo('Fetching pipeline configuration', { id: pipelineId });
82
+ await fetchPipelineConfig(pipelineId, options);
83
+ }
84
+ else if (!pipelineId && !process.env.PIPELINE_PROPS) {
85
+ printWarning('No pipeline ID or PIPELINE_PROPS set');
86
+ throw new Error('Pipeline ID is required. Use --id <id> or set PIPELINE_ID env var.');
87
+ }
88
+ // Local-tool prerequisites (cdk + esbuild/pnpm) are verified up front by
89
+ // the CLI's preAction hook, so by here they're guaranteed present.
90
+ // Build cdk synth command
91
+ if (options.output)
92
+ assertShellSafe(options.output, 'output');
93
+ if (options.profile)
94
+ assertShellSafe(options.profile, 'profile');
95
+ const boilerplatePath = resolveBoilerplatePath(__dirname);
96
+ const parts = [
97
+ 'cdk synth',
98
+ `--app="node ${boilerplatePath}"`,
99
+ `--output=${options.output}`,
100
+ ];
101
+ if (options.profile)
102
+ parts.push(`--profile=${options.profile}`);
103
+ if (options.quiet)
104
+ parts.push('--quiet');
105
+ if (options.notices === false)
106
+ parts.push('--no-notices');
107
+ if (options.verbose)
108
+ parts.push('--verbose');
109
+ const command = parts.join(' ');
110
+ printInfo('Executing', { command: (command.split('--app')[0] ?? '').trim() + ' ...' });
111
+ console.log('');
112
+ const result = executeCdkShellCommand(command, {
113
+ showOutput: !options.quiet,
114
+ });
115
+ console.log('');
116
+ printSection('Synthesis Complete');
117
+ if (result.success) {
118
+ if (options.json) {
119
+ console.log(JSON.stringify({
120
+ success: true,
121
+ executionId,
122
+ duration: result.duration,
123
+ output: options.output,
124
+ }, null, 2));
125
+ }
126
+ else {
127
+ printKeyValue({
128
+ 'Execution ID': executionId,
129
+ 'Duration': `${result.duration}ms`,
130
+ 'Output': options.output,
131
+ 'Status': '✓ Success',
132
+ });
133
+ }
134
+ }
135
+ }
136
+ catch (error) {
137
+ handleError(error, ERROR_CODES.API_REQUEST, {
138
+ debug: program.opts().debug,
139
+ exit: true,
140
+ context: { command: 'synth', executionId, pipelineId: options.id },
141
+ });
142
+ }
143
+ });
144
+ }
145
+ /**
146
+ * Fetch the pipeline by ID, apply pass-1 self-referencing template
147
+ * resolution, and print it to stdout. Used by `synth --show-resolved`
148
+ * and `deploy --show-resolved` to preview substitution before running CDK.
149
+ */
150
+ async function showResolvedPipeline(pipelineId, options) {
151
+ if (!pipelineId) {
152
+ throw new Error('--show-resolved requires --id or PIPELINE_ID env var');
153
+ }
154
+ const client = await createAuthenticatedClientAsync(options);
155
+ const { propsWithIds } = await fetchPipelineProps(client, pipelineId);
156
+ await printResolvedOrExit(propsWithIds);
157
+ }
158
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ludGguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3ludGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZGLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckssT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUVqRCwwREFBMEQ7QUFDMUQsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBRTFEOzs7R0FHRztBQUNILEtBQUssVUFBVSxtQkFBbUIsQ0FDaEMsVUFBa0IsRUFDbEIsT0FBMEY7SUFFMUYsTUFBTSxN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QUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxFQUFFLEVBQUU7YUFDbkUsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsb0JBQW9CLENBQ2pDLFVBQThCLEVBQzlCLE9BQTBGO0lBRTFGLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sOEJBQThCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0QsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sa0JBQWtCLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RFLE1BQU0sbUJBQW1CLENBQUMsWUFBWSxDQUFDLENBQUM7QUFDMUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBkaXJuYW1lIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IGFzc2VydFNoZWxsU2FmZSB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGF1ZGl0TG9nIH0gZnJvbSAnLi4vdXRpbHMvYXVkaXQtbG9nLmpzJztcbmltcG9ydCB7IGV4ZWN1dGVDZGtTaGVsbENvbW1hbmQsIHJlc29sdmVCb2lsZXJwbGF0ZVBhdGggfSBmcm9tICcuLi91dGlscy9jZGstdXRpbHMuanMnO1xuaW1wb3J0IHsgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudEFzeW5jLCBwcmludENvbW1hbmRIZWFkZXIsIHByaW50U3NsV2FybmluZywgd2l0aFByb2ZpbGVPcHRpb24sIHdpdGhSZWdpb25PcHRpb24sIHdpdGhTc2xPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyBFUlJPUl9DT0RFUywgaGFuZGxlRXJyb3IgfSBmcm9tICcuLi91dGlscy9lcnJvci1oYW5kbGVyLmpzJztcbmltcG9ydCB7IHByaW50SW5mbywgcHJpbnRLZXlWYWx1ZSwgcHJpbnRTZWN0aW9uLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBmZXRjaFBpcGVsaW5lUHJvcHMsIHByaW50UmVzb2x2ZWRPckV4aXQgfSBmcm9tICcuLi91dGlscy9waXBlbGluZS1jb25maWcuanMnO1xuaW1wb3J0IHsgcmVsYXhUbHNGb3JDbGkgfSBmcm9tICcuLi91dGlscy90bHMuanMnO1xuXG4vLyBFU00gaGFzIG5vIF9fZGlybmFtZTsgZGVyaXZlIGl0IGZyb20gdGhpcyBtb2R1bGUncyBVUkwuXG5jb25zdCBfX2Rpcm5hbWUgPSBkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5cbi8qKlxuICogRmV0Y2ggcGlwZWxpbmUgY29uZmlnIGFuZCBzZXQgUElQRUxJTkVfUFJPUFMgZW52IHZhciBmb3IgdGhlIGJvaWxlcnBsYXRlIGFwcC5cbiAqIFVzZXMgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudEFzeW5jIHdoaWNoIHN1cHBvcnRzIGFsbCB0aHJlZSBhdXRoIG1ldGhvZHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZldGNoUGlwZWxpbmVDb25maWcoXG4gIHBpcGVsaW5lSWQ6IHN0cmluZyxcbiAgb3B0aW9uczogeyBzdG9yZVRva2Vucz86IGJvb2xlYW47IHZlcmlmeVNzbD86IGJvb2xlYW47IHJlZ2lvbj86IHN0cmluZzsgcHJvZmlsZT86IHN0cmluZyB9LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNsaWVudCA9IGF3YWl0IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYyhvcHRpb25zKTtcbiAgY29uc3QgeyBwcm9wc1dpdGhJZHMsIGJhc2VVcmwgfSA9IGF3YWl0IGZldGNoUGlwZWxpbmVQcm9wcyhjbGllbnQsIHBpcGVsaW5lSWQpO1xuXG4gIHByb2Nlc3MuZW52LlBJUEVMSU5FX1BST1BTID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkocHJvcHNXaXRoSWRzKSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gIC8vIFByb3BhZ2F0ZSB0aGUgcmVzb2x2ZWQgcGxhdGZvcm0gYmFzZSBVUkwgaW50byB0aGUgYm9pbGVycGxhdGUgc3ludGggKHdoaWNoXG4gIC8vIGluaGVyaXRzIHByb2Nlc3MuZW52KS4gVGhlIHN5bnRoIHVzZXMgaXQgZm9yIHNlcnZlckNvbmZpZy5wbGF0Zm9ybVVybCAodGhlXG4gIC8vIFBsdWdpbkxvb2t1cCBMYW1iZGEgZW5kcG9pbnQpIGFuZCBhcyB0aGUgbG9hZFJlZ2lzdHJ5Q29uZmlnIHB1bGwtaG9zdFxuICAvLyBmYWxsYmFjay4gV2l0aG91dCB0aGlzLCBhIFVSTCBjb25maWd1cmVkIHZpYSB+Ly5waXBlbGluZS1tYW5hZ2VyL2NvbmZpZy55bWxcbiAgLy8gaXMgaW52aXNpYmxlIHRvIHRoZSBzeW50aCBzdWJwcm9jZXNzIChpdCByZWFkcyBvbmx5IHRoZSBlbnYpLlxuICBpZiAoYmFzZVVybCkge1xuICAgIHByb2Nlc3MuZW52LlBMQVRGT1JNX0JBU0VfVVJMID0gYmFzZVVybDtcbiAgfVxuXG4gIHByaW50U3VjY2VzcygnUGlwZWxpbmUgY29uZmlndXJhdGlvbiBsb2FkZWQnKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBzeW50aGAgY29tbWFuZCB3aXRoIHRoZSBDTEkgcHJvZ3JhbS5cbiAqXG4gKiBSdW5zIENESyBzeW50aGVzaXMgdXNpbmcgdGhlIGJvaWxlcnBsYXRlIGFwcC4gUGlwZWxpbmUgY29uZmlnIGlzIHJlc29sdmVkIGZyb206XG4gKiAxLiAtLWlkIGZsYWcgb3IgUElQRUxJTkVfSUQgZW52IHZhciDihpIgZmV0Y2hlcyBjb25maWcgZnJvbSBwbGF0Zm9ybSBBUElcbiAqIDIuIFBJUEVMSU5FX1BST1BTIGVudiB2YXIgKHByZS1lbmNvZGVkLCBmcm9tIGRlcGxveSBjb21tYW5kKVxuICpcbiAqIEF1dGhlbnRpY2F0aW9uIG1ldGhvZHMgKGluIHByaW9yaXR5IG9yZGVyKTpcbiAqIC0gUExBVEZPUk1fVE9LRU4gZW52IHZhclxuICogLSAtLXN0b3JlLXRva2VucyDihpIgZmV0Y2ggZnJvbSBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgc3ludGggLS1pZCA8cGlwZWxpbmUtaWQ+IC0tbm8tdmVyaWZ5LXNzbFxuICogcGlwZWxpbmUtbWFuYWdlciBwaXBlbGluZSBzeW50aCAtLWlkIDxwaXBlbGluZS1pZD4gLS1zdG9yZS10b2tlbnNcbiAqIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgc3ludGggLS1xdWlldCAtLW5vLW5vdGljZXMgICAgICAgICAgIyBDb2RlUGlwZWxpbmUgKHVzZXMgZW52IHZhcnMpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN5bnRoKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgd2l0aFJlZ2lvbk9wdGlvbihcbiAgICAgIHdpdGhQcm9maWxlT3B0aW9uKHByb2dyYW1cbiAgICAgICAgLmNvbW1hbmQoJ3N5bnRoJylcbiAgICAgICAgLmRlc2NyaXB0aW9uKCdSdW4gQ0RLIHN5bnRoZXNpcyB1c2luZyBwaXBlbGluZSBjb25maWd1cmF0aW9uJylcbiAgICAgICAgLm9wdGlvbignLWksIC0taWQgPGlkPicsICdQaXBlbGluZSBJRCAob3Igc2V0IFBJUEVMSU5FX0lEIGVudiB2YXIpJylcbiAgICAgICAgLm9wdGlvbignLS1zdG9yZS10b2tlbnMnLCAnQXV0aGVudGljYXRlIHVzaW5nIHRva2VuIGZyb20gQVdTIFNlY3JldHMgTWFuYWdlciAocmVxdWlyZXMgUExBVEZPUk1fU0VDUkVUX05BTUUgZW52IHZhciknLCBmYWxzZSlcbiAgICAgICAgLm9wdGlvbignLS1vdXRwdXQgPGRpcj4nLCAnQ0RLIG91dHB1dCBkaXJlY3RvcnknLCAnY2RrLm91dCcpKSxcbiAgICApXG4gICAgICAub3B0aW9uKCctLXF1aWV0JywgJ1N1cHByZXNzIENESyBvdXRwdXQnLCBmYWxzZSlcbiAgICAgIC5vcHRpb24oJy0tbm8tbm90aWNlcycsICdTdXBwcmVzcyBDREsgbm90aWNlcycpXG4gICAgICAub3B0aW9uKCctLXZlcmJvc2UnLCAnU2hvdyB2ZXJib3NlIENESyBvdXRwdXQnLCBmYWxzZSlcbiAgICAgIC5vcHRpb24oJy0tanNvbicsICdPdXRwdXQgcmVzdWx0IGFzIEpTT04nLCBmYWxzZSksXG4gIClcbiAgICAub3B0aW9uKCctLXNob3ctcmVzb2x2ZWQnLCAnUHJpbnQgdGhlIHJlc29sdmVkIHBpcGVsaW5lIGNvbmZpZyAod2l0aCB7eyAuLi4gfX0gdGVtcGxhdGVzIGV4cGFuZGVkKSBhbmQgZXhpdCB3aXRob3V0IHJ1bm5pbmcgQ0RLJywgZmFsc2UpXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ0NESyBTeW50aGVzaXMnLCB1bmRlZmluZWQsIHsgcXVpZXQ6IG9wdGlvbnMuanNvbiB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGlwZWxpbmVJZCA9IG9wdGlvbnMuaWQgfHwgcHJvY2Vzcy5lbnYuUElQRUxJTkVfSUQ7XG5cbiAgICAgICAgLy8gLS1zaG93LXJlc29sdmVkOiBwcmV2aWV3IHRlbXBsYXRlcyBhbmQgZXhpdFxuICAgICAgICBpZiAob3B0aW9ucy5zaG93UmVzb2x2ZWQpIHtcbiAgICAgICAgICBhd2FpdCBzaG93UmVzb2x2ZWRQaXBlbGluZShwaXBlbGluZUlkLCBvcHRpb25zKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBhdWRpdExvZygnc3ludGgnLCB7IGV4ZWN1dGlvbklkLCBwaXBlbGluZUlkLCBvdXRwdXQ6IG9wdGlvbnMub3V0cHV0LCBwcm9maWxlOiBvcHRpb25zLnByb2ZpbGUgfSk7XG4gICAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgICAgLy8gUHJvcGFnYXRlIHRvIHByb2Nlc3MuZW52IHNvIENESyBjb25zdHJ1Y3RzIChMYW1iZGEsIENvZGVCdWlsZCkgaW5oZXJpdCBpdCxcbiAgICAgICAgLy8gYnV0IHJlZnVzZSBpbiBwcm9kdWN0aW9uIChzZWUgcmVsYXhUbHNGb3JDbGkpIOKAlCB0aGUgZmxhZyBkaXNhYmxlcyBjZXJ0XG4gICAgICAgIC8vIHZhbGlkYXRpb24gZm9yIEFMTCBvdXRib3VuZCBUTFMsIGluY2x1ZGluZyB0aGUgQVdTIFNESy5cbiAgICAgICAgcmVsYXhUbHNGb3JDbGkob3B0aW9ucy52ZXJpZnlTc2wsIHByaW50V2FybmluZyk7XG5cbiAgICAgICAgLy8gRmV0Y2ggcGlwZWxpbmUgY29uZmlnIGlmIElEIGlzIGF2YWlsYWJsZSBhbmQgUElQRUxJTkVfUFJPUFMgbm90IGFscmVhZHkgc2V0XG4gICAgICAgIGlmIChwaXBlbGluZUlkICYmICFwcm9jZXNzLmVudi5QSVBFTElORV9QUk9QUykge1xuICAgICAgICAgIHByaW50SW5mbygnRmV0Y2hpbmcgcGlwZWxpbmUgY29uZmlndXJhdGlvbicsIHsgaWQ6IHBpcGVsaW5lSWQgfSk7XG4gICAgICAgICAgYXdhaXQgZmV0Y2hQaXBlbGluZUNvbmZpZyhwaXBlbGluZUlkLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIGlmICghcGlwZWxpbmVJZCAmJiAhcHJvY2Vzcy5lbnYuUElQRUxJTkVfUFJPUFMpIHtcbiAgICAgICAgICBwcmludFdhcm5pbmcoJ05vIHBpcGVsaW5lIElEIG9yIFBJUEVMSU5FX1BST1BTIHNldCcpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGlwZWxpbmUgSUQgaXMgcmVxdWlyZWQuIFVzZSAtLWlkIDxpZD4gb3Igc2V0IFBJUEVMSU5FX0lEIGVudiB2YXIuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMb2NhbC10b29sIHByZXJlcXVpc2l0ZXMgKGNkayArIGVzYnVpbGQvcG5wbSkgYXJlIHZlcmlmaWVkIHVwIGZyb250IGJ5XG4gICAgICAgIC8vIHRoZSBDTEkncyBwcmVBY3Rpb24gaG9vaywgc28gYnkgaGVyZSB0aGV5J3JlIGd1YXJhbnRlZWQgcHJlc2VudC5cblxuICAgICAgICAvLyBCdWlsZCBjZGsgc3ludGggY29tbWFuZFxuICAgICAgICBpZiAob3B0aW9ucy5vdXRwdXQpIGFzc2VydFNoZWxsU2FmZShvcHRpb25zLm91dHB1dCwgJ291dHB1dCcpO1xuICAgICAgICBpZiAob3B0aW9ucy5wcm9maWxlKSBhc3NlcnRTaGVsbFNhZmUob3B0aW9ucy5wcm9maWxlLCAncHJvZmlsZScpO1xuXG4gICAgICAgIGNvbnN0IGJvaWxlcnBsYXRlUGF0aCA9IHJlc29sdmVCb2lsZXJwbGF0ZVBhdGgoX19kaXJuYW1lKTtcbiAgICAgICAgY29uc3QgcGFydHMgPSBbXG4gICAgICAgICAgJ2NkayBzeW50aCcsXG4gICAgICAgICAgYC0tYXBwPVwibm9kZSAke2JvaWxlcnBsYXRlUGF0aH1cImAsXG4gICAgICAgICAgYC0tb3V0cHV0PSR7b3B0aW9ucy5vdXRwdXR9YCxcbiAgICAgICAgXTtcblxuICAgICAgICBpZiAob3B0aW9ucy5wcm9maWxlKSBwYXJ0cy5wdXNoKGAtLXByb2ZpbGU9JHtvcHRpb25zLnByb2ZpbGV9YCk7XG4gICAgICAgIGlmIChvcHRpb25zLnF1aWV0KSBwYXJ0cy5wdXNoKCctLXF1aWV0Jyk7XG4gICAgICAgIGlmIChvcHRpb25zLm5vdGljZXMgPT09IGZhbHNlKSBwYXJ0cy5wdXNoKCctLW5vLW5vdGljZXMnKTtcbiAgICAgICAgaWYgKG9wdGlvbnMudmVyYm9zZSkgcGFydHMucHVzaCgnLS12ZXJib3NlJyk7XG5cbiAgICAgICAgY29uc3QgY29tbWFuZCA9IHBhcnRzLmpvaW4oJyAnKTtcblxuICAgICAgICBwcmludEluZm8oJ0V4ZWN1dGluZycsIHsgY29tbWFuZDogKGNvbW1hbmQuc3BsaXQoJy0tYXBwJylbMF0gPz8gJycpLnRyaW0oKSArICcgLi4uJyB9KTtcbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGV4ZWN1dGVDZGtTaGVsbENvbW1hbmQoY29tbWFuZCwge1xuICAgICAgICAgIHNob3dPdXRwdXQ6ICFvcHRpb25zLnF1aWV0LFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U2VjdGlvbignU3ludGhlc2lzIENvbXBsZXRlJyk7XG5cbiAgICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgICAgaWYgKG9wdGlvbnMuanNvbikge1xuICAgICAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgICAgICAgZHVyYXRpb246IHJlc3VsdC5kdXJhdGlvbixcbiAgICAgICAgICAgICAgb3V0cHV0OiBvcHRpb25zLm91dHB1dCxcbiAgICAgICAgICAgIH0sIG51bGwsIDIpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgICAgICdFeGVjdXRpb24gSUQnOiBleGVjdXRpb25JZCxcbiAgICAgICAgICAgICAgJ0R1cmF0aW9uJzogYCR7cmVzdWx0LmR1cmF0aW9ufW1zYCxcbiAgICAgICAgICAgICAgJ091dHB1dCc6IG9wdGlvbnMub3V0cHV0LFxuICAgICAgICAgICAgICAnU3RhdHVzJzogJ+KckyBTdWNjZXNzJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuQVBJX1JFUVVFU1QsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgICAgICBjb250ZXh0OiB7IGNvbW1hbmQ6ICdzeW50aCcsIGV4ZWN1dGlvbklkLCBwaXBlbGluZUlkOiBvcHRpb25zLmlkIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIEZldGNoIHRoZSBwaXBlbGluZSBieSBJRCwgYXBwbHkgcGFzcy0xIHNlbGYtcmVmZXJlbmNpbmcgdGVtcGxhdGVcbiAqIHJlc29sdXRpb24sIGFuZCBwcmludCBpdCB0byBzdGRvdXQuIFVzZWQgYnkgYHN5bnRoIC0tc2hvdy1yZXNvbHZlZGBcbiAqIGFuZCBgZGVwbG95IC0tc2hvdy1yZXNvbHZlZGAgdG8gcHJldmlldyBzdWJzdGl0dXRpb24gYmVmb3JlIHJ1bm5pbmcgQ0RLLlxuICovXG5hc3luYyBmdW5jdGlvbiBzaG93UmVzb2x2ZWRQaXBlbGluZShcbiAgcGlwZWxpbmVJZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBvcHRpb25zOiB7IHByb2ZpbGU/OiBzdHJpbmc7IHJlZ2lvbj86IHN0cmluZzsgc3RvcmVUb2tlbnM/OiBib29sZWFuOyB2ZXJpZnlTc2w/OiBib29sZWFuIH0sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFwaXBlbGluZUlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCctLXNob3ctcmVzb2x2ZWQgcmVxdWlyZXMgLS1pZCBvciBQSVBFTElORV9JRCBlbnYgdmFyJyk7XG4gIH1cbiAgY29uc3QgY2xpZW50ID0gYXdhaXQgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudEFzeW5jKG9wdGlvbnMpO1xuICBjb25zdCB7IHByb3BzV2l0aElkcyB9ID0gYXdhaXQgZmV0Y2hQaXBlbGluZVByb3BzKGNsaWVudCwgcGlwZWxpbmVJZCk7XG4gIGF3YWl0IHByaW50UmVzb2x2ZWRPckV4aXQocHJvcHNXaXRoSWRzKTtcbn1cbiJdfQ==
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `upload-plugin` command with the CLI program.
4
+ *
5
+ * Validates a local plugin ZIP file (size, extension, readability),
6
+ * builds a multipart form, and uploads it to the platform API.
7
+ * Plugin name and version can be auto-detected from the package
8
+ * or overridden via CLI flags.
9
+ *
10
+ * @param program - The root Commander program instance to attach the command to.
11
+ *
12
+ * @example
13
+ * ```bash
14
+ * cli plugin upload --file plugin.zip --organization acme
15
+ * cli plugin upload --file plugin.zip --organization acme --public
16
+ * cli plugin upload --file plugin.zip --organization acme --name my-plugin --version 1.0.0
17
+ * cli plugin upload --file plugin.zip --organization acme --no-verify-ssl
18
+ * ```
19
+ */
20
+ export declare function uploadPlugin(program: Command): void;
21
+ //# sourceMappingURL=upload-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-plugin.d.ts","sourceRoot":"","sources":["../../src/commands/upload-plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoRnD"}