@pipeline-builder/pipeline-manager 4.1.14 → 4.1.16

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 (92) hide show
  1. package/config.yml +16 -37
  2. package/dist/boilerplate.js +10 -2
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +97 -79
  5. package/dist/commands/audit-stacks.js +3 -3
  6. package/dist/commands/create-pat.d.ts +2 -3
  7. package/dist/commands/create-pat.d.ts.map +1 -1
  8. package/dist/commands/create-pat.js +3 -4
  9. package/dist/commands/create-pipeline.d.ts.map +1 -1
  10. package/dist/commands/create-pipeline.js +198 -190
  11. package/dist/commands/list-pipelines.js +2 -2
  12. package/dist/commands/list-plugins.js +2 -2
  13. package/dist/commands/login.d.ts +2 -2
  14. package/dist/commands/login.js +3 -3
  15. package/dist/commands/new-plugin.d.ts +48 -5
  16. package/dist/commands/new-plugin.d.ts.map +1 -1
  17. package/dist/commands/new-plugin.js +261 -95
  18. package/dist/commands/plugin-lifecycle.d.ts +29 -0
  19. package/dist/commands/plugin-lifecycle.d.ts.map +1 -0
  20. package/dist/commands/plugin-lifecycle.js +147 -0
  21. package/dist/commands/provision.d.ts +42 -2
  22. package/dist/commands/provision.d.ts.map +1 -1
  23. package/dist/commands/provision.js +184 -147
  24. package/dist/commands/publish-plugin.d.ts +62 -0
  25. package/dist/commands/publish-plugin.d.ts.map +1 -0
  26. package/dist/commands/publish-plugin.js +224 -0
  27. package/dist/commands/redrive-events.d.ts +1 -1
  28. package/dist/commands/redrive-events.js +2 -2
  29. package/dist/commands/store-token.d.ts +46 -1
  30. package/dist/commands/store-token.d.ts.map +1 -1
  31. package/dist/commands/store-token.js +127 -102
  32. package/dist/commands/test-plugin.d.ts +72 -0
  33. package/dist/commands/test-plugin.d.ts.map +1 -0
  34. package/dist/commands/test-plugin.js +285 -0
  35. package/dist/commands/upload-plugin.d.ts +6 -7
  36. package/dist/commands/upload-plugin.d.ts.map +1 -1
  37. package/dist/commands/upload-plugin.js +127 -189
  38. package/dist/commands/validate-plugin.d.ts +37 -4
  39. package/dist/commands/validate-plugin.d.ts.map +1 -1
  40. package/dist/commands/validate-plugin.js +129 -144
  41. package/dist/commands/validate-templates.d.ts.map +1 -1
  42. package/dist/commands/validate-templates.js +8 -9
  43. package/dist/config/plugin-catalog-assets.d.ts +13 -0
  44. package/dist/config/plugin-catalog-assets.d.ts.map +1 -0
  45. package/dist/config/plugin-catalog-assets.js +21 -0
  46. package/dist/config.yml +16 -37
  47. package/dist/lambda/token-renew-handler.d.ts.map +1 -1
  48. package/dist/lambda/token-renew-handler.js +109 -154
  49. package/dist/types/config.d.ts +2 -6
  50. package/dist/types/config.d.ts.map +1 -1
  51. package/dist/types/config.js +1 -1
  52. package/dist/types/plugin.d.ts +21 -0
  53. package/dist/types/plugin.d.ts.map +1 -1
  54. package/dist/types/plugin.js +1 -1
  55. package/dist/utils/aws-env.d.ts +1 -2
  56. package/dist/utils/aws-env.d.ts.map +1 -1
  57. package/dist/utils/aws-env.js +2 -3
  58. package/dist/utils/catalog-prompt.d.ts +26 -0
  59. package/dist/utils/catalog-prompt.d.ts.map +1 -0
  60. package/dist/utils/catalog-prompt.js +113 -0
  61. package/dist/utils/command-utils.d.ts.map +1 -1
  62. package/dist/utils/command-utils.js +14 -3
  63. package/dist/utils/config-loader.d.ts.map +1 -1
  64. package/dist/utils/config-loader.js +4 -6
  65. package/dist/utils/credential-store.d.ts +16 -0
  66. package/dist/utils/credential-store.d.ts.map +1 -1
  67. package/dist/utils/credential-store.js +57 -2
  68. package/dist/utils/deploy-runner.d.ts.map +1 -1
  69. package/dist/utils/deploy-runner.js +7 -2
  70. package/dist/utils/pipeline-config.d.ts +1 -2
  71. package/dist/utils/pipeline-config.d.ts.map +1 -1
  72. package/dist/utils/pipeline-config.js +1 -1
  73. package/dist/utils/plugin-docker.d.ts +44 -0
  74. package/dist/utils/plugin-docker.d.ts.map +1 -0
  75. package/dist/utils/plugin-docker.js +71 -0
  76. package/dist/utils/plugin-package.d.ts +40 -0
  77. package/dist/utils/plugin-package.d.ts.map +1 -0
  78. package/dist/utils/plugin-package.js +159 -0
  79. package/dist/utils/plugin-resolver.d.ts.map +1 -1
  80. package/dist/utils/plugin-resolver.js +43 -29
  81. package/dist/utils/plugin-scan.d.ts +22 -0
  82. package/dist/utils/plugin-scan.d.ts.map +1 -0
  83. package/dist/utils/plugin-scan.js +52 -0
  84. package/dist/utils/plugin-zip.d.ts +15 -0
  85. package/dist/utils/plugin-zip.d.ts.map +1 -0
  86. package/dist/utils/plugin-zip.js +96 -0
  87. package/dist/utils/registry.d.ts +15 -0
  88. package/dist/utils/registry.d.ts.map +1 -1
  89. package/dist/utils/registry.js +17 -2
  90. package/dist/utils/service-account.d.ts.map +1 -1
  91. package/dist/utils/service-account.js +9 -10
  92. package/package.json +45 -8
@@ -8,28 +8,125 @@ import FormData from 'form-data';
8
8
  import ora from 'ora';
9
9
  import pico from 'picocolors';
10
10
  import { FILE_SIZE_LIMITS, formatFileSize } from '../config/cli.constants.js';
11
- import {} from '../types/index.js';
12
11
  import { printCommandHeader, printSslWarning, createAuthenticatedClient, withSslOptions } from '../utils/command-utils.js';
13
12
  import { ERROR_CODES, handleError, ValidationError } from '../utils/error-handler.js';
14
13
  import { fileExists, printError, printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
15
- import { extractSingleResponse } from '../utils/response-utils.js';
14
+ import { unwrapEnvelope } from '../utils/response-utils.js';
16
15
  const { bold, green } = pico;
16
+ /**
17
+ * Validate the plugin ZIP (non-empty path, exists, `.zip`, size cap, readable).
18
+ * Returns the resolved path and its formatted size.
19
+ */
20
+ function validatePluginZip(file) {
21
+ // Validate file path
22
+ if (typeof file !== 'string' || file.trim().length === 0) {
23
+ printError('Invalid file path', { provided: file });
24
+ throw new ValidationError('File path must be a non-empty string', 'file', file);
25
+ }
26
+ const filePath = path.resolve(file);
27
+ // Validate file exists
28
+ printInfo('Validating plugin file', { path: filePath });
29
+ if (!fileExists(filePath)) {
30
+ printError('Plugin file not found', { path: filePath });
31
+ throw new ValidationError(`Plugin file not found: ${filePath}`, 'file', filePath);
32
+ }
33
+ // Validate file extension
34
+ const fileExt = path.extname(filePath).toLowerCase();
35
+ if (fileExt !== '.zip') {
36
+ printWarning('File extension is not .zip', {
37
+ provided: fileExt,
38
+ expected: '.zip',
39
+ });
40
+ throw new ValidationError('Plugin file must be a ZIP archive', 'file', filePath);
41
+ }
42
+ // Get file stats
43
+ const stats = fs.statSync(filePath);
44
+ const sizeBytes = stats.size;
45
+ const sizeFormatted = formatFileSize(sizeBytes);
46
+ printSuccess('Plugin file found', {
47
+ path: filePath,
48
+ size: sizeFormatted,
49
+ modified: new Date(stats.mtime).toLocaleString(),
50
+ });
51
+ // Check file size
52
+ if (sizeBytes > FILE_SIZE_LIMITS.PLUGIN) {
53
+ printError('Plugin file too large', {
54
+ size: sizeFormatted,
55
+ maximum: formatFileSize(FILE_SIZE_LIMITS.PLUGIN),
56
+ exceededBy: formatFileSize(sizeBytes - FILE_SIZE_LIMITS.PLUGIN),
57
+ });
58
+ throw new ValidationError(`Plugin file exceeds maximum size of ${formatFileSize(FILE_SIZE_LIMITS.PLUGIN)} (actual: ${sizeFormatted})`, 'file.size', sizeBytes);
59
+ }
60
+ // Check if file is readable
61
+ try {
62
+ fs.accessSync(filePath, fs.constants.R_OK);
63
+ }
64
+ catch (error) {
65
+ printError('Cannot read plugin file', {
66
+ path: filePath,
67
+ error: errorMessage(error),
68
+ });
69
+ throw new ValidationError('Plugin file is not readable', 'file', filePath);
70
+ }
71
+ printSuccess('Plugin file validated');
72
+ return { filePath, sizeFormatted };
73
+ }
74
+ /** POST the ZIP as multipart form data; returns the raw response and its duration. */
75
+ async function postPluginZip(client, filePath, sizeFormatted, isPublic) {
76
+ const config = client.getConfig();
77
+ // Create form data
78
+ console.log('');
79
+ printSection('Uploading Plugin');
80
+ printInfo('Preparing upload', {
81
+ file: path.basename(filePath),
82
+ size: sizeFormatted,
83
+ });
84
+ const formData = new FormData();
85
+ formData.append('plugin', fs.createReadStream(filePath), {
86
+ filename: path.basename(filePath),
87
+ contentType: 'application/zip',
88
+ });
89
+ // The upload API reads `visibility` (private | org | public); without
90
+ // it the version is `org`. `public` needs plugins:publish. Name and
91
+ // version come from the package's spec; the org from the session.
92
+ if (isPublic)
93
+ formData.append('visibility', 'public');
94
+ // Make API request
95
+ const endpoint = config.api.pluginUploadUrl;
96
+ printInfo('Uploading to API', {
97
+ endpoint: `${config.api.baseUrl}${endpoint}`,
98
+ });
99
+ console.log('');
100
+ const spinner = ora('Uploading plugin...').start();
101
+ let rawResponse;
102
+ let duration;
103
+ try {
104
+ const startTime = Date.now();
105
+ rawResponse = await client.postForm(endpoint, formData);
106
+ duration = Date.now() - startTime;
107
+ spinner.succeed('Plugin uploaded');
108
+ }
109
+ catch (error) {
110
+ spinner.fail('Upload failed');
111
+ throw error;
112
+ }
113
+ return { rawResponse, duration };
114
+ }
17
115
  /**
18
116
  * Registers the `upload-plugin` command with the CLI program.
19
117
  *
20
118
  * Validates a local plugin ZIP file (size, extension, readability),
21
- * builds a multipart form, and uploads it to the platform API.
22
- * Plugin name and version can be auto-detected from the package
23
- * or overridden via CLI flags.
119
+ * builds a multipart form, and uploads it to the platform API. The
120
+ * plugin's name and version always come from the package's
121
+ * `plugin-spec.yaml`, and the organization from the signed-in session.
24
122
  *
25
123
  * @param program - The root Commander program instance to attach the command to.
26
124
  *
27
125
  * @example
28
126
  * ```bash
29
- * cli plugin upload --file plugin.zip --organization acme
30
- * cli plugin upload --file plugin.zip --organization acme --public
31
- * cli plugin upload --file plugin.zip --organization acme --name my-plugin --version 1.0.0
32
- * cli plugin upload --file plugin.zip --organization acme --no-verify-ssl
127
+ * cli plugin upload --file plugin.zip
128
+ * cli plugin upload --file plugin.zip --public
129
+ * cli plugin upload --file plugin.zip --no-verify-ssl
33
130
  * ```
34
131
  */
35
132
  export function uploadPlugin(program) {
@@ -37,12 +134,7 @@ export function uploadPlugin(program) {
37
134
  .command('upload')
38
135
  .description('Upload and deploy a plugin package')
39
136
  .requiredOption('-f, --file <file>', 'Path to plugin ZIP file')
40
- .requiredOption('-o, --organization <organization>', 'Organization name')
41
- .option('-n, --name <name>', 'Plugin name (optional, extracted from package if not provided)')
42
- .option('-v, --version <version>', 'Plugin version (optional, extracted from package if not provided)')
43
- .option('--public', 'Make plugin publicly accessible', false)
44
- .option('--active', 'Set plugin as active', true)
45
- .option('--no-active', 'Upload the plugin as inactive'))
137
+ .option('--public', 'Make plugin publicly accessible (needs plugins:publish)', false))
46
138
  .option('--dry-run', 'Validate file without uploading', false)
47
139
  .action(async (options) => {
48
140
  const executionId = printCommandHeader('Upload Plugin');
@@ -50,93 +142,13 @@ export function uploadPlugin(program) {
50
142
  // Display parameters
51
143
  printInfo('Upload parameters', {
52
144
  file: options.file,
53
- organization: options.organization,
54
- name: options.name || '(auto-detect)',
55
- version: options.version || '(auto-detect)',
56
145
  public: options.public ? 'Yes' : 'No',
57
- active: options.active ? 'Yes' : 'No',
58
146
  dryRun: options.dryRun,
59
147
  verifySsl: options.verifySsl,
60
148
  });
61
149
  // Security warning for SSL verification disabled
62
150
  printSslWarning(options.verifySsl);
63
- // Validate organization
64
- if (!options.organization || typeof options.organization !== 'string' || options.organization.trim().length === 0) {
65
- printError('Invalid organization name', { provided: options.organization });
66
- throw new ValidationError('Organization must be a non-empty string', 'organization', options.organization);
67
- }
68
- // Validate file path
69
- if (!options.file || typeof options.file !== 'string' || options.file.trim().length === 0) {
70
- printError('Invalid file path', { provided: options.file });
71
- throw new ValidationError('File path must be a non-empty string', 'file', options.file);
72
- }
73
- const filePath = path.resolve(options.file);
74
- // Validate file exists
75
- printInfo('Validating plugin file', { path: filePath });
76
- if (!fileExists(filePath)) {
77
- printError('Plugin file not found', { path: filePath });
78
- throw new ValidationError(`Plugin file not found: ${filePath}`, 'file', filePath);
79
- }
80
- // Validate file extension
81
- const fileExt = path.extname(filePath).toLowerCase();
82
- if (fileExt !== '.zip') {
83
- printWarning('File extension is not .zip', {
84
- provided: fileExt,
85
- expected: '.zip',
86
- });
87
- throw new ValidationError('Plugin file must be a ZIP archive', 'file', filePath);
88
- }
89
- // Get file stats
90
- const stats = fs.statSync(filePath);
91
- const sizeBytes = stats.size;
92
- const sizeFormatted = formatFileSize(sizeBytes);
93
- printSuccess('Plugin file found', {
94
- path: filePath,
95
- size: sizeFormatted,
96
- modified: new Date(stats.mtime).toLocaleString(),
97
- });
98
- // Check file size
99
- if (sizeBytes > FILE_SIZE_LIMITS.PLUGIN) {
100
- printError('Plugin file too large', {
101
- size: sizeFormatted,
102
- maximum: formatFileSize(FILE_SIZE_LIMITS.PLUGIN),
103
- exceededBy: formatFileSize(sizeBytes - FILE_SIZE_LIMITS.PLUGIN),
104
- });
105
- throw new ValidationError(`Plugin file exceeds maximum size of ${formatFileSize(FILE_SIZE_LIMITS.PLUGIN)} (actual: ${sizeFormatted})`, 'file.size', sizeBytes);
106
- }
107
- // Check if file is readable
108
- try {
109
- fs.accessSync(filePath, fs.constants.R_OK);
110
- }
111
- catch (error) {
112
- printError('Cannot read plugin file', {
113
- path: filePath,
114
- error: errorMessage(error),
115
- });
116
- throw new ValidationError('Plugin file is not readable', 'file', filePath);
117
- }
118
- printSuccess('Plugin file validated');
119
- // Validate version format if provided. Allows -prerelease and +build
120
- // metadata (valid semver) to match validate-plugin and the DB constraint.
121
- if (options.version) {
122
- const versionRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
123
- if (!versionRegex.test(options.version)) {
124
- printWarning('Version format may be invalid', {
125
- provided: options.version,
126
- expected: 'semantic version (e.g., 1.0.0, 1.2.3-beta.1)',
127
- });
128
- }
129
- }
130
- // Validate name format if provided
131
- if (options.name) {
132
- const nameRegex = /^[a-z0-9-]+$/;
133
- if (!nameRegex.test(options.name)) {
134
- printWarning('Plugin name format may be invalid', {
135
- provided: options.name,
136
- expected: 'lowercase alphanumeric with dashes (e.g., my-plugin-name)',
137
- });
138
- }
139
- }
151
+ const { filePath, sizeFormatted } = validatePluginZip(options.file);
140
152
  // Dry run mode
141
153
  if (options.dryRun) {
142
154
  console.log('');
@@ -145,84 +157,29 @@ export function uploadPlugin(program) {
145
157
  printKeyValue({
146
158
  File: filePath,
147
159
  Size: sizeFormatted,
148
- Organization: options.organization,
149
- Name: options.name || '(will be auto-detected)',
150
- Version: options.version || '(will be auto-detected)',
151
160
  Public: options.public ? 'Yes' : 'No',
152
- Active: options.active ? 'Yes' : 'No',
153
161
  });
154
162
  return;
155
163
  }
156
- // Create authenticated API client
157
164
  const client = createAuthenticatedClient(options);
158
- const config = client.getConfig();
159
- // Create form data
160
- console.log('');
161
- printSection('Uploading Plugin');
162
- printInfo('Preparing upload', {
163
- file: path.basename(filePath),
164
- size: sizeFormatted,
165
- });
166
- const formData = new FormData();
167
- formData.append('plugin', fs.createReadStream(filePath), {
168
- filename: path.basename(filePath),
169
- contentType: 'application/zip',
170
- });
171
- formData.append('organization', options.organization);
172
- if (options.name)
173
- formData.append('name', options.name);
174
- if (options.version)
175
- formData.append('version', options.version);
176
- formData.append('isPublic', options.public ? 'true' : 'false');
177
- formData.append('isActive', options.active ? 'true' : 'false');
178
- // Make API request
179
- const endpoint = config.api.pluginUploadUrl;
180
- printInfo('Uploading to API', {
181
- endpoint: `${config.api.baseUrl}${endpoint}`,
182
- });
183
- console.log('');
184
- const spinner = ora('Uploading plugin...').start();
185
- let rawResponse;
186
- let duration;
187
- try {
188
- const startTime = Date.now();
189
- rawResponse = await client.postForm(endpoint, formData);
190
- duration = Date.now() - startTime;
191
- spinner.succeed('Plugin uploaded');
192
- }
193
- catch (error) {
194
- spinner.fail('Upload failed');
195
- throw error;
196
- }
197
- const response = extractSingleResponse(rawResponse, 'plugin', 'name');
198
- if (!response) {
199
- printError('No valid plugin data in response', {
200
- responseKeys: rawResponse ? Object.keys(rawResponse) : '(null)',
165
+ const { rawResponse, duration } = await postPluginZip(client, filePath, sizeFormatted, !!options.public);
166
+ const response = unwrapEnvelope(rawResponse);
167
+ if (!response.pluginName) {
168
+ printError('No valid upload result in response', {
169
+ responseKeys: Object.keys(response).join(', ') || '(none)',
201
170
  });
202
- throw new Error('Upload failed - no valid plugin data received');
171
+ throw new Error('Upload failed - no valid upload result received');
203
172
  }
173
+ // 201: a metadata-only plugin, deployed directly (has a pluginId).
174
+ // 202: the image build was queued; the worker persists the version.
175
+ const queued = !response.pluginId;
204
176
  console.log('');
205
- printSection('Plugin Uploaded Successfully');
206
- // Display plugin information
207
- printKeyValue({
208
- 'Plugin ID': green(bold(response.id)),
209
- 'Name': response.name,
210
- 'Version': response.version,
211
- 'Organization': response.organization,
212
- 'Description': response.description || '(not set)',
213
- });
214
- console.log('');
177
+ printSection(queued ? 'Plugin Build Queued' : 'Plugin Deployed');
215
178
  printKeyValue({
216
- 'File URL': response.fileUrl || '(not available)',
217
- 'File Size': response.fileSize ? `${(response.fileSize / 1024).toFixed(2)} KB` : '(not available)',
218
- 'Checksum': response.checksum ? `${response.checksum.substring(0, 16)}...` : '(not available)',
219
- });
220
- console.log('');
221
- printKeyValue({
222
- 'Public': response.isPublic ? 'Yes' : 'No',
223
- 'Active': response.isActive ? 'Yes' : 'No',
224
- 'Created At': response.createdAt || '(not available)',
225
- 'Uploaded By': response.uploadedBy || '(not available)',
179
+ 'Plugin': green(bold(`${response.pluginName}@${response.version ?? '?'}`)),
180
+ ...(response.pluginId ? { 'Plugin ID': response.pluginId } : {}),
181
+ 'Request ID': response.requestId ?? '(not available)',
182
+ 'Visibility': options.public ? 'public' : 'org',
226
183
  });
227
184
  console.log('');
228
185
  printKeyValue({
@@ -230,28 +187,13 @@ export function uploadPlugin(program) {
230
187
  'Upload Duration': `${(duration / 1000).toFixed(2)}s`,
231
188
  'Status': green('✓ Success'),
232
189
  });
233
- // Print additional information if available
234
- if (response.metadata) {
235
- console.log('');
236
- printInfo('Plugin metadata available', {
237
- keys: Object.keys(response.metadata).length,
238
- });
239
- }
240
- // Print deployment logs URL if available
241
- const resp = response;
242
- const requestId = resp['X-Request-Id'] || resp.requestId;
243
- if (requestId) {
244
- console.log('');
245
- printInfo('Deployment logs available', {
246
- requestId,
247
- url: `${config.api.baseUrl}/logs/${requestId}`,
248
- });
249
- }
250
190
  // Next steps
251
191
  console.log('');
252
192
  printInfo('Next steps', {
253
- view: `Use "get-plugin --id ${response.id}" to view plugin details`,
254
- list: 'Use "list-plugins" to see all plugins',
193
+ ...(response.pluginId
194
+ ? { view: `Use "plugin get --id ${response.pluginId}" to view plugin details` }
195
+ : { build: 'The version appears in "plugin list" once its image build completes' }),
196
+ list: 'Use "plugin list" to see all plugins',
255
197
  });
256
198
  }
257
199
  catch (error) {
@@ -262,15 +204,11 @@ export function uploadPlugin(program) {
262
204
  command: 'upload-plugin',
263
205
  executionId,
264
206
  file: options.file,
265
- organization: options.organization,
266
- name: options.name,
267
- version: options.version,
268
207
  public: options.public,
269
- active: options.active,
270
208
  verifySsl: options.verifySsl,
271
209
  },
272
210
  });
273
211
  }
274
212
  });
275
213
  }
276
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLXBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy91cGxvYWQtcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxRQUFRLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQztBQUN0QixPQUFPLElBQUksTUFBTSxZQUFZLENBQUM7QUFDOUIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzlFLE9BQU8sRUFBb0MsTUFBTSxtQkFBbUIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLHlCQUF5QixFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzNILE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN0SSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVuRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQztBQUU3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUFDLE9BQWdCO0lBQzNDLGNBQWMs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QUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxXQUFXLEVBQUU7Z0JBQzFDLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSztnQkFDM0IsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsT0FBTyxFQUFFO29CQUNQLE9BQU8sRUFBRSxlQUFlO29CQUN4QixXQUFXO29CQUNYLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO29CQUNsQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7b0JBQ2xCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztvQkFDeEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO29CQUN0QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07b0JBQ3RCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztpQkFDN0I7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBlcnJvck1lc3NhZ2UgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCBGb3JtRGF0YSBmcm9tICdmb3JtLWRhdGEnO1xuaW1wb3J0IG9yYSBmcm9tICdvcmEnO1xuaW1wb3J0IHBpY28gZnJvbSAncGljb2NvbG9ycyc7XG5pbXBvcnQgeyBGSUxFX1NJWkVfTElNSVRTLCBmb3JtYXRGaWxlU2l6ZSB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHR5cGUgUGx1Z2luLCB0eXBlIFBsdWdpblJlc3BvbnNlIH0gZnJvbSAnLi4vdHlwZXMvaW5kZXguanMnO1xuaW1wb3J0IHsgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcsIGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnQsIHdpdGhTc2xPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyBFUlJPUl9DT0RFUywgaGFuZGxlRXJyb3IsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgZmlsZUV4aXN0cywgcHJpbnRFcnJvciwgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcywgcHJpbnRXYXJuaW5nIH0gZnJvbSAnLi4vdXRpbHMvb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IGV4dHJhY3RTaW5nbGVSZXNwb25zZSB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLXV0aWxzLmpzJztcblxuY29uc3QgeyBib2xkLCBncmVlbiB9ID0gcGljbztcblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGB1cGxvYWQtcGx1Z2luYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIFZhbGlkYXRlcyBhIGxvY2FsIHBsdWdpbiBaSVAgZmlsZSAoc2l6ZSwgZXh0ZW5zaW9uLCByZWFkYWJpbGl0eSksXG4gKiBidWlsZHMgYSBtdWx0aXBhcnQgZm9ybSwgYW5kIHVwbG9hZHMgaXQgdG8gdGhlIHBsYXRmb3JtIEFQSS5cbiAqIFBsdWdpbiBuYW1lIGFuZCB2ZXJzaW9uIGNhbiBiZSBhdXRvLWRldGVjdGVkIGZyb20gdGhlIHBhY2thZ2VcbiAqIG9yIG92ZXJyaWRkZW4gdmlhIENMSSBmbGFncy5cbiAqXG4gKiBAcGFyYW0gcHJvZ3JhbSAtIFRoZSByb290IENvbW1hbmRlciBwcm9ncmFtIGluc3RhbmNlIHRvIGF0dGFjaCB0aGUgY29tbWFuZCB0by5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgYmFzaFxuICogY2xpIHBsdWdpbiB1cGxvYWQgLS1maWxlIHBsdWdpbi56aXAgLS1vcmdhbml6YXRpb24gYWNtZVxuICogY2xpIHBsdWdpbiB1cGxvYWQgLS1maWxlIHBsdWdpbi56aXAgLS1vcmdhbml6YXRpb24gYWNtZSAtLXB1YmxpY1xuICogY2xpIHBsdWdpbiB1cGxvYWQgLS1maWxlIHBsdWdpbi56aXAgLS1vcmdhbml6YXRpb24gYWNtZSAtLW5hbWUgbXktcGx1Z2luIC0tdmVyc2lvbiAxLjAuMFxuICogY2xpIHBsdWdpbiB1cGxvYWQgLS1maWxlIHBsdWdpbi56aXAgLS1vcmdhbml6YXRpb24gYWNtZSAtLW5vLXZlcmlmeS1zc2xcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBsb2FkUGx1Z2luKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMocHJvZ3JhbVxuICAgIC5jb21tYW5kKCd1cGxvYWQnKVxuICAgIC5kZXNjcmlwdGlvbignVXBsb2FkIGFuZCBkZXBsb3kgYSBwbHVnaW4gcGFja2FnZScpXG4gICAgLnJlcXVpcmVkT3B0aW9uKCctZiwgLS1maWxlIDxmaWxlPicsICdQYXRoIHRvIHBsdWdpbiBaSVAgZmlsZScpXG4gICAgLnJlcXVpcmVkT3B0aW9uKCctbywgLS1vcmdhbml6YXRpb24gPG9yZ2FuaXphdGlvbj4nLCAnT3JnYW5pemF0aW9uIG5hbWUnKVxuICAgIC5vcHRpb24oJy1uLCAtLW5hbWUgPG5hbWU+JywgJ1BsdWdpbiBuYW1lIChvcHRpb25hbCwgZXh0cmFjdGVkIGZyb20gcGFja2FnZSBpZiBub3QgcHJvdmlkZWQpJylcbiAgICAub3B0aW9uKCctdiwgLS12ZXJzaW9uIDx2ZXJzaW9uPicsICdQbHVnaW4gdmVyc2lvbiAob3B0aW9uYWwsIGV4dHJhY3RlZCBmcm9tIHBhY2thZ2UgaWYgbm90IHByb3ZpZGVkKScpXG4gICAgLm9wdGlvbignLS1wdWJsaWMnLCAnTWFrZSBwbHVnaW4gcHVibGljbHkgYWNjZXNzaWJsZScsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tYWN0aXZlJywgJ1NldCBwbHVnaW4gYXMgYWN0aXZlJywgdHJ1ZSlcbiAgICAub3B0aW9uKCctLW5vLWFjdGl2ZScsICdVcGxvYWQgdGhlIHBsdWdpbiBhcyBpbmFjdGl2ZScpKVxuICAgIC5vcHRpb24oJy0tZHJ5LXJ1bicsICdWYWxpZGF0ZSBmaWxlIHdpdGhvdXQgdXBsb2FkaW5nJywgZmFsc2UpXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ1VwbG9hZCBQbHVnaW4nKTtcblxuICAgICAgdHJ5IHtcblxuICAgICAgICAvLyBEaXNwbGF5IHBhcmFtZXRlcnNcbiAgICAgICAgcHJpbnRJbmZvKCdVcGxvYWQgcGFyYW1ldGVycycsIHtcbiAgICAgICAgICBmaWxlOiBvcHRpb25zLmZpbGUsXG4gICAgICAgICAgb3JnYW5pemF0aW9uOiBvcHRpb25zLm9yZ2FuaXphdGlvbixcbiAgICAgICAgICBuYW1lOiBvcHRpb25zLm5hbWUgfHwgJyhhdXRvLWRldGVjdCknLFxuICAgICAgICAgIHZlcnNpb246IG9wdGlvbnMudmVyc2lvbiB8fCAnKGF1dG8tZGV0ZWN0KScsXG4gICAgICAgICAgcHVibGljOiBvcHRpb25zLnB1YmxpYyA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICBhY3RpdmU6IG9wdGlvbnMuYWN0aXZlID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4sXG4gICAgICAgICAgdmVyaWZ5U3NsOiBvcHRpb25zLnZlcmlmeVNzbCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2VjdXJpdHkgd2FybmluZyBmb3IgU1NMIHZlcmlmaWNhdGlvbiBkaXNhYmxlZFxuICAgICAgICBwcmludFNzbFdhcm5pbmcob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIG9yZ2FuaXphdGlvblxuICAgICAgICBpZiAoIW9wdGlvbnMub3JnYW5pemF0aW9uIHx8IHR5cGVvZiBvcHRpb25zLm9yZ2FuaXphdGlvbiAhPT0gJ3N0cmluZycgfHwgb3B0aW9ucy5vcmdhbml6YXRpb24udHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHByaW50RXJyb3IoJ0ludmFsaWQgb3JnYW5pemF0aW9uIG5hbWUnLCB7IHByb3ZpZGVkOiBvcHRpb25zLm9yZ2FuaXphdGlvbiB9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdPcmdhbml6YXRpb24gbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcnLCAnb3JnYW5pemF0aW9uJywgb3B0aW9ucy5vcmdhbml6YXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgZmlsZSBwYXRoXG4gICAgICAgIGlmICghb3B0aW9ucy5maWxlIHx8IHR5cGVvZiBvcHRpb25zLmZpbGUgIT09ICdzdHJpbmcnIHx8IG9wdGlvbnMuZmlsZS50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcHJpbnRFcnJvcignSW52YWxpZCBmaWxlIHBhdGgnLCB7IHByb3ZpZGVkOiBvcHRpb25zLmZpbGUgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignRmlsZSBwYXRoIG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nJywgJ2ZpbGUnLCBvcHRpb25zLmZpbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLnJlc29sdmUob3B0aW9ucy5maWxlKTtcblxuICAgICAgICAvLyBWYWxpZGF0ZSBmaWxlIGV4aXN0c1xuICAgICAgICBwcmludEluZm8oJ1ZhbGlkYXRpbmcgcGx1Z2luIGZpbGUnLCB7IHBhdGg6IGZpbGVQYXRoIH0pO1xuXG4gICAgICAgIGlmICghZmlsZUV4aXN0cyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBwcmludEVycm9yKCdQbHVnaW4gZmlsZSBub3QgZm91bmQnLCB7IHBhdGg6IGZpbGVQYXRoIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYFBsdWdpbiBmaWxlIG5vdCBmb3VuZDogJHtmaWxlUGF0aH1gLCAnZmlsZScsIGZpbGVQYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRlIGZpbGUgZXh0ZW5zaW9uXG4gICAgICAgIGNvbnN0IGZpbGVFeHQgPSBwYXRoLmV4dG5hbWUoZmlsZVBhdGgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmIChmaWxlRXh0ICE9PSAnLnppcCcpIHtcbiAgICAgICAgICBwcmludFdhcm5pbmcoJ0ZpbGUgZXh0ZW5zaW9uIGlzIG5vdCAuemlwJywge1xuICAgICAgICAgICAgcHJvdmlkZWQ6IGZpbGVFeHQsXG4gICAgICAgICAgICBleHBlY3RlZDogJy56aXAnLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ1BsdWdpbiBmaWxlIG11c3QgYmUgYSBaSVAgYXJjaGl2ZScsICdmaWxlJywgZmlsZVBhdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2V0IGZpbGUgc3RhdHNcbiAgICAgICAgY29uc3Qgc3RhdHMgPSBmcy5zdGF0U3luYyhmaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IHNpemVCeXRlcyA9IHN0YXRzLnNpemU7XG4gICAgICAgIGNvbnN0IHNpemVGb3JtYXR0ZWQgPSBmb3JtYXRGaWxlU2l6ZShzaXplQnl0ZXMpO1xuXG4gICAgICAgIHByaW50U3VjY2VzcygnUGx1Z2luIGZpbGUgZm91bmQnLCB7XG4gICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgc2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgICAgICAgICBtb2RpZmllZDogbmV3IERhdGUoc3RhdHMubXRpbWUpLnRvTG9jYWxlU3RyaW5nKCksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIENoZWNrIGZpbGUgc2l6ZVxuICAgICAgICBpZiAoc2l6ZUJ5dGVzID4gRklMRV9TSVpFX0xJTUlUUy5QTFVHSU4pIHtcbiAgICAgICAgICBwcmludEVycm9yKCdQbHVnaW4gZmlsZSB0b28gbGFyZ2UnLCB7XG4gICAgICAgICAgICBzaXplOiBzaXplRm9ybWF0dGVkLFxuICAgICAgICAgICAgbWF4aW11bTogZm9ybWF0RmlsZVNpemUoRklMRV9TSVpFX0xJTUlUUy5QTFVHSU4pLFxuICAgICAgICAgICAgZXhjZWVkZWRCeTogZm9ybWF0RmlsZVNpemUoc2l6ZUJ5dGVzIC0gRklMRV9TSVpFX0xJTUlUUy5QTFVHSU4pLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICAgICBgUGx1Z2luIGZpbGUgZXhjZWVkcyBtYXhpbXVtIHNpemUgb2YgJHtmb3JtYXRGaWxlU2l6ZShGSUxFX1NJWkVfTElNSVRTLlBMVUdJTil9IChhY3R1YWw6ICR7c2l6ZUZvcm1hdHRlZH0pYCxcbiAgICAgICAgICAgICdmaWxlLnNpemUnLFxuICAgICAgICAgICAgc2l6ZUJ5dGVzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiBmaWxlIGlzIHJlYWRhYmxlXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZnMuYWNjZXNzU3luYyhmaWxlUGF0aCwgZnMuY29uc3RhbnRzLlJfT0spO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHByaW50RXJyb3IoJ0Nhbm5vdCByZWFkIHBsdWdpbiBmaWxlJywge1xuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICBlcnJvcjogZXJyb3JNZXNzYWdlKGVycm9yKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdQbHVnaW4gZmlsZSBpcyBub3QgcmVhZGFibGUnLCAnZmlsZScsIGZpbGVQYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByaW50U3VjY2VzcygnUGx1Z2luIGZpbGUgdmFsaWRhdGVkJyk7XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgdmVyc2lvbiBmb3JtYXQgaWYgcHJvdmlkZWQuIEFsbG93cyAtcHJlcmVsZWFzZSBhbmQgK2J1aWxkXG4gICAgICAgIC8vIG1ldGFkYXRhICh2YWxpZCBzZW12ZXIpIHRvIG1hdGNoIHZhbGlkYXRlLXBsdWdpbiBhbmQgdGhlIERCIGNvbnN0cmFpbnQuXG4gICAgICAgIGlmIChvcHRpb25zLnZlcnNpb24pIHtcbiAgICAgICAgICBjb25zdCB2ZXJzaW9uUmVnZXggPSAvXlxcZCtcXC5cXGQrXFwuXFxkKygtW2EtekEtWjAtOS4tXSspPyhcXCtbYS16QS1aMC05Li1dKyk/JC87XG4gICAgICAgICAgaWYgKCF2ZXJzaW9uUmVnZXgudGVzdChvcHRpb25zLnZlcnNpb24pKSB7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoJ1ZlcnNpb24gZm9ybWF0IG1heSBiZSBpbnZhbGlkJywge1xuICAgICAgICAgICAgICBwcm92aWRlZDogb3B0aW9ucy52ZXJzaW9uLFxuICAgICAgICAgICAgICBleHBlY3RlZDogJ3NlbWFudGljIHZlcnNpb24gKGUuZy4sIDEuMC4wLCAxLjIuMy1iZXRhLjEpJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRlIG5hbWUgZm9ybWF0IGlmIHByb3ZpZGVkXG4gICAgICAgIGlmIChvcHRpb25zLm5hbWUpIHtcbiAgICAgICAgICBjb25zdCBuYW1lUmVnZXggPSAvXlthLXowLTktXSskLztcbiAgICAgICAgICBpZiAoIW5hbWVSZWdleC50ZXN0KG9wdGlvbnMubmFtZSkpIHtcbiAgICAgICAgICAgIHByaW50V2FybmluZygnUGx1Z2luIG5hbWUgZm9ybWF0IG1heSBiZSBpbnZhbGlkJywge1xuICAgICAgICAgICAgICBwcm92aWRlZDogb3B0aW9ucy5uYW1lLFxuICAgICAgICAgICAgICBleHBlY3RlZDogJ2xvd2VyY2FzZSBhbHBoYW51bWVyaWMgd2l0aCBkYXNoZXMgKGUuZy4sIG15LXBsdWdpbi1uYW1lKScsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEcnkgcnVuIG1vZGVcbiAgICAgICAgaWYgKG9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignRHJ5IFJ1biAtIFZhbGlkYXRpb24gQ29tcGxldGUnKTtcbiAgICAgICAgICBwcmludFN1Y2Nlc3MoJ0ZpbGUgdmFsaWRhdGlvbiBwYXNzZWQgLSBubyB1cGxvYWQgcGVyZm9ybWVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgIEZpbGU6IGZpbGVQYXRoLFxuICAgICAgICAgICAgU2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgICAgICAgICAgIE9yZ2FuaXphdGlvbjogb3B0aW9ucy5vcmdhbml6YXRpb24sXG4gICAgICAgICAgICBOYW1lOiBvcHRpb25zLm5hbWUgfHwgJyh3aWxsIGJlIGF1dG8tZGV0ZWN0ZWQpJyxcbiAgICAgICAgICAgIFZlcnNpb246IG9wdGlvbnMudmVyc2lvbiB8fCAnKHdpbGwgYmUgYXV0by1kZXRlY3RlZCknLFxuICAgICAgICAgICAgUHVibGljOiBvcHRpb25zLnB1YmxpYyA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICAgIEFjdGl2ZTogb3B0aW9ucy5hY3RpdmUgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgYXV0aGVudGljYXRlZCBBUEkgY2xpZW50XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnQob3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IGNsaWVudC5nZXRDb25maWcoKTtcblxuICAgICAgICAvLyBDcmVhdGUgZm9ybSBkYXRhXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRTZWN0aW9uKCdVcGxvYWRpbmcgUGx1Z2luJyk7XG4gICAgICAgIHByaW50SW5mbygnUHJlcGFyaW5nIHVwbG9hZCcsIHtcbiAgICAgICAgICBmaWxlOiBwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKSxcbiAgICAgICAgICBzaXplOiBzaXplRm9ybWF0dGVkLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ3BsdWdpbicsIGZzLmNyZWF0ZVJlYWRTdHJlYW0oZmlsZVBhdGgpLCB7XG4gICAgICAgICAgZmlsZW5hbWU6IHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpLFxuICAgICAgICAgIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vemlwJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGZvcm1EYXRhLmFwcGVuZCgnb3JnYW5pemF0aW9uJywgb3B0aW9ucy5vcmdhbml6YXRpb24pO1xuXG4gICAgICAgIGlmIChvcHRpb25zLm5hbWUpIGZvcm1EYXRhLmFwcGVuZCgnbmFtZScsIG9wdGlvbnMubmFtZSk7XG4gICAgICAgIGlmIChvcHRpb25zLnZlcnNpb24pIGZvcm1EYXRhLmFwcGVuZCgndmVyc2lvbicsIG9wdGlvbnMudmVyc2lvbik7XG4gICAgICAgIGZvcm1EYXRhLmFwcGVuZCgnaXNQdWJsaWMnLCBvcHRpb25zLnB1YmxpYyA/ICd0cnVlJyA6ICdmYWxzZScpO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ2lzQWN0aXZlJywgb3B0aW9ucy5hY3RpdmUgPyAndHJ1ZScgOiAnZmFsc2UnKTtcblxuICAgICAgICAvLyBNYWtlIEFQSSByZXF1ZXN0XG4gICAgICAgIGNvbnN0IGVuZHBvaW50ID0gY29uZmlnLmFwaS5wbHVnaW5VcGxvYWRVcmw7XG4gICAgICAgIHByaW50SW5mbygnVXBsb2FkaW5nIHRvIEFQSScsIHtcbiAgICAgICAgICBlbmRwb2ludDogYCR7Y29uZmlnLmFwaS5iYXNlVXJsfSR7ZW5kcG9pbnR9YCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuXG4gICAgICAgIGNvbnN0IHNwaW5uZXIgPSBvcmEoJ1VwbG9hZGluZyBwbHVnaW4uLi4nKS5zdGFydCgpO1xuICAgICAgICBsZXQgcmF3UmVzcG9uc2U6IFBsdWdpblJlc3BvbnNlO1xuICAgICAgICBsZXQgZHVyYXRpb246IG51bWJlcjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIHJhd1Jlc3BvbnNlID0gYXdhaXQgY2xpZW50LnBvc3RGb3JtPFBsdWdpblJlc3BvbnNlPihlbmRwb2ludCwgZm9ybURhdGEpO1xuICAgICAgICAgIGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgICAgICBzcGlubmVyLnN1Y2NlZWQoJ1BsdWdpbiB1cGxvYWRlZCcpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHNwaW5uZXIuZmFpbCgnVXBsb2FkIGZhaWxlZCcpO1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBleHRyYWN0U2luZ2xlUmVzcG9uc2U8UGx1Z2luPihyYXdSZXNwb25zZSwgJ3BsdWdpbicsICduYW1lJyk7XG5cbiAgICAgICAgaWYgKCFyZXNwb25zZSkge1xuICAgICAgICAgIHByaW50RXJyb3IoJ05vIHZhbGlkIHBsdWdpbiBkYXRhIGluIHJlc3BvbnNlJywge1xuICAgICAgICAgICAgcmVzcG9uc2VLZXlzOiByYXdSZXNwb25zZSA/IE9iamVjdC5rZXlzKHJhd1Jlc3BvbnNlKSA6ICcobnVsbCknLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVXBsb2FkIGZhaWxlZCAtIG5vIHZhbGlkIHBsdWdpbiBkYXRhIHJlY2VpdmVkJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U2VjdGlvbignUGx1Z2luIFVwbG9hZGVkIFN1Y2Nlc3NmdWxseScpO1xuXG4gICAgICAgIC8vIERpc3BsYXkgcGx1Z2luIGluZm9ybWF0aW9uXG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdQbHVnaW4gSUQnOiBncmVlbihib2xkKHJlc3BvbnNlLmlkKSksXG4gICAgICAgICAgJ05hbWUnOiByZXNwb25zZS5uYW1lLFxuICAgICAgICAgICdWZXJzaW9uJzogcmVzcG9uc2UudmVyc2lvbixcbiAgICAgICAgICAnT3JnYW5pemF0aW9uJzogcmVzcG9uc2Uub3JnYW5pemF0aW9uLFxuICAgICAgICAgICdEZXNjcmlwdGlvbic6IHJlc3BvbnNlLmRlc2NyaXB0aW9uIHx8ICcobm90IHNldCknLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdGaWxlIFVSTCc6IHJlc3BvbnNlLmZpbGVVcmwgfHwgJyhub3QgYXZhaWxhYmxlKScsXG4gICAgICAgICAgJ0ZpbGUgU2l6ZSc6IHJlc3BvbnNlLmZpbGVTaXplID8gYCR7KHJlc3BvbnNlLmZpbGVTaXplIC8gMTAyNCkudG9GaXhlZCgyKX0gS0JgIDogJyhub3QgYXZhaWxhYmxlKScsXG4gICAgICAgICAgJ0NoZWNrc3VtJzogcmVzcG9uc2UuY2hlY2tzdW0gPyBgJHtyZXNwb25zZS5jaGVja3N1bS5zdWJzdHJpbmcoMCwgMTYpfS4uLmAgOiAnKG5vdCBhdmFpbGFibGUpJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAnUHVibGljJzogcmVzcG9uc2UuaXNQdWJsaWMgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgJ0FjdGl2ZSc6IHJlc3BvbnNlLmlzQWN0aXZlID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgICdDcmVhdGVkIEF0JzogcmVzcG9uc2UuY3JlYXRlZEF0IHx8ICcobm90IGF2YWlsYWJsZSknLFxuICAgICAgICAgICdVcGxvYWRlZCBCeSc6IHJlc3BvbnNlLnVwbG9hZGVkQnkgfHwgJyhub3QgYXZhaWxhYmxlKScsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgJ0V4ZWN1dGlvbiBJRCc6IGV4ZWN1dGlvbklkLFxuICAgICAgICAgICdVcGxvYWQgRHVyYXRpb24nOiBgJHsoZHVyYXRpb24gLyAxMDAwKS50b0ZpeGVkKDIpfXNgLFxuICAgICAgICAgICdTdGF0dXMnOiBncmVlbign4pyTIFN1Y2Nlc3MnKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUHJpbnQgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBpZiBhdmFpbGFibGVcbiAgICAgICAgaWYgKHJlc3BvbnNlLm1ldGFkYXRhKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50SW5mbygnUGx1Z2luIG1ldGFkYXRhIGF2YWlsYWJsZScsIHtcbiAgICAgICAgICAgIGtleXM6IE9iamVjdC5rZXlzKHJlc3BvbnNlLm1ldGFkYXRhKS5sZW5ndGgsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmludCBkZXBsb3ltZW50IGxvZ3MgVVJMIGlmIGF2YWlsYWJsZVxuICAgICAgICBjb25zdCByZXNwID0gcmVzcG9uc2UgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgY29uc3QgcmVxdWVzdElkID0gcmVzcFsnWC1SZXF1ZXN0LUlkJ10gfHwgcmVzcC5yZXF1ZXN0SWQ7XG4gICAgICAgIGlmIChyZXF1ZXN0SWQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRJbmZvKCdEZXBsb3ltZW50IGxvZ3MgYXZhaWxhYmxlJywge1xuICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgdXJsOiBgJHtjb25maWcuYXBpLmJhc2VVcmx9L2xvZ3MvJHtyZXF1ZXN0SWR9YCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5leHQgc3RlcHNcbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICBwcmludEluZm8oJ05leHQgc3RlcHMnLCB7XG4gICAgICAgICAgdmlldzogYFVzZSBcImdldC1wbHVnaW4gLS1pZCAke3Jlc3BvbnNlLmlkfVwiIHRvIHZpZXcgcGx1Z2luIGRldGFpbHNgLFxuICAgICAgICAgIGxpc3Q6ICdVc2UgXCJsaXN0LXBsdWdpbnNcIiB0byBzZWUgYWxsIHBsdWdpbnMnLFxuICAgICAgICB9KTtcblxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkFQSV9SRVFVRVNULCB7XG4gICAgICAgICAgZGVidWc6IHByb2dyYW0ub3B0cygpLmRlYnVnLFxuICAgICAgICAgIGV4aXQ6IHRydWUsXG4gICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgY29tbWFuZDogJ3VwbG9hZC1wbHVnaW4nLFxuICAgICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgICBmaWxlOiBvcHRpb25zLmZpbGUsXG4gICAgICAgICAgICBvcmdhbml6YXRpb246IG9wdGlvbnMub3JnYW5pemF0aW9uLFxuICAgICAgICAgICAgbmFtZTogb3B0aW9ucy5uYW1lLFxuICAgICAgICAgICAgdmVyc2lvbjogb3B0aW9ucy52ZXJzaW9uLFxuICAgICAgICAgICAgcHVibGljOiBvcHRpb25zLnB1YmxpYyxcbiAgICAgICAgICAgIGFjdGl2ZTogb3B0aW9ucy5hY3RpdmUsXG4gICAgICAgICAgICB2ZXJpZnlTc2w6IG9wdGlvbnMudmVyaWZ5U3NsLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xufVxuIl19
214
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLXBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy91cGxvYWQtcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxRQUFRLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQztBQUN0QixPQUFPLElBQUksTUFBTSxZQUFZLENBQUM7QUFDOUIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUseUJBQXlCLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0gsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RJLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQVk1RCxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQztBQUU3Qjs7O0dBR0c7QUFDSCxTQUFTLGlCQUFpQixDQUFDLElBQWE7SUFDdEMscUJBQXFCO0lBQ3JCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxJQUFJLEVB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WUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2hCLFNBQVMsQ0FBQyxZQUFZLEVBQUU7Z0JBQ3RCLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUTtvQkFDbkIsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixRQUFRLENBQUMsUUFBUSwwQkFBMEIsRUFBRTtvQkFDL0UsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLHFFQUFxRSxFQUFFLENBQUM7Z0JBQ3JGLElBQUksRUFBRSxzQ0FBc0M7YUFDN0MsQ0FBQyxDQUFDO1FBRUwsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixXQUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxXQUFXLEVBQUU7Z0JBQzFDLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSztnQkFDM0IsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsT0FBTyxFQUFFO29CQUNQLE9BQU8sRUFBRSxlQUFlO29CQUN4QixXQUFXO29CQUNYLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO29CQUN0QixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7aUJBQzdCO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZXJyb3JNZXNzYWdlIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgRm9ybURhdGEgZnJvbSAnZm9ybS1kYXRhJztcbmltcG9ydCBvcmEgZnJvbSAnb3JhJztcbmltcG9ydCBwaWNvIGZyb20gJ3BpY29jb2xvcnMnO1xuaW1wb3J0IHsgRklMRV9TSVpFX0xJTUlUUywgZm9ybWF0RmlsZVNpemUgfSBmcm9tICcuLi9jb25maWcvY2xpLmNvbnN0YW50cy5qcyc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIsIHByaW50U3NsV2FybmluZywgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudCwgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBmaWxlRXhpc3RzLCBwcmludEVycm9yLCBwcmludEluZm8sIHByaW50S2V5VmFsdWUsIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzLCBwcmludFdhcm5pbmcgfSBmcm9tICcuLi91dGlscy9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHsgdW53cmFwRW52ZWxvcGUgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS11dGlscy5qcyc7XG5cbi8qKiBUaGUgdXBsb2FkIHJvdXRlJ3Mgc3VjY2VzcyBwYXlsb2FkIChgUE9TVCAvcGx1Z2lucy91cGxvYWRgKS4gKi9cbmludGVyZmFjZSBQbHVnaW5VcGxvYWRSZXN1bHQge1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIHBsdWdpbk5hbWU/OiBzdHJpbmc7XG4gIHZlcnNpb24/OiBzdHJpbmc7XG4gIC8qKiBQcmVzZW50IG9ubHkgb24gMjAxIChtZXRhZGF0YS1vbmx5IHBsdWdpbiwgZGVwbG95ZWQgd2l0aG91dCBhIGJ1aWxkKS4gKi9cbiAgcGx1Z2luSWQ/OiBzdHJpbmc7XG4gIGJ1aWxkVHlwZT86IHN0cmluZztcbn1cblxuY29uc3QgeyBib2xkLCBncmVlbiB9ID0gcGljbztcblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGUgcGx1Z2luIFpJUCAobm9uLWVtcHR5IHBhdGgsIGV4aXN0cywgYC56aXBgLCBzaXplIGNhcCwgcmVhZGFibGUpLlxuICogUmV0dXJucyB0aGUgcmVzb2x2ZWQgcGF0aCBhbmQgaXRzIGZvcm1hdHRlZCBzaXplLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVBsdWdpblppcChmaWxlOiB1bmtub3duKTogeyBmaWxlUGF0aDogc3RyaW5nOyBzaXplRm9ybWF0dGVkOiBzdHJpbmcgfSB7XG4gIC8vIFZhbGlkYXRlIGZpbGUgcGF0aFxuICBpZiAodHlwZW9mIGZpbGUgIT09ICdzdHJpbmcnIHx8IGZpbGUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgIHByaW50RXJyb3IoJ0ludmFsaWQgZmlsZSBwYXRoJywgeyBwcm92aWRlZDogZmlsZSB9KTtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdGaWxlIHBhdGggbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcnLCAnZmlsZScsIGZpbGUpO1xuICB9XG5cbiAgY29uc3QgZmlsZVBhdGggPSBwYXRoLnJlc29sdmUoZmlsZSk7XG5cbiAgLy8gVmFsaWRhdGUgZmlsZSBleGlzdHNcbiAgcHJpbnRJbmZvKCdWYWxpZGF0aW5nIHBsdWdpbiBmaWxlJywgeyBwYXRoOiBmaWxlUGF0aCB9KTtcblxuICBpZiAoIWZpbGVFeGlzdHMoZmlsZVBhdGgpKSB7XG4gICAgcHJpbnRFcnJvcignUGx1Z2luIGZpbGUgbm90IGZvdW5kJywgeyBwYXRoOiBmaWxlUGF0aCB9KTtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGBQbHVnaW4gZmlsZSBub3QgZm91bmQ6ICR7ZmlsZVBhdGh9YCwgJ2ZpbGUnLCBmaWxlUGF0aCk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBmaWxlIGV4dGVuc2lvblxuICBjb25zdCBmaWxlRXh0ID0gcGF0aC5leHRuYW1lKGZpbGVQYXRoKS50b0xvd2VyQ2FzZSgpO1xuICBpZiAoZmlsZUV4dCAhPT0gJy56aXAnKSB7XG4gICAgcHJpbnRXYXJuaW5nKCdGaWxlIGV4dGVuc2lvbiBpcyBub3QgLnppcCcsIHtcbiAgICAgIHByb3ZpZGVkOiBmaWxlRXh0LFxuICAgICAgZXhwZWN0ZWQ6ICcuemlwJyxcbiAgICB9KTtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdQbHVnaW4gZmlsZSBtdXN0IGJlIGEgWklQIGFyY2hpdmUnLCAnZmlsZScsIGZpbGVQYXRoKTtcbiAgfVxuXG4gIC8vIEdldCBmaWxlIHN0YXRzXG4gIGNvbnN0IHN0YXRzID0gZnMuc3RhdFN5bmMoZmlsZVBhdGgpO1xuICBjb25zdCBzaXplQnl0ZXMgPSBzdGF0cy5zaXplO1xuICBjb25zdCBzaXplRm9ybWF0dGVkID0gZm9ybWF0RmlsZVNpemUoc2l6ZUJ5dGVzKTtcblxuICBwcmludFN1Y2Nlc3MoJ1BsdWdpbiBmaWxlIGZvdW5kJywge1xuICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgIHNpemU6IHNpemVGb3JtYXR0ZWQsXG4gICAgbW9kaWZpZWQ6IG5ldyBEYXRlKHN0YXRzLm10aW1lKS50b0xvY2FsZVN0cmluZygpLFxuICB9KTtcblxuICAvLyBDaGVjayBmaWxlIHNpemVcbiAgaWYgKHNpemVCeXRlcyA+IEZJTEVfU0laRV9MSU1JVFMuUExVR0lOKSB7XG4gICAgcHJpbnRFcnJvcignUGx1Z2luIGZpbGUgdG9vIGxhcmdlJywge1xuICAgICAgc2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgICAgIG1heGltdW06IGZvcm1hdEZpbGVTaXplKEZJTEVfU0laRV9MSU1JVFMuUExVR0lOKSxcbiAgICAgIGV4Y2VlZGVkQnk6IGZvcm1hdEZpbGVTaXplKHNpemVCeXRlcyAtIEZJTEVfU0laRV9MSU1JVFMuUExVR0lOKSxcbiAgICB9KTtcbiAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgYFBsdWdpbiBmaWxlIGV4Y2VlZHMgbWF4aW11bSBzaXplIG9mICR7Zm9ybWF0RmlsZVNpemUoRklMRV9TSVpFX0xJTUlUUy5QTFVHSU4pfSAoYWN0dWFsOiAke3NpemVGb3JtYXR0ZWR9KWAsXG4gICAgICAnZmlsZS5zaXplJyxcbiAgICAgIHNpemVCeXRlcyxcbiAgICApO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgZmlsZSBpcyByZWFkYWJsZVxuICB0cnkge1xuICAgIGZzLmFjY2Vzc1N5bmMoZmlsZVBhdGgsIGZzLmNvbnN0YW50cy5SX09LKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBwcmludEVycm9yKCdDYW5ub3QgcmVhZCBwbHVnaW4gZmlsZScsIHtcbiAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgZXJyb3I6IGVycm9yTWVzc2FnZShlcnJvciksXG4gICAgfSk7XG4gICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUGx1Z2luIGZpbGUgaXMgbm90IHJlYWRhYmxlJywgJ2ZpbGUnLCBmaWxlUGF0aCk7XG4gIH1cblxuICBwcmludFN1Y2Nlc3MoJ1BsdWdpbiBmaWxlIHZhbGlkYXRlZCcpO1xuICByZXR1cm4geyBmaWxlUGF0aCwgc2l6ZUZvcm1hdHRlZCB9O1xufVxuXG4vKiogUE9TVCB0aGUgWklQIGFzIG11bHRpcGFydCBmb3JtIGRhdGE7IHJldHVybnMgdGhlIHJhdyByZXNwb25zZSBhbmQgaXRzIGR1cmF0aW9uLiAqL1xuYXN5bmMgZnVuY3Rpb24gcG9zdFBsdWdpblppcChcbiAgY2xpZW50OiBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50PixcbiAgZmlsZVBhdGg6IHN0cmluZyxcbiAgc2l6ZUZvcm1hdHRlZDogc3RyaW5nLFxuICBpc1B1YmxpYzogYm9vbGVhbixcbik6IFByb21pc2U8eyByYXdSZXNwb25zZTogdW5rbm93bjsgZHVyYXRpb246IG51bWJlciB9PiB7XG4gIGNvbnN0IGNvbmZpZyA9IGNsaWVudC5nZXRDb25maWcoKTtcbiAgLy8gQ3JlYXRlIGZvcm0gZGF0YVxuICBjb25zb2xlLmxvZygnJyk7XG4gIHByaW50U2VjdGlvbignVXBsb2FkaW5nIFBsdWdpbicpO1xuICBwcmludEluZm8oJ1ByZXBhcmluZyB1cGxvYWQnLCB7XG4gICAgZmlsZTogcGF0aC5iYXNlbmFtZShmaWxlUGF0aCksXG4gICAgc2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgfSk7XG5cbiAgY29uc3QgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgZm9ybURhdGEuYXBwZW5kKCdwbHVnaW4nLCBmcy5jcmVhdGVSZWFkU3RyZWFtKGZpbGVQYXRoKSwge1xuICAgIGZpbGVuYW1lOiBwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKSxcbiAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL3ppcCcsXG4gIH0pO1xuICAvLyBUaGUgdXBsb2FkIEFQSSByZWFkcyBgdmlzaWJpbGl0eWAgKHByaXZhdGUgfCBvcmcgfCBwdWJsaWMpOyB3aXRob3V0XG4gIC8vIGl0IHRoZSB2ZXJzaW9uIGlzIGBvcmdgLiBgcHVibGljYCBuZWVkcyBwbHVnaW5zOnB1Ymxpc2guIE5hbWUgYW5kXG4gIC8vIHZlcnNpb24gY29tZSBmcm9tIHRoZSBwYWNrYWdlJ3Mgc3BlYzsgdGhlIG9yZyBmcm9tIHRoZSBzZXNzaW9uLlxuICBpZiAoaXNQdWJsaWMpIGZvcm1EYXRhLmFwcGVuZCgndmlzaWJpbGl0eScsICdwdWJsaWMnKTtcblxuICAvLyBNYWtlIEFQSSByZXF1ZXN0XG4gIGNvbnN0IGVuZHBvaW50ID0gY29uZmlnLmFwaS5wbHVnaW5VcGxvYWRVcmw7XG4gIHByaW50SW5mbygnVXBsb2FkaW5nIHRvIEFQSScsIHtcbiAgICBlbmRwb2ludDogYCR7Y29uZmlnLmFwaS5iYXNlVXJsfSR7ZW5kcG9pbnR9YCxcbiAgfSk7XG5cbiAgY29uc29sZS5sb2coJycpO1xuXG4gIGNvbnN0IHNwaW5uZXIgPSBvcmEoJ1VwbG9hZGluZyBwbHVnaW4uLi4nKS5zdGFydCgpO1xuICBsZXQgcmF3UmVzcG9uc2U6IHVua25vd247XG4gIGxldCBkdXJhdGlvbjogbnVtYmVyO1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcmF3UmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdEZvcm08dW5rbm93bj4oZW5kcG9pbnQsIGZvcm1EYXRhKTtcbiAgICBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgc3Bpbm5lci5zdWNjZWVkKCdQbHVnaW4gdXBsb2FkZWQnKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBzcGlubmVyLmZhaWwoJ1VwbG9hZCBmYWlsZWQnKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuICByZXR1cm4geyByYXdSZXNwb25zZSwgZHVyYXRpb24gfTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGB1cGxvYWQtcGx1Z2luYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIFZhbGlkYXRlcyBhIGxvY2FsIHBsdWdpbiBaSVAgZmlsZSAoc2l6ZSwgZXh0ZW5zaW9uLCByZWFkYWJpbGl0eSksXG4gKiBidWlsZHMgYSBtdWx0aXBhcnQgZm9ybSwgYW5kIHVwbG9hZHMgaXQgdG8gdGhlIHBsYXRmb3JtIEFQSS4gVGhlXG4gKiBwbHVnaW4ncyBuYW1lIGFuZCB2ZXJzaW9uIGFsd2F5cyBjb21lIGZyb20gdGhlIHBhY2thZ2Unc1xuICogYHBsdWdpbi1zcGVjLnlhbWxgLCBhbmQgdGhlIG9yZ2FuaXphdGlvbiBmcm9tIHRoZSBzaWduZWQtaW4gc2Vzc2lvbi5cbiAqXG4gKiBAcGFyYW0gcHJvZ3JhbSAtIFRoZSByb290IENvbW1hbmRlciBwcm9ncmFtIGluc3RhbmNlIHRvIGF0dGFjaCB0aGUgY29tbWFuZCB0by5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgYmFzaFxuICogY2xpIHBsdWdpbiB1cGxvYWQgLS1maWxlIHBsdWdpbi56aXBcbiAqIGNsaSBwbHVnaW4gdXBsb2FkIC0tZmlsZSBwbHVnaW4uemlwIC0tcHVibGljXG4gKiBjbGkgcGx1Z2luIHVwbG9hZCAtLWZpbGUgcGx1Z2luLnppcCAtLW5vLXZlcmlmeS1zc2xcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBsb2FkUGx1Z2luKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMocHJvZ3JhbVxuICAgIC5jb21tYW5kKCd1cGxvYWQnKVxuICAgIC5kZXNjcmlwdGlvbignVXBsb2FkIGFuZCBkZXBsb3kgYSBwbHVnaW4gcGFja2FnZScpXG4gICAgLnJlcXVpcmVkT3B0aW9uKCctZiwgLS1maWxlIDxmaWxlPicsICdQYXRoIHRvIHBsdWdpbiBaSVAgZmlsZScpXG4gICAgLm9wdGlvbignLS1wdWJsaWMnLCAnTWFrZSBwbHVnaW4gcHVibGljbHkgYWNjZXNzaWJsZSAobmVlZHMgcGx1Z2luczpwdWJsaXNoKScsIGZhbHNlKSlcbiAgICAub3B0aW9uKCctLWRyeS1ydW4nLCAnVmFsaWRhdGUgZmlsZSB3aXRob3V0IHVwbG9hZGluZycsIGZhbHNlKVxuICAgIC5hY3Rpb24oYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgIGNvbnN0IGV4ZWN1dGlvbklkID0gcHJpbnRDb21tYW5kSGVhZGVyKCdVcGxvYWQgUGx1Z2luJyk7XG5cbiAgICAgIHRyeSB7XG5cbiAgICAgICAgLy8gRGlzcGxheSBwYXJhbWV0ZXJzXG4gICAgICAgIHByaW50SW5mbygnVXBsb2FkIHBhcmFtZXRlcnMnLCB7XG4gICAgICAgICAgZmlsZTogb3B0aW9ucy5maWxlLFxuICAgICAgICAgIHB1YmxpYzogb3B0aW9ucy5wdWJsaWMgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgZHJ5UnVuOiBvcHRpb25zLmRyeVJ1bixcbiAgICAgICAgICB2ZXJpZnlTc2w6IG9wdGlvbnMudmVyaWZ5U3NsLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTZWN1cml0eSB3YXJuaW5nIGZvciBTU0wgdmVyaWZpY2F0aW9uIGRpc2FibGVkXG4gICAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgICAgY29uc3QgeyBmaWxlUGF0aCwgc2l6ZUZvcm1hdHRlZCB9ID0gdmFsaWRhdGVQbHVnaW5aaXAob3B0aW9ucy5maWxlKTtcblxuICAgICAgICAvLyBEcnkgcnVuIG1vZGVcbiAgICAgICAgaWYgKG9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignRHJ5IFJ1biAtIFZhbGlkYXRpb24gQ29tcGxldGUnKTtcbiAgICAgICAgICBwcmludFN1Y2Nlc3MoJ0ZpbGUgdmFsaWRhdGlvbiBwYXNzZWQgLSBubyB1cGxvYWQgcGVyZm9ybWVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgIEZpbGU6IGZpbGVQYXRoLFxuICAgICAgICAgICAgU2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgICAgICAgICAgIFB1YmxpYzogb3B0aW9ucy5wdWJsaWMgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGllbnQgPSBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50KG9wdGlvbnMpO1xuICAgICAgICBjb25zdCB7IHJhd1Jlc3BvbnNlLCBkdXJhdGlvbiB9ID0gYXdhaXQgcG9zdFBsdWdpblppcChjbGllbnQsIGZpbGVQYXRoLCBzaXplRm9ybWF0dGVkLCAhIW9wdGlvbnMucHVibGljKTtcblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IHVud3JhcEVudmVsb3BlKHJhd1Jlc3BvbnNlKSBhcyBQbHVnaW5VcGxvYWRSZXN1bHQ7XG4gICAgICAgIGlmICghcmVzcG9uc2UucGx1Z2luTmFtZSkge1xuICAgICAgICAgIHByaW50RXJyb3IoJ05vIHZhbGlkIHVwbG9hZCByZXN1bHQgaW4gcmVzcG9uc2UnLCB7XG4gICAgICAgICAgICByZXNwb25zZUtleXM6IE9iamVjdC5rZXlzKHJlc3BvbnNlKS5qb2luKCcsICcpIHx8ICcobm9uZSknLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVXBsb2FkIGZhaWxlZCAtIG5vIHZhbGlkIHVwbG9hZCByZXN1bHQgcmVjZWl2ZWQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDIwMTogYSBtZXRhZGF0YS1vbmx5IHBsdWdpbiwgZGVwbG95ZWQgZGlyZWN0bHkgKGhhcyBhIHBsdWdpbklkKS5cbiAgICAgICAgLy8gMjAyOiB0aGUgaW1hZ2UgYnVpbGQgd2FzIHF1ZXVlZDsgdGhlIHdvcmtlciBwZXJzaXN0cyB0aGUgdmVyc2lvbi5cbiAgICAgICAgY29uc3QgcXVldWVkID0gIXJlc3BvbnNlLnBsdWdpbklkO1xuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U2VjdGlvbihxdWV1ZWQgPyAnUGx1Z2luIEJ1aWxkIFF1ZXVlZCcgOiAnUGx1Z2luIERlcGxveWVkJyk7XG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdQbHVnaW4nOiBncmVlbihib2xkKGAke3Jlc3BvbnNlLnBsdWdpbk5hbWV9QCR7cmVzcG9uc2UudmVyc2lvbiA/PyAnPyd9YCkpLFxuICAgICAgICAgIC4uLihyZXNwb25zZS5wbHVnaW5JZCA/IHsgJ1BsdWdpbiBJRCc6IHJlc3BvbnNlLnBsdWdpbklkIH0gOiB7fSksXG4gICAgICAgICAgJ1JlcXVlc3QgSUQnOiByZXNwb25zZS5yZXF1ZXN0SWQgPz8gJyhub3QgYXZhaWxhYmxlKScsXG4gICAgICAgICAgJ1Zpc2liaWxpdHknOiBvcHRpb25zLnB1YmxpYyA/ICdwdWJsaWMnIDogJ29yZycsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgJ0V4ZWN1dGlvbiBJRCc6IGV4ZWN1dGlvbklkLFxuICAgICAgICAgICdVcGxvYWQgRHVyYXRpb24nOiBgJHsoZHVyYXRpb24gLyAxMDAwKS50b0ZpeGVkKDIpfXNgLFxuICAgICAgICAgICdTdGF0dXMnOiBncmVlbign4pyTIFN1Y2Nlc3MnKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTmV4dCBzdGVwc1xuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50SW5mbygnTmV4dCBzdGVwcycsIHtcbiAgICAgICAgICAuLi4ocmVzcG9uc2UucGx1Z2luSWRcbiAgICAgICAgICAgID8geyB2aWV3OiBgVXNlIFwicGx1Z2luIGdldCAtLWlkICR7cmVzcG9uc2UucGx1Z2luSWR9XCIgdG8gdmlldyBwbHVnaW4gZGV0YWlsc2AgfVxuICAgICAgICAgICAgOiB7IGJ1aWxkOiAnVGhlIHZlcnNpb24gYXBwZWFycyBpbiBcInBsdWdpbiBsaXN0XCIgb25jZSBpdHMgaW1hZ2UgYnVpbGQgY29tcGxldGVzJyB9KSxcbiAgICAgICAgICBsaXN0OiAnVXNlIFwicGx1Z2luIGxpc3RcIiB0byBzZWUgYWxsIHBsdWdpbnMnLFxuICAgICAgICB9KTtcblxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkFQSV9SRVFVRVNULCB7XG4gICAgICAgICAgZGVidWc6IHByb2dyYW0ub3B0cygpLmRlYnVnLFxuICAgICAgICAgIGV4aXQ6IHRydWUsXG4gICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgY29tbWFuZDogJ3VwbG9hZC1wbHVnaW4nLFxuICAgICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgICBmaWxlOiBvcHRpb25zLmZpbGUsXG4gICAgICAgICAgICBwdWJsaWM6IG9wdGlvbnMucHVibGljLFxuICAgICAgICAgICAgdmVyaWZ5U3NsOiBvcHRpb25zLnZlcmlmeVNzbCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -1,12 +1,45 @@
1
+ import { type DetectedField, type HeuristicFinding, type HeuristicsInputFile, type PluginCatalogField, type PluginLintFinding } from '@pipeline-builder/api-core';
1
2
  import { Command } from 'commander';
3
+ import { type PluginPackage } from '../utils/plugin-package.js';
4
+ /** Fields a version needs before a publish request is accepted (the publish gates). */
5
+ export declare const PUBLISH_REQUIRED_FIELDS: ReadonlySet<PluginCatalogField>;
6
+ export interface ValidationReport {
7
+ pkg: PluginPackage;
8
+ /** What the upload would refuse. */
9
+ problems: string[];
10
+ /** test-plugins.sh-equivalent findings (only when linted). */
11
+ lint: PluginLintFinding[];
12
+ /** The catalog fields as the server will detect them. */
13
+ fields: DetectedField[];
14
+ /** The malware heuristics the anonymous-submission gate runs: `high` fails, `medium` warns. */
15
+ heuristics: HeuristicFinding[];
16
+ }
17
+ /** Every regular file under the plugin dir (what the zip would carry), bounded like the server's read. */
18
+ export declare function readPackageFilesForHeuristics(dir: string, max?: number): HeuristicsInputFile[];
19
+ /** A heuristic finding as one line of CLI output. */
20
+ export declare function formatHeuristic(f: HeuristicFinding): string;
21
+ /** Validate a plugin directory: server checks, optional catalog lint, catalog detection. */
22
+ export declare function validatePluginDir(dir: string, opts: {
23
+ lint: boolean;
24
+ }): Promise<ValidationReport>;
25
+ /** Invalid detected values (blanked by the server) and publish-required fields left empty. */
26
+ export declare function catalogIssues(fields: DetectedField[]): {
27
+ invalid: DetectedField[];
28
+ missingForPublish: DetectedField[];
29
+ };
30
+ /** Print each catalog field with its value (or why it's blank) and where it came from. */
31
+ export declare function printCatalogReport(fields: DetectedField[]): void;
2
32
  /**
3
- * Register the `validate-plugin` command — run the same structural + `{{ }}`
4
- * template checks the server's upload path enforces, against a LOCAL plugin
5
- * directory, so authors catch problems before packaging/uploading. Exits
6
- * non-zero on any problem (CI-friendly), mirroring `validate-templates`.
33
+ * Register `plugin validate` — the upload's own checks against a LOCAL plugin
34
+ * directory (the server's Zod spec/config schemas and template contract, shared
35
+ * from api-core), plus a report of every catalog field: its detected value, its
36
+ * source, and whether it would be empty or invalid. `--lint` adds the
37
+ * catalog's Dockerfile rules (test-plugins.sh). Exits non-zero on any problem,
38
+ * any invalid detected catalog value or any lint error (CI-friendly).
7
39
  *
8
40
  * Usage:
9
41
  * pipeline-manager plugin validate --dir ./my-linter
42
+ * pipeline-manager plugin validate --dir ./my-linter --lint --json
10
43
  */
11
44
  export declare function validatePlugin(program: Command): void;
12
45
  //# sourceMappingURL=validate-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-plugin.d.ts","sourceRoot":"","sources":["../../src/commands/validate-plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+IrD"}
1
+ {"version":3,"file":"validate-plugin.d.ts","sourceRoot":"","sources":["../../src/commands/validate-plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EACrH,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,EACwF,KAAK,aAAa,EAChH,MAAM,4BAA4B,CAAC;AAIpC,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,kBAAkB,CAAkC,CAAC;AAEvG,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,aAAa,CAAC;IACnB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8DAA8D;IAC9D,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,yDAAyD;IACzD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,+FAA+F;IAC/F,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,0GAA0G;AAC1G,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAQ,GAAG,mBAAmB,EAAE,CAqB7F;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAE3D;AAED,4FAA4F;AAC5F,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAWvG;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,iBAAiB,EAAE,aAAa,EAAE,CAAA;CAAE,CAKvH;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAgBhE;AAQD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsDrD"}