@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,274 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import * as fs from 'fs';
4
+ import { Command } from 'commander';
5
+ import ora from 'ora';
6
+ import pico from 'picocolors';
7
+ import {} from '../types/index.js';
8
+ import { createAuthenticatedClient, printCommandHeader, printExecutionSummary, printSslWarning, withSslOptions } from '../utils/command-utils.js';
9
+ import { ERROR_CODES, handleError, ValidationError } from '../utils/error-handler.js';
10
+ import { outputData, printError, printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
11
+ import { extractListResponse, extractSingleResponse } from '../utils/response-utils.js';
12
+ const { bold, cyan, dim, green } = pico;
13
+ /**
14
+ * Accumulate a repeatable `--input KEY=VALUE` flag. This only collects — it does
15
+ * NOT validate, because Commander runs `parseArg` before the action callback, so
16
+ * a throw here would escape the action's `handleError` and surface as an
17
+ * unhandled stack trace with the wrong exit code instead of a clean validation
18
+ * failure. Parsing happens in {@link parseInputPairs}, inside the action.
19
+ */
20
+ function collectInput(pair, previous) {
21
+ return [...previous, pair];
22
+ }
23
+ /**
24
+ * Split collected `KEY=VALUE` pairs into a map. Values stay strings; the platform
25
+ * coerces each to its declared input type (and rejects what doesn't fit), so the
26
+ * CLI does not guess types locally. Only the FIRST `=` splits, so a value may
27
+ * itself contain `=`.
28
+ */
29
+ function parseInputPairs(pairs) {
30
+ const out = {};
31
+ for (const pair of pairs) {
32
+ const eq = pair.indexOf('=');
33
+ if (eq < 1) {
34
+ throw new ValidationError(`Invalid --input "${pair}" — expected KEY=VALUE`, 'input', pair, 'key=value', 'e.g. --input orgId=1234abcd-...');
35
+ }
36
+ out[pair.slice(0, eq)] = pair.slice(eq + 1);
37
+ }
38
+ return out;
39
+ }
40
+ /** Read and parse `--inputs-file`, which holds a flat `{ name: value }` object. */
41
+ function readInputsFile(file) {
42
+ if (!fs.existsSync(file)) {
43
+ throw new ValidationError(`Inputs file not found: ${file}`, 'inputs-file', file);
44
+ }
45
+ let parsed;
46
+ try {
47
+ parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
48
+ }
49
+ catch (error) {
50
+ throw new ValidationError(`Inputs file is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, 'inputs-file', file);
51
+ }
52
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
53
+ throw new ValidationError('Inputs file must contain a JSON object of { "inputName": value }', 'inputs-file', file);
54
+ }
55
+ for (const [k, v] of Object.entries(parsed)) {
56
+ const t = typeof v;
57
+ if (t !== 'string' && t !== 'number' && t !== 'boolean') {
58
+ throw new ValidationError(`Input "${k}" must be a string, number, or boolean (got ${t})`, 'inputs-file', file);
59
+ }
60
+ }
61
+ return parsed;
62
+ }
63
+ /**
64
+ * Resolve a template `name` to its id through the catalog list endpoint. The list
65
+ * is visibility-scoped server-side, so this only ever sees templates the caller
66
+ * may read. Matching is exact on `name` — the `name` query param is a filter, not
67
+ * a unique lookup, so a fuzzy backend match must not silently instantiate a
68
+ * DIFFERENT template than the one asked for.
69
+ */
70
+ async function resolveTemplateByName(client, name) {
71
+ const url = client.getConfig().api.pipelineTemplateUrl;
72
+ const response = await client.get(url, { name, limit: 100 });
73
+ const { items } = extractListResponse(response, 'templates');
74
+ const exact = items.filter((t) => t.name === name);
75
+ if (exact.length === 0) {
76
+ throw new ValidationError(`No pipeline template named "${name}" is visible to you.`, 'name', name, undefined, items.length > 0
77
+ ? `Did you mean one of: ${items.slice(0, 10).map((t) => t.name).join(', ')}`
78
+ : 'Load the sample catalog with deploy/bin/load-templates.sh, or pass --id.');
79
+ }
80
+ // A name is unique per org, but the visible set spans your org + parent + the
81
+ // system catalog, so the same name can legitimately appear more than once.
82
+ // Refuse to guess — the wrong pick would silently synth someone else's body.
83
+ if (exact.length > 1) {
84
+ throw new ValidationError(`"${name}" matches ${exact.length} visible templates — pass --id to choose one.`, 'name', name, undefined, `ids: ${exact.map((t) => t.id).join(', ')}`);
85
+ }
86
+ return exact[0];
87
+ }
88
+ /**
89
+ * Registers the `template instantiate` command.
90
+ *
91
+ * Renders a golden-path template into a concrete pipeline `props` document by
92
+ * supplying its declared inputs. It **creates nothing** — the rendered props are
93
+ * written to a file (or stdout) and go through the normal `pipeline create` path,
94
+ * where compliance and quota still apply.
95
+ *
96
+ * @example
97
+ * ```bash
98
+ * pipeline-manager template instantiate --name react-javascript \
99
+ * --project react --organization AcmeCorp \
100
+ * --input orgId=1234abcd-... --output pipeline-props.json
101
+ *
102
+ * pipeline-manager pipeline create --file pipeline-props.json --deploy
103
+ * ```
104
+ */
105
+ export function instantiateTemplate(program) {
106
+ withSslOptions(program
107
+ .command('instantiate')
108
+ .description('Render a pipeline template into concrete pipeline props (creates nothing)')
109
+ .option('-n, --name <name>', 'Template name (resolved against the catalog you can see)')
110
+ .option('-i, --id <id>', 'Template ID (skips the name lookup)')
111
+ .requiredOption('-p, --project <project>', 'Project name for the pipeline this template will produce')
112
+ .requiredOption('-o, --organization <organization>', 'Organization name for the pipeline')
113
+ .option('--pipeline-name <name>', 'Pipeline name (defaults to <organization>-<project>-pipeline at synth)')
114
+ .option('--input <key=value>', 'Template input, repeatable (e.g. --input orgId=1234abcd-...)', collectInput, [])
115
+ .option('--inputs-file <file>', 'JSON file of { "inputName": value } — merged UNDER any --input flags')
116
+ .option('--output <file>', 'Write the rendered props to a file (default: stdout)')
117
+ .option('-f, --format <format>', 'Output format (json, yaml)', 'json'))
118
+ .option('--json', 'Print ONLY the rendered props as JSON (for piping); implies no decorative output', false)
119
+ .action(async (options) => {
120
+ // With --json (or props headed for stdout in any format) the payload IS the
121
+ // output, so the banner must not land on stdout ahead of it and break piping.
122
+ const toStdout = !options.output;
123
+ const quiet = options.json || toStdout;
124
+ const executionId = printCommandHeader('Instantiate Template', undefined, { quiet });
125
+ try {
126
+ if (!options.name && !options.id) {
127
+ throw new ValidationError('Provide --name or --id to select a template', 'name');
128
+ }
129
+ if (options.name && options.id) {
130
+ throw new ValidationError('Pass either --name or --id, not both', 'name');
131
+ }
132
+ // Only the round-trippable formats: the rendered props exist to be fed
133
+ // back to `pipeline create --file`, and `table`/`csv` would flatten them
134
+ // into something that can no longer be parsed as props.
135
+ if (!['json', 'yaml'].includes(options.format)) {
136
+ throw new ValidationError(`Unsupported --format "${options.format}" — rendered props must stay parseable`, 'format', options.format, 'json|yaml');
137
+ }
138
+ if (!quiet)
139
+ printSslWarning(options.verifySsl);
140
+ // --input flags win over --inputs-file so a file can hold shared defaults
141
+ // that a single flag overrides on the command line.
142
+ const inputs = {
143
+ ...(options.inputsFile ? readInputsFile(options.inputsFile) : {}),
144
+ ...parseInputPairs(options.input),
145
+ };
146
+ if (!quiet) {
147
+ printInfo('Request parameters', {
148
+ template: options.name ?? options.id,
149
+ project: options.project,
150
+ organization: options.organization,
151
+ pipelineName: options.pipelineName ?? '(default)',
152
+ inputs: Object.keys(inputs).length > 0 ? Object.keys(inputs).join(', ') : '(none)',
153
+ output: options.output ?? '(stdout)',
154
+ });
155
+ console.log('');
156
+ printSection('Rendering Template');
157
+ }
158
+ const client = createAuthenticatedClient(options);
159
+ const templateUrl = client.getConfig().api.pipelineTemplateUrl;
160
+ const startTime = Date.now();
161
+ const spinner = quiet ? null : ora('Resolving template...').start();
162
+ let templateId;
163
+ let templateName;
164
+ try {
165
+ if (options.id) {
166
+ templateId = options.id;
167
+ }
168
+ else {
169
+ const template = await resolveTemplateByName(client, options.name);
170
+ templateId = template.id;
171
+ templateName = template.name;
172
+ }
173
+ spinner?.succeed(`Template resolved${templateName ? ` (${templateName})` : ''}`);
174
+ }
175
+ catch (error) {
176
+ spinner?.fail('Template resolution failed');
177
+ throw error;
178
+ }
179
+ const body = {
180
+ project: options.project,
181
+ organization: options.organization,
182
+ ...(options.pipelineName ? { pipelineName: options.pipelineName } : {}),
183
+ ...(Object.keys(inputs).length > 0 ? { inputs } : {}),
184
+ };
185
+ const renderSpinner = quiet ? null : ora('Instantiating...').start();
186
+ let rendered;
187
+ try {
188
+ const response = await client.post(`${templateUrl}/${encodeURIComponent(templateId)}/instantiate`, body);
189
+ // `props` is the identifier key: the envelope's data IS { props, ... }.
190
+ rendered = extractSingleResponse(response, 'template', 'props');
191
+ renderSpinner?.succeed('Template instantiated');
192
+ }
193
+ catch (error) {
194
+ renderSpinner?.fail('Instantiate failed');
195
+ throw error;
196
+ }
197
+ const duration = Date.now() - startTime;
198
+ if (!rendered?.props) {
199
+ printError('No props returned from API', { templateId });
200
+ throw new Error(`Template ${templateId} rendered no props`);
201
+ }
202
+ const props = rendered.props;
203
+ // A leftover `{{ ... }}` in a *self-scope* field means an input was never
204
+ // supplied and the placeholder would fail opaquely at synth. `pipeline.*`
205
+ // tokens are expected here — they resolve at synth, not at instantiate.
206
+ const unresolved = unresolvedSelfVars(props);
207
+ if (unresolved.length > 0) {
208
+ printWarning('Rendered props still contain unresolved placeholders', {
209
+ vars: unresolved.join(', '),
210
+ hint: 'Supply them with --input <name>=<value>',
211
+ });
212
+ }
213
+ if (!quiet) {
214
+ console.log('');
215
+ printSection('Rendered Props');
216
+ printKeyValue({
217
+ 'Template': green(bold(templateName ?? templateId)),
218
+ 'Project': props.project,
219
+ 'Organization': props.organization,
220
+ 'Pipeline Name': props.pipelineName ?? dim('(default at synth)'),
221
+ 'Vars': Object.keys(props.vars ?? {}).join(', ') || dim('(none)'),
222
+ 'Stages': String(Array.isArray(props.stages) ? props.stages.length : 0),
223
+ });
224
+ printExecutionSummary(executionId, duration);
225
+ }
226
+ outputData(props, {
227
+ format: options.json ? 'json' : options.format,
228
+ file: options.output,
229
+ silent: quiet,
230
+ });
231
+ if (options.output && !quiet) {
232
+ console.log('');
233
+ printSuccess('Pipeline props saved', { path: options.output });
234
+ printInfo('Next step', {
235
+ command: `pipeline-manager pipeline create --file ${options.output} --deploy`,
236
+ });
237
+ console.log(dim(` ${cyan('Tip:')} instantiate only renders — nothing exists on the platform yet.`));
238
+ }
239
+ }
240
+ catch (error) {
241
+ handleError(error, ERROR_CODES.API_REQUEST, {
242
+ debug: program.opts().debug,
243
+ exit: true,
244
+ context: { command: 'instantiate-template', executionId, template: options.name ?? options.id },
245
+ });
246
+ }
247
+ });
248
+ }
249
+ /**
250
+ * Names of `{{ vars.X }}` placeholders still present in the rendered props' own
251
+ * self-scope fields (`project`, `metadata.*`, `vars.*`) — i.e. inputs the caller
252
+ * never supplied. `{{ pipeline.* }}` tokens are deliberately ignored: those are
253
+ * synth-time references (e.g. the GitHub source token) and are SUPPOSED to
254
+ * survive instantiation.
255
+ */
256
+ function unresolvedSelfVars(props) {
257
+ const found = new Set();
258
+ const scan = (value) => {
259
+ if (typeof value === 'string') {
260
+ for (const m of value.matchAll(/\{\{\s*vars\.([A-Za-z_][A-Za-z0-9_]*)/g))
261
+ found.add(m[1]);
262
+ return;
263
+ }
264
+ if (Array.isArray(value))
265
+ return value.forEach(scan);
266
+ if (value && typeof value === 'object')
267
+ return Object.values(value).forEach(scan);
268
+ };
269
+ scan(props.project);
270
+ scan(props.metadata);
271
+ scan(props.vars);
272
+ return [...found];
273
+ }
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFudGlhdGUtdGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvaW5zdGFudGlhdGUtdGVtcGxhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQztBQUN0QixPQUFPLElBQUksTUFBTSxZQUFZLENBQUM7QUFDOUIsT0FBTyxFQUtOLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGtCQUFrQixFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNsSixPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN0RixPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdEksT0FBTyxFQUFFLG1CQUFtQixFQUFFLHFCQUFxQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFeEYsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQztBQUV4Qzs7Ozs7O0dBTUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxJQUFZLEVBQUUsUUFBa0I7SUFDcEQsT0FBTyxDQUFDLEdBQUcsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzdCLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsZUFBZSxDQUFDLEtBQWU7SUFDdEMsTUFBTSxHQUFHLEdBQTJCLEVBQUUsQ0FB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QUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUU7YUFDaEcsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsa0JBQWtCLENBQUMsS0FBb0I7SUFDOUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNoQyxNQUFNLElBQUksR0FBRyxDQUFDLEtBQWMsRUFBUSxFQUFFO1FBQ3BDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDOUIsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLHdDQUF3QyxDQUFDO2dCQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUM7WUFDM0YsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JELElBQUksS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7WUFBRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BGLENBQUMsQ0FBQztJQUNGLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNyQixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pCLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ3BCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgb3JhIGZyb20gJ29yYSc7XG5pbXBvcnQgcGljbyBmcm9tICdwaWNvY29sb3JzJztcbmltcG9ydCB7XG4gIHR5cGUgSW5zdGFudGlhdGVUZW1wbGF0ZVJlcXVlc3QsXG4gIHR5cGUgSW5zdGFudGlhdGVUZW1wbGF0ZVJlc3BvbnNlLFxuICB0eXBlIFBpcGVsaW5lVGVtcGxhdGUsXG4gIHR5cGUgUGlwZWxpbmVQcm9wcyxcbn0gZnJvbSAnLi4vdHlwZXMvaW5kZXguanMnO1xuaW1wb3J0IHsgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudCwgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludEV4ZWN1dGlvblN1bW1hcnksIHByaW50U3NsV2FybmluZywgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBvdXRwdXREYXRhLCBwcmludEVycm9yLCBwcmludEluZm8sIHByaW50S2V5VmFsdWUsIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzLCBwcmludFdhcm5pbmcgfSBmcm9tICcuLi91dGlscy9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHsgZXh0cmFjdExpc3RSZXNwb25zZSwgZXh0cmFjdFNpbmdsZVJlc3BvbnNlIH0gZnJvbSAnLi4vdXRpbHMvcmVzcG9uc2UtdXRpbHMuanMnO1xuXG5jb25zdCB7IGJvbGQsIGN5YW4sIGRpbSwgZ3JlZW4gfSA9IHBpY287XG5cbi8qKlxuICogQWNjdW11bGF0ZSBhIHJlcGVhdGFibGUgYC0taW5wdXQgS0VZPVZBTFVFYCBmbGFnLiBUaGlzIG9ubHkgY29sbGVjdHMg4oCUIGl0IGRvZXNcbiAqIE5PVCB2YWxpZGF0ZSwgYmVjYXVzZSBDb21tYW5kZXIgcnVucyBgcGFyc2VBcmdgIGJlZm9yZSB0aGUgYWN0aW9uIGNhbGxiYWNrLCBzb1xuICogYSB0aHJvdyBoZXJlIHdvdWxkIGVzY2FwZSB0aGUgYWN0aW9uJ3MgYGhhbmRsZUVycm9yYCBhbmQgc3VyZmFjZSBhcyBhblxuICogdW5oYW5kbGVkIHN0YWNrIHRyYWNlIHdpdGggdGhlIHdyb25nIGV4aXQgY29kZSBpbnN0ZWFkIG9mIGEgY2xlYW4gdmFsaWRhdGlvblxuICogZmFpbHVyZS4gUGFyc2luZyBoYXBwZW5zIGluIHtAbGluayBwYXJzZUlucHV0UGFpcnN9LCBpbnNpZGUgdGhlIGFjdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29sbGVjdElucHV0KHBhaXI6IHN0cmluZywgcHJldmlvdXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICByZXR1cm4gWy4uLnByZXZpb3VzLCBwYWlyXTtcbn1cblxuLyoqXG4gKiBTcGxpdCBjb2xsZWN0ZWQgYEtFWT1WQUxVRWAgcGFpcnMgaW50byBhIG1hcC4gVmFsdWVzIHN0YXkgc3RyaW5nczsgdGhlIHBsYXRmb3JtXG4gKiBjb2VyY2VzIGVhY2ggdG8gaXRzIGRlY2xhcmVkIGlucHV0IHR5cGUgKGFuZCByZWplY3RzIHdoYXQgZG9lc24ndCBmaXQpLCBzbyB0aGVcbiAqIENMSSBkb2VzIG5vdCBndWVzcyB0eXBlcyBsb2NhbGx5LiBPbmx5IHRoZSBGSVJTVCBgPWAgc3BsaXRzLCBzbyBhIHZhbHVlIG1heVxuICogaXRzZWxmIGNvbnRhaW4gYD1gLlxuICovXG5mdW5jdGlvbiBwYXJzZUlucHV0UGFpcnMocGFpcnM6IHN0cmluZ1tdKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHtcbiAgICBjb25zdCBlcSA9IHBhaXIuaW5kZXhPZignPScpO1xuICAgIGlmIChlcSA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIC0taW5wdXQgXCIke3BhaXJ9XCIg4oCUIGV4cGVjdGVkIEtFWT1WQUxVRWAsXG4gICAgICAgICdpbnB1dCcsIHBhaXIsICdrZXk9dmFsdWUnLCAnZS5nLiAtLWlucHV0IG9yZ0lkPTEyMzRhYmNkLS4uLicsXG4gICAgICApO1xuICAgIH1cbiAgICBvdXRbcGFpci5zbGljZSgwLCBlcSldID0gcGFpci5zbGljZShlcSArIDEpO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBSZWFkIGFuZCBwYXJzZSBgLS1pbnB1dHMtZmlsZWAsIHdoaWNoIGhvbGRzIGEgZmxhdCBgeyBuYW1lOiB2YWx1ZSB9YCBvYmplY3QuICovXG5mdW5jdGlvbiByZWFkSW5wdXRzRmlsZShmaWxlOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPiB7XG4gIGlmICghZnMuZXhpc3RzU3luYyhmaWxlKSkge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYElucHV0cyBmaWxlIG5vdCBmb3VuZDogJHtmaWxlfWAsICdpbnB1dHMtZmlsZScsIGZpbGUpO1xuICB9XG4gIGxldCBwYXJzZWQ6IHVua25vd247XG4gIHRyeSB7XG4gICAgcGFyc2VkID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoZmlsZSwgJ3V0Zi04JykpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBgSW5wdXRzIGZpbGUgaXMgbm90IHZhbGlkIEpTT046ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWAsXG4gICAgICAnaW5wdXRzLWZpbGUnLCBmaWxlLFxuICAgICk7XG4gIH1cbiAgaWYgKHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IHBhcnNlZCA9PT0gbnVsbCB8fCBBcnJheS5pc0FycmF5KHBhcnNlZCkpIHtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdJbnB1dHMgZmlsZSBtdXN0IGNvbnRhaW4gYSBKU09OIG9iamVjdCBvZiB7IFwiaW5wdXROYW1lXCI6IHZhbHVlIH0nLCAnaW5wdXRzLWZpbGUnLCBmaWxlKTtcbiAgfVxuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhwYXJzZWQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pKSB7XG4gICAgY29uc3QgdCA9IHR5cGVvZiB2O1xuICAgIGlmICh0ICE9PSAnc3RyaW5nJyAmJiB0ICE9PSAnbnVtYmVyJyAmJiB0ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYElucHV0IFwiJHtrfVwiIG11c3QgYmUgYSBzdHJpbmcsIG51bWJlciwgb3IgYm9vbGVhbiAoZ290ICR7dH0pYCwgJ2lucHV0cy1maWxlJywgZmlsZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBwYXJzZWQgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj47XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIHRlbXBsYXRlIGBuYW1lYCB0byBpdHMgaWQgdGhyb3VnaCB0aGUgY2F0YWxvZyBsaXN0IGVuZHBvaW50LiBUaGUgbGlzdFxuICogaXMgdmlzaWJpbGl0eS1zY29wZWQgc2VydmVyLXNpZGUsIHNvIHRoaXMgb25seSBldmVyIHNlZXMgdGVtcGxhdGVzIHRoZSBjYWxsZXJcbiAqIG1heSByZWFkLiBNYXRjaGluZyBpcyBleGFjdCBvbiBgbmFtZWAg4oCUIHRoZSBgbmFtZWAgcXVlcnkgcGFyYW0gaXMgYSBmaWx0ZXIsIG5vdFxuICogYSB1bmlxdWUgbG9va3VwLCBzbyBhIGZ1enp5IGJhY2tlbmQgbWF0Y2ggbXVzdCBub3Qgc2lsZW50bHkgaW5zdGFudGlhdGUgYVxuICogRElGRkVSRU5UIHRlbXBsYXRlIHRoYW4gdGhlIG9uZSBhc2tlZCBmb3IuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVUZW1wbGF0ZUJ5TmFtZShcbiAgY2xpZW50OiBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50PixcbiAgbmFtZTogc3RyaW5nLFxuKTogUHJvbWlzZTxQaXBlbGluZVRlbXBsYXRlPiB7XG4gIGNvbnN0IHVybCA9IGNsaWVudC5nZXRDb25maWcoKS5hcGkucGlwZWxpbmVUZW1wbGF0ZVVybDtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZ2V0KHVybCwgeyBuYW1lLCBsaW1pdDogMTAwIH0pO1xuICBjb25zdCB7IGl0ZW1zIH0gPSBleHRyYWN0TGlzdFJlc3BvbnNlPFBpcGVsaW5lVGVtcGxhdGU+KHJlc3BvbnNlLCAndGVtcGxhdGVzJyk7XG5cbiAgY29uc3QgZXhhY3QgPSBpdGVtcy5maWx0ZXIoKHQpID0+IHQubmFtZSA9PT0gbmFtZSk7XG4gIGlmIChleGFjdC5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgYE5vIHBpcGVsaW5lIHRlbXBsYXRlIG5hbWVkIFwiJHtuYW1lfVwiIGlzIHZpc2libGUgdG8geW91LmAsXG4gICAgICAnbmFtZScsIG5hbWUsIHVuZGVmaW5lZCxcbiAgICAgIGl0ZW1zLmxlbmd0aCA+IDBcbiAgICAgICAgPyBgRGlkIHlvdSBtZWFuIG9uZSBvZjogJHtpdGVtcy5zbGljZSgwLCAxMCkubWFwKCh0KSA9PiB0Lm5hbWUpLmpvaW4oJywgJyl9YFxuICAgICAgICA6ICdMb2FkIHRoZSBzYW1wbGUgY2F0YWxvZyB3aXRoIGRlcGxveS9iaW4vbG9hZC10ZW1wbGF0ZXMuc2gsIG9yIHBhc3MgLS1pZC4nLFxuICAgICk7XG4gIH1cbiAgLy8gQSBuYW1lIGlzIHVuaXF1ZSBwZXIgb3JnLCBidXQgdGhlIHZpc2libGUgc2V0IHNwYW5zIHlvdXIgb3JnICsgcGFyZW50ICsgdGhlXG4gIC8vIHN5c3RlbSBjYXRhbG9nLCBzbyB0aGUgc2FtZSBuYW1lIGNhbiBsZWdpdGltYXRlbHkgYXBwZWFyIG1vcmUgdGhhbiBvbmNlLlxuICAvLyBSZWZ1c2UgdG8gZ3Vlc3Mg4oCUIHRoZSB3cm9uZyBwaWNrIHdvdWxkIHNpbGVudGx5IHN5bnRoIHNvbWVvbmUgZWxzZSdzIGJvZHkuXG4gIGlmIChleGFjdC5sZW5ndGggPiAxKSB7XG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIGBcIiR7bmFtZX1cIiBtYXRjaGVzICR7ZXhhY3QubGVuZ3RofSB2aXNpYmxlIHRlbXBsYXRlcyDigJQgcGFzcyAtLWlkIHRvIGNob29zZSBvbmUuYCxcbiAgICAgICduYW1lJywgbmFtZSwgdW5kZWZpbmVkLFxuICAgICAgYGlkczogJHtleGFjdC5tYXAoKHQpID0+IHQuaWQpLmpvaW4oJywgJyl9YCxcbiAgICApO1xuICB9XG4gIHJldHVybiBleGFjdFswXSE7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgdGVtcGxhdGUgaW5zdGFudGlhdGVgIGNvbW1hbmQuXG4gKlxuICogUmVuZGVycyBhIGdvbGRlbi1wYXRoIHRlbXBsYXRlIGludG8gYSBjb25jcmV0ZSBwaXBlbGluZSBgcHJvcHNgIGRvY3VtZW50IGJ5XG4gKiBzdXBwbHlpbmcgaXRzIGRlY2xhcmVkIGlucHV0cy4gSXQgKipjcmVhdGVzIG5vdGhpbmcqKiDigJQgdGhlIHJlbmRlcmVkIHByb3BzIGFyZVxuICogd3JpdHRlbiB0byBhIGZpbGUgKG9yIHN0ZG91dCkgYW5kIGdvIHRocm91Z2ggdGhlIG5vcm1hbCBgcGlwZWxpbmUgY3JlYXRlYCBwYXRoLFxuICogd2hlcmUgY29tcGxpYW5jZSBhbmQgcXVvdGEgc3RpbGwgYXBwbHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgdGVtcGxhdGUgaW5zdGFudGlhdGUgLS1uYW1lIHJlYWN0LWphdmFzY3JpcHQgXFxcbiAqICAgLS1wcm9qZWN0IHJlYWN0IC0tb3JnYW5pemF0aW9uIEFjbWVDb3JwIFxcXG4gKiAgIC0taW5wdXQgb3JnSWQ9MTIzNGFiY2QtLi4uIC0tb3V0cHV0IHBpcGVsaW5lLXByb3BzLmpzb25cbiAqXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHBpcGVsaW5lIGNyZWF0ZSAtLWZpbGUgcGlwZWxpbmUtcHJvcHMuanNvbiAtLWRlcGxveVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnN0YW50aWF0ZVRlbXBsYXRlKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgcHJvZ3JhbVxuICAgICAgLmNvbW1hbmQoJ2luc3RhbnRpYXRlJylcbiAgICAgIC5kZXNjcmlwdGlvbignUmVuZGVyIGEgcGlwZWxpbmUgdGVtcGxhdGUgaW50byBjb25jcmV0ZSBwaXBlbGluZSBwcm9wcyAoY3JlYXRlcyBub3RoaW5nKScpXG4gICAgICAub3B0aW9uKCctbiwgLS1uYW1lIDxuYW1lPicsICdUZW1wbGF0ZSBuYW1lIChyZXNvbHZlZCBhZ2FpbnN0IHRoZSBjYXRhbG9nIHlvdSBjYW4gc2VlKScpXG4gICAgICAub3B0aW9uKCctaSwgLS1pZCA8aWQ+JywgJ1RlbXBsYXRlIElEIChza2lwcyB0aGUgbmFtZSBsb29rdXApJylcbiAgICAgIC5yZXF1aXJlZE9wdGlvbignLXAsIC0tcHJvamVjdCA8cHJvamVjdD4nLCAnUHJvamVjdCBuYW1lIGZvciB0aGUgcGlwZWxpbmUgdGhpcyB0ZW1wbGF0ZSB3aWxsIHByb2R1Y2UnKVxuICAgICAgLnJlcXVpcmVkT3B0aW9uKCctbywgLS1vcmdhbml6YXRpb24gPG9yZ2FuaXphdGlvbj4nLCAnT3JnYW5pemF0aW9uIG5hbWUgZm9yIHRoZSBwaXBlbGluZScpXG4gICAgICAub3B0aW9uKCctLXBpcGVsaW5lLW5hbWUgPG5hbWU+JywgJ1BpcGVsaW5lIG5hbWUgKGRlZmF1bHRzIHRvIDxvcmdhbml6YXRpb24+LTxwcm9qZWN0Pi1waXBlbGluZSBhdCBzeW50aCknKVxuICAgICAgLm9wdGlvbignLS1pbnB1dCA8a2V5PXZhbHVlPicsICdUZW1wbGF0ZSBpbnB1dCwgcmVwZWF0YWJsZSAoZS5nLiAtLWlucHV0IG9yZ0lkPTEyMzRhYmNkLS4uLiknLCBjb2xsZWN0SW5wdXQsIFtdKVxuICAgICAgLm9wdGlvbignLS1pbnB1dHMtZmlsZSA8ZmlsZT4nLCAnSlNPTiBmaWxlIG9mIHsgXCJpbnB1dE5hbWVcIjogdmFsdWUgfSDigJQgbWVyZ2VkIFVOREVSIGFueSAtLWlucHV0IGZsYWdzJylcbiAgICAgIC5vcHRpb24oJy0tb3V0cHV0IDxmaWxlPicsICdXcml0ZSB0aGUgcmVuZGVyZWQgcHJvcHMgdG8gYSBmaWxlIChkZWZhdWx0OiBzdGRvdXQpJylcbiAgICAgIC5vcHRpb24oJy1mLCAtLWZvcm1hdCA8Zm9ybWF0PicsICdPdXRwdXQgZm9ybWF0IChqc29uLCB5YW1sKScsICdqc29uJyksXG4gIClcbiAgICAub3B0aW9uKCctLWpzb24nLCAnUHJpbnQgT05MWSB0aGUgcmVuZGVyZWQgcHJvcHMgYXMgSlNPTiAoZm9yIHBpcGluZyk7IGltcGxpZXMgbm8gZGVjb3JhdGl2ZSBvdXRwdXQnLCBmYWxzZSlcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICAvLyBXaXRoIC0tanNvbiAob3IgcHJvcHMgaGVhZGVkIGZvciBzdGRvdXQgaW4gYW55IGZvcm1hdCkgdGhlIHBheWxvYWQgSVMgdGhlXG4gICAgICAvLyBvdXRwdXQsIHNvIHRoZSBiYW5uZXIgbXVzdCBub3QgbGFuZCBvbiBzdGRvdXQgYWhlYWQgb2YgaXQgYW5kIGJyZWFrIHBpcGluZy5cbiAgICAgIGNvbnN0IHRvU3Rkb3V0ID0gIW9wdGlvbnMub3V0cHV0O1xuICAgICAgY29uc3QgcXVpZXQgPSBvcHRpb25zLmpzb24gfHwgdG9TdGRvdXQ7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignSW5zdGFudGlhdGUgVGVtcGxhdGUnLCB1bmRlZmluZWQsIHsgcXVpZXQgfSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghb3B0aW9ucy5uYW1lICYmICFvcHRpb25zLmlkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUHJvdmlkZSAtLW5hbWUgb3IgLS1pZCB0byBzZWxlY3QgYSB0ZW1wbGF0ZScsICduYW1lJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMubmFtZSAmJiBvcHRpb25zLmlkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUGFzcyBlaXRoZXIgLS1uYW1lIG9yIC0taWQsIG5vdCBib3RoJywgJ25hbWUnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPbmx5IHRoZSByb3VuZC10cmlwcGFibGUgZm9ybWF0czogdGhlIHJlbmRlcmVkIHByb3BzIGV4aXN0IHRvIGJlIGZlZFxuICAgICAgICAvLyBiYWNrIHRvIGBwaXBlbGluZSBjcmVhdGUgLS1maWxlYCwgYW5kIGB0YWJsZWAvYGNzdmAgd291bGQgZmxhdHRlbiB0aGVtXG4gICAgICAgIC8vIGludG8gc29tZXRoaW5nIHRoYXQgY2FuIG5vIGxvbmdlciBiZSBwYXJzZWQgYXMgcHJvcHMuXG4gICAgICAgIGlmICghWydqc29uJywgJ3lhbWwnXS5pbmNsdWRlcyhvcHRpb25zLmZvcm1hdCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAgICAgYFVuc3VwcG9ydGVkIC0tZm9ybWF0IFwiJHtvcHRpb25zLmZvcm1hdH1cIiDigJQgcmVuZGVyZWQgcHJvcHMgbXVzdCBzdGF5IHBhcnNlYWJsZWAsXG4gICAgICAgICAgICAnZm9ybWF0Jywgb3B0aW9ucy5mb3JtYXQsICdqc29ufHlhbWwnLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFxdWlldCkgcHJpbnRTc2xXYXJuaW5nKG9wdGlvbnMudmVyaWZ5U3NsKTtcblxuICAgICAgICAvLyAtLWlucHV0IGZsYWdzIHdpbiBvdmVyIC0taW5wdXRzLWZpbGUgc28gYSBmaWxlIGNhbiBob2xkIHNoYXJlZCBkZWZhdWx0c1xuICAgICAgICAvLyB0aGF0IGEgc2luZ2xlIGZsYWcgb3ZlcnJpZGVzIG9uIHRoZSBjb21tYW5kIGxpbmUuXG4gICAgICAgIGNvbnN0IGlucHV0czogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj4gPSB7XG4gICAgICAgICAgLi4uKG9wdGlvbnMuaW5wdXRzRmlsZSA/IHJlYWRJbnB1dHNGaWxlKG9wdGlvbnMuaW5wdXRzRmlsZSkgOiB7fSksXG4gICAgICAgICAgLi4ucGFyc2VJbnB1dFBhaXJzKG9wdGlvbnMuaW5wdXQgYXMgc3RyaW5nW10pLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICghcXVpZXQpIHtcbiAgICAgICAgICBwcmludEluZm8oJ1JlcXVlc3QgcGFyYW1ldGVycycsIHtcbiAgICAgICAgICAgIHRlbXBsYXRlOiBvcHRpb25zLm5hbWUgPz8gb3B0aW9ucy5pZCxcbiAgICAgICAgICAgIHByb2plY3Q6IG9wdGlvbnMucHJvamVjdCxcbiAgICAgICAgICAgIG9yZ2FuaXphdGlvbjogb3B0aW9ucy5vcmdhbml6YXRpb24sXG4gICAgICAgICAgICBwaXBlbGluZU5hbWU6IG9wdGlvbnMucGlwZWxpbmVOYW1lID8/ICcoZGVmYXVsdCknLFxuICAgICAgICAgICAgaW5wdXRzOiBPYmplY3Qua2V5cyhpbnB1dHMpLmxlbmd0aCA+IDAgPyBPYmplY3Qua2V5cyhpbnB1dHMpLmpvaW4oJywgJykgOiAnKG5vbmUpJyxcbiAgICAgICAgICAgIG91dHB1dDogb3B0aW9ucy5vdXRwdXQgPz8gJyhzdGRvdXQpJyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRTZWN0aW9uKCdSZW5kZXJpbmcgVGVtcGxhdGUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnQob3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlVXJsID0gY2xpZW50LmdldENvbmZpZygpLmFwaS5waXBlbGluZVRlbXBsYXRlVXJsO1xuXG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHNwaW5uZXIgPSBxdWlldCA/IG51bGwgOiBvcmEoJ1Jlc29sdmluZyB0ZW1wbGF0ZS4uLicpLnN0YXJ0KCk7XG4gICAgICAgIGxldCB0ZW1wbGF0ZUlkOiBzdHJpbmc7XG4gICAgICAgIGxldCB0ZW1wbGF0ZU5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5pZCkge1xuICAgICAgICAgICAgdGVtcGxhdGVJZCA9IG9wdGlvbnMuaWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHRlbXBsYXRlID0gYXdhaXQgcmVzb2x2ZVRlbXBsYXRlQnlOYW1lKGNsaWVudCwgb3B0aW9ucy5uYW1lKTtcbiAgICAgICAgICAgIHRlbXBsYXRlSWQgPSB0ZW1wbGF0ZS5pZDtcbiAgICAgICAgICAgIHRlbXBsYXRlTmFtZSA9IHRlbXBsYXRlLm5hbWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNwaW5uZXI/LnN1Y2NlZWQoYFRlbXBsYXRlIHJlc29sdmVkJHt0ZW1wbGF0ZU5hbWUgPyBgICgke3RlbXBsYXRlTmFtZX0pYCA6ICcnfWApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHNwaW5uZXI/LmZhaWwoJ1RlbXBsYXRlIHJlc29sdXRpb24gZmFpbGVkJyk7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBib2R5OiBJbnN0YW50aWF0ZVRlbXBsYXRlUmVxdWVzdCA9IHtcbiAgICAgICAgICBwcm9qZWN0OiBvcHRpb25zLnByb2plY3QsXG4gICAgICAgICAgb3JnYW5pemF0aW9uOiBvcHRpb25zLm9yZ2FuaXphdGlvbixcbiAgICAgICAgICAuLi4ob3B0aW9ucy5waXBlbGluZU5hbWUgPyB7IHBpcGVsaW5lTmFtZTogb3B0aW9ucy5waXBlbGluZU5hbWUgfSA6IHt9KSxcbiAgICAgICAgICAuLi4oT2JqZWN0LmtleXMoaW5wdXRzKS5sZW5ndGggPiAwID8geyBpbnB1dHMgfSA6IHt9KSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZW5kZXJTcGlubmVyID0gcXVpZXQgPyBudWxsIDogb3JhKCdJbnN0YW50aWF0aW5nLi4uJykuc3RhcnQoKTtcbiAgICAgICAgbGV0IHJlbmRlcmVkOiBJbnN0YW50aWF0ZVRlbXBsYXRlUmVzcG9uc2UgfCB1bmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdChgJHt0ZW1wbGF0ZVVybH0vJHtlbmNvZGVVUklDb21wb25lbnQodGVtcGxhdGVJZCl9L2luc3RhbnRpYXRlYCwgYm9keSk7XG4gICAgICAgICAgLy8gYHByb3BzYCBpcyB0aGUgaWRlbnRpZmllciBrZXk6IHRoZSBlbnZlbG9wZSdzIGRhdGEgSVMgeyBwcm9wcywgLi4uIH0uXG4gICAgICAgICAgcmVuZGVyZWQgPSBleHRyYWN0U2luZ2xlUmVzcG9uc2U8SW5zdGFudGlhdGVUZW1wbGF0ZVJlc3BvbnNlPihyZXNwb25zZSwgJ3RlbXBsYXRlJywgJ3Byb3BzJyk7XG4gICAgICAgICAgcmVuZGVyU3Bpbm5lcj8uc3VjY2VlZCgnVGVtcGxhdGUgaW5zdGFudGlhdGVkJyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgcmVuZGVyU3Bpbm5lcj8uZmFpbCgnSW5zdGFudGlhdGUgZmFpbGVkJyk7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZHVyYXRpb24gPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xuXG4gICAgICAgIGlmICghcmVuZGVyZWQ/LnByb3BzKSB7XG4gICAgICAgICAgcHJpbnRFcnJvcignTm8gcHJvcHMgcmV0dXJuZWQgZnJvbSBBUEknLCB7IHRlbXBsYXRlSWQgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW1wbGF0ZSAke3RlbXBsYXRlSWR9IHJlbmRlcmVkIG5vIHByb3BzYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcHJvcHMgPSByZW5kZXJlZC5wcm9wcyBhcyBQaXBlbGluZVByb3BzO1xuXG4gICAgICAgIC8vIEEgbGVmdG92ZXIgYHt7IC4uLiB9fWAgaW4gYSAqc2VsZi1zY29wZSogZmllbGQgbWVhbnMgYW4gaW5wdXQgd2FzIG5ldmVyXG4gICAgICAgIC8vIHN1cHBsaWVkIGFuZCB0aGUgcGxhY2Vob2xkZXIgd291bGQgZmFpbCBvcGFxdWVseSBhdCBzeW50aC4gYHBpcGVsaW5lLipgXG4gICAgICAgIC8vIHRva2VucyBhcmUgZXhwZWN0ZWQgaGVyZSDigJQgdGhleSByZXNvbHZlIGF0IHN5bnRoLCBub3QgYXQgaW5zdGFudGlhdGUuXG4gICAgICAgIGNvbnN0IHVucmVzb2x2ZWQgPSB1bnJlc29sdmVkU2VsZlZhcnMocHJvcHMpO1xuICAgICAgICBpZiAodW5yZXNvbHZlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcHJpbnRXYXJuaW5nKCdSZW5kZXJlZCBwcm9wcyBzdGlsbCBjb250YWluIHVucmVzb2x2ZWQgcGxhY2Vob2xkZXJzJywge1xuICAgICAgICAgICAgdmFyczogdW5yZXNvbHZlZC5qb2luKCcsICcpLFxuICAgICAgICAgICAgaGludDogJ1N1cHBseSB0aGVtIHdpdGggLS1pbnB1dCA8bmFtZT49PHZhbHVlPicsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXF1aWV0KSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignUmVuZGVyZWQgUHJvcHMnKTtcbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdUZW1wbGF0ZSc6IGdyZWVuKGJvbGQodGVtcGxhdGVOYW1lID8/IHRlbXBsYXRlSWQpKSxcbiAgICAgICAgICAgICdQcm9qZWN0JzogcHJvcHMucHJvamVjdCBhcyBzdHJpbmcsXG4gICAgICAgICAgICAnT3JnYW5pemF0aW9uJzogcHJvcHMub3JnYW5pemF0aW9uIGFzIHN0cmluZyxcbiAgICAgICAgICAgICdQaXBlbGluZSBOYW1lJzogKHByb3BzLnBpcGVsaW5lTmFtZSBhcyBzdHJpbmcpID8/IGRpbSgnKGRlZmF1bHQgYXQgc3ludGgpJyksXG4gICAgICAgICAgICAnVmFycyc6IE9iamVjdC5rZXlzKChwcm9wcy52YXJzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA/PyB7fSkuam9pbignLCAnKSB8fCBkaW0oJyhub25lKScpLFxuICAgICAgICAgICAgJ1N0YWdlcyc6IFN0cmluZyhBcnJheS5pc0FycmF5KHByb3BzLnN0YWdlcykgPyBwcm9wcy5zdGFnZXMubGVuZ3RoIDogMCksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcHJpbnRFeGVjdXRpb25TdW1tYXJ5KGV4ZWN1dGlvbklkLCBkdXJhdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICBvdXRwdXREYXRhKHByb3BzLCB7XG4gICAgICAgICAgZm9ybWF0OiBvcHRpb25zLmpzb24gPyAnanNvbicgOiBvcHRpb25zLmZvcm1hdCxcbiAgICAgICAgICBmaWxlOiBvcHRpb25zLm91dHB1dCxcbiAgICAgICAgICBzaWxlbnQ6IHF1aWV0LFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAob3B0aW9ucy5vdXRwdXQgJiYgIXF1aWV0KSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U3VjY2VzcygnUGlwZWxpbmUgcHJvcHMgc2F2ZWQnLCB7IHBhdGg6IG9wdGlvbnMub3V0cHV0IH0pO1xuICAgICAgICAgIHByaW50SW5mbygnTmV4dCBzdGVwJywge1xuICAgICAgICAgICAgY29tbWFuZDogYHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgY3JlYXRlIC0tZmlsZSAke29wdGlvbnMub3V0cHV0fSAtLWRlcGxveWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc29sZS5sb2coZGltKGAgICR7Y3lhbignVGlwOicpfSBpbnN0YW50aWF0ZSBvbmx5IHJlbmRlcnMg4oCUIG5vdGhpbmcgZXhpc3RzIG9uIHRoZSBwbGF0Zm9ybSB5ZXQuYCkpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuQVBJX1JFUVVFU1QsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgICAgICBjb250ZXh0OiB7IGNvbW1hbmQ6ICdpbnN0YW50aWF0ZS10ZW1wbGF0ZScsIGV4ZWN1dGlvbklkLCB0ZW1wbGF0ZTogb3B0aW9ucy5uYW1lID8/IG9wdGlvbnMuaWQgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogTmFtZXMgb2YgYHt7IHZhcnMuWCB9fWAgcGxhY2Vob2xkZXJzIHN0aWxsIHByZXNlbnQgaW4gdGhlIHJlbmRlcmVkIHByb3BzJyBvd25cbiAqIHNlbGYtc2NvcGUgZmllbGRzIChgcHJvamVjdGAsIGBtZXRhZGF0YS4qYCwgYHZhcnMuKmApIOKAlCBpLmUuIGlucHV0cyB0aGUgY2FsbGVyXG4gKiBuZXZlciBzdXBwbGllZC4gYHt7IHBpcGVsaW5lLiogfX1gIHRva2VucyBhcmUgZGVsaWJlcmF0ZWx5IGlnbm9yZWQ6IHRob3NlIGFyZVxuICogc3ludGgtdGltZSByZWZlcmVuY2VzIChlLmcuIHRoZSBHaXRIdWIgc291cmNlIHRva2VuKSBhbmQgYXJlIFNVUFBPU0VEIHRvXG4gKiBzdXJ2aXZlIGluc3RhbnRpYXRpb24uXG4gKi9cbmZ1bmN0aW9uIHVucmVzb2x2ZWRTZWxmVmFycyhwcm9wczogUGlwZWxpbmVQcm9wcyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZm91bmQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3Qgc2NhbiA9ICh2YWx1ZTogdW5rbm93bik6IHZvaWQgPT4ge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBmb3IgKGNvbnN0IG0gb2YgdmFsdWUubWF0Y2hBbGwoL1xce1xce1xccyp2YXJzXFwuKFtBLVphLXpfXVtBLVphLXowLTlfXSopL2cpKSBmb3VuZC5hZGQobVsxXSEpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiB2YWx1ZS5mb3JFYWNoKHNjYW4pO1xuICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSByZXR1cm4gT2JqZWN0LnZhbHVlcyh2YWx1ZSkuZm9yRWFjaChzY2FuKTtcbiAgfTtcbiAgc2Nhbihwcm9wcy5wcm9qZWN0KTtcbiAgc2Nhbihwcm9wcy5tZXRhZGF0YSk7XG4gIHNjYW4ocHJvcHMudmFycyk7XG4gIHJldHVybiBbLi4uZm91bmRdO1xufVxuIl19
@@ -0,0 +1,20 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `list-pipelines` command with the CLI program.
4
+ *
5
+ * Queries pipelines with filters for project, organization, name,
6
+ * access modifier, active/default status, plus pagination and sorting.
7
+ *
8
+ * @param program - The root Commander program instance to attach the command to.
9
+ *
10
+ * @example
11
+ * ```bash
12
+ * cli pipeline list
13
+ * cli pipeline list --project my-app --is-active true
14
+ * cli pipeline list --organization my-org
15
+ * cli pipeline list --limit 50 --offset 100 --sort "pipelineName:asc"
16
+ * cli pipeline list --format json --output pipelines.json
17
+ * ```
18
+ */
19
+ export declare function listPipelines(program: Command): void;
20
+ //# sourceMappingURL=list-pipelines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-pipelines.d.ts","sourceRoot":"","sources":["../../src/commands/list-pipelines.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgEpD"}
@@ -0,0 +1,99 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { runListEntity } from './entity-list.js';
5
+ import { validateBoolean } from '../config/cli.constants.js';
6
+ import {} from '../types/index.js';
7
+ import { withSslOptions } from '../utils/command-utils.js';
8
+ import {} from '../utils/list-command-utils.js';
9
+ /**
10
+ * Registers the `list-pipelines` command with the CLI program.
11
+ *
12
+ * Queries pipelines with filters for project, organization, name,
13
+ * access modifier, active/default status, plus pagination and sorting.
14
+ *
15
+ * @param program - The root Commander program instance to attach the command to.
16
+ *
17
+ * @example
18
+ * ```bash
19
+ * cli pipeline list
20
+ * cli pipeline list --project my-app --is-active true
21
+ * cli pipeline list --organization my-org
22
+ * cli pipeline list --limit 50 --offset 100 --sort "pipelineName:asc"
23
+ * cli pipeline list --format json --output pipelines.json
24
+ * ```
25
+ */
26
+ export function listPipelines(program) {
27
+ withSslOptions(program
28
+ .command('list')
29
+ .description('Query pipelines with comprehensive filters')
30
+ // Common filter options
31
+ .option('--id <id>', 'Filter by pipeline ID (can specify multiple with commas)')
32
+ .option('--visibility <rung>', 'Filter by sharing rung (private/org/public)')
33
+ .option('--is-default <boolean>', 'Filter by default status (true/false)')
34
+ .option('--is-active <boolean>', 'Filter by active status (true/false)')
35
+ .option('--limit <number>', 'Maximum number of results (1-1000)', (v) => parseInt(v, 10), 50)
36
+ .option('--offset <number>', 'Number of results to skip', (v) => parseInt(v, 10), 0)
37
+ .option('--sort <sort>', 'Sort format: field:direction (e.g., pipelineName:asc, createdAt:desc)')
38
+ // Pipeline-specific filter options
39
+ .option('--project <project>', 'Filter by exact project name')
40
+ .option('--organization <organization>', 'Filter by exact organization name')
41
+ .option('--pipeline-name <name>', 'Filter by exact pipeline name')
42
+ // Output options
43
+ .option('-f, --format <format>', 'Output format (json, yaml, table, csv)', 'table')
44
+ .option('-o, --output <file>', 'Save output to file')
45
+ .option('--show-props', 'Include pipeline properties in output (json/yaml only)', false))
46
+ .action((options) => runListEntity(program, options, {
47
+ labelPlural: 'Pipelines',
48
+ responseKey: 'pipelines',
49
+ listUrl: (config) => config.api.pipelineListUrl,
50
+ commandName: 'list-pipelines',
51
+ buildFilters: (options, base) => {
52
+ const filters = { ...base };
53
+ if (options.visibility)
54
+ filters.visibility = options.visibility;
55
+ if (options.isDefault !== undefined)
56
+ filters.isDefault = validateBoolean(options.isDefault, 'is-default');
57
+ if (options.project)
58
+ filters.project = options.project;
59
+ if (options.organization)
60
+ filters.organization = options.organization;
61
+ if (options.pipelineName)
62
+ filters.pipelineName = options.pipelineName;
63
+ return filters;
64
+ },
65
+ activeFilters: (filters) => {
66
+ const active = {};
67
+ if (filters.id)
68
+ active.ID = filters.id;
69
+ if (filters.visibility)
70
+ active.Visibility = filters.visibility;
71
+ if (filters.isDefault !== undefined)
72
+ active['Is Default'] = filters.isDefault;
73
+ if (filters.isActive !== undefined)
74
+ active['Is Active'] = filters.isActive;
75
+ if (filters.project)
76
+ active.Project = filters.project;
77
+ if (filters.organization)
78
+ active.Organization = filters.organization;
79
+ if (filters.pipelineName)
80
+ active['Pipeline Name'] = filters.pipelineName;
81
+ return active;
82
+ },
83
+ statistics: (pipelines) => ({
84
+ 'Active Pipelines': `${pipelines.filter(p => p.isActive).length}/${pipelines.length}`,
85
+ 'Default Pipelines': `${pipelines.filter(p => p.isDefault).length}/${pipelines.length}`,
86
+ }),
87
+ rows: (pipelines, options) => options.showProps ? pipelines : pipelines.map(p => ({
88
+ 'ID': p.id,
89
+ 'Project': p.project,
90
+ 'Organization': p.organization,
91
+ 'Name': p.pipelineName || 'N/A',
92
+ 'Visibility': p.visibility || 'private',
93
+ 'Default': p.isDefault ? 'Yes' : 'No',
94
+ 'Active': p.isActive ? 'Yes' : 'No',
95
+ 'Created At': p.createdAt || 'N/A',
96
+ })),
97
+ }));
98
+ }
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC1waXBlbGluZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvbGlzdC1waXBlbGluZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFpQixNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQTJCLE1BQU0sZ0NBQWdDLENBQUM7QUFnQnpFOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUFnQjtJQUM1QyxjQUFjLENBQUMsT0FBTztTQUNuQixPQUFPLENBQUMsTUFBTSxDQUFDO1NBQ2YsV0FBVyxDQUFDLDRDQUE0QyxDQUFDO1FBRTFELHdCQUF3QjtTQUN2QixNQUFNLENBQUMsV0FBVyxFQUFFLDBEQUEwRCxDQUFDO1NBQy9FLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSw2Q0FBNkMsQ0FBQztTQUM1RSxNQUFNLENBQUMsd0JBQXdCLEVBQUUsdUNBQXVDLENBQUM7U0FDekUsTUFBTSxDQUFDLHVCQUF1QixFQUFFLHNDQUFzQyxDQUFDO1NBQ3ZFLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxvQ0FBb0MsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7U0FDNUYsTUFBTSxDQUFDLG1CQUFtQixFQUFFLDJCQUEyQixFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FB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QUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sSUFBSSxTQUFTLENBQUMsTUFBTSxFQUFFO1lBQ3JGLG1CQUFtQixFQUFFLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLE1BQU0sRUFBRTtTQUN4RixDQUFDO1FBQ0YsSUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNoRixJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUU7WUFDVixTQUFTLEVBQUUsQ0FBQyxDQUFDLE9BQU87WUFDcEIsY0FBYyxFQUFFLENBQUMsQ0FBQyxZQUFZO1lBQzlCLE1BQU0sRUFBRSxDQUFDLENBQUMsWUFBWSxJQUFJLEtBQUs7WUFDL0IsWUFBWSxFQUFFLENBQUMsQ0FBQyxVQUFVLElBQUksU0FBUztZQUN2QyxTQUFTLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQ3JDLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDbkMsWUFBWSxFQUFFLENBQUMsQ0FBQyxTQUFTLElBQUksS0FBSztTQUNuQyxDQUFDLENBQUM7S0FDSixDQUFDLENBQUMsQ0FBQztBQUNSLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgeyBydW5MaXN0RW50aXR5IH0gZnJvbSAnLi9lbnRpdHktbGlzdC5qcyc7XG5pbXBvcnQgeyB2YWxpZGF0ZUJvb2xlYW4gfSBmcm9tICcuLi9jb25maWcvY2xpLmNvbnN0YW50cy5qcyc7XG5pbXBvcnQgeyB0eXBlIFBpcGVsaW5lIH0gZnJvbSAnLi4vdHlwZXMvaW5kZXguanMnO1xuaW1wb3J0IHsgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IHR5cGUgQ29tbW9uRmlsdGVyUGFyYW1zIH0gZnJvbSAnLi4vdXRpbHMvbGlzdC1jb21tYW5kLXV0aWxzLmpzJztcblxuLyoqXG4gKiBRdWVyeSBwYXJhbWV0ZXJzIGZvciB0aGUgcGlwZWxpbmUgbGlzdCBBUEkgZW5kcG9pbnQuXG4gKiBDb21iaW5lcyBjb21tb24gZmlsdGVycyAocGFnaW5hdGlvbiwgc29ydCwgYWNjZXNzKSB3aXRoIHBpcGVsaW5lLXNwZWNpZmljIGZpbHRlcnMuXG4gKi9cbmludGVyZmFjZSBQaXBlbGluZUZpbHRlclBhcmFtcyBleHRlbmRzIENvbW1vbkZpbHRlclBhcmFtcyB7XG4gIHZpc2liaWxpdHk/OiBzdHJpbmc7XG4gIGlzRGVmYXVsdD86IGJvb2xlYW47XG5cbiAgLy8gUGlwZWxpbmUtc3BlY2lmaWMgZmlsdGVyc1xuICBwcm9qZWN0Pzogc3RyaW5nO1xuICBvcmdhbml6YXRpb24/OiBzdHJpbmc7XG4gIHBpcGVsaW5lTmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBsaXN0LXBpcGVsaW5lc2AgY29tbWFuZCB3aXRoIHRoZSBDTEkgcHJvZ3JhbS5cbiAqXG4gKiBRdWVyaWVzIHBpcGVsaW5lcyB3aXRoIGZpbHRlcnMgZm9yIHByb2plY3QsIG9yZ2FuaXphdGlvbiwgbmFtZSxcbiAqIGFjY2VzcyBtb2RpZmllciwgYWN0aXZlL2RlZmF1bHQgc3RhdHVzLCBwbHVzIHBhZ2luYXRpb24gYW5kIHNvcnRpbmcuXG4gKlxuICogQHBhcmFtIHByb2dyYW0gLSBUaGUgcm9vdCBDb21tYW5kZXIgcHJvZ3JhbSBpbnN0YW5jZSB0byBhdHRhY2ggdGhlIGNvbW1hbmQgdG8uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIGNsaSBwaXBlbGluZSBsaXN0XG4gKiBjbGkgcGlwZWxpbmUgbGlzdCAtLXByb2plY3QgbXktYXBwIC0taXMtYWN0aXZlIHRydWVcbiAqIGNsaSBwaXBlbGluZSBsaXN0IC0tb3JnYW5pemF0aW9uIG15LW9yZ1xuICogY2xpIHBpcGVsaW5lIGxpc3QgLS1saW1pdCA1MCAtLW9mZnNldCAxMDAgLS1zb3J0IFwicGlwZWxpbmVOYW1lOmFzY1wiXG4gKiBjbGkgcGlwZWxpbmUgbGlzdCAtLWZvcm1hdCBqc29uIC0tb3V0cHV0IHBpcGVsaW5lcy5qc29uXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RQaXBlbGluZXMocHJvZ3JhbTogQ29tbWFuZCk6IHZvaWQge1xuICB3aXRoU3NsT3B0aW9ucyhwcm9ncmFtXG4gICAgLmNvbW1hbmQoJ2xpc3QnKVxuICAgIC5kZXNjcmlwdGlvbignUXVlcnkgcGlwZWxpbmVzIHdpdGggY29tcHJlaGVuc2l2ZSBmaWx0ZXJzJylcblxuICAgIC8vIENvbW1vbiBmaWx0ZXIgb3B0aW9uc1xuICAgIC5vcHRpb24oJy0taWQgPGlkPicsICdGaWx0ZXIgYnkgcGlwZWxpbmUgSUQgKGNhbiBzcGVjaWZ5IG11bHRpcGxlIHdpdGggY29tbWFzKScpXG4gICAgLm9wdGlvbignLS12aXNpYmlsaXR5IDxydW5nPicsICdGaWx0ZXIgYnkgc2hhcmluZyBydW5nIChwcml2YXRlL29yZy9wdWJsaWMpJylcbiAgICAub3B0aW9uKCctLWlzLWRlZmF1bHQgPGJvb2xlYW4+JywgJ0ZpbHRlciBieSBkZWZhdWx0IHN0YXR1cyAodHJ1ZS9mYWxzZSknKVxuICAgIC5vcHRpb24oJy0taXMtYWN0aXZlIDxib29sZWFuPicsICdGaWx0ZXIgYnkgYWN0aXZlIHN0YXR1cyAodHJ1ZS9mYWxzZSknKVxuICAgIC5vcHRpb24oJy0tbGltaXQgPG51bWJlcj4nLCAnTWF4aW11bSBudW1iZXIgb2YgcmVzdWx0cyAoMS0xMDAwKScsICh2KSA9PiBwYXJzZUludCh2LCAxMCksIDUwKVxuICAgIC5vcHRpb24oJy0tb2Zmc2V0IDxudW1iZXI+JywgJ051bWJlciBvZiByZXN1bHRzIHRvIHNraXAnLCAodikgPT4gcGFyc2VJbnQodiwgMTApLCAwKVxuICAgIC5vcHRpb24oJy0tc29ydCA8c29ydD4nLCAnU29ydCBmb3JtYXQ6IGZpZWxkOmRpcmVjdGlvbiAoZS5nLiwgcGlwZWxpbmVOYW1lOmFzYywgY3JlYXRlZEF0OmRlc2MpJylcblxuICAgIC8vIFBpcGVsaW5lLXNwZWNpZmljIGZpbHRlciBvcHRpb25zXG4gICAgLm9wdGlvbignLS1wcm9qZWN0IDxwcm9qZWN0PicsICdGaWx0ZXIgYnkgZXhhY3QgcHJvamVjdCBuYW1lJylcbiAgICAub3B0aW9uKCctLW9yZ2FuaXphdGlvbiA8b3JnYW5pemF0aW9uPicsICdGaWx0ZXIgYnkgZXhhY3Qgb3JnYW5pemF0aW9uIG5hbWUnKVxuICAgIC5vcHRpb24oJy0tcGlwZWxpbmUtbmFtZSA8bmFtZT4nLCAnRmlsdGVyIGJ5IGV4YWN0IHBpcGVsaW5lIG5hbWUnKVxuXG4gICAgLy8gT3V0cHV0IG9wdGlvbnNcbiAgICAub3B0aW9uKCctZiwgLS1mb3JtYXQgPGZvcm1hdD4nLCAnT3V0cHV0IGZvcm1hdCAoanNvbiwgeWFtbCwgdGFibGUsIGNzdiknLCAndGFibGUnKVxuICAgIC5vcHRpb24oJy1vLCAtLW91dHB1dCA8ZmlsZT4nLCAnU2F2ZSBvdXRwdXQgdG8gZmlsZScpXG4gICAgLm9wdGlvbignLS1zaG93LXByb3BzJywgJ0luY2x1ZGUgcGlwZWxpbmUgcHJvcGVydGllcyBpbiBvdXRwdXQgKGpzb24veWFtbCBvbmx5KScsIGZhbHNlKSlcblxuICAgIC5hY3Rpb24oKG9wdGlvbnMpID0+IHJ1bkxpc3RFbnRpdHk8UGlwZWxpbmUsIFBpcGVsaW5lRmlsdGVyUGFyYW1zPihwcm9ncmFtLCBvcHRpb25zLCB7XG4gICAgICBsYWJlbFBsdXJhbDogJ1BpcGVsaW5lcycsXG4gICAgICByZXNwb25zZUtleTogJ3BpcGVsaW5lcycsXG4gICAgICBsaXN0VXJsOiAoY29uZmlnKSA9PiBjb25maWcuYXBpLnBpcGVsaW5lTGlzdFVybCxcbiAgICAgIGNvbW1hbmROYW1lOiAnbGlzdC1waXBlbGluZXMnLFxuICAgICAgYnVpbGRGaWx0ZXJzOiAob3B0aW9ucywgYmFzZSkgPT4ge1xuICAgICAgICBjb25zdCBmaWx0ZXJzOiBQaXBlbGluZUZpbHRlclBhcmFtcyA9IHsgLi4uYmFzZSB9O1xuICAgICAgICBpZiAob3B0aW9ucy52aXNpYmlsaXR5KSBmaWx0ZXJzLnZpc2liaWxpdHkgPSBvcHRpb25zLnZpc2liaWxpdHkgYXMgc3RyaW5nO1xuICAgICAgICBpZiAob3B0aW9ucy5pc0RlZmF1bHQgIT09IHVuZGVmaW5lZCkgZmlsdGVycy5pc0RlZmF1bHQgPSB2YWxpZGF0ZUJvb2xlYW4ob3B0aW9ucy5pc0RlZmF1bHQgYXMgc3RyaW5nLCAnaXMtZGVmYXVsdCcpO1xuICAgICAgICBpZiAob3B0aW9ucy5wcm9qZWN0KSBmaWx0ZXJzLnByb2plY3QgPSBvcHRpb25zLnByb2plY3QgYXMgc3RyaW5nO1xuICAgICAgICBpZiAob3B0aW9ucy5vcmdhbml6YXRpb24pIGZpbHRlcnMub3JnYW5pemF0aW9uID0gb3B0aW9ucy5vcmdhbml6YXRpb24gYXMgc3RyaW5nO1xuICAgICAgICBpZiAob3B0aW9ucy5waXBlbGluZU5hbWUpIGZpbHRlcnMucGlwZWxpbmVOYW1lID0gb3B0aW9ucy5waXBlbGluZU5hbWUgYXMgc3RyaW5nO1xuICAgICAgICByZXR1cm4gZmlsdGVycztcbiAgICAgIH0sXG4gICAgICBhY3RpdmVGaWx0ZXJzOiAoZmlsdGVycykgPT4ge1xuICAgICAgICBjb25zdCBhY3RpdmU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgICAgIGlmIChmaWx0ZXJzLmlkKSBhY3RpdmUuSUQgPSBmaWx0ZXJzLmlkO1xuICAgICAgICBpZiAoZmlsdGVycy52aXNpYmlsaXR5KSBhY3RpdmUuVmlzaWJpbGl0eSA9IGZpbHRlcnMudmlzaWJpbGl0eTtcbiAgICAgICAgaWYgKGZpbHRlcnMuaXNEZWZhdWx0ICE9PSB1bmRlZmluZWQpIGFjdGl2ZVsnSXMgRGVmYXVsdCddID0gZmlsdGVycy5pc0RlZmF1bHQ7XG4gICAgICAgIGlmIChmaWx0ZXJzLmlzQWN0aXZlICE9PSB1bmRlZmluZWQpIGFjdGl2ZVsnSXMgQWN0aXZlJ10gPSBmaWx0ZXJzLmlzQWN0aXZlO1xuICAgICAgICBpZiAoZmlsdGVycy5wcm9qZWN0KSBhY3RpdmUuUHJvamVjdCA9IGZpbHRlcnMucHJvamVjdDtcbiAgICAgICAgaWYgKGZpbHRlcnMub3JnYW5pemF0aW9uKSBhY3RpdmUuT3JnYW5pemF0aW9uID0gZmlsdGVycy5vcmdhbml6YXRpb247XG4gICAgICAgIGlmIChmaWx0ZXJzLnBpcGVsaW5lTmFtZSkgYWN0aXZlWydQaXBlbGluZSBOYW1lJ10gPSBmaWx0ZXJzLnBpcGVsaW5lTmFtZTtcbiAgICAgICAgcmV0dXJuIGFjdGl2ZTtcbiAgICAgIH0sXG4gICAgICBzdGF0aXN0aWNzOiAocGlwZWxpbmVzKSA9PiAoe1xuICAgICAgICAnQWN0aXZlIFBpcGVsaW5lcyc6IGAke3BpcGVsaW5lcy5maWx0ZXIocCA9PiBwLmlzQWN0aXZlKS5sZW5ndGh9LyR7cGlwZWxpbmVzLmxlbmd0aH1gLFxuICAgICAgICAnRGVmYXVsdCBQaXBlbGluZXMnOiBgJHtwaXBlbGluZXMuZmlsdGVyKHAgPT4gcC5pc0RlZmF1bHQpLmxlbmd0aH0vJHtwaXBlbGluZXMubGVuZ3RofWAsXG4gICAgICB9KSxcbiAgICAgIHJvd3M6IChwaXBlbGluZXMsIG9wdGlvbnMpID0+IG9wdGlvbnMuc2hvd1Byb3BzID8gcGlwZWxpbmVzIDogcGlwZWxpbmVzLm1hcChwID0+ICh7XG4gICAgICAgICdJRCc6IHAuaWQsXG4gICAgICAgICdQcm9qZWN0JzogcC5wcm9qZWN0LFxuICAgICAgICAnT3JnYW5pemF0aW9uJzogcC5vcmdhbml6YXRpb24sXG4gICAgICAgICdOYW1lJzogcC5waXBlbGluZU5hbWUgfHwgJ04vQScsXG4gICAgICAgICdWaXNpYmlsaXR5JzogcC52aXNpYmlsaXR5IHx8ICdwcml2YXRlJyxcbiAgICAgICAgJ0RlZmF1bHQnOiBwLmlzRGVmYXVsdCA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgJ0FjdGl2ZSc6IHAuaXNBY3RpdmUgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICdDcmVhdGVkIEF0JzogcC5jcmVhdGVkQXQgfHwgJ04vQScsXG4gICAgICB9KSksXG4gICAgfSkpO1xufVxuIl19
@@ -0,0 +1,20 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `list-plugins` command with the CLI program.
4
+ *
5
+ * Queries plugins with filters for name, version, image tag,
6
+ * active status, plus pagination and sorting.
7
+ *
8
+ * @param program - The root Commander program instance to attach the command to.
9
+ *
10
+ * @example
11
+ * ```bash
12
+ * cli plugin list
13
+ * cli plugin list --name auth-plugin --is-active true
14
+ * cli plugin list --version "^1.0.0"
15
+ * cli plugin list --limit 50 --offset 100 --sort "name:asc"
16
+ * cli plugin list --format json --output plugins.json
17
+ * ```
18
+ */
19
+ export declare function listPlugins(program: Command): void;
20
+ //# sourceMappingURL=list-plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-plugins.d.ts","sourceRoot":"","sources":["../../src/commands/list-plugins.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+DlD"}
@@ -0,0 +1,92 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { runListEntity } from './entity-list.js';
5
+ import { formatFileSize } from '../config/cli.constants.js';
6
+ import {} from '../types/index.js';
7
+ import { withSslOptions } from '../utils/command-utils.js';
8
+ import {} from '../utils/list-command-utils.js';
9
+ import { printWarning } from '../utils/output-utils.js';
10
+ /**
11
+ * Registers the `list-plugins` command with the CLI program.
12
+ *
13
+ * Queries plugins with filters for name, version, image tag,
14
+ * active status, plus pagination and sorting.
15
+ *
16
+ * @param program - The root Commander program instance to attach the command to.
17
+ *
18
+ * @example
19
+ * ```bash
20
+ * cli plugin list
21
+ * cli plugin list --name auth-plugin --is-active true
22
+ * cli plugin list --version "^1.0.0"
23
+ * cli plugin list --limit 50 --offset 100 --sort "name:asc"
24
+ * cli plugin list --format json --output plugins.json
25
+ * ```
26
+ */
27
+ export function listPlugins(program) {
28
+ withSslOptions(program
29
+ .command('list')
30
+ .description('Query plugins with comprehensive filters')
31
+ // Common filter options
32
+ .option('--id <id>', 'Filter by plugin ID (can specify multiple with commas)')
33
+ .option('--is-active <boolean>', 'Filter by active status (true/false)')
34
+ .option('--limit <number>', 'Maximum number of results (1-1000)', (v) => parseInt(v, 10), 50)
35
+ .option('--offset <number>', 'Number of results to skip', (v) => parseInt(v, 10), 0)
36
+ .option('--sort <sort>', 'Sort format: field:direction (e.g., name:asc, createdAt:desc)')
37
+ // Plugin-specific filter options
38
+ .option('--name <name>', 'Filter by exact plugin name')
39
+ .option('--version <version>', 'Filter by version (supports semver, e.g., "^1.0.0")')
40
+ // Output options
41
+ .option('-f, --format <format>', 'Output format (json, yaml, table, csv)', 'table')
42
+ .option('-o, --output <file>', 'Save output to file')
43
+ .option('--show-metadata', 'Include full metadata in output (json/yaml only)', false))
44
+ .action((options) => runListEntity(program, options, {
45
+ labelPlural: 'Plugins',
46
+ responseKey: 'plugins',
47
+ listUrl: (config) => config.api.pluginListUrl,
48
+ commandName: 'list-plugins',
49
+ buildFilters: (options, base) => {
50
+ const filters = { ...base };
51
+ if (options.name)
52
+ filters.name = options.name;
53
+ if (options.version) {
54
+ // Validate semver format
55
+ const versionPattern = /^(\^|~)?(\d+)\.(\d+)\.(\d+)(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
56
+ if (!versionPattern.test(options.version)) {
57
+ printWarning(`Version "${options.version}" may not be valid semver format`);
58
+ }
59
+ filters.version = options.version;
60
+ }
61
+ return filters;
62
+ },
63
+ activeFilters: (filters) => {
64
+ const active = {};
65
+ if (filters.id)
66
+ active.ID = filters.id;
67
+ if (filters.isActive !== undefined)
68
+ active['Is Active'] = filters.isActive;
69
+ if (filters.name)
70
+ active.Name = filters.name;
71
+ if (filters.version)
72
+ active.Version = filters.version;
73
+ return active;
74
+ },
75
+ statistics: (plugins) => ({
76
+ 'Active Plugins': `${plugins.filter(p => p.isActive).length}/${plugins.length}`,
77
+ 'Public Plugins': `${plugins.filter(p => p.isPublic === true).length}/${plugins.length}`,
78
+ 'Total Size': formatFileSize(plugins.reduce((sum, p) => sum + (p.fileSize || 0), 0)),
79
+ }),
80
+ rows: (plugins, options) => options.showMetadata ? plugins : plugins.map(p => ({
81
+ 'ID': p.id,
82
+ 'Name': p.name,
83
+ 'Version': p.version,
84
+ 'Organization': p.organization,
85
+ 'Active': p.isActive ? 'Yes' : 'No',
86
+ 'Public': p.isPublic ? 'Yes' : 'No',
87
+ 'Size': p.fileSize ? formatFileSize(p.fileSize) : 'N/A',
88
+ 'Created At': p.createdAt || 'N/A',
89
+ })),
90
+ }));
91
+ }
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC1wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2xpc3QtcGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQWUsTUFBTSxtQkFBbUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0QsT0FBTyxFQUEyQixNQUFNLGdDQUFnQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQVl4RDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsT0FBZ0I7SUFDMUMsY0FBYyxDQUFDLE9BQU87U0FDbkIsT0FBTyxDQUFDLE1BQU0sQ0FBQztTQUNmLFdBQVcsQ0FBQywwQ0FBMEMsQ0FBQztRQUV4RCx3QkFBd0I7U0FDdkIsTUFBTSxDQUFDLFdBQVcsRUFBRSx3REFBd0QsQ0FBQztTQUM3RSxNQUFNLENBQUMsdUJBQXVCLEVBQUUsc0NBQXNDLENBQUM7U0FDdkUsTUFBTSxDQUFDLGtCQUFrQixFQUFFLG9DQUFvQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztTQUM1RixNQUFNLENBQUMsbUJBQW1CLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ25GLE1BQU0sQ0FBQyxlQUFlLEVBQUUs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QUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDN0UsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFO1lBQ1YsTUFBTSxFQUFFLENBQUMsQ0FBQyxJQUFJO1lBQ2QsU0FBUyxFQUFFLENBQUMsQ0FBQyxPQUFPO1lBQ3BCLGNBQWMsRUFBRSxDQUFDLENBQUMsWUFBWTtZQUM5QixRQUFRLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQ25DLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDbkMsTUFBTSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUs7WUFDdkQsWUFBWSxFQUFFLENBQUMsQ0FBQyxTQUFTLElBQUksS0FBSztTQUNuQyxDQUFDLENBQUM7S0FDSixDQUFDLENBQUMsQ0FBQztBQUNSLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgeyBydW5MaXN0RW50aXR5IH0gZnJvbSAnLi9lbnRpdHktbGlzdC5qcyc7XG5pbXBvcnQgeyBmb3JtYXRGaWxlU2l6ZSB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHR5cGUgUGx1Z2luIH0gZnJvbSAnLi4vdHlwZXMvaW5kZXguanMnO1xuaW1wb3J0IHsgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IHR5cGUgQ29tbW9uRmlsdGVyUGFyYW1zIH0gZnJvbSAnLi4vdXRpbHMvbGlzdC1jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IHByaW50V2FybmluZyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbi8qKlxuICogUXVlcnkgcGFyYW1ldGVycyBmb3IgdGhlIHBsdWdpbiBsaXN0IEFQSSBlbmRwb2ludC5cbiAqIENvbWJpbmVzIGNvbW1vbiBmaWx0ZXJzIChwYWdpbmF0aW9uLCBzb3J0KSB3aXRoIHBsdWdpbi1zcGVjaWZpYyBmaWx0ZXJzLlxuICovXG5pbnRlcmZhY2UgUGx1Z2luRmlsdGVyUGFyYW1zIGV4dGVuZHMgQ29tbW9uRmlsdGVyUGFyYW1zIHtcbiAgLy8gUGx1Z2luLXNwZWNpZmljIGZpbHRlcnNcbiAgbmFtZT86IHN0cmluZztcbiAgdmVyc2lvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBsaXN0LXBsdWdpbnNgIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogUXVlcmllcyBwbHVnaW5zIHdpdGggZmlsdGVycyBmb3IgbmFtZSwgdmVyc2lvbiwgaW1hZ2UgdGFnLFxuICogYWN0aXZlIHN0YXR1cywgcGx1cyBwYWdpbmF0aW9uIGFuZCBzb3J0aW5nLlxuICpcbiAqIEBwYXJhbSBwcm9ncmFtIC0gVGhlIHJvb3QgQ29tbWFuZGVyIHByb2dyYW0gaW5zdGFuY2UgdG8gYXR0YWNoIHRoZSBjb21tYW5kIHRvLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBjbGkgcGx1Z2luIGxpc3RcbiAqIGNsaSBwbHVnaW4gbGlzdCAtLW5hbWUgYXV0aC1wbHVnaW4gLS1pcy1hY3RpdmUgdHJ1ZVxuICogY2xpIHBsdWdpbiBsaXN0IC0tdmVyc2lvbiBcIl4xLjAuMFwiXG4gKiBjbGkgcGx1Z2luIGxpc3QgLS1saW1pdCA1MCAtLW9mZnNldCAxMDAgLS1zb3J0IFwibmFtZTphc2NcIlxuICogY2xpIHBsdWdpbiBsaXN0IC0tZm9ybWF0IGpzb24gLS1vdXRwdXQgcGx1Z2lucy5qc29uXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RQbHVnaW5zKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMocHJvZ3JhbVxuICAgIC5jb21tYW5kKCdsaXN0JylcbiAgICAuZGVzY3JpcHRpb24oJ1F1ZXJ5IHBsdWdpbnMgd2l0aCBjb21wcmVoZW5zaXZlIGZpbHRlcnMnKVxuXG4gICAgLy8gQ29tbW9uIGZpbHRlciBvcHRpb25zXG4gICAgLm9wdGlvbignLS1pZCA8aWQ+JywgJ0ZpbHRlciBieSBwbHVnaW4gSUQgKGNhbiBzcGVjaWZ5IG11bHRpcGxlIHdpdGggY29tbWFzKScpXG4gICAgLm9wdGlvbignLS1pcy1hY3RpdmUgPGJvb2xlYW4+JywgJ0ZpbHRlciBieSBhY3RpdmUgc3RhdHVzICh0cnVlL2ZhbHNlKScpXG4gICAgLm9wdGlvbignLS1saW1pdCA8bnVtYmVyPicsICdNYXhpbXVtIG51bWJlciBvZiByZXN1bHRzICgxLTEwMDApJywgKHYpID0+IHBhcnNlSW50KHYsIDEwKSwgNTApXG4gICAgLm9wdGlvbignLS1vZmZzZXQgPG51bWJlcj4nLCAnTnVtYmVyIG9mIHJlc3VsdHMgdG8gc2tpcCcsICh2KSA9PiBwYXJzZUludCh2LCAxMCksIDApXG4gICAgLm9wdGlvbignLS1zb3J0IDxzb3J0PicsICdTb3J0IGZvcm1hdDogZmllbGQ6ZGlyZWN0aW9uIChlLmcuLCBuYW1lOmFzYywgY3JlYXRlZEF0OmRlc2MpJylcblxuICAgIC8vIFBsdWdpbi1zcGVjaWZpYyBmaWx0ZXIgb3B0aW9uc1xuICAgIC5vcHRpb24oJy0tbmFtZSA8bmFtZT4nLCAnRmlsdGVyIGJ5IGV4YWN0IHBsdWdpbiBuYW1lJylcbiAgICAub3B0aW9uKCctLXZlcnNpb24gPHZlcnNpb24+JywgJ0ZpbHRlciBieSB2ZXJzaW9uIChzdXBwb3J0cyBzZW12ZXIsIGUuZy4sIFwiXjEuMC4wXCIpJylcblxuICAgIC8vIE91dHB1dCBvcHRpb25zXG4gICAgLm9wdGlvbignLWYsIC0tZm9ybWF0IDxmb3JtYXQ+JywgJ091dHB1dCBmb3JtYXQgKGpzb24sIHlhbWwsIHRhYmxlLCBjc3YpJywgJ3RhYmxlJylcbiAgICAub3B0aW9uKCctbywgLS1vdXRwdXQgPGZpbGU+JywgJ1NhdmUgb3V0cHV0IHRvIGZpbGUnKVxuICAgIC5vcHRpb24oJy0tc2hvdy1tZXRhZGF0YScsICdJbmNsdWRlIGZ1bGwgbWV0YWRhdGEgaW4gb3V0cHV0IChqc29uL3lhbWwgb25seSknLCBmYWxzZSkpXG5cbiAgICAuYWN0aW9uKChvcHRpb25zKSA9PiBydW5MaXN0RW50aXR5PFBsdWdpbiwgUGx1Z2luRmlsdGVyUGFyYW1zPihwcm9ncmFtLCBvcHRpb25zLCB7XG4gICAgICBsYWJlbFBsdXJhbDogJ1BsdWdpbnMnLFxuICAgICAgcmVzcG9uc2VLZXk6ICdwbHVnaW5zJyxcbiAgICAgIGxpc3RVcmw6IChjb25maWcpID0+IGNvbmZpZy5hcGkucGx1Z2luTGlzdFVybCxcbiAgICAgIGNvbW1hbmROYW1lOiAnbGlzdC1wbHVnaW5zJyxcbiAgICAgIGJ1aWxkRmlsdGVyczogKG9wdGlvbnMsIGJhc2UpID0+IHtcbiAgICAgICAgY29uc3QgZmlsdGVyczogUGx1Z2luRmlsdGVyUGFyYW1zID0geyAuLi5iYXNlIH07XG4gICAgICAgIGlmIChvcHRpb25zLm5hbWUpIGZpbHRlcnMubmFtZSA9IG9wdGlvbnMubmFtZSBhcyBzdHJpbmc7XG4gICAgICAgIGlmIChvcHRpb25zLnZlcnNpb24pIHtcbiAgICAgICAgICAvLyBWYWxpZGF0ZSBzZW12ZXIgZm9ybWF0XG4gICAgICAgICAgY29uc3QgdmVyc2lvblBhdHRlcm4gPSAvXihcXF58fik/KFxcZCspXFwuKFxcZCspXFwuKFxcZCspKC1bYS16QS1aMC05Li1dKyk/KFxcK1thLXpBLVowLTkuLV0rKT8kLztcbiAgICAgICAgICBpZiAoIXZlcnNpb25QYXR0ZXJuLnRlc3Qob3B0aW9ucy52ZXJzaW9uIGFzIHN0cmluZykpIHtcbiAgICAgICAgICAgIHByaW50V2FybmluZyhgVmVyc2lvbiBcIiR7b3B0aW9ucy52ZXJzaW9ufVwiIG1heSBub3QgYmUgdmFsaWQgc2VtdmVyIGZvcm1hdGApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmaWx0ZXJzLnZlcnNpb24gPSBvcHRpb25zLnZlcnNpb24gYXMgc3RyaW5nO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWx0ZXJzO1xuICAgICAgfSxcbiAgICAgIGFjdGl2ZUZpbHRlcnM6IChmaWx0ZXJzKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICAgICAgaWYgKGZpbHRlcnMuaWQpIGFjdGl2ZS5JRCA9IGZpbHRlcnMuaWQ7XG4gICAgICAgIGlmIChmaWx0ZXJzLmlzQWN0aXZlICE9PSB1bmRlZmluZWQpIGFjdGl2ZVsnSXMgQWN0aXZlJ10gPSBmaWx0ZXJzLmlzQWN0aXZlO1xuICAgICAgICBpZiAoZmlsdGVycy5uYW1lKSBhY3RpdmUuTmFtZSA9IGZpbHRlcnMubmFtZTtcbiAgICAgICAgaWYgKGZpbHRlcnMudmVyc2lvbikgYWN0aXZlLlZlcnNpb24gPSBmaWx0ZXJzLnZlcnNpb247XG4gICAgICAgIHJldHVybiBhY3RpdmU7XG4gICAgICB9LFxuICAgICAgc3RhdGlzdGljczogKHBsdWdpbnMpID0+ICh7XG4gICAgICAgICdBY3RpdmUgUGx1Z2lucyc6IGAke3BsdWdpbnMuZmlsdGVyKHAgPT4gcC5pc0FjdGl2ZSkubGVuZ3RofS8ke3BsdWdpbnMubGVuZ3RofWAsXG4gICAgICAgICdQdWJsaWMgUGx1Z2lucyc6IGAke3BsdWdpbnMuZmlsdGVyKHAgPT4gcC5pc1B1YmxpYyA9PT0gdHJ1ZSkubGVuZ3RofS8ke3BsdWdpbnMubGVuZ3RofWAsXG4gICAgICAgICdUb3RhbCBTaXplJzogZm9ybWF0RmlsZVNpemUocGx1Z2lucy5yZWR1Y2UoKHN1bSwgcCkgPT4gc3VtICsgKHAuZmlsZVNpemUgfHwgMCksIDApKSxcbiAgICAgIH0pLFxuICAgICAgcm93czogKHBsdWdpbnMsIG9wdGlvbnMpID0+IG9wdGlvbnMuc2hvd01ldGFkYXRhID8gcGx1Z2lucyA6IHBsdWdpbnMubWFwKHAgPT4gKHtcbiAgICAgICAgJ0lEJzogcC5pZCxcbiAgICAgICAgJ05hbWUnOiBwLm5hbWUsXG4gICAgICAgICdWZXJzaW9uJzogcC52ZXJzaW9uLFxuICAgICAgICAnT3JnYW5pemF0aW9uJzogcC5vcmdhbml6YXRpb24sXG4gICAgICAgICdBY3RpdmUnOiBwLmlzQWN0aXZlID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAnUHVibGljJzogcC5pc1B1YmxpYyA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgJ1NpemUnOiBwLmZpbGVTaXplID8gZm9ybWF0RmlsZVNpemUocC5maWxlU2l6ZSkgOiAnTi9BJyxcbiAgICAgICAgJ0NyZWF0ZWQgQXQnOiBwLmNyZWF0ZWRBdCB8fCAnTi9BJyxcbiAgICAgIH0pKSxcbiAgICB9KSk7XG59XG4iXX0=